ebi/
exact.rs

1use anyhow::Result;
2use std::sync::atomic::AtomicBool;
3
4//======================== exactness tools ========================//
5
6static EXACT: AtomicBool = AtomicBool::new(true);
7
8/// Enables or disables exact arithmetic globally.
9/// Exact arithmetic cannot be combined with approximate arithmetic.
10pub fn set_exact_globally(exact: bool) {
11    EXACT.store(exact, std::sync::atomic::Ordering::Relaxed);
12}
13
14pub fn is_exact_globally() -> bool {
15    if cfg!(any(
16        all(
17            feature = "exactarithmetic",
18            feature = "approximatearithmetic"
19        ),
20        all(
21            not(feature = "exactarithmetic"),
22            not(feature = "approximatearithmetic")
23        )
24    )) {
25        EXACT.load(std::sync::atomic::Ordering::Relaxed)
26    } else if cfg!(feature = "exactarithmetic") {
27        true
28    } else {
29        false
30    }
31}
32
33//======================== exactness trait ========================//
34pub trait MaybeExact {
35    type Approximate;
36    type Exact;
37
38    fn is_exact(&self) -> bool;
39
40    /**
41     * This is a low-level function to extract an f64. Will only succeed if the fraction is approximate.
42     */
43    fn extract_approx(&self) -> Result<Self::Approximate>;
44
45    /**
46     * This is a low-level function to extract an exact value. Will only succeed if the fraction is exact.
47     */
48    fn extract_exact(&self) -> Result<&Self::Exact>;
49}