Files
pi/src/main.rs
Eric Lynema 8838d1497e feat: Implement multi-threaded Pi calculator
This commit introduces a new Rust program that calculates the first n
digits of Pi using the BBP algorithm. The program is multi-threaded and
allows the user to specify the number of threads to use. It uses the
`rug` crate for arbitrary-precision arithmetic to ensure the accuracy of
the calculated digits.

The program can be run from the command line, taking the number of
digits and the number of threads as arguments.
2025-09-01 19:29:52 -04:00

70 lines
1.8 KiB
Rust

use clap::Parser;
use rug::{Float, ops::Pow};
use std::thread;
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
/// Number of digits of Pi to calculate
n: u32,
/// Number of threads to use
#[arg(short, long, default_value_t = 4)]
threads: usize,
}
fn bbp_term(k: u32, prec: u32) -> Float {
let mut term = Float::with_val(prec, 4);
term /= Float::with_val(prec, 8 * k + 1);
let mut term2 = Float::with_val(prec, 2);
term2 /= Float::with_val(prec, 8 * k + 4);
term -= term2;
let mut term3 = Float::with_val(prec, 1);
term3 /= Float::with_val(prec, 8 * k + 5);
term -= term3;
let mut term4 = Float::with_val(prec, 1);
term4 /= Float::with_val(prec, 8 * k + 6);
term -= term4;
let sixteen = Float::with_val(prec, 16);
term /= sixteen.pow(k);
term
}
fn main() {
let args = Args::parse();
let n = args.n;
let num_threads = args.threads;
// Precision for rug::Float. We need a bit more than n decimal digits.
// log2(10) is approx 3.32. So, we need n * 3.32 bits.
let prec = (n as f64 * 3.33).ceil() as u32;
let terms_per_thread = (n + num_threads as u32 - 1) / num_threads as u32;
let mut handles = vec![];
for i in 0..num_threads {
let start = i as u32 * terms_per_thread;
let end = ((i + 1) as u32 * terms_per_thread).min(n);
let handle = thread::spawn(move || {
let mut partial_sum = Float::with_val(prec, 0);
for k in start..end {
partial_sum += bbp_term(k, prec);
}
partial_sum
});
handles.push(handle);
}
let mut pi = Float::with_val(prec, 0);
for handle in handles {
pi += handle.join().unwrap();
}
println!("Pi: {}", pi.to_string_radix(10, Some(n as usize)));
}