1use std::fmt;
2use std::ops::Deref;
3
4#[cfg(feature = "serde-serialize-no-std")]
5use serde::{Deserialize, Deserializer, Serialize, Serializer};
6
7use crate::allocator::Allocator;
8use crate::base::DefaultAllocator;
9use crate::storage::RawStorage;
10use crate::{Dim, Matrix, OMatrix, RealField, Scalar, SimdComplexField, SimdRealField};
11
12#[cfg(feature = "rkyv-serialize")]
13use rkyv::bytecheck;
14
15#[repr(transparent)]
26#[derive(Clone, Hash, Copy)]
27#[cfg_attr(
28 feature = "rkyv-serialize-no-std",
29 derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize),
30 archive(
31 as = "Unit<T::Archived>",
32 bound(archive = "
33 T: rkyv::Archive,
34 ")
35 )
36)]
37#[cfg_attr(feature = "rkyv-serialize", derive(bytecheck::CheckBytes))]
38pub struct Unit<T> {
39 pub(crate) value: T,
40}
41
42impl<T: fmt::Debug> fmt::Debug for Unit<T> {
43 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
44 self.value.fmt(formatter)
45 }
46}
47
48#[cfg(feature = "bytemuck")]
49unsafe impl<T> bytemuck::Zeroable for Unit<T> where T: bytemuck::Zeroable {}
50
51#[cfg(feature = "bytemuck")]
52unsafe impl<T> bytemuck::Pod for Unit<T> where T: bytemuck::Pod {}
53
54#[cfg(feature = "serde-serialize-no-std")]
55impl<T: Serialize> Serialize for Unit<T> {
56 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
57 where
58 S: Serializer,
59 {
60 self.value.serialize(serializer)
61 }
62}
63
64#[cfg(feature = "serde-serialize-no-std")]
65impl<'de, T: Deserialize<'de>> Deserialize<'de> for Unit<T> {
66 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
67 where
68 D: Deserializer<'de>,
69 {
70 T::deserialize(deserializer).map(|x| Unit { value: x })
71 }
72}
73
74impl<T, R, C, S> PartialEq for Unit<Matrix<T, R, C, S>>
75where
76 T: Scalar + PartialEq,
77 R: Dim,
78 C: Dim,
79 S: RawStorage<T, R, C>,
80{
81 #[inline]
82 fn eq(&self, rhs: &Self) -> bool {
83 self.value.eq(&rhs.value)
84 }
85}
86
87impl<T, R, C, S> Eq for Unit<Matrix<T, R, C, S>>
88where
89 T: Scalar + Eq,
90 R: Dim,
91 C: Dim,
92 S: RawStorage<T, R, C>,
93{
94}
95
96pub trait Normed {
98 type Norm: SimdRealField;
100 fn norm(&self) -> Self::Norm;
102 fn norm_squared(&self) -> Self::Norm;
104 fn scale_mut(&mut self, n: Self::Norm);
106 fn unscale_mut(&mut self, n: Self::Norm);
108}
109
110impl<T: Normed> Unit<T> {
112 #[inline]
114 pub fn new_normalize(value: T) -> Self {
115 Self::new_and_get(value).0
116 }
117
118 #[inline]
122 pub fn try_new(value: T, min_norm: T::Norm) -> Option<Self>
123 where
124 T::Norm: RealField,
125 {
126 Self::try_new_and_get(value, min_norm).map(|res| res.0)
127 }
128
129 #[inline]
131 pub fn new_and_get(mut value: T) -> (Self, T::Norm) {
132 let n = value.norm();
133 value.unscale_mut(n.clone());
134 (Unit { value }, n)
135 }
136
137 #[inline]
141 pub fn try_new_and_get(mut value: T, min_norm: T::Norm) -> Option<(Self, T::Norm)>
142 where
143 T::Norm: RealField,
144 {
145 let sq_norm = value.norm_squared();
146
147 if sq_norm > min_norm.clone() * min_norm {
148 let n = sq_norm.simd_sqrt();
149 value.unscale_mut(n.clone());
150 Some((Unit { value }, n))
151 } else {
152 None
153 }
154 }
155
156 #[inline]
162 pub fn renormalize(&mut self) -> T::Norm {
163 let n = self.norm();
164 self.value.unscale_mut(n.clone());
165 n
166 }
167
168 #[inline]
172 pub fn renormalize_fast(&mut self) {
173 let sq_norm = self.value.norm_squared();
174 let three: T::Norm = crate::convert(3.0);
175 let half: T::Norm = crate::convert(0.5);
176 self.value.scale_mut(half * (three - sq_norm));
177 }
178}
179
180impl<T> Unit<T> {
182 #[inline]
184 pub const fn new_unchecked(value: T) -> Self {
185 Unit { value }
186 }
187
188 #[inline]
190 pub fn from_ref_unchecked(value: &T) -> &Self {
191 unsafe { &*(value as *const T as *const Self) }
192 }
193
194 #[inline]
196 pub fn into_inner(self) -> T {
197 self.value
198 }
199
200 #[deprecated(note = "use `.into_inner()` instead")]
203 #[inline]
204 pub fn unwrap(self) -> T {
205 self.value
206 }
207
208 #[inline]
212 pub fn as_mut_unchecked(&mut self) -> &mut T {
213 &mut self.value
214 }
215}
216
217impl<T> AsRef<T> for Unit<T> {
218 #[inline]
219 fn as_ref(&self) -> &T {
220 &self.value
221 }
222}
223
224impl<T> Deref for Unit<T> {
290 type Target = T;
291
292 #[inline]
293 fn deref(&self) -> &T {
294 unsafe { &*(self as *const Self as *const T) }
295 }
296}
297
298impl<T: Scalar + simba::simd::PrimitiveSimdValue, R: Dim, C: Dim>
302 From<[Unit<OMatrix<T::Element, R, C>>; 2]> for Unit<OMatrix<T, R, C>>
303where
304 T: From<[<T as simba::simd::SimdValue>::Element; 2]>,
305 T::Element: Scalar,
306 DefaultAllocator: Allocator<R, C>,
307{
308 #[inline]
309 fn from(arr: [Unit<OMatrix<T::Element, R, C>>; 2]) -> Self {
310 Self::new_unchecked(OMatrix::from([
311 arr[0].clone().into_inner(),
312 arr[1].clone().into_inner(),
313 ]))
314 }
315}
316
317impl<T: Scalar + simba::simd::PrimitiveSimdValue, R: Dim, C: Dim>
318 From<[Unit<OMatrix<T::Element, R, C>>; 4]> for Unit<OMatrix<T, R, C>>
319where
320 T: From<[<T as simba::simd::SimdValue>::Element; 4]>,
321 T::Element: Scalar,
322 DefaultAllocator: Allocator<R, C>,
323{
324 #[inline]
325 fn from(arr: [Unit<OMatrix<T::Element, R, C>>; 4]) -> Self {
326 Self::new_unchecked(OMatrix::from([
327 arr[0].clone().into_inner(),
328 arr[1].clone().into_inner(),
329 arr[2].clone().into_inner(),
330 arr[3].clone().into_inner(),
331 ]))
332 }
333}
334
335impl<T: Scalar + simba::simd::PrimitiveSimdValue, R: Dim, C: Dim>
336 From<[Unit<OMatrix<T::Element, R, C>>; 8]> for Unit<OMatrix<T, R, C>>
337where
338 T: From<[<T as simba::simd::SimdValue>::Element; 8]>,
339 T::Element: Scalar,
340 DefaultAllocator: Allocator<R, C>,
341{
342 #[inline]
343 fn from(arr: [Unit<OMatrix<T::Element, R, C>>; 8]) -> Self {
344 Self::new_unchecked(OMatrix::from([
345 arr[0].clone().into_inner(),
346 arr[1].clone().into_inner(),
347 arr[2].clone().into_inner(),
348 arr[3].clone().into_inner(),
349 arr[4].clone().into_inner(),
350 arr[5].clone().into_inner(),
351 arr[6].clone().into_inner(),
352 arr[7].clone().into_inner(),
353 ]))
354 }
355}
356
357impl<T: Scalar + simba::simd::PrimitiveSimdValue, R: Dim, C: Dim>
358 From<[Unit<OMatrix<T::Element, R, C>>; 16]> for Unit<OMatrix<T, R, C>>
359where
360 T: From<[<T as simba::simd::SimdValue>::Element; 16]>,
361 T::Element: Scalar,
362 DefaultAllocator: Allocator<R, C>,
363{
364 #[inline]
365 fn from(arr: [Unit<OMatrix<T::Element, R, C>>; 16]) -> Self {
366 Self::new_unchecked(OMatrix::from([
367 arr[0].clone().into_inner(),
368 arr[1].clone().into_inner(),
369 arr[2].clone().into_inner(),
370 arr[3].clone().into_inner(),
371 arr[4].clone().into_inner(),
372 arr[5].clone().into_inner(),
373 arr[6].clone().into_inner(),
374 arr[7].clone().into_inner(),
375 arr[8].clone().into_inner(),
376 arr[9].clone().into_inner(),
377 arr[10].clone().into_inner(),
378 arr[11].clone().into_inner(),
379 arr[12].clone().into_inner(),
380 arr[13].clone().into_inner(),
381 arr[14].clone().into_inner(),
382 arr[15].clone().into_inner(),
383 ]))
384 }
385}