memo_int_sqrt/
lib.rs

1pub mod tables {
2    include!(concat!(env!("OUT_DIR"), "/tables.rs"));
3}
4
5pub mod u8 {
6    pub mod f32 {
7        pub fn sqrt(x: u8) -> f32 {
8            crate::tables::SQRT_F32[x as usize]
9        }
10        pub fn inv_sqrt(x: u8) -> f32 {
11            crate::tables::INV_SQRT_F32[x as usize]
12        }
13    }
14    pub mod f64 {
15        pub fn sqrt(x: u8) -> f64 {
16            crate::tables::SQRT_F64[x as usize]
17        }
18        pub fn inv_sqrt(x: u8) -> f64 {
19            crate::tables::INV_SQRT_F64[x as usize]
20        }
21    }
22}
23
24macro_rules! generate_inner {
25    ($in:ident, $out:ident) => {
26        pub mod $out {
27            pub fn sqrt(x: $in) -> $out {
28                if x < 256 {
29                    crate::u8::$out::sqrt(x as u8)
30                } else {
31                    (x as $out).sqrt()
32                }
33            }
34            pub fn inv_sqrt(x: $in) -> $out {
35                if x < 256 {
36                    crate::u8::$out::inv_sqrt(x as u8)
37                } else {
38                    (x as $out).sqrt().recip()
39                }
40            }
41        }
42    };
43}
44macro_rules! generate {
45    ($in:ident) => {
46        pub mod $in {
47            generate_inner!($in, f32);
48            generate_inner!($in, f64);
49        }
50    };
51}
52generate!(u16);
53generate!(u32);
54generate!(u64);
55generate!(u128);
56
57#[cfg(test)]
58mod test {
59    macro_rules! test {
60        ($in:ident, $count:expr) => {
61            #[test]
62            fn $in() {
63                for x in 0..$count {
64                    assert_eq!((x as f32).sqrt(), crate::$in::f32::sqrt(x as $in));
65                    assert_eq!((x as f32).sqrt().recip(), crate::$in::f32::inv_sqrt(x as $in));
66                    assert_eq!((x as f64).sqrt(), crate::$in::f64::sqrt(x as $in));
67                    assert_eq!((x as f64).sqrt().recip(), crate::$in::f64::inv_sqrt(x as $in));
68                }
69            }
70        };
71    }
72    test!(u8, 255);
73    test!(u16, 1024);
74    test!(u32, 1024);
75    test!(u64, 1024);
76    test!(u128, 1024);
77
78    #[test]
79    fn specific_values() {
80        assert_eq!(crate::u8::f32::sqrt(16), 4.);
81        assert_eq!(crate::u8::f32::inv_sqrt(16), 0.25);
82    }
83}