1use hexf::hexf32 as h;
28
29pub fn cr_cbrtf16(x: f16) -> f16 {
30 const TM: [u16; 16] = [
31 0x00, 0xff, 0xff, 0xff, 0x33, 0x1c, 0x32, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff,
32 0x10,
33 ];
34 const TE: [u16; 16] = [0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0];
35 const TF: [u16; 16] = [
36 0x3c00, 0, 0, 0, 0x3d80, 0x3f00, 0x3c80, 0, 0, 0, 0, 0x3e00, 0, 0, 0, 0x3d00,
37 ];
38
39 let t = x;
40 let mut tu = t.to_bits();
41 let xf = f32::from(x);
42 let xu = xf.to_bits();
43 if u32::from(TM[((xu >> 19) % 16) as usize]) == ((xu >> 13) % 64) {
44 let expo = ((xu & 0x7fffffff) >> 23) as i32;
46 if (i32::from(TE[((xu >> 19) % 16) as usize]) == ((expo + 2) % 3))
47 && (
48 (expo & 0xff) != 0xff
50 )
52 {
53 tu = u32::from(tu & 0x8000)
54 .wrapping_add(
55 (((expo - 127 - i32::from(TE[((xu >> 19) % 16) as usize])) / 3) as u32) << 10,
56 )
57 .wrapping_add(u32::from(TF[((xu >> 19) % 16) as usize])) as u16;
58 return f16::from_bits(tu);
59 }
60 }
61 if (tu & 0x03ff) == 0x0151 {
62 let expo = i32::from((tu & 0x7fff) >> 10);
64 if ((expo % 3) == 1) && (expo < 31) {
65 tu = ((((expo - 16) / 3 + 15) << 10) + 0x018b + i32::from((tu >> 15) << 15)) as u16;
67 return (f32::from(f16::from_bits(tu)) + h!("0x1p-16") * (f32::from(tu >> 15) - 0.5))
68 as f16;
69 }
70 }
71 xf.cbrt() as f16
73}
74
75#[cfg(test)]
76mod tests {
77 #[test]
78 fn exhaustive() {
79 for b in 0..=u16::MAX {
80 let x = f16::from_bits(b);
81 let y1 = super::cr_cbrtf16(x);
82 let y2 = core_math::cbrtf16(x);
83 assert_eq!(
84 y1.to_bits(),
85 y2.to_bits(),
86 "cbrtf16({x} @ {b:#04x}) = ({y1} @ {y1b:#04x}) vs ({y2} @ {y2b:#04x})",
87 y1b = y1.to_bits(),
88 y2b = y2.to_bits()
89 );
90 }
91 }
92
93 #[test]
94 fn edge() {
95 assert_eq!(
96 super::cr_cbrtf16(-f16::NAN).to_bits(),
97 (-f16::NAN).to_bits()
98 );
99 assert_eq!(super::cr_cbrtf16(-f16::INFINITY), -f16::INFINITY);
100 assert_eq!(super::cr_cbrtf16(-1.0), -1.0);
101 assert_eq!(super::cr_cbrtf16(-0.0).to_bits(), (-0.0_f16).to_bits());
102 assert_eq!(super::cr_cbrtf16(0.0).to_bits(), (0.0_f16).to_bits());
103 assert_eq!(super::cr_cbrtf16(1.0), 1.0);
104 assert_eq!(super::cr_cbrtf16(f16::INFINITY), f16::INFINITY);
105 assert_eq!(super::cr_cbrtf16(f16::NAN).to_bits(), (f16::NAN).to_bits());
106 }
107}