pub struct RrLU<T: Scalar> { /* private fields */ }Expand description
Rank-Revealing LU decomposition.
Represents a matrix A as P_row * A * P_col = L * U, where P_row
and P_col are permutation matrices, L is lower-triangular, and U
is upper-triangular. One of L or U has unit diagonal, controlled by
the left_orthogonal option.
§Examples
use tensor4all_tcicore::{from_vec2d, matrixlu::rrlu, matrix::mat_mul};
let m = from_vec2d(vec![
vec![1.0_f64, 2.0, 3.0],
vec![4.0, 5.0, 6.0],
vec![7.0, 8.0, 10.0],
]);
let lu = rrlu(&m, None).unwrap();
assert_eq!(lu.npivots(), 3);
// Verify L * U reconstructs the permuted matrix
let l = lu.left(false);
let u = lu.right(false);
let reconstructed = mat_mul(&l, &u);
// Check reconstruction matches the permuted matrix
for i in 0..3 {
for j in 0..3 {
let orig_row = lu.row_permutation()[i];
let orig_col = lu.col_permutation()[j];
assert!((reconstructed[[i, j]] - m[[orig_row, orig_col]]).abs() < 1e-10);
}
}Implementations§
Source§impl<T: Scalar> RrLU<T>
impl<T: Scalar> RrLU<T>
Sourcepub fn new(nr: usize, nc: usize, left_orthogonal: bool) -> Self
pub fn new(nr: usize, nc: usize, left_orthogonal: bool) -> Self
Create an empty rrLU for a matrix of given size.
Used internally. Most users should call rrlu or rrlu_inplace
instead.
§Examples
use tensor4all_tcicore::RrLU;
let lu = RrLU::<f64>::new(3, 4, true);
assert_eq!(lu.nrows(), 3);
assert_eq!(lu.ncols(), 4);
assert_eq!(lu.npivots(), 0);
assert!(lu.is_left_orthogonal());Sourcepub fn nrows(&self) -> usize
pub fn nrows(&self) -> usize
Number of rows
§Examples
use tensor4all_tcicore::{from_vec2d, matrixlu::rrlu};
let m = from_vec2d(vec![vec![1.0_f64, 2.0], vec![3.0, 4.0], vec![5.0, 6.0]]);
let lu = rrlu(&m, None).unwrap();
assert_eq!(lu.nrows(), 3);Sourcepub fn ncols(&self) -> usize
pub fn ncols(&self) -> usize
Number of columns
§Examples
use tensor4all_tcicore::{from_vec2d, matrixlu::rrlu};
let m = from_vec2d(vec![vec![1.0_f64, 2.0, 3.0], vec![4.0, 5.0, 6.0]]);
let lu = rrlu(&m, None).unwrap();
assert_eq!(lu.ncols(), 3);Sourcepub fn npivots(&self) -> usize
pub fn npivots(&self) -> usize
Number of pivots
§Examples
use tensor4all_tcicore::{from_vec2d, matrixlu::rrlu};
let m = from_vec2d(vec![vec![1.0_f64, 2.0], vec![3.0, 4.0]]);
let lu = rrlu(&m, None).unwrap();
assert_eq!(lu.npivots(), 2);Sourcepub fn row_permutation(&self) -> &[usize]
pub fn row_permutation(&self) -> &[usize]
Row permutation
§Examples
use tensor4all_tcicore::{from_vec2d, matrixlu::rrlu};
let m = from_vec2d(vec![vec![1.0_f64, 2.0], vec![3.0, 4.0]]);
let lu = rrlu(&m, None).unwrap();
let perm = lu.row_permutation();
assert_eq!(perm.len(), 2);
// Permutation is a rearrangement of 0..nrows
let mut sorted = perm.to_vec();
sorted.sort();
assert_eq!(sorted, vec![0, 1]);Sourcepub fn col_permutation(&self) -> &[usize]
pub fn col_permutation(&self) -> &[usize]
Column permutation
§Examples
use tensor4all_tcicore::{from_vec2d, matrixlu::rrlu};
let m = from_vec2d(vec![vec![1.0_f64, 2.0], vec![3.0, 4.0]]);
let lu = rrlu(&m, None).unwrap();
let perm = lu.col_permutation();
assert_eq!(perm.len(), 2);
let mut sorted = perm.to_vec();
sorted.sort();
assert_eq!(sorted, vec![0, 1]);Sourcepub fn row_indices(&self) -> Vec<usize>
pub fn row_indices(&self) -> Vec<usize>
Get row indices (selected pivots)
§Examples
use tensor4all_tcicore::{from_vec2d, matrixlu::rrlu, RrLUOptions};
let m = from_vec2d(vec![vec![1.0_f64, 2.0], vec![3.0, 4.0]]);
let lu = rrlu(&m, Some(RrLUOptions { max_rank: 1, ..Default::default() })).unwrap();
let rows = lu.row_indices();
assert_eq!(rows.len(), 1);
assert!(rows[0] < 2);Sourcepub fn col_indices(&self) -> Vec<usize>
pub fn col_indices(&self) -> Vec<usize>
Get column indices (selected pivots)
§Examples
use tensor4all_tcicore::{from_vec2d, matrixlu::rrlu, RrLUOptions};
let m = from_vec2d(vec![vec![1.0_f64, 2.0], vec![3.0, 4.0]]);
let lu = rrlu(&m, Some(RrLUOptions { max_rank: 1, ..Default::default() })).unwrap();
let cols = lu.col_indices();
assert_eq!(cols.len(), 1);
assert!(cols[0] < 2);Sourcepub fn left(&self, permute: bool) -> Matrix<T>
pub fn left(&self, permute: bool) -> Matrix<T>
Get left matrix (optionally permuted)
§Examples
use tensor4all_tcicore::{from_vec2d, matrixlu::rrlu, matrix::mat_mul};
let m = from_vec2d(vec![vec![1.0_f64, 2.0], vec![3.0, 4.0]]);
let lu = rrlu(&m, None).unwrap();
// Unpermuted: L * U reconstructs the row/col-permuted matrix
let l = lu.left(false);
let u = lu.right(false);
let prod = mat_mul(&l, &u);
for i in 0..2 {
for j in 0..2 {
let ri = lu.row_permutation()[i];
let cj = lu.col_permutation()[j];
assert!((prod[[i, j]] - m[[ri, cj]]).abs() < 1e-10);
}
}Sourcepub fn right(&self, permute: bool) -> Matrix<T>
pub fn right(&self, permute: bool) -> Matrix<T>
Get right matrix (optionally permuted)
§Examples
use tensor4all_tcicore::{from_vec2d, matrixlu::rrlu, matrix::mat_mul};
let m = from_vec2d(vec![vec![1.0_f64, 2.0], vec![3.0, 4.0]]);
let lu = rrlu(&m, None).unwrap();
let l = lu.left(false);
let u = lu.right(false);
assert_eq!(u.nrows(), lu.npivots());
assert_eq!(u.ncols(), lu.ncols());
// L * U reconstructs the permuted matrix
let prod = mat_mul(&l, &u);
assert!((prod[[0, 0]] - m[[lu.row_permutation()[0], lu.col_permutation()[0]]]).abs() < 1e-10);Sourcepub fn diag(&self) -> Vec<T>
pub fn diag(&self) -> Vec<T>
Get diagonal elements
§Examples
use tensor4all_tcicore::{from_vec2d, matrixlu::rrlu};
let m = from_vec2d(vec![vec![1.0_f64, 2.0], vec![3.0, 4.0]]);
let lu = rrlu(&m, None).unwrap();
let d = lu.diag();
assert_eq!(d.len(), lu.npivots());
// Diagonal elements are non-zero for full-rank matrices
for &val in &d {
assert!(val.abs() > 1e-14);
}Sourcepub fn pivot_errors(&self) -> Vec<f64>
pub fn pivot_errors(&self) -> Vec<f64>
Get pivot errors
§Examples
use tensor4all_tcicore::{from_vec2d, matrixlu::rrlu};
let m = from_vec2d(vec![vec![1.0_f64, 2.0], vec![3.0, 4.0]]);
let lu = rrlu(&m, None).unwrap();
let errs = lu.pivot_errors();
// One entry per pivot plus the final residual
assert_eq!(errs.len(), lu.npivots() + 1);
// Errors are non-negative
for &e in &errs {
assert!(e >= 0.0);
}Sourcepub fn last_pivot_error(&self) -> f64
pub fn last_pivot_error(&self) -> f64
Get last pivot error
§Examples
use tensor4all_tcicore::{from_vec2d, matrixlu::rrlu};
let m = from_vec2d(vec![vec![1.0_f64, 2.0], vec![3.0, 4.0]]);
let lu = rrlu(&m, None).unwrap();
// Full-rank decomposition has zero residual
assert_eq!(lu.last_pivot_error(), 0.0);Sourcepub fn transpose(&self) -> RrLU<T>
pub fn transpose(&self) -> RrLU<T>
Transpose the decomposition
§Examples
use tensor4all_tcicore::{from_vec2d, matrixlu::rrlu};
let m = from_vec2d(vec![vec![1.0_f64, 2.0], vec![3.0, 4.0]]);
let lu = rrlu(&m, None).unwrap();
let lu_t = lu.transpose();
assert_eq!(lu_t.nrows(), lu.ncols());
assert_eq!(lu_t.ncols(), lu.nrows());
assert_eq!(lu_t.npivots(), lu.npivots());
assert_eq!(lu_t.is_left_orthogonal(), !lu.is_left_orthogonal());Sourcepub fn is_left_orthogonal(&self) -> bool
pub fn is_left_orthogonal(&self) -> bool
Check if left-orthogonal (L has 1s on diagonal)
§Examples
use tensor4all_tcicore::{from_vec2d, matrixlu::rrlu, RrLUOptions};
let m = from_vec2d(vec![vec![1.0_f64, 2.0], vec![3.0, 4.0]]);
let lu = rrlu(&m, None).unwrap();
assert!(lu.is_left_orthogonal()); // default
let lu2 = rrlu(&m, Some(RrLUOptions {
left_orthogonal: false, ..Default::default()
})).unwrap();
assert!(!lu2.is_left_orthogonal());Trait Implementations§
Auto Trait Implementations§
impl<T> Freeze for RrLU<T>
impl<T> RefUnwindSafe for RrLU<T>where
T: RefUnwindSafe,
impl<T> Send for RrLU<T>
impl<T> Sync for RrLU<T>
impl<T> Unpin for RrLU<T>where
T: Unpin,
impl<T> UnsafeUnpin for RrLU<T>
impl<T> UnwindSafe for RrLU<T>where
T: UnwindSafe,
Blanket Implementations§
§impl<U> As for U
impl<U> As for U
§fn as_<T>(self) -> Twhere
T: CastFrom<U>,
fn as_<T>(self) -> Twhere
T: CastFrom<U>,
Casts
self to type T. The semantics of numeric casting with the as operator are followed, so <T as As>::as_::<U> can be used in the same way as T as U for numeric conversions. Read moreSource§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> DistributionExt for Twhere
T: ?Sized,
impl<T> DistributionExt for Twhere
T: ?Sized,
fn rand<T>(&self, rng: &mut (impl Rng + ?Sized)) -> Twhere
Self: Distribution<T>,
§impl<T> DistributionExt for Twhere
T: ?Sized,
impl<T> DistributionExt for Twhere
T: ?Sized,
fn rand<T>(&self, rng: &mut (impl Rng + ?Sized)) -> Twhere
Self: Distribution<T>,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
Converts
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
Converts
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more