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