1use crate::base::constraint::{AreMultipliable, DimEq, SameNumberOfRows, ShapeConstraint};
2use crate::base::{Const, Matrix, Unit, Vector};
3use crate::dimension::{Dim, U1};
4use crate::storage::{Storage, StorageMut};
5use simba::scalar::ComplexField;
6
7use crate::geometry::Point;
8
9pub struct Reflection<T, D, S> {
11 axis: Vector<T, D, S>,
12 bias: T,
13}
14
15impl<T: ComplexField, S: Storage<T, Const<D>>, const D: usize> Reflection<T, Const<D>, S> {
16 pub fn new_containing_point(axis: Unit<Vector<T, Const<D>, S>>, pt: &Point<T, D>) -> Self {
19 let bias = axis.dotc(&pt.coords);
20 Self::new(axis, bias)
21 }
22}
23
24impl<T: ComplexField, D: Dim, S: Storage<T, D>> Reflection<T, D, S> {
25 pub fn new(axis: Unit<Vector<T, D, S>>, bias: T) -> Self {
30 Self {
31 axis: axis.into_inner(),
32 bias,
33 }
34 }
35
36 #[must_use]
38 pub fn axis(&self) -> &Vector<T, D, S> {
39 &self.axis
40 }
41
42 #[must_use]
47 pub fn bias(&self) -> T {
48 self.bias.clone()
49 }
50
51 pub fn reflect<R2: Dim, C2: Dim, S2>(&self, rhs: &mut Matrix<T, R2, C2, S2>)
54 where
55 S2: StorageMut<T, R2, C2>,
56 ShapeConstraint: SameNumberOfRows<R2, D>,
57 {
58 for i in 0..rhs.ncols() {
59 let m_two: T = crate::convert(-2.0f64);
63 let factor = (self.axis.dotc(&rhs.column(i)) - self.bias.clone()) * m_two;
64 rhs.column_mut(i).axpy(factor, &self.axis, T::one());
65 }
66 }
67
68 pub fn reflect_with_sign<R2: Dim, C2: Dim, S2>(&self, rhs: &mut Matrix<T, R2, C2, S2>, sign: T)
71 where
72 S2: StorageMut<T, R2, C2>,
73 ShapeConstraint: SameNumberOfRows<R2, D>,
74 {
75 for i in 0..rhs.ncols() {
76 let m_two = sign.clone().scale(crate::convert(-2.0f64));
80 let factor = (self.axis.dotc(&rhs.column(i)) - self.bias.clone()) * m_two;
81 rhs.column_mut(i).axpy(factor, &self.axis, sign.clone());
82 }
83 }
84
85 pub fn reflect_rows<R2: Dim, C2: Dim, S2, S3>(
87 &self,
88 lhs: &mut Matrix<T, R2, C2, S2>,
89 work: &mut Vector<T, R2, S3>,
90 ) where
91 S2: StorageMut<T, R2, C2>,
92 S3: StorageMut<T, R2>,
93 ShapeConstraint: DimEq<C2, D> + AreMultipliable<R2, C2, D, U1>,
94 {
95 lhs.mul_to(&self.axis, work);
96
97 if !self.bias.is_zero() {
98 work.add_scalar_mut(-self.bias.clone());
99 }
100
101 let m_two: T = crate::convert(-2.0f64);
102 lhs.gerc(m_two, work, &self.axis, T::one());
103 }
104
105 pub fn reflect_rows_with_sign<R2: Dim, C2: Dim, S2, S3>(
107 &self,
108 lhs: &mut Matrix<T, R2, C2, S2>,
109 work: &mut Vector<T, R2, S3>,
110 sign: T,
111 ) where
112 S2: StorageMut<T, R2, C2>,
113 S3: StorageMut<T, R2>,
114 ShapeConstraint: DimEq<C2, D> + AreMultipliable<R2, C2, D, U1>,
115 {
116 lhs.mul_to(&self.axis, work);
117
118 if !self.bias.is_zero() {
119 work.add_scalar_mut(-self.bias.clone());
120 }
121
122 let m_two = sign.clone().scale(crate::convert(-2.0f64));
123 lhs.gerc(m_two, work, &self.axis, sign);
124 }
125}