Skip to main content

Crate la_stack

Crate la_stack 

Source
Expand description

§la-stack

DOI Crates.io Downloads License Docs.rs CI rust-clippy analyze codecov Audit dependencies

la-stack

Fast, stack-allocated linear algebra for fixed dimensions in Rust.

This crate grew from the need to support delaunay with fast, stack-allocated linear algebra primitives and algorithms while keeping the API intentionally small and explicit.

§📐 Introduction

la-stack provides a handful of const-generic, stack-backed building blocks:

  • Vector<const D: usize> for fixed-length f64 vectors backed by [f64; D]
  • Matrix<const D: usize> for fixed-size square f64 matrices backed by [[f64; D]; D]
  • Lu<const D: usize> for LU factorization with partial pivoting (solve + det)
  • Ldlt<const D: usize> for no-pivot factorization intended for exactly symmetric positive-definite matrices (solve + det; typed pivot diagnostics)

§🧮 Mathematical basis

la-stack operates on finite IEEE 754 binary64 values in small, fixed dimensions. Its floating-point paths use LU with partial pivoting, LDLT without pivoting for exactly symmetric positive-definite matrices, and closed-form determinants through D=4. These results remain subject to conditioning and binary64 rounding; factorization tolerances are rejection thresholds, not accuracy guarantees. For D≤4, direct determinants can be paired with a conservative absolute roundoff bound when its range preconditions hold.

With features = ["exact"], stored binary64 inputs are lifted losslessly to rationals for exact determinant signs, determinant values, and solves. Exactness starts at the stored values and cannot recover information rounded away before construction. See the mathematical basis for the algorithms, validity boundaries, and supporting references.

§✨ Design goals

  • Copy types where possible
  • ✅ Const-generic storage (no dynamically sized matrix or vector representation)
  • const fn where possible (compile-time evaluation of determinants, dot products, etc.)
  • ✅ Explicit algorithms (LU, solve, determinant)
  • ✅ Error-bounded f64 determinant filtering plus optional exact signs (det_errbound, det_sign_exact)
  • ✅ Exact determinant values and linear solves via optional arbitrary-precision arithmetic (det_exact, solve_exact, strict/rounded f64 conversions)
  • ✅ No runtime dependencies by default (optional features may add deps)
  • ✅ Inline, stack-backed storage for core types; optional arbitrary-precision exact values allocate as required
  • unsafe forbidden

See CHANGELOG.md for release history and docs/roadmap.md for current release planning.

§🚫 Anti-goals

  • Bare-metal performance: see blas-src, lapack-src, or openblas-src
  • Broad general-purpose linear algebra: use nalgebra
  • Large matrices/dimensions with parallelism: use faer
  • Alternate floating-point scalar families: la-stack supports f64 and optional exact arithmetic, not f32 / f16 APIs

§✅ Use this crate when

  • Your matrices and vectors have small, fixed dimensions known at compile time
  • Stack allocation and Copy value semantics fit your data flow
  • You want explicit LU / LDLT / determinant APIs rather than a broad algebra toolkit
  • You need exact determinants, exact determinant signs, or exact linear solves for fixed-size systems
  • Robust predicates matter for geometry-style workloads near degeneracy
  • You prefer a default build with no runtime dependencies

§🔢 Scalar types

The scalar model is intentionally limited to f64 for floating-point work and exact rationals behind the optional "exact" feature. This matches the crate’s focus on small, robustness-sensitive numerical and computational geometry workloads. When f64 precision is insufficient (e.g. near-degenerate geometric configurations), the optional "exact" feature provides arbitrary-precision arithmetic via BigRational (see below).

Lower-precision f32 / f16 throughput-oriented workloads are outside the crate’s scope; they usually indicate large-matrix or accelerator-oriented use cases better served by broader linear-algebra libraries.

§🚀 Quickstart

Add this to your Cargo.toml:

[dependencies]
la-stack = "0.4.4"

§Feature flags

  • default: no runtime dependencies
  • exact: BigRational exact determinant and solve APIs
  • bench: repository-development gate used only by benchmark targets and benchmark-input tests; application crates should not enable it

§LU solve

Solve a 5×5 system via LU:

use la_stack::prelude::*;

fn main() -> Result<(), LaError> {
    // This system requires pivoting (a[0][0] = 0), so it's a good LU demo.
    // A = J - I: zeros on diagonal, ones elsewhere.
    let a = Matrix::<5>::try_from_rows([
        [0.0, 1.0, 1.0, 1.0, 1.0],
        [1.0, 0.0, 1.0, 1.0, 1.0],
        [1.0, 1.0, 0.0, 1.0, 1.0],
        [1.0, 1.0, 1.0, 0.0, 1.0],
        [1.0, 1.0, 1.0, 1.0, 0.0],
    ])?;

    let b = Vector::<5>::try_new([14.0, 13.0, 12.0, 11.0, 10.0])?;

    let lu = a.lu(DEFAULT_SINGULAR_TOL)?;
    let x = lu.solve(b)?.into_array();

    // Floating-point rounding is expected; compare with a tolerance.
    let expected = [1.0, 2.0, 3.0, 4.0, 5.0];
    for (x_i, e_i) in x.iter().zip(expected.iter()) {
        assert!((*x_i - *e_i).abs() <= 1e-12);
    }

    Ok(())
}

§LDLT determinant

Compute a determinant for a symmetric positive-definite matrix via LDLT (no pivoting).

For these matrices, LDLᵀ is a square-root-free Cholesky form. Multiplying each column of L by the square root of the corresponding diagonal entry yields a Cholesky factor:

use la_stack::prelude::*;

fn main() -> Result<(), LaError> {
    // This matrix is symmetric positive-definite (A = L*L^T) so LDLT works without pivoting.
    let a = Matrix::<5>::try_from_rows([
        [1.0, 1.0, 0.0, 0.0, 0.0],
        [1.0, 2.0, 1.0, 0.0, 0.0],
        [0.0, 1.0, 2.0, 1.0, 0.0],
        [0.0, 0.0, 1.0, 2.0, 1.0],
        [0.0, 0.0, 0.0, 1.0, 2.0],
    ])?;

    let ldlt = match a.ldlt(DEFAULT_SINGULAR_TOL) {
        Ok(ldlt) => ldlt,
        Err(err @ LaError::Asymmetric {
            row,
            col,
            upper,
            lower,
            allowed_abs_diff,
            ..
        }) => {
            eprintln!(
                "LDLT mismatch at ({row}, {col}): {upper} vs {lower} (allowed {allowed_abs_diff})"
            );
            return Err(err);
        }
        Err(err) => return Err(err),
    };

    let det = ldlt.det()?;
    assert!((det - 1.0).abs() <= 1e-12);

    Ok(())
}

⚠️ LDLT invariant: The input matrix must be exactly symmetric: every mirrored pair must compare equal (+0.0 == -0.0 is accepted). Asymmetric inputs passed to Matrix::ldlt return a typed LaError::Asymmetric containing both observed values and the required allowed difference of zero. The tolerance-based Matrix::first_asymmetry and Matrix::is_symmetric methods remain useful diagnostics, but do not prove the exact precondition required by LDLT. Use lu() when exact symmetry or positive definiteness is not guaranteed. A negative LDLT diagonal or a zero diagonal with nonzero remaining coupling returns LaError::NotPositiveSemidefinite with a typed PositiveSemidefiniteViolation. An uncoupled zero or positive pivot at or below the caller’s tolerance returns LaError::Singular with a numerical SingularityReason. Because these pivots are computed in binary64, success is not an exact positive-definiteness certificate for the stored matrix.

§⚡ Compile-time determinants (D ≤ 4)

det_direct() is a const fn providing closed-form determinants for D=0–4, using fused multiply-add where applicable. It returns Ok(Some(det)) for those dimensions and Ok(None) for D ≥ 5. Matrix::<0>::zero().det_direct() returns Ok(Some(1.0)) (the empty-product convention). For D=1–4, direct formulas bypass LU factorization entirely. This enables compile-time evaluation when inputs are known:

use la_stack::prelude::*;

// Evaluated entirely at compile time — no runtime cost.
const DET: Result<Option<f64>, LaError> = match Matrix::<4>::try_from_rows([
    [2.0, 0.0, 0.0, 0.0],
    [0.0, 3.0, 0.0, 0.0],
    [0.0, 0.0, 5.0, 0.0],
    [0.0, 0.0, 0.0, 7.0],
]) {
    Ok(matrix) => matrix.det_direct(),
    Err(err) => Err(err),
};

fn main() -> Result<(), LaError> {
    assert_eq!(DET?, Some(210.0));
    Ok(())
}

The public det() method automatically dispatches through the closed-form path for D ≤ 4 and falls back to zero-tolerance LU for D ≥ 5. Tiny nonzero determinants are not flattened by a configured pivot tolerance. The LU fallback returns LaError::Singular when floating-point elimination cannot produce a non-zero pivot; it does not misreport that numerical failure as an exact zero. Use lu() directly when you need a different tolerance policy, and use the exact determinant APIs when exact singularity classification matters.

§🔬 Exact arithmetic ("exact" feature)

The default build has zero runtime dependencies. Enable the optional exact Cargo feature to add exact arithmetic methods using arbitrary-precision rationals (this pulls in num-bigint, num-rational, and num-traits for BigRational):

[dependencies]
la-stack = { version = "0.4.4", features = ["exact"] }

These routines are exact with respect to the finite binary64 values stored in Matrix and Vector. They treat each stored value as the exact rational number represented by its bits, so the exact determinant or solve stage introduces no further roundoff. They cannot recover information already lost when source values were rounded to f64 before construction.

Determinants:

  • det_exact() — returns the exact determinant as a BigRational
  • det_exact_f64() — returns the exact determinant as f64 only when it is exactly representable (or LaError::Unrepresentable otherwise)
  • det_exact_rounded_f64() — returns the exact determinant rounded to a finite f64 using IEEE 754 round-to-nearest, ties-to-even
  • det_sign_exact() — infallibly returns the provably correct DeterminantSign variant (Negative, Zero, or Positive)

Linear system solve:

  • solve_exact(b) — solves Ax = b exactly, returning [BigRational; D]
  • solve_exact_f64(b) — solves Ax = b exactly, returning Vector<D> only when every component is exactly representable as f64
  • solve_exact_rounded_f64(b) — solves Ax = b exactly, returning each component rounded to finite f64 using IEEE 754 round-to-nearest, ties-to-even
  • ExactF64Conversion — converts an existing exact determinant or solution under the strict or rounded contract without repeating exact elimination

For exact-to-f64 output, strict conversions use UnrepresentableReason::RequiresRounding when explicit rounding can produce a finite value and UnrepresentableReason::NotFinite otherwise. Rounded conversions opt into nearest-even rounding but still report NotFinite when no finite f64 exists.

use la_stack::prelude::*;

fn main() -> Result<(), LaError> {
    // Exact determinant
    let m = Matrix::<3>::try_from_rows([
        [1.0, 2.0, 3.0],
        [4.0, 5.0, 6.0],
        [7.0, 8.0, 9.0],
    ])?;
    assert_eq!(m.det_sign_exact(), DeterminantSign::Zero); // exactly singular

    let det = m.det_exact()?;
    assert_eq!(det, BigRational::from_integer(0.into())); // exact zero
    let det_f64 = det.try_to_f64()?;
    assert_eq!(det_f64, 0.0);

    // If strict exact-to-f64 conversion would require rounding, opt in
    // explicitly with the rounded API.
    let inexact = Matrix::<2>::try_from_rows([
        [1.0 + f64::EPSILON, 0.0],
        [0.0, 1.0 - f64::EPSILON],
    ])?;
    let exact_det = inexact.det_exact()?;
    let rounded_det = match exact_det.try_to_f64() {
        Ok(det) => det,
        Err(err) if err.requires_rounding() => exact_det.to_rounded_f64()?,
        Err(err) => return Err(err),
    };
    assert_eq!(rounded_det.to_bits(), 1.0f64.to_bits());

    // If the exact determinant cannot fit in f64, keep the BigRational value.
    let big = f64::MAX / 2.0;
    let huge = Matrix::<3>::try_from_rows([
        [0.0, 0.0, 1.0],
        [big, 0.0, 1.0],
        [0.0, big, 1.0],
    ])?;
    let huge_det = huge.det_exact()?;
    assert_eq!(
        huge_det
            .try_to_f64()
            .err()
            .and_then(|err| err.unrepresentable_reason()),
        Some(UnrepresentableReason::NotFinite)
    );
    println!("exact determinant = {huge_det}");

    // Exact linear system solve
    let a = Matrix::<2>::try_from_rows([[1.0, 2.0], [3.0, 4.0]])?;
    let b = Vector::<2>::try_new([5.0, 11.0])?;
    let exact_x = a.solve_exact(b)?;
    let x = exact_x.try_to_f64()?.into_array();
    assert!((x[0] - 1.0).abs() <= f64::EPSILON);
    assert!((x[1] - 2.0).abs() <= f64::EPSILON);

    Ok(())
}

With the exact feature enabled, DeterminantSign, ExactF64Conversion, BigInt, and BigRational are re-exported from the crate root and prelude, alongside the most commonly needed num-traits items (FromPrimitive, ToPrimitive, Signed). This lets consumers construct exact values (BigRational::from_f64, from_i64), query sign (is_positive / is_negative), and convert back to f64 (try_to_f64, to_rounded_f64, or the raw to_f64) with a single use la_stack::prelude::*; — no need to add num-bigint, num-rational, or num-traits to their own Cargo.toml. Use DeterminantSign::as_i8() only when numeric −1/0/+1 interoperability is required.

For det_sign_exact(), D ≤ 4 matrices first use a fast f64 filter (error-bounded det_direct()) when its rounded intermediates stay in the normal range or are exact structural zeros. An inconclusive filter falls back to the same direct determinant expansion in BigInt. D ≥ 5 skips the closed-form filter and uses fraction-free Bareiss elimination in BigInt. Because Matrix stores only finite entries, arithmetic range failures in the filter are inconclusive rather than errors and the exact fallback is total.

§🛡️ Adaptive determinant filtering (D ≤ 4)

det_direct_with_errbound() returns a closed-form determinant together with the conservative absolute error bound used by the fast filter, computed from one call that evaluates the determinant once and computes its matching bound. It returns None when a D ≤ 4 computation may be affected by gradual underflow, as well as for unsupported D ≥ 5 dimensions. This method does NOT require the exact feature — it uses pure f64 arithmetic and is available by default. Use det_errbound() when only the bound is needed. The paired API enables custom adaptive-precision logic for geometric predicates:

use la_stack::prelude::*;

fn adaptive_det_sign<const D: usize>(
    matrix: &Matrix<D>,
) -> DeterminantSign {
    if let Ok(Some(estimate)) = matrix.det_direct_with_errbound() {
        if estimate.determinant().abs() > estimate.absolute_error_bound() {
            return if estimate.determinant() > 0.0 {
                DeterminantSign::Positive
            } else {
                DeterminantSign::Negative
            };
        }
    }

    matrix.det_sign_exact()
}

fn main() -> Result<(), LaError> {
    let identity = Matrix::<3>::identity();
    assert_eq!(
        adaptive_det_sign(&identity),
        DeterminantSign::Positive
    );

    // A zero determinant cannot pass the f64 sign filter, so this exercises
    // the exact fallback.
    let singular = Matrix::<3>::try_from_rows([
        [1.0, 2.0, 3.0],
        [4.0, 5.0, 6.0],
        [7.0, 8.0, 9.0],
    ])?;
    assert_eq!(adaptive_det_sign(&singular), DeterminantSign::Zero);

    // The f64 filter overflows for this finite matrix, but the exact fallback
    // still resolves its positive determinant sign.
    let big = f64::MAX / 2.0;
    let overflowing = Matrix::<3>::try_from_rows([
        [0.0, 0.0, 1.0],
        [big, 0.0, 1.0],
        [0.0, big, 1.0],
    ])?;
    assert_eq!(
        adaptive_det_sign(&overflowing),
        DeterminantSign::Positive
    );

    Ok(())
}

The error coefficients (ERR_COEFF_2, ERR_COEFF_3, ERR_COEFF_4) are conservative, dimension-specific constants, not caller-tunable tolerances. The mathematical basis documents the bound and states its range preconditions. The constants are explicit crate-root exports for advanced users who want to compose the same bound: use la_stack::{ERR_COEFF_2, ERR_COEFF_3, ERR_COEFF_4};. They intentionally stay out of the common prelude.

§🧩 API at a glance

TypeStoragePurposeKey methods
Vector<D>[f64; D]Finite fixed-length vector for input and computationtry_new, as_array, into_array, dot, norm2_sq
Matrix<D>[[f64; D]; D]Finite square matrix for input and computationSee below
DeterminantWithErrorBoundOpaque validated pairPaired direct determinant and certified absolute bounddeterminant, absolute_error_bound
Lu<D>Inline factors + permutationFactorization for solves/detsolve, det
Ldlt<D>Inline factorsNo-pivot SPD factorization for solves/detsolve, det
Tolerancefinite non-negative f64Validated numerical thresholdtry_new, get
LaErrortyped variants and reasonsStructured, actionable failure reportingSee error semantics below
DeterminantSign¹enumExact determinant signas_i8

Storage shown above reflects the intentional f64 scalar model.

For a runtime dimension from 0 through MAX_STACK_MATRIX_DISPATCH_DIM (7), try_with_stack_matrix! dispatches to a concrete Matrix<N> while preserving inline stack storage. Larger dimensions return LaError::UnsupportedDimension; the macro does not introduce a dynamically sized matrix representation.

Matrix<D> key methods: as_rows, into_rows, lu, ldlt, det, det_direct, det_direct_with_errbound, det_errbound, det_exact¹, det_exact_f64¹, det_exact_rounded_f64¹, det_sign_exact¹, solve_exact¹, solve_exact_f64¹, solve_exact_rounded_f64¹. Matrix and vector constructors validate non-finite inputs at public API boundaries. After construction, Matrix<D> and Vector<D> carry that finite-storage invariant directly, so factorization kernels do not repeat an O(D²) input scan. Computed factor matrices are still checked before they become observable results.

Matrix::as_rows and Vector::as_array borrow their validated backing arrays; Matrix::into_rows and Vector::into_array consume the value and return the owned fixed-size arrays.

Matrix::get(row, col) returns None for out-of-bounds coordinates; Matrix::try_get instead returns a structured LaError preserving those coordinates. The single fallible Matrix::set validates both coordinates and finiteness before mutating the matrix.

LaError and its reason/location enums are non-exhaustive. Numerical singularity records the FactorizationKind, observed pivot magnitude, and tolerance, while exact-arithmetic singularity is identified separately. LaError::NonFinite retains the crate-wide non-finite contract but uses NonFiniteOrigin, NonFiniteLocation, and ArithmeticOperation to distinguish invalid inputs from computed overflow. InvalidToleranceReason distinguishes negative from non-finite tolerances, and PositiveSemidefiniteViolation distinguishes negative LDLT pivots from a zero pivot with nonzero coupling. Match these public enums with a wildcard and use .. for struct-style variants so future error context can be added without breaking callers.

¹ Requires features = ["exact"].

§📊 Benchmarks (vs nalgebra/faer)

LU solve (factor + solve): median time vs dimension

Raw data: docs/assets/bench/vs_linalg_lu_solve_median.csv Measurement provenance: docs/assets/bench/vs_linalg_lu_solve_median.provenance.json

Representative benchmark: lu_solve factors the matrix and solves one right-hand side. Median time is lower-is-better, and the “la-stack vs nalgebra/faer” columns show the % time reduction relative to each baseline (positive means the recorded la-stack median is lower). These are descriptive point-estimate ratios, not statistical significance claims or an aggregate score across operations.

Timings count only when the implementation preserves the documented correctness guarantees and invariants. Performance claims require comparable before-and-after evidence using the same inputs, configuration, and environment. This snapshot records the measured source state, CPU, operating system, Rust toolchain, dependency lock and harness digests, Criterion command, and correctness-gate result in the adjacent JSON sidecar. The publication workflow requires complete canonical-dimension coverage and regenerates the CSV, SVG, README table, and provenance together.

For the full per-kernel comparison methodology, input construction, and release-comparison workflow details, see docs/BENCHMARKING.md. For the current release-to-release performance snapshot, see docs/PERFORMANCE.md.

Dla-stack median (ns)nalgebra median (ns)faer median (ns)reduction vs nalgebra (point est.)reduction vs faer (point est.)
22.0514.609149.537+55.5%+98.6%
310.03223.094185.935+56.6%+94.6%
421.80653.542218.921+59.3%+90.0%
543.78770.437282.262+37.8%+84.5%
8128.337167.505414.791+23.4%+69.1%
16672.680581.273875.411-15.7%+23.2%
322,873.7202,470.4352,861.209-16.3%-0.4%
6418,165.36915,021.73712,225.703-20.9%-48.6%

§📋 Examples

The examples/ directory contains small, runnable programs:

  • solve_5x5 — solve a 5×5 system via LU with partial pivoting
  • det_5x5 — determinant of a 5×5 matrix via LU
  • ldlt_solve_3x3 — solve a 3×3 symmetric positive definite system via LDLT
  • const_det_4x4 — compile-time 4×4 determinant via det_direct()
  • exact_det_3x3 — exact determinant value of a near-singular 3×3 matrix (requires exact feature)
  • exact_sign_3x3 — exact determinant sign of a near-singular 3×3 matrix (requires exact feature)
  • exact_solve_3x3 — exact solve of a near-singular 3×3 system vs f64 LU (requires exact feature)
just examples
# or individually:
cargo run --example solve_5x5
cargo run --example det_5x5
cargo run --example ldlt_solve_3x3
cargo run --example const_det_4x4
cargo run --features exact --example exact_det_3x3
cargo run --features exact --example exact_sign_3x3
cargo run --features exact --example exact_solve_3x3

§🤝 Contributing

A short contributor workflow:

Install Rust 1.97.0 through rustup, Git, Python 3.14, uv 0.11.28, and jq. Then install the pinned just release from its locked dependency graph:

cargo install --locked just --version 1.56.0
just setup        # install/verify dev tools + sync Python deps
just check        # lint/validate (non-mutating)
just fix          # apply auto-fixes (mutating)
just ci           # lint + tests + examples + bench compile

The repository uses cargo-nextest for runnable Rust tests, cargo-machete for unused-dependency checks, rumdl for Markdown, dprint plus yamllint for YAML/CFF, taplo for TOML, and typos for spelling. Python 3.14 support tooling is locked with uv and checked by Ruff, Ty, and Semgrep. GitHub Actions references are SHA-pinned, restricted to an explicit allowlist, and kept with readable version comments for review.

CI runs just ci on Ubuntu, macOS, and Windows to keep platform coverage aligned with the local comprehensive validation path.

For coverage commands and report locations, see docs/COVERAGE.md. For the full contributor workflow, see CONTRIBUTING.md.

§📝 Citation

If you use this library in academic work, please cite it using CITATION.cff (or GitHub’s “Cite this repository” feature). Tagged releases are archived on Zenodo under the all-versions concept DOI.

§📚 References

For canonical references to the algorithms used by this crate, see REFERENCES.md.

§🤖 AI Agents

AI coding assistants should read AGENTS.md before proposing or applying changes. See CONTRIBUTING.md for the repository’s AI-assisted development note.

§📄 License

BSD 3-Clause License. See LICENSE.

Modules§

prelude
Common imports for ergonomic usage.

Macros§

try_with_stack_matrix
Fallibly dispatch a runtime dimension to a concrete stack-allocated matrix.

Structs§

BigInt
A big signed integer type.
DeterminantWithErrorBound
A closed-form determinant and its certified absolute error bound.
Ldlt
LDLT factorization (A = L D Lᵀ) for exactly symmetric positive-definite matrices.
Lu
LU decomposition (PA = LU) with partial pivoting.
Matrix
Finite fixed-size square matrix D×D, stored inline.
Tolerance
Finite, non-negative tolerance used by numerical predicates and factorizations.
Vector
Finite fixed-size vector of length D, stored inline.

Enums§

ArithmeticOperation
Floating-point operation that produced a non-finite intermediate or result.
DeterminantSign
The exact sign of a determinant.
FactorizationKind
Factorization whose pivot policy rejected a matrix as numerically singular.
InvalidToleranceReason
Reason a raw tolerance cannot become a crate::Tolerance.
LaError
Linear algebra errors.
NonFiniteLocation
Location at which a non-finite value was observed.
NonFiniteOrigin
Provenance of a non-finite value.
PositiveSemidefiniteViolation
Computed LDLT condition that violates the no-pivot positive-semidefinite factorization requirements.
SingularityReason
Mathematical or numerical reason a matrix was classified as singular.
UnrepresentableReason
Reason an exact result cannot satisfy an exact-to-f64 conversion contract.

Constants§

DEFAULT_SINGULAR_TOL
Default absolute threshold used for singularity/degeneracy detection.
ERR_COEFF_2
Absolute error coefficient for Matrix::<2>::det_direct.
ERR_COEFF_3
Absolute error coefficient for Matrix::<3>::det_direct.
ERR_COEFF_4
Absolute error coefficient for Matrix::<4>::det_direct.
MAX_STACK_MATRIX_DISPATCH_DIM
Largest dimension supported by try_with_stack_matrix!.

Traits§

ExactF64Conversion
Convert an already-computed exact result to finite binary64 output.
FromPrimitive
A generic trait for converting a number to a value.
Signed
Useful functions for signed numbers (i.e. numbers that can be negative).
ToPrimitive
A generic trait for converting a value to a number.

Type Aliases§

BigRational
Alias for arbitrary precision rationals.