smartcore/numbers/
floatnum.rs

1use num_traits::{Float, Signed};
2
3use crate::{numbers::basenum::Number, rand_custom::get_rng_impl};
4
5/// Defines float number
6/// <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS_CHTML"></script>
7pub trait FloatNumber: Number + Float + Signed {
8    /// Copy sign from `sign` - another real number
9    fn copysign(self, sign: Self) -> Self;
10
11    /// Calculates natural \\( \ln(1+e^x) \\) without overflow.
12    fn ln_1pe(self) -> Self;
13
14    /// Efficient implementation of Sigmoid function, \\( S(x) = \frac{1}{1 + e^{-x}} \\), see [Sigmoid function](https://en.wikipedia.org/wiki/Sigmoid_function)
15    fn sigmoid(self) -> Self;
16
17    /// Returns pseudorandom number between 0 and 1
18    fn rand() -> Self;
19
20    /// Returns 2
21    fn two() -> Self;
22
23    /// Returns .5
24    fn half() -> Self;
25
26    /// Returns \\( x^2 \\)
27    fn square(self) -> Self {
28        self * self
29    }
30
31    /// Raw transmutation to u64
32    fn to_f32_bits(self) -> u32;
33}
34
35impl FloatNumber for f64 {
36    fn copysign(self, sign: Self) -> Self {
37        self.copysign(sign)
38    }
39
40    fn ln_1pe(self) -> f64 {
41        if self > 15. {
42            self
43        } else {
44            self.exp().ln_1p()
45        }
46    }
47
48    fn sigmoid(self) -> f64 {
49        if self < -40. {
50            0.
51        } else if self > 40. {
52            1.
53        } else {
54            1. / (1. + f64::exp(-self))
55        }
56    }
57
58    fn rand() -> f64 {
59        use rand::Rng;
60        let mut rng = get_rng_impl(None);
61        rng.gen()
62    }
63
64    fn two() -> Self {
65        2f64
66    }
67
68    fn half() -> Self {
69        0.5f64
70    }
71
72    fn to_f32_bits(self) -> u32 {
73        self.to_bits() as u32
74    }
75}
76
77impl FloatNumber for f32 {
78    fn copysign(self, sign: Self) -> Self {
79        self.copysign(sign)
80    }
81
82    fn ln_1pe(self) -> f32 {
83        if self > 15. {
84            self
85        } else {
86            self.exp().ln_1p()
87        }
88    }
89
90    fn sigmoid(self) -> f32 {
91        if self < -40. {
92            0.
93        } else if self > 40. {
94            1.
95        } else {
96            1. / (1. + f32::exp(-self))
97        }
98    }
99
100    fn rand() -> f32 {
101        use rand::Rng;
102        let mut rng = get_rng_impl(None);
103        rng.gen()
104    }
105
106    fn two() -> Self {
107        2f32
108    }
109
110    fn half() -> Self {
111        0.5f32
112    }
113
114    fn to_f32_bits(self) -> u32 {
115        self.to_bits()
116    }
117}