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]
478 pub fn set(&mut self, row: usize, col: usize, value: T) {
479 assert!(
480 !(self.diag == DiagonalKind::Unit && row == col),
481 "Cannot set diagonal of unit triangular matrix"
482 );
483 self.packed.set(row, col, value);
484 }
485
486 #[inline]
488 pub fn as_ptr(&self) -> *const T {
489 self.packed.as_ptr()
490 }
491
492 #[inline]
494 pub fn as_mut_ptr(&mut self) -> *mut T {
495 self.packed.as_mut_ptr()
496 }
497
498 #[inline]
500 pub fn as_slice(&self) -> &[T] {
501 self.packed.as_slice()
502 }
503
504 #[inline]
506 pub fn as_slice_mut(&mut self) -> &mut [T] {
507 self.packed.as_slice_mut()
508 }
509
510 #[inline]
512 pub fn as_packed(&self) -> &PackedMat<T> {
513 &self.packed
514 }
515
516 #[inline]
518 pub fn as_packed_mut(&mut self) -> &mut PackedMat<T> {
519 &mut self.packed
520 }
521
522 pub fn to_dense(&self) -> Mat<T>
524 where
525 T: bytemuck::Zeroable,
526 {
527 let n = self.dim();
528 let mut mat = Mat::zeros(n, n);
529
530 for j in 0..n {
531 for i in 0..n {
532 if let Some(&val) = self.packed.get(i, j) {
533 if self.diag == DiagonalKind::Unit && i == j {
534 mat[(i, j)] = T::one();
535 } else {
536 mat[(i, j)] = val;
537 }
538 } else if self.diag == DiagonalKind::Unit && i == j {
539 mat[(i, j)] = T::one();
540 }
541 }
542 }
543
544 mat
545 }
546
547 pub fn diagonal(&self) -> Vec<T> {
551 let n = self.dim();
552 if self.diag == DiagonalKind::Unit {
553 vec![T::one(); n]
554 } else {
555 self.packed.diagonal()
556 }
557 }
558
559 pub fn set_diagonal(&mut self, diag: &[T]) {
564 assert!(
565 self.diag != DiagonalKind::Unit,
566 "Cannot set diagonal of unit triangular matrix"
567 );
568 self.packed.set_diagonal(diag);
569 }
570
571 pub fn fill(&mut self, value: T) {
573 if self.diag == DiagonalKind::Unit {
574 let n = self.dim();
576 for j in 0..n {
577 for i in 0..n {
578 if self.in_triangle(i, j) && i != j {
579 self.packed.set(i, j, value);
580 }
581 }
582 }
583 } else {
584 self.packed.fill(value);
585 }
586 }
587
588 pub fn scale(&mut self, alpha: T) {
590 if self.diag == DiagonalKind::Unit {
591 let n = self.dim();
593 for j in 0..n {
594 for i in 0..n {
595 if self.in_triangle(i, j) && i != j {
596 if let Some(val) = self.packed.get_mut(i, j) {
597 *val *= alpha;
598 }
599 }
600 }
601 }
602 } else {
603 self.packed.scale(alpha);
604 }
605 }
606
607 pub fn transpose(&self) -> Self
609 where
610 T: bytemuck::Zeroable,
611 {
612 TriangularMat {
613 packed: self.packed.transpose(),
614 diag: self.diag,
615 }
616 }
617}
618
619impl<T: Scalar + core::fmt::Debug> core::fmt::Debug for TriangularMat<T> {
620 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
621 let n = self.dim();
622 writeln!(
623 f,
624 "TriangularMat {}×{} ({:?}, {:?}) {{",
625 n,
626 n,
627 self.uplo(),
628 self.diag
629 )?;
630
631 let max_dim = 8.min(n);
632 for i in 0..max_dim {
633 write!(f, " [")?;
634 for j in 0..max_dim {
635 if j > 0 {
636 write!(f, ", ")?;
637 }
638 if self.in_triangle(i, j) {
639 if self.diag == DiagonalKind::Unit && i == j {
640 write!(f, "{:8.4?}", T::one())?;
641 } else if let Some(v) = self.packed.get(i, j) {
642 write!(f, "{:8.4?}", v)?;
643 } else {
644 write!(f, " * ")?;
645 }
646 } else {
647 write!(f, " 0 ")?;
648 }
649 }
650 if n > max_dim {
651 write!(f, ", ...")?;
652 }
653 writeln!(f, "]")?;
654 }
655 if n > max_dim {
656 writeln!(f, " ...")?;
657 }
658 write!(f, "}}")
659 }
660}
661
662#[derive(Clone, Copy)]
664pub struct TriangularRef<'a, T: Scalar> {
665 packed: PackedRef<'a, T>,
667 diag: DiagonalKind,
669}
670
671impl<'a, T: Scalar> TriangularRef<'a, T> {
672 #[inline]
674 pub fn new(packed: PackedRef<'a, T>, diag: DiagonalKind) -> Self {
675 TriangularRef { packed, diag }
676 }
677
678 #[inline]
680 pub fn from_slice(data: &'a [T], n: usize, uplo: TriangularKind, diag: DiagonalKind) -> Self {
681 TriangularRef {
682 packed: PackedRef::from_slice(data, n, uplo),
683 diag,
684 }
685 }
686
687 #[inline]
689 pub fn dim(&self) -> usize {
690 self.packed.dim()
691 }
692
693 #[inline]
695 pub fn uplo(&self) -> TriangularKind {
696 self.packed.kind()
697 }
698
699 #[inline]
701 pub fn diag(&self) -> DiagonalKind {
702 self.diag
703 }
704
705 #[inline]
707 pub fn get(&self, row: usize, col: usize) -> Option<&T> {
708 if self.diag == DiagonalKind::Unit && row == col {
709 return None;
710 }
711 self.packed.get(row, col)
712 }
713
714 #[inline]
716 pub fn as_packed(&self) -> PackedRef<'a, T> {
717 self.packed
718 }
719}
720
721pub struct TriangularMut<'a, T: Scalar> {
723 packed: PackedMut<'a, T>,
725 diag: DiagonalKind,
727}
728
729impl<'a, T: Scalar> TriangularMut<'a, T> {
730 #[inline]
732 pub fn new(packed: PackedMut<'a, T>, diag: DiagonalKind) -> Self {
733 TriangularMut { packed, diag }
734 }
735
736 #[inline]
738 pub fn from_slice(
739 data: &'a mut [T],
740 n: usize,
741 uplo: TriangularKind,
742 diag: DiagonalKind,
743 ) -> Self {
744 TriangularMut {
745 packed: PackedMut::from_slice(data, n, uplo),
746 diag,
747 }
748 }
749
750 #[inline]
752 pub fn dim(&self) -> usize {
753 self.packed.dim()
754 }
755
756 #[inline]
758 pub fn uplo(&self) -> TriangularKind {
759 self.packed.kind()
760 }
761
762 #[inline]
764 pub fn diag(&self) -> DiagonalKind {
765 self.diag
766 }
767
768 #[inline]
770 pub fn get(&self, row: usize, col: usize) -> Option<&T> {
771 if self.diag == DiagonalKind::Unit && row == col {
772 return None;
773 }
774 self.packed.get(row, col)
775 }
776
777 #[inline]
779 pub fn get_mut(&mut self, row: usize, col: usize) -> Option<&mut T> {
780 if self.diag == DiagonalKind::Unit && row == col {
781 return None;
782 }
783 self.packed.get_mut(row, col)
784 }
785
786 #[inline]
788 pub fn set(&mut self, row: usize, col: usize, value: T) {
789 assert!(
790 !(self.diag == DiagonalKind::Unit && row == col),
791 "Cannot set diagonal of unit triangular matrix"
792 );
793 self.packed.set(row, col, value);
794 }
795
796 #[inline]
798 pub fn rb(&self) -> TriangularRef<'_, T> {
799 TriangularRef {
800 packed: self.packed.rb(),
801 diag: self.diag,
802 }
803 }
804
805 #[inline]
807 pub fn rb_mut(&mut self) -> TriangularMut<'_, T> {
808 TriangularMut {
809 packed: self.packed.rb_mut(),
810 diag: self.diag,
811 }
812 }
813}
814
815#[cfg(test)]
816mod tests {
817 use super::*;
818
819 #[test]
820 fn test_triangular_view_upper() {
821 let mut m: Mat<f64> = Mat::zeros(3, 3);
822 m[(0, 0)] = 1.0;
823 m[(0, 1)] = 2.0;
824 m[(0, 2)] = 3.0;
825 m[(1, 1)] = 4.0;
826 m[(1, 2)] = 5.0;
827 m[(2, 2)] = 6.0;
828 m[(1, 0)] = 99.0;
830 m[(2, 0)] = 99.0;
831 m[(2, 1)] = 99.0;
832
833 let tri = TriangularView::new(m.as_ref(), TriangularKind::Upper, DiagonalKind::NonUnit);
834
835 assert_eq!(tri.get(0, 0), Some(&1.0));
837 assert_eq!(tri.get(0, 1), Some(&2.0));
838 assert_eq!(tri.get(0, 2), Some(&3.0));
839 assert_eq!(tri.get(1, 1), Some(&4.0));
840 assert_eq!(tri.get(1, 2), Some(&5.0));
841 assert_eq!(tri.get(2, 2), Some(&6.0));
842
843 assert_eq!(tri.get(1, 0), None);
845 assert_eq!(tri.get(2, 0), None);
846 assert_eq!(tri.get(2, 1), None);
847
848 let dense = tri.to_dense();
850 assert_eq!(dense[(0, 0)], 1.0);
851 assert_eq!(dense[(0, 1)], 2.0);
852 assert_eq!(dense[(1, 0)], 0.0); assert_eq!(dense[(2, 1)], 0.0);
854 }
855
856 #[test]
857 fn test_triangular_view_unit() {
858 let mut m: Mat<f64> = Mat::zeros(3, 3);
859 m[(0, 0)] = 99.0; m[(0, 1)] = 2.0;
861 m[(0, 2)] = 3.0;
862 m[(1, 1)] = 99.0; m[(1, 2)] = 4.0;
864 m[(2, 2)] = 99.0; let tri = TriangularView::new(m.as_ref(), TriangularKind::Upper, DiagonalKind::Unit);
867
868 assert_eq!(tri.get(0, 0), None);
870 assert_eq!(tri.get(1, 1), None);
871 assert_eq!(tri.get(2, 2), None);
872
873 assert_eq!(tri.get(0, 1), Some(&2.0));
875 assert_eq!(tri.get(0, 2), Some(&3.0));
876 assert_eq!(tri.get(1, 2), Some(&4.0));
877
878 let dense = tri.to_dense();
880 assert_eq!(dense[(0, 0)], 1.0);
881 assert_eq!(dense[(1, 1)], 1.0);
882 assert_eq!(dense[(2, 2)], 1.0);
883 assert_eq!(dense[(0, 1)], 2.0);
884 }
885
886 #[test]
887 fn test_triangular_view_lower() {
888 let mut m: Mat<f64> = Mat::zeros(3, 3);
889 m[(0, 0)] = 1.0;
890 m[(1, 0)] = 2.0;
891 m[(1, 1)] = 3.0;
892 m[(2, 0)] = 4.0;
893 m[(2, 1)] = 5.0;
894 m[(2, 2)] = 6.0;
895
896 let tri = TriangularView::new(m.as_ref(), TriangularKind::Lower, DiagonalKind::NonUnit);
897
898 assert_eq!(tri.get(0, 0), Some(&1.0));
900 assert_eq!(tri.get(1, 0), Some(&2.0));
901 assert_eq!(tri.get(1, 1), Some(&3.0));
902 assert_eq!(tri.get(2, 0), Some(&4.0));
903 assert_eq!(tri.get(2, 1), Some(&5.0));
904 assert_eq!(tri.get(2, 2), Some(&6.0));
905
906 assert_eq!(tri.get(0, 1), None);
908 assert_eq!(tri.get(0, 2), None);
909 assert_eq!(tri.get(1, 2), None);
910 }
911
912 #[test]
913 fn test_triangular_mat_packed() {
914 let mut tri: TriangularMat<f64> =
915 TriangularMat::zeros(3, TriangularKind::Upper, DiagonalKind::NonUnit);
916
917 tri.set(0, 0, 1.0);
918 tri.set(0, 1, 2.0);
919 tri.set(0, 2, 3.0);
920 tri.set(1, 1, 4.0);
921 tri.set(1, 2, 5.0);
922 tri.set(2, 2, 6.0);
923
924 assert_eq!(tri.get(0, 0), Some(&1.0));
925 assert_eq!(tri.get(0, 1), Some(&2.0));
926 assert_eq!(tri.get(1, 2), Some(&5.0));
927
928 assert_eq!(tri.get(1, 0), None);
930
931 let diag = tri.diagonal();
932 assert_eq!(diag, vec![1.0, 4.0, 6.0]);
933 }
934
935 #[test]
936 fn test_triangular_mat_unit() {
937 let mut tri: TriangularMat<f64> = TriangularMat::unit_zeros(3, TriangularKind::Lower);
938
939 tri.set(1, 0, 2.0);
941 tri.set(2, 0, 3.0);
942 tri.set(2, 1, 4.0);
943
944 assert_eq!(tri.get(0, 0), None);
946 assert_eq!(tri.get(1, 1), None);
947 assert_eq!(tri.get(2, 2), None);
948
949 assert_eq!(tri.get(1, 0), Some(&2.0));
951 assert_eq!(tri.get(2, 0), Some(&3.0));
952 assert_eq!(tri.get(2, 1), Some(&4.0));
953
954 let diag = tri.diagonal();
956 assert_eq!(diag, vec![1.0, 1.0, 1.0]);
957
958 let dense = tri.to_dense();
960 assert_eq!(dense[(0, 0)], 1.0);
961 assert_eq!(dense[(1, 1)], 1.0);
962 assert_eq!(dense[(2, 2)], 1.0);
963 assert_eq!(dense[(1, 0)], 2.0);
964 assert_eq!(dense[(0, 1)], 0.0);
965 }
966
967 #[test]
968 fn test_triangular_mat_transpose() {
969 let mut tri: TriangularMat<f64> =
970 TriangularMat::zeros(3, TriangularKind::Upper, DiagonalKind::NonUnit);
971
972 tri.set(0, 0, 1.0);
973 tri.set(0, 1, 2.0);
974 tri.set(0, 2, 3.0);
975 tri.set(1, 1, 4.0);
976 tri.set(1, 2, 5.0);
977 tri.set(2, 2, 6.0);
978
979 let tri_t = tri.transpose();
980 assert_eq!(tri_t.uplo(), TriangularKind::Lower);
981
982 assert_eq!(tri_t.get(0, 0), Some(&1.0));
984 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));
987 assert_eq!(tri_t.get(2, 1), Some(&5.0)); assert_eq!(tri_t.get(2, 2), Some(&6.0));
989 }
990
991 #[test]
992 fn test_triangular_view_mut() {
993 let mut m: Mat<f64> = Mat::zeros(3, 3);
994 let mut view =
995 TriangularViewMut::new(m.as_mut(), TriangularKind::Upper, DiagonalKind::NonUnit);
996
997 view.set(0, 0, 1.0);
998 view.set(0, 1, 2.0);
999 view.set(1, 1, 3.0);
1000
1001 assert_eq!(view.get(0, 0), Some(&1.0));
1002 assert_eq!(view.get(0, 1), Some(&2.0));
1003 assert_eq!(view.get(1, 1), Some(&3.0));
1004
1005 view.zero_non_triangle();
1007 view.fill(5.0);
1011 assert_eq!(view.get(0, 0), Some(&5.0));
1012 assert_eq!(view.get(0, 1), Some(&5.0));
1013 }
1014
1015 #[test]
1016 fn test_triangular_from_dense() {
1017 let m = Mat::from_rows(&[&[1.0, 2.0, 3.0], &[4.0, 5.0, 6.0], &[7.0, 8.0, 9.0]]);
1018
1019 let tri =
1020 TriangularMat::from_dense(&m.as_ref(), TriangularKind::Upper, DiagonalKind::NonUnit);
1021
1022 assert_eq!(tri.get(0, 0), Some(&1.0));
1023 assert_eq!(tri.get(0, 1), Some(&2.0));
1024 assert_eq!(tri.get(0, 2), Some(&3.0));
1025 assert_eq!(tri.get(1, 1), Some(&5.0));
1026 assert_eq!(tri.get(1, 2), Some(&6.0));
1027 assert_eq!(tri.get(2, 2), Some(&9.0));
1028
1029 assert_eq!(tri.get(1, 0), None);
1031 assert_eq!(tri.get(2, 0), None);
1032 assert_eq!(tri.get(2, 1), None);
1033 }
1034
1035 #[test]
1036 fn test_triangular_ref_mut() {
1037 let mut data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0];
1038 let mut tmut =
1039 TriangularMut::from_slice(&mut data, 3, TriangularKind::Upper, DiagonalKind::NonUnit);
1040
1041 assert_eq!(tmut.get(0, 0), Some(&1.0));
1042 assert_eq!(tmut.get(0, 1), Some(&2.0));
1043
1044 tmut.set(0, 0, 10.0);
1045 assert_eq!(tmut.get(0, 0), Some(&10.0));
1046 assert_eq!(data[0], 10.0);
1047 }
1048}