|
2 | 2 |
|
3 | 3 | use ndarray::*;
|
4 | 4 |
|
| 5 | +use crate::convert::*; |
5 | 6 | use crate::error::*;
|
6 | 7 | use crate::layout::*;
|
| 8 | +use crate::tridiagonal::Tridiagonal; |
7 | 9 | use crate::types::*;
|
8 | 10 |
|
9 | 11 | pub use crate::lapack::NormType;
|
|
46 | 48 | Ok(unsafe { A::opnorm(t, l, a) })
|
47 | 49 | }
|
48 | 50 | }
|
| 51 | + |
| 52 | +impl<A> OperationNorm for Tridiagonal<A> |
| 53 | +where |
| 54 | + A: Scalar + Lapack, |
| 55 | +{ |
| 56 | + type Output = A::Real; |
| 57 | + |
| 58 | + fn opnorm(&self, t: NormType) -> Result<Self::Output> { |
| 59 | + // `self` is a tridiagonal matrix like, |
| 60 | + // [d0, u1, 0, ..., 0, |
| 61 | + // l1, d1, u2, ..., |
| 62 | + // 0, l2, d2, |
| 63 | + // ... ..., u{n-1}, |
| 64 | + // 0, ..., l{n-1}, d{n-1},] |
| 65 | + let arr = match t { |
| 66 | + // opnorm_one() calculates muximum column sum. |
| 67 | + // Therefore, This part align the columns and make a (3 x n) matrix like, |
| 68 | + // [ 0, u1, u2, ..., u{n-1}, |
| 69 | + // d0, d1, d2, ..., d{n-1}, |
| 70 | + // l1, l2, l3, ..., 0,] |
| 71 | + NormType::One => { |
| 72 | + let zl: Array1<A> = Array::zeros(1); |
| 73 | + let zu: Array1<A> = Array::zeros(1); |
| 74 | + let dl = stack![Axis(0), self.dl.to_owned(), zl]; |
| 75 | + let du = stack![Axis(0), zu, self.du.to_owned()]; |
| 76 | + let arr = stack![Axis(0), into_row(du), into_row(arr1(&self.d)), into_row(dl)]; |
| 77 | + arr |
| 78 | + } |
| 79 | + // opnorm_inf() calculates muximum row sum. |
| 80 | + // Therefore, This part align the rows and make a (n x 3) matrix like, |
| 81 | + // [ 0, d0, u1, |
| 82 | + // l1, d1, u2, |
| 83 | + // l2, d2, u3, |
| 84 | + // ..., ..., ..., |
| 85 | + // l{n-1}, d{n-1}, 0,] |
| 86 | + NormType::Infinity => { |
| 87 | + let zl: Array1<A> = Array::zeros(1); |
| 88 | + let zu: Array1<A> = Array::zeros(1); |
| 89 | + let dl = stack![Axis(0), zl, self.dl.to_owned()]; |
| 90 | + let du = stack![Axis(0), self.du.to_owned(), zu]; |
| 91 | + let arr = stack![Axis(1), into_col(dl), into_col(arr1(&self.d)), into_col(du)]; |
| 92 | + arr |
| 93 | + } |
| 94 | + // opnorm_fro() calculates square root of sum of squares. |
| 95 | + // Because it is independent of the shape of matrix, |
| 96 | + // this part make a (1 x (3n-2)) matrix like, |
| 97 | + // [l1, ..., l{n-1}, d0, ..., d{n-1}, u1, ..., u{n-1}] |
| 98 | + NormType::Frobenius => { |
| 99 | + let arr = stack![ |
| 100 | + Axis(1), |
| 101 | + into_row(arr1(&self.dl)), |
| 102 | + into_row(arr1(&self.d)), |
| 103 | + into_row(arr1(&self.du)) |
| 104 | + ]; |
| 105 | + arr |
| 106 | + } |
| 107 | + }; |
| 108 | + |
| 109 | + let l = arr.layout()?; |
| 110 | + let a = arr.as_allocated()?; |
| 111 | + Ok(unsafe { A::opnorm(t, l, a) }) |
| 112 | + } |
| 113 | +} |
0 commit comments