Skip to content

Commit 84dde17

Browse files
authored
Use a direct formula to calculate log(2^x) (#475)
Replaces the current approximate `logf()` which we don't really need for this specific form of the argument. Note: I am not sure why we calculate `log(2^floor(bit_size / nprimes))` while we could just as well calculate `log(2^(bit_size/nprimes))`, but I left that part intact.
1 parent 8e8bd6a commit 84dde17

File tree

1 file changed

+4
-42
lines changed

1 file changed

+4
-42
lines changed

src/algorithms/generate.rs

+4-42
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,10 @@ pub(crate) fn generate_multi_prime_key_with_exp<R: CryptoRngCore>(
4545
let prime_limit = (1u64 << (bit_size / nprimes) as u64) as f64;
4646

4747
// pi aproximates the number of primes less than prime_limit
48-
let mut pi = prime_limit / (logf(prime_limit) - 1f64);
48+
49+
// Calculate `log(prime_limit)` as `log(x) = log2(x) / log2(e) = log2(x) * log(2)`.
50+
let mut pi = prime_limit / ((bit_size / nprimes) as f64 * core::f64::consts::LN_2 - 1.);
51+
4952
// Generated primes start with 0b11, so we can only use a quarter of them.
5053
pi /= 4f64;
5154
// Use a factor of two to ensure that key generation terminates in a
@@ -117,31 +120,6 @@ pub(crate) fn generate_multi_prime_key_with_exp<R: CryptoRngCore>(
117120
})
118121
}
119122

120-
/// Natural logarithm for `f64`.
121-
#[cfg(feature = "std")]
122-
fn logf(val: f64) -> f64 {
123-
val.ln()
124-
}
125-
126-
/// Natural logarithm for `f64`.
127-
#[cfg(not(feature = "std"))]
128-
fn logf(val: f64) -> 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)
143-
}
144-
145123
fn generate_prime_with_rng<R: CryptoRngCore>(rng: &mut R, bit_length: u32) -> BoxedUint {
146124
sieve_and_find(
147125
rng,
@@ -154,7 +132,6 @@ fn generate_prime_with_rng<R: CryptoRngCore>(rng: &mut R, bit_length: u32) -> Bo
154132
#[cfg(test)]
155133
mod tests {
156134
use super::*;
157-
use rand::Rng;
158135
use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng};
159136

160137
const EXP: u64 = 65537;
@@ -200,19 +177,4 @@ mod tests {
200177
key_generation!(key_generation_multi_8_576, 8, 576);
201178
// TODO: reenable, currently slow
202179
// 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-
}
218180
}

0 commit comments

Comments
 (0)