pub struct ComplexDiagonalSSM { /* private fields */ }alloc only.Expand description
Complex Diagonal SSM — standalone streaming primitive.
Maintains a complex hidden state h ∈ C^N (stored as 2N real values,
interleaved re/im) evolving via a stable complex diagonal recurrence.
The real-valued scalar output y = Re(C^T · h) projects the complex
state back to a real observation.
§State layout
h is a flat Vec<f64> of length 2 * n_state:
[re_0, im_0, re_1, im_1, ..., re_{N-1}, im_{N-1}].
§Stability guarantee
The A parameterization A_n = -exp(log_a_complex[2n]) + j·log_a_complex[2n+1]
ensures Re(A_n) < 0 structurally. Combined with either Tustin or
exp-trapezoidal discretization, the spectral radius of the state transition
is guaranteed < 1 for any valid Δ > 0.
§Initialization
Default: S4D-Inv complex (s4d_inv_complex), which gives harmonically-spaced
eigenvalues with oscillatory imaginary parts. This is the Mamba-3 default.
§Example
use irithyll_core::ssm::complex_diag::{ComplexDiagonalSSM, DiscretizeMethod};
let mut cell = ComplexDiagonalSSM::new(8, DiscretizeMethod::Tustin);
let b = vec![1.0; 8];
let c = vec![1.0; 8];
let y = cell.step(0.1, &b, &c, 1.0, 0.5);
assert!(y.is_finite(), "output must be finite");
assert_eq!(cell.state().len(), 16, "state is 2*n_state complex values");Implementations§
Source§impl ComplexDiagonalSSM
impl ComplexDiagonalSSM
Sourcepub fn new(n_state: usize, method: DiscretizeMethod) -> Self
pub fn new(n_state: usize, method: DiscretizeMethod) -> Self
Create a new complex diagonal SSM with S4D-Inv complex initialization.
Uses s4d_inv_complex for harmonically-spaced eigenvalues with
oscillatory imaginary parts (Gu et al., NeurIPS 2022).
§Arguments
n_state– number of complex state dimensions (total state dim = 2*N)method– discretization method (Tustin or ExpTrapezoidal)
Sourcepub fn with_init(log_a_complex: Vec<f64>, method: DiscretizeMethod) -> Self
pub fn with_init(log_a_complex: Vec<f64>, method: DiscretizeMethod) -> Self
Create a ComplexDiagonalSSM with custom A-matrix log-parameters.
§Arguments
log_a_complex– 2*n_state values in[log|re_0|, im_0, ...]layout. Real parts:A_re = -exp(log_a[2n])(must satisfylog_a[2n] > 0for |A_re| > 1).method– discretization method
§Panics
Panics if log_a_complex.len() is not even.
Sourcepub fn step(
&mut self,
delta: f64,
b: &[f64],
c: &[f64],
x: f64,
lambda: f64,
) -> f64
pub fn step( &mut self, delta: f64, b: &[f64], c: &[f64], x: f64, lambda: f64, ) -> f64
Advance state by one timestep and return the real-valued scalar output.
Implements the SISO (single-input single-output) forward pass:
A_n = -exp(log_a[2n]) + j·log_a[2n+1]
(α, β, γ) = discretize(A_n, delta, lambda)
h_n ← α·h_n + β·prev_bx_n + γ·(B[n]·x)
y += Re(C[n]·h_n) = C[n] · Re(h_n) (real C case)For DiscretizeMethod::Tustin, the 3-term β·prev_bx term is zero
(β=0 by construction — prev_bx is not used).
§Arguments
delta– step size (positive, data-dependent in Mamba-3)b– real input projection vector (length = n_state)c– real output projection vector (length = n_state)x– scalar input at this timesteplambda– exp-trapezoidal mixing parameter ∈ [0,1] (ignored for Tustin)
§Returns
Real scalar output y = Re(C^T · h).
Sourcepub fn step_complex(
&mut self,
delta: f64,
b_re: &[f64],
b_im: &[f64],
c_re: &[f64],
c_im: &[f64],
x: f64,
lambda: f64,
) -> f64
pub fn step_complex( &mut self, delta: f64, b_re: &[f64], b_im: &[f64], c_re: &[f64], c_im: &[f64], x: f64, lambda: f64, ) -> f64
Advance state with complex B and C projections.
Returns Re(C^* · h) where C^* is the complex conjugate of C.
This is the full complex SSM output per Mamba-3 Proposition 2:
y = Re((C_re + j·C_im)^* · h) = C_re·Re(h) + C_im·Im(h).
§Arguments
delta– step sizeb_re– real part of B vector (length = n_state)b_im– imaginary part of B vector (length = n_state)c_re– real part of C vector (length = n_state)c_im– imaginary part of C vector (length = n_state)x– scalar inputlambda– exp-trapezoidal λ_t (ignored for Tustin)
§Returns
Real scalar output Re(C^* · h).
Sourcepub fn state_energies(&self) -> Vec<f64>
pub fn state_energies(&self) -> Vec<f64>
Per-state-dimension L2 energy for plasticity and diagnostics.
Returns a vec of length n_state where each element is
sqrt(Re(h_n)² + Im(h_n)²) — the magnitude of the n-th complex state.
Bounded by stability: |h_n| ≤ Σ_{t} |α|^{T-t} · |input_t|. Under a
stable recurrence, this converges to a finite value.
Sourcepub fn state(&self) -> &[f64]
pub fn state(&self) -> &[f64]
Get the complex hidden state as interleaved re/im f64 slice.
Layout: [re_0, im_0, re_1, im_1, ...], length = 2 * n_state.
Sourcepub fn method(&self) -> DiscretizeMethod
pub fn method(&self) -> DiscretizeMethod
Current discretization method.
Auto Trait Implementations§
impl Freeze for ComplexDiagonalSSM
impl RefUnwindSafe for ComplexDiagonalSSM
impl Send for ComplexDiagonalSSM
impl Sync for ComplexDiagonalSSM
impl Unpin for ComplexDiagonalSSM
impl UnsafeUnpin for ComplexDiagonalSSM
impl UnwindSafe for ComplexDiagonalSSM
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more