core/tests/test_rust_backend.py
Shay da92c1c3c0 feat(rust): scalar Cl(4,1) zero-copy input boundary (ADR-0235 PR C)
Replace extract_f32_slice list conversion on geometric_product, cga_inner,
versor_condition, versor_apply_with_closure, and versor_apply_with_closure_f64
with PyReadonlyArray1 zero-copy views. Wrong shape, dtype, and non-contiguous
layouts fail loudly. Update Apple UMA benchmark truth table and claim audit
after parity gates pass.
2026-06-24 13:02:06 -07:00

139 lines
4.2 KiB
Python

"""Rust versor_apply parity tests.
Verifies that the Rust closure-aware versor_apply produces identical results
to the Python algebra.versor.versor_apply for all critical cases:
identity, rotors, null vectors, versor condition, and backend dispatch.
"""
from __future__ import annotations
import numpy as np
import pytest
from algebra.versor import (
unitize_versor,
versor_apply as python_versor_apply,
versor_condition,
)
from algebra.cga import embed_point, is_null
try:
import core_rs
HAS_RUST = True
except ImportError:
HAS_RUST = False
skip_no_rust = pytest.mark.skipif(not HAS_RUST, reason="core_rs not available")
def _positive_unit_reflector(seed: int) -> np.ndarray:
rng = np.random.default_rng(seed)
vec4 = rng.standard_normal(4).astype(np.float32)
norm4 = float(np.linalg.norm(vec4))
if norm4 < 1e-6:
vec4[0] = 1.0
norm4 = 1.0
vec = np.zeros(5, dtype=np.float32)
vec[:4] = vec4
vec[4] = 0.25 * norm4 * np.tanh(float(rng.standard_normal()))
mv = np.zeros(32, dtype=np.float32)
mv[1:6] = vec
return unitize_versor(mv)
def _random_rotor(seed: int) -> np.ndarray:
from algebra.cl41 import geometric_product as gp
a = _positive_unit_reflector(seed)
b = _positive_unit_reflector(seed + 10000)
return unitize_versor(gp(a, b))
@skip_no_rust
def test_rust_versor_apply_matches_python_for_identity():
identity = np.zeros(32, dtype=np.float32)
identity[0] = 1.0
F = _positive_unit_reflector(42)
F32 = np.asarray(F, dtype=np.float32)
py_result = python_versor_apply(identity, F)
rust_result = np.asarray(
core_rs.versor_apply_with_closure(identity, F32), dtype=np.float32
)
assert np.allclose(py_result, rust_result, atol=1e-4), (
f"max diff: {np.max(np.abs(py_result - rust_result))}"
)
@skip_no_rust
def test_rust_versor_apply_matches_python_for_rotors():
for seed in range(20):
V = _random_rotor(seed)
F = _positive_unit_reflector(seed + 500)
V32 = np.asarray(V, dtype=np.float32)
F32 = np.asarray(F, dtype=np.float32)
py_result = python_versor_apply(V, F)
rust_result = np.asarray(
core_rs.versor_apply_with_closure(V32, F32), dtype=np.float32
)
assert np.allclose(py_result, rust_result, atol=1e-3), (
f"seed={seed} max diff: {np.max(np.abs(py_result - rust_result))}"
)
@skip_no_rust
def test_rust_versor_apply_preserves_null_vectors():
point = embed_point(np.array([1.0, 2.0, 3.0], dtype=np.float32))
assert is_null(point)
V32 = np.asarray(_positive_unit_reflector(7), dtype=np.float32)
point32 = np.asarray(point, dtype=np.float32)
rust_result = np.asarray(
core_rs.versor_apply_with_closure(V32, point32), dtype=np.float32
)
py_result = python_versor_apply(V32, point32)
py_is_null = is_null(py_result)
rust_is_null = is_null(rust_result)
assert py_is_null == rust_is_null, (
f"null preservation mismatch: python={py_is_null}, rust={rust_is_null}"
)
@skip_no_rust
def test_rust_versor_apply_preserves_versor_condition():
for seed in range(20):
V32 = np.asarray(_positive_unit_reflector(seed), dtype=np.float32)
F32 = np.asarray(_positive_unit_reflector(seed + 1000), dtype=np.float32)
rust_result = np.asarray(
core_rs.versor_apply_with_closure(V32, F32), dtype=np.float32
)
cond = versor_condition(rust_result)
assert cond < 1e-4, f"seed={seed} condition={cond:.2e}"
@skip_no_rust
def test_backend_dispatch_uses_rust_only_when_enabled():
"""Verify that algebra.backend.versor_apply only uses Rust when CORE_BACKEND=rust."""
import os
from importlib import reload
import algebra.backend as backend_mod
original = os.environ.get("CORE_BACKEND", "")
os.environ["CORE_BACKEND"] = "numpy"
reload(backend_mod)
assert not (backend_mod._REQUESTED_BACKEND == "rust")
os.environ["CORE_BACKEND"] = "rust"
reload(backend_mod)
assert backend_mod._REQUESTED_BACKEND == "rust"
if original:
os.environ["CORE_BACKEND"] = original
else:
os.environ.pop("CORE_BACKEND", None)
reload(backend_mod)