#[cfg(feature = "abomonation-serialize")] use std::io::{Result as IOResult, Write}; use std::mem; use std::ops::Deref; #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[cfg(feature = "abomonation-serialize")] use abomonation::Abomonation; use crate::{RealField, SimdComplexField, SimdRealField}; /// A wrapper that ensures the underlying algebraic entity has a unit norm. /// /// Use `.as_ref()` or `.into_inner()` to obtain the underlying value by-reference or by-move. #[repr(transparent)] #[derive(Eq, PartialEq, Clone, Hash, Debug, Copy)] pub struct Unit { pub(crate) value: T, } #[cfg(feature = "serde-serialize")] impl Serialize for Unit { fn serialize(&self, serializer: S) -> Result where S: Serializer { self.value.serialize(serializer) } } #[cfg(feature = "serde-serialize")] 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 = "abomonation-serialize")] impl Abomonation for Unit { unsafe fn entomb(&self, writer: &mut W) -> IOResult<()> { self.value.entomb(writer) } fn extent(&self) -> usize { self.value.extent() } unsafe fn exhume<'a, 'b>(&'a mut self, bytes: &'b mut [u8]) -> Option<&'b mut [u8]> { self.value.exhume(bytes) } } pub trait Normed { type Norm: SimdRealField; fn norm(&self) -> Self::Norm; fn norm_squared(&self) -> Self::Norm; fn scale_mut(&mut self, n: Self::Norm); fn unscale_mut(&mut self, n: Self::Norm); } 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); (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 * min_norm { let n = sq_norm.simd_sqrt(); value.unscale_mut(n); 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); 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 _3: T::Norm = crate::convert(3.0); let _0_5: T::Norm = crate::convert(0.5); self.value.scale_mut(_0_5 * (_3 - sq_norm)); } } impl Unit { /// Wraps the given value, assuming it is already normalized. #[inline] pub fn new_unchecked(value: T) -> Self { Unit { value } } /// Wraps the given reference, assuming it is already normalized. #[inline] pub fn from_ref_unchecked<'a>(value: &'a T) -> &'a Self { unsafe { mem::transmute(value) } } /// 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) // } // } */ // FIXME: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 { mem::transmute(self) } } }