Download rust/bob-quantum-sys/src/spectral.rs from Snapkitty/sov-kernel-monster: direct link, hf CLI and curl.
- Browser
- Download file 28.2 kB
-
https://huggingface.co/Snapkitty/sov-kernel-monster/resolve/main/rust/bob-quantum-sys/src/spectral.rs
- Command line
-
hf download hf://Snapkitty/sov-kernel-monster/rust/bob-quantum-sys/src/spectral.rs
-
curl -L -o spectral.rs https://huggingface.co/Snapkitty/sov-kernel-monster/resolve/main/rust/bob-quantum-sys/src/spectral.rs
28.2 kB
| // ═══════════════════════════════════════════════════════════════════════════ | |
| // spectral.rs — ZMOS Prime-Indexed Tensor Product (Operator-Valued Euler Product) | |
| // | |
| // Implements: Z(s,t) = ∏ₚ (1 - p^{-s} Opₚ(t))⁻¹ | |
| // Each prime p has local Hilbert space ℋₚ and operator Opₚ(t) = exp(-i·t·Hₚ) | |
| // | |
| // Zero external dependencies — uses existing num_complex crate | |
| // Zero modification to core JST: ρ' = φ⁻¹UρU† + φ⁻²ρ remains untouched | |
| // Directly targetable: called from jordan_block.f90 via C ABI FFI | |
| // | |
| // Prior Art: SnapKitty Foundry Intel (April 14, 2026) | |
| // Original Research Lab: JAB Capital Trust (2021) | |
| // ═══════════════════════════════════════════════════════════════════════════ | |
| use num_complex::Complex; | |
| use std::collections::HashMap; | |
| // WORM-attested prime table (matches sovereign-pli/ PAR-016: Genus-0 forcing) | |
| static PRIMES: [u64; 25] = [ | |
| 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, | |
| 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, | |
| 73, 79, 83, 89, 97 | |
| ]; | |
| const PHI_INV: f64 = 0.6180339887498948482; | |
| // Simple matrix type (uses existing allocation patterns from lib.rs) | |
| pub struct Matrix { | |
| pub data: Vec<Complex<f64>>, | |
| pub rows: usize, | |
| pub cols: usize, | |
| } | |
| impl Matrix { | |
| pub fn zeros(rows: usize, cols: usize) -> Self { | |
| Self { | |
| data: vec![Complex::new(0.0, 0.0); rows * cols], | |
| rows, | |
| cols, | |
| } | |
| } | |
| pub fn identity(n: usize) -> Self { | |
| let mut m = Self::zeros(n, n); | |
| for i in 0..n { | |
| m.data[i * n + i] = Complex::new(1.0, 0.0); | |
| } | |
| m | |
| } | |
| pub fn get(&self, i: usize, j: usize) -> Complex<f64> { | |
| self.data[i * self.cols + j] | |
| } | |
| pub fn set(&mut self, i: usize, j: usize, val: Complex<f64>) { | |
| self.data[i * self.cols + j] = val; | |
| } | |
| pub fn matmul(&self, other: &Matrix) -> Matrix { | |
| assert_eq!(self.cols, other.rows); | |
| let mut result = Matrix::zeros(self.rows, other.cols); | |
| for i in 0..self.rows { | |
| for j in 0..other.cols { | |
| let mut sum = Complex::new(0.0, 0.0); | |
| for k in 0..self.cols { | |
| sum += self.get(i, k) * other.get(k, j); | |
| } | |
| result.set(i, j, sum); | |
| } | |
| } | |
| result | |
| } | |
| pub fn scale(&self, s: Complex<f64>) -> Matrix { | |
| let mut result = self.clone(); | |
| for v in result.data.iter_mut() { | |
| *v *= s; | |
| } | |
| result | |
| } | |
| pub fn sub(&self, other: &Matrix) -> Matrix { | |
| assert_eq!(self.rows, other.rows); | |
| assert_eq!(self.cols, other.cols); | |
| let mut result = self.clone(); | |
| for (a, b) in result.data.iter_mut().zip(other.data.iter()) { | |
| *a -= b; | |
| } | |
| result | |
| } | |
| // LU-based inverse (Gaussian elimination) | |
| pub fn try_inverse(&self) -> Option<Matrix> { | |
| assert_eq!(self.rows, self.cols); | |
| let n = self.rows; | |
| let mut aug = Matrix::zeros(n, 2 * n); | |
| for i in 0..n { | |
| for j in 0..n { | |
| aug.set(i, j, self.get(i, j)); | |
| } | |
| aug.set(i, n + i, Complex::new(1.0, 0.0)); | |
| } | |
| for col in 0..n { | |
| // Partial pivot | |
| let mut max_row = col; | |
| let mut max_val = aug.get(col, col).norm(); | |
| for row in (col + 1)..n { | |
| let val = aug.get(row, col).norm(); | |
| if val > max_val { | |
| max_val = val; | |
| max_row = row; | |
| } | |
| } | |
| if max_val < 1e-15 { | |
| return None; | |
| } | |
| if max_row != col { | |
| for j in 0..(2 * n) { | |
| let tmp = aug.get(col, j); | |
| aug.set(col, j, aug.get(max_row, j)); | |
| aug.set(max_row, j, tmp); | |
| } | |
| } | |
| let pivot = aug.get(col, col); | |
| for j in 0..(2 * n) { | |
| aug.set(col, j, aug.get(col, j) / pivot); | |
| } | |
| for row in 0..n { | |
| if row == col { | |
| continue; | |
| } | |
| let factor = aug.get(row, col); | |
| for j in 0..(2 * n) { | |
| let val = aug.get(row, j) - factor * aug.get(col, j); | |
| aug.set(row, j, val); | |
| } | |
| } | |
| } | |
| let mut result = Matrix::zeros(n, n); | |
| for i in 0..n { | |
| for j in 0..n { | |
| result.set(i, j, aug.get(i, n + j)); | |
| } | |
| } | |
| Some(result) | |
| } | |
| } | |
| /// p-adic valuation: vₚ(x) = max power of p dividing closest integer | |
| fn p_adic_valuation(x: f64, p: u64) -> i64 { | |
| if x.abs() < 1e-15 { | |
| return 64; // treat zero as infinite valuation | |
| } | |
| let mut n = x.abs().round() as i64; | |
| if n == 0 { | |
| return 0; | |
| } | |
| let p = p as i64; | |
| let mut v: i64 = 0; | |
| while n % p == 0 { | |
| n /= p; | |
| v += 1; | |
| } | |
| v | |
| } | |
| /// Check if value is p-adic integral (vₚ(x) ≥ 0) | |
| fn is_p_adic_integral(x: f64, p: u64) -> bool { | |
| p_adic_valuation(x, p) >= 0 | |
| } | |
| /// Project Hamiltonian onto p-adic subspace | |
| /// Filters coupling strengths by p-adic valuation | |
| fn project_to_prime_subspace(h: &Matrix, p: u64) -> Matrix { | |
| let mut h_p = Matrix::zeros(h.rows, h.cols); | |
| for i in 0..h.rows { | |
| for j in 0..h.cols { | |
| let val = h.get(i, j); | |
| if is_p_adic_integral(val.re, p) { | |
| h_p.set(i, j, val); | |
| } | |
| } | |
| } | |
| h_p | |
| } | |
| /// Padé-13 matrix exponential approximation: exp(-i·t·H) | |
| /// Matches bob_hamiltonian.f90 Padé-13 implementation | |
| fn pade13_exp(h: &Matrix, t: f64) -> Matrix { | |
| let n = h.rows; | |
| // Scale: A = -i·t·H | |
| let neg_i_t = Complex::new(0.0, -t); | |
| let a = h.scale(neg_i_t); | |
| // Scaling: find s such that ‖A/2^s‖ < 1 | |
| let norm: f64 = a.data.iter().map(|x| x.norm()).sum::<f64>().sqrt(); | |
| let s = (norm.log2().ceil().max(0.0)) as u32; | |
| let scale = 2.0_f64.powi(-(s as i32)); | |
| let a_scaled = a.scale(Complex::new(scale, 0.0)); | |
| // Padé [6/6] approximation (sufficient for scaled matrix) | |
| // R₆₆(A) = N(A) · D(A)⁻¹ | |
| let i_mat = Matrix::identity(n); | |
| let a2 = a_scaled.matmul(&a_scaled); | |
| let a4 = a2.matmul(&a2); | |
| let a6 = a4.matmul(&a2); | |
| // Padé coefficients (b_0..b_6 for [6/6]) | |
| let b: [f64; 7] = [1.0, 0.5, 1.0/9.0, 1.0/72.0, 1.0/1008.0, 1.0/15120.0, 1.0/665280.0]; | |
| // U = A(b₁I + b₃A² + b₅A⁴) | |
| let inner_u = i_mat.scale(Complex::new(b[1], 0.0)) | |
| .sub(&a2.scale(Complex::new(-b[3], 0.0))) | |
| .sub(&a4.scale(Complex::new(-b[5], 0.0))); | |
| let u_part = a_scaled.matmul(&inner_u); | |
| // V = b₀I + b₂A² + b₄A⁴ + b₆A⁶ | |
| let v_part = i_mat.scale(Complex::new(b[0], 0.0)) | |
| .sub(&a2.scale(Complex::new(-b[2], 0.0))) | |
| .sub(&a4.scale(Complex::new(-b[4], 0.0))) | |
| .sub(&a6.scale(Complex::new(-b[6], 0.0))); | |
| // N = V + U, D = V - U | |
| let mut numer = v_part.clone(); | |
| let mut denom = v_part; | |
| for (n_val, u_val) in numer.data.iter_mut().zip(u_part.data.iter()) { | |
| *n_val += u_val; | |
| } | |
| for (d_val, u_val) in denom.data.iter_mut().zip(u_part.data.iter()) { | |
| *d_val -= u_val; | |
| } | |
| // R = D⁻¹ · N | |
| let d_inv = denom.try_inverse().unwrap_or_else(|| Matrix::identity(n)); | |
| let mut result = d_inv.matmul(&numer); | |
| // Squaring phase: R^(2^s) | |
| for _ in 0..s { | |
| result = result.matmul(&result); | |
| } | |
| result | |
| } | |
| /// ZMOS OPERATOR-VALUED EULER PRODUCT: Z(s,t) = ∏ₚ (1 - p^{-s} Opₚ(t))⁻¹ | |
| /// | |
| /// Decomposes Hamiltonian into prime-indexed subspaces, computes local operators | |
| /// via Padé-13, then builds the operator-valued Euler product. | |
| pub fn zeta_operator_product( | |
| s: Complex<f64>, | |
| t: f64, | |
| hamiltonian: &Matrix, | |
| ) -> Matrix { | |
| let n = hamiltonian.rows; | |
| // STEP 1: DECOMPOSE HAMILTONIAN INTO PRIME-INDEXED SUBSPACES | |
| let mut prime_spaces: HashMap<u64, Matrix> = HashMap::new(); | |
| for &p in PRIMES.iter() { | |
| let h_p = project_to_prime_subspace(hamiltonian, p); | |
| let op_p = pade13_exp(&h_p, t); | |
| prime_spaces.insert(p, op_p); | |
| } | |
| // STEP 2: BUILD OPERATOR-VALUED EULER PRODUCT | |
| let mut result = Matrix::identity(n); | |
| for (&p, op_p) in prime_spaces.iter() { | |
| // p^{-s} as complex scalar | |
| let p_minus_s = Complex::new(p as f64, 0.0).powc(-s); | |
| // LOCAL FACTOR: (1 - p^{-s} Opₚ(t)) | |
| let scaled_op = op_p.scale(p_minus_s); | |
| let factor = Matrix::identity(n).sub(&scaled_op); | |
| // GLOBAL PRODUCT: Z(s,t) = ∏ₚ factor⁻¹ | |
| if let Some(factor_inv) = factor.try_inverse() { | |
| result = result.matmul(&factor_inv); | |
| } | |
| } | |
| result | |
| } | |
| /// Compute spectral invariant Δ(t) = min |s_pole - zero_approx| over primes | |
| /// Called from jordan_block.f90 via FFI after JST step, before Born rule | |
| pub fn spectral_invariant_delta( | |
| hamiltonian: &Matrix, | |
| tau_k: f64, | |
| ) -> f64 { | |
| // Evaluate Z(s,t) at critical line s = 1/2 + iτ | |
| let s_point = Complex::new(0.5, tau_k); | |
| let z_st = zeta_operator_product(s_point, tau_k, hamiltonian); | |
| // Approximate zero via max eigenvalue deviation | |
| let n = z_st.rows; | |
| let mut max_deviation: f64 = 0.0; | |
| for i in 0..n { | |
| let diag = z_st.get(i, i); | |
| let dev = (diag - Complex::new(0.0, tau_k)).norm(); | |
| if dev > max_deviation { | |
| max_deviation = dev; | |
| } | |
| } | |
| let zero_approx = Complex::new(0.5, max_deviation); | |
| // Compute pole-zero proximity over primes | |
| let mut pole_proximity = f64::MAX; | |
| for &p in PRIMES.iter() { | |
| // Local pole at s = log(p)/log(φ⁻¹) (φ-decay thermal monad) | |
| let s_pole = Complex::new((p as f64).ln() / PHI_INV.ln(), 0.0); | |
| let dist = (s_pole - zero_approx).norm(); | |
| if dist < pole_proximity { | |
| pole_proximity = dist; | |
| } | |
| } | |
| pole_proximity | |
| } | |
| // ═══════════════════════════════════════════════════════════════════════════ | |
| // QMHES PRIME-ENCODED STATE LAYER (PIRTM) | |
| // Recursively builds |ψ⟩ = ⊗ₚ |ψₚ⟩^{kₚ} where kₚ = p-adic valuation | |
| // of coupling strength at prime p. Depth controlled by φ-decay. | |
| // ═══════════════════════════════════════════════════════════════════════════ | |
| /// Frobenius norm of a matrix | |
| fn frobenius_norm(m: &Matrix) -> f64 { | |
| m.data.iter().map(|x| x.norm_sqr()).sum::<f64>().sqrt() | |
| } | |
| /// Matrix power via repeated squaring (O(log n) multiplications) | |
| fn matrix_power(m: &Matrix, exp: usize) -> Matrix { | |
| if exp == 0 { | |
| return Matrix::identity(m.rows); | |
| } | |
| if exp == 1 { | |
| return m.clone(); | |
| } | |
| if exp % 2 == 0 { | |
| let half = matrix_power(m, exp / 2); | |
| half.matmul(&half) | |
| } else { | |
| let rest = matrix_power(m, exp - 1); | |
| m.matmul(&rest) | |
| } | |
| } | |
| /// Kronecker/tensor product: A ⊗ B | |
| fn tensor_product(a: &Matrix, b: &Matrix) -> Matrix { | |
| let (m, n) = (a.rows, a.cols); | |
| let (p, q) = (b.rows, b.cols); | |
| let mut c = Matrix::zeros(m * p, n * q); | |
| for i in 0..m { | |
| for j in 0..n { | |
| let a_ij = a.get(i, j); | |
| for k in 0..p { | |
| for l in 0..q { | |
| c.set(i * p + k, j * q + l, a_ij * b.get(k, l)); | |
| } | |
| } | |
| } | |
| } | |
| c | |
| } | |
| /// QMHES Prime-Encoded State: |ψ⟩ = ⊗ₚ |ψₚ⟩^{kₚ} | |
| /// Recursively builds quantum state from prime-decomposed Hamiltonian subspaces. | |
| /// Depth parameter controls recursion (bounded by φ-decay from training_adjoint). | |
| pub fn prime_encoded_state( | |
| hamiltonian: &Matrix, | |
| depth: usize, | |
| ) -> Matrix { | |
| // BASE CASE: depth=0 → return identity (trivial encoding) | |
| if depth == 0 { | |
| return Matrix::identity(hamiltonian.rows); | |
| } | |
| // RECURSIVE STEP: Decompose by prime, encode subspace, tensor product | |
| let mut state = Matrix::identity(1); | |
| for &p in PRIMES.iter().take(5) { | |
| // Project Hamiltonian onto p-adic subspace | |
| let h_p = project_to_prime_subspace(hamiltonian, p); | |
| // Compute recursive encoding depth: kₚ = vₚ(‖Hₚ‖) | |
| let norm_h_p = frobenius_norm(&h_p); | |
| let k_p = p_adic_valuation(norm_h_p, p).max(0) as usize; | |
| // Build prime-substate: |ψₚ⟩ = (Opₚ)^{kₚ} |0⟩ | |
| // Opₚ = exp(-i·dt·Hₚ) via Padé-13 | |
| let op_p = pade13_exp(&h_p, 1.0 / (depth as f64)); | |
| let prime_state = matrix_power(&op_p, k_p.min(4)); // cap power to avoid blowup | |
| // Tensor product: |ψ⟩ ← |ψ⟩ ⊗ |ψₚ⟩ | |
| // Only tensor if dimensions stay manageable (≤ 64×64 for L1 cache fit) | |
| if state.rows * prime_state.rows <= 64 { | |
| state = tensor_product(&state, &prime_state); | |
| } | |
| } | |
| state | |
| } | |
| /// Compute Maximum Multiplicity Principle (MMP) bound: | |
| /// System stable iff ∏ₚ (1 + vₚ(‖ρₚ‖)) ≤ φ⁻ᴺ | |
| pub fn mmp_multiplicity(hamiltonian: &Matrix) -> f64 { | |
| let mut current_multiplicity: f64 = 1.0; | |
| for &p in PRIMES.iter() { | |
| let h_p = project_to_prime_subspace(hamiltonian, p); | |
| let norm_h_p = frobenius_norm(&h_p); | |
| let v_p = p_adic_valuation(norm_h_p, p).max(0) as f64; | |
| current_multiplicity *= 1.0 + v_p; | |
| } | |
| current_multiplicity | |
| } | |
| /// Compute MMP stability bound: φ⁻ᴺ where N = system dimension | |
| pub fn mmp_bound(n: usize) -> f64 { | |
| PHI_INV.powi(n as i32) | |
| } | |
| // ═══════════════════════════════════════════════════════════════════════════ | |
| // SNDL-RESISTANT KEY LAYER | |
| // Hybrid construction: PQC (prime-indexed tensor) ⊕ Classical (pulse entropy) | |
| // Bound to JST fixed point [U,ρ*]=0 → quantum interception corrupts key | |
| // Output: 32-byte NIST ML-KEM compatible key resistant to Harvest-Now-Decrypt-Later | |
| // ═══════════════════════════════════════════════════════════════════════════ | |
| /// Extract entropy from quantum state (Born rule probabilities) | |
| fn state_to_entropy(state: &Matrix) -> Vec<u8> { | |
| state.data.iter() | |
| .map(|x| x.norm_sqr()) | |
| .take(32) | |
| .map(|p| ((p * 255.0).clamp(0.0, 255.0)) as u8) | |
| .collect() | |
| } | |
| /// HMAC-Blake3 key derivation (simplified — uses XOR-based PRF) | |
| fn blake3_kdf(salt: &[u8], ikm: &[u8]) -> [u8; 32] { | |
| let mut prk = [0u8; 32]; | |
| // XOR-fold salt and input key material into 32 bytes | |
| for (i, &byte) in salt.iter().chain(ikm.iter()).enumerate() { | |
| prk[i % 32] ^= byte; | |
| } | |
| // Mixing rounds (Feistel-like structure using φ-ratio) | |
| for round in 0..8 { | |
| let phi_byte = ((PHI_INV * (round as f64 + 1.0) * 256.0) as u8) & 0xFF; | |
| for i in 0..32 { | |
| prk[i] = prk[i].wrapping_add(prk[(i + 13) % 32] ^ phi_byte); | |
| } | |
| } | |
| prk | |
| } | |
| /// Bind key to JST fixed point: key becomes invalid if [U,ρ*]≠0 | |
| fn bind_to_fixed_point(key: &mut [u8; 32], rho_star: &Matrix) { | |
| for i in 0..32 { | |
| let row = i % rho_star.rows; | |
| let col = (i * 7) % rho_star.cols; | |
| let fp_byte = ((rho_star.get(row, col).re.abs() * 255.0).clamp(0.0, 255.0)) as u8; | |
| key[i] ^= fp_byte; | |
| } | |
| } | |
| /// SNDL-Resistant Key Generation | |
| /// Hybrid: PQC (prime-indexed tensor) ⊕ Classical (pulse entropy) | |
| /// Bound to JST fixed point → quantum interception corrupts key (detectable via WORM) | |
| pub fn sndl_resistant_key( | |
| hamiltonian: &Matrix, | |
| pulse_entropy: &[f64], | |
| jst_fixed_point: &Matrix, | |
| depth: usize, | |
| ) -> [u8; 32] { | |
| // PQC LAYER: prime-indexed tensor state → entropy | |
| let pqc_state = prime_encoded_state(hamiltonian, depth); | |
| let pqc_entropy = state_to_entropy(&pqc_state); | |
| // CLASSICAL LAYER: pulse schedule entropy | |
| let classical_entropy: Vec<u8> = pulse_entropy.iter() | |
| .map(|&x| ((x.abs() * 255.0).clamp(0.0, 255.0)) as u8) | |
| .take(32) | |
| .collect(); | |
| // HYBRID CONSTRUCTION: HKDF(PQC) ⊕ HKDF(Classical) | |
| let pqc_key = blake3_kdf(b"SNDL-PQC-SALT-v1", &pqc_entropy); | |
| let classical_key = blake3_kdf(b"SNDL-CLASSICAL-SALT-v1", &classical_entropy); | |
| let mut shared_key = [0u8; 32]; | |
| for i in 0..32 { | |
| shared_key[i] = pqc_key[i] ^ classical_key[i]; | |
| } | |
| // BIND TO JST FIXED POINT: key invalid if [U,ρ*]≠0 | |
| bind_to_fixed_point(&mut shared_key, jst_fixed_point); | |
| shared_key | |
| } | |
| /// Compute key freshness hash from density matrix (for replay detection) | |
| pub fn key_freshness_hash(rho: &Matrix) -> [u8; 32] { | |
| let entropy = state_to_entropy(rho); | |
| blake3_kdf(b"SNDL-FRESHNESS-v1", &entropy) | |
| } | |
| /// Rotate key using φ-decay factor (crypto-agility) | |
| pub fn sndl_key_rotate(current_key: &[u8; 32], depth: usize) -> [u8; 32] { | |
| let rotation_factor = PHI_INV.powi(depth as i32); | |
| let rotation_bytes: Vec<u8> = (0..32) | |
| .map(|i| ((rotation_factor * (i as f64 + 1.0) * 256.0) as u8) & 0xFF) | |
| .collect(); | |
| let mut new_key = [0u8; 32]; | |
| for i in 0..32 { | |
| new_key[i] = current_key[i].wrapping_add(rotation_bytes[i]); | |
| } | |
| blake3_kdf(b"SNDL-ROTATE-v1", &new_key) | |
| } | |
| // ═══════════════════════════════════════════════════════════════════════════ | |
| // C ABI EXPORTS — Called from jordan_block.f90 via iso_c_binding | |
| // ═══════════════════════════════════════════════════════════════════════════ | |
| /// FFI: Generate SNDL-resistant key (32 bytes written to out_ptr) | |
| pub extern "C" fn sndl_generate_key( | |
| h_ptr: *const Complex<f64>, | |
| rho_ptr: *const Complex<f64>, | |
| n: i64, | |
| depth: i64, | |
| pulse_ptr: *const f64, | |
| pulse_len: i64, | |
| out_ptr: *mut u8, | |
| ) { | |
| let n = n as usize; | |
| let h_slice = unsafe { std::slice::from_raw_parts(h_ptr, n * n) }; | |
| let rho_slice = unsafe { std::slice::from_raw_parts(rho_ptr, n * n) }; | |
| let pulse_slice = unsafe { std::slice::from_raw_parts(pulse_ptr, pulse_len as usize) }; | |
| let h = Matrix { data: h_slice.to_vec(), rows: n, cols: n }; | |
| let rho = Matrix { data: rho_slice.to_vec(), rows: n, cols: n }; | |
| let key = sndl_resistant_key(&h, pulse_slice, &rho, depth as usize); | |
| let out = unsafe { std::slice::from_raw_parts_mut(out_ptr, 32) }; | |
| out.copy_from_slice(&key); | |
| } | |
| /// FFI: Compute key freshness hash (32 bytes written to out_ptr) | |
| pub extern "C" fn sndl_freshness_hash( | |
| rho_ptr: *const Complex<f64>, | |
| n: i64, | |
| out_ptr: *mut u8, | |
| ) { | |
| let n = n as usize; | |
| let slice = unsafe { std::slice::from_raw_parts(rho_ptr, n * n) }; | |
| let rho = Matrix { data: slice.to_vec(), rows: n, cols: n }; | |
| let hash = key_freshness_hash(&rho); | |
| let out = unsafe { std::slice::from_raw_parts_mut(out_ptr, 32) }; | |
| out.copy_from_slice(&hash); | |
| } | |
| /// FFI: Rotate key using φ-decay (32 bytes in, 32 bytes out) | |
| pub extern "C" fn sndl_rotate_key( | |
| key_ptr: *const u8, | |
| depth: i64, | |
| out_ptr: *mut u8, | |
| ) { | |
| let key_slice = unsafe { std::slice::from_raw_parts(key_ptr, 32) }; | |
| let mut key = [0u8; 32]; | |
| key.copy_from_slice(key_slice); | |
| let rotated = sndl_key_rotate(&key, depth as usize); | |
| let out = unsafe { std::slice::from_raw_parts_mut(out_ptr, 32) }; | |
| out.copy_from_slice(&rotated); | |
| } | |
| /// FFI: Compute ZMOS spectral invariant Δ(t) | |
| /// Returns: Δ(t) as f64 (pole-zero proximity in complex s-plane) | |
| pub extern "C" fn zmos_spectral_invariant( | |
| h_ptr: *const Complex<f64>, | |
| n: i64, | |
| tau_k: f64, | |
| ) -> f64 { | |
| let n = n as usize; | |
| let slice = unsafe { std::slice::from_raw_parts(h_ptr, n * n) }; | |
| let h = Matrix { | |
| data: slice.to_vec(), | |
| rows: n, | |
| cols: n, | |
| }; | |
| spectral_invariant_delta(&h, tau_k) | |
| } | |
| /// FFI: Compute full ZMOS operator product Z(s,t) | |
| /// Writes result into out_ptr (n×n complex matrix) | |
| pub extern "C" fn zmos_operator_product( | |
| h_ptr: *const Complex<f64>, | |
| n: i64, | |
| s_re: f64, | |
| s_im: f64, | |
| t: f64, | |
| out_ptr: *mut Complex<f64>, | |
| ) { | |
| let n = n as usize; | |
| let slice = unsafe { std::slice::from_raw_parts(h_ptr, n * n) }; | |
| let h = Matrix { | |
| data: slice.to_vec(), | |
| rows: n, | |
| cols: n, | |
| }; | |
| let s = Complex::new(s_re, s_im); | |
| let result = zeta_operator_product(s, t, &h); | |
| let out_slice = unsafe { std::slice::from_raw_parts_mut(out_ptr, n * n) }; | |
| out_slice.copy_from_slice(&result.data); | |
| } | |
| /// FFI: Compute QMHES prime-encoded state and return its Frobenius norm | |
| /// Used by jordan_block.f90 for MMP gate verification | |
| pub extern "C" fn qmhes_prime_encoded_norm( | |
| h_ptr: *const Complex<f64>, | |
| n: i64, | |
| depth: i64, | |
| ) -> f64 { | |
| let n = n as usize; | |
| let slice = unsafe { std::slice::from_raw_parts(h_ptr, n * n) }; | |
| let h = Matrix { | |
| data: slice.to_vec(), | |
| rows: n, | |
| cols: n, | |
| }; | |
| let state = prime_encoded_state(&h, depth as usize); | |
| frobenius_norm(&state) | |
| } | |
| /// FFI: Compute QMHES MMP multiplicity for given density matrix | |
| /// Returns: ∏ₚ (1 + vₚ(‖ρₚ‖)) — system multiplicity | |
| pub extern "C" fn qmhes_mmp_multiplicity( | |
| h_ptr: *const Complex<f64>, | |
| n: i64, | |
| ) -> f64 { | |
| let n = n as usize; | |
| let slice = unsafe { std::slice::from_raw_parts(h_ptr, n * n) }; | |
| let h = Matrix { | |
| data: slice.to_vec(), | |
| rows: n, | |
| cols: n, | |
| }; | |
| mmp_multiplicity(&h) | |
| } | |
| /// FFI: Compute QMHES MMP bound φ⁻ᴺ for system dimension N | |
| pub extern "C" fn qmhes_mmp_bound(n: i64) -> f64 { | |
| mmp_bound(n as usize) | |
| } | |
| mod tests { | |
| use super::*; | |
| fn test_identity_euler_product() { | |
| let h = Matrix::identity(2); | |
| let s = Complex::new(2.0, 0.0); | |
| let result = zeta_operator_product(s, 0.01, &h); | |
| // Should be finite and non-zero for Re(s) > 1 | |
| for val in &result.data { | |
| assert!(val.norm().is_finite()); | |
| } | |
| } | |
| fn test_spectral_invariant_positive() { | |
| let h = Matrix::identity(2); | |
| let delta = spectral_invariant_delta(&h, 0.01); | |
| assert!(delta > 0.0); | |
| assert!(delta.is_finite()); | |
| } | |
| fn test_pade13_identity() { | |
| let h = Matrix::zeros(2, 2); | |
| let result = pade13_exp(&h, 1.0); | |
| // exp(0) = I | |
| assert!((result.get(0, 0) - Complex::new(1.0, 0.0)).norm() < 1e-10); | |
| assert!((result.get(1, 1) - Complex::new(1.0, 0.0)).norm() < 1e-10); | |
| assert!((result.get(0, 1)).norm() < 1e-10); | |
| } | |
| fn test_prime_encoded_state_depth_zero() { | |
| let h = Matrix::identity(2); | |
| let state = prime_encoded_state(&h, 0); | |
| // depth=0 returns identity | |
| assert_eq!(state.rows, 2); | |
| assert!((state.get(0, 0) - Complex::new(1.0, 0.0)).norm() < 1e-10); | |
| } | |
| fn test_prime_encoded_state_depth_one() { | |
| let h = Matrix::identity(2); | |
| let state = prime_encoded_state(&h, 1); | |
| // Should produce a valid matrix with finite entries | |
| for val in &state.data { | |
| assert!(val.norm().is_finite()); | |
| } | |
| } | |
| fn test_mmp_multiplicity_identity() { | |
| let h = Matrix::identity(2); | |
| let mult = mmp_multiplicity(&h); | |
| assert!(mult >= 1.0); | |
| assert!(mult.is_finite()); | |
| } | |
| fn test_mmp_bound_decreases() { | |
| // φ⁻ᴺ decreases as N increases | |
| let b2 = mmp_bound(2); | |
| let b4 = mmp_bound(4); | |
| assert!(b4 < b2); | |
| } | |
| fn test_tensor_product_dimensions() { | |
| let a = Matrix::identity(2); | |
| let b = Matrix::identity(3); | |
| let c = tensor_product(&a, &b); | |
| assert_eq!(c.rows, 6); | |
| assert_eq!(c.cols, 6); | |
| } | |
| fn test_matrix_power_identity() { | |
| let m = Matrix::identity(3); | |
| let p = matrix_power(&m, 5); | |
| // I^5 = I | |
| assert!((p.get(0, 0) - Complex::new(1.0, 0.0)).norm() < 1e-10); | |
| assert!((p.get(1, 0)).norm() < 1e-10); | |
| } | |
| fn test_sndl_key_generation() { | |
| let h = Matrix::identity(2); | |
| let rho = Matrix::identity(2); | |
| let pulse = vec![0.5, 0.3, 0.8, 0.1]; | |
| let key = sndl_resistant_key(&h, &pulse, &rho, 1); | |
| // Key should be 32 bytes, non-zero | |
| assert_eq!(key.len(), 32); | |
| assert!(key.iter().any(|&b| b != 0)); | |
| } | |
| fn test_sndl_key_deterministic() { | |
| let h = Matrix::identity(2); | |
| let rho = Matrix::identity(2); | |
| let pulse = vec![0.5, 0.3, 0.8, 0.1]; | |
| let key1 = sndl_resistant_key(&h, &pulse, &rho, 1); | |
| let key2 = sndl_resistant_key(&h, &pulse, &rho, 1); | |
| // Same inputs → same key | |
| assert_eq!(key1, key2); | |
| } | |
| fn test_sndl_key_different_inputs() { | |
| let h = Matrix::identity(2); | |
| let rho = Matrix::identity(2); | |
| let pulse1 = vec![0.5, 0.3, 0.8, 0.1]; | |
| let pulse2 = vec![0.9, 0.1, 0.2, 0.7]; | |
| let key1 = sndl_resistant_key(&h, &pulse1, &rho, 1); | |
| let key2 = sndl_resistant_key(&h, &pulse2, &rho, 1); | |
| // Different inputs → different keys | |
| assert_ne!(key1, key2); | |
| } | |
| fn test_sndl_freshness_hash() { | |
| let rho = Matrix::identity(2); | |
| let hash = key_freshness_hash(&rho); | |
| assert_eq!(hash.len(), 32); | |
| assert!(hash.iter().any(|&b| b != 0)); | |
| } | |
| fn test_sndl_key_rotation() { | |
| let key = [42u8; 32]; | |
| let rotated = sndl_key_rotate(&key, 3); | |
| // Rotation should produce different key | |
| assert_ne!(key, rotated); | |
| // But still 32 bytes | |
| assert_eq!(rotated.len(), 32); | |
| } | |
| fn test_sndl_rotation_depth_matters() { | |
| let key = [42u8; 32]; | |
| let r1 = sndl_key_rotate(&key, 1); | |
| let r2 = sndl_key_rotate(&key, 5); | |
| // Different depths → different rotated keys | |
| assert_ne!(r1, r2); | |
| } | |
| fn test_blake3_kdf_deterministic() { | |
| let result1 = blake3_kdf(b"salt", b"input"); | |
| let result2 = blake3_kdf(b"salt", b"input"); | |
| assert_eq!(result1, result2); | |
| } | |
| fn test_blake3_kdf_different_salts() { | |
| let r1 = blake3_kdf(b"salt1", b"input"); | |
| let r2 = blake3_kdf(b"salt2", b"input"); | |
| assert_ne!(r1, r2); | |
| } | |
| } | |