1#[cfg(not(feature = "std"))]
20use alloc::{vec, vec::Vec};
21
22use crate::packed::{PackedMat, PackedMut, PackedRef, TriangularKind};
23use crate::{Mat, MatMut, MatRef};
24use oxiblas_core::scalar::Scalar;
25
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub enum DiagonalKind {
29 NonUnit,
31 Unit,
33}
34
35#[derive(Clone, Copy)]
61pub struct TriangularView<'a, T: Scalar> {
62 inner: MatRef<'a, T>,
64 uplo: TriangularKind,
66 diag: DiagonalKind,
68}
69
70impl<'a, T: Scalar> TriangularView<'a, T> {
71 #[inline]
76 pub fn new(mat: MatRef<'a, T>, uplo: TriangularKind, diag: DiagonalKind) -> Self {
77 assert!(mat.is_square(), "Triangular matrix must be square");
78 TriangularView {
79 inner: mat,
80 uplo,
81 diag,
82 }
83 }
84
85 #[inline]
87 pub fn dim(&self) -> usize {
88 self.inner.nrows()
89 }
90
91 #[inline]
93 pub fn shape(&self) -> (usize, usize) {
94 self.inner.shape()
95 }
96
97 #[inline]
99 pub fn uplo(&self) -> TriangularKind {
100 self.uplo
101 }
102
103 #[inline]
105 pub fn diag(&self) -> DiagonalKind {
106 self.diag
107 }
108
109 #[inline]
111 pub fn in_triangle(&self, row: usize, col: usize) -> bool {
112 match self.uplo {
113 TriangularKind::Upper => row <= col,
114 TriangularKind::Lower => row >= col,
115 }
116 }
117
118 #[inline]
124 pub fn get(&self, row: usize, col: usize) -> Option<&T> {
125 if !self.in_triangle(row, col) {
126 return None;
127 }
128
129 if self.diag == DiagonalKind::Unit && row == col {
130 return None; }
132
133 self.inner.get(row, col)
134 }
135
136 #[inline]
138 pub fn as_inner(&self) -> MatRef<'a, T> {
139 self.inner
140 }
141
142 #[inline]
144 pub fn as_ptr(&self) -> *const T {
145 self.inner.as_ptr()
146 }
147
148 #[inline]
150 pub fn row_stride(&self) -> usize {
151 self.inner.row_stride()
152 }
153
154 pub fn to_dense(&self) -> Mat<T>
156 where
157 T: bytemuck::Zeroable,
158 {
159 let n = self.dim();
160 let mut mat = Mat::zeros(n, n);
161
162 for j in 0..n {
163 for i in 0..n {
164 if self.in_triangle(i, j) {
165 if self.diag == DiagonalKind::Unit && i == j {
166 mat[(i, j)] = T::one();
167 } else {
168 mat[(i, j)] = self.inner[(i, j)];
169 }
170 }
171 }
172 }
173
174 mat
175 }
176
177 pub fn to_packed(&self) -> PackedMat<T>
179 where
180 T: bytemuck::Zeroable,
181 {
182 PackedMat::from_dense(&self.inner, self.uplo)
183 }
184}
185
186pub struct TriangularViewMut<'a, T: Scalar> {
188 inner: MatMut<'a, T>,
190 uplo: TriangularKind,
192 diag: DiagonalKind,
194}
195
196impl<'a, T: Scalar> TriangularViewMut<'a, T> {
197 #[inline]
199 pub fn new(mat: MatMut<'a, T>, uplo: TriangularKind, diag: DiagonalKind) -> Self {
200 assert!(mat.is_square(), "Triangular matrix must be square");
201 TriangularViewMut {
202 inner: mat,
203 uplo,
204 diag,
205 }
206 }
207
208 #[inline]
210 pub fn dim(&self) -> usize {
211 self.inner.nrows()
212 }
213
214 #[inline]
216 pub fn shape(&self) -> (usize, usize) {
217 self.inner.shape()
218 }
219
220 #[inline]
222 pub fn uplo(&self) -> TriangularKind {
223 self.uplo
224 }
225
226 #[inline]
228 pub fn diag(&self) -> DiagonalKind {
229 self.diag
230 }
231
232 #[inline]
234 pub fn in_triangle(&self, row: usize, col: usize) -> bool {
235 match self.uplo {
236 TriangularKind::Upper => row <= col,
237 TriangularKind::Lower => row >= col,
238 }
239 }
240
241 #[inline]
243 pub fn get(&self, row: usize, col: usize) -> Option<&T> {
244 if !self.in_triangle(row, col) {
245 return None;
246 }
247 if self.diag == DiagonalKind::Unit && row == col {
248 return None;
249 }
250 self.inner.get(row, col)
251 }
252
253 #[inline]
255 pub fn get_mut(&mut self, row: usize, col: usize) -> Option<&mut T> {
256 if !self.in_triangle(row, col) {
257 return None;
258 }
259 if self.diag == DiagonalKind::Unit && row == col {
260 return None;
261 }
262 self.inner.get_mut(row, col)
263 }
264
265 #[inline]
271 pub fn set(&mut self, row: usize, col: usize, value: T) {
272 assert!(
273 self.in_triangle(row, col),
274 "Element outside stored triangle"
275 );
276 assert!(
277 !(self.diag == DiagonalKind::Unit && row == col),
278 "Cannot set diagonal of unit triangular matrix"
279 );
280 self.inner.set(row, col, value);
281 }
282
283 #[inline]
285 pub fn rb(&self) -> TriangularView<'_, T> {
286 TriangularView {
287 inner: self.inner.rb(),
288 uplo: self.uplo,
289 diag: self.diag,
290 }
291 }
292
293 #[inline]
295 pub fn rb_mut(&mut self) -> TriangularViewMut<'_, T> {
296 TriangularViewMut {
297 inner: self.inner.rb_mut(),
298 uplo: self.uplo,
299 diag: self.diag,
300 }
301 }
302
303 #[inline]
305 pub fn as_mut_ptr(&mut self) -> *mut T {
306 self.inner.as_mut_ptr()
307 }
308
309 pub fn fill(&mut self, value: T) {
313 let n = self.dim();
314 for j in 0..n {
315 for i in 0..n {
316 if self.in_triangle(i, j) {
317 if self.diag == DiagonalKind::Unit && i == j {
318 continue;
319 }
320 self.inner.set(i, j, value);
321 }
322 }
323 }
324 }
325
326 pub fn scale(&mut self, alpha: T) {
328 let n = self.dim();
329 for j in 0..n {
330 for i in 0..n {
331 if self.in_triangle(i, j) {
332 if self.diag == DiagonalKind::Unit && i == j {
333 continue;
334 }
335 if let Some(val) = self.inner.get(i, j) {
336 self.inner.set(i, j, *val * alpha);
337 }
338 }
339 }
340 }
341 }
342
343 pub fn zero_non_triangle(&mut self)
345 where
346 T: num_traits::Zero,
347 {
348 let n = self.dim();
349 for j in 0..n {
350 for i in 0..n {
351 if !self.in_triangle(i, j) {
352 self.inner.set(i, j, T::zero());
353 }
354 }
355 }
356 }
357}
358
359#[derive(Clone)]
364pub struct TriangularMat<T: Scalar> {
365 packed: PackedMat<T>,
367 diag: DiagonalKind,
369}
370
371impl<T: Scalar> TriangularMat<T> {
372 pub fn zeros(n: usize, uplo: TriangularKind, diag: DiagonalKind) -> Self
374 where
375 T: bytemuck::Zeroable,
376 {
377 TriangularMat {
378 packed: PackedMat::zeros(n, uplo),
379 diag,
380 }
381 }
382
383 pub fn unit_zeros(n: usize, uplo: TriangularKind) -> Self
387 where
388 T: bytemuck::Zeroable,
389 {
390 Self::zeros(n, uplo, DiagonalKind::Unit)
391 }
392
393 #[inline]
395 pub fn from_packed(packed: PackedMat<T>, diag: DiagonalKind) -> Self {
396 TriangularMat { packed, diag }
397 }
398
399 pub fn from_dense(mat: &MatRef<'_, T>, uplo: TriangularKind, diag: DiagonalKind) -> Self
401 where
402 T: bytemuck::Zeroable,
403 {
404 TriangularMat {
405 packed: PackedMat::from_dense(mat, uplo),
406 diag,
407 }
408 }
409
410 #[inline]
412 pub fn dim(&self) -> usize {
413 self.packed.dim()
414 }
415
416 #[inline]
418 pub fn shape(&self) -> (usize, usize) {
419 let n = self.dim();
420 (n, n)
421 }
422
423 #[inline]
425 pub fn uplo(&self) -> TriangularKind {
426 self.packed.kind()
427 }
428
429 #[inline]
431 pub fn diag(&self) -> DiagonalKind {
432 self.diag
433 }
434
435 #[inline]
437 pub fn len(&self) -> usize {
438 self.packed.len()
439 }
440
441 #[inline]
443 pub fn is_empty(&self) -> bool {
444 self.packed.is_empty()
445 }
446
447 #[inline]
449 pub fn in_triangle(&self, row: usize, col: usize) -> bool {
450 self.packed.packed_index(row, col).is_some()
451 }
452
453 #[inline]
457 pub fn get(&self, row: usize, col: usize) -> Option<&T> {
458 if self.diag == DiagonalKind::Unit && row == col {
459 return None;
460 }
461 self.packed.get(row, col)
462 }
463
464 #[inline]
466 pub fn get_mut(&mut self, row: usize, col: usize) -> Option<&mut T> {
467 if self.diag == DiagonalKind::Unit && row == col {
468 return None;
469 }
470 self.packed.get_mut(row, col)
471 }
472
473 #[inline]
479 pub fn set(&mut self, row: usize, col: usize, value: T) {
480 assert!(
481 !(self.diag == DiagonalKind::Unit && row == col),
482 "Cannot set diagonal of unit triangular matrix"
483 );
484 assert!(
485 self.in_triangle(row, col),
486 "Element outside stored triangle"
487 );
488 self.packed
492 .set(row, col, value)
493 .expect("in_triangle check above guarantees this index is valid");
494 }
495
496 #[inline]
498 pub fn as_ptr(&self) -> *const T {
499 self.packed.as_ptr()
500 }
501
502 #[inline]
504 pub fn as_mut_ptr(&mut self) -> *mut T {
505 self.packed.as_mut_ptr()
506 }
507
508 #[inline]
510 pub fn as_slice(&self) -> &[T] {
511 self.packed.as_slice()
512 }
513
514 #[inline]
516 pub fn as_slice_mut(&mut self) -> &mut [T] {
517 self.packed.as_slice_mut()
518 }
519
520 #[inline]
522 pub fn as_packed(&self) -> &PackedMat<T> {
523 &self.packed
524 }
525
526 #[inline]
528 pub fn as_packed_mut(&mut self) -> &mut PackedMat<T> {
529 &mut self.packed
530 }
531
532 pub fn to_dense(&self) -> Mat<T>
534 where
535 T: bytemuck::Zeroable,
536 {
537 let n = self.dim();
538 let mut mat = Mat::zeros(n, n);
539
540 for j in 0..n {
541 for i in 0..n {
542 if let Some(&val) = self.packed.get(i, j) {
543 if self.diag == DiagonalKind::Unit && i == j {
544 mat[(i, j)] = T::one();
545 } else {
546 mat[(i, j)] = val;
547 }
548 } else if self.diag == DiagonalKind::Unit && i == j {
549 mat[(i, j)] = T::one();
550 }
551 }
552 }
553
554 mat
555 }
556
557 pub fn diagonal(&self) -> Vec<T> {
561 let n = self.dim();
562 if self.diag == DiagonalKind::Unit {
563 vec![T::one(); n]
564 } else {
565 self.packed.diagonal()
566 }
567 }
568
569 pub fn set_diagonal(&mut self, diag: &[T]) {
574 assert!(
575 self.diag != DiagonalKind::Unit,
576 "Cannot set diagonal of unit triangular matrix"
577 );
578 self.packed.set_diagonal(diag);
579 }
580
581 pub fn fill(&mut self, value: T) {
583 if self.diag == DiagonalKind::Unit {
584 let n = self.dim();
586 for j in 0..n {
587 for i in 0..n {
588 if self.in_triangle(i, j) && i != j {
589 self.packed
591 .set(i, j, value)
592 .expect("in_triangle check above guarantees this index is valid");
593 }
594 }
595 }
596 } else {
597 self.packed.fill(value);
598 }
599 }
600
601 pub fn scale(&mut self, alpha: T) {
603 if self.diag == DiagonalKind::Unit {
604 let n = self.dim();
606 for j in 0..n {
607 for i in 0..n {
608 if self.in_triangle(i, j) && i != j {
609 if let Some(val) = self.packed.get_mut(i, j) {
610 *val *= alpha;
611 }
612 }
613 }
614 }
615 } else {
616 self.packed.scale(alpha);
617 }
618 }
619
620 pub fn transpose(&self) -> Self
622 where
623 T: bytemuck::Zeroable,
624 {
625 TriangularMat {
626 packed: self.packed.transpose(),
627 diag: self.diag,
628 }
629 }
630}
631
632impl<T: Scalar + core::fmt::Debug> core::fmt::Debug for TriangularMat<T> {
633 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
634 let n = self.dim();
635 writeln!(
636 f,
637 "TriangularMat {}×{} ({:?}, {:?}) {{",
638 n,
639 n,
640 self.uplo(),
641 self.diag
642 )?;
643
644 let max_dim = 8.min(n);
645 for i in 0..max_dim {
646 write!(f, " [")?;
647 for j in 0..max_dim {
648 if j > 0 {
649 write!(f, ", ")?;
650 }
651 if self.in_triangle(i, j) {
652 if self.diag == DiagonalKind::Unit && i == j {
653 write!(f, "{:8.4?}", T::one())?;
654 } else if let Some(v) = self.packed.get(i, j) {
655 write!(f, "{:8.4?}", v)?;
656 } else {
657 write!(f, " * ")?;
658 }
659 } else {
660 write!(f, " 0 ")?;
661 }
662 }
663 if n > max_dim {
664 write!(f, ", ...")?;
665 }
666 writeln!(f, "]")?;
667 }
668 if n > max_dim {
669 writeln!(f, " ...")?;
670 }
671 write!(f, "}}")
672 }
673}
674
675#[derive(Clone, Copy)]
677pub struct TriangularRef<'a, T: Scalar> {
678 packed: PackedRef<'a, T>,
680 diag: DiagonalKind,
682}
683
684impl<'a, T: Scalar> TriangularRef<'a, T> {
685 #[inline]
687 pub fn new(packed: PackedRef<'a, T>, diag: DiagonalKind) -> Self {
688 TriangularRef { packed, diag }
689 }
690
691 #[inline]
693 pub fn from_slice(data: &'a [T], n: usize, uplo: TriangularKind, diag: DiagonalKind) -> Self {
694 TriangularRef {
695 packed: PackedRef::from_slice(data, n, uplo),
696 diag,
697 }
698 }
699
700 #[inline]
702 pub fn dim(&self) -> usize {
703 self.packed.dim()
704 }
705
706 #[inline]
708 pub fn uplo(&self) -> TriangularKind {
709 self.packed.kind()
710 }
711
712 #[inline]
714 pub fn diag(&self) -> DiagonalKind {
715 self.diag
716 }
717
718 #[inline]
720 pub fn get(&self, row: usize, col: usize) -> Option<&T> {
721 if self.diag == DiagonalKind::Unit && row == col {
722 return None;
723 }
724 self.packed.get(row, col)
725 }
726
727 #[inline]
729 pub fn as_packed(&self) -> PackedRef<'a, T> {
730 self.packed
731 }
732}
733
734pub struct TriangularMut<'a, T: Scalar> {
736 packed: PackedMut<'a, T>,
738 diag: DiagonalKind,
740}
741
742impl<'a, T: Scalar> TriangularMut<'a, T> {
743 #[inline]
745 pub fn new(packed: PackedMut<'a, T>, diag: DiagonalKind) -> Self {
746 TriangularMut { packed, diag }
747 }
748
749 #[inline]
751 pub fn from_slice(
752 data: &'a mut [T],
753 n: usize,
754 uplo: TriangularKind,
755 diag: DiagonalKind,
756 ) -> Self {
757 TriangularMut {
758 packed: PackedMut::from_slice(data, n, uplo),
759 diag,
760 }
761 }
762
763 #[inline]
765 pub fn dim(&self) -> usize {
766 self.packed.dim()
767 }
768
769 #[inline]
771 pub fn uplo(&self) -> TriangularKind {
772 self.packed.kind()
773 }
774
775 #[inline]
777 pub fn diag(&self) -> DiagonalKind {
778 self.diag
779 }
780
781 #[inline]
783 pub fn get(&self, row: usize, col: usize) -> Option<&T> {
784 if self.diag == DiagonalKind::Unit && row == col {
785 return None;
786 }
787 self.packed.get(row, col)
788 }
789
790 #[inline]
792 pub fn get_mut(&mut self, row: usize, col: usize) -> Option<&mut T> {
793 if self.diag == DiagonalKind::Unit && row == col {
794 return None;
795 }
796 self.packed.get_mut(row, col)
797 }
798
799 #[inline]
805 pub fn set(&mut self, row: usize, col: usize, value: T) {
806 assert!(
807 !(self.diag == DiagonalKind::Unit && row == col),
808 "Cannot set diagonal of unit triangular matrix"
809 );
810 assert!(
811 self.packed.packed_index(row, col).is_some(),
812 "Element outside stored triangle"
813 );
814 self.packed
817 .set(row, col, value)
818 .expect("packed_index check above guarantees this index is valid");
819 }
820
821 #[inline]
823 pub fn rb(&self) -> TriangularRef<'_, T> {
824 TriangularRef {
825 packed: self.packed.rb(),
826 diag: self.diag,
827 }
828 }
829
830 #[inline]
832 pub fn rb_mut(&mut self) -> TriangularMut<'_, T> {
833 TriangularMut {
834 packed: self.packed.rb_mut(),
835 diag: self.diag,
836 }
837 }
838}
839
840#[cfg(test)]
841mod tests {
842 use super::*;
843
844 #[test]
845 fn test_triangular_view_upper() {
846 let mut m: Mat<f64> = Mat::zeros(3, 3);
847 m[(0, 0)] = 1.0;
848 m[(0, 1)] = 2.0;
849 m[(0, 2)] = 3.0;
850 m[(1, 1)] = 4.0;
851 m[(1, 2)] = 5.0;
852 m[(2, 2)] = 6.0;
853 m[(1, 0)] = 99.0;
855 m[(2, 0)] = 99.0;
856 m[(2, 1)] = 99.0;
857
858 let tri = TriangularView::new(m.as_ref(), TriangularKind::Upper, DiagonalKind::NonUnit);
859
860 assert_eq!(tri.get(0, 0), Some(&1.0));
862 assert_eq!(tri.get(0, 1), Some(&2.0));
863 assert_eq!(tri.get(0, 2), Some(&3.0));
864 assert_eq!(tri.get(1, 1), Some(&4.0));
865 assert_eq!(tri.get(1, 2), Some(&5.0));
866 assert_eq!(tri.get(2, 2), Some(&6.0));
867
868 assert_eq!(tri.get(1, 0), None);
870 assert_eq!(tri.get(2, 0), None);
871 assert_eq!(tri.get(2, 1), None);
872
873 let dense = tri.to_dense();
875 assert_eq!(dense[(0, 0)], 1.0);
876 assert_eq!(dense[(0, 1)], 2.0);
877 assert_eq!(dense[(1, 0)], 0.0); assert_eq!(dense[(2, 1)], 0.0);
879 }
880
881 #[test]
882 fn test_triangular_view_unit() {
883 let mut m: Mat<f64> = Mat::zeros(3, 3);
884 m[(0, 0)] = 99.0; m[(0, 1)] = 2.0;
886 m[(0, 2)] = 3.0;
887 m[(1, 1)] = 99.0; m[(1, 2)] = 4.0;
889 m[(2, 2)] = 99.0; let tri = TriangularView::new(m.as_ref(), TriangularKind::Upper, DiagonalKind::Unit);
892
893 assert_eq!(tri.get(0, 0), None);
895 assert_eq!(tri.get(1, 1), None);
896 assert_eq!(tri.get(2, 2), None);
897
898 assert_eq!(tri.get(0, 1), Some(&2.0));
900 assert_eq!(tri.get(0, 2), Some(&3.0));
901 assert_eq!(tri.get(1, 2), Some(&4.0));
902
903 let dense = tri.to_dense();
905 assert_eq!(dense[(0, 0)], 1.0);
906 assert_eq!(dense[(1, 1)], 1.0);
907 assert_eq!(dense[(2, 2)], 1.0);
908 assert_eq!(dense[(0, 1)], 2.0);
909 }
910
911 #[test]
912 fn test_triangular_view_lower() {
913 let mut m: Mat<f64> = Mat::zeros(3, 3);
914 m[(0, 0)] = 1.0;
915 m[(1, 0)] = 2.0;
916 m[(1, 1)] = 3.0;
917 m[(2, 0)] = 4.0;
918 m[(2, 1)] = 5.0;
919 m[(2, 2)] = 6.0;
920
921 let tri = TriangularView::new(m.as_ref(), TriangularKind::Lower, DiagonalKind::NonUnit);
922
923 assert_eq!(tri.get(0, 0), Some(&1.0));
925 assert_eq!(tri.get(1, 0), Some(&2.0));
926 assert_eq!(tri.get(1, 1), Some(&3.0));
927 assert_eq!(tri.get(2, 0), Some(&4.0));
928 assert_eq!(tri.get(2, 1), Some(&5.0));
929 assert_eq!(tri.get(2, 2), Some(&6.0));
930
931 assert_eq!(tri.get(0, 1), None);
933 assert_eq!(tri.get(0, 2), None);
934 assert_eq!(tri.get(1, 2), None);
935 }
936
937 #[test]
938 fn test_triangular_mat_packed() {
939 let mut tri: TriangularMat<f64> =
940 TriangularMat::zeros(3, TriangularKind::Upper, DiagonalKind::NonUnit);
941
942 tri.set(0, 0, 1.0);
943 tri.set(0, 1, 2.0);
944 tri.set(0, 2, 3.0);
945 tri.set(1, 1, 4.0);
946 tri.set(1, 2, 5.0);
947 tri.set(2, 2, 6.0);
948
949 assert_eq!(tri.get(0, 0), Some(&1.0));
950 assert_eq!(tri.get(0, 1), Some(&2.0));
951 assert_eq!(tri.get(1, 2), Some(&5.0));
952
953 assert_eq!(tri.get(1, 0), None);
955
956 let diag = tri.diagonal();
957 assert_eq!(diag, vec![1.0, 4.0, 6.0]);
958 }
959
960 #[test]
961 fn test_triangular_mat_unit() {
962 let mut tri: TriangularMat<f64> = TriangularMat::unit_zeros(3, TriangularKind::Lower);
963
964 tri.set(1, 0, 2.0);
966 tri.set(2, 0, 3.0);
967 tri.set(2, 1, 4.0);
968
969 assert_eq!(tri.get(0, 0), None);
971 assert_eq!(tri.get(1, 1), None);
972 assert_eq!(tri.get(2, 2), None);
973
974 assert_eq!(tri.get(1, 0), Some(&2.0));
976 assert_eq!(tri.get(2, 0), Some(&3.0));
977 assert_eq!(tri.get(2, 1), Some(&4.0));
978
979 let diag = tri.diagonal();
981 assert_eq!(diag, vec![1.0, 1.0, 1.0]);
982
983 let dense = tri.to_dense();
985 assert_eq!(dense[(0, 0)], 1.0);
986 assert_eq!(dense[(1, 1)], 1.0);
987 assert_eq!(dense[(2, 2)], 1.0);
988 assert_eq!(dense[(1, 0)], 2.0);
989 assert_eq!(dense[(0, 1)], 0.0);
990 }
991
992 #[test]
993 fn test_triangular_mat_transpose() {
994 let mut tri: TriangularMat<f64> =
995 TriangularMat::zeros(3, TriangularKind::Upper, DiagonalKind::NonUnit);
996
997 tri.set(0, 0, 1.0);
998 tri.set(0, 1, 2.0);
999 tri.set(0, 2, 3.0);
1000 tri.set(1, 1, 4.0);
1001 tri.set(1, 2, 5.0);
1002 tri.set(2, 2, 6.0);
1003
1004 let tri_t = tri.transpose();
1005 assert_eq!(tri_t.uplo(), TriangularKind::Lower);
1006
1007 assert_eq!(tri_t.get(0, 0), Some(&1.0));
1009 assert_eq!(tri_t.get(1, 0), Some(&2.0)); assert_eq!(tri_t.get(2, 0), Some(&3.0)); assert_eq!(tri_t.get(1, 1), Some(&4.0));
1012 assert_eq!(tri_t.get(2, 1), Some(&5.0)); assert_eq!(tri_t.get(2, 2), Some(&6.0));
1014 }
1015
1016 #[test]
1017 fn test_triangular_view_mut() {
1018 let mut m: Mat<f64> = Mat::zeros(3, 3);
1019 let mut view =
1020 TriangularViewMut::new(m.as_mut(), TriangularKind::Upper, DiagonalKind::NonUnit);
1021
1022 view.set(0, 0, 1.0);
1023 view.set(0, 1, 2.0);
1024 view.set(1, 1, 3.0);
1025
1026 assert_eq!(view.get(0, 0), Some(&1.0));
1027 assert_eq!(view.get(0, 1), Some(&2.0));
1028 assert_eq!(view.get(1, 1), Some(&3.0));
1029
1030 view.zero_non_triangle();
1032 view.fill(5.0);
1036 assert_eq!(view.get(0, 0), Some(&5.0));
1037 assert_eq!(view.get(0, 1), Some(&5.0));
1038 }
1039
1040 #[test]
1041 fn test_triangular_from_dense() {
1042 let m = Mat::from_rows(&[&[1.0, 2.0, 3.0], &[4.0, 5.0, 6.0], &[7.0, 8.0, 9.0]]);
1043
1044 let tri =
1045 TriangularMat::from_dense(&m.as_ref(), TriangularKind::Upper, DiagonalKind::NonUnit);
1046
1047 assert_eq!(tri.get(0, 0), Some(&1.0));
1048 assert_eq!(tri.get(0, 1), Some(&2.0));
1049 assert_eq!(tri.get(0, 2), Some(&3.0));
1050 assert_eq!(tri.get(1, 1), Some(&5.0));
1051 assert_eq!(tri.get(1, 2), Some(&6.0));
1052 assert_eq!(tri.get(2, 2), Some(&9.0));
1053
1054 assert_eq!(tri.get(1, 0), None);
1056 assert_eq!(tri.get(2, 0), None);
1057 assert_eq!(tri.get(2, 1), None);
1058 }
1059
1060 #[test]
1061 fn test_triangular_ref_mut() {
1062 let mut data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0];
1063 let mut tmut =
1064 TriangularMut::from_slice(&mut data, 3, TriangularKind::Upper, DiagonalKind::NonUnit);
1065
1066 assert_eq!(tmut.get(0, 0), Some(&1.0));
1067 assert_eq!(tmut.get(0, 1), Some(&2.0));
1068
1069 tmut.set(0, 0, 10.0);
1070 assert_eq!(tmut.get(0, 0), Some(&10.0));
1071 assert_eq!(data[0], 10.0);
1072 }
1073}