1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#![allow(non_snake_case)]

//! Standard prefixes for units

macro_rules! prefix {
    ($name: ident, $($symbol: expr),+; $scale: expr, $($doc: tt)*) => {
        #[doc = $($doc)*]
        $(
            #[doc(alias = $symbol)]
        )+
        pub const fn $name(units: $crate::SI) -> $crate::SI {
            units.scale_by($scale)
        }
    };
}

prefix!(quetta, "Q"; (10_i128.pow(30), 1), "Q: 10^30");
prefix!(ronna, "R"; (10_i128.pow(27), 1), "R: 10^27");
prefix!(yotta, "Y"; (10_i128.pow(24), 1), "Y: 10^24");
prefix!(zetta, "Z"; (10_i128.pow(21), 1), "Z: 10^21");
prefix!(exa, "E"; (10_i128.pow(18), 1), "E: 10^18");
prefix!(peta, "P"; (10_i128.pow(15), 1), "P: 10^15");
prefix!(tera, "T"; (10_i128.pow(12), 1), "T: 10^12");
prefix!(giga, "G"; (10_i128.pow(9), 1), "G: 10^9");
prefix!(mega, "M"; (1_000_000, 1), "M: 1 000 000");
prefix!(kilo, "k"; (1_000, 1), "k: 1000");
prefix!(hecto, "h"; (100, 1), "h: 100");
prefix!(deca, "da"; (10, 1), "da: 10");

prefix!(deci, "d"; (1, 10), "d: 0.1");
prefix!(centi, "c"; (1, 100), "c: 0.01");
prefix!(milli, "m"; (1, 1_000), "m: 0.001");
prefix!(micro, "u", "mu", "μ"; (1, 1_000_000), "μ: 10^-6");
prefix!(nano, "n"; (1, 10_u128.pow(9)), "n: 10^-9");
prefix!(pico, "p"; (1, 10_u128.pow(12)), "p: 10^-12");
prefix!(femto, "f"; (1, 10_u128.pow(15)), "f: 10^-15");
prefix!(atto, "a"; (1, 10_u128.pow(18)), "a: 10^-18");
prefix!(zepto, "z"; (1, 10_u128.pow(21)), "z: 10^-21");
prefix!(yocto, "y"; (1, 10_u128.pow(24)), "y: 10^-24");
prefix!(ronto, "r"; (1, 10_u128.pow(27)), "r: 10^-27");
prefix!(quecto, "q"; (1, 10_u128.pow(30)), "q: 10^-30");

// Must be sorted for binary search
pub(crate) const PREFIX_MAP: [(&str, (i128, u128)); 25] = [
    ("E", (10_i128.pow(18), 1)),
    ("G", (10_i128.pow(9), 1)),
    ("M", (1_000_000, 1)),
    ("P", (10_i128.pow(15), 1)),
    ("Q", (10_i128.pow(30), 1)),
    ("R", (10_i128.pow(27), 1)),
    ("T", (10_i128.pow(12), 1)),
    ("Y", (10_i128.pow(24), 1)),
    ("Z", (10_i128.pow(21), 1)),
    ("a", (1, 10_u128.pow(18))),
    ("c", (1, 100)),
    ("d", (1, 10)),
    ("da", (10, 1)),
    ("f", (1, 10_u128.pow(15))),
    ("h", (100, 1)),
    ("k", (1_000, 1)),
    ("m", (1, 1_000)),
    ("n", (1, 10_u128.pow(9))),
    ("p", (1, 10_u128.pow(12))),
    ("q", (1, 10_u128.pow(30))),
    ("r", (1, 10_u128.pow(27))),
    ("u", (1, 1_000_000)),
    ("y", (1, 10_u128.pow(24))),
    ("z", (1, 10_u128.pow(21))),
    ("μ", (1, 1_000_000)),
];

#[cfg(test)]
mod tests {
    use crate::prefixes::PREFIX_MAP;

    #[test]
    fn is_sorted() {
        for i in 0..PREFIX_MAP.len() - 1 {
            assert!(PREFIX_MAP[i].0 < PREFIX_MAP[i + 1].0);
        }
    }
}