Skip to content

Commit

Permalink
Reimplement ten_to_the
Browse files Browse the repository at this point in the history
  • Loading branch information
akubera committed Jul 28, 2023
1 parent 94e2145 commit 6e3c04a
Showing 1 changed file with 36 additions and 11 deletions.
47 changes: 36 additions & 11 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,27 +102,52 @@ mod parsing;
pub mod rounding;
pub use rounding::RoundingMode;

#[inline(always)]
/// Return 10^pow
///
/// Try to calculate this with fewest number of allocations
///
fn ten_to_the(pow: u64) -> BigInt {
if pow < 20 {
BigInt::from(10u64.pow(pow as u32))
} else {
let (half, rem) = pow.div_rem(&16);
return BigInt::from(10u64.pow(pow as u32));
}

// linear case of 10^pow = 10^(19 * count + rem)
if pow < 590 {
let ten_to_nineteen = 10u64.pow(19);

let mut x = ten_to_the(half);
// count factors of 19
let (count, rem) = pow.div_rem(&19);

for _ in 0..4 {
x = &x * &x;
let mut res = BigInt::from(ten_to_nineteen);

for _ in 1..count {
res *= ten_to_nineteen;
}

if rem == 0 {
x
} else {
x * ten_to_the(rem)
if rem != 0 {
res *= 10u64.pow(rem as u32);
}

return res;
}

// use recursive algorithm where linear case might be too slow
let (quoteint, rem) = pow.div_rem(&16);
let x = ten_to_the(quoteint);

let x2 = &x * &x;
let x4 = &x2 * &x2;
let x8 = &x4 * &x4;
let res = &x8 * &x8;

if rem == 0 {
res
} else {
res * 10u64.pow(rem as u32)
}
}


#[inline(always)]
fn count_decimal_digits(int: &BigInt) -> u64 {
if int.is_zero() {
Expand Down

0 comments on commit 6e3c04a

Please sign in to comment.