1use super::*;
2use crate::internal_prelude::*;
3use crate::{Idx, IdxInc, TryReserveError, assert};
4use core::alloc::Layout;
5use dyn_stack::StackReq;
6use faer_traits::ComplexField;
7#[inline]
8pub(crate) fn align_for(size: usize, align: usize, needs_drop: bool) -> usize {
9 if needs_drop || !size.is_power_of_two() {
10 align
11 } else {
12 Ord::max(align, 64)
13 }
14}
15#[inline(never)]
16unsafe fn noalias_annotate<T, Rows: Shape, Cols: Shape>(
17 iter: &mut [core::mem::MaybeUninit<T>],
18 new_nrows: IdxInc<Rows>,
19 old_nrows: IdxInc<Rows>,
20 f: &mut impl FnMut(Idx<Rows>, Idx<Cols>) -> T,
21 j: Idx<Cols>,
22) {
23 let ptr = iter.as_mut_ptr();
24 let mut guard = DropCol {
25 ptr: ptr as *mut T,
26 nrows: 0,
27 };
28 for i in Rows::indices(old_nrows, new_nrows) {
29 let ptr = iter.as_mut_ptr().add(i.unbound()) as *mut T;
30 ptr.write((*f)(i, j));
31 guard.nrows += 1;
32 }
33 core::mem::forget(guard);
34}
35pub(crate) struct DropIter<I: Iterator>(pub I);
36impl<I: Iterator> Drop for DropIter<I> {
37 #[inline]
38 fn drop(&mut self) {
39 pub struct DropIterRetry<'a, I: Iterator>(pub &'a mut I);
40 impl<I: Iterator> Drop for DropIterRetry<'_, I> {
41 #[inline]
42 fn drop(&mut self) {
43 self.0.for_each(drop);
44 }
45 }
46 let in_case_of_panic = DropIterRetry(&mut self.0);
47 in_case_of_panic.0.for_each(drop);
48 core::mem::forget(in_case_of_panic);
49 }
50}
51extern crate alloc;
52struct RawMatUnit<T> {
53 ptr: NonNull<T>,
54 row_capacity: usize,
55 col_capacity: usize,
56 layout: StackReq,
57 __marker: PhantomData<T>,
58}
59struct RawMat<T> {
60 ptr: NonNull<T>,
61 row_capacity: usize,
62 col_capacity: usize,
63 layout: StackReq,
64 __marker: PhantomData<T>,
65}
66impl<T> RawMatUnit<T> {
67 fn try_with_capacity(
68 mut row_capacity: usize,
69 col_capacity: usize,
70 ) -> Result<Self, TryReserveError> {
71 let size = core::mem::size_of::<T>();
72 let prev_align = core::mem::align_of::<T>();
73 let align = align_for(size, prev_align, core::mem::needs_drop::<T>());
74 if align > size {
75 row_capacity = row_capacity
76 .msrv_checked_next_multiple_of(align / size)
77 .ok_or(TryReserveError::CapacityOverflow)?;
78 }
79 let size = size
80 .checked_mul(row_capacity)
81 .and_then(|size| size.checked_mul(col_capacity))
82 .ok_or(TryReserveError::CapacityOverflow)?;
83 let layout;
84 let ptr = if size == 0 {
85 layout = StackReq::empty();
86 core::ptr::null_mut::<u8>().wrapping_add(align)
87 } else {
88 let new_layout = Layout::from_size_align(size, align)
89 .map_err(|_| TryReserveError::CapacityOverflow)?;
90 layout = StackReq::new_aligned::<u8>(
91 new_layout.size(),
92 new_layout.align(),
93 );
94 let ptr = unsafe { alloc::alloc::alloc(new_layout) };
95 if ptr.is_null() {
96 return Err(TryReserveError::AllocError { layout: new_layout });
97 }
98 ptr
99 };
100 let ptr = ptr as *mut T;
101 Ok(Self {
102 ptr: unsafe { NonNull::new_unchecked(ptr) },
103 row_capacity,
104 col_capacity,
105 layout,
106 __marker: PhantomData,
107 })
108 }
109
110 fn into_raw_parts(self) -> (NonNull<T>, usize, usize, StackReq) {
111 let this = core::mem::ManuallyDrop::new(self);
112 (this.ptr, this.row_capacity, this.col_capacity, this.layout)
113 }
114}
115impl<T> Drop for RawMatUnit<T> {
116 #[inline]
117 fn drop(&mut self) {
118 if self.layout.size_bytes() > 0 {
119 unsafe {
120 alloc::alloc::dealloc(
121 self.ptr.as_ptr() as *mut u8,
122 Layout::from_size_align_unchecked(
123 self.layout.size_bytes(),
124 self.layout.align_bytes(),
125 ),
126 )
127 };
128 }
129 }
130}
131impl<T> RawMat<T> {
132 #[cold]
133 fn try_with_capacity(
134 row_capacity: usize,
135 col_capacity: usize,
136 ) -> Result<Self, TryReserveError> {
137 let mut err = None;
138 let alloc = {
139 let alloc =
140 RawMatUnit::<T>::try_with_capacity(row_capacity, col_capacity);
141 if let Err(alloc_err) = &alloc {
142 err = Some(*alloc_err);
143 }
144 alloc
145 };
146 if let Some(err) = err {
147 return Err(err);
148 }
149 let layout;
150 let row_capacity;
151 let ptr = {
152 let (ptr, new_row_capacity, _, unit_layout) =
153 alloc.unwrap().into_raw_parts();
154 row_capacity = new_row_capacity;
155 layout = unit_layout;
156 ptr
157 };
158 Ok(Self {
159 ptr,
160 row_capacity,
161 col_capacity,
162 layout,
163 __marker: PhantomData,
164 })
165 }
166
167 #[cold]
168 fn do_reserve_with(
169 &mut self,
170 nrows: usize,
171 ncols: usize,
172 new_row_capacity: usize,
173 new_col_capacity: usize,
174 ) -> Result<(), TryReserveError> {
175 let old_row_capacity = self.row_capacity;
176 let size = core::mem::size_of::<T>();
177 let new = Self::try_with_capacity(new_row_capacity, new_col_capacity)?;
178 let new_row_capacity = new.row_capacity;
179 unsafe fn move_mat(
180 mut new: *mut u8,
181 mut old: *const u8,
182 col_bytes: usize,
183 ncols: usize,
184 new_byte_stride: isize,
185 old_byte_stride: isize,
186 ) {
187 for _ in 0..ncols {
188 core::ptr::copy_nonoverlapping(old, new, col_bytes);
189 new = new.wrapping_offset(new_byte_stride);
190 old = old.wrapping_offset(old_byte_stride);
191 }
192 }
193 {
194 let new = new.ptr;
195 let old = self.ptr;
196 let new = new.as_ptr() as *mut u8;
197 let old = old.as_ptr() as *const u8;
198 unsafe {
199 move_mat(
200 new,
201 old,
202 nrows * size,
203 ncols,
204 (new_row_capacity * size) as isize,
205 (old_row_capacity * size) as isize,
206 )
207 };
208 };
209 *self = new;
210 Ok(())
211 }
212
213 fn try_reserve(
214 &mut self,
215 nrows: usize,
216 ncols: usize,
217 new_row_capacity: usize,
218 new_col_capacity: usize,
219 ) -> Result<(), TryReserveError> {
220 let new_row_capacity = Ord::max(new_row_capacity, nrows);
221 let new_col_capacity = Ord::max(new_col_capacity, ncols);
222 if new_row_capacity > self.row_capacity
223 || new_col_capacity > self.col_capacity
224 {
225 self.do_reserve_with(
226 nrows,
227 ncols,
228 new_row_capacity,
229 new_col_capacity,
230 )?
231 }
232 Ok(())
233 }
234}
235impl<T> Drop for RawMat<T> {
236 fn drop(&mut self) {
237 let ptr = self.ptr;
238 drop(RawMatUnit {
239 ptr,
240 row_capacity: self.row_capacity,
241 col_capacity: self.col_capacity,
242 layout: self.layout,
243 __marker: PhantomData,
244 });
245 }
246}
247pub struct Own<T, Rows: Shape = usize, Cols: Shape = usize> {
249 raw: RawMat<T>,
250 nrows: Rows,
251 ncols: Cols,
252}
253unsafe impl<T: Send, Rows: Shape, Cols: Shape> Send for Own<T, Rows, Cols> {}
254unsafe impl<T: Sync, Rows: Shape, Cols: Shape> Sync for Own<T, Rows, Cols> {}
255pub(crate) struct DropCol<T> {
256 ptr: *mut T,
257 nrows: usize,
258}
259pub(crate) struct DropMat<T> {
260 ptr: *mut T,
261 nrows: usize,
262 ncols: usize,
263 byte_col_stride: usize,
264}
265impl<T> Drop for DropCol<T> {
266 #[inline]
267 fn drop(&mut self) {
268 if const { core::mem::needs_drop::<T>() } {
269 unsafe {
270 let slice =
271 core::slice::from_raw_parts_mut(self.ptr, self.nrows);
272 core::ptr::drop_in_place(slice);
273 }
274 }
275 }
276}
277impl<T> Drop for DropMat<T> {
278 #[inline]
279 fn drop(&mut self) {
280 if const { core::mem::needs_drop::<T>() } {
281 let mut ptr = self.ptr;
282 if self.nrows > 0 {
283 DropIter((0..self.ncols).map(|_| {
284 DropCol {
285 ptr,
286 nrows: self.nrows,
287 };
288 ptr = ptr.wrapping_byte_add(self.byte_col_stride);
289 }));
290 }
291 }
292 }
293}
294impl<T, Rows: Shape, Cols: Shape> Drop for Own<T, Rows, Cols> {
295 #[inline]
296 fn drop(&mut self) {
297 if const { core::mem::needs_drop::<T>() } {
298 if self.nrows.unbound() > 0 && self.ncols.unbound() > 0 {
299 let size = core::mem::size_of::<T>();
300 let ptr = self.raw.ptr.as_ptr();
301 let row_capacity = self.raw.row_capacity;
302 let stride = row_capacity * size;
303 drop(DropMat {
304 ptr,
305 nrows: self.nrows.unbound(),
306 ncols: self.ncols.unbound(),
307 byte_col_stride: stride,
308 })
309 }
310 }
311 }
312}
313impl<T> Mat<T> {
314 #[inline]
316 pub const fn new() -> Self {
317 Self(Own {
318 raw: RawMat {
319 ptr: NonNull::dangling(),
320 row_capacity: 0,
321 col_capacity: 0,
322 layout: StackReq::EMPTY,
323 __marker: PhantomData,
324 },
325 nrows: 0,
326 ncols: 0,
327 })
328 }
329
330 #[track_caller]
334 pub fn with_capacity(row_capacity: usize, col_capacity: usize) -> Self {
335 let mut me = Self::new();
336 me.reserve(row_capacity, col_capacity);
337 me
338 }
339}
340impl<T, Rows: Shape, Cols: Shape> Mat<T, Rows, Cols> {
341 unsafe fn init_with(
342 ptr: *mut T,
343 old_nrows: IdxInc<Rows>,
344 old_ncols: IdxInc<Cols>,
345 new_nrows: IdxInc<Rows>,
346 new_ncols: IdxInc<Cols>,
347 row_capacity: usize,
348 f: &mut impl FnMut(Idx<Rows>, Idx<Cols>) -> T,
349 ) {
350 let stride = row_capacity;
351 let mut ptr = ptr.wrapping_add(stride * old_ncols.unbound());
352 let mut col_guard = DropMat {
353 ptr,
354 nrows: new_nrows.unbound() - old_nrows.unbound(),
355 ncols: 0,
356 byte_col_stride: stride,
357 };
358 for j in Cols::indices(old_ncols, new_ncols) {
359 let old = ptr;
360 noalias_annotate::<T, Rows, Cols>(
361 core::slice::from_raw_parts_mut(
362 ptr as *mut _,
363 new_nrows.unbound(),
364 ),
365 new_nrows,
366 old_nrows,
367 f,
368 j,
369 );
370 col_guard.ncols += 1;
371 ptr = old.wrapping_add(stride);
372 }
373 core::mem::forget(col_guard);
374 }
375
376 pub fn from_fn(
379 nrows: Rows,
380 ncols: Cols,
381 f: impl FnMut(Idx<Rows>, Idx<Cols>) -> T,
382 ) -> Self {
383 unsafe {
384 let raw = RawMat::<T>::try_with_capacity(
385 nrows.unbound(),
386 ncols.unbound(),
387 )
388 .unwrap();
389 let ptr = raw.ptr.as_ptr();
390 Self::init_with(
391 ptr,
392 Rows::start(),
393 Cols::start(),
394 nrows.end(),
395 ncols.end(),
396 raw.row_capacity,
397 &mut { f },
398 );
399 Self(Own { raw, nrows, ncols })
400 }
401 }
402
403 #[inline]
405 pub fn zeros(nrows: Rows, ncols: Cols) -> Self
406 where
407 T: ComplexField,
408 {
409 Self::from_fn(nrows, ncols, |_, _| T::zero_impl())
410 }
411
412 #[inline]
414 pub fn ones(nrows: Rows, ncols: Cols) -> Self
415 where
416 T: ComplexField,
417 {
418 Self::from_fn(nrows, ncols, |_, _| T::one_impl())
419 }
420
421 #[inline]
424 pub fn identity(nrows: Rows, ncols: Cols) -> Self
425 where
426 T: ComplexField,
427 {
428 Self::from_fn(nrows, ncols, |i, j| {
429 if i.unbound() == j.unbound() {
430 T::one_impl()
431 } else {
432 T::zero_impl()
433 }
434 })
435 }
436
437 #[inline]
440 pub fn full(nrows: Rows, ncols: Cols, value: T) -> Self
441 where
442 T: Clone,
443 {
444 Self::from_fn(nrows, ncols, |_, _| value.clone())
445 }
446
447 pub fn try_reserve(
451 &mut self,
452 new_row_capacity: usize,
453 new_col_capacity: usize,
454 ) -> Result<(), TryReserveError> {
455 self.0.raw.try_reserve(
456 self.0.nrows.unbound(),
457 self.0.ncols.unbound(),
458 new_row_capacity,
459 new_col_capacity,
460 )
461 }
462
463 #[track_caller]
467 pub fn reserve(
468 &mut self,
469 new_row_capacity: usize,
470 new_col_capacity: usize,
471 ) {
472 self.try_reserve(new_row_capacity, new_col_capacity)
473 .unwrap()
474 }
475
476 pub fn resize_with(
480 &mut self,
481 new_nrows: Rows,
482 new_ncols: Cols,
483 f: impl FnMut(Idx<Rows>, Idx<Cols>) -> T,
484 ) {
485 unsafe {
486 let this = &mut *self;
487 if new_nrows == this.0.nrows && new_ncols == this.0.ncols {
488 return;
489 }
490 this.truncate(new_nrows, new_ncols);
491 if new_nrows > this.0.nrows || new_ncols > this.0.ncols {
492 this.reserve(new_nrows.unbound(), new_ncols.unbound());
493 }
494 let mut f = f;
495 if new_nrows > this.0.nrows {
496 Self::init_with(
497 this.0.raw.ptr.as_ptr(),
498 this.0.nrows.end(),
499 Cols::start(),
500 new_nrows.end(),
501 this.0.ncols.end(),
502 this.0.raw.row_capacity,
503 &mut f,
504 );
505 this.0.nrows = new_nrows;
506 }
507 if new_ncols > this.0.ncols {
508 Self::init_with(
509 this.0.raw.ptr.as_ptr(),
510 Rows::start(),
511 this.0.ncols.end(),
512 new_nrows.end(),
513 new_ncols.end(),
514 this.0.raw.row_capacity,
515 &mut f,
516 );
517 this.0.ncols = new_ncols;
518 }
519 };
520 }
521
522 pub fn truncate(&mut self, new_nrows: Rows, new_ncols: Cols) {
531 if new_ncols < self.0.ncols {
532 let stride = self.0.raw.row_capacity;
533 drop(DropMat {
534 ptr: self
535 .0
536 .raw
537 .ptr
538 .as_ptr()
539 .wrapping_add(stride * new_ncols.unbound()),
540 nrows: self.0.nrows.unbound(),
541 ncols: self.0.ncols.unbound() - new_ncols.unbound(),
542 byte_col_stride: stride,
543 });
544 self.0.ncols = new_ncols;
545 }
546 if new_nrows < self.0.nrows {
547 let size = core::mem::size_of::<T>();
548 let stride = size * self.0.raw.row_capacity;
549 drop(DropMat {
550 ptr: self.0.raw.ptr.as_ptr().wrapping_add(new_nrows.unbound()),
551 nrows: self.0.nrows.unbound() - new_nrows.unbound(),
552 ncols: self.0.ncols.unbound(),
553 byte_col_stride: stride,
554 });
555 self.0.nrows = new_nrows;
556 }
557 }
558
559 #[track_caller]
561 pub fn into_shape<V: Shape, H: Shape>(
562 self,
563 nrows: V,
564 ncols: H,
565 ) -> Mat<T, V, H> {
566 assert!(all(
567 self.nrows().unbound() == nrows.unbound(),
568 self.ncols().unbound() == ncols.unbound()
569 ));
570 let this = core::mem::ManuallyDrop::new(self);
571 Mat {
572 0: Own {
573 raw: RawMat {
574 ptr: this.0.raw.ptr,
575 row_capacity: this.0.raw.row_capacity,
576 col_capacity: this.0.raw.col_capacity,
577 layout: this.0.raw.layout,
578 __marker: PhantomData,
579 },
580 nrows,
581 ncols,
582 },
583 }
584 }
585
586 pub unsafe fn set_dims(&mut self, nrows: Rows, ncols: Cols) {
597 self.0.nrows = nrows;
598 self.0.ncols = ncols;
599 }
600
601 pub fn col_as_slice(&self, j: Idx<Cols>) -> &[T] {
603 self.col(j).try_as_col_major().unwrap().as_slice()
604 }
605
606 pub fn col_as_slice_mut(&mut self, j: Idx<Cols>) -> &mut [T] {
608 self.col_mut(j)
609 .try_as_col_major_mut()
610 .unwrap()
611 .as_slice_mut()
612 }
613}
614impl<T, Rows: Shape, Cols: Shape> Mat<T, Rows, Cols> {
615 #[inline]
617 pub fn nrows(&self) -> Rows {
618 self.0.nrows
619 }
620
621 #[inline]
623 pub fn ncols(&self) -> Cols {
624 self.0.ncols
625 }
626}
627impl<T: Clone, Rows: Shape, Cols: Shape> Clone for Own<T, Rows, Cols> {
628 #[inline]
629 fn clone(&self) -> Self {
630 let __self__ = Mat::from_inner_ref(self);
631 with_dim!(M, __self__.nrows().unbound());
632 with_dim!(N, __self__.ncols().unbound());
633 let this = __self__.as_ref().as_shape(M, N);
634 Mat::from_fn(this.nrows(), this.ncols(), |i, j| this.at(i, j).clone())
635 .into_shape(__self__.nrows(), __self__.ncols())
636 .0
637 }
638}
639impl<T: core::fmt::Debug, Rows: Shape, Cols: Shape> core::fmt::Debug
640 for Own<T, Rows, Cols>
641{
642 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
643 self.rb().fmt(f)
644 }
645}
646impl<T, Rows: Shape, Cols: Shape> Mat<T, Rows, Cols> {
647 #[inline(always)]
649 pub fn as_ptr(&self) -> *const T {
650 self.as_ref().as_ptr()
651 }
652
653 #[inline(always)]
655 pub fn shape(&self) -> (Rows, Cols) {
656 (self.nrows(), self.ncols())
657 }
658
659 #[inline(always)]
662 pub fn row_stride(&self) -> isize {
663 1
664 }
665
666 #[inline(always)]
669 pub fn col_stride(&self) -> isize {
670 self.0.raw.row_capacity as isize
671 }
672
673 #[inline]
674 pub fn map<U>(&self, f: impl Fn(&T) -> U) -> Mat<U, Rows, Cols> {
675 self.rb().map(f)
676 }
677
678 #[inline]
679 pub fn for_each(&self, f: impl Fn(&T)) {
680 self.rb().for_each(f)
681 }
682
683 #[inline]
684 pub fn map_mut<U>(
685 &mut self,
686 f: impl FnMut(&mut T) -> U,
687 ) -> Mat<U, Rows, Cols> {
688 self.rb_mut().map_mut(f)
689 }
690
691 #[inline]
692 pub fn for_each_mut(&mut self, f: impl FnMut(&mut T)) {
693 self.rb_mut().for_each_mut(f)
694 }
695
696 #[inline(always)]
698 pub fn ptr_at(&self, row: IdxInc<Rows>, col: IdxInc<Cols>) -> *const T {
699 self.as_ref().ptr_at(row, col)
700 }
701
702 #[inline(always)]
711 #[track_caller]
712 pub unsafe fn ptr_inbounds_at(
713 &self,
714 row: Idx<Rows>,
715 col: Idx<Cols>,
716 ) -> *const T {
717 self.as_ref().ptr_inbounds_at(row, col)
718 }
719
720 #[inline]
721 #[track_caller]
722 pub fn split_at(
724 &self,
725 row: IdxInc<Rows>,
726 col: IdxInc<Cols>,
727 ) -> (
728 MatRef<'_, T, usize, usize>,
729 MatRef<'_, T, usize, usize>,
730 MatRef<'_, T, usize, usize>,
731 MatRef<'_, T, usize, usize>,
732 ) {
733 self.as_ref().split_at(row, col)
734 }
735
736 #[inline]
737 #[track_caller]
738 pub fn split_at_row(
740 &self,
741 row: IdxInc<Rows>,
742 ) -> (MatRef<'_, T, usize, Cols>, MatRef<'_, T, usize, Cols>) {
743 self.as_ref().split_at_row(row)
744 }
745
746 #[inline]
747 #[track_caller]
748 pub fn split_at_col(
750 &self,
751 col: IdxInc<Cols>,
752 ) -> (MatRef<'_, T, Rows, usize>, MatRef<'_, T, Rows, usize>) {
753 self.as_ref().split_at_col(col)
754 }
755
756 #[inline(always)]
757 pub fn transpose(&self) -> MatRef<'_, T, Cols, Rows> {
759 self.as_ref().transpose()
760 }
761
762 #[inline(always)]
763 pub fn conjugate(&self) -> MatRef<'_, T::Conj, Rows, Cols>
765 where
766 T: Conjugate,
767 {
768 self.as_ref().conjugate()
769 }
770
771 #[inline(always)]
772 pub fn canonical(&self) -> MatRef<'_, T::Canonical, Rows, Cols>
774 where
775 T: Conjugate,
776 {
777 self.as_ref().canonical()
778 }
779
780 #[inline(always)]
781 pub fn adjoint(&self) -> MatRef<'_, T::Conj, Cols, Rows>
783 where
784 T: Conjugate,
785 {
786 self.as_ref().adjoint()
787 }
788
789 #[inline]
790 pub fn reverse_rows(&self) -> MatRef<'_, T, Rows, Cols> {
792 self.as_ref().reverse_rows()
793 }
794
795 #[inline]
796 pub fn reverse_cols(&self) -> MatRef<'_, T, Rows, Cols> {
798 self.as_ref().reverse_cols()
799 }
800
801 #[inline]
802 pub fn reverse_rows_and_cols(&self) -> MatRef<'_, T, Rows, Cols> {
804 self.as_ref().reverse_rows_and_cols()
805 }
806
807 #[inline]
808 pub fn submatrix<V: Shape, H: Shape>(
810 &self,
811 row_start: IdxInc<Rows>,
812 col_start: IdxInc<Cols>,
813 nrows: V,
814 ncols: H,
815 ) -> MatRef<'_, T, V, H> {
816 self.as_ref().submatrix(row_start, col_start, nrows, ncols)
817 }
818
819 #[inline]
820 pub fn subrows<V: Shape>(
822 &self,
823 row_start: IdxInc<Rows>,
824 nrows: V,
825 ) -> MatRef<'_, T, V, Cols> {
826 self.as_ref().subrows(row_start, nrows)
827 }
828
829 #[inline]
830 pub fn subcols<H: Shape>(
832 &self,
833 col_start: IdxInc<Cols>,
834 ncols: H,
835 ) -> MatRef<'_, T, Rows, H> {
836 self.as_ref().subcols(col_start, ncols)
837 }
838
839 #[inline]
840 pub fn as_shape<V: Shape, H: Shape>(
842 &self,
843 nrows: V,
844 ncols: H,
845 ) -> MatRef<'_, T, V, H> {
846 self.as_ref().as_shape(nrows, ncols)
847 }
848
849 #[inline]
850 pub fn as_row_shape<V: Shape>(&self, nrows: V) -> MatRef<'_, T, V, Cols> {
852 self.as_ref().as_row_shape(nrows)
853 }
854
855 #[inline]
856 pub fn as_col_shape<H: Shape>(&self, ncols: H) -> MatRef<'_, T, Rows, H> {
858 self.as_ref().as_col_shape(ncols)
859 }
860
861 #[inline]
862 pub fn as_dyn_stride(&self) -> MatRef<'_, T, Rows, Cols, isize, isize> {
864 self.as_ref().as_dyn_stride()
865 }
866
867 #[inline]
868 pub fn as_dyn(&self) -> MatRef<'_, T, usize, usize> {
870 self.as_ref().as_dyn()
871 }
872
873 #[inline]
874 pub fn as_dyn_rows(&self) -> MatRef<'_, T, usize, Cols> {
876 self.as_ref().as_dyn_rows()
877 }
878
879 #[inline]
880 pub fn as_dyn_cols(&self) -> MatRef<'_, T, Rows, usize> {
882 self.as_ref().as_dyn_cols()
883 }
884
885 #[inline]
886 pub fn row(&self, i: Idx<Rows>) -> RowRef<'_, T, Cols> {
888 self.as_ref().row(i)
889 }
890
891 #[inline]
892 #[track_caller]
893 pub fn col(&self, j: Idx<Cols>) -> ColRef<'_, T, Rows> {
895 self.as_ref().col(j)
896 }
897
898 #[inline]
899 pub fn col_iter(
901 &self,
902 ) -> impl '_ + ExactSizeIterator + DoubleEndedIterator<Item = ColRef<'_, T, Rows>>
903 {
904 self.as_ref().col_iter()
905 }
906
907 #[inline]
908 pub fn row_iter(
910 &self,
911 ) -> impl '_ + ExactSizeIterator + DoubleEndedIterator<Item = RowRef<'_, T, Cols>>
912 {
913 self.as_ref().row_iter()
914 }
915
916 #[inline]
917 #[track_caller]
918 #[cfg(feature = "rayon")]
919 pub fn par_col_iter(
921 &self,
922 ) -> impl '_ + rayon::iter::IndexedParallelIterator<Item = ColRef<'_, T, Rows>>
923 where
924 T: Sync,
925 {
926 self.as_ref().par_col_iter()
927 }
928
929 #[inline]
930 #[track_caller]
931 #[cfg(feature = "rayon")]
932 pub fn par_row_iter(
934 &self,
935 ) -> impl '_ + rayon::iter::IndexedParallelIterator<Item = RowRef<'_, T, Cols>>
936 where
937 T: Sync,
938 {
939 self.as_ref().par_row_iter()
940 }
941
942 #[inline]
943 #[track_caller]
944 #[cfg(feature = "rayon")]
945 pub fn par_col_chunks(
947 &self,
948 chunk_size: usize,
949 ) -> impl '_
950 + rayon::iter::IndexedParallelIterator<
951 Item = MatRef<'_, T, Rows, usize>,
952 >
953 where
954 T: Sync,
955 {
956 self.as_ref().par_col_chunks(chunk_size)
957 }
958
959 #[inline]
960 #[track_caller]
961 #[cfg(feature = "rayon")]
962 pub fn par_col_partition(
964 &self,
965 count: usize,
966 ) -> impl '_
967 + rayon::iter::IndexedParallelIterator<
968 Item = MatRef<'_, T, Rows, usize>,
969 >
970 where
971 T: Sync,
972 {
973 self.as_ref().par_col_partition(count)
974 }
975
976 #[inline]
977 #[track_caller]
978 #[cfg(feature = "rayon")]
979 pub fn par_row_chunks(
981 &self,
982 chunk_size: usize,
983 ) -> impl '_
984 + rayon::iter::IndexedParallelIterator<
985 Item = MatRef<'_, T, usize, Cols>,
986 >
987 where
988 T: Sync,
989 {
990 self.as_ref().par_row_chunks(chunk_size)
991 }
992
993 #[inline]
994 #[track_caller]
995 #[cfg(feature = "rayon")]
996 pub fn par_row_partition(
998 &self,
999 count: usize,
1000 ) -> impl '_
1001 + rayon::iter::IndexedParallelIterator<
1002 Item = MatRef<'_, T, usize, Cols>,
1003 >
1004 where
1005 T: Sync,
1006 {
1007 self.as_ref().par_row_partition(count)
1008 }
1009
1010 #[inline]
1011 pub fn try_as_col_major(
1013 &self,
1014 ) -> Option<MatRef<'_, T, Rows, Cols, ContiguousFwd>> {
1015 self.as_ref().try_as_col_major()
1016 }
1017
1018 #[inline]
1019 pub fn try_as_row_major(
1021 &self,
1022 ) -> Option<MatRef<'_, T, Rows, Cols, isize, ContiguousFwd>> {
1023 self.as_ref().try_as_row_major()
1024 }
1025
1026 #[track_caller]
1027 #[inline]
1028 pub fn get<RowRange, ColRange>(
1030 &self,
1031 row: RowRange,
1032 col: ColRange,
1033 ) -> <MatRef<'_, T, Rows, Cols> as MatIndex<RowRange, ColRange>>::Target
1034 where
1035 for<'a> MatRef<'a, T, Rows, Cols>: MatIndex<RowRange, ColRange>,
1036 {
1037 <MatRef<'_, T, Rows, Cols> as MatIndex<RowRange, ColRange>>::get(
1038 self.as_ref(),
1039 row,
1040 col,
1041 )
1042 }
1043
1044 #[track_caller]
1045 #[inline]
1046 pub unsafe fn get_unchecked<RowRange, ColRange>(
1048 &self,
1049 row: RowRange,
1050 col: ColRange,
1051 ) -> <MatRef<'_, T, Rows, Cols> as MatIndex<RowRange, ColRange>>::Target
1052 where
1053 for<'a> MatRef<'a, T, Rows, Cols>: MatIndex<RowRange, ColRange>,
1054 {
1055 unsafe {
1056 <MatRef<'_, T, Rows, Cols> as MatIndex<RowRange, ColRange>>::get_unchecked(self.as_ref(), row, col)
1057 }
1058 }
1059
1060 #[track_caller]
1061 #[inline]
1062 pub fn get_mut<RowRange, ColRange>(
1064 &mut self,
1065 row: RowRange,
1066 col: ColRange,
1067 ) -> <MatMut<'_, T, Rows, Cols> as MatIndex<RowRange, ColRange>>::Target
1068 where
1069 for<'a> MatMut<'a, T, Rows, Cols>: MatIndex<RowRange, ColRange>,
1070 {
1071 <MatMut<'_, T, Rows, Cols> as MatIndex<RowRange, ColRange>>::get(
1072 self.as_mut(),
1073 row,
1074 col,
1075 )
1076 }
1077
1078 #[track_caller]
1079 #[inline]
1080 pub unsafe fn get_mut_unchecked<RowRange, ColRange>(
1082 &mut self,
1083 row: RowRange,
1084 col: ColRange,
1085 ) -> <MatMut<'_, T, Rows, Cols> as MatIndex<RowRange, ColRange>>::Target
1086 where
1087 for<'a> MatMut<'a, T, Rows, Cols>: MatIndex<RowRange, ColRange>,
1088 {
1089 unsafe {
1090 <MatMut<'_, T, Rows, Cols> as MatIndex<RowRange, ColRange>>::get_unchecked(self.as_mut(), row, col)
1091 }
1092 }
1093}
1094impl<T, Rows: Shape, Cols: Shape> Mat<T, Rows, Cols> {
1095 #[inline(always)]
1096 pub fn as_ptr_mut(&mut self) -> *mut T {
1098 self.as_mut().as_ptr_mut()
1099 }
1100
1101 #[inline(always)]
1102 pub fn ptr_at_mut(
1104 &mut self,
1105 row: IdxInc<Rows>,
1106 col: IdxInc<Cols>,
1107 ) -> *mut T {
1108 self.as_mut().ptr_at_mut(row, col)
1109 }
1110
1111 #[inline(always)]
1112 #[track_caller]
1113 pub unsafe fn ptr_inbounds_at_mut(
1122 &mut self,
1123 row: Idx<Rows>,
1124 col: Idx<Cols>,
1125 ) -> *mut T {
1126 self.as_mut().ptr_inbounds_at_mut(row, col)
1127 }
1128
1129 #[inline]
1130 #[track_caller]
1131 pub fn split_at_mut(
1133 &mut self,
1134 row: IdxInc<Rows>,
1135 col: IdxInc<Cols>,
1136 ) -> (
1137 MatMut<'_, T, usize, usize>,
1138 MatMut<'_, T, usize, usize>,
1139 MatMut<'_, T, usize, usize>,
1140 MatMut<'_, T, usize, usize>,
1141 ) {
1142 self.as_mut().split_at_mut(row, col)
1143 }
1144
1145 #[inline]
1146 #[track_caller]
1147 pub fn split_at_row_mut(
1149 &mut self,
1150 row: IdxInc<Rows>,
1151 ) -> (MatMut<'_, T, usize, Cols>, MatMut<'_, T, usize, Cols>) {
1152 self.as_mut().split_at_row_mut(row)
1153 }
1154
1155 #[inline]
1156 #[track_caller]
1157 pub fn split_at_col_mut(
1159 &mut self,
1160 col: IdxInc<Cols>,
1161 ) -> (MatMut<'_, T, Rows, usize>, MatMut<'_, T, Rows, usize>) {
1162 self.as_mut().split_at_col_mut(col)
1163 }
1164
1165 #[inline(always)]
1166 pub fn transpose_mut(&mut self) -> MatMut<'_, T, Cols, Rows> {
1168 self.as_mut().transpose_mut()
1169 }
1170
1171 #[inline(always)]
1172 pub fn conjugate_mut(&mut self) -> MatMut<'_, T::Conj, Rows, Cols>
1174 where
1175 T: Conjugate,
1176 {
1177 self.as_mut().conjugate_mut()
1178 }
1179
1180 #[inline(always)]
1181 pub fn canonical_mut(&mut self) -> MatMut<'_, T::Canonical, Rows, Cols>
1183 where
1184 T: Conjugate,
1185 {
1186 self.as_mut().canonical_mut()
1187 }
1188
1189 #[inline(always)]
1190 pub fn adjoint_mut(&mut self) -> MatMut<'_, T::Conj, Cols, Rows>
1192 where
1193 T: Conjugate,
1194 {
1195 self.as_mut().adjoint_mut()
1196 }
1197
1198 #[inline]
1199 pub fn reverse_rows_mut(&mut self) -> MatMut<'_, T, Rows, Cols> {
1201 self.as_mut().reverse_rows_mut()
1202 }
1203
1204 #[inline]
1205 pub fn reverse_cols_mut(&mut self) -> MatMut<'_, T, Rows, Cols> {
1207 self.as_mut().reverse_cols_mut()
1208 }
1209
1210 #[inline]
1211 pub fn reverse_rows_and_cols_mut(&mut self) -> MatMut<'_, T, Rows, Cols> {
1213 self.as_mut().reverse_rows_and_cols_mut()
1214 }
1215
1216 #[inline]
1217 pub fn submatrix_mut<V: Shape, H: Shape>(
1219 &mut self,
1220 row_start: IdxInc<Rows>,
1221 col_start: IdxInc<Cols>,
1222 nrows: V,
1223 ncols: H,
1224 ) -> MatMut<'_, T, V, H> {
1225 self.as_mut()
1226 .submatrix_mut(row_start, col_start, nrows, ncols)
1227 }
1228
1229 #[inline]
1230 pub fn subrows_mut<V: Shape>(
1232 &mut self,
1233 row_start: IdxInc<Rows>,
1234 nrows: V,
1235 ) -> MatMut<'_, T, V, Cols> {
1236 self.as_mut().subrows_mut(row_start, nrows)
1237 }
1238
1239 #[inline]
1240 pub fn subcols_mut<H: Shape>(
1242 &mut self,
1243 col_start: IdxInc<Cols>,
1244 ncols: H,
1245 ) -> MatMut<'_, T, Rows, H> {
1246 self.as_mut().subcols_mut(col_start, ncols)
1247 }
1248
1249 #[inline]
1250 #[track_caller]
1251 pub fn as_shape_mut<V: Shape, H: Shape>(
1253 &mut self,
1254 nrows: V,
1255 ncols: H,
1256 ) -> MatMut<'_, T, V, H> {
1257 self.as_mut().as_shape_mut(nrows, ncols)
1258 }
1259
1260 #[inline]
1261 pub fn as_row_shape_mut<V: Shape>(
1263 &mut self,
1264 nrows: V,
1265 ) -> MatMut<'_, T, V, Cols> {
1266 self.as_mut().as_row_shape_mut(nrows)
1267 }
1268
1269 #[inline]
1270 pub fn as_col_shape_mut<H: Shape>(
1272 &mut self,
1273 ncols: H,
1274 ) -> MatMut<'_, T, Rows, H> {
1275 self.as_mut().as_col_shape_mut(ncols)
1276 }
1277
1278 #[inline]
1279 pub fn as_dyn_stride_mut(
1281 &mut self,
1282 ) -> MatMut<'_, T, Rows, Cols, isize, isize> {
1283 self.as_mut().as_dyn_stride_mut()
1284 }
1285
1286 #[inline]
1287 pub fn as_dyn_mut(&mut self) -> MatMut<'_, T, usize, usize> {
1289 self.as_mut().as_dyn_mut()
1290 }
1291
1292 #[inline]
1293 pub fn as_dyn_rows_mut(&mut self) -> MatMut<'_, T, usize, Cols> {
1295 self.as_mut().as_dyn_rows_mut()
1296 }
1297
1298 #[inline]
1299 pub fn as_dyn_cols_mut(&mut self) -> MatMut<'_, T, Rows, usize> {
1301 self.as_mut().as_dyn_cols_mut()
1302 }
1303
1304 #[inline]
1305 pub fn row_mut(&mut self, i: Idx<Rows>) -> RowMut<'_, T, Cols> {
1307 self.as_mut().row_mut(i)
1308 }
1309
1310 #[inline]
1311 pub fn col_mut(&mut self, j: Idx<Cols>) -> ColMut<'_, T, Rows> {
1313 self.as_mut().col_mut(j)
1314 }
1315
1316 #[inline]
1317 pub fn col_iter_mut(
1319 &mut self,
1320 ) -> impl '_ + ExactSizeIterator + DoubleEndedIterator<Item = ColMut<'_, T, Rows>>
1321 {
1322 self.as_mut().col_iter_mut()
1323 }
1324
1325 #[inline]
1326 pub fn row_iter_mut(
1328 &mut self,
1329 ) -> impl '_ + ExactSizeIterator + DoubleEndedIterator<Item = RowMut<'_, T, Cols>>
1330 {
1331 self.as_mut().row_iter_mut()
1332 }
1333
1334 #[inline]
1335 #[track_caller]
1336 #[cfg(feature = "rayon")]
1337 pub fn par_col_iter_mut(
1339 &mut self,
1340 ) -> impl '_ + rayon::iter::IndexedParallelIterator<Item = ColMut<'_, T, Rows>>
1341 where
1342 T: Send,
1343 {
1344 self.as_mut().par_col_iter_mut()
1345 }
1346
1347 #[inline]
1348 #[track_caller]
1349 #[cfg(feature = "rayon")]
1350 pub fn par_row_iter_mut(
1352 &mut self,
1353 ) -> impl '_ + rayon::iter::IndexedParallelIterator<Item = RowMut<'_, T, Cols>>
1354 where
1355 T: Send,
1356 {
1357 self.as_mut().par_row_iter_mut()
1358 }
1359
1360 #[inline]
1361 #[track_caller]
1362 #[cfg(feature = "rayon")]
1363 pub fn par_col_chunks_mut(
1365 &mut self,
1366 chunk_size: usize,
1367 ) -> impl '_
1368 + rayon::iter::IndexedParallelIterator<
1369 Item = MatMut<'_, T, Rows, usize>,
1370 >
1371 where
1372 T: Send,
1373 {
1374 self.as_mut().par_col_chunks_mut(chunk_size)
1375 }
1376
1377 #[inline]
1378 #[track_caller]
1379 #[cfg(feature = "rayon")]
1380 pub fn par_col_partition_mut(
1382 &mut self,
1383 count: usize,
1384 ) -> impl '_
1385 + rayon::iter::IndexedParallelIterator<
1386 Item = MatMut<'_, T, Rows, usize>,
1387 >
1388 where
1389 T: Send,
1390 {
1391 self.as_mut().par_col_partition_mut(count)
1392 }
1393
1394 #[inline]
1395 #[track_caller]
1396 #[cfg(feature = "rayon")]
1397 pub fn par_row_chunks_mut(
1399 &mut self,
1400 chunk_size: usize,
1401 ) -> impl '_
1402 + rayon::iter::IndexedParallelIterator<
1403 Item = MatMut<'_, T, usize, Cols>,
1404 >
1405 where
1406 T: Send,
1407 {
1408 self.as_mut().par_row_chunks_mut(chunk_size)
1409 }
1410
1411 #[inline]
1412 #[track_caller]
1413 #[cfg(feature = "rayon")]
1414 pub fn par_row_partition_mut(
1416 &mut self,
1417 count: usize,
1418 ) -> impl '_
1419 + rayon::iter::IndexedParallelIterator<
1420 Item = MatMut<'_, T, usize, Cols>,
1421 >
1422 where
1423 T: Send,
1424 {
1425 self.as_mut().par_row_partition_mut(count)
1426 }
1427
1428 #[inline]
1429 pub fn split_first_row_mut(
1431 &mut self,
1432 ) -> Option<(RowMut<'_, T, Cols>, MatMut<'_, T, usize, Cols>)> {
1433 self.as_mut().split_first_row_mut()
1434 }
1435
1436 #[inline]
1437 pub fn try_as_col_major_mut(
1439 &mut self,
1440 ) -> Option<MatMut<'_, T, Rows, Cols, ContiguousFwd>> {
1441 self.as_mut().try_as_col_major_mut()
1442 }
1443
1444 #[inline]
1445 pub fn try_as_row_major_mut(
1447 &mut self,
1448 ) -> Option<MatMut<'_, T, Rows, Cols, isize, ContiguousFwd>> {
1449 self.as_mut().try_as_row_major_mut()
1450 }
1451
1452 #[inline]
1453 #[track_caller]
1454 pub fn two_cols_mut(
1456 &mut self,
1457 i0: Idx<Cols>,
1458 i1: Idx<Cols>,
1459 ) -> (ColMut<'_, T, Rows>, ColMut<'_, T, Rows>) {
1460 self.as_mut().two_cols_mut(i0, i1)
1461 }
1462
1463 #[inline]
1464 #[track_caller]
1465 pub fn two_rows_mut(
1467 &mut self,
1468 i0: Idx<Rows>,
1469 i1: Idx<Rows>,
1470 ) -> (RowMut<'_, T, Cols>, RowMut<'_, T, Cols>) {
1471 self.as_mut().two_rows_mut(i0, i1)
1472 }
1473}
1474impl<T, Dim: Shape> Mat<T, Dim, Dim> {
1475 #[inline]
1476 pub fn diagonal(&self) -> DiagRef<'_, T, Dim, isize> {
1478 self.as_ref().diagonal()
1479 }
1480
1481 #[inline]
1482 pub fn diagonal_mut(&mut self) -> DiagMut<'_, T, Dim, isize> {
1484 self.as_mut().diagonal_mut()
1485 }
1486}
1487impl<'short, T, Rows: Shape, Cols: Shape> Reborrow<'short>
1488 for Own<T, Rows, Cols>
1489{
1490 type Target = Ref<'short, T, Rows, Cols>;
1491
1492 #[inline]
1493 fn rb(&'short self) -> Self::Target {
1494 Ref {
1495 imp: MatView {
1496 ptr: self.raw.ptr,
1497 nrows: self.nrows,
1498 ncols: self.ncols,
1499 row_stride: 1,
1500 col_stride: self.raw.row_capacity as isize,
1501 },
1502 __marker: PhantomData,
1503 }
1504 }
1505}
1506impl<'short, T, Rows: Shape, Cols: Shape> ReborrowMut<'short>
1507 for Own<T, Rows, Cols>
1508{
1509 type Target = Mut<'short, T, Rows, Cols>;
1510
1511 #[inline]
1512 fn rb_mut(&'short mut self) -> Self::Target {
1513 Mut {
1514 imp: MatView {
1515 ptr: self.raw.ptr,
1516 nrows: self.nrows,
1517 ncols: self.ncols,
1518 row_stride: 1,
1519 col_stride: self.raw.row_capacity as isize,
1520 },
1521 __marker: PhantomData,
1522 }
1523 }
1524}
1525impl<T, Cols: Shape> Mat<T, usize, Cols> {
1526 pub fn push_row(&mut self, row: RowRef<'_, T, Cols>)
1531 where
1532 T: Clone,
1533 {
1534 self::assert!(
1535 self.ncols() == row.ncols(),
1536 "row ncols ({:?}) must match matrix ncols ({:?})",
1537 row.ncols(),
1538 self.ncols()
1539 );
1540 self.resize_with(self.nrows() + 1, self.ncols(), |_, j| row[j].clone());
1541 }
1542}
1543impl<T, Rows: Shape> Mat<T, Rows, usize> {
1544 pub fn push_col(&mut self, col: ColRef<'_, T, Rows>)
1549 where
1550 T: Clone,
1551 {
1552 self::assert!(
1553 self.nrows() == col.nrows(),
1554 "col nrows ({:?}) must match matrix nrows ({:?})",
1555 col.nrows(),
1556 self.nrows()
1557 );
1558 self.resize_with(self.nrows(), self.ncols() + 1, |i, _| col[i].clone());
1559 }
1560}
1561impl<T, Rows: Shape, Cols: Shape> Mat<T, Rows, Cols>
1562where
1563 T: RealField,
1564{
1565 pub fn min(self) -> Option<T> {
1567 MatRef::internal_min(self.as_dyn())
1568 }
1569
1570 pub fn max(self) -> Option<T> {
1572 MatRef::internal_max(self.as_dyn())
1573 }
1574}
1575#[cfg(test)]
1576mod tests {
1577 use super::Mat;
1578 use crate::assert;
1579 #[test]
1580 fn test_resize() {
1581 let mut m = mat![
1582 [1.0, 2.0, 3.0],
1583 [4.0, 5.0, 6.0],
1584 [7.0, 8.0, 9.0],
1585 [10.0, 11.0, 12.0],
1586 ];
1587 m.resize_with(m.nrows() + 1, m.ncols(), |_, _| 99.9);
1588 let target = mat![
1589 [1.0, 2.0, 3.0],
1590 [4.0, 5.0, 6.0],
1591 [7.0, 8.0, 9.0],
1592 [10.0, 11.0, 12.0],
1593 [99.9, 99.9, 99.9],
1594 ];
1595 assert!(m == target);
1596 }
1597 #[test]
1598 fn test_resize_5() {
1599 let mut m = mat![
1600 [1.0, 2.0, 3.0],
1601 [4.0, 5.0, 6.0],
1602 [7.0, 8.0, 9.0],
1603 [10.0, 11.0, 12.0],
1604 ];
1605 m.resize_with(m.nrows() + 5, m.ncols(), |_, _| 99.9);
1606 let target = mat![
1607 [1.0, 2.0, 3.0],
1608 [4.0, 5.0, 6.0],
1609 [7.0, 8.0, 9.0],
1610 [10.0, 11.0, 12.0],
1611 [99.9, 99.9, 99.9],
1612 [99.9, 99.9, 99.9],
1613 [99.9, 99.9, 99.9],
1614 [99.9, 99.9, 99.9],
1615 [99.9, 99.9, 99.9],
1616 ];
1617 assert!(m == target);
1618 }
1619 #[test]
1620 fn test_resize_5_1() {
1621 let mut m = mat![
1622 [1.0, 2.0, 3.0],
1623 [4.0, 5.0, 6.0],
1624 [7.0, 8.0, 9.0],
1625 [10.0, 11.0, 12.0],
1626 ];
1627 m.resize_with(m.nrows() + 5, m.ncols() + 1, |_, _| 99.9);
1628 let target = mat![
1629 [1.0, 2.0, 3.0, 99.9],
1630 [4.0, 5.0, 6.0, 99.9],
1631 [7.0, 8.0, 9.0, 99.9],
1632 [10.0, 11.0, 12.0, 99.9],
1633 [99.9, 99.9, 99.9, 99.9],
1634 [99.9, 99.9, 99.9, 99.9],
1635 [99.9, 99.9, 99.9, 99.9],
1636 [99.9, 99.9, 99.9, 99.9],
1637 [99.9, 99.9, 99.9, 99.9],
1638 ];
1639 assert!(m == target);
1640 }
1641 #[test]
1642 fn test_push_row() {
1643 let mut m = mat![[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0],];
1644 let row = row![10.0, 11.0, 12.0];
1645 m.push_row(row.as_ref());
1646 let target = mat![
1647 [1.0, 2.0, 3.0],
1648 [4.0, 5.0, 6.0],
1649 [7.0, 8.0, 9.0],
1650 [10.0, 11.0, 12.0],
1651 ];
1652 assert!(m == target);
1653 }
1654 #[test]
1655 #[should_panic]
1656 fn test_push_row_panic() {
1657 let mut m = mat![[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0],];
1658 let row = row![10.0, 11.0, 12.0, 13.0];
1659 m.push_row(row.as_ref());
1660 }
1661 #[test]
1662 fn test_push_col() {
1663 let mut m = mat![[1.0, 2.0, 3.0], [1.0, 2.0, 3.0], [1.0, 2.0, 3.0],];
1664 let col = col![4.0, 4.0, 4.0];
1665 m.push_col(col.as_ref());
1666 let target = mat![
1667 [1.0, 2.0, 3.0, 4.0],
1668 [1.0, 2.0, 3.0, 4.0],
1669 [1.0, 2.0, 3.0, 4.0],
1670 ];
1671 assert!(m == target);
1672 }
1673 #[test]
1674 #[should_panic]
1675 fn test_push_col_panic() {
1676 let mut m = mat![[1.0, 2.0, 3.0], [1.0, 2.0, 3.0], [1.0, 2.0, 3.0],];
1677 let col = col![4.0, 4.0, 4.0, 4.0];
1678 m.push_col(col.as_ref());
1679 }
1680 #[test]
1681 fn test_min() {
1682 use crate::Mat;
1683 let m = mat![[1.0, 5.0, 3.0], [4.0, 2.0, 9.0], [7.0, 8.0, 6.0],];
1684 assert_eq!(m.min(), Some(1.0));
1685 let empty: Mat<f64> = Mat::new();
1686 assert_eq!(empty.min(), None);
1687 }
1688 #[test]
1689 fn test_max() {
1690 use crate::Mat;
1691 let m = mat![[1.0, 5.0, 3.0], [4.0, 2.0, 9.0], [7.0, 8.0, 6.0],];
1692 assert_eq!(m.max(), Some(9.0));
1693 let empty: Mat<f64> = Mat::new();
1694 assert_eq!(empty.max(), None);
1695 }
1696
1697 #[test]
1698 fn test_drop() {
1699 use core::cell::Cell;
1700 const M: usize = 5;
1701 const N: usize = 7;
1702
1703 #[derive(Clone)]
1704 struct PanicOnDrop<'a> {
1705 counter: &'a Cell<usize>,
1706 }
1707
1708 impl Drop for PanicOnDrop<'_> {
1709 fn drop(&mut self) {
1710 self.counter.set(self.counter.get() + 1);
1711 if self.counter.get() == M * (N / 2) {
1712 panic!();
1713 }
1714 }
1715 }
1716
1717 let counter = &Cell::new(0);
1718 std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
1719 drop(Mat::full(M, N, PanicOnDrop { counter }))
1720 }))
1721 .unwrap_err();
1722 assert!(counter.get() == M * N + 1);
1724 }
1725}