@@ -126,7 +126,21 @@ fn logf(val: f64) -> f64 {
126126/// Natural logarithm for `f64`.
127127#[ cfg( not( feature = "std" ) ) ]
128128fn 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 )
130144}
131145
132146fn 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
141155#[ cfg( test) ]
142156mod tests {
143157 use super :: * ;
158+ use rand:: Rng ;
144159 use rand_chacha:: { rand_core:: SeedableRng , ChaCha8Rng } ;
145160
146161 const EXP : u64 = 65537 ;
@@ -186,4 +201,19 @@ mod tests {
186201 key_generation ! ( key_generation_multi_8_576, 8 , 576 ) ;
187202 // TODO: reenable, currently slow
188203 // 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+ }
189219}
0 commit comments