Last active 1741880459

ecalculator.rs Raw
1use std::time::Instant;
2use rand::prelude::*;
3use std::f64::consts;
4use console::Term;
5use std::sync::atomic::{AtomicBool, Ordering};
6use std::sync::Arc;
7
8fn main() {
9 //Handler to terminate on CTRL+C
10 let running = Arc::new(AtomicBool::new(true));
11 let r = running.clone();
12 ctrlc::set_handler(move || {
13 r.store(false, Ordering::SeqCst);
14 println!();
15 }).expect("Error setting Ctrl-C handler");
16
17 let term = Term::stdout();
18
19 //Parses env 'SHOW_PROGRESS', value must be an int and sets how frequent to log progress
20 //If has a value, should log progress.
21 let log_interval: Option<u64> = match std::env::var("SHOW_PROGRESS").ok() {
22 Some(value) => Some(value.parse::<u64>().expect("not a valid integer")),
23 None => None
24 };
25
26 //Gets the maximum loops to run or none for infinity
27 let max_loops: Option<u64> = match std::env::var("LOOPS") {
28 Ok(val) => Some(val.parse::<u64>().expect("not a valid integer")),
29 _ => None
30 };
31
32 match max_loops {
33 Some(max_loops) => {
34 println!("Running {} iterations. Press CTRL+C to exit at any time.", max_loops);
35 run_limited(term, running, log_interval, max_loops);
36 },
37 None => {
38 println!("No maximum loops specified, running forever. Press CTRL+C to exit at any time.");
39 run_unlimited(term, running, log_interval);
40 }
41 }
42}
43
44//Runs upto X times
45fn run_limited(term: Term, running: Arc<AtomicBool>, log_interval: Option<u64>, max_loops: u64) {
46 let now = Instant::now();
47
48 let mut total_count: u64 = 0;
49 let mut count: u64;
50 let mut sum: f64;
51
52 //Print header only if showing progress
53 if log_interval.is_some() {
54 println!("Iteration\tValue \t% Err\tCurrent %\tTime Elapsed");
55 }
56
57 for i in 0..max_loops {
58 count = 0;
59 sum = 0.0;
60 //Run until sum hits 1.0
61 while sum <= 1.0 {
62 count += 1;
63 sum += rand::thread_rng().gen::<f64>();
64 }
65
66 total_count += count;
67
68 //Prints progress:
69 if log_interval.is_some() && i % log_interval.unwrap() == 0 {
70 let average = total_count as f64 / i as f64;
71 let pererror = (average - consts::E).abs() / consts::E * 100.0;
72 let cur_percent = i as f64 / max_loops as f64 * 100.0;
73 term.write_line(&format!(" {:9.10}\t{:.10}\t{:5.2}%\t{:9.2}%\t{:?}", i, average, pererror, cur_percent, now.elapsed())).ok();
74 term.move_cursor_up(1).ok();
75 }
76
77 //Checks if CTRL+C was called, end loop here
78 if !running.load(Ordering::SeqCst) {
79 break;
80 }
81 }
82
83 let average = total_count as f64 / max_loops as f64;
84 let pererror = (average - consts::E).abs() / consts::E * 100.0;
85 println!("---------------------------");
86 println!("Iterations: {}", max_loops);
87 println!("Final Average: {}", average);
88 println!("Final % Error: {:.4}%", pererror);
89 println!("Took: {:?}", now.elapsed());
90}
91
92fn run_unlimited(term: Term, running: Arc<AtomicBool>, log_interval: Option<u64>) {
93 let now = Instant::now();
94 let mut total_count: u64 = 0;
95 let mut count: u64;
96 let mut sum: f64;
97 let mut i: u64 = 0;
98
99 if log_interval.is_some() {
100 println!("Iteration\tValue \t% Err\tTime Elapsed");
101 }
102
103 loop {
104 count = 0;
105 sum = 0.0;
106 //Run until sum hits 1.0
107 while sum <= 1.0 {
108 count += 1;
109 sum += rand::thread_rng().gen::<f64>();
110 }
111
112 total_count += count;
113
114 //Prints progress:
115 if log_interval.is_some() && i % log_interval.unwrap() == 0 {
116 let average = total_count as f64 / i as f64;
117 let pererror = (average - consts::E).abs() / consts::E * 100.0;
118 term.write_line(&format!(" {:9.10}\t{:.10}\t{:5.2}%\t{:?}", i, average, pererror, now.elapsed())).ok();
119 term.move_cursor_up(1).ok();
120 }
121
122 //Checks if CTRL+C was called, end loop here
123 if !running.load(Ordering::SeqCst) {
124 break;
125 }
126
127 i += 1;
128 }
129
130 let average = total_count as f64 / i as f64;
131 let pererror = (average - consts::E).abs() / consts::E * 100.0;
132 println!("---------------------------");
133 println!("Iterations: {}", i);
134 println!("Final Average: {}", average);
135 println!("Final % Error: {:.4}%", pererror);
136 println!("Took: {:?}", now.elapsed());
137}