concrete_commons/numeric/
float.rs

1use std::ops::{
2    Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign,
3};
4
5use super::Numeric;
6
7/// A trait shared by all the floating point types.
8pub trait FloatingPoint:
9    Numeric
10    + Neg<Output = Self>
11    + Add<Self, Output = Self>
12    + AddAssign<Self>
13    + Div<Self, Output = Self>
14    + DivAssign<Self>
15    + Mul<Self, Output = Self>
16    + MulAssign<Self>
17    + Rem<Self, Output = Self>
18    + RemAssign<Self>
19    + Sub<Self, Output = Self>
20    + SubAssign<Self>
21{
22    /// Raises a float to an integer power.
23    #[must_use]
24    fn powi(self, power: i32) -> Self;
25
26    /// Rounds the float to the closest integer.
27    #[must_use]
28    fn round(self) -> Self;
29
30    /// Keeps the fractional part of the number.
31    #[must_use]
32    fn fract(self) -> Self;
33
34    /// Remainder of the euclidean division.
35    #[must_use]
36    fn rem_euclid(self, rhs: Self) -> Self;
37
38    /// Returns the square root of the input float.
39    #[must_use]
40    fn sqrt(self) -> Self;
41
42    /// Returns the natural logarithm of the input float.
43    #[must_use]
44    fn ln(self) -> Self;
45
46    /// Returns the absolute value of the input float.
47    #[must_use]
48    fn abs(self) -> Self;
49
50    /// Returns the floor value of the input float.
51    #[must_use]
52    fn floor(self) -> Self;
53
54    /// Returns a bit representation of the float, with the sign, exponent, and mantissa bits
55    /// separated by whitespaces for increased readability.
56    fn to_bit_string(&self) -> String;
57}
58
59macro_rules! implement {
60    ($Type: tt, $bits:expr) => {
61        impl Numeric for $Type {
62            const BITS: usize = $bits;
63            const ZERO: Self = 0.;
64            const ONE: Self = 1.;
65            const TWO: Self = 2.;
66            const MAX: Self = <$Type>::MAX;
67        }
68        impl FloatingPoint for $Type {
69            fn powi(self, power: i32) -> Self {
70                self.powi(power)
71            }
72            fn round(self) -> Self {
73                self.round()
74            }
75            fn fract(self) -> Self {
76                self.fract()
77            }
78            fn rem_euclid(self, rhs: Self) -> Self {
79                self.rem_euclid(rhs)
80            }
81            fn sqrt(self) -> Self {
82                self.sqrt()
83            }
84            fn ln(self) -> Self {
85                self.ln()
86            }
87            fn abs(self) -> Self {
88                self.abs()
89            }
90            fn floor(self) -> Self {
91                self.floor()
92            }
93            fn to_bit_string(&self) -> String {
94                if Self::BITS == 32 {
95                    let mut bit_string = format!("{:032b}", self.to_bits());
96                    bit_string.insert(1, ' ');
97                    bit_string.insert(10, ' ');
98                    format!("{}", bit_string)
99                } else {
100                    let mut bit_string = format!("{:064b}", self.to_bits());
101                    bit_string.insert(1, ' ');
102                    bit_string.insert(13, ' ');
103                    format!("{}", bit_string)
104                }
105            }
106        }
107    };
108}
109
110implement!(f64, 64);
111implement!(f32, 32);
112
113#[cfg(test)]
114mod test {
115    use super::*;
116
117    #[test]
118    fn test_f64_binary_rep() {
119        let a = 1123214.4321432_f64;
120        let b = a.to_bit_string();
121        assert_eq!(
122            b,
123            "0 10000010011 0001001000111000111001101110101000001110111111001111".to_string()
124        );
125    }
126
127    #[test]
128    fn test_f32_binary_rep() {
129        let a = -1.276_663_9e27_f32;
130        let b = a.to_bit_string();
131        assert_eq!(b, "1 11011001 00001000000000100000011".to_string());
132    }
133}