use reckoner::{Integer, Rational, RoundMode};
use std::env;
fn main() {
let args: Vec<_> = env::args().collect();
if let Some([iterations, precision]) = args.get(1..=2) {
let iterations = iterations
.parse()
.expect("Unable to parse 'iterations' value as a 32-bit unsigned integer.");
let precision = precision
.parse()
.expect("Unable to parse 'precision' value as a 16-bit unsigned integer.");
let pi = compute_pi_approx(iterations);
println!("{}", pi.to_decimal(RoundMode::HalfUp, precision));
} else {
help();
}
}
fn factorial(v: &Integer) -> Integer {
let mut accum = 1.into();
let mut f = v.clone();
while f > 0 {
accum *= &f;
f -= 1;
}
accum
}
fn odd_factorial(v: &Integer) -> Integer {
let mut accum = 1.into();
let mut f = if v % 2 == 0 { v - 1 } else { v.clone() };
while f > 0 {
accum *= &f;
f -= 2;
}
accum
}
fn compute_pi_approx(iterations: u32) -> Rational {
2 * (0..iterations)
.map(Integer::from)
.map(|n| {
let numerator = factorial(&n);
let denominator = odd_factorial(&(2 * n + 1));
(numerator, denominator).into()
})
.sum::<Rational>()
}
fn help() {
eprintln!("Usage: ./pi.rs <iterations> <precision>");
}