nalgebra/base/
properties.rs1use approx::RelativeEq;
3use num::{One, Zero};
4
5use simba::scalar::{ClosedAddAssign, ClosedMulAssign, ComplexField, RealField};
6
7use crate::base::allocator::Allocator;
8use crate::base::dimension::{Dim, DimMin};
9use crate::base::storage::Storage;
10use crate::base::{DefaultAllocator, Matrix, SquareMatrix};
11use crate::RawStorage;
12
13impl<T, R: Dim, C: Dim, S: RawStorage<T, R, C>> Matrix<T, R, C, S> {
14 #[inline]
24 #[must_use]
25 pub fn len(&self) -> usize {
26 let (nrows, ncols) = self.shape();
27 nrows * ncols
28 }
29
30 #[inline]
40 #[must_use]
41 pub fn is_empty(&self) -> bool {
42 self.len() == 0
43 }
44
45 #[inline]
47 #[must_use]
48 pub fn is_square(&self) -> bool {
49 let (nrows, ncols) = self.shape();
50 nrows == ncols
51 }
52
53 #[inline]
59 #[must_use]
60 pub fn is_identity(&self, eps: T::Epsilon) -> bool
61 where
62 T: Zero + One + RelativeEq,
63 T::Epsilon: Clone,
64 {
65 let (nrows, ncols) = self.shape();
66
67 for j in 0..ncols {
68 for i in 0..nrows {
69 let el = unsafe { self.get_unchecked((i, j)) };
70 if (i == j && !relative_eq!(*el, T::one(), epsilon = eps.clone()))
71 || (i != j && !relative_eq!(*el, T::zero(), epsilon = eps.clone()))
72 {
73 return false;
74 }
75 }
76 }
77
78 true
79 }
80}
81
82impl<T: ComplexField, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
83 #[inline]
88 #[must_use]
89 pub fn is_orthogonal(&self, eps: T::Epsilon) -> bool
90 where
91 T: Zero + One + ClosedAddAssign + ClosedMulAssign + RelativeEq,
92 S: Storage<T, R, C>,
93 T::Epsilon: Clone,
94 DefaultAllocator: Allocator<R, C> + Allocator<C, C>,
95 {
96 (self.ad_mul(self)).is_identity(eps)
97 }
98}
99
100impl<T: RealField, D: Dim, S: Storage<T, D, D>> SquareMatrix<T, D, S>
101where
102 DefaultAllocator: Allocator<D, D>,
103{
104 #[inline]
106 #[must_use]
107 pub fn is_special_orthogonal(&self, eps: T) -> bool
108 where
109 D: DimMin<D, Output = D>,
110 DefaultAllocator: Allocator<D>,
111 {
112 self.is_square() && self.is_orthogonal(eps) && self.determinant() > T::zero()
113 }
114
115 #[inline]
117 #[must_use]
118 pub fn is_invertible(&self) -> bool {
119 self.clone_owned().try_inverse().is_some()
121 }
122}