@@ -126,7 +126,21 @@ fn logf(val: f64) -> f64 {
126
126
/// Natural logarithm for `f64`.
127
127
#[ cfg( not( feature = "std" ) ) ]
128
128
fn logf ( val : f64 ) -> f64 {
129
- libm:: logf ( val as f32 ) as f64
129
+ logf_approx ( val as f32 ) as f64
130
+ }
131
+
132
+ /// Ln implementation based on
133
+ /// <https://gist.github.com/LingDong-/7e4c4cae5cbbc44400a05fba65f06f23>
134
+ #[ cfg( any( not( feature = "std" ) , test) ) ]
135
+ fn logf_approx ( x : f32 ) -> f32 {
136
+ let bx: u32 = x. to_bits ( ) ;
137
+ let ex: u32 = bx >> 23 ;
138
+ let t: i32 = ( ex as i32 ) - 127 ;
139
+ let s: u32 = if t < 0 { -t as u32 } else { t as u32 } ;
140
+ let bx = 1065353216 | ( bx & 8388607 ) ;
141
+ let x = f32:: from_bits ( bx) ;
142
+
143
+ -1.49278 + ( 2.11263 + ( -0.729104 + 0.10969 * x) * x) * x + core:: f32:: consts:: LN_2 * ( s as f32 )
130
144
}
131
145
132
146
fn generate_prime_with_rng < R : CryptoRngCore > ( rng : & mut R , bit_length : u32 ) -> BoxedUint {
@@ -141,6 +155,7 @@ fn generate_prime_with_rng<R: CryptoRngCore>(rng: &mut R, bit_length: u32) -> Bo
141
155
#[ cfg( test) ]
142
156
mod tests {
143
157
use super :: * ;
158
+ use rand:: Rng ;
144
159
use rand_chacha:: { rand_core:: SeedableRng , ChaCha8Rng } ;
145
160
146
161
const EXP : u64 = 65537 ;
@@ -186,4 +201,19 @@ mod tests {
186
201
key_generation ! ( key_generation_multi_8_576, 8 , 576 ) ;
187
202
// TODO: reenable, currently slow
188
203
// key_generation!(key_generation_multi_16_1024, 16, 1024);
204
+
205
+ #[ test]
206
+ fn test_log_approx ( ) {
207
+ let mut rng = ChaCha8Rng :: from_seed ( [ 42 ; 32 ] ) ;
208
+
209
+ for i in 0 ..100 {
210
+ println ! ( "round {i}" ) ;
211
+ let prime_limit: f64 = rng. gen ( ) ;
212
+ let a = logf ( prime_limit) ;
213
+ let b = logf_approx ( prime_limit as f32 ) ;
214
+
215
+ let diff = a - b as f64 ;
216
+ assert ! ( diff < 0.001 , "{} != {}" , a, b) ;
217
+ }
218
+ }
189
219
}
0 commit comments