1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
use crate::util; use std::sync::mpsc; use std::thread; pub fn pihex(d: u64) -> String { let (tx, rx) = mpsc::channel(); for &(j, k, l) in &[ (4, 1, -32.0), (4, 3, -1.0), (10, 1, 256.0), (10, 3, -64.0), (10, 5, -4.0), (10, 7, -4.0), (10, 9, 1.0), ] { let tx = tx.clone(); thread::spawn(move || tx.send(l * series_sum(d, j, k)).unwrap()); } drop(tx); let fraction: f64 = rx.iter().sum(); (0..4) .scan(fraction, |x, _| { *x = (*x - x.floor()) * 16.0; Some(format!("{:x}", x.floor() as u32)) }) .fold(String::new(), |s, t| s + &t) } fn series_sum(d: u64, j: u64, k: u64) -> f64 { let fraction1: f64 = (0..(2 * d + 2) / 5) .map(|i| { (if i % 2 == 0 { 1.0 } else { -1.0 }) * util::pow_mod(4, 2 * d - 3 - 5 * i, j * i + k) as f64 / (j * i + k) as f64 }) .fold(0.0, |x, y| (x + y).fract()); let fraction2: f64 = ((2 * d + 2) / 5..) .map(|i| -(-4.0_f64).powi(-((5 * i + 3 - 2 * d) as i32)) / ((j * i + k) as f64)) .take_while(|&x| x.abs() > 1e-13_f64) .sum(); fraction1 + fraction2 }