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