1#[cfg(all(feature = "alloc", not(feature = "std")))]
2use alloc::vec::Vec;
3
4use num::Zero;
5use std::ops::Neg;
6
7use crate::allocator::Allocator;
8use crate::base::{DefaultAllocator, Dim, DimName, Matrix, Normed, OMatrix, OVector};
9use crate::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint};
10use crate::storage::{Storage, StorageMut};
11use crate::{ComplexField, Scalar, SimdComplexField, Unit};
12use simba::scalar::ClosedNeg;
13use simba::simd::{SimdOption, SimdPartialOrd, SimdValue};
14
15pub trait Norm<T: SimdComplexField> {
20 fn norm<R, C, S>(&self, m: &Matrix<T, R, C, S>) -> T::SimdRealField
22 where
23 R: Dim,
24 C: Dim,
25 S: Storage<T, R, C>;
26 fn metric_distance<R1, C1, S1, R2, C2, S2>(
28 &self,
29 m1: &Matrix<T, R1, C1, S1>,
30 m2: &Matrix<T, R2, C2, S2>,
31 ) -> T::SimdRealField
32 where
33 R1: Dim,
34 C1: Dim,
35 S1: Storage<T, R1, C1>,
36 R2: Dim,
37 C2: Dim,
38 S2: Storage<T, R2, C2>,
39 ShapeConstraint: SameNumberOfRows<R1, R2> + SameNumberOfColumns<C1, C2>;
40}
41
42#[derive(Copy, Clone, Debug)]
50pub struct EuclideanNorm;
51
52#[derive(Copy, Clone, Debug)]
60pub struct LpNorm(pub i32);
61
62#[derive(Copy, Clone, Debug)]
69pub struct OneNorm;
70
71#[derive(Copy, Clone, Debug)]
81pub struct UniformNorm;
82
83impl<T: SimdComplexField> Norm<T> for EuclideanNorm {
84 #[inline]
85 fn norm<R, C, S>(&self, m: &Matrix<T, R, C, S>) -> T::SimdRealField
86 where
87 R: Dim,
88 C: Dim,
89 S: Storage<T, R, C>,
90 {
91 m.norm_squared().simd_sqrt()
92 }
93
94 #[inline]
95 fn metric_distance<R1, C1, S1, R2, C2, S2>(
96 &self,
97 m1: &Matrix<T, R1, C1, S1>,
98 m2: &Matrix<T, R2, C2, S2>,
99 ) -> T::SimdRealField
100 where
101 R1: Dim,
102 C1: Dim,
103 S1: Storage<T, R1, C1>,
104 R2: Dim,
105 C2: Dim,
106 S2: Storage<T, R2, C2>,
107 ShapeConstraint: SameNumberOfRows<R1, R2> + SameNumberOfColumns<C1, C2>,
108 {
109 m1.zip_fold(m2, T::SimdRealField::zero(), |acc, a, b| {
110 let diff = a - b;
111 acc + diff.simd_modulus_squared()
112 })
113 .simd_sqrt()
114 }
115}
116
117impl<T: SimdComplexField> Norm<T> for LpNorm {
118 #[inline]
119 fn norm<R, C, S>(&self, m: &Matrix<T, R, C, S>) -> T::SimdRealField
120 where
121 R: Dim,
122 C: Dim,
123 S: Storage<T, R, C>,
124 {
125 m.fold(T::SimdRealField::zero(), |a, b| {
126 a + b.simd_modulus().simd_powi(self.0)
127 })
128 .simd_powf(crate::convert(1.0 / (self.0 as f64)))
129 }
130
131 #[inline]
132 fn metric_distance<R1, C1, S1, R2, C2, S2>(
133 &self,
134 m1: &Matrix<T, R1, C1, S1>,
135 m2: &Matrix<T, R2, C2, S2>,
136 ) -> T::SimdRealField
137 where
138 R1: Dim,
139 C1: Dim,
140 S1: Storage<T, R1, C1>,
141 R2: Dim,
142 C2: Dim,
143 S2: Storage<T, R2, C2>,
144 ShapeConstraint: SameNumberOfRows<R1, R2> + SameNumberOfColumns<C1, C2>,
145 {
146 m1.zip_fold(m2, T::SimdRealField::zero(), |acc, a, b| {
147 let diff = a - b;
148 acc + diff.simd_modulus().simd_powi(self.0)
149 })
150 .simd_powf(crate::convert(1.0 / (self.0 as f64)))
151 }
152}
153
154impl<T: SimdComplexField> Norm<T> for OneNorm {
155 #[inline]
156 fn norm<R, C, S>(&self, m: &Matrix<T, R, C, S>) -> T::SimdRealField
157 where
158 R: Dim,
159 C: Dim,
160 S: Storage<T, R, C>,
161 {
162 m.column_iter()
163 .map(|col| col.fold(T::SimdRealField::zero(), |a, b| a + b.simd_modulus()))
164 .fold(T::SimdRealField::zero(), T::SimdRealField::simd_max)
165 }
166
167 #[inline]
168 fn metric_distance<R1, C1, S1, R2, C2, S2>(
169 &self,
170 m1: &Matrix<T, R1, C1, S1>,
171 m2: &Matrix<T, R2, C2, S2>,
172 ) -> T::SimdRealField
173 where
174 R1: Dim,
175 C1: Dim,
176 S1: Storage<T, R1, C1>,
177 R2: Dim,
178 C2: Dim,
179 S2: Storage<T, R2, C2>,
180 ShapeConstraint: SameNumberOfRows<R1, R2> + SameNumberOfColumns<C1, C2>,
181 {
182 m1.column_iter()
183 .zip(m2.column_iter())
184 .map(|(c1, c2)| {
185 c1.zip_fold(&c2, T::SimdRealField::zero(), |acc, a, b| {
186 acc + (a - b).simd_modulus()
187 })
188 })
189 .fold(T::SimdRealField::zero(), T::SimdRealField::simd_max)
190 }
191}
192
193impl<T: SimdComplexField> Norm<T> for UniformNorm {
194 #[inline]
195 fn norm<R, C, S>(&self, m: &Matrix<T, R, C, S>) -> T::SimdRealField
196 where
197 R: Dim,
198 C: Dim,
199 S: Storage<T, R, C>,
200 {
201 m.fold(T::SimdRealField::zero(), |acc, a| {
204 acc.simd_max(a.simd_modulus())
205 })
206 }
207
208 #[inline]
209 fn metric_distance<R1, C1, S1, R2, C2, S2>(
210 &self,
211 m1: &Matrix<T, R1, C1, S1>,
212 m2: &Matrix<T, R2, C2, S2>,
213 ) -> T::SimdRealField
214 where
215 R1: Dim,
216 C1: Dim,
217 S1: Storage<T, R1, C1>,
218 R2: Dim,
219 C2: Dim,
220 S2: Storage<T, R2, C2>,
221 ShapeConstraint: SameNumberOfRows<R1, R2> + SameNumberOfColumns<C1, C2>,
222 {
223 m1.zip_fold(m2, T::SimdRealField::zero(), |acc, a, b| {
224 let val = (a - b).simd_modulus();
225 acc.simd_max(val)
226 })
227 }
228}
229
230impl<T: Scalar, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
235 #[inline]
237 #[must_use]
238 pub fn norm_squared(&self) -> T::SimdRealField
239 where
240 T: SimdComplexField,
241 {
242 let mut res = T::SimdRealField::zero();
243
244 for i in 0..self.ncols() {
245 let col = self.column(i);
246 res += col.dotc(&col).simd_real()
247 }
248
249 res
250 }
251
252 #[inline]
256 #[must_use]
257 pub fn norm(&self) -> T::SimdRealField
258 where
259 T: SimdComplexField,
260 {
261 self.norm_squared().simd_sqrt()
262 }
263
264 #[inline]
268 #[must_use]
269 pub fn metric_distance<R2, C2, S2>(&self, rhs: &Matrix<T, R2, C2, S2>) -> T::SimdRealField
270 where
271 T: SimdComplexField,
272 R2: Dim,
273 C2: Dim,
274 S2: Storage<T, R2, C2>,
275 ShapeConstraint: SameNumberOfRows<R, R2> + SameNumberOfColumns<C, C2>,
276 {
277 self.apply_metric_distance(rhs, &EuclideanNorm)
278 }
279
280 #[inline]
293 #[must_use]
294 pub fn apply_norm(&self, norm: &impl Norm<T>) -> T::SimdRealField
295 where
296 T: SimdComplexField,
297 {
298 norm.norm(self)
299 }
300
301 #[inline]
316 #[must_use]
317 pub fn apply_metric_distance<R2, C2, S2>(
318 &self,
319 rhs: &Matrix<T, R2, C2, S2>,
320 norm: &impl Norm<T>,
321 ) -> T::SimdRealField
322 where
323 T: SimdComplexField,
324 R2: Dim,
325 C2: Dim,
326 S2: Storage<T, R2, C2>,
327 ShapeConstraint: SameNumberOfRows<R, R2> + SameNumberOfColumns<C, C2>,
328 {
329 norm.metric_distance(self, rhs)
330 }
331
332 #[inline]
338 #[must_use]
339 pub fn magnitude(&self) -> T::SimdRealField
340 where
341 T: SimdComplexField,
342 {
343 self.norm()
344 }
345
346 #[inline]
352 #[must_use]
353 pub fn magnitude_squared(&self) -> T::SimdRealField
354 where
355 T: SimdComplexField,
356 {
357 self.norm_squared()
358 }
359
360 #[inline]
362 pub fn set_magnitude(&mut self, magnitude: T::SimdRealField)
363 where
364 T: SimdComplexField,
365 S: StorageMut<T, R, C>,
366 {
367 let n = self.norm();
368 self.scale_mut(magnitude / n)
369 }
370
371 #[inline]
373 #[must_use = "Did you mean to use normalize_mut()?"]
374 pub fn normalize(&self) -> OMatrix<T, R, C>
375 where
376 T: SimdComplexField,
377 DefaultAllocator: Allocator<R, C>,
378 {
379 self.unscale(self.norm())
380 }
381
382 #[inline]
390 #[must_use]
391 pub fn lp_norm(&self, p: i32) -> T::SimdRealField
392 where
393 T: SimdComplexField,
394 {
395 self.apply_norm(&LpNorm(p))
396 }
397
398 #[inline]
405 #[must_use]
406 pub fn one_norm(&self) -> T::SimdRealField
407 where
408 T: SimdComplexField,
409 {
410 self.apply_norm(&OneNorm)
411 }
412
413 #[inline]
417 #[must_use = "Did you mean to use simd_try_normalize_mut()?"]
418 pub fn simd_try_normalize(&self, min_norm: T::SimdRealField) -> SimdOption<OMatrix<T, R, C>>
419 where
420 T: SimdComplexField,
421 T::Element: Scalar,
422 DefaultAllocator: Allocator<R, C>,
423 {
424 let n = self.norm();
425 let le = n.clone().simd_le(min_norm);
426 let val = self.unscale(n);
427 SimdOption::new(val, le)
428 }
429
430 #[inline]
435 pub fn try_set_magnitude(&mut self, magnitude: T::RealField, min_magnitude: T::RealField)
436 where
437 T: ComplexField,
438 S: StorageMut<T, R, C>,
439 {
440 let n = self.norm();
441
442 if n > min_magnitude {
443 self.scale_mut(magnitude / n)
444 }
445 }
446
447 #[inline]
449 #[must_use]
450 pub fn cap_magnitude(&self, max: T::RealField) -> OMatrix<T, R, C>
451 where
452 T: ComplexField,
453 DefaultAllocator: Allocator<R, C>,
454 {
455 let n = self.norm();
456
457 if n > max {
458 self.scale(max / n)
459 } else {
460 self.clone_owned()
461 }
462 }
463
464 #[inline]
466 #[must_use]
467 pub fn simd_cap_magnitude(&self, max: T::SimdRealField) -> OMatrix<T, R, C>
468 where
469 T: SimdComplexField,
470 T::Element: Scalar,
471 DefaultAllocator: Allocator<R, C>,
472 {
473 let n = self.norm();
474 let scaled = self.scale(max.clone() / n.clone());
475 let use_scaled = n.simd_gt(max);
476 scaled.select(use_scaled, self.clone_owned())
477 }
478
479 #[inline]
483 #[must_use = "Did you mean to use try_normalize_mut()?"]
484 pub fn try_normalize(&self, min_norm: T::RealField) -> Option<OMatrix<T, R, C>>
485 where
486 T: ComplexField,
487 DefaultAllocator: Allocator<R, C>,
488 {
489 let n = self.norm();
490
491 if n <= min_norm {
492 None
493 } else {
494 Some(self.unscale(n))
495 }
496 }
497}
498
499impl<T: Scalar, R: Dim, C: Dim, S: StorageMut<T, R, C>> Matrix<T, R, C, S> {
501 #[inline]
505 pub fn normalize_mut(&mut self) -> T::SimdRealField
506 where
507 T: SimdComplexField,
508 {
509 let n = self.norm();
510 self.unscale_mut(n.clone());
511
512 n
513 }
514
515 #[inline]
519 #[must_use = "Did you mean to use simd_try_normalize_mut()?"]
520 pub fn simd_try_normalize_mut(
521 &mut self,
522 min_norm: T::SimdRealField,
523 ) -> SimdOption<T::SimdRealField>
524 where
525 T: SimdComplexField,
526 T::Element: Scalar,
527 DefaultAllocator: Allocator<R, C>,
528 {
529 let n = self.norm();
530 let le = n.clone().simd_le(min_norm);
531 self.apply(|e| *e = e.clone().simd_unscale(n.clone()).select(le, e.clone()));
532 SimdOption::new(n, le)
533 }
534
535 #[inline]
539 pub fn try_normalize_mut(&mut self, min_norm: T::RealField) -> Option<T::RealField>
540 where
541 T: ComplexField,
542 {
543 let n = self.norm();
544
545 if n <= min_norm {
546 None
547 } else {
548 self.unscale_mut(n.clone());
549 Some(n)
550 }
551 }
552}
553
554impl<T: SimdComplexField, R: Dim, C: Dim> Normed for OMatrix<T, R, C>
555where
556 DefaultAllocator: Allocator<R, C>,
557{
558 type Norm = T::SimdRealField;
559
560 #[inline]
561 fn norm(&self) -> T::SimdRealField {
562 self.norm()
563 }
564
565 #[inline]
566 fn norm_squared(&self) -> T::SimdRealField {
567 self.norm_squared()
568 }
569
570 #[inline]
571 fn scale_mut(&mut self, n: Self::Norm) {
572 self.scale_mut(n)
573 }
574
575 #[inline]
576 fn unscale_mut(&mut self, n: Self::Norm) {
577 self.unscale_mut(n)
578 }
579}
580
581impl<T: Scalar + ClosedNeg, R: Dim, C: Dim> Neg for Unit<OMatrix<T, R, C>>
582where
583 DefaultAllocator: Allocator<R, C>,
584{
585 type Output = Unit<OMatrix<T, R, C>>;
586
587 #[inline]
588 fn neg(self) -> Self::Output {
589 Unit::new_unchecked(-self.value)
590 }
591}
592
593impl<T: ComplexField, D: DimName> OVector<T, D>
599where
600 DefaultAllocator: Allocator<D>,
601{
602 #[inline]
604 fn canonical_basis_element(i: usize) -> Self {
605 let mut res = Self::zero();
606 res[i] = T::one();
607 res
608 }
609
610 #[inline]
614 pub fn orthonormalize(vs: &mut [Self]) -> usize {
615 let mut nbasis_elements = 0;
616
617 for i in 0..vs.len() {
618 {
619 let (elt, basis) = vs[..i + 1].split_last_mut().unwrap();
620
621 for basis_element in &basis[..nbasis_elements] {
622 *elt -= basis_element * elt.dot(basis_element)
623 }
624 }
625
626 if vs[i].try_normalize_mut(T::RealField::zero()).is_some() {
627 vs.swap(nbasis_elements, i);
630 nbasis_elements += 1;
631
632 if nbasis_elements == D::DIM {
634 break;
635 }
636 }
637 }
638
639 nbasis_elements
640 }
641
642 #[inline]
647 pub fn orthonormal_subspace_basis<F>(vs: &[Self], mut f: F)
648 where
649 F: FnMut(&Self) -> bool,
650 {
651 assert!(
653 vs.len() <= D::DIM,
654 "The given set of vectors has no chance of being a free family."
655 );
656
657 match D::DIM {
658 1 => {
659 if vs.is_empty() {
660 let _ = f(&Self::canonical_basis_element(0));
661 }
662 }
663 2 => {
664 if vs.is_empty() {
665 let _ = f(&Self::canonical_basis_element(0))
666 && f(&Self::canonical_basis_element(1));
667 } else if vs.len() == 1 {
668 let v = &vs[0];
669 let res = Self::from_column_slice(&[-v[1].clone(), v[0].clone()]);
670
671 let _ = f(&res.normalize());
672 }
673
674 }
676 3 => {
677 if vs.is_empty() {
678 let _ = f(&Self::canonical_basis_element(0))
679 && f(&Self::canonical_basis_element(1))
680 && f(&Self::canonical_basis_element(2));
681 } else if vs.len() == 1 {
682 let v = &vs[0];
683 let mut a;
684
685 if v[0].clone().norm1() > v[1].clone().norm1() {
686 a = Self::from_column_slice(&[v[2].clone(), T::zero(), -v[0].clone()]);
687 } else {
688 a = Self::from_column_slice(&[T::zero(), -v[2].clone(), v[1].clone()]);
689 };
690
691 let _ = a.normalize_mut();
692
693 if f(&a.cross(v)) {
694 let _ = f(&a);
695 }
696 } else if vs.len() == 2 {
697 let _ = f(&vs[0].cross(&vs[1]).normalize());
698 }
699 }
700 _ => {
701 #[cfg(any(feature = "std", feature = "alloc"))]
702 {
703 let mut known_basis = Vec::new();
705
706 for v in vs.iter() {
707 known_basis.push(v.normalize())
708 }
709
710 for i in 0..D::DIM - vs.len() {
711 let mut elt = Self::canonical_basis_element(i);
712
713 for v in &known_basis {
714 elt -= v * elt.dot(v)
715 }
716
717 if let Some(subsp_elt) = elt.try_normalize(T::RealField::zero()) {
718 if !f(&subsp_elt) {
719 return;
720 };
721
722 known_basis.push(subsp_elt);
723 }
724 }
725 }
726 #[cfg(all(not(feature = "std"), not(feature = "alloc")))]
727 {
728 panic!(
729 "Cannot compute the orthogonal subspace basis of a vector with a dimension greater than 3 \
730 if #![no_std] is enabled and the 'alloc' feature is not enabled."
731 )
732 }
733 }
734 }
735 }
736}