#[doc(hidden)]
#[macro_export(local_inner_macros)]
macro_rules! impl_floating_point_operations {
( $struct: ident { $($field: ident), + }, $size: expr ) => {
impl<T: num_traits::float::FloatCore> $struct<T> {
#[inline]
pub fn dot(&self, other: &Self) -> T {
$crate::sum_repeating!(
$( + (self.$field * other.$field) ) +
)
}
pub fn length_squared(&self) -> T {
let squared = Self {
$( $field: self.$field * self.$field ), +
};
$crate::sum_repeating!(
$( + squared.$field ) +
)
}
#[inline]
pub fn floor(self) -> Self {
self.map(T::floor)
}
#[inline]
pub fn ceil(self) -> Self {
self.map(T::ceil)
}
#[inline]
pub fn round(self) -> Self {
self.map(T::round)
}
#[inline]
pub fn abs(self) -> Self {
self.map(T::abs)
}
#[inline]
pub fn trunc(self) -> Self {
self.map(T::trunc)
}
#[inline]
pub fn fract(self) -> Self {
self.map(T::fract)
}
#[inline]
pub fn powi(self, n: i32) -> Self {
self.map(|f| f.powi(n))
}
#[inline(always)]
pub fn lerp(self, to: Self, weight: T) -> Self {
Self {
$( $field: self.$field + (weight * (to.$field - self.$field)) ), +
}
}
}
impl<T> $struct<T>
where
T: $crate::macros::floating::_FloatingPoint
+ num_traits::float::FloatCore
{
#[inline]
pub fn sqrt(self) -> Self {
self.map(T::sqrt)
}
#[inline]
pub fn length(&self) -> T {
self.length_squared().sqrt()
}
pub fn normalized(self) -> Self {
let length_squared = self.length_squared();
if length_squared == T::zero() {
return Self { $( $field: T::zero() ), + };
}
let length = length_squared.sqrt();
Self {
$( $field: self.$field / length ), +
}
}
pub fn normalize(&mut self) {
let length_squared = self.length_squared();
if length_squared == T::zero() {
*self = Self { $( $field: T::zero() ), + };
return;
}
let length = length_squared.sqrt();
*self = Self {
$( $field: self.$field / length ), +
}
}
}
};
}
#[doc(hidden)]
#[macro_export(local_inner_macros)]
macro_rules! sum_repeating {
( + $($item: tt) * ) => {
$($item) *
};
}
#[doc(hidden)]
pub trait _FloatingPoint {
fn sqrt(self) -> Self;
}
impl _FloatingPoint for f32 {
#[inline(always)]
fn sqrt(self) -> Self {
libm::sqrtf(self)
}
}
impl _FloatingPoint for f64 {
#[inline(always)]
fn sqrt(self) -> Self {
libm::sqrt(self)
}
}