1#![no_std]
2
3use core::cmp::*;
4use core::fmt;
5use core::ops::*;
6
7pub type DF = DyadicFraction;
8
9#[derive(Copy, Clone, Debug, Default)]
10pub struct DyadicFraction {
11 num: i32,
12 power: i8,
13}
14
15impl DyadicFraction {
16 pub const fn new(numerator: i32, denominator_power: i8) -> Self {
17 Self {
18 num: numerator,
19 power: denominator_power,
20 }
21 .canonical()
22 }
23
24 pub const fn zero() -> Self {
25 Self { num: 0, power: 0 }
26 }
27
28 pub const fn abs(self) -> Self {
29 Self::new(self.num.abs(), self.power)
30 }
31
32 pub const fn signum(self) -> Self {
33 Self::new(self.num.signum(), 0)
34 }
35
36 pub const fn copysign(self, sign: i32) -> Self {
37 if sign.signum() == self.num.signum() {
38 return self;
39 }
40 Self::new(-self.num, self.power)
41 }
42
43 pub const fn is_positive(self) -> bool {
44 self.num.is_positive()
45 }
46
47 pub const fn is_negative(self) -> bool {
48 self.num.is_negative()
49 }
50
51 pub const fn canonical(&self) -> Self {
52 let mut res = *self;
53 if res.num == 0 {
54 res.power = 0;
55 }
56 while res.power > 0 && (res.num & 1) == 0 {
57 res.power -= 1;
58 res.num >>= 1;
59 }
60 res
61 }
62
63 pub const fn round(&self, denominator_power: i8) -> Self {
64 let mut res = *self;
65 if res.num == 0 {
66 res.power = 0;
67 }
68 loop {
69 while res.power > 0 && (res.num & 1) == 0 {
70 res.power -= 1;
71 res.num >>= 1;
72 }
73 if res.power > denominator_power {
74 res.num &= !1;
75 } else {
76 break;
77 }
78 }
79 res
80 }
81
82 pub fn floor(&self) -> i32 {
83 let val = self.canonical();
84 let shift = val.power.abs();
85 if val.power <= 0 {
86 saturating_shl(val.num, shift)
87 } else {
88 saturating_shr(val.num, shift)
89 }
90 }
91
92 pub fn div_by_two(&self) -> Self {
93 let mut res = *self;
94 res.power = res.power.saturating_add(1);
95 res
96 }
97
98 pub fn mul_add(self, a: impl Into<Self>, b: impl Into<Self>) -> Self {
99 self * a.into() + b.into()
100 }
101
102 pub fn scale(self, a: impl Into<Self>) -> i32 {
103 self.canonical().mul(a.into()).floor()
104 }
105
106 pub fn pow(self, n: u8) -> Self {
107 if n == 0 {
108 return self.signum();
109 }
110 let mut res = self;
111 for _ in 0..n - 1 {
112 res *= self;
113 }
114 res
115 }
116
117 pub fn max(lhs: Self, rhs: Self) -> Self {
118 if lhs > rhs {
119 lhs
120 } else {
121 rhs
122 }
123 }
124
125 pub fn min(lhs: Self, rhs: Self) -> Self {
126 if lhs < rhs {
127 lhs
128 } else {
129 rhs
130 }
131 }
132
133 pub fn numerator(&self) -> i32 {
134 self.num
135 }
136
137 pub fn denominator_power(&self) -> i8 {
138 self.power
139 }
140
141 fn saturating_cross(self, other: Self) -> (i32, i32, i8) {
142 let (min_power, max_power) = if self.power > other.power {
143 (other.power, self.power)
144 } else {
145 (self.power, other.power)
146 };
147 (
148 saturating_shl(self.num, other.power - min_power),
149 saturating_shl(other.num, self.power - min_power),
150 max_power,
151 )
152 }
153}
154
155fn saturating_shl(num: i32, rhs: i8) -> i32 {
156 if rhs < 32 {
157 num.shl(rhs)
158 } else if num.is_positive() {
159 i32::MAX
160 } else {
161 i32::MIN
162 }
163}
164
165fn saturating_shr(num: i32, rhs: i8) -> i32 {
166 if rhs < 32 {
167 num.shr(rhs)
168 } else {
169 0
170 }
171}
172
173impl From<i32> for DyadicFraction {
174 fn from(num: i32) -> Self {
175 Self::new(num, 0)
176 }
177}
178
179impl From<isize> for DyadicFraction {
180 fn from(num: isize) -> Self {
181 Self::new(num as _, 0)
182 }
183}
184
185impl From<i16> for DyadicFraction {
186 fn from(num: i16) -> Self {
187 Self::new(num as _, 0)
188 }
189}
190
191impl From<u16> for DyadicFraction {
192 fn from(num: u16) -> Self {
193 Self::new(num as _, 0)
194 }
195}
196
197impl From<u8> for DyadicFraction {
198 fn from(num: u8) -> Self {
199 Self::new(num as _, 0)
200 }
201}
202
203impl From<i8> for DyadicFraction {
204 fn from(num: i8) -> Self {
205 Self::new(num as _, 0)
206 }
207}
208
209impl Add for DyadicFraction {
210 type Output = Self;
211
212 fn add(self, other: Self) -> Self {
213 let (fst, snd, power) = self.saturating_cross(other);
214 Self::new(fst.saturating_add(snd), power)
215 }
216}
217
218impl AddAssign for DyadicFraction {
219 fn add_assign(&mut self, rhs: Self) {
220 *self = *self + rhs;
221 }
222}
223
224impl Sub for DyadicFraction {
225 type Output = Self;
226
227 fn sub(self, other: Self) -> Self {
228 let (fst, snd, power) = self.saturating_cross(other);
229 Self::new(fst.saturating_sub(snd), power)
230 }
231}
232
233impl SubAssign for DyadicFraction {
234 fn sub_assign(&mut self, rhs: Self) {
235 *self = *self - rhs;
236 }
237}
238
239impl Mul for DyadicFraction {
240 type Output = Self;
241
242 fn mul(self, other: Self) -> Self {
243 Self::new(
244 self.num.saturating_mul(other.num),
245 self.power.saturating_add(other.power),
246 )
247 .canonical()
248 }
249}
250
251impl MulAssign for DyadicFraction {
252 fn mul_assign(&mut self, rhs: Self) {
253 *self = *self * rhs;
254 }
255}
256
257impl Neg for DyadicFraction {
258 type Output = Self;
259
260 fn neg(self) -> Self::Output {
261 Self::new(-self.num, self.power)
262 }
263}
264
265impl PartialEq for DyadicFraction {
266 fn eq(&self, other: &Self) -> bool {
267 let lhs = self.canonical();
268 let rhs = other.canonical();
269 lhs.power == rhs.power && lhs.num == rhs.num
270 }
271}
272
273impl Eq for DyadicFraction {}
274
275impl PartialOrd for DyadicFraction {
276 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
277 Some(self.cmp(other))
278 }
279}
280
281impl Ord for DyadicFraction {
282 fn cmp(&self, other: &Self) -> Ordering {
283 let delta = (*self - *other).numerator().signum();
284 if delta == 0 {
285 Ordering::Equal
286 } else if delta.is_positive() {
287 Ordering::Greater
288 } else {
289 Ordering::Less
290 }
291 }
292}
293
294impl fmt::Display for DyadicFraction {
295 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
296 let val = self.canonical();
297 let shift = val.power.abs();
298 if val.power <= 0 {
299 write!(f, "{}", saturating_shl(val.num, shift))
300 } else {
301 write!(f, "{}/{}", val.num, saturating_shl(1, shift))
302 }
303 }
304}
305
306pub mod consts {
307 use super::*;
308
309 pub const TAU: DyadicFraction = DyadicFraction::new(3217, 9);
313
314 pub const PI: DyadicFraction = DyadicFraction::new(3217, 10);
316
317 pub const FRAC_PI_2: DyadicFraction = DyadicFraction::new(3217, 11);
319
320 pub const FRAC_PI_4: DyadicFraction = DyadicFraction::new(3217, 12);
322
323 pub const FRAC_PI_3: DyadicFraction = DyadicFraction::new(68629, 16);
325
326 pub const FRAC_1_PI: DyadicFraction = DyadicFraction::new(20861, 16);
328
329 pub const FRAC_2_PI: DyadicFraction = DyadicFraction::new(20861, 15);
331
332 pub const FRAC_2_SQRT_PI: DyadicFraction = DyadicFraction::new(73949, 16);
334
335 pub const SQRT_2: DyadicFraction = DyadicFraction::new(46341, 15);
337
338 pub const FRAC_1_SQRT_2: DyadicFraction = DyadicFraction::new(46341, 16);
340
341 pub const E: DyadicFraction = DyadicFraction::new(178145, 16);
343
344 pub const LOG2_10: DyadicFraction = DyadicFraction::new(108853, 15);
346
347 pub const LOG2_E: DyadicFraction = DyadicFraction::new(23637, 14);
349
350 pub const LOG10_2: DyadicFraction = DyadicFraction::new(1233, 12);
352
353 pub const LOG10_E: DyadicFraction = DyadicFraction::new(14231, 15);
355
356 pub const LN_2: DyadicFraction = DyadicFraction::new(22713, 15);
358
359 pub const LN_10: DyadicFraction = DyadicFraction::new(75451, 15);
361
362 pub const PHI: DyadicFraction = DyadicFraction::new(13255, 13);
364
365 pub const PSI: DyadicFraction = DyadicFraction::new(6003, 12);
367}