use std::f64::consts;
use super::tolerance;
#[macro_export]
macro_rules! frac {
($n:tt / $d:tt) => {
(($n as f64) / ($d as f64))
};
($n:tt) => {
($n as f64)
};
}
#[macro_export]
macro_rules! frac_pi {
($n:tt / $d:tt) => {
(($n as f64) / ($d as f64)) * consts::PI
};
($n:tt) => {
($n as f64) * consts::PI
};
}
pub fn as_frac(value: f64) -> (f64, f64) {
if tolerance::is_zero(value) {
return (0.0, 1.0);
}
let sign = value.signum();
let mut val = value.abs();
let mut num_prev = 0.0;
let mut den_prev = 1.0;
let mut num_curr = 1.0;
let mut den_curr = 0.0;
for _ in 0..64 {
let a = val.floor();
let num_next = a * num_curr + num_prev;
let den_next = a * den_curr + den_prev;
if den_next > 1_000_000.0 {
break;
}
num_prev = num_curr;
den_prev = den_curr;
num_curr = num_next;
den_curr = den_next;
let diff = val - a;
if tolerance::is_zero(diff) {
break;
}
val = 1.0 / diff;
}
(sign * num_curr, den_curr)
}
pub fn as_frac_pi(value: f64) -> (f64, f64) { as_frac(value / consts::PI) }