Source code for memory_esn._speedups._loader

"""
Selects the compiled Cython kernel when importable, else the NumPy fallback.

Import errors from the compiled extensions (missing build, ABI mismatch, etc.)
are caught and downgraded to a one-time warning so the package still works.
"""

from __future__ import annotations

import warnings

import numpy as _np

from . import _fallback

# --- reservoir update ------------------------------------------------------
try:
    from .esn_reservoir_optimized import reservoir_update_fast as reservoir_update
    USING_CYTHON_RESERVOIR = True
except Exception:  # noqa: BLE001 - any import/ABI failure -> fallback
    reservoir_update = _fallback.reservoir_update
    USING_CYTHON_RESERVOIR = False

# Sparse reservoir update (large, highly-sparse reservoirs). The fused Cython
# CSR kernel does the recurrent sparse matvec inside one nogil loop -- no
# per-timestep Python overhead -- and benchmarks faster than a dense dgemv AND
# than scipy-per-step approaches. Falls back to the NumPy sparse matvec when the
# compiled extension is unavailable. Selected in BaseESN._compute_states when W
# is a scipy CSR matrix.
try:
    from .esn_reservoir_optimized import reservoir_update_sparse as _cython_sparse
except Exception:  # noqa: BLE001
    _cython_sparse = None


[docs] def reservoir_update_sparse(input_sequence, W_in, W_reservoir, activation="tanh", leaky=1.0, bias=None, x0=None, noise_sequence=None): """Sparse-``W`` reservoir update; fused Cython CSR kernel when available.""" if _cython_sparse is None: return _fallback.reservoir_update( input_sequence, W_in, W_reservoir, activation=activation, leaky=leaky, bias=bias, x0=x0, noise_sequence=noise_sequence) csr = W_reservoir.tocsr() return _cython_sparse( input_sequence=_np.ascontiguousarray(input_sequence, dtype=_np.float64), W_in=_np.ascontiguousarray(W_in, dtype=_np.float64), W_data=_np.ascontiguousarray(csr.data, dtype=_np.float64), W_indices=_np.ascontiguousarray(csr.indices, dtype=_np.int32), W_indptr=_np.ascontiguousarray(csr.indptr, dtype=_np.int32), activation=activation, leaky=leaky, bias=bias, x0=x0, noise_sequence=noise_sequence)
# --- fractional differencing ---------------------------------------------- try: from .fractional_diff import fractional_diff USING_CYTHON_FRACDIFF = True except Exception: # noqa: BLE001 fractional_diff = _fallback.fractional_diff USING_CYTHON_FRACDIFF = False # --- MODWT ----------------------------------------------------------------- try: from .modwt_fast import modwt USING_CYTHON_MODWT = True except Exception: # noqa: BLE001 modwt = _fallback.modwt USING_CYTHON_MODWT = False if not (USING_CYTHON_RESERVOIR and USING_CYTHON_FRACDIFF and USING_CYTHON_MODWT): _missing = [ name for name, ok in ( ("reservoir", USING_CYTHON_RESERVOIR), ("fractional_diff", USING_CYTHON_FRACDIFF), ("modwt", USING_CYTHON_MODWT), ) if not ok ] warnings.warn( "memory_esn: using NumPy fallback for {} (compiled kernels not found). " "For best performance run: python setup.py build_ext --inplace".format( ", ".join(_missing) ), RuntimeWarning, stacklevel=2, )