Skip to main content

vonkarman_core/
float.rs

1use std::fmt::{Debug, Display};
2use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
3
4/// Multi-precision floating-point trait.
5///
6/// Implemented for f64 (Phase 1). DDReal, QDReal, MpfrFloat in Phase 2+.
7/// Every arithmetic operation, transcendental, and conversion needed by
8/// the solver and diagnostics pipeline.
9pub trait Float:
10    Copy
11    + Send
12    + Sync
13    + Debug
14    + Display
15    + PartialEq
16    + PartialOrd
17    + Add<Output = Self>
18    + Sub<Output = Self>
19    + Mul<Output = Self>
20    + Div<Output = Self>
21    + Neg<Output = Self>
22    + AddAssign
23    + SubAssign
24    + MulAssign
25    + DivAssign
26    + 'static
27{
28    const ZERO: Self;
29    const ONE: Self;
30    const TWO: Self;
31    const PI: Self;
32    const EPSILON_VAL: Self;
33
34    fn from_f64(x: f64) -> Self;
35    fn to_f64(self) -> f64;
36    fn sqrt(self) -> Self;
37    fn cbrt(self) -> Self;
38    fn sin(self) -> Self;
39    fn cos(self) -> Self;
40    fn exp(self) -> Self;
41    fn ln(self) -> Self;
42    fn abs(self) -> Self;
43    fn powi(self, n: i32) -> Self;
44    fn powf(self, e: Self) -> Self;
45    fn max(self, other: Self) -> Self;
46    fn min(self, other: Self) -> Self;
47    fn is_finite(self) -> bool;
48    fn is_nan(self) -> bool;
49
50    fn recip(self) -> Self {
51        Self::ONE / self
52    }
53
54    fn sin_cos(self) -> (Self, Self) {
55        (self.sin(), self.cos())
56    }
57}
58
59impl Float for f64 {
60    const ZERO: Self = 0.0;
61    const ONE: Self = 1.0;
62    const TWO: Self = 2.0;
63    const PI: Self = std::f64::consts::PI;
64    const EPSILON_VAL: Self = f64::EPSILON;
65
66    #[inline]
67    fn from_f64(x: f64) -> Self {
68        x
69    }
70    #[inline]
71    fn to_f64(self) -> f64 {
72        self
73    }
74    #[inline]
75    fn sqrt(self) -> Self {
76        f64::sqrt(self)
77    }
78    #[inline]
79    fn cbrt(self) -> Self {
80        f64::cbrt(self)
81    }
82    #[inline]
83    fn sin(self) -> Self {
84        f64::sin(self)
85    }
86    #[inline]
87    fn cos(self) -> Self {
88        f64::cos(self)
89    }
90    #[inline]
91    fn exp(self) -> Self {
92        f64::exp(self)
93    }
94    #[inline]
95    fn ln(self) -> Self {
96        f64::ln(self)
97    }
98    #[inline]
99    fn abs(self) -> Self {
100        f64::abs(self)
101    }
102    #[inline]
103    fn powi(self, n: i32) -> Self {
104        f64::powi(self, n)
105    }
106    #[inline]
107    fn powf(self, e: Self) -> Self {
108        f64::powf(self, e)
109    }
110    #[inline]
111    fn max(self, other: Self) -> Self {
112        f64::max(self, other)
113    }
114    #[inline]
115    fn min(self, other: Self) -> Self {
116        f64::min(self, other)
117    }
118    #[inline]
119    fn is_finite(self) -> bool {
120        f64::is_finite(self)
121    }
122    #[inline]
123    fn is_nan(self) -> bool {
124        f64::is_nan(self)
125    }
126
127    #[inline]
128    fn sin_cos(self) -> (Self, Self) {
129        f64::sin_cos(self)
130    }
131}
132
133#[cfg(test)]
134mod tests {
135    use super::*;
136
137    #[test]
138    fn f64_constants() {
139        assert_eq!(f64::ZERO, 0.0);
140        assert_eq!(f64::ONE, 1.0);
141        assert!((f64::PI - std::f64::consts::PI).abs() < 1e-15);
142        assert_eq!(f64::EPSILON_VAL, f64::EPSILON);
143    }
144
145    #[test]
146    fn f64_from_to() {
147        let x = <f64 as Float>::from_f64(2.78);
148        assert_eq!(x.to_f64(), 2.78);
149    }
150
151    #[test]
152    fn f64_transcendentals() {
153        let x = <f64 as Float>::from_f64(1.0);
154        assert!((Float::sin(x) - 1.0_f64.sin()).abs() < 1e-15);
155        assert!((Float::cos(x) - 1.0_f64.cos()).abs() < 1e-15);
156        assert!((Float::exp(x) - 1.0_f64.exp()).abs() < 1e-15);
157        assert!((Float::ln(x)).abs() < 1e-15);
158        assert!((Float::sqrt(x) - 1.0).abs() < 1e-15);
159    }
160
161    #[test]
162    fn f64_powi() {
163        let x = <f64 as Float>::from_f64(2.0);
164        assert!((Float::powi(x, 10) - 1024.0).abs() < 1e-10);
165    }
166
167    #[test]
168    fn f64_powf() {
169        let x = <f64 as Float>::from_f64(2.0);
170        let e = <f64 as Float>::from_f64(0.5);
171        assert!((Float::powf(x, e) - std::f64::consts::SQRT_2).abs() < 1e-14);
172    }
173}