pub struct RationalMatrix<const D: usize> { /* private fields */ }exact only.Expand description
Exact rational square matrix with compile-time dimension D.
Construction validates that every denominator is non-zero and canonicalizes
every entry to lowest terms with a positive denominator. The private storage
then carries those invariants, so determinant and solve methods do not repeat
input validation. Unlike crate::Matrix, entries are already exact rational
values rather than finite binary64 values interpreted exactly.
Direct field construction is intentionally unavailable:
use la_stack::{BigRational, RationalMatrix};
let _ = RationalMatrix::<1> {
rows: [[BigRational::from_integer(1.into())]],
};Implementations§
Source§impl<const D: usize> RationalMatrix<D>
impl<const D: usize> RationalMatrix<D>
Sourcepub fn try_from_rows(rows: [[BigRational; D]; D]) -> Result<Self, LaError>
pub fn try_from_rows(rows: [[BigRational; D]; D]) -> Result<Self, LaError>
Try to create an exact matrix from row-major rational storage.
Raw, non-reduced BigRational::new_raw values and negative
denominators are accepted, interpreted as their mathematical quotient,
and stored canonically. A raw zero denominator is not a rational value
and is rejected at this construction boundary.
§Examples
use la_stack::prelude::*;
let matrix = RationalMatrix::<2>::try_from_rows([
[
BigRational::new(1.into(), 3.into()),
BigRational::from_integer(2.into()),
],
[
BigRational::from_integer(1.into()),
BigRational::new(5.into(), 2.into()),
],
])?;
assert_eq!(
matrix.det(),
BigRational::new((-7).into(), 6.into())
);§Errors
Returns LaError::NonFinite at the first matrix cell whose raw
rational denominator is zero.
Sourcepub fn try_from_fn(
make_entry: impl FnMut(usize, usize) -> BigRational,
) -> Result<Self, LaError>
pub fn try_from_fn( make_entry: impl FnMut(usize, usize) -> BigRational, ) -> Result<Self, LaError>
Try to create an exact matrix by evaluating a function at every cell.
The function is evaluated once per cell in row-major order.
§Examples
use la_stack::prelude::*;
let diagonal = RationalMatrix::<3>::try_from_fn(|row, col| {
BigRational::from_integer(u8::from(row == col).into())
})?;
assert_eq!(diagonal.det_sign(), DeterminantSign::Positive);§Errors
Returns LaError::NonFinite at the first generated cell whose raw
rational denominator is zero.
Sourcepub const fn as_rows(&self) -> &[[BigRational; D]; D]
pub const fn as_rows(&self) -> &[[BigRational; D]; D]
Borrow the row-major exact storage.
Sourcepub fn into_rows(self) -> [[BigRational; D]; D]
pub fn into_rows(self) -> [[BigRational; D]; D]
Consume the matrix and return its row-major exact storage.
Sourcepub fn get(&self, row: usize, col: usize) -> Option<&BigRational>
pub fn get(&self, row: usize, col: usize) -> Option<&BigRational>
Borrow one entry, returning None for an out-of-bounds index.
Sourcepub fn set(
&mut self,
row: usize,
col: usize,
value: BigRational,
) -> Result<(), LaError>
pub fn set( &mut self, row: usize, col: usize, value: BigRational, ) -> Result<(), LaError>
Replace one exact entry while preserving the canonical non-zero- denominator invariant.
As with try_from_rows, non-reduced values and
negative denominators are accepted and canonicalized. Rejected indices
or denominators leave the matrix unchanged.
§Examples
use core::assert_matches;
use la_stack::prelude::*;
let mut matrix = RationalMatrix::<2>::zero();
matrix.set(0, 1, BigRational::new_raw((-2).into(), (-4).into()))?;
let half = BigRational::new(1.into(), 2.into());
assert_eq!(matrix.get(0, 1), Some(&half));
let before = matrix.clone();
assert_matches!(
matrix.set(0, 1, BigRational::new_raw(1.into(), 0.into())),
Err(LaError::NonFinite {
location: NonFiniteLocation::MatrixCell { row: 0, col: 1, .. },
origin: NonFiniteOrigin::Input,
..
})
);
assert_eq!(matrix, before);§Errors
Returns LaError::IndexOutOfBounds when (row, col) lies outside the
matrix, or LaError::NonFinite when value has a raw zero
denominator.
Sourcepub fn det_sign(&self) -> DeterminantSign
pub fn det_sign(&self) -> DeterminantSign
Return the provably exact determinant sign.
This path clears denominators and reads the sign of the resulting
integer determinant. It does not construct a rational determinant.
For D=0, the empty-product determinant has positive sign.
Use det when the determinant value is also needed.
§Examples
use la_stack::prelude::*;
let mut matrix = RationalMatrix::<2>::zero();
assert_eq!(matrix.det_sign(), DeterminantSign::Zero);
matrix.set(0, 1, BigRational::new(1.into(), 3.into()))?;
matrix.set(1, 0, BigRational::new(1.into(), 2.into()))?;
// The exact determinant is -1/6, so its sign is negative.
assert_eq!(matrix.det_sign(), DeterminantSign::Negative);Sourcepub fn det(&self) -> BigRational
pub fn det(&self) -> BigRational
Return the exact determinant.
Denominators are cleared independently per row. If row i uses
positive scale sᵢ, the integer determinant is divided by ∏ᵢ sᵢ.
For D=0, this returns the empty-product determinant 1.
Use det_sign when only the sign is needed, or
ExactF64Conversion to convert this result
under an explicit strict or rounded binary64 contract.
§Examples
use la_stack::prelude::*;
let mut matrix = RationalMatrix::<2>::zero();
matrix.set(0, 0, BigRational::new(1.into(), 3.into()))?;
matrix.set(1, 1, BigRational::from_integer(2.into()))?;
let determinant = matrix.det();
assert_eq!(determinant, BigRational::new(2.into(), 3.into()));
// Conversion rounds only after the exact determinant has been computed.
assert_eq!(determinant.to_rounded_f64()?, 2.0 / 3.0);Sourcepub fn solve(
&self,
rhs: &RationalVector<D>,
) -> Result<RationalVector<D>, LaError>
pub fn solve( &self, rhs: &RationalVector<D>, ) -> Result<RationalVector<D>, LaError>
Solve A x = b exactly.
Each augmented row is multiplied by one positive common denominator,
then fraction-free Bareiss forward elimination runs in BigInt. Only
the O(D²) back-substitution phase constructs BigRational values.
For D=0, the empty matrix and vector have the unique empty solution.
§Examples
use la_stack::prelude::*;
let zero = BigRational::from_integer(0.into());
let one = BigRational::from_integer(1.into());
let matrix = RationalMatrix::<2>::try_from_rows([
[BigRational::new(1.into(), 2.into()), zero.clone()],
[zero, BigRational::new(1.into(), 3.into())],
])?;
let rhs = RationalVector::try_new([one.clone(), one])?;
let solution = matrix.solve(&rhs)?.try_to_f64()?.into_array();
assert_eq!(solution, [2.0, 3.0]);§Errors
Returns LaError::Singular with exact-singularity metadata when a
pivot column contains no non-zero entry.
Trait Implementations§
Source§impl<const D: usize> Clone for RationalMatrix<D>
impl<const D: usize> Clone for RationalMatrix<D>
Source§fn clone(&self) -> RationalMatrix<D>
fn clone(&self) -> RationalMatrix<D>
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more