@@ -126,7 +126,20 @@ 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 bx = 1065353216 | ( bx & 8388607 ) ;
140
+ let x = f32:: from_bits ( bx) ;
141
+
142
+ -1.49278 + ( 2.11263 + ( -0.729104 + 0.10969 * x) * x) * x + core:: f32:: consts:: LN_2 * ( t as f32 )
130
143
}
131
144
132
145
fn generate_prime_with_rng < R : CryptoRngCore > ( rng : & mut R , bit_length : u32 ) -> BoxedUint {
@@ -141,6 +154,7 @@ fn generate_prime_with_rng<R: CryptoRngCore>(rng: &mut R, bit_length: u32) -> Bo
141
154
#[ cfg( test) ]
142
155
mod tests {
143
156
use super :: * ;
157
+ use rand:: Rng ;
144
158
use rand_chacha:: { rand_core:: SeedableRng , ChaCha8Rng } ;
145
159
146
160
const EXP : u64 = 65537 ;
@@ -186,4 +200,19 @@ mod tests {
186
200
key_generation ! ( key_generation_multi_8_576, 8 , 576 ) ;
187
201
// TODO: reenable, currently slow
188
202
// key_generation!(key_generation_multi_16_1024, 16, 1024);
203
+
204
+ #[ test]
205
+ fn test_log_approx ( ) {
206
+ let mut rng = ChaCha8Rng :: from_seed ( [ 42 ; 32 ] ) ;
207
+
208
+ for i in 0 ..100 {
209
+ println ! ( "round {i}" ) ;
210
+ let prime_limit: f64 = rng. gen ( ) ;
211
+ let a = logf ( prime_limit) ;
212
+ let b = logf_approx ( prime_limit as f32 ) ;
213
+
214
+ let diff = a - b as f64 ;
215
+ assert ! ( diff < 0.001 , "{} != {}" , a, b) ;
216
+ }
217
+ }
189
218
}
0 commit comments