mirror of
https://git.sdf.org/epl692/pi.git
synced 2025-12-08 05:38:50 -05:00
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.
This commit is contained in:
70
src/main.rs
Normal file
70
src/main.rs
Normal file
@@ -0,0 +1,70 @@
|
||||
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)));
|
||||
}
|
||||
Reference in New Issue
Block a user