use std::fmt; use std::ops::Deref; #[cfg(feature = "serde-serialize-no-std")] use serde::{Deserialize, Deserializer, Serialize, Serializer}; use crate::allocator::Allocator; use crate::base::DefaultAllocator; use crate::storage::RawStorage; use crate::{Dim, Matrix, OMatrix, RealField, Scalar, SimdComplexField, SimdRealField}; #[cfg(feature = "rkyv-serialize")] use rkyv::bytecheck; /// A wrapper that ensures the underlying algebraic entity has a unit norm. /// /// **It is likely that the only piece of documentation that you need in this page are:** /// - **[The construction with normalization](#construction-with-normalization)** /// - **[Data extraction and construction without normalization](#data-extraction-and-construction-without-normalization)** /// - **[Interpolation between two unit vectors](#interpolation-between-two-unit-vectors)** /// /// All the other impl blocks you will see in this page are about [`UnitComplex`](crate::UnitComplex) /// and [`UnitQuaternion`](crate::UnitQuaternion); both built on top of `Unit`. If you are interested /// in their documentation, read their dedicated pages directly. #[repr(transparent)] #[derive(Clone, Hash, Copy)] #[cfg_attr( feature = "rkyv-serialize-no-std", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive( as = "Unit", bound(archive = " T: rkyv::Archive, ") ) )] #[cfg_attr(feature = "rkyv-serialize", derive(bytecheck::CheckBytes))] // #[cfg_attr(feature = "cuda", derive(cust_core::DeviceCopy))] pub struct Unit { pub(crate) value: T, } impl fmt::Debug for Unit { fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { self.value.fmt(formatter) } } #[cfg(feature = "bytemuck")] unsafe impl bytemuck::Zeroable for Unit where T: bytemuck::Zeroable {} #[cfg(feature = "bytemuck")] unsafe impl bytemuck::Pod for Unit where T: bytemuck::Pod {} #[cfg(feature = "serde-serialize-no-std")] impl Serialize for Unit { fn serialize(&self, serializer: S) -> Result where S: Serializer, { self.value.serialize(serializer) } } #[cfg(feature = "serde-serialize-no-std")] impl<'de, T: Deserialize<'de>> Deserialize<'de> for Unit { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { T::deserialize(deserializer).map(|x| Unit { value: x }) } } #[cfg(feature = "cuda")] unsafe impl cust_core::DeviceCopy for Unit> where T: Scalar, R: Dim, C: Dim, S: RawStorage + Copy, { } impl PartialEq for Unit> where T: Scalar + PartialEq, R: Dim, C: Dim, S: RawStorage, { #[inline] fn eq(&self, rhs: &Self) -> bool { self.value.eq(&rhs.value) } } impl Eq for Unit> where T: Scalar + Eq, R: Dim, C: Dim, S: RawStorage, { } /// Trait implemented by entities scan be be normalized and put in an `Unit` struct. pub trait Normed { /// The type of the norm. type Norm: SimdRealField; /// Computes the norm. fn norm(&self) -> Self::Norm; /// Computes the squared norm. fn norm_squared(&self) -> Self::Norm; /// Multiply `self` by n. fn scale_mut(&mut self, n: Self::Norm); /// Divides `self` by n. fn unscale_mut(&mut self, n: Self::Norm); } /// # Construction with normalization impl Unit { /// Normalize the given vector and return it wrapped on a `Unit` structure. #[inline] pub fn new_normalize(value: T) -> Self { Self::new_and_get(value).0 } /// Attempts to normalize the given vector and return it wrapped on a `Unit` structure. /// /// Returns `None` if the norm was smaller or equal to `min_norm`. #[inline] pub fn try_new(value: T, min_norm: T::Norm) -> Option where T::Norm: RealField, { Self::try_new_and_get(value, min_norm).map(|res| res.0) } /// Normalize the given vector and return it wrapped on a `Unit` structure and its norm. #[inline] pub fn new_and_get(mut value: T) -> (Self, T::Norm) { let n = value.norm(); value.unscale_mut(n.clone()); (Unit { value }, n) } /// Normalize the given vector and return it wrapped on a `Unit` structure and its norm. /// /// Returns `None` if the norm was smaller or equal to `min_norm`. #[inline] pub fn try_new_and_get(mut value: T, min_norm: T::Norm) -> Option<(Self, T::Norm)> where T::Norm: RealField, { let sq_norm = value.norm_squared(); if sq_norm > min_norm.clone() * min_norm { let n = sq_norm.simd_sqrt(); value.unscale_mut(n.clone()); Some((Unit { value }, n)) } else { None } } /// Normalizes this vector again. This is useful when repeated computations /// might cause a drift in the norm because of float inaccuracies. /// /// Returns the norm before re-normalization. See `.renormalize_fast` for a faster alternative /// that may be slightly less accurate if `self` drifted significantly from having a unit length. #[inline] pub fn renormalize(&mut self) -> T::Norm { let n = self.norm(); self.value.unscale_mut(n.clone()); n } /// Normalizes this vector again using a first-order Taylor approximation. /// This is useful when repeated computations might cause a drift in the norm /// because of float inaccuracies. #[inline] pub fn renormalize_fast(&mut self) { let sq_norm = self.value.norm_squared(); let three: T::Norm = crate::convert(3.0); let half: T::Norm = crate::convert(0.5); self.value.scale_mut(half * (three - sq_norm)); } } /// # Data extraction and construction without normalization impl Unit { /// Wraps the given value, assuming it is already normalized. #[inline] pub const fn new_unchecked(value: T) -> Self { Unit { value } } /// Wraps the given reference, assuming it is already normalized. #[inline] pub fn from_ref_unchecked(value: &T) -> &Self { unsafe { &*(value as *const T as *const Self) } } /// Retrieves the underlying value. #[inline] pub fn into_inner(self) -> T { self.value } /// Retrieves the underlying value. /// Deprecated: use [`Unit::into_inner`] instead. #[deprecated(note = "use `.into_inner()` instead")] #[inline] pub fn unwrap(self) -> T { self.value } /// Returns a mutable reference to the underlying value. This is `_unchecked` because modifying /// the underlying value in such a way that it no longer has unit length may lead to unexpected /// results. #[inline] pub fn as_mut_unchecked(&mut self) -> &mut T { &mut self.value } } impl AsRef for Unit { #[inline] fn as_ref(&self) -> &T { &self.value } } /* /* * * Conversions. * */ impl SubsetOf for Unit where T::RealField: RelativeEq { #[inline] fn to_superset(&self) -> T { self.clone().into_inner() } #[inline] fn is_in_subset(value: &T) -> bool { relative_eq!(value.norm_squared(), crate::one()) } #[inline] fn from_superset_unchecked(value: &T) -> Self { Unit::new_normalize(value.clone()) // We still need to re-normalize because the condition is inexact. } } // impl RelativeEq for Unit { // type Epsilon = T::Epsilon; // // #[inline] // fn default_epsilon() -> Self::Epsilon { // T::default_epsilon() // } // // #[inline] // fn default_max_relative() -> Self::Epsilon { // T::default_max_relative() // } // // #[inline] // fn default_max_ulps() -> u32 { // T::default_max_ulps() // } // // #[inline] // fn relative_eq(&self, other: &Self, epsilon: Self::Epsilon, max_relative: Self::Epsilon) -> bool { // self.value.relative_eq(&other.value, epsilon, max_relative) // } // // #[inline] // fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool { // self.value.ulps_eq(&other.value, epsilon, max_ulps) // } // } */ // TODO:re-enable this impl when specialization is possible. // Currently, it is disabled so that we can have a nice output for the `UnitQuaternion` display. /* impl fmt::Display for Unit { // XXX: will not always work correctly due to rounding errors. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.value.fmt(f) } } */ impl Deref for Unit { type Target = T; #[inline] fn deref(&self) -> &T { unsafe { &*(self as *const Self as *const T) } } } // NOTE: we can't use a generic implementation for `Unit` because // num_complex::Complex does not implement `From[Complex<...>...]` (and can't // because of the orphan rules). impl From<[Unit>; 2]> for Unit> where T: From<[::Element; 2]>, T::Element: Scalar, DefaultAllocator: Allocator + Allocator, { #[inline] fn from(arr: [Unit>; 2]) -> Self { Self::new_unchecked(OMatrix::from([ arr[0].clone().into_inner(), arr[1].clone().into_inner(), ])) } } impl From<[Unit>; 4]> for Unit> where T: From<[::Element; 4]>, T::Element: Scalar, DefaultAllocator: Allocator + Allocator, { #[inline] fn from(arr: [Unit>; 4]) -> Self { Self::new_unchecked(OMatrix::from([ arr[0].clone().into_inner(), arr[1].clone().into_inner(), arr[2].clone().into_inner(), arr[3].clone().into_inner(), ])) } } impl From<[Unit>; 8]> for Unit> where T: From<[::Element; 8]>, T::Element: Scalar, DefaultAllocator: Allocator + Allocator, { #[inline] fn from(arr: [Unit>; 8]) -> Self { Self::new_unchecked(OMatrix::from([ arr[0].clone().into_inner(), arr[1].clone().into_inner(), arr[2].clone().into_inner(), arr[3].clone().into_inner(), arr[4].clone().into_inner(), arr[5].clone().into_inner(), arr[6].clone().into_inner(), arr[7].clone().into_inner(), ])) } } impl From<[Unit>; 16]> for Unit> where T: From<[::Element; 16]>, T::Element: Scalar, DefaultAllocator: Allocator + Allocator, { #[inline] fn from(arr: [Unit>; 16]) -> Self { Self::new_unchecked(OMatrix::from([ arr[0].clone().into_inner(), arr[1].clone().into_inner(), arr[2].clone().into_inner(), arr[3].clone().into_inner(), arr[4].clone().into_inner(), arr[5].clone().into_inner(), arr[6].clone().into_inner(), arr[7].clone().into_inner(), arr[8].clone().into_inner(), arr[9].clone().into_inner(), arr[10].clone().into_inner(), arr[11].clone().into_inner(), arr[12].clone().into_inner(), arr[13].clone().into_inner(), arr[14].clone().into_inner(), arr[15].clone().into_inner(), ])) } }