nalgebra/base/
unit.rs

1// Needed otherwise the rkyv macros generate code incompatible with rust-2024
2#![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/// A wrapper that ensures the underlying algebraic entity has a unit norm.
19///
20/// **It is likely that the only piece of documentation that you need in this page are:**
21/// - **[The construction with normalization](#construction-with-normalization)**
22/// - **[Data extraction and construction without normalization](#data-extraction-and-construction-without-normalization)**
23/// - **[Interpolation between two unit vectors](#interpolation-between-two-unit-vectors)**
24///
25/// All the other impl blocks you will see in this page are about [`UnitComplex`](crate::UnitComplex)
26/// and [`UnitQuaternion`](crate::UnitQuaternion); both built on top of `Unit`.  If you are interested
27/// in their documentation, read their dedicated pages directly.
28#[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
100/// Trait implemented by entities scan be be normalized and put in an `Unit` struct.
101pub trait Normed {
102    /// The type of the norm.
103    type Norm: SimdRealField;
104    /// Computes the norm.
105    fn norm(&self) -> Self::Norm;
106    /// Computes the squared norm.
107    fn norm_squared(&self) -> Self::Norm;
108    /// Multiply `self` by n.
109    fn scale_mut(&mut self, n: Self::Norm);
110    /// Divides `self` by n.
111    fn unscale_mut(&mut self, n: Self::Norm);
112}
113
114/// # Construction with normalization
115impl<T: Normed> Unit<T> {
116    /// Normalize the given vector and return it wrapped on a `Unit` structure.
117    #[inline]
118    pub fn new_normalize(value: T) -> Self {
119        Self::new_and_get(value).0
120    }
121
122    /// Attempts to normalize the given vector and return it wrapped on a `Unit` structure.
123    ///
124    /// Returns `None` if the norm was smaller or equal to `min_norm`.
125    #[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    /// Normalize the given vector and return it wrapped on a `Unit` structure and its norm.
134    #[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    /// Normalize the given vector and return it wrapped on a `Unit` structure and its norm.
142    ///
143    /// Returns `None` if the norm was smaller or equal to `min_norm`.
144    #[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    /// Normalizes this vector again. This is useful when repeated computations
161    /// might cause a drift in the norm because of float inaccuracies.
162    ///
163    /// Returns the norm before re-normalization. See `.renormalize_fast` for a faster alternative
164    /// that may be slightly less accurate if `self` drifted significantly from having a unit length.
165    #[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    /// Normalizes this vector again using a first-order Taylor approximation.
173    /// This is useful when repeated computations might cause a drift in the norm
174    /// because of float inaccuracies.
175    #[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
184/// # Data extraction and construction without normalization
185impl<T> Unit<T> {
186    /// Wraps the given value, assuming it is already normalized.
187    #[inline]
188    pub const fn new_unchecked(value: T) -> Self {
189        Unit { value }
190    }
191
192    /// Wraps the given reference, assuming it is already normalized.
193    #[inline]
194    pub const fn from_ref_unchecked(value: &T) -> &Self {
195        unsafe { &*(value as *const T as *const Self) }
196    }
197
198    /// Retrieves the underlying value.
199    #[inline]
200    pub fn into_inner(self) -> T {
201        self.value
202    }
203
204    /// Retrieves the underlying value.
205    /// Deprecated: use [`Unit::into_inner`] instead.
206    #[deprecated(note = "use `.into_inner()` instead")]
207    #[inline]
208    pub fn unwrap(self) -> T {
209        self.value
210    }
211
212    /// Returns a mutable reference to the underlying value. This is `_unchecked` because modifying
213    /// the underlying value in such a way that it no longer has unit length may lead to unexpected
214    /// results.
215    #[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
228/*
229/*
230 *
231 * Conversions.
232 *
233 */
234impl<T: NormedSpace> SubsetOf<T> for Unit<T>
235where T::RealField: RelativeEq
236{
237    #[inline]
238    fn to_superset(&self) -> T {
239        self.clone().into_inner()
240    }
241
242    #[inline]
243    fn is_in_subset(value: &T) -> bool {
244        relative_eq!(value.norm_squared(), crate::one())
245    }
246
247    #[inline]
248    fn from_superset_unchecked(value: &T) -> Self {
249        Unit::new_normalize(value.clone()) // We still need to re-normalize because the condition is inexact.
250    }
251}
252
253// impl<T: RelativeEq> RelativeEq for Unit<T> {
254//     type Epsilon = T::Epsilon;
255//
256//     #[inline]
257//     fn default_epsilon() -> Self::Epsilon {
258//         T::default_epsilon()
259//     }
260//
261//     #[inline]
262//     fn default_max_relative() -> Self::Epsilon {
263//         T::default_max_relative()
264//     }
265//
266//     #[inline]
267//     fn default_max_ulps() -> u32 {
268//         T::default_max_ulps()
269//     }
270//
271//     #[inline]
272//     fn relative_eq(&self, other: &Self, epsilon: Self::Epsilon, max_relative: Self::Epsilon) -> bool {
273//         self.value.relative_eq(&other.value, epsilon, max_relative)
274//     }
275//
276//     #[inline]
277//     fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
278//         self.value.ulps_eq(&other.value, epsilon, max_ulps)
279//     }
280// }
281*/
282// TODO:re-enable this impl when specialization is possible.
283// Currently, it is disabled so that we can have a nice output for the `UnitQuaternion` display.
284/*
285impl<T: fmt::Display> fmt::Display for Unit<T> {
286    // XXX: will not always work correctly due to rounding errors.
287    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
288        self.value.fmt(f)
289    }
290}
291*/
292
293impl<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
302// NOTE: we can't use a generic implementation for `Unit<T>` because
303// num_complex::Complex does not implement `From[Complex<...>...]` (and can't
304// because of the orphan rules).
305impl<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}