batbox_num/
real.rs

1use super::*;
2
3/// Real number (differs from [Float] as doesn't support NaN)
4pub trait Real: Num + Copy {
5    /// Archimedes’ constant (π)
6    const PI: Self;
7
8    /// Computes the arccosine of a number.
9    ///
10    /// Return value is in radians in the range [0, pi] or NaN if the number is outside the range [-1, 1].
11    fn acos(self) -> Self;
12
13    /// Computes the arcsine of a number.
14    ///
15    /// Return value is in radians in the range [-pi/2, pi/2] or NaN if the number is outside the range [-1, 1].
16    fn asin(self) -> Self;
17
18    /// Computes the arctangent of a number.
19    ///
20    /// Return value is in radians in the range [-pi/2, pi/2];
21    fn atan(self) -> Self;
22
23    /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians.  
24    ///
25    /// * `x = 0`, `y = 0`: `0`
26    /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]`
27    /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]`
28    /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)`
29    fn atan2(y: Self, x: Self) -> Self;
30
31    /// Returns the smallest integer greater than or equal to a number.
32    fn ceil(self) -> Self;
33
34    /// Computes the cosine of a number (in radians).
35    fn cos(self) -> Self;
36
37    /// Calculates Euclidean division, the matching method for rem_euclid.
38    ///
39    /// This computes the integer n such that self = n * rhs + self.rem_euclid(rhs).
40    /// In other words, the result is self / rhs rounded to the integer n such that self >= n * rhs.
41    fn div_euclid(self, other: Self) -> Self;
42
43    /// Returns `e^(self)`, (the exponential function).
44    fn exp(self) -> Self;
45
46    /// Returns the largest integer less than or equal to `self`.
47    fn floor(self) -> Self;
48
49    /// Returns the fractional part of `self`.
50    fn fract(self) -> Self;
51
52    /// Returns the natural logarithm of the number.
53    fn ln(self) -> Self;
54
55    /// Returns the logarithm of the number with respect to an arbitrary base.
56    fn log(self, base: Self) -> Self;
57
58    /// Returns the base 10 logarithm of the number.
59    fn log10(self) -> Self;
60
61    /// Returns the base 2 logarithm of the number.
62    fn log2(self) -> Self;
63
64    /// Raises a number to a floating point power.
65    fn powf(self, n: Self) -> Self;
66
67    /// Raises a number to an integer power.
68    fn powi(self, n: i32) -> Self;
69
70    /// Takes the reciprocal (inverse) of a number, 1/x
71    fn recip(self) -> Self;
72
73    /// Calculates the least nonnegative remainder of `self (mod rhs)`.
74    ///
75    /// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in
76    /// most cases. However, due to a floating point round-off error it can
77    /// result in `r == rhs.abs()`, violating the mathematical definition, if
78    /// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`.
79    /// This result is not an element of the function's codomain, but it is the
80    /// closest floating point number in the real numbers and thus fulfills the
81    /// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)`
82    /// approximately.
83    fn rem_euclid(self, other: Self) -> Self;
84
85    /// Returns the nearest integer to `self`.
86    /// Round half-way cases away from `0.0`.
87    fn round(self) -> Self;
88
89    /// Computes the sine of a number (in radians).
90    fn sin(self) -> Self;
91
92    /// Simultaneously computes the sine and cosine of the number, `x`.
93    /// Returns `(sin(x), cos(x))`.
94    fn sin_cos(self) -> (Self, Self);
95
96    /// Returns the square root of a number.
97    ///
98    /// Returns NaN if `self` is a negative number other than `-0.0`.
99    fn sqrt(self) -> Self;
100
101    /// Computes the tangent of a number (in radians).
102    fn tan(self) -> Self;
103
104    /// Convert an [f32] into [Self]
105    fn from_f32(x: f32) -> Self;
106
107    /// Convert self into an [f32]
108    fn as_f32(self) -> f32;
109}
110
111impl<T: Real> Float for T {
112    const PI: Self = <Self as Real>::PI;
113    fn acos(self) -> Self {
114        Real::acos(self)
115    }
116    fn asin(self) -> Self {
117        Real::asin(self)
118    }
119    fn atan(self) -> Self {
120        Real::atan(self)
121    }
122    fn atan2(y: Self, x: Self) -> Self {
123        Real::atan2(y, x)
124    }
125    fn ceil(self) -> Self {
126        Real::ceil(self)
127    }
128    fn cos(self) -> Self {
129        Real::cos(self)
130    }
131    fn div_euclid(self, other: Self) -> Self {
132        Real::div_euclid(self, other)
133    }
134    fn exp(self) -> Self {
135        Real::exp(self)
136    }
137    fn floor(self) -> Self {
138        Real::floor(self)
139    }
140    fn fract(self) -> Self {
141        Real::fract(self)
142    }
143    fn ln(self) -> Self {
144        Real::ln(self)
145    }
146    fn log(self, base: Self) -> Self {
147        Real::log(self, base)
148    }
149    fn log10(self) -> Self {
150        Real::log10(self)
151    }
152    fn log2(self) -> Self {
153        Real::log2(self)
154    }
155    fn powf(self, n: Self) -> Self {
156        Real::powf(self, n)
157    }
158    fn powi(self, n: i32) -> Self {
159        Real::powi(self, n)
160    }
161    fn recip(self) -> Self {
162        Real::recip(self)
163    }
164    fn rem_euclid(self, other: Self) -> Self {
165        Real::rem_euclid(self, other)
166    }
167    fn round(self) -> Self {
168        Real::round(self)
169    }
170    fn sin(self) -> Self {
171        Real::sin(self)
172    }
173    fn sin_cos(self) -> (Self, Self) {
174        Real::sin_cos(self)
175    }
176    fn sqrt(self) -> Self {
177        Real::sqrt(self)
178    }
179    fn tan(self) -> Self {
180        Real::tan(self)
181    }
182    fn from_f32(x: f32) -> Self {
183        Real::from_f32(x)
184    }
185    fn as_f32(self) -> f32 {
186        Real::as_f32(self)
187    }
188    fn is_finite(self) -> bool {
189        true
190    }
191}
192
193/// Wrapper around T that checks for valid values (panics on NaN/Inf)
194#[derive(Copy, Clone, PartialEq, serde::Serialize)]
195#[serde(transparent)]
196#[repr(transparent)]
197pub struct RealImpl<T: Float>(T);
198
199macro_rules! impl_for {
200    ($t:ty) => {
201        impl<'de> serde::Deserialize<'de> for RealImpl<$t> {
202            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
203            where
204                D: serde::Deserializer<'de>,
205            {
206                <$t as serde::Deserialize>::deserialize(deserializer)?
207                    .try_into()
208                    .map_err(serde::de::Error::custom)
209            }
210        }
211        impl TryFrom<$t> for RealImpl<$t> {
212            type Error = &'static str;
213            fn try_from(value: $t) -> Result<Self, Self::Error> {
214                if value.is_finite() {
215                    Ok(Self::new_unchecked(value))
216                } else {
217                    Err("Value must be finite")
218                }
219            }
220        }
221    };
222}
223
224#[test]
225fn test_real_ron() {
226    let s = ron::to_string(&r32(1.5)).unwrap();
227    assert_eq!(ron::from_str(&s), Ok(r32(1.5)));
228}
229
230#[test]
231fn test_real_bincode() {
232    let data = bincode::serialize(&f32::NAN).unwrap();
233    assert!(bincode::deserialize::<R32>(&data).is_err());
234    let data = bincode::serialize(&1.3f32).unwrap();
235    assert_eq!(bincode::deserialize::<R32>(&data).unwrap(), r32(1.3));
236}
237
238impl_for!(f32);
239impl_for!(f64);
240
241impl<T: Float> std::fmt::Debug for RealImpl<T> {
242    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
243        <T as std::fmt::Debug>::fmt(&self.0, fmt)
244    }
245}
246
247impl<T: Float> std::fmt::Display for RealImpl<T> {
248    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
249        <T as std::fmt::Display>::fmt(&self.0, fmt)
250    }
251}
252
253impl<T: Float> RealImpl<T> {
254    /// Create a new value, panics if not finite
255    pub fn new(value: T) -> Self {
256        assert!(value.is_finite());
257        Self(value)
258    }
259
260    /// Create a new value without checking
261    pub fn new_unchecked(value: T) -> Self {
262        Self(value)
263    }
264
265    /// Get raw value
266    pub fn raw(self) -> T {
267        self.0
268    }
269}
270
271impl<T: Float> Eq for RealImpl<T> {}
272
273impl<T: Float> PartialOrd for RealImpl<T> {
274    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
275        Some(self.cmp(other))
276    }
277}
278
279impl<T: Float> Ord for RealImpl<T> {
280    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
281        self.0.partial_cmp(&other.0).unwrap()
282    }
283}
284
285macro_rules! impl_op {
286    ($($op:ident: $fn:ident,)*) => {
287        $(
288            impl<T: Float> std::ops::$op for RealImpl<T> {
289                type Output = Self;
290                fn $fn(self, rhs: Self) -> Self {
291                    Self::new(self.0 .$fn(rhs.0))
292                }
293            }
294        )*
295    };
296}
297macro_rules! impl_op_assign {
298    ($($op:ident: $fn:ident,)*) => {
299        $(
300            impl<T: Float> std::ops::$op for RealImpl<T> {
301                fn $fn(&mut self, rhs: Self) {
302                    self.0 .$fn(rhs.0);
303                }
304            }
305        )*
306    };
307}
308
309impl_op! {
310    Add: add,
311    Sub: sub,
312    Mul: mul,
313    Div: div,
314}
315
316impl_op_assign! {
317    AddAssign: add_assign,
318    SubAssign: sub_assign,
319    MulAssign: mul_assign,
320    DivAssign: div_assign,
321}
322
323impl<T: Float> std::ops::Neg for RealImpl<T> {
324    type Output = Self;
325    fn neg(self) -> Self {
326        Self::new(-self.0)
327    }
328}
329
330impl<T: Float> UNum for RealImpl<T> {
331    const ZERO: Self = Self(T::ZERO);
332    const ONE: Self = Self(T::ONE);
333}
334
335impl<T: Float> Num for RealImpl<T> {
336    fn signum(self) -> Self {
337        Self::new(<T as Num>::signum(self.0))
338    }
339}
340
341/// Uniform [RealImpl] sampler
342pub struct UniformReal<T: rand::distributions::uniform::SampleUniform>(T::Sampler);
343
344impl<T: Float + rand::distributions::uniform::SampleUniform>
345    rand::distributions::uniform::UniformSampler for UniformReal<T>
346{
347    type X = RealImpl<T>;
348
349    fn new<B1, B2>(low: B1, high: B2) -> Self
350    where
351        B1: rand::distributions::uniform::SampleBorrow<Self::X> + Sized,
352        B2: rand::distributions::uniform::SampleBorrow<Self::X> + Sized,
353    {
354        Self(T::Sampler::new(low.borrow().0, high.borrow().0))
355    }
356
357    fn new_inclusive<B1, B2>(low: B1, high: B2) -> Self
358    where
359        B1: rand::distributions::uniform::SampleBorrow<Self::X> + Sized,
360        B2: rand::distributions::uniform::SampleBorrow<Self::X> + Sized,
361    {
362        Self(T::Sampler::new_inclusive(low.borrow().0, high.borrow().0))
363    }
364
365    fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
366        RealImpl(self.0.sample(rng))
367    }
368
369    fn sample_single<R: rand::Rng + ?Sized, B1, B2>(low: B1, high: B2, rng: &mut R) -> Self::X
370    where
371        B1: rand::distributions::uniform::SampleBorrow<Self::X> + Sized,
372        B2: rand::distributions::uniform::SampleBorrow<Self::X> + Sized,
373    {
374        RealImpl(T::Sampler::sample_single(
375            low.borrow().0,
376            high.borrow().0,
377            rng,
378        ))
379    }
380
381    fn sample_single_inclusive<R: rand::Rng + ?Sized, B1, B2>(
382        low: B1,
383        high: B2,
384        rng: &mut R,
385    ) -> Self::X
386    where
387        B1: rand::distributions::uniform::SampleBorrow<Self::X> + Sized,
388        B2: rand::distributions::uniform::SampleBorrow<Self::X> + Sized,
389    {
390        RealImpl(T::Sampler::sample_single_inclusive(
391            low.borrow().0,
392            high.borrow().0,
393            rng,
394        ))
395    }
396}
397
398impl<T: Float + rand::distributions::uniform::SampleUniform>
399    rand::distributions::uniform::SampleUniform for RealImpl<T>
400{
401    type Sampler = UniformReal<T>;
402}
403
404impl<T: Float> Real for RealImpl<T> {
405    const PI: Self = Self(T::PI);
406    fn acos(self) -> Self {
407        Self::new(T::acos(self.0))
408    }
409    fn asin(self) -> Self {
410        Self::new(T::asin(self.0))
411    }
412    fn atan(self) -> Self {
413        Self::new(T::atan(self.0))
414    }
415    fn atan2(y: Self, x: Self) -> Self {
416        Self::new(T::atan2(y.0, x.0))
417    }
418    fn ceil(self) -> Self {
419        Self::new(T::ceil(self.0))
420    }
421    fn cos(self) -> Self {
422        Self::new(T::cos(self.0))
423    }
424    fn div_euclid(self, other: Self) -> Self {
425        Self::new(T::div_euclid(self.0, other.0))
426    }
427    fn exp(self) -> Self {
428        Self::new(T::exp(self.0))
429    }
430    fn floor(self) -> Self {
431        Self::new(T::floor(self.0))
432    }
433    fn fract(self) -> Self {
434        Self::new(T::fract(self.0))
435    }
436    fn ln(self) -> Self {
437        Self::new(T::ln(self.0))
438    }
439    fn log(self, base: Self) -> Self {
440        Self::new(T::log(self.0, base.0))
441    }
442    fn log10(self) -> Self {
443        Self::new(T::log10(self.0))
444    }
445    fn log2(self) -> Self {
446        Self::new(T::log2(self.0))
447    }
448    fn powf(self, n: Self) -> Self {
449        Self::new(T::powf(self.0, n.0))
450    }
451    fn powi(self, n: i32) -> Self {
452        Self::new(T::powi(self.0, n))
453    }
454    fn recip(self) -> Self {
455        Self::new(T::recip(self.0))
456    }
457    fn rem_euclid(self, other: Self) -> Self {
458        Self::new(T::rem_euclid(self.0, other.0))
459    }
460    fn round(self) -> Self {
461        Self::new(T::round(self.0))
462    }
463    fn sin(self) -> Self {
464        Self::new(T::sin(self.0))
465    }
466    fn sin_cos(self) -> (Self, Self) {
467        let (sin, cos) = T::sin_cos(self.0);
468        (Self::new(sin), Self::new(cos))
469    }
470    fn sqrt(self) -> Self {
471        Self::new(T::sqrt(self.0))
472    }
473    fn tan(self) -> Self {
474        Self::new(T::tan(self.0))
475    }
476    fn from_f32(x: f32) -> Self {
477        Self::new(T::from_f32(x))
478    }
479    fn as_f32(self) -> f32 {
480        self.0.as_f32()
481    }
482}
483
484// TODO: basically duplicates the trait wtf
485impl<T: Float> RealImpl<T> {
486    /// Archimedes’ constant (π)
487    pub const PI: Self = <Self as Real>::PI;
488
489    /// Computes the arccosine of a number.
490    ///
491    /// Return value is in radians in the range [0, pi] or NaN if the number is outside the range [-1, 1].
492    pub fn acos(self) -> Self {
493        <Self as Real>::acos(self)
494    }
495
496    /// Computes the arcsine of a number.
497    ///
498    /// Return value is in radians in the range [-pi/2, pi/2] or NaN if the number is outside the range [-1, 1].
499    pub fn asin(self) -> Self {
500        <Self as Real>::asin(self)
501    }
502
503    /// Computes the arctangent of a number.
504    ///
505    /// Return value is in radians in the range [-pi/2, pi/2];
506    pub fn atan(self) -> Self {
507        <Self as Real>::atan(self)
508    }
509
510    /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians.  
511    ///
512    /// * `x = 0`, `y = 0`: `0`
513    /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]`
514    /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]`
515    /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)`
516    pub fn atan2(y: Self, x: Self) -> Self {
517        <Self as Real>::atan2(y, x)
518    }
519
520    /// Returns the smallest integer greater than or equal to a number.
521    pub fn ceil(self) -> Self {
522        <Self as Real>::ceil(self)
523    }
524
525    /// Computes the cosine of a number (in radians).
526    pub fn cos(self) -> Self {
527        <Self as Real>::cos(self)
528    }
529
530    /// Calculates Euclidean division, the matching method for rem_euclid.
531    ///
532    /// This computes the integer n such that self = n * rhs + self.rem_euclid(rhs).
533    /// In other words, the result is self / rhs rounded to the integer n such that self >= n * rhs.
534    pub fn div_euclid(self, other: Self) -> Self {
535        <Self as Real>::div_euclid(self, other)
536    }
537
538    /// Returns `e^(self)`, (the exponential function).
539    pub fn exp(self) -> Self {
540        <Self as Real>::exp(self)
541    }
542
543    /// Returns the largest integer less than or equal to `self`.
544    pub fn floor(self) -> Self {
545        <Self as Real>::floor(self)
546    }
547
548    /// Returns the fractional part of `self`.
549    pub fn fract(self) -> Self {
550        <Self as Real>::fract(self)
551    }
552
553    /// Returns the natural logarithm of the number.
554    pub fn ln(self) -> Self {
555        <Self as Real>::ln(self)
556    }
557
558    /// Returns the logarithm of the number with respect to an arbitrary base.
559    pub fn log(self, base: Self) -> Self {
560        <Self as Real>::log(self, base)
561    }
562
563    /// Returns the base 10 logarithm of the number.
564    pub fn log10(self) -> Self {
565        <Self as Real>::log10(self)
566    }
567
568    /// Returns the base 2 logarithm of the number.
569    pub fn log2(self) -> Self {
570        <Self as Real>::log2(self)
571    }
572
573    /// Raises a number to a floating point power.
574    pub fn powf(self, n: Self) -> Self {
575        <Self as Real>::powf(self, n)
576    }
577
578    /// Raises a number to an integer power.
579    pub fn powi(self, n: i32) -> Self {
580        <Self as Real>::powi(self, n)
581    }
582
583    /// Takes the reciprocal (inverse) of a number, 1/x
584    pub fn recip(self) -> Self {
585        <Self as Real>::recip(self)
586    }
587
588    /// Calculates the least nonnegative remainder of `self (mod rhs)`.
589    ///
590    /// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in
591    /// most cases. However, due to a floating point round-off error it can
592    /// result in `r == rhs.abs()`, violating the mathematical definition, if
593    /// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`.
594    /// This result is not an element of the function's codomain, but it is the
595    /// closest floating point number in the real numbers and thus fulfills the
596    /// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)`
597    /// approximately.
598    pub fn rem_euclid(self, other: Self) -> Self {
599        <Self as Real>::rem_euclid(self, other)
600    }
601
602    /// Returns the nearest integer to `self`.
603    /// Round half-way cases away from `0.0`.
604    pub fn round(self) -> Self {
605        <Self as Real>::round(self)
606    }
607
608    /// Returns a number that represents the sign of `self`.
609    ///
610    /// - `1.0` if the number is positive, `+0.0` or `INFINITY`
611    /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
612    /// - NaN if the number is NaN
613    pub fn signum(self) -> Self {
614        <Self as Num>::signum(self)
615    }
616
617    /// Computes the sine of a number (in radians).
618    pub fn sin(self) -> Self {
619        <Self as Real>::sin(self)
620    }
621
622    /// Simultaneously computes the sine and cosine of the number, `x`.
623    /// Returns `(sin(x), cos(x))`.
624    pub fn sin_cos(self) -> (Self, Self) {
625        <Self as Real>::sin_cos(self)
626    }
627
628    /// Returns the square root of a number.
629    ///
630    /// Returns NaN if `self` is a negative number other than `-0.0`.
631    pub fn sqrt(self) -> Self {
632        <Self as Real>::sqrt(self)
633    }
634
635    /// Computes the tangent of a number (in radians).
636    pub fn tan(self) -> Self {
637        <Self as Real>::tan(self)
638    }
639
640    /// Convert an [f32] into [Self]
641    pub fn from_f32(x: f32) -> Self {
642        <Self as Real>::from_f32(x)
643    }
644
645    /// Convert self into an [f32]
646    pub fn as_f32(self) -> f32 {
647        <Self as Real>::as_f32(self)
648    }
649}
650
651/// Like [f32] but panics on NaN/Inf
652pub type R32 = RealImpl<f32>;
653
654/// Construct a new [R32] from an [f32]
655pub fn r32(value: f32) -> R32 {
656    R32::new(value)
657}
658
659/// Like [f64] but panics on NaN/Inf
660pub type R64 = RealImpl<f64>;
661
662/// Construct a new [R64] from an [f64]
663pub fn r64(value: f64) -> R64 {
664    R64::new(value)
665}
666
667#[test]
668fn test_reals() {
669    let a = r64(3.0);
670    let b = r64(2.0);
671    println!("a = {a:?}, b = {b:?}");
672    println!("a + b = {:?}", a + b);
673    println!("a - b = {:?}", a - b);
674    println!("a * b = {:?}", a * b);
675    println!("a / b = {:?}", a / b);
676    println!("sin_cos(a) = {:?}", a.sin_cos());
677
678    let mut arr = [r32(1.0), r32(0.0)];
679    arr.sort();
680
681    let _random = rand::Rng::gen_range(&mut rand::thread_rng(), r32(0.0)..r32(1.0));
682}
683
684#[test]
685#[should_panic]
686fn test_reals_fail() {
687    println!("0 / 0 = {:?}", R64::ZERO / R64::ZERO);
688}