1use std::{
2 fmt::Display,
3 ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub},
4};
5
6#[derive(Debug, PartialEq, PartialOrd, Clone, Copy, Default)]
7pub struct UnsignedF64(f64);
9
10impl UnsignedF64 {
11 pub fn new(value: f64) -> Option<UnsignedF64> {
16 if value == 0.0_f64 {
17 Some(UnsignedF64(0.0))
18 } else if value >= 0.0_f64 {
19 Some(UnsignedF64(value))
20 } else {
21 None
22 }
23 }
24
25 pub fn square(f: f64) -> UnsignedF64 {
26 UnsignedF64(f * f)
27 }
28
29 pub fn floor(&self) -> UnsignedF64 {
32 UnsignedF64(self.0.floor())
33 }
34
35 pub fn ceil(&self) -> UnsignedF64 {
36 UnsignedF64(self.0.ceil())
37 }
38
39 pub fn round(&self) -> UnsignedF64 {
40 UnsignedF64(self.0.round())
41 }
42
43 pub fn trunc(&self) -> UnsignedF64 {
44 UnsignedF64(self.0.trunc())
45 }
46
47 pub fn fract(&self) -> UnsignedF64 {
48 UnsignedF64(self.0.fract())
49 }
50
51 pub fn abs(&self) -> UnsignedF64 {
52 UnsignedF64(self.0.abs())
53 }
54
55 pub fn signum(&self) -> f64 {
58 self.0.signum()
59 }
60
61 pub fn copysign(&self, sign: f64) -> f64 {
64 self.0.copysign(sign)
65 }
66
67 pub fn mul_add(&self, a: UnsignedF64, b: UnsignedF64) -> UnsignedF64 {
68 UnsignedF64(self.0.mul_add(a.0, b.0))
69 }
70
71 pub fn rem_euclid(&self, rhs: UnsignedF64) -> UnsignedF64 {
78 UnsignedF64(self.0.rem_euclid(rhs.0))
79 }
80
81 pub fn powi(&self, n: i32) -> UnsignedF64 {
82 UnsignedF64(self.0.powi(n))
83 }
84
85 pub fn powf(&self, n: f64) -> UnsignedF64 {
86 UnsignedF64(self.0.powf(n))
87 }
88
89 pub fn sqrt(&self) -> UnsignedF64 {
91 UnsignedF64(self.0.sqrt())
92 }
93
94 pub fn exp(&self) -> UnsignedF64 {
95 UnsignedF64(self.0.exp())
96 }
97
98 pub fn exp2(&self) -> UnsignedF64 {
99 UnsignedF64(self.0.exp2())
100 }
101
102 pub fn ln(&self) -> f64 {
103 self.0.ln()
104 }
105
106 pub fn log(&self, base: f64) -> f64 {
107 self.0.log(base)
108 }
109
110 pub fn log2(&self) -> f64 {
111 self.0.log2()
112 }
113
114 pub fn log10(&self) -> f64 {
115 self.0.log10()
116 }
117
118 pub fn cbrt(&self) -> UnsignedF64 {
119 UnsignedF64(self.0.cbrt())
120 }
121
122 pub fn hypot(&self, other: f64) -> UnsignedF64 {
123 UnsignedF64(self.0.hypot(other))
124 }
125
126 pub fn sin(&self) -> f64 {
127 self.0.sin()
128 }
129
130 pub fn cos(&self) -> f64 {
131 self.0.cos()
132 }
133
134 pub fn tan(&self) -> f64 {
135 self.0.tan()
136 }
137
138 pub fn asin(&self) -> UnsignedF64 {
139 UnsignedF64(self.0.asin())
140 }
141
142 pub fn acos(&self) -> UnsignedF64 {
143 UnsignedF64(self.0.acos())
144 }
145
146 pub fn atan(&self) -> UnsignedF64 {
147 UnsignedF64(self.0.atan())
148 }
149
150 pub fn sin_cos(&self) -> (f64, f64) {
156 self.0.sin_cos()
157 }
158
159 pub fn exp_m1(&self) -> UnsignedF64 {
160 UnsignedF64(self.0.exp_m1())
161 }
162
163 pub fn ln_1p(&self) -> UnsignedF64 {
164 UnsignedF64(self.0.ln_1p())
165 }
166
167 pub fn sinh(&self) -> UnsignedF64 {
168 UnsignedF64(self.0.sinh())
169 }
170
171 pub fn cosh(&self) -> UnsignedF64 {
172 UnsignedF64(self.0.cosh())
173 }
174
175 pub fn tanh(&self) -> UnsignedF64 {
176 UnsignedF64(self.0.tanh())
177 }
178
179 pub fn asinh(&self) -> UnsignedF64 {
180 UnsignedF64(self.0.asinh())
181 }
182
183 pub fn acosh(&self) -> UnsignedF64 {
184 UnsignedF64(self.0.acosh())
185 }
186
187 pub fn atanh(&self) -> UnsignedF64 {
188 UnsignedF64(self.0.atanh())
189 }
190
191 pub fn is_nan(&self) -> bool {
192 self.0.is_nan()
193 }
194
195 pub fn is_infinite(&self) -> bool {
196 self.0.is_infinite()
197 }
198
199 pub fn is_finite(&self) -> bool {
200 self.0.is_finite()
201 }
202
203 pub fn is_subnormal(&self) -> bool {
204 self.0.is_subnormal()
205 }
206
207 pub fn is_normal(&self) -> bool {
208 self.0.is_normal()
209 }
210
211 pub fn classify(&self) -> std::num::FpCategory {
212 self.0.classify()
213 }
214
215 pub fn is_sign_positive(&self) -> bool {
217 self.0.is_sign_positive()
218 }
219
220 pub fn is_sign_negative(&self) -> bool {
222 self.0.is_sign_negative()
223 }
224
225 pub fn recip(&self) -> UnsignedF64 {
226 UnsignedF64(self.0.recip())
227 }
228
229 pub fn to_degrees(&self) -> UnsignedF64 {
230 UnsignedF64(self.0.to_degrees())
231 }
232
233 pub fn to_radians(&self) -> UnsignedF64 {
234 UnsignedF64(self.0.to_radians())
235 }
236
237 pub fn max(self, other: UnsignedF64) -> UnsignedF64 {
238 UnsignedF64(self.0.max(other.0))
239 }
240
241 pub fn min(self, other: UnsignedF64) -> UnsignedF64 {
242 UnsignedF64(self.0.min(other.0))
243 }
244
245 pub fn total_cmp(&self, other: &UnsignedF64) -> std::cmp::Ordering {
248 self.0.total_cmp(&other.0)
249 }
250
251 pub fn clamp(self, min: UnsignedF64, max: UnsignedF64) -> UnsignedF64 {
252 UnsignedF64(self.0.clamp(min.0, max.0))
253 }
254
255 pub unsafe fn from_f64_unchecked(value: f64) -> UnsignedF64 {
259 UnsignedF64(value)
260 }
261
262 pub const PI: UnsignedF64 = UnsignedF64(std::f64::consts::PI);
263 pub const E: UnsignedF64 = UnsignedF64(std::f64::consts::E);
264 pub const FRAC_1_PI: UnsignedF64 = UnsignedF64(std::f64::consts::FRAC_1_PI);
265 pub const FRAC_1_SQRT_2: UnsignedF64 = UnsignedF64(std::f64::consts::FRAC_1_SQRT_2);
266 pub const FRAC_2_PI: UnsignedF64 = UnsignedF64(std::f64::consts::FRAC_2_PI);
267 pub const FRAC_2_SQRT_PI: UnsignedF64 = UnsignedF64(std::f64::consts::FRAC_2_SQRT_PI);
268 pub const FRAC_PI_2: UnsignedF64 = UnsignedF64(std::f64::consts::FRAC_PI_2);
269 pub const FRAC_PI_3: UnsignedF64 = UnsignedF64(std::f64::consts::FRAC_PI_3);
270 pub const FRAC_PI_4: UnsignedF64 = UnsignedF64(std::f64::consts::FRAC_PI_4);
271 pub const FRAC_PI_6: UnsignedF64 = UnsignedF64(std::f64::consts::FRAC_PI_6);
272 pub const FRAC_PI_8: UnsignedF64 = UnsignedF64(std::f64::consts::FRAC_PI_8);
273 pub const LN_10: UnsignedF64 = UnsignedF64(std::f64::consts::LN_10);
274 pub const LN_2: UnsignedF64 = UnsignedF64(std::f64::consts::LN_2);
275 pub const LOG10_E: UnsignedF64 = UnsignedF64(std::f64::consts::LOG10_E);
276 pub const LOG2_E: UnsignedF64 = UnsignedF64(std::f64::consts::LOG2_E);
277 pub const SQRT_2: UnsignedF64 = UnsignedF64(std::f64::consts::SQRT_2);
278 pub const TAU: UnsignedF64 = UnsignedF64(std::f64::consts::TAU);
279 pub const EPSILON: UnsignedF64 = UnsignedF64(f64::EPSILON);
280 pub const INFINITY: UnsignedF64 = UnsignedF64(f64::INFINITY);
281
282 pub const ZERO: UnsignedF64 = UnsignedF64(0.0);
283 pub const ONE: UnsignedF64 = UnsignedF64(1.0);
284}
285
286impl Display for UnsignedF64 {
287 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
288 self.0.fmt(f)
289 }
290}
291
292impl PartialEq<f64> for UnsignedF64 {
293 fn eq(&self, other: &f64) -> bool {
294 self.0 == *other
295 }
296}
297
298impl PartialOrd<f64> for UnsignedF64 {
299 fn partial_cmp(&self, other: &f64) -> Option<std::cmp::Ordering> {
300 self.0.partial_cmp(other)
301 }
302}
303
304impl From<UnsignedF64> for f64 {
305 fn from(value: UnsignedF64) -> f64 {
306 value.0
307 }
308}
309
310impl TryFrom<f64> for UnsignedF64 {
311 type Error = (); fn try_from(value: f64) -> Result<Self, Self::Error> {
314 if value >= 0.0 {
315 Ok(UnsignedF64(value))
316 } else {
317 Err(())
318 }
319 }
320}
321
322impl AsRef<f64> for UnsignedF64 {
323 fn as_ref(&self) -> &f64 {
324 &self.0
325 }
326}
327
328impl AsMut<f64> for UnsignedF64 {
329 fn as_mut(&mut self) -> &mut f64 {
330 &mut self.0
331 }
332}
333
334impl Add for UnsignedF64 {
335 type Output = UnsignedF64;
336 fn add(self, other: UnsignedF64) -> UnsignedF64 {
337 UnsignedF64(self.0 + other.0)
338 }
339}
340
341impl Add<f64> for UnsignedF64 {
342 type Output = f64;
343 fn add(self, rhs: f64) -> Self::Output {
344 self.0 + rhs
345 }
346}
347
348impl Sub for UnsignedF64 {
349 type Output = f64;
350 fn sub(self, rhs: Self) -> Self::Output {
351 self.0 - rhs.0
352 }
353}
354
355impl Sub<f64> for UnsignedF64 {
356 type Output = f64;
357 fn sub(self, rhs: f64) -> Self::Output {
358 self.0 - rhs
359 }
360}
361
362impl Mul for UnsignedF64 {
363 type Output = UnsignedF64;
364 fn mul(self, rhs: Self) -> Self::Output {
365 UnsignedF64(self.0 * rhs.0)
366 }
367}
368
369impl Mul<f64> for UnsignedF64 {
370 type Output = f64;
371 fn mul(self, rhs: f64) -> Self::Output {
372 self.0 * rhs
373 }
374}
375
376impl Div for UnsignedF64 {
377 type Output = UnsignedF64;
378 fn div(self, rhs: Self) -> Self::Output {
379 UnsignedF64(self.0 / rhs.0)
380 }
381}
382
383impl Div<f64> for UnsignedF64 {
384 type Output = f64;
385 fn div(self, rhs: f64) -> Self::Output {
386 self.0 / rhs
387 }
388}
389
390impl Neg for UnsignedF64 {
391 type Output = f64;
392 fn neg(self) -> Self::Output {
393 -self.0
394 }
395}
396
397impl AddAssign for UnsignedF64 {
398 fn add_assign(&mut self, rhs: Self) {
399 self.0 += rhs.0;
400 }
401}
402
403impl MulAssign for UnsignedF64 {
404 fn mul_assign(&mut self, rhs: Self) {
405 self.0 *= rhs.0;
406 }
407}
408
409impl DivAssign for UnsignedF64 {
410 fn div_assign(&mut self, rhs: Self) {
411 self.0 /= rhs.0;
412 }
413}