hyperlattice provides small fixed-size linear algebra over a crate-owned
Scalar type.
It includes scalars, complex numbers, 3D/4D vectors, and 3x3/4x4 matrices. The public types are generic over backend markers:
HyperrealBackend: exact/symbolic scalars backed byhyperreal::RealApproxBackend: anf64center value plus an absolutef64error boundDefaultBackend:HyperrealBackendwhenhyperreal-backendis enabled, otherwiseApproxBackendwhen onlyapprox-backendis enabled
The default feature set enables both backends. The default scalar representation
remains HyperrealBackend.
hyperrealsupplies the default exact/symbolic scalar representation.hyperlatticeowns complex, vector, and matrix algebra over backend-neutralScalar<B>values.hyperlimitcan consumehyperlattice::Scalar<B>structural facts when geometry predicates need sign provenance, filtering, refinement, or robust fallback.
hyperlattice forwards scalar facts. It does not own robust predicate policy
or geometry topology.
Version 0.3.3 is experimental, benchmarked, and intended for small-object
algebra over rich scalar backends, not high-throughput dense BLAS.
Implemented:
Scalar<B>constants and elementary functionsComplex<B>arithmetic and integer powersVector3<B>andVector4<B>componentwise arithmetic, scalar operations, dot products, magnitude, normalization, and checked variantsMatrix3<B>andMatrix4<B>componentwise arithmetic, multiplication, scalar division, matrix division, determinant, inverse, transpose, reciprocal, integer powers, and checked/abort-aware variantsZeroStatus,ScalarFacts,ScalarSign, andScalarMagnitudeBitsAbortSignaland_with_abortAPIs for computations that may refine hyperreal values- symbolic and alternate decimal formatting for hyperreal-backed values
Fallible operations return BlasResult<T>. Checked operations reject both
definite zero and unknown-zero divisors or pivots.
[dependencies]
hyperlattice = "0.3.3"From sibling checkouts:
[dependencies]
hyperlattice = { path = "../hyperlattice" }The hyperreal-backed feature pulls in the matching hyperreal and num
dependencies. Applications only need direct hyperreal or num dependencies
when they use those crates outside hyperlattice.
Approx-only build:
[dependencies]
hyperlattice = {
version = "0.3.3",
default-features = false,
features = ["approx-backend"],
}Features:
| Feature | Default | Purpose |
|---|---|---|
hyperreal-backend |
yes | Enables HyperrealBackend, Real/Rational re-exports, and exact/symbolic scalars. |
approx-backend |
yes | Enables ApproxBackend with f64 +/- epsilon scalar intervals. |
use hyperlattice::{Scalar, ln, log10, pi, sqrt, tau};
fn s(value: i32) -> Scalar {
value.into()
}
let nine: Scalar = 9.into();
assert_eq!(sqrt(nine).unwrap(), s(3));
assert_eq!(tau(), s(2) * pi());
assert_eq!(ln(hyperlattice::e()).unwrap(), s(1));
assert_eq!(log10(s(100)).unwrap(), s(2));use hyperlattice::{ApproxBackend, HyperrealBackend, Scalar, Vector3};
let exact: Scalar<HyperrealBackend> = Scalar::try_from(1.25).unwrap();
let approx: Scalar<ApproxBackend> = Scalar::<ApproxBackend>::approx(1.25, 0.01).unwrap();
let exact_vector = Vector3::<HyperrealBackend>::new([exact.clone(), exact.clone(), exact]);
let approx_vector = Vector3::<ApproxBackend>::new([approx.clone(), approx.clone(), approx]);
assert_eq!(exact_vector.0.len(), approx_vector.0.len());use hyperlattice::{Rational, Scalar, Vector3, one};
fn s(value: i32) -> Scalar {
value.into()
}
let v = Vector3::new([s(3), s(4), s(0)]);
let offset = v.clone() + s(10);
assert_eq!(v.dot(&v), s(25));
assert_eq!(offset, Vector3::new([s(13), s(14), s(10)]));
assert_eq!(v.normalize().unwrap().dot(&v.normalize().unwrap()), one());
let half = Rational::fraction(1, 2).unwrap().into();
let displayed = Vector3::new([half, s(2), s(3)]);
assert_eq!(format!("{displayed}"), "[1/2, 2, 3]");
assert_eq!(format!("{displayed:#}"), "[0.5, 2, 3]");use hyperlattice::{Matrix3, Scalar};
fn s(value: i32) -> Scalar {
value.into()
}
let matrix = Matrix3::new([
[s(1), s(2), s(3)],
[s(0), s(1), s(4)],
[s(5), s(6), s(0)],
]);
assert_eq!(matrix.determinant(), s(1));
assert_eq!(matrix.clone() * matrix.clone().inverse().unwrap(), Matrix3::identity());
assert_eq!((matrix ^ 0).unwrap(), Matrix3::identity());use hyperlattice::{ScalarSign, ZeroStatus, pi};
let facts = pi().structural_facts();
assert_eq!(facts.sign, Some(ScalarSign::Positive));
assert_eq!(facts.zero, ZeroStatus::NonZero);
assert!(!facts.exact_rational);
let approx = pi().to_f64_approx().unwrap();
assert!(approx > 3.0 && approx < 4.0);The hyperreal backend forwards Real::structural_facts,
Real::refine_sign_until, and Real::to_f64_approx. The approx backend derives
facts from its stored interval.
Two backend details are intentionally visible at the type boundary:
Scalar<HyperrealBackend>inheritshyperreal::Realstructural equality.PartialEqis not a full symbolic-equivalence prover, so borrowed and owned operations that build semantically equivalent computable expressions can differ structurally for symbolic values. Exact rationals and dyadic imports are the right inputs for strict borrowed/owned equality tests; use facts or approximation when comparing symbolic construction histories.Scalar::try_from(-0.0_f32)andScalar::try_from(-0.0_f64)import through exact rational zero on the hyperreal backend. The numeric value round-trips, but the IEEE signed-zero bit is intentionally not represented.
use hyperlattice::{AbortSignal, Vector3};
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
let signal: AbortSignal = Arc::new(AtomicBool::new(false));
let vector = Vector3::new([3.into(), 4.into(), 0.into()]);
let unit = vector.normalize_checked_with_abort(&signal).unwrap();
assert_eq!(unit.dot(&unit), 1.into());The crate is optimized for small fixed-size algebra over rich scalars:
- backend hooks for borrowed add, subtract, multiply, divide, inverse, and dot products reduce cloning of hyperreal expression graphs
- hyperreal-backed constants and identities delegate to
hyperrealconstructors - vector, matrix, and complex operations use owned-left/borrowed-right forms in hot paths
- small scalar powers are specialized before exponentiation by squaring
- 3x3 and 4x4 borrowed matrix multiplication is unrolled
- matrix division and inversion use checked zero-status paths where requested
- scalar facts are forwarded by borrow so
hyperlimitcan query them cheaply - the approx backend mirrors the API with a lower-cost interval representation
- backend-specific loop shape is allowed when benchmarks justify it: first try to gate exact/symbolic wins away from approx with a narrow backend capability; if a split is not practical, favor measured hyperreal performance while keeping approx regressions visible in targeted guards
Run the benchmark suite:
cargo bench --bench mathbenchThe generated benchmark summary is in benchmarks.md.
Run dispatch tracing separately:
cargo bench --bench mathbench --features hyperreal-dispatch-trace -- --write-dispatch-trace-mdThe generated trace summary is in dispatch_trace.md.
src/scalar.rs: scalar constants, functions, facts, and zero statussrc/complex.rs:Complexsrc/vector.rs:Vector3andVector4src/matrix.rs:Matrix3andMatrix4src/backend/hyperreal: hyperreal-backed scalar implementationsrc/backend/approx: approximate scalar implementation
cargo fmt --check
cargo test --all-targets
cargo test --all-targets --all-features
cargo test --all-targets --no-default-features --features approx-backend
cargo clippy --all-targets -- -D warnings
cargo clippy --all-targets --all-features -- -D warningsUse --all-features when checking code that uses explicit
HyperrealBackend and ApproxBackend type parameters in the same build.
MIT.
