1#![forbid(unsafe_code)]
10#![no_std]
11
12use core::cmp::Ordering;
13use core::fmt::Formatter;
14use core::str::FromStr;
15use irox_tools::f64::cordic;
16pub use irox_tools::f64::FloatExt;
17pub use irox_tools::Cast;
18
19macro_rules! consts {
20 ($prim:ty, $val:literal, $shift:ident, $valt:ident, $mask:ident) => {
21 const $shift: $prim = $val;
22 const $valt: $prim = 1 << $shift;
23 const $mask: $prim = $valt - 1;
24 };
25}
26consts!(u32, 16, U32_SHIFT, U32_VAL, U32_MASK);
27consts!(i32, 16, I32_SHIFT, I32_VAL, I32_MASK);
28consts!(u64, 32, U64_SHIFT, U64_VAL, U64_MASK);
29consts!(i64, 32, I64_SHIFT, I64_VAL, I64_MASK);
30consts!(u128, 64, U128_SHIFT, U128_VAL, U128_MASK);
31consts!(i128, 64, I128_SHIFT, I128_VAL, I128_MASK);
32
33macro_rules! impl_partial_cmp_eq {
34 ($prim:ty, $($typ:tt)+) => {
35 impl core::cmp::PartialEq<$prim> for $($typ)+ {
36 fn eq(&self, other: &$prim) -> bool {
37 <$prim>::from(*self) == *other
38 }
39 }
40 impl core::cmp::PartialOrd<$prim> for $($typ)+ {
41 fn partial_cmp(&self, other: &$prim) -> Option<core::cmp::Ordering> {
42 <$prim>::partial_cmp(&self.into(), &other)
43 }
44 }
45 };
46}
47
48macro_rules! impl_fromf64 {
49 ($shift:ident, $val:ident, $mask:ident, $($typ:tt)+) => {
50 impl From<$($typ)+> for f64 {
51 fn from(value: $($typ)+) -> Self {
52 let val = (value.data >> $shift) as f64;
53 val + ((value.data & $mask) as f64 / $val as f64)
54 }
55 }
56 };
57}
58macro_rules! impl_from {
59 ($prim:ty, $shift:expr, $($typ:tt)+) => {
60 impl From<$($typ)+> for $prim {
61 fn from(value: $($typ)+) -> Self {
62 value.data >> $shift
63 }
64 }
65 };
66}
67
68macro_rules! impl_ops {
69 ($strukt:ty, $prim:ty, $next_prim:ty, $shift:ident, $($typ:tt)+) => {
70 impl core::ops::Add<$strukt> for $($typ)+ {
71 type Output = $strukt;
72
73 fn add(self, rhs: $strukt) -> Self::Output {
74 <$strukt>::from_raw_value(self.data.saturating_add(rhs.data))
75 }
76 }
77 impl core::ops::Sub<$strukt> for $($typ)+ {
78 type Output = $strukt;
79
80 fn sub(self, rhs: $strukt) -> Self::Output {
81 <$strukt>::from_raw_value(self.data.saturating_sub(rhs.data))
82 }
83 }
84 impl core::ops::AddAssign<$($typ)+> for $strukt {
85 fn add_assign(&mut self, rhs: $($typ)+) {
86 self.data = self.data.saturating_add(rhs.data)
87 }
88 }
89
90 impl core::ops::AddAssign<$($typ)+> for &mut $strukt {
91 fn add_assign(&mut self, rhs: $($typ)+) {
92 self.data = self.data.saturating_add(rhs.data)
93 }
94 }
95 impl core::ops::SubAssign<$($typ)+> for $strukt {
96 fn sub_assign(&mut self, rhs: $($typ)+) {
97 self.data = self.data.saturating_sub(rhs.data)
98 }
99 }
100
101 impl core::ops::SubAssign<$($typ)+> for &mut $strukt {
102 fn sub_assign(&mut self, rhs: $($typ)+) {
103 self.data = self.data.saturating_sub(rhs.data)
104 }
105 }
106 impl core::ops::Mul<$($typ)+> for $strukt {
107 type Output = $strukt;
108
109 fn mul(self, rhs: $($typ)+) -> Self::Output {
110 let o = (self.data as $next_prim * rhs.data as $next_prim) >> ($shift - 1);
111 let add = o & 0x01;
112 let o = (o >> 1) + add;
113 <$strukt>::from_raw_value(o as $prim)
114 }
115 }
116
117 impl core::ops::Mul<$($typ)+> for &mut $strukt {
118 type Output = $strukt;
119
120 fn mul(self, rhs: $($typ)+) -> Self::Output {
121 let o = ((self.data as $next_prim).saturating_mul(rhs.data as $next_prim)) >> ($shift - 1);
122 let add = o & 0x01;
123 let o = (o >> 1) + add;
124 <$strukt>::from_raw_value(o as $prim)
125 }
126 }
127 impl core::ops::Div<$($typ)+> for $strukt {
128 type Output = $strukt;
129
130 fn div(self, rhs: $($typ)+) -> Self::Output {
131 let a = (self.data as $next_prim) << $shift;
132 let b = (rhs.data as $next_prim);
133 let o = (a / b) as $prim;
134 <$strukt>::from_raw_value(o)
135 }
136 }
137 };
138}
139macro_rules! impl_mut_ops {
140 ($strukt:ty, $prim:ty, $next_prim:ty, $shift:ident) => {
141 impl core::ops::MulAssign for $strukt {
142 fn mul_assign(&mut self, rhs: $strukt) {
143 self.data = core::ops::Mul::mul(*self, rhs).data;
144 }
145 }
146 impl core::ops::MulAssign for &mut $strukt {
147 fn mul_assign(&mut self, rhs: &mut $strukt) {
148 self.data = core::ops::Mul::mul(**self, rhs).data;
149 }
150 }
151 impl core::ops::DivAssign for $strukt {
152 fn div_assign(&mut self, rhs: $strukt) {
153 self.data = core::ops::Div::div(*self, rhs).data;
154 }
155 }
156 impl core::ops::DivAssign for &mut $strukt {
157 fn div_assign(&mut self, rhs: &mut $strukt) {
158 self.data = core::ops::Div::div(**self, rhs).data;
159 }
160 }
161 };
162}
163macro_rules! impl_fmt_as_f64 {
164 ($typ:ty, $f:path) => {
165 impl $f for $typ {
166 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
167 <dyn $f>::fmt(&Into::<f64>::into(self), f)
168 }
169 }
170 };
171}
172macro_rules! impl_fmt_as_inner {
173 ($typ:ty, $f:path) => {
174 impl $f for $typ {
175 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
176 <dyn $f>::fmt(&self.data, f)
177 }
178 }
179 };
180}
181
182macro_rules! impl_unsigned_flops {
183 ($typ:ty, $sign:ty, $prim:ty, $lower_prim:ty, $shift:ident, $val:ident, $mask:ident) => {
184 impl core::ops::Add<f64> for $typ {
185 type Output = Self;
186 fn add(self, rhs: f64) -> Self::Output {
187 let v = <$typ>::from(rhs);
188 self + v
189 }
190 }
191 impl core::ops::AddAssign<f64> for $typ {
192 fn add_assign(&mut self, rhs: f64) {
193 *self = *self + rhs;
194 }
195 }
196 impl core::ops::AddAssign<f64> for &mut $typ {
197 fn add_assign(&mut self, rhs: f64) {
198 **self = **self + rhs;
199 }
200 }
201 impl core::ops::Sub<f64> for $typ {
202 type Output = Self;
203
204 fn sub(self, rhs: f64) -> Self::Output {
205 let v = <$typ>::from(rhs);
206 self - v
207 }
208 }
209 impl irox_tools::f64::FloatExt for $typ {
210 type Type = Self;
211 type Size = $prim;
212
213 fn trunc(self) -> Self::Type {
214 Self::from_raw_value(self.data & ($mask << $shift))
216 }
217
218 fn fract(self) -> Self::Type {
219 Self::from_raw_value(self.data & $mask)
221 }
222
223 fn abs(self) -> Self::Type {
224 self
226 }
227
228 fn round(self) -> Self::Type {
229 (self + Self::Type::ONE_HALF).trunc()
230 }
231
232 fn floor(self) -> Self::Type {
233 self.trunc()
235 }
236
237 fn ceil(self) -> Self::Type {
238 if Self::Type::fract(&self) == 0 {
239 return self;
240 }
241 Self::Type::from_parts(self.whole() + 1, 0)
242 }
243
244 fn signum(self) -> Self::Type {
245 1.into()
246 }
247
248 fn clamp(self, min: Self, max: Self) -> Self::Type {
249 if self < min {
250 return min;
251 } else if self > max {
252 return max;
253 }
254 self
255 }
256
257 fn exp(self) -> Self::Type {
260 let mut out = Self::from_parts(1, 0);
261 let i = self;
262 let mut idx = 1u16;
263 let mut next = self;
264
265 while next.abs() != 0.0 {
266 out += next;
267 idx += 1;
268 next *= i / idx;
269 }
270
271 out
272 }
273
274 fn ln(self) -> Self::Type {
277 let z = self;
278 if z == 0. {
279 return Self::Type::from_parts(1, 0);
280 }
281 let iter = (z - 1u8) / (z + 1u8);
282 let mut out = Self::Type::default();
283 let mut next = iter * 2u8;
284 let mut idx = 1 as $lower_prim;
285 let mut base = iter;
286 while !next.is_zero() {
287 out += next;
288 idx += 2;
289 base *= iter * iter;
290 next = (base * 2 as $lower_prim) / idx;
291 }
292 out
293 }
294
295 fn log10(self) -> Self::Type {
296 self.ln() / Self::LN10
297 }
298
299 fn powi(self, val: i32) -> Self::Type {
300 let mut out = self;
301 let i = self;
302 for _ in 0..val.abs() {
303 out *= i;
304 }
305 out
306 }
307
308 fn powf(self, a: Self::Type) -> Self::Type {
311 let z = self;
312
313 (a * z.ln()).exp()
314 }
315
316 fn sqrt(self) -> Self::Type {
317 self.powf(0.5.into())
318 }
319 fn to_bits(self) -> Self::Size {
320 self.raw_value()
321 }
322
323 fn exponent(self) -> u16 {
324 irox_tools::f64::FloatExt::exponent(self.as_f64())
325 }
326
327 fn significand(self) -> Self::Size {
328 irox_tools::f64::FloatExt::significand(self.as_f64()) as $prim
329 }
330
331 fn sin(self) -> Self::Type {
332 cordic(self).0
333 }
334
335 fn cos(self) -> Self::Type {
336 cordic(self).1
337 }
338 fn tan(self) -> Self::Type {
339 self.sin() / self.cos()
340 }
341 fn atan(self) -> Self::Type {
342 todo!()
343 }
344 fn atan2(self, _o: Self) -> Self::Type {
345 todo!()
346 }
347 }
348 impl irox_tools::One for $typ {
349 const ONE: Self = Self::from_parts(1, 0);
350 }
351 impl irox_tools::Zero for $typ {
352 const ZERO: Self = Self::from_parts(0, 0);
353 }
354 impl irox_tools::ToF64 for $typ {
355 fn to_f64(&self) -> f64 {
356 self.as_f64()
357 }
358 }
359 impl irox_tools::FromF64 for $typ {
360 fn from_f64(value: f64) -> Self {
361 value.into()
362 }
363 }
364 impl irox_tools::ToSigned for $typ {
365 type Output = $sign;
366 fn to_signed(self) -> Self::Output {
367 Self::Output {
368 data: self.data.cast(),
369 }
370 }
371 fn negative_one() -> Self::Output {
372 <$sign>::from_parts(-1, 0)
373 }
374 }
375 impl irox_tools::PrimitiveMath for $typ {}
376 impl irox_tools::FloatIsh for $typ {}
377 };
378}
379macro_rules! impl_signed_flops {
380 ($typ:ty, $prim:ty, $lower_prim:ty, $shift:ident, $val:ident, $mask:ident) => {
381 impl core::ops::Add<f64> for $typ {
382 type Output = Self;
383 fn add(self, rhs: f64) -> Self::Output {
384 let v = <$typ>::from(rhs);
385 self + v
386 }
387 }
388 impl core::ops::AddAssign<f64> for $typ {
389 fn add_assign(&mut self, rhs: f64) {
390 *self = *self + rhs;
391 }
392 }
393 impl core::ops::AddAssign<f64> for &mut $typ {
394 fn add_assign(&mut self, rhs: f64) {
395 **self = **self + rhs;
396 }
397 }
398 impl core::ops::Sub<f64> for $typ {
399 type Output = Self;
400
401 fn sub(self, rhs: f64) -> Self::Output {
402 let v = <$typ>::from(rhs);
403 self - v
404 }
405 }
406 impl irox_tools::One for $typ {
407 const ONE: Self = Self::from_parts(1, 0);
408 }
409 impl irox_tools::Zero for $typ {
410 const ZERO: Self = Self::from_parts(0, 0);
411 }
412 impl irox_tools::ToF64 for $typ {
413 fn to_f64(&self) -> f64 {
414 self.as_f64()
415 }
416 }
417 impl irox_tools::FromF64 for $typ {
418 fn from_f64(value: f64) -> Self {
419 value.into()
420 }
421 }
422 impl irox_tools::ToSigned for $typ {
423 type Output = Self;
424 fn to_signed(self) -> Self::Output {
425 self
426 }
427 fn negative_one() -> Self::Output {
428 Self::from_parts(-1, 0)
429 }
430 }
431 impl irox_tools::PrimitiveMath for $typ {}
432 impl irox_tools::FloatIsh for $typ {}
433 impl irox_tools::f64::FloatExt for $typ {
434 type Type = Self;
435 type Size = $prim;
436
437 fn trunc(self) -> Self::Type {
438 Self::from_raw_value(self.data & ($mask << $shift))
440 }
441
442 fn fract(self) -> Self::Type {
443 Self::from_raw_value(self.data & $mask)
445 }
446
447 fn abs(self) -> Self::Type {
448 let bm = $mask | ($mask << $shift);
449
450 Self::from_raw_value(self.data & bm)
451 }
452
453 fn round(self) -> Self::Type {
454 (self + Self::Type::ONE_HALF).trunc()
455 }
456
457 fn floor(self) -> Self::Type {
458 todo!()
459 }
460
461 fn ceil(self) -> Self::Type {
462 if Self::Type::fract(&self) == 0 {
463 return self;
464 }
465 Self::Type::from_parts(self.whole() + 1, 0)
466 }
467
468 fn signum(self) -> Self::Type {
469 1.into()
470 }
471
472 fn clamp(self, min: Self, max: Self) -> Self::Type {
473 if self < min {
474 return min;
475 } else if self > max {
476 return max;
477 }
478 self
479 }
480
481 fn exp(self) -> Self::Type {
484 let mut out = Self::from_parts(1, 0);
485 let i = self;
486 let mut idx = 1u16;
487 let mut next = self;
488
489 while next.abs() != 0.0 {
490 out += next;
491 idx += 1;
492 next *= i / idx;
493 }
494
495 out
496 }
497
498 fn ln(self) -> Self::Type {
501 let z = self;
502 if z == 0. {
503 return Self::Type::from_parts(1, 0);
504 }
505 let iter = (z - 1u8) / (z + 1u8);
506 let mut out = Self::Type::default();
507 let mut next = iter * 2u8;
508 let mut idx = 1 as $lower_prim;
509 let mut base = iter;
510 while !next.is_zero() {
511 out += next;
512 idx += 2;
513 base *= iter * iter;
514 next = (base * 2 as $lower_prim) / idx;
515 }
516 out
517 }
518 fn log10(self) -> Self::Type {
519 self.ln() / Self::LN10
520 }
521 fn powi(self, val: i32) -> Self::Type {
522 let mut out = self;
523 let i = self;
524 for _ in 0..val.abs() {
525 out *= i;
526 }
527 out
528 }
529
530 fn powf(self, a: Self::Type) -> Self::Type {
533 let z = self;
534
535 (a * z.ln()).exp()
536 }
537
538 fn sqrt(self) -> Self::Type {
539 self.powf(0.5.into())
540 }
541 fn to_bits(self) -> Self::Size {
542 self.raw_value()
543 }
544
545 fn exponent(self) -> u16 {
546 irox_tools::f64::FloatExt::exponent(self.as_f64())
547 }
548
549 fn significand(self) -> Self::Size {
550 irox_tools::f64::FloatExt::significand(self.as_f64()) as $prim
551 }
552
553 fn sin(self) -> Self::Type {
554 cordic(self).0
555 }
556
557 fn cos(self) -> Self::Type {
558 cordic(self).1
559 }
560 fn tan(self) -> Self::Type {
561 self.sin() / self.cos()
562 }
563 fn atan(self) -> Self::Type {
564 todo!()
565 }
566 fn atan2(self, _o: Self) -> Self::Type {
567 todo!()
568 }
569 }
570 };
571}
572macro_rules! impl_prim_ops {
573 ($typ:ty, $prim:ty, $rhs:ty) => {
574 impl core::ops::Add<$rhs> for $typ {
575 type Output = Self;
576
577 fn add(self, rhs: $rhs) -> Self::Output {
578 self + Self::from_parts(rhs as $prim, 0)
579 }
580 }
581 impl core::ops::Add<$typ> for $rhs {
582 type Output = $typ;
583
584 fn add(self, rhs: $typ) -> Self::Output {
585 rhs + self
586 }
587 }
588 impl core::ops::Sub<$rhs> for $typ {
589 type Output = Self;
590
591 fn sub(self, rhs: $rhs) -> Self::Output {
592 self - Self::from_parts(rhs as $prim, 0)
593 }
594 }
595 impl core::ops::Sub<$typ> for $rhs {
596 type Output = $typ;
597
598 fn sub(self, rhs: $typ) -> Self::Output {
599 <$typ>::from_parts(self as $prim, 0) - rhs
600 }
601 }
602 impl core::ops::Mul<$rhs> for $typ {
603 type Output = Self;
604
605 fn mul(self, rhs: $rhs) -> Self::Output {
606 self * Self::from_parts(rhs as $prim, 0)
607 }
608 }
609 impl core::ops::Mul<$typ> for $rhs {
610 type Output = $typ;
611
612 fn mul(self, rhs: $typ) -> Self::Output {
613 rhs * self
614 }
615 }
616 impl core::ops::Div<$rhs> for $typ {
617 type Output = Self;
618
619 fn div(self, rhs: $rhs) -> Self::Output {
620 self / Self::from_parts(rhs as $prim, 0)
621 }
622 }
623 impl core::ops::Div<$typ> for $rhs {
624 type Output = $typ;
625
626 fn div(self, rhs: $typ) -> Self::Output {
627 <$typ>::from_parts(self as $prim, 0) / rhs
628 }
629 }
630 impl core::cmp::PartialEq<$rhs> for $typ {
631 fn eq(&self, other: &$rhs) -> bool {
632 (*self).eq(&Self::from_parts(*other as $prim, 0))
633 }
634 }
635 impl core::cmp::PartialEq<$typ> for $rhs {
636 fn eq(&self, other: &$typ) -> bool {
637 <$typ>::from_parts(*self as $prim, 0).eq(other)
638 }
639 }
640 impl core::cmp::PartialOrd<$rhs> for $typ {
641 fn partial_cmp(&self, other: &$rhs) -> Option<Ordering> {
642 self.partial_cmp(&Self::from_parts(*other as $prim, 0))
643 }
644 }
645 impl core::cmp::PartialOrd<$typ> for $rhs {
646 fn partial_cmp(&self, other: &$typ) -> Option<Ordering> {
647 <$typ>::from_parts(*self as $prim, 0).partial_cmp(other)
648 }
649 }
650 };
651}
652macro_rules! impl_base {
653 ($typ:ty, $prim:ty, $lower_prim:ty, $next_prim:ty, $shift:ident, $val:ident, $mask:ident) => {
654 impl_fmt_as_f64!($typ, core::fmt::Display);
655 impl_fmt_as_f64!($typ, core::fmt::LowerExp);
656 impl_fmt_as_f64!($typ, core::fmt::UpperExp);
657 impl_fmt_as_inner!($typ, core::fmt::LowerHex);
658 impl_fmt_as_inner!($typ, core::fmt::UpperHex);
659
660 impl core::fmt::Debug for $typ {
661 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
662 let w = self.whole();
663 let p = self.fract();
664 f.write_fmt(format_args!("{}: {}/{}", stringify!($typ), w, p))
665 }
666 }
667
668 impl $typ {
669 pub const fn from_parts(whole: $lower_prim, fracs: $lower_prim) -> Self {
670 Self {
671 data: (whole as $prim) << $shift | (fracs as $prim),
672 }
673 }
674 pub const fn from_raw_value(data: $prim) -> Self {
675 Self { data }
676 }
677 pub const fn trunc(&self) -> $lower_prim {
678 (self.data >> $shift) as $lower_prim
679 }
680 pub const fn whole(&self) -> $lower_prim {
681 self.trunc()
682 }
683 pub const fn fract(&self) -> $lower_prim {
684 (self.data & $mask) as $lower_prim
685 }
686 pub const fn raw_value(&self) -> $prim {
687 self.data
688 }
689 pub fn as_f64(&self) -> f64 {
690 self.into()
691 }
692 pub const fn is_zero(&self) -> bool {
693 self.data == 0 as $prim
694 }
695 }
696
697 impl From<$prim> for $typ {
698 fn from(data: $prim) -> Self {
699 Self {
700 data: data << $shift,
701 }
702 }
703 }
704 impl From<f64> for $typ {
705 fn from(value: f64) -> Self {
706 let w = irox_tools::f64::FloatExt::floor(value) as $lower_prim;
707 let f = irox_tools::f64::FloatExt::fract(value) * <$lower_prim>::MAX as f64;
708 let f = irox_tools::f64::FloatExt::round(f) as $lower_prim;
709 Self::from_parts(w, f)
710 }
711 }
712 impl From<f32> for $typ {
713 fn from(value: f32) -> Self {
714 From::<f64>::from(value as f64)
715 }
716 }
717 impl FromStr for $typ {
718 type Err = <f64 as core::str::FromStr>::Err;
719
720 fn from_str(s: &str) -> Result<Self, Self::Err> {
721 let v = <f64 as core::str::FromStr>::from_str(s)?;
722 Ok(v.into())
723 }
724 }
725 impl core::iter::Sum for $typ {
726 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
727 let mut out = Self::default();
728 for v in iter {
729 out += v;
730 }
731 out
732 }
733 }
734 impl<'a> core::iter::Sum<&'a $typ> for $typ {
735 fn sum<I: Iterator<Item = &'a $typ>>(iter: I) -> Self {
736 let mut out = Self::default();
737 for v in iter {
738 out *= *v;
739 }
740 out
741 }
742 }
743 impl core::iter::Product for $typ {
744 fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
745 let mut out = Self::default();
746 for v in iter {
747 out *= v;
748 }
749 out
750 }
751 }
752 impl<'a> core::iter::Product<&'a $typ> for $typ {
753 fn product<I: Iterator<Item = &'a $typ>>(iter: I) -> Self {
754 let mut out = Self::default();
755 for v in iter {
756 out *= *v;
757 }
758 out
759 }
760 }
761
762 impl_fromf64!($shift, $val, $mask, $typ);
763 impl_fromf64!($shift, $val, $mask, &$typ);
764 impl_fromf64!($shift, $val, $mask, &mut $typ);
765 impl_from!($prim, $shift, $typ);
766 impl_from!($prim, $shift, &$typ);
767 impl_from!($prim, $shift, &mut $typ);
768 impl_ops!($typ, $prim, $next_prim, $shift, $typ);
769 impl_ops!($typ, $prim, $next_prim, $shift, &$typ);
770 impl_ops!($typ, $prim, $next_prim, $shift, &mut $typ);
771
772 impl_mut_ops!($typ, $prim, $next_prim, $shift);
773
774 impl_partial_cmp_eq!(f64, $typ);
775 };
776}
777
778#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
784pub struct FixedU32 {
785 data: u32,
786}
787impl FixedU32 {
788 pub const E: FixedU32 = FixedU32::from_parts(2, 47_073);
789 pub const PI: FixedU32 = FixedU32::from_parts(3, 9_279);
790 pub const ONE_HALF: FixedU32 = FixedU32::from_parts(0, 32_768);
791 pub const RESOLUTION: FixedU32 = FixedU32::from_parts(0, 1);
792 pub const LN10: FixedU32 = FixedU32::from_parts(2, 19_830);
793}
794impl_base!(FixedU32, u32, u16, u64, U32_SHIFT, U32_VAL, U32_MASK);
795impl_prim_ops!(FixedU32, u16, u8);
796impl_prim_ops!(FixedU32, u16, u16);
797impl_unsigned_flops!(FixedU32, FixedI32, u32, u16, U32_SHIFT, U32_VAL, U32_MASK);
798
799#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
805pub struct FixedI32 {
806 data: i32,
807}
808impl_base!(FixedI32, i32, i16, i64, I32_SHIFT, I32_VAL, I32_MASK);
809impl_prim_ops!(FixedI32, i16, u8);
810impl_prim_ops!(FixedI32, i16, u16);
811
812#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
818pub struct FixedU64 {
819 data: u64,
820}
821impl FixedU64 {
822 pub const E: FixedU64 = FixedU64::from_parts(2, 3_084_996_962);
823 pub const PI: FixedU64 = FixedU64::from_parts(3, 608_135_816);
824 pub const ONE_HALF: FixedU64 = FixedU64::from_parts(0, 2_147_483_648);
825 pub const RESOLUTION: FixedU64 = FixedU64::from_parts(0, 1);
826 pub const LN10: FixedU64 = FixedU64::from_parts(2, 1_299_593_075);
827}
828impl_base!(FixedU64, u64, u32, u128, U64_SHIFT, U64_VAL, U64_MASK);
829impl_unsigned_flops!(FixedU64, FixedI64, u64, u32, U64_SHIFT, U64_VAL, U64_MASK);
830impl_prim_ops!(FixedU64, u32, u8);
831impl_prim_ops!(FixedU64, u32, u16);
832impl_prim_ops!(FixedU64, u32, u32);
833
834#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
840pub struct FixedI64 {
841 data: i64,
842}
843impl_base!(FixedI64, i64, i32, i128, I64_SHIFT, I64_VAL, I64_MASK);
844impl_prim_ops!(FixedI64, i32, u8);
845impl_prim_ops!(FixedI64, i32, u16);
846impl_prim_ops!(FixedI64, i32, u32);
847
848#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
856pub struct FixedU128 {
857 data: u128,
858}
859impl FixedU128 {
860 pub const E: FixedU128 = FixedU128::from_parts(2, 13_249_961_062_380_153_450);
861 pub const PI: FixedU128 = FixedU128::from_parts(3, 2_611_923_443_488_327_891);
862 pub const ONE_HALF: FixedU128 = FixedU128::from_parts(0, 9_223_372_036_854_775_808);
863 pub const RESOLUTION: FixedU128 = FixedU128::from_parts(0, 1);
864 pub const LN10: FixedU128 = FixedU128::from_parts(2, 5_581_709_770_980_770_000);
865}
866impl_base!(FixedU128, u128, u64, u128, U128_SHIFT, U128_VAL, U128_MASK);
867impl_unsigned_flops!(FixedU128, FixedI128, u128, u64, U128_SHIFT, U128_VAL, U128_MASK);
868impl_prim_ops!(FixedU128, u64, u8);
869impl_prim_ops!(FixedU128, u64, u16);
870impl_prim_ops!(FixedU128, u64, u32);
871impl_prim_ops!(FixedU128, u64, u64);
872
873#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
882pub struct FixedI128 {
883 data: i128,
884}
885impl FixedI128 {
886 pub const PI: FixedI128 = FixedI128::from_parts(3, 2_611_923_443_488_327_891);
888 pub const ONE_HALF: FixedI128 = FixedI128::from_parts(0, 9_223_372_036_854_775_807);
889 pub const RESOLUTION: FixedI128 = FixedI128::from_parts(0, 1);
890 pub const LN10: FixedI128 = FixedI128::from_parts(2, 5_581_709_770_980_770_000);
891}
892impl_base!(FixedI128, i128, i64, i128, I128_SHIFT, I128_VAL, I128_MASK);
893impl_signed_flops!(FixedI128, i128, i64, I128_SHIFT, I128_VAL, I128_MASK);
894impl_prim_ops!(FixedI128, i64, u8);
895impl_prim_ops!(FixedI128, i64, i8);
896impl_prim_ops!(FixedI128, i64, u16);
897impl_prim_ops!(FixedI128, i64, i16);
898impl_prim_ops!(FixedI128, i64, u32);
899impl_prim_ops!(FixedI128, i64, i32);
900impl_prim_ops!(FixedI128, i64, u64);
901impl_prim_ops!(FixedI128, i64, i64);
902
903pub trait AsFixedPoint {
904 fn as_fixed_u32(&self) -> FixedU32;
905 fn as_fixed_i32(&self) -> FixedI32;
906 fn as_fixed_u64(&self) -> FixedU64;
907 fn as_fixed_i64(&self) -> FixedI64;
908 fn as_fixed_u128(&self) -> FixedU128;
909 fn as_fixed_i128(&self) -> FixedI128;
910}
911macro_rules! impl_as_fixedpt {
912 ($ty:ty) => {
913 impl AsFixedPoint for $ty {
914 fn as_fixed_u32(&self) -> FixedU32 {
915 FixedU32::from(*self)
916 }
917
918 fn as_fixed_i32(&self) -> FixedI32 {
919 FixedI32::from(*self)
920 }
921
922 fn as_fixed_u64(&self) -> FixedU64 {
923 FixedU64::from(*self)
924 }
925
926 fn as_fixed_i64(&self) -> FixedI64 {
927 FixedI64::from(*self)
928 }
929
930 fn as_fixed_u128(&self) -> FixedU128 {
931 FixedU128::from(*self)
932 }
933
934 fn as_fixed_i128(&self) -> FixedI128 {
935 FixedI128::from(*self)
936 }
937 }
938 };
939}
940impl_as_fixedpt!(f32);
941impl_as_fixedpt!(f64);