1use std::fmt::{Debug, Display};
2use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
3
4pub 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}