softposit/p16e1/math/
sin_pi.rs1use super::P16E1;
2
3impl P16E1 {
4 pub const fn sin_pi(self) -> Self {
5 let ui_a = self.to_bits();
6
7 let mut f = ui_a as u64;
8
9 let mut sign = f & 0x8000;
10 if sign != 0 {
11 f = 0x10000 - f; }
13 if f > 31743 {
14 if f == 0x8000 {
16 return Self::NAR; } else {
18 return Self::ZERO; }
20 }
21 if f == 0 {
22 return Self::ZERO;
24 }
25 let mut s: i32;
26 if (f & 0x4000) != 0 {
27 s = 16;
29 while (f & 0x2000) != 0 {
30 f <<= 1;
31 s += 2;
32 }
33 } else {
34 s = 14;
35 while (f & 0x2000) == 0 {
36 f <<= 1;
37 s -= 2;
38 }
39 }
40 if (f & 0x1000) != 0 {
41 s += 1; }
43 f = (f & 0x0FFF) | 0x1000; f = if s < 0 { f >> -s } else { f << s };
45 f &= 0x_1FFF_FFFF; let mut s = f >> 27; f &= 0x_07FF_FFFF; if (s & 2) != 0 {
49 sign ^= 0x8000; }
51 if f == 0 {
52 return Self::from_bits(if (s & 1) != 0 {
53 (sign as u16) | 0x4000
54 } else {
55 0
56 });
57 }
58 if (s & 1) != 0 {
59 f = 0x_0800_0000 - f;
60 }
61 f = poly(f);
62 s = 1; while (f & 0x_0800_0000) == 0 {
64 f <<= 1;
65 s += 1;
66 }
67 let bit = s & 1;
68 s = (s >> 1) + 14 + bit;
69 if bit == 0 {
70 f &= 0x_07FF_FFFF; }
72 f |= 0x_1000_0000; let bit = 1_u64 << (s - 1);
74 if ((f & bit) != 0) && (((f & (bit - 1)) != 0) || ((f & (bit << 1)) != 0)) {
75 f += bit;
77 }
78 f >>= s;
79 Self::from_bits((if sign != 0 { 0x10000 - f } else { f }) as u16)
80 }
81}
82
83#[inline]
84const fn poly(f: u64) -> u64 {
85 if f < 0x_000A_5801 {
86 return (f * 102_943) >> 15; }
88 let fs = f >> 11;
89 let fsq = (fs * fs) >> 8;
90 let mut s = (fsq * 650) >> 25;
91 s = (fsq * (9_813 - s)) >> 23;
92 s = (fsq * (334_253 - s)) >> 23;
93 s = (fsq * (5_418_741 - s)) >> 22;
94 (fs * (52_707_180 - s)) >> 13
95}
96
97#[test]
98fn test_sin_pi() {
99 use rand::Rng;
100 let mut rng = rand::thread_rng();
101 for _ in 0..crate::NTESTS16 {
102 let p_a: P16E1 = rng.gen();
103 let f_a = f64::from(p_a);
104 let p = p_a.sin_pi();
105 let f = (f_a * core::f64::consts::PI).sin();
106 let expected = P16E1::from(f);
107 if p.is_zero() {
108 continue;
109 }
110 assert_eq!(p, expected);
111 }
112}