├── .gitignore ├── start.cmd ├── Cargo.lock ├── Cargo.toml └── src ├── cf.rs └── main.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /start.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | cargo watch -c -d 0 -x "run --quiet" -q --use-shell cmd 3 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "fasteval" 7 | version = "0.2.4" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "4f4cdac9e4065d7c48e30770f8665b8cef9a3a73a63a4056a33a5f395bc7cf75" 10 | 11 | [[package]] 12 | name = "integrate" 13 | version = "1.1.0" 14 | dependencies = [ 15 | "fasteval", 16 | ] 17 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "integrate" 3 | version = "1.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | fasteval = { version = "0.2.2", features = ["unsafe-vars"] } 10 | 11 | [features] 12 | unsafe-vars = [] 13 | 14 | [profile.release] 15 | opt-level = 3 16 | debug = false 17 | debug-assertions = false 18 | overflow-checks = false 19 | lto = true 20 | panic = 'unwind' 21 | incremental = false 22 | codegen-units = 1 23 | rpath = false -------------------------------------------------------------------------------- /src/cf.rs: -------------------------------------------------------------------------------- 1 | pub fn dec_to_fraction(n: f64) -> (u64, u64) { 2 | find_convergents(&continued_fraction(n).take(16).collect::>()) 3 | } 4 | 5 | fn continued_fraction(mut n: f64) -> impl Iterator { 6 | let mut done = false; 7 | std::iter::from_fn(move || { 8 | if done { 9 | return None; 10 | } 11 | let i = n.floor(); 12 | let f = n - i; 13 | if f <= 1e-6 { 14 | done = true; 15 | } else { 16 | n = 1.0 / f; 17 | } 18 | Some(i as u64) 19 | }) 20 | } 21 | 22 | fn find_convergents(vec: &[u64]) -> (u64, u64) { 23 | fn p_n(vec: &[u64]) -> u64 { 24 | let len = vec.len(); 25 | match vec { 26 | [] => 1, 27 | [x] => *x, 28 | [.., x] => x * p_n(&vec[..(len - 1)]) + p_n(&vec[..(len - 2)]), 29 | } 30 | } 31 | fn q_n(vec: &[u64]) -> u64 { 32 | let len = vec.len(); 33 | match vec { 34 | [] => 0, 35 | [_] => 1, 36 | [.., x] => x * q_n(&vec[..(len - 1)]) + q_n(&vec[..(len - 2)]), 37 | } 38 | } 39 | (p_n(vec), q_n(vec)) 40 | } 41 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use fasteval::{Compiler, Evaler}; 2 | use std::{ 3 | alloc::{self, Layout}, 4 | io::Write, 5 | time::Instant, 6 | }; 7 | 8 | mod cf; 9 | 10 | const EPSILON: f64 = 1e-11; 11 | 12 | fn integrate( 13 | mut func: impl FnMut(f64) -> f64, 14 | lower_bound: f64, 15 | upper_bound: f64, 16 | iterations: u32, 17 | ) -> f64 { 18 | let (a, b, k) = if upper_bound > lower_bound { 19 | (lower_bound, upper_bound, 1.0) 20 | } else { 21 | (upper_bound, lower_bound, -1.0) 22 | }; 23 | let precision = (b - a) / iterations as f64; 24 | 25 | let mut area = 0.0; 26 | let mut i = lower_bound; 27 | 28 | while i <= upper_bound { 29 | area += func(i) * precision; 30 | i += precision; 31 | } 32 | 33 | if area < EPSILON { 34 | return 0.0; 35 | } else { 36 | return area * k; 37 | } 38 | } 39 | 40 | fn parse_bounds() -> (f64, f64) { 41 | print!("lower bound = "); 42 | std::io::stdout().flush().ok(); 43 | 44 | let mut input = String::new(); 45 | std::io::stdin().read_line(&mut input).unwrap(); 46 | input = input.trim().to_string(); 47 | 48 | let lower_bound: f64 = input.parse().unwrap(); 49 | 50 | print!("upper bound = "); 51 | std::io::stdout().flush().ok(); 52 | 53 | let mut input = String::new(); 54 | std::io::stdin().read_line(&mut input).unwrap(); 55 | input = input.trim().to_string(); 56 | 57 | let upper_bound: f64 = input.parse().unwrap(); 58 | 59 | return (lower_bound, upper_bound); 60 | } 61 | 62 | fn main() { 63 | unsafe { 64 | let parser = fasteval::Parser::new(); 65 | let mut slab = fasteval::Slab::new(); 66 | 67 | let layout = Layout::new::(); 68 | let x_ptr = alloc::alloc(layout); 69 | let x_ptr: *mut f64 = x_ptr as *mut f64; 70 | 71 | //* it's gonna blow up! 72 | slab.ps.add_unsafe_var("x".to_string(), &*x_ptr); 73 | 74 | print!("f(x) = "); 75 | std::io::stdout().flush().ok(); 76 | 77 | let mut input = String::new(); 78 | std::io::stdin().read_line(&mut input).unwrap(); 79 | input = input.trim().to_string(); 80 | 81 | // let expr_str = "2 * y^2"; 82 | let expr_str = input.as_str(); 83 | let compiled = parser 84 | .parse(expr_str, &mut slab.ps) 85 | .unwrap() 86 | .from(&slab.ps) 87 | .compile(&slab.ps, &mut slab.cs); 88 | 89 | let mut ns = fasteval::EmptyNamespace; 90 | let mut ns1 = fasteval::EmptyNamespace; 91 | 92 | let func = |x: f64| -> f64 { 93 | *x_ptr = x; 94 | compiled.eval(&slab, &mut ns).unwrap() 95 | }; 96 | 97 | // let func = |x: f64| -> f64 { x * x }; 98 | 99 | // just so it panics if there's something wrong 100 | { 101 | if compiled.eval(&slab, &mut ns1).is_err() { 102 | eprintln!("Bad expression"); 103 | std::process::exit(-1); 104 | } 105 | } 106 | 107 | let (lower_bound, upper_bound) = parse_bounds(); 108 | 109 | // let func = |x: f64| -> f64 { x * x }; 110 | // let lower_bound = 0.0; 111 | // let upper_bound = 1.0; 112 | 113 | let t1 = Instant::now(); 114 | 115 | let result = integrate(func, lower_bound, upper_bound, 2.6e7 as u32); 116 | let (p, q): (u64, u64) = cf::dec_to_fraction(result); 117 | 118 | let time = Instant::now() - t1; 119 | 120 | println!("Result: {result}"); 121 | println!("Possible fraction: {p}/{q}"); 122 | println!("Time: {time:?}"); 123 | } 124 | } 125 | --------------------------------------------------------------------------------