use cord_sparse::*; use std::time::Instant; fn product_fn(fp: &FixedPoint) -> impl Fn(&[i64]) -> i64 + '_ { move |pt: &[i64]| { let mut result = fp.one(); for &x in pt { result = fp.mul(result, x); } result } } fn measure_runtime f64>(mut f: F, k: usize) -> f64 { let n = 2 * k + 1; let mut results: Vec = (0..n).map(|_| f()).collect(); results.sort_by(|a, b| a.partial_cmp(b).unwrap()); results[k] } fn main() { let fp = FixedPoint::new(32); let basis = MonomialBasis; let pts = GoldenPoints; let dimensions = [2usize, 4, 8, 16, 32, 64]; let max_num_points: usize = 100_000_000; let min_quotient = 2.0; let max_runtime = 10.0; let epsilon = 0.01; let k = 2; // warm-up eprintln!("Warm-up"); { let iter = BoundedSumIter::new(5, 60); let f = product_fn(&fp); let rhs = evaluate_function(&iter, &f, &pts, &fp); let mut op = create_interpolation_operator(fp, &iter, &basis, &pts); let _ = op.solve(rhs); } eprintln!("Warm-up finished"); let mut csv = String::new(); for &d in &dimensions { eprintln!("Dimension: {d}"); let mut last_num_points = 0usize; let mut last_runtime = 0.0f64; for bound in 1.. { let num_points = index::binom(bound + d, d); if num_points > max_num_points { break; } if num_points as f64 / (last_num_points as f64 + epsilon) * last_runtime > max_runtime { break; } if num_points < (last_num_points as f64 * min_quotient) as usize { continue; } last_num_points = num_points; eprintln!(" Bound: {bound}, points: {num_points}"); let runtime = measure_runtime( || { let iter = BoundedSumIter::new(d, bound); let f = product_fn(&fp); let rhs = evaluate_function(&iter, &f, &pts, &fp); let mut op = create_interpolation_operator(fp, &iter, &basis, &pts); let start = Instant::now(); let _ = op.solve(rhs); let elapsed = start.elapsed().as_secs_f64(); eprintln!(" Time for solve(): {elapsed:.6} s"); elapsed }, k, ); csv.push_str(&format!("{d}, {bound}, {num_points}, {runtime}\n")); last_runtime = runtime; } } println!("{csv}"); }