use core::intrinsics; use core::ops::{ Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign, }; use core::cmp::{Eq, Ord, Ordering, PartialOrd}; #[cfg(feature = "serde")] use serde::{Serialize, Deserialize}; #[cfg(feature = "fmt")] use core::fmt; pub trait ToFloat { // TODO: make these by-value fn to_f32(&self) -> f32 { self.to_f64() as _ } fn to_f64(&self) -> f64 { self.to_f32() as _ } fn to_r32(&self) -> R32 { R32::new(self.to_f32()) } fn to_r64(&self) -> R64 { R64::new(self.to_f64()) } } #[cfg(all(not(feature = "fmt"), not(feature = "serde")))] pub trait RealFeatures {} #[cfg(all(not(feature = "fmt"), feature = "serde"))] pub trait RealFeatures: Serialize + for<'a> Deserialize<'a> {} #[cfg(all(feature = "fmt", not(feature = "serde")))] pub trait RealFeatures: fmt::LowerExp + fmt::Display + fmt::Debug {} #[cfg(all(feature = "fmt", feature = "serde"))] pub trait RealFeatures: fmt::LowerExp + fmt::Display + fmt::Debug + Serialize + for<'a> Deserialize<'a> {} /// This exists to allow configuration over # of bits (f32 v.s. f64) as well as /// constraints. pub trait Real: ToFloat + RealFeatures + PartialOrd + Add + Sub + Mul + Div + AddAssign + MulAssign + SubAssign + DivAssign + Neg + Copy + Clone + Default + Send + Sync + 'static { // TODO: fold with from_ fn from_primitive(p: P) -> Self { Self::from_f64(p.to_f64()) } fn from_f32(f: f32) -> Self { Self::from_f64(f as _) } fn from_f64(f: f64) -> Self { Self::from_f32(f as _) } fn from_u64(u: u64) -> Self { Self::from_primitive(u) } fn from_u32(u: u32) -> Self { Self::from_primitive(u) } // TODO: make this by-value fn cast(&self) -> R { R::from_primitive(*self) } fn is_finite(self) -> bool; fn floor(self) -> Self; fn ceil(self) -> Self; fn round(self) -> Self; fn abs(self) -> Self; fn exp(self) -> Self; fn powf(self, p: Self) -> Self; fn sqrt(self) -> Self; fn sin_cos(self) -> (Self, Self); fn sin(self) -> Self { self.sin_cos().0 } fn cos(self) -> Self { self.sin_cos().1 } fn min_max_or_undefined(self, other: Self) -> (Self, Self) { match self.partial_cmp(&other) { Some(ordering) => match ordering { Ordering::Less | Ordering::Equal => (self, other), _ => (other, self), }, _ => unreachable!(), } } fn min_or_undefined(self, other: Self) -> Self { self.min_max_or_undefined(other).0 } fn max_or_undefined(self, other: Self) -> Self { self.min_max_or_undefined(other).1 } fn is_zero(self) -> bool { self == Self::zero() } fn inv(self) -> Self { Self::one() / self } fn zero() -> Self; fn one() -> Self; fn two() -> Self; fn three() -> Self; fn ten() -> Self; fn tenth() -> Self; fn third() -> Self; fn half() -> Self; fn pi() -> Self; fn two_pi() -> Self; fn ln2() -> Self; /// Speed of light in a vacuum; m/s. /// Also equal to 1/sqrt(epsilon_0 mu_0) fn c() -> Self; fn c_inv() -> Self; /// Vaccum Permittivity fn eps0() -> Self; fn eps0_inv() -> Self; fn twice_eps0() -> Self; /// Vacuum Permeability fn mu0() -> Self; fn mu0_inv() -> Self; } macro_rules! decl_consts { ($wrap:expr) => { fn zero() -> Self { $wrap(0.0) } fn one() -> Self { $wrap(1.0) } fn two() -> Self { $wrap(2.0) } fn three() -> Self { $wrap(3.0) } fn ten() -> Self { $wrap(10.0) } fn tenth() -> Self { $wrap(0.1) } fn third() -> Self { $wrap(0.3333333333333333) } fn half() -> Self { $wrap(0.5) } fn pi() -> Self { $wrap(3.141592653589793) } fn two_pi() -> Self { $wrap(6.283185307179586) } fn ln2() -> Self { $wrap(0.6931471805599453) } /// Speed of light in a vacuum; m/s. /// Also equal to 1/sqrt(epsilon_0 mu_0) fn c() -> Self { $wrap(299792458.0) } fn c_inv() -> Self { $wrap(3.3356409519815204e-09) } /// Vaccum Permittivity fn eps0() -> Self { $wrap(8.854187812813e-12) // F/m } fn eps0_inv() -> Self { $wrap(112940906737.1361) // m/F } fn twice_eps0() -> Self { $wrap(1.7708375625626e-11) // F/m } /// Vacuum Permeability fn mu0() -> Self { $wrap(1.2566370621219e-6) // H/m } fn mu0_inv() -> Self { $wrap(795774.715025073) // m/H } }; } impl ToFloat for f32 { fn to_f32(&self) -> f32 { *self } } impl RealFeatures for f32 {} impl Real for f32 { decl_consts!(Real::from_f32); fn from_primitive(p: P) -> Self { Self::from_f32(p.to_f32()) } fn from_f32(f: f32) -> Self { f } fn is_finite(self) -> bool { f32::is_finite(self) } fn floor(self) -> Self { unsafe { intrinsics::floorf32(self) } } fn ceil(self) -> Self { unsafe { intrinsics::ceilf32(self) } } fn round(self) -> Self { unsafe { intrinsics::roundf32(self) } } fn abs(self) -> Self { unsafe { intrinsics::fabsf32(self) } } fn exp(self) -> Self { unsafe { intrinsics::expf32(self) } } fn sqrt(self) -> Self { unsafe { intrinsics::sqrtf32(self) } } fn powf(self, p: Self) -> Self { unsafe { intrinsics::powf32(self, p) } } fn sin_cos(self) -> (Self, Self) { unsafe {( intrinsics::sinf32(self), intrinsics::cosf32(self), )} } } impl ToFloat for f64 { fn to_f64(&self) -> f64 { *self } } impl RealFeatures for f64 {} impl Real for f64 { decl_consts!(Real::from_f64); fn from_f64(f: f64) -> Self { f } fn is_finite(self) -> bool { f64::is_finite(self) } fn floor(self) -> Self { unsafe { intrinsics::floorf64(self) } } fn ceil(self) -> Self { unsafe { intrinsics::ceilf64(self) } } fn round(self) -> Self { unsafe { intrinsics::roundf64(self) } } fn abs(self) -> Self { unsafe { intrinsics::fabsf64(self) } } fn exp(self) -> Self { unsafe { intrinsics::expf64(self) } } fn sqrt(self) -> Self { unsafe { intrinsics::sqrtf64(self) } } fn powf(self, p: Self) -> Self { unsafe { intrinsics::powf64(self, p) } } fn sin_cos(self) -> (Self, Self) { unsafe {( intrinsics::sinf64(self), intrinsics::cosf64(self), )} } } #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] #[cfg_attr(feature = "fmt", derive(Debug))] #[derive(Default, Copy, Clone, PartialEq, PartialOrd)] pub struct Finite(T); pub type R32 = Finite; pub type R64 = Finite; impl Finite { fn new(inner: T) -> Self { if !inner.is_finite() { Self::handle_non_finite(inner); } Self(inner) } #[cfg(feature = "fmt")] fn handle_non_finite(inner: T) -> ! { panic!("{} is not finite", inner); } #[cfg(not(feature = "fmt"))] fn handle_non_finite(_inner: T) -> ! { panic!(); // expected a finite real } } impl Eq for Finite {} impl Ord for Finite { fn cmp(&self, other: &Self) -> Ordering { self.partial_cmp(other).unwrap() } } #[cfg(feature = "fmt")] impl fmt::Display for Finite { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.0.fmt(f) } } #[cfg(feature = "fmt")] impl fmt::LowerExp for Finite { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.0.fmt(f) } } impl Neg for Finite { type Output = Self; fn neg(self) -> Self { Self::new(self.0.neg()) } } impl AddAssign for Finite { fn add_assign(&mut self, other: Self) { *self = Self::new(self.0.add(other.0)) } } impl SubAssign for Finite { fn sub_assign(&mut self, other: Self) { *self = Self::new(self.0.sub(other.0)) } } impl MulAssign for Finite { fn mul_assign(&mut self, other: Self) { *self = Self::new(self.0.mul(other.0)) } } impl DivAssign for Finite { fn div_assign(&mut self, other: Self) { *self = Self::new(self.0.div(other.0)) } } impl Add for Finite { type Output = Self; fn add(self, other: Self) -> Self { Self::new(self.0.add(other.0)) } } impl Sub for Finite { type Output = Self; fn sub(self, other: Self) -> Self { Self::new(self.0.sub(other.0)) } } impl Mul for Finite { type Output = Self; fn mul(self, other: Self) -> Self { Self::new(self.0.mul(other.0)) } } impl Div for Finite { type Output = Self; fn div(self, other: Self) -> Self { Self::new(self.0.div(other.0)) } } #[cfg(feature = "iter")] impl std::iter::Sum for Finite { fn sum(iter: I) -> Self where I: Iterator { iter.fold(Self::zero(), |a, b| a + b) } } impl ToFloat for Finite { fn to_f32(&self) -> f32 { self.0.to_f32() } fn to_f64(&self) -> f64 { self.0.to_f64() } } impl RealFeatures for Finite {} impl Real for Finite { fn from_primitive(p: P) -> Self { Self::new(T::from_primitive(p)) } fn from_f32(f: f32) -> Self { Self::new(T::from_f32(f)) } fn from_f64(f: f64) -> Self { Self::new(T::from_f64(f)) } fn is_finite(self) -> bool { true } fn floor(self) -> Self { Self::new(self.0.floor()) } fn ceil(self) -> Self { Self::new(self.0.ceil()) } fn round(self) -> Self { Self::new(self.0.round()) } fn abs(self) -> Self { Self::new(self.0.abs()) } fn exp(self) -> Self { Self::new(self.0.exp()) } fn sqrt(self) -> Self { Self::new(self.0.sqrt()) } fn powf(self, p: Self) -> Self { Self::new(self.0.powf(p.0)) } fn sin_cos(self) -> (Self, Self) { let (s, c) = self.0.sin_cos(); (Self::new(s), Self::new(c)) } // we would ideally use `decl_consts` here, but that produces f64 -> f32 casts for R32 code. fn zero() -> Self { Self::from_primitive(T::zero()) } fn one() -> Self { Self::from_primitive(T::one()) } fn two() -> Self { Self::from_primitive(T::two()) } fn three() -> Self { Self::from_primitive(T::three()) } fn ten() -> Self { Self::from_primitive(T::ten()) } fn tenth() -> Self { Self::from_primitive(T::tenth()) } fn third() -> Self { Self::from_primitive(T::third()) } fn half() -> Self { Self::from_primitive(T::half()) } fn pi() -> Self { Self::from_primitive(T::pi()) } fn two_pi() -> Self { Self::from_primitive(T::two_pi()) } fn ln2() -> Self { Self::from_primitive(T::ln2()) } fn c() -> Self { Self::from_primitive(T::c()) } fn c_inv() -> Self { Self::from_primitive(T::c_inv()) } fn eps0() -> Self { Self::from_primitive(T::eps0()) } fn eps0_inv() -> Self { Self::from_primitive(T::eps0_inv()) } fn twice_eps0() -> Self { Self::from_primitive(T::twice_eps0()) } fn mu0() -> Self { Self::from_primitive(T::mu0()) } fn mu0_inv() -> Self { Self::from_primitive(T::mu0_inv()) } } impl ToFloat for i32 { fn to_f32(&self) -> f32 { *self as _ } fn to_f64(&self) -> f64 { *self as _ } } impl ToFloat for u32 { fn to_f32(&self) -> f32 { *self as _ } fn to_f64(&self) -> f64 { *self as _ } } impl ToFloat for u64 { fn to_f32(&self) -> f32 { *self as _ } fn to_f64(&self) -> f64 { *self as _ } }