1use std::{
2 cmp::Ordering,
3 fmt::{Debug, Display},
4 ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
5 str::FromStr,
6};
7
8use num_traits::{CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, One, Zero, cast};
9
10use crate::{
11 Halfway, OutOfRange, ParseDecimalError, checked_pow10, debug_decimal, display_decimal,
12 div_ceil, div_floor, i128_mul_pow10_round_even, parse_decimal, pow10, round_inner, u256::I256,
13};
14
15#[derive(Copy, Clone, Default, Eq, Ord, Hash)]
41#[cfg_attr(feature = "size_of", derive(size_of::SizeOf))]
42pub struct Fixed<const P: usize, const S: usize>(pub(super) i128);
43
44impl<const P0: usize, const S0: usize, const P1: usize, const S1: usize> PartialEq<Fixed<P1, S1>>
45 for Fixed<P0, S0>
46{
47 fn eq(&self, other: &Fixed<P1, S1>) -> bool {
48 match S0.cmp(&S1) {
49 Ordering::Less => I256::from_product(self.0, pow10(S1 - S0)) == I256::from(other.0),
50 Ordering::Equal => self.0 == other.0,
51 Ordering::Greater => I256::from(self.0) == I256::from_product(other.0, pow10(S0 - S1)),
52 }
53 }
54}
55
56macro_rules! partial_eq_int {
57 ($type_name:ty) => {
58 impl<const P0: usize, const S0: usize> PartialEq<$type_name> for Fixed<P0, S0> {
59 fn eq(&self, other: &$type_name) -> bool {
60 self.0 % Self::scale() == 0 && self.0 / Self::scale() == *other as i128
61 }
62 }
63 };
64}
65partial_eq_int!(i8);
66partial_eq_int!(i16);
67partial_eq_int!(i32);
68partial_eq_int!(i64);
69partial_eq_int!(i128);
70partial_eq_int!(isize);
71partial_eq_int!(u8);
72partial_eq_int!(u16);
73partial_eq_int!(u32);
74partial_eq_int!(u64);
75
76impl<const P0: usize, const S0: usize> PartialEq<u128> for Fixed<P0, S0> {
77 fn eq(&self, other: &u128) -> bool {
78 self.0 >= 0
79 && self.0 % Self::scale() == 0
80 && (self.0 / Self::scale()).cast_unsigned() == *other
81 }
82}
83
84impl<const P0: usize, const S0: usize> PartialEq<usize> for Fixed<P0, S0> {
85 fn eq(&self, other: &usize) -> bool {
86 self.0 >= 0
87 && self.0 % Self::scale() == 0
88 && (self.0 / Self::scale()).cast_unsigned() == *other as u128
89 }
90}
91
92impl<const P0: usize, const S0: usize, const P1: usize, const S1: usize> PartialOrd<Fixed<P1, S1>>
93 for Fixed<P0, S0>
94{
95 fn partial_cmp(&self, other: &Fixed<P1, S1>) -> Option<Ordering> {
96 match S0.cmp(&S1) {
97 Ordering::Less => {
98 I256::from_product(self.0, pow10(S1 - S0)).partial_cmp(&I256::from(other.0))
99 }
100 Ordering::Equal => self.0.partial_cmp(&other.0),
101 Ordering::Greater => {
102 I256::from(self.0).partial_cmp(&I256::from_product(other.0, pow10(S0 - S1)))
103 }
104 }
105 }
106}
107
108impl<const P: usize, const S: usize> Fixed<P, S> {
109 pub const MAX: Self = Self(pow10(P) - 1);
111
112 pub const MIN: Self = Self(-Self::MAX.0);
116
117 pub const ZERO: Self = Self(0);
119
120 pub const ONE: Self = {
127 if S < P {
128 Self(pow10(S))
129 } else {
130 panic!("all values of Fixed::<S,P>::one() for S >= P have magnitude less than one");
131 }
132 };
133
134 pub fn mantissa(&self) -> i128 {
140 self.0
141 }
142
143 pub const fn for_i64(value: i64) -> Self {
149 assert!(P.saturating_sub(S) >= 19);
150 Self(value as i128 * Self::scale())
151 }
152
153 pub const fn for_u64(value: u64) -> Self {
159 assert!(P.saturating_sub(S) >= 19);
160 Self(value as i128 * Self::scale())
161 }
162
163 pub const fn for_i32(value: i32) -> Self {
169 assert!(P.saturating_sub(S) >= 10);
170 Self(value as i128 * Self::scale())
171 }
172
173 pub const fn for_u32(value: u32) -> Self {
179 assert!(P.saturating_sub(S) >= 10);
180 Self(value as i128 * Self::scale())
181 }
182
183 pub const fn for_i16(value: i16) -> Self {
189 assert!(P.saturating_sub(S) >= 5);
190 Self(value as i128 * Self::scale())
191 }
192
193 pub const fn for_u16(value: u16) -> Self {
199 assert!(P.saturating_sub(S) >= 5);
200 Self(value as i128 * Self::scale())
201 }
202
203 pub const fn for_i8(value: i8) -> Self {
209 assert!(P.saturating_sub(S) >= 3);
210 Self(value as i128 * Self::scale())
211 }
212
213 pub const fn for_u8(value: u8) -> Self {
219 assert!(P.saturating_sub(S) >= 3);
220 Self(value as i128 * Self::scale())
221 }
222
223 pub const fn for_isize(value: isize) -> Self {
229 match isize::BITS {
230 64 => Self::for_i64(value as i64),
231 32 => Self::for_i32(value as i32),
232 16 => Self::for_i16(value as i16),
233 _ => panic!(),
234 }
235 }
236
237 pub const fn for_usize(value: usize) -> Self {
243 match usize::BITS {
244 64 => Self::for_u64(value as u64),
245 32 => Self::for_u32(value as u32),
246 16 => Self::for_u16(value as u16),
247 _ => panic!(),
248 }
249 }
250
251 pub fn new(value: i128, scale: i32) -> Option<Self> {
266 Self::try_new_with_exponent(value, (S as i32).saturating_sub(scale))
267 }
268
269 pub fn new_round_even(value: i128, scale: i32) -> Option<Self> {
284 Self::try_new_with_exponent_round_even(value, (S as i32).saturating_sub(scale))
285 }
286
287 fn try_new(value: i128) -> Option<Self> {
289 const { Self::check_constraints() };
290 (Self::MIN.0..=Self::MAX.0)
291 .contains(&value)
292 .then_some(Self(value))
293 }
294
295 pub fn internal_representation(self) -> i128 {
298 self.0
299 }
300
301 pub(super) fn try_new_with_exponent_round_even(value: i128, exponent: i32) -> Option<Self> {
304 i128_mul_pow10_round_even(value, exponent).and_then(Self::try_new)
305 }
306
307 pub(super) fn try_new_with_exponent(value: i128, exponent: i32) -> Option<Self> {
310 fn inner(value: i128, exponent: i32) -> Option<i128> {
312 Some(match exponent.cmp(&0) {
313 Ordering::Less => {
314 if let Some(divisor) = checked_pow10(exponent.unsigned_abs()) {
316 value / divisor
317 } else {
318 0
321 }
322 }
323 Ordering::Equal => value,
324 Ordering::Greater => {
325 value.checked_mul(checked_pow10(exponent.cast_unsigned())?)?
327 }
328 })
329 }
330 inner(value, exponent).and_then(Self::try_new)
331 }
332
333 const fn check_constraints() {
335 assert!(P >= 1 && P <= 38, "Fixed<S,P> must have 1 <= S <= 38");
336 assert!(S <= P, "Fixed<S,P> must have S <= P");
337 }
338
339 const fn scale() -> i128 {
341 Self::check_constraints();
342 pow10(S)
343 }
344
345 pub const fn checked_div_integer(self, other: Self) -> Option<i128> {
351 self.0.checked_div(other.0)
352 }
353
354 pub const fn strict_div_integer(self, other: Self) -> i128 {
361 self.checked_div_integer(other).unwrap()
362 }
363
364 pub fn checked_rem<const P0: usize, const S0: usize, const P1: usize, const S1: usize>(
369 self,
370 other: Fixed<P0, S0>,
371 ) -> Option<Fixed<P1, S1>> {
372 let neg = self.is_negative();
373 let left = self.abs();
374 let right = other.abs();
375 let div: Self = left.checked_div_generic(right)?;
376 let trunc: Self = div.trunc();
377 let mul: Self = right.checked_mul_generic(trunc)?;
378 let rem: Fixed<P1, S1> = left.checked_sub_generic(mul)?;
379 Some(if neg { rem.neg() } else { rem })
380 }
381
382 pub const fn abs(self) -> Self {
385 Self(self.0.abs())
386 }
387
388 pub const fn is_negative(self) -> bool {
390 self.0.is_negative()
391 }
392
393 pub fn checked_sqrt(self) -> Option<Self> {
399 Some(Self(
400 I256::from_product(self.0, Self::scale()).checked_isqrt()?,
401 ))
402 }
403
404 pub fn sqrt(self) -> Self {
413 self.checked_sqrt().unwrap()
414 }
415
416 pub fn checked_round(&self, n: i32) -> Option<Self> {
421 round_inner(self.0, S as i32, n, Halfway::AwayFromZero).and_then(Self::try_new)
422 }
423
424 pub fn round(&self, n: i32) -> Self {
433 self.checked_round(n)
434 .unwrap_or_else(|| panic!("Could not round value {} to {} digits", self, n))
435 }
436
437 pub fn checked_round_ties_even(&self, n: i32) -> Option<Self> {
442 round_inner(self.0, S as i32, n, Halfway::Even).and_then(Self::try_new)
443 }
444
445 pub fn round_ties_even(&self, n: i32) -> Self {
455 self.checked_round_ties_even(n).unwrap()
456 }
457
458 pub fn checked_floor(&self) -> Option<Self> {
461 if S > 0 {
462 Self::try_new(div_floor(self.0, Self::scale()) * Self::scale())
463 } else {
464 Some(*self)
465 }
466 }
467
468 pub fn floor(&self) -> Self {
476 self.checked_floor().unwrap()
477 }
478
479 pub fn int_floor(&self) -> Fixed<P, 0> {
481 if S > 0 {
482 Fixed::<P, 0>::new(div_floor(self.0, Self::scale()), 0i32).unwrap()
483 } else {
484 Fixed::<P, 0>::new(self.0, S as i32).unwrap()
485 }
486 }
487
488 pub fn trunc(&self) -> Self {
494 Self(self.0 / Self::scale() * Self::scale())
495 }
496
497 pub fn trunc_digits(&self, digits: i32) -> Self {
500 let exponent = (S as i32).saturating_sub(digits);
501 if exponent <= 0 {
502 *self
503 } else if let Some(divisor) = checked_pow10(exponent.cast_unsigned()) {
504 Self(self.0 / divisor * divisor)
505 } else {
506 Self::ZERO
507 }
508 }
509
510 pub fn checked_ceil(&self) -> Option<Self> {
513 if S > 0 {
514 Self::try_new(div_ceil(self.0, Self::scale()) * Self::scale())
515 } else {
516 Some(*self)
517 }
518 }
519
520 pub fn ceil(&self) -> Self {
528 self.checked_ceil().unwrap()
529 }
530
531 pub fn int_ceil(&self) -> Fixed<P, 0> {
534 if S > 0 {
535 Fixed::<P, 0>::new(div_ceil(self.0, Self::scale()), 0i32).unwrap()
536 } else {
537 Fixed::<P, 0>::new(self.0, S as i32).unwrap()
538 }
539 }
540
541 pub fn sign(&self) -> Fixed<1, 0> {
544 self.checked_sign_generic().unwrap()
545 }
546
547 pub fn checked_recip(&self) -> Option<Self> {
550 if S < P {
551 Self(Self::scale()).checked_div(self)
552 } else {
553 None
557 }
558 }
559
560 pub fn recip(&self) -> Self {
567 self.checked_recip().unwrap()
568 }
569
570 pub fn checked_powi(&self, exp: i32) -> Option<Self> {
580 if self.is_zero() {
581 (exp > 0).then_some(Self::ZERO)
582 } else if exp == 0 {
583 if S < P {
584 Some(Self::ONE)
585 } else {
586 None
588 }
589 } else if exp > 0 {
590 let mut exp = exp.unsigned_abs();
591 let mut base = self.0;
592 let mut base_scale = S as i32;
593 let mut acc = None;
594 loop {
595 if (exp & 1) == 1 {
596 acc = if let Some((acc, acc_scale)) = acc {
597 let (acc, shift) = I256::from_product(acc, base).reduce_to_i128();
598 Some((acc, (acc_scale + base_scale) - shift as i32))
599 } else {
600 Some((base, base_scale))
601 };
602 }
603 exp /= 2;
604 if exp == 0 {
605 let (acc, acc_scale) = acc.unwrap();
606 return Self::try_new_with_exponent(acc, S as i32 - acc_scale);
607 }
608
609 let (next_base, shift) = I256::from_product(base, base).reduce_to_i128();
610 base = next_base;
611 base_scale = base_scale * 2 - shift as i32;
612 }
613 } else {
614 let mut exp = exp.unsigned_abs();
615 let mut base = *self;
616 let mut acc: Option<Fixed<P, S>> = None;
617 loop {
618 if (exp & 1) == 1 {
619 acc = Some(if let Some(acc) = acc {
620 acc.checked_div(&base)
621 } else {
622 base.checked_recip()
623 }?)
624 }
625 exp /= 2;
626 if exp == 0 {
627 return acc;
628 }
629 base *= base;
630 }
631 }
632 }
633
634 pub fn powi(&self, exp: i32) -> Self {
645 self.checked_powi(exp).unwrap()
646 }
647
648 pub fn next_up(&self) -> Option<Self> {
651 if *self < Self::MAX {
652 Some(Self(self.0 + 1))
653 } else {
654 None
655 }
656 }
657
658 pub fn next_down(&self) -> Option<Self> {
661 if *self > Self::MIN {
662 Some(Self(self.0 - 1))
663 } else {
664 None
665 }
666 }
667}
668
669impl<const P0: usize, const S0: usize> Fixed<P0, S0> {
670 pub fn convert<const P1: usize, const S1: usize>(&self) -> Option<Fixed<P1, S1>> {
679 Fixed::try_new_with_exponent(self.0, S1 as i32 - S0 as i32)
680 }
681
682 pub fn convert_round_even<const P1: usize, const S1: usize>(&self) -> Option<Fixed<P1, S1>> {
687 Fixed::try_new_with_exponent_round_even(self.0, S1 as i32 - S0 as i32)
688 }
689
690 pub fn checked_sign_generic<const P1: usize, const S1: usize>(&self) -> Option<Fixed<P1, S1>> {
694 let one = Fixed::<P1, S1>::scale();
695 match self.0.cmp(&0) {
696 Ordering::Less if S1 < P1 => Some(Fixed(-one)),
697 Ordering::Equal => Some(Fixed::ZERO),
698 Ordering::Greater if S1 < P1 => Some(Fixed(one)),
699 _ => None,
700 }
701 }
702
703 pub fn checked_add_generic<
709 const P1: usize,
710 const S1: usize,
711 const P2: usize,
712 const S2: usize,
713 >(
714 self,
715 other: Fixed<P1, S1>,
716 ) -> Option<Fixed<P2, S2>> {
717 match S0.cmp(&S1) {
718 Ordering::Less => {
719 let factor = pow10(S1 - S0);
720 if let Some(shifted) = self.0.checked_mul(factor)
721 && let Some(sum) = other.0.checked_add(shifted)
722 {
723 Fixed::try_new_with_exponent(sum, S2 as i32 - S1 as i32)
727 } else {
728 let result = (I256::from_product(self.0, factor) + I256::from(other.0))
732 .narrowing_div(pow10(S1.saturating_sub(S2)))?;
733 Fixed::try_new_with_exponent(result, (S2.saturating_sub(S1)) as i32)
734 }
735 }
736 Ordering::Equal => {
737 if let Some(sum) = self.0.checked_add(other.0) {
738 Fixed::try_new_with_exponent(sum, S2 as i32 - S0 as i32)
740 } else if S2 < S0 {
741 Fixed::try_new(
744 (I256::from(self.0) + I256::from(other.0)).narrowing_div(pow10(S0 - S2))?,
745 )
746 } else {
747 None
749 }
750 }
751 Ordering::Greater => {
752 let factor = pow10(S0 - S1);
754 if let Some(shifted) = other.0.checked_mul(factor)
755 && let Some(sum) = self.0.checked_add(shifted)
756 {
757 Fixed::try_new_with_exponent(sum, S2 as i32 - S0 as i32)
758 } else {
759 let result = (I256::from_product(other.0, factor) + I256::from(self.0))
760 .narrowing_div(pow10(S0.saturating_sub(S2)))?;
761 Fixed::try_new_with_exponent(result, S2.saturating_sub(S0) as i32)
762 }
763 }
764 }
765 }
766
767 pub fn checked_sub_generic<
773 const P1: usize,
774 const S1: usize,
775 const P2: usize,
776 const S2: usize,
777 >(
778 self,
779 other: Fixed<P1, S1>,
780 ) -> Option<Fixed<P2, S2>> {
781 self.checked_add_generic(-other)
782 }
783
784 pub fn checked_mul_generic<
790 const P1: usize,
791 const S1: usize,
792 const P2: usize,
793 const S2: usize,
794 >(
795 self,
796 other: Fixed<P1, S1>,
797 ) -> Option<Fixed<P2, S2>> {
798 Fixed::<P2, S2>::try_new_with_exponent(
799 I256::from_product(self.0, other.0)
800 .narrowing_div(pow10((S0 + S1).saturating_sub(S2)))?,
801 S2.saturating_sub(S0 + S1) as i32,
802 )
803 }
804
805 pub fn checked_div_generic<
811 const P1: usize,
812 const S1: usize,
813 const P2: usize,
814 const S2: usize,
815 >(
816 self,
817 other: Fixed<P1, S1>,
818 ) -> Option<Fixed<P2, S2>> {
819 if other == 0 {
820 None
821 } else {
822 let shift_left = (S1 + S2).saturating_sub(S0);
823 if shift_left > 38 {
824 None
828 } else {
829 Fixed::try_new_with_exponent(
830 I256::from_product(self.0, pow10(shift_left)).narrowing_div(other.0)?,
831 -(S0.saturating_sub(S1 + S2) as i32),
832 )
833 }
834 }
835 }
836
837 pub fn strict_add_generic<
840 const P1: usize,
841 const S1: usize,
842 const P2: usize,
843 const S2: usize,
844 >(
845 self,
846 other: Fixed<P1, S1>,
847 ) -> Fixed<P2, S2> {
848 self.checked_add_generic(other).unwrap()
849 }
850
851 pub fn strict_sub_generic<
854 const P1: usize,
855 const S1: usize,
856 const P2: usize,
857 const S2: usize,
858 >(
859 self,
860 other: Fixed<P1, S1>,
861 ) -> Fixed<P2, S2> {
862 self.checked_sub_generic(other).unwrap()
863 }
864
865 pub fn strict_mul_generic<
868 const P1: usize,
869 const S1: usize,
870 const P2: usize,
871 const S2: usize,
872 >(
873 self,
874 other: Fixed<P1, S1>,
875 ) -> Fixed<P2, S2> {
876 self.checked_mul_generic(other).unwrap()
877 }
878
879 pub fn strict_div_generic<
882 const P1: usize,
883 const S1: usize,
884 const P2: usize,
885 const S2: usize,
886 >(
887 self,
888 other: Fixed<P1, S1>,
889 ) -> Fixed<P2, S2> {
890 self.checked_div_generic(other).unwrap()
891 }
892}
893
894impl<const P: usize, const S: usize> Zero for Fixed<P, S> {
895 fn zero() -> Self {
896 Self::ZERO
897 }
898
899 fn is_zero(&self) -> bool {
900 *self == Self::ZERO
901 }
902}
903
904impl<const P: usize, const S: usize> One for Fixed<P, S> {
905 fn one() -> Self {
907 Self::ONE
908 }
909}
910
911impl<const P: usize, const S: usize> TryFrom<f64> for Fixed<P, S> {
912 type Error = OutOfRange;
913
914 fn try_from(value: f64) -> Result<Self, Self::Error> {
917 cast(value * Self::scale() as f64)
918 .and_then(Self::try_new)
919 .ok_or(OutOfRange)
920 }
921}
922
923impl<const P: usize, const S: usize> TryFrom<f32> for Fixed<P, S> {
924 type Error = OutOfRange;
925
926 fn try_from(value: f32) -> Result<Self, Self::Error> {
929 cast(value as f64 * Self::scale() as f64)
930 .and_then(Self::try_new)
931 .ok_or(OutOfRange)
932 }
933}
934
935impl<const P: usize, const S: usize> From<Fixed<P, S>> for f64 {
936 fn from(value: Fixed<P, S>) -> Self {
937 value.0 as f64 / Fixed::<P, S>::scale() as f64
938 }
939}
940
941impl<const P: usize, const S: usize> TryFrom<i128> for Fixed<P, S> {
942 type Error = OutOfRange;
943
944 fn try_from(value: i128) -> Result<Self, Self::Error> {
948 if value.unsigned_abs() <= Self::max_u128() {
949 Ok(Self(value * Self::scale()))
950 } else {
951 Err(OutOfRange)
952 }
953 }
954}
955
956macro_rules! try_from_signed_int {
957 ($type_name:ty) => {
958 impl<const P: usize, const S: usize> TryFrom<$type_name> for Fixed<P, S> {
959 type Error = OutOfRange;
960
961 fn try_from(value: $type_name) -> Result<Self, Self::Error> {
964 (value as i128).try_into()
965 }
966 }
967 };
968}
969
970try_from_signed_int!(isize);
971try_from_signed_int!(i64);
972try_from_signed_int!(i32);
973try_from_signed_int!(i16);
974try_from_signed_int!(i8);
975
976impl<const P: usize, const S: usize> TryFrom<u128> for Fixed<P, S> {
977 type Error = OutOfRange;
978
979 fn try_from(value: u128) -> Result<Self, Self::Error> {
983 if value <= Self::max_i128() as u128 {
984 Ok(Self(value as i128 * Self::scale()))
985 } else {
986 Err(OutOfRange)
987 }
988 }
989}
990
991macro_rules! try_from_unsigned_int {
992 ($type_name:ty) => {
993 impl<const P: usize, const S: usize> TryFrom<$type_name> for Fixed<P, S> {
994 type Error = OutOfRange;
995
996 fn try_from(value: $type_name) -> Result<Self, Self::Error> {
1000 (value as u128).try_into()
1001 }
1002 }
1003 };
1004}
1005
1006try_from_unsigned_int!(usize);
1007try_from_unsigned_int!(u64);
1008try_from_unsigned_int!(u32);
1009try_from_unsigned_int!(u16);
1010try_from_unsigned_int!(u8);
1011
1012macro_rules! min_max_int {
1013 ($signed_type:ty, $max_signed:ident, $min_signed:ident, $unsigned_type:ty, $max_unsigned:ident) => {
1014 #[doc = "Returns the maximum `"]
1015 #[doc = stringify!($signed_type)]
1016 #[doc = "` that can be converted to this type."]
1017 pub const fn $max_signed() -> $signed_type {
1018 if Self::max_i128() > <$signed_type>::MAX as i128 {
1019 <$signed_type>::MAX
1020 } else {
1021 Self::max_i128() as $signed_type
1022 }
1023 }
1024
1025 #[doc = "Returns the minimum `"]
1026 #[doc = stringify!($signed_type)]
1027 #[doc = "` that can be converted to this type."]
1028 pub const fn $min_signed() -> $signed_type {
1029 -Self::$max_signed()
1030 }
1031
1032 #[doc = "Returns the maximum `"]
1033 #[doc = stringify!($unsigned_type)]
1034 #[doc = "` that can be converted to this type.\n\nThe minimum is 0."]
1035 pub const fn $max_unsigned() -> $unsigned_type {
1036 if Self::max_u128() > <$unsigned_type>::MAX as u128 {
1037 <$unsigned_type>::MAX
1038 } else {
1039 Self::max_u128() as $unsigned_type
1040 }
1041 }
1042 };
1043}
1044
1045impl<const P: usize, const S: usize> Fixed<P, S> {
1046 pub const fn max_i128() -> i128 {
1048 if P > S { pow10(P - S) - 1 } else { 0 }
1049 }
1050
1051 pub const fn min_i128() -> i128 {
1053 -Self::max_i128()
1054 }
1055
1056 pub const fn max_u128() -> u128 {
1060 Self::max_i128().cast_unsigned()
1061 }
1062
1063 min_max_int!(isize, max_isize, min_isize, usize, max_usize);
1064 min_max_int!(i64, max_i64, min_i64, u64, max_u64);
1065 min_max_int!(i32, max_i32, min_i32, u32, max_u32);
1066 min_max_int!(i16, max_i16, min_i16, u16, max_u16);
1067 min_max_int!(i8, max_i8, min_i8, u8, max_u8);
1068}
1069
1070impl<const P: usize, const S: usize> From<Fixed<P, S>> for i128 {
1071 fn from(value: Fixed<P, S>) -> Self {
1074 value.0 / <Fixed<P, S>>::scale()
1076 }
1077}
1078
1079macro_rules! try_to_signed_int {
1080 ($type_name:ty) => {
1081 impl<const P: usize, const S: usize> TryFrom<Fixed<P, S>> for $type_name {
1082 type Error = OutOfRange;
1083
1084 fn try_from(value: Fixed<P, S>) -> Result<Self, Self::Error> {
1087 i128::from(value).try_into().map_err(|_| OutOfRange)
1088 }
1089 }
1090 };
1091}
1092
1093try_to_signed_int!(i64);
1094try_to_signed_int!(i32);
1095try_to_signed_int!(i16);
1096try_to_signed_int!(i8);
1097try_to_signed_int!(isize);
1098
1099macro_rules! try_to_unsigned_int {
1102 ($type_name:ty) => {
1103 impl<const P: usize, const S: usize> TryFrom<Fixed<P, S>> for $type_name {
1104 type Error = OutOfRange;
1105
1106 fn try_from(value: Fixed<P, S>) -> Result<Self, Self::Error> {
1112 i128::from(value).try_into().map_err(|_| OutOfRange)
1113 }
1114 }
1115 };
1116}
1117
1118try_to_unsigned_int!(u128);
1119try_to_unsigned_int!(u64);
1120try_to_unsigned_int!(u32);
1121try_to_unsigned_int!(u16);
1122try_to_unsigned_int!(u8);
1123try_to_unsigned_int!(usize);
1124
1125impl<const P: usize, const S: usize> Add for Fixed<P, S> {
1126 type Output = Self;
1127
1128 fn add(self, other: Self) -> Self::Output {
1134 self.checked_add(&other).unwrap()
1135 }
1136}
1137
1138impl<const P: usize, const S: usize> Add for &Fixed<P, S> {
1139 type Output = Fixed<P, S>;
1140
1141 fn add(self, other: Self) -> Self::Output {
1147 self.checked_add(other).unwrap()
1148 }
1149}
1150
1151impl<const P: usize, const S: usize> CheckedAdd for Fixed<P, S> {
1152 fn checked_add(&self, other: &Self) -> Option<Self> {
1155 self.checked_add_generic(*other)
1156 }
1157}
1158
1159impl<const P: usize, const S: usize> AddAssign for Fixed<P, S> {
1160 fn add_assign(&mut self, other: Self) {
1166 *self = *self + other;
1167 }
1168}
1169
1170impl<const P: usize, const S: usize> AddAssign<&Fixed<P, S>> for Fixed<P, S> {
1171 fn add_assign(&mut self, other: &Fixed<P, S>) {
1177 *self = *self + *other;
1178 }
1179}
1180
1181impl<const P: usize, const S: usize> Sub for Fixed<P, S> {
1182 type Output = Self;
1183
1184 fn sub(self, other: Self) -> Self::Output {
1190 self.checked_sub(&other).unwrap()
1191 }
1192}
1193
1194impl<const P: usize, const S: usize> Sub for &Fixed<P, S> {
1195 type Output = Fixed<P, S>;
1196
1197 fn sub(self, other: Self) -> Self::Output {
1203 self.checked_sub(other).unwrap()
1204 }
1205}
1206
1207impl<const P: usize, const S: usize> CheckedSub for Fixed<P, S> {
1208 fn checked_sub(&self, other: &Self) -> Option<Self> {
1211 self.checked_sub_generic(*other)
1212 }
1213}
1214
1215impl<const P: usize, const S: usize> SubAssign for Fixed<P, S> {
1216 fn sub_assign(&mut self, other: Self) {
1222 *self = *self - other;
1223 }
1224}
1225
1226impl<const P: usize, const S: usize> Mul for Fixed<P, S> {
1227 type Output = Self;
1228
1229 fn mul(self, other: Self) -> Self::Output {
1235 self.checked_mul(&other).unwrap()
1236 }
1237}
1238
1239impl<const P: usize, const S: usize> Mul for &Fixed<P, S> {
1240 type Output = Fixed<P, S>;
1241
1242 fn mul(self, other: Self) -> Self::Output {
1248 self.checked_mul(other).unwrap()
1249 }
1250}
1251
1252impl<const P: usize, const S: usize> CheckedMul for Fixed<P, S> {
1253 fn checked_mul(&self, other: &Self) -> Option<Self> {
1256 Self::checked_mul_generic(*self, *other)
1257 }
1258}
1259
1260impl<const P: usize, const S: usize> MulAssign for Fixed<P, S> {
1261 fn mul_assign(&mut self, other: Self) {
1267 *self = *self * other;
1268 }
1269}
1270
1271impl<const P: usize, const S: usize> Div for Fixed<P, S> {
1272 type Output = Self;
1273
1274 fn div(self, other: Self) -> Self::Output {
1280 self.checked_div(&other).unwrap()
1281 }
1282}
1283
1284impl<const P: usize, const S: usize> Div for &Fixed<P, S> {
1285 type Output = Fixed<P, S>;
1286
1287 fn div(self, other: Self) -> Self::Output {
1293 self.checked_div(other).unwrap()
1294 }
1295}
1296
1297impl<const P: usize, const S: usize> CheckedDiv for Fixed<P, S> {
1298 fn checked_div(&self, other: &Self) -> Option<Self> {
1301 Self::checked_div_generic(*self, *other)
1302 }
1303}
1304
1305impl<const P: usize, const S: usize> DivAssign for Fixed<P, S> {
1306 fn div_assign(&mut self, other: Self) {
1312 *self = *self / other;
1313 }
1314}
1315
1316impl<const P: usize, const S: usize> Neg for Fixed<P, S> {
1317 type Output = Self;
1318
1319 fn neg(self) -> Self::Output {
1321 Self(-self.0)
1322 }
1323}
1324
1325impl<const P: usize, const S: usize> Neg for &Fixed<P, S> {
1326 type Output = Fixed<P, S>;
1327
1328 fn neg(self) -> Self::Output {
1330 Fixed(-self.0)
1331 }
1332}
1333
1334impl<const P: usize, const S: usize> FromStr for Fixed<P, S> {
1335 type Err = ParseDecimalError;
1336
1337 fn from_str(s: &str) -> Result<Self, Self::Err> {
1344 let (value, exponent) = parse_decimal(s, S as i32)?;
1345 Self::try_new_with_exponent_round_even(value, exponent).ok_or(ParseDecimalError::OutOfRange)
1346 }
1347}
1348
1349impl<const P: usize, const S: usize> Debug for Fixed<P, S> {
1350 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1351 debug_decimal(self.0, S, f)
1352 }
1353}
1354
1355impl<const P: usize, const S: usize> Display for Fixed<P, S> {
1356 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1357 display_decimal(self.0, S, f)
1358 }
1359}
1360
1361impl<const P: usize, const S: usize> Fixed<P, S> {
1362 pub const UNSIGNED_MIN: u128 = 0;
1366
1367 pub const UNSIGNED_ZERO: u128 = pow10(P).cast_unsigned() - 1;
1369
1370 pub const UNSIGNED_MAX: u128 = pow10(P).cast_unsigned() * 2 - 2;
1372
1373 pub fn to_unsigned_encoding(self) -> u128 {
1387 Self::UNSIGNED_ZERO.checked_add_signed(self.0).unwrap()
1388 }
1389
1390 pub fn from_unsigned_encoding(encoding: u128) -> Option<Self> {
1405 if encoding < Self::UNSIGNED_ZERO {
1406 Some(Self(-(Self::UNSIGNED_ZERO - encoding).cast_signed()))
1407 } else if encoding <= Self::UNSIGNED_MAX {
1408 Some(Self((encoding - Self::UNSIGNED_ZERO).cast_signed()))
1409 } else {
1410 None
1411 }
1412 }
1413}
1414
1415#[cfg(test)]
1416mod test {
1417 use std::str::FromStr;
1418
1419 use num_traits::{CheckedAdd, CheckedDiv, CheckedMul, CheckedSub};
1420
1421 use crate::Fixed;
1422
1423 type F = Fixed<10, 2>;
1424 fn f(n: f64) -> F {
1425 Fixed::try_from(n).unwrap()
1426 }
1427
1428 fn f38_0(n: f64) -> Fixed<38, 0> {
1429 Fixed::try_from(n).unwrap()
1430 }
1431
1432 fn f38_38(s: &str) -> Fixed<38, 38> {
1433 Fixed::from_str(s).unwrap()
1434 }
1435
1436 #[test]
1437 fn mul() {
1438 assert_eq!(f(1.23) * f(2.34), f(2.87));
1440 assert_eq!(f(-1.23) * f(2.34), f(-2.87));
1441 assert_eq!(f(1.23) * f(-2.34), f(-2.87));
1442 assert_eq!(f(-1.23) * f(-2.34), f(2.87));
1443
1444 for a in -999..=999 {
1446 let af: Fixed<10, 2> = Fixed(a);
1447 for b in -999..=999 {
1448 let bf: Fixed<10, 2> = Fixed(b);
1449 assert_eq!(af * bf, Fixed::<10, 2>(a * b / 100));
1450 }
1451 }
1452
1453 for a in -999..=999 {
1455 let af: Fixed<3, 2> = Fixed(a);
1456 for b in -999..=999 {
1457 let bf: Fixed<3, 2> = Fixed(b);
1458 let c = a * b / 100;
1459 let expected = (c.unsigned_abs() < 1000).then_some(Fixed(c));
1460 assert_eq!(af.checked_mul(&bf), expected);
1461 }
1462 }
1463 }
1464
1465 #[test]
1466 fn mul_generic() {
1467 for a in -999..=999 {
1468 let af: Fixed<10, 2> = Fixed(a);
1469 for b in -999..=999 {
1470 let bf: Fixed<10, 3> = Fixed(b);
1471 let cf: Fixed<10, 5> = af.checked_mul_generic(bf).unwrap();
1472 assert_eq!(cf, Fixed::<10, 5>(a * b));
1473 let df: Fixed<10, 6> = af.checked_mul_generic(bf).unwrap();
1474 assert_eq!(df, Fixed::<10, 6>(a * b * 10));
1475 let ef: Fixed<10, 0> = af.checked_mul_generic(bf).unwrap();
1476 assert_eq!(ef, Fixed::<10, 0>(a * b / 100_000));
1477 }
1478 }
1479 }
1480
1481 #[test]
1482 fn div() {
1483 assert_eq!(f(1.23) / f(2.34), f(0.52));
1485 assert_eq!(f(-1.23) / f(2.34), f(-0.52));
1486 assert_eq!(f(1.23) / f(-2.34), f(-0.52));
1487 assert_eq!(f(-1.23) / f(-2.34), f(0.52));
1488 assert_eq!(
1489 f38_0(1.0)
1490 .checked_div_generic::<38, 0, 38, 38>(f38_0(7.0))
1491 .unwrap(),
1492 f38_38("0.14285714285714285714285714285714285714")
1493 );
1494
1495 assert_eq!(
1496 f38_0(123.0).checked_div_generic::<38, 38, 38, 38>(f38_38("0.456")),
1497 None
1498 );
1499
1500 for a in -999..=999 {
1502 let af: Fixed<10, 2> = Fixed(a);
1503 for b in -999..=999 {
1504 let bf: Fixed<10, 2> = Fixed(b);
1505 assert_eq!(af.checked_div(&bf), (b != 0).then(|| Fixed(a * 100 / b)));
1506 }
1507 }
1508
1509 for a in -999..=999 {
1511 let af: Fixed<3, 2> = Fixed(a);
1512 for b in -999..=999 {
1513 let bf: Fixed<3, 2> = Fixed(b);
1514 let expected = if b != 0 {
1515 let result = a * 100 / b;
1516 (result.unsigned_abs() <= 999).then_some(Fixed(result))
1517 } else {
1518 None
1519 };
1520 assert_eq!(af.checked_div(&bf), expected);
1521 }
1522 }
1523 }
1524
1525 #[test]
1526 fn div_generic() {
1527 fn test<const P: usize, const S: usize>(a: i128, af: Fixed<P, S>) {
1528 for b in -999..=999 {
1529 if b != 0 {
1530 let bf: Fixed<10, 3> = Fixed(b);
1531 let cf: Fixed<10, 5> = af.checked_div_generic(bf).unwrap();
1532 assert_eq!(cf, Fixed::<10, 5>(a * 1_000_000 / b));
1533 let df: Fixed<10, 6> = af.checked_div_generic(bf).unwrap();
1534 assert_eq!(df, Fixed::<10, 6>(a * 10_000_000 / b));
1535 let ef: Fixed<10, 0> = af.checked_div_generic(bf).unwrap();
1536 assert_eq!(ef, Fixed::<10, 0>(a * 10 / b));
1537 }
1538 }
1539 }
1540
1541 for a in -999..=999 {
1542 let af: Fixed<10, 2> = Fixed(a);
1543 test(a, af);
1544 let af2: Fixed<18, 10> = af.convert().unwrap();
1545 test(a, af2);
1546 }
1547 }
1548
1549 #[test]
1550 fn add() {
1551 assert_eq!(f(1.23) + f(2.34), f(3.57));
1553 assert_eq!(f(-1.23) + f(2.34), f(1.11));
1554 assert_eq!(f(1.23) + f(-2.34), f(-1.11));
1555 assert_eq!(f(-1.23) + f(-2.34), f(-3.57));
1556
1557 let af: Fixed<38, 35> = Fixed::try_from(999).unwrap();
1559 let bf: Fixed<37, 34> = Fixed::try_from(999).unwrap();
1560 let cf: Fixed<36, 30> = af.checked_add_generic(bf).unwrap();
1561 assert_eq!(cf, 1998);
1562 let df: Fixed<36, 30> = bf.checked_add_generic(af).unwrap();
1563 assert_eq!(df, 1998);
1564 let ef: Fixed<36, 3> = af.checked_add_generic(af).unwrap();
1565 assert_eq!(ef, 1998);
1566 let ff: Option<Fixed<38, 35>> = af.checked_add_generic(af);
1567 assert_eq!(ff, None);
1568
1569 for a in -999..=999 {
1571 let af: Fixed<10, 2> = Fixed(a);
1572 for b in -999..=999 {
1573 let bf: Fixed<10, 2> = Fixed(b);
1574 assert_eq!(af + bf, Fixed::<10, 2>(a + b));
1575 }
1576 }
1577
1578 for a in -999..=999 {
1580 let af: Fixed<3, 2> = Fixed(a);
1581 for b in -999..=999 {
1582 let bf: Fixed<3, 2> = Fixed(b);
1583 let c = a + b;
1584 let expected = (c.unsigned_abs() < 1000).then_some(Fixed(c));
1585 assert_eq!(af.checked_add(&bf), expected);
1586 }
1587 }
1588
1589 for a in -999..=999 {
1591 let af: Fixed<10, 2> = Fixed(a);
1592 for b in -999..=999 {
1593 let bf: Fixed<10, 3> = Fixed(b);
1594 let cf: Fixed<10, 5> = af.checked_add_generic(bf).unwrap();
1595 assert_eq!(
1596 cf,
1597 Fixed::<10, 5>(a * 1000 + b * 100),
1598 "{af} + {bf} ?= {cf}"
1599 );
1600 let cf: Fixed<10, 5> = bf.checked_add_generic(af).unwrap();
1601 assert_eq!(
1602 cf,
1603 Fixed::<10, 5>(a * 1000 + b * 100),
1604 "{bf} + {af} ?= {cf}"
1605 );
1606 let df: Fixed<10, 6> = af.checked_add_generic(bf).unwrap();
1607 assert_eq!(
1608 df,
1609 Fixed::<10, 6>(a * 10_000 + b * 1000),
1610 "{af} + {bf} ?= {df}"
1611 );
1612 let ef: Fixed<10, 0> = af.checked_add_generic(bf).unwrap();
1613 assert_eq!(
1614 ef,
1615 Fixed::<10, 0>((a * 10 + b) / 1000),
1616 "{af} + {bf} ?= {ef}"
1617 );
1618
1619 let ff: Fixed<10, 2> = Fixed(b);
1620 let gf: Fixed<10, 1> = af.checked_add_generic(ff).unwrap();
1621 assert_eq!(gf, Fixed::<10, 1>((a + b) / 10), "{af} + {ff} ?= {gf}");
1622 let hf: Fixed<10, 3> = af.checked_add_generic(ff).unwrap();
1623 assert_eq!(hf, Fixed::<10, 3>((a + b) * 10), "{af} + {ff} ?= {hf}");
1624 }
1625 }
1626 }
1627
1628 #[test]
1629 fn sub() {
1630 assert_eq!(f(1.23) - f(2.34), f(-1.11));
1632 assert_eq!(f(-1.23) - f(2.34), f(-3.57));
1633 assert_eq!(f(1.23) - f(-2.34), f(3.57));
1634 assert_eq!(f(-1.23) - f(-2.34), f(1.11));
1635
1636 for a in -999..=999 {
1638 let af: Fixed<10, 2> = Fixed(a);
1639 for b in -999..=999 {
1640 let bf: Fixed<10, 2> = Fixed(b);
1641 assert_eq!(af - bf, Fixed::<10, 2>(a - b));
1642 }
1643 }
1644
1645 for a in -999..=999 {
1647 let af: Fixed<3, 2> = Fixed(a);
1648 for b in -999..=999 {
1649 let bf: Fixed<3, 2> = Fixed(b);
1650 let c = a - b;
1651 let expected = (c.unsigned_abs() < 1000).then_some(Fixed(c));
1652 assert_eq!(af.checked_sub(&bf), expected);
1653 }
1654 }
1655
1656 for a in -999..=999 {
1658 let af: Fixed<10, 2> = Fixed(a);
1659 for b in -999..=999 {
1660 let bf: Fixed<10, 3> = Fixed(b);
1661 let cf: Fixed<10, 5> = af.checked_sub_generic(bf).unwrap();
1662 assert_eq!(
1663 cf,
1664 Fixed::<10, 5>(a * 1000 - b * 100),
1665 "{af} - {bf} ?= {cf}"
1666 );
1667 let cf: Fixed<10, 5> = bf.checked_sub_generic(af).unwrap();
1668 assert_eq!(
1669 cf,
1670 Fixed::<10, 5>(b * 100 - a * 1000),
1671 "{bf} - {af} ?= {cf}"
1672 );
1673 let df: Fixed<10, 6> = af.checked_sub_generic(bf).unwrap();
1674 assert_eq!(df, Fixed::<10, 6>(a * 10_000 - b * 1000));
1675 }
1676 }
1677 }
1678
1679 #[test]
1680 fn powi() {
1681 assert_eq!(
1682 Fixed::<10, 8>::from_str("1.12345678")
1683 .unwrap()
1684 .powi(8)
1685 .to_string()
1686 .as_str(),
1687 "2.53776238"
1688 );
1689 assert_eq!(f(2.0).powi(3), f(8.0));
1690 assert_eq!(f(-2.0).powi(3), f(-8.0));
1691 assert_eq!(f(1.7).powi(8), f(69.75));
1692 assert_eq!(f(1.7).powi(-8), f(0.01));
1693 assert_eq!(f(0.0).powi(1), f(0.0));
1694 assert_eq!(f(0.0).checked_powi(0), None);
1695 assert_eq!(f(0.0).checked_powi(-1), None);
1696 }
1697
1698 #[test]
1699 fn convert() {
1700 let a = Fixed::<10, 10>::from_str("0.0123456789").unwrap();
1701 assert_eq!(&a.convert::<10, 0>().unwrap().to_string(), "0");
1702 assert_eq!(&a.convert::<10, 1>().unwrap().to_string(), "0");
1703 assert_eq!(&a.convert::<10, 2>().unwrap().to_string(), "0.01");
1704 assert_eq!(&a.convert::<10, 3>().unwrap().to_string(), "0.012");
1705 assert_eq!(&a.convert::<10, 4>().unwrap().to_string(), "0.0123");
1706 assert_eq!(&a.convert::<10, 5>().unwrap().to_string(), "0.01234");
1707 assert_eq!(&a.convert::<10, 6>().unwrap().to_string(), "0.012345");
1708 assert_eq!(&a.convert::<10, 7>().unwrap().to_string(), "0.0123456");
1709 assert_eq!(&a.convert::<10, 8>().unwrap().to_string(), "0.01234567");
1710 assert_eq!(&a.convert::<10, 9>().unwrap().to_string(), "0.012345678");
1711 assert_eq!(&a.convert::<10, 10>().unwrap().to_string(), "0.0123456789");
1712 assert_eq!(&a.convert_round_even::<10, 0>().unwrap().to_string(), "0");
1713 assert_eq!(&a.convert_round_even::<10, 1>().unwrap().to_string(), "0");
1714 assert_eq!(
1715 &a.convert_round_even::<10, 2>().unwrap().to_string(),
1716 "0.01"
1717 );
1718 assert_eq!(
1719 &a.convert_round_even::<10, 3>().unwrap().to_string(),
1720 "0.012"
1721 );
1722 assert_eq!(
1723 &a.convert_round_even::<10, 4>().unwrap().to_string(),
1724 "0.0123"
1725 );
1726 assert_eq!(
1727 &a.convert_round_even::<10, 5>().unwrap().to_string(),
1728 "0.01235"
1729 );
1730 assert_eq!(
1731 &a.convert_round_even::<10, 6>().unwrap().to_string(),
1732 "0.012346"
1733 );
1734 assert_eq!(
1735 &a.convert_round_even::<10, 7>().unwrap().to_string(),
1736 "0.0123457"
1737 );
1738 assert_eq!(
1739 &a.convert_round_even::<10, 8>().unwrap().to_string(),
1740 "0.01234568"
1741 );
1742 assert_eq!(
1743 &a.convert_round_even::<10, 9>().unwrap().to_string(),
1744 "0.012345679"
1745 );
1746 assert_eq!(
1747 &a.convert_round_even::<10, 10>().unwrap().to_string(),
1748 "0.0123456789"
1749 );
1750
1751 let b = Fixed::<10, 5>::from_str("12345.67895").unwrap();
1752 assert_eq!(&b.convert::<10, 0>().unwrap().to_string(), "12345");
1753 assert_eq!(&b.convert::<10, 1>().unwrap().to_string(), "12345.6");
1754 assert_eq!(&b.convert::<10, 2>().unwrap().to_string(), "12345.67");
1755 assert_eq!(&b.convert::<10, 3>().unwrap().to_string(), "12345.678");
1756 assert_eq!(&b.convert::<10, 4>().unwrap().to_string(), "12345.6789");
1757 assert_eq!(&b.convert::<10, 5>().unwrap().to_string(), "12345.67895");
1758 assert_eq!(b.convert::<10, 6>(), None);
1759 assert_eq!(b.convert::<10, 7>(), None);
1760 assert_eq!(b.convert::<10, 8>(), None);
1761 assert_eq!(b.convert::<10, 9>(), None);
1762 assert_eq!(b.convert::<10, 10>(), None);
1763 assert_eq!(
1764 &b.convert_round_even::<10, 0>().unwrap().to_string(),
1765 "12346"
1766 );
1767 assert_eq!(
1768 &b.convert_round_even::<10, 1>().unwrap().to_string(),
1769 "12345.7"
1770 );
1771 assert_eq!(
1772 &b.convert_round_even::<10, 2>().unwrap().to_string(),
1773 "12345.68"
1774 );
1775 assert_eq!(
1776 &b.convert_round_even::<10, 3>().unwrap().to_string(),
1777 "12345.679"
1778 );
1779 assert_eq!(
1780 &b.convert_round_even::<10, 4>().unwrap().to_string(),
1781 "12345.679"
1782 );
1783 assert_eq!(
1784 &b.convert_round_even::<10, 5>().unwrap().to_string(),
1785 "12345.67895"
1786 );
1787 assert_eq!(b.convert_round_even::<10, 6>(), None);
1788 assert_eq!(b.convert_round_even::<10, 7>(), None);
1789 assert_eq!(b.convert_round_even::<10, 8>(), None);
1790 assert_eq!(b.convert_round_even::<10, 9>(), None);
1791 assert_eq!(b.convert_round_even::<10, 10>(), None);
1792 }
1793
1794 #[test]
1795 fn constants() {
1796 assert_eq!(Fixed::<5, 0>::MAX, Fixed::<5, 0>(99999));
1797 assert_eq!(Fixed::<5, 0>::MIN, Fixed::<5, 0>(-99999));
1798 assert_eq!(Fixed::<5, 0>::ZERO, Fixed::<5, 0>(0));
1799 assert_eq!(Fixed::<5, 0>::ONE, Fixed::<5, 0>(1));
1800
1801 assert_eq!(Fixed::<5, 1>::MAX, Fixed::<5, 1>(99999));
1802 assert_eq!(Fixed::<5, 1>::MIN, Fixed::<5, 1>(-99999));
1803 assert_eq!(Fixed::<5, 1>::ZERO, Fixed::<5, 1>(0));
1804 assert_eq!(Fixed::<5, 1>::ONE, Fixed::<5, 1>(10));
1805
1806 assert_eq!(Fixed::<5, 2>::MAX, Fixed::<5, 2>(99999));
1807 assert_eq!(Fixed::<5, 2>::MIN, Fixed::<5, 2>(-99999));
1808 assert_eq!(Fixed::<5, 2>::ZERO, Fixed::<5, 2>(0));
1809 assert_eq!(Fixed::<5, 2>::ONE, Fixed::<5, 2>(100));
1810
1811 assert_eq!(Fixed::<5, 3>::MAX, Fixed::<5, 3>(99999));
1812 assert_eq!(Fixed::<5, 3>::MIN, Fixed::<5, 3>(-99999));
1813 assert_eq!(Fixed::<5, 3>::ZERO, Fixed::<5, 3>(0));
1814 assert_eq!(Fixed::<5, 3>::ONE, Fixed::<5, 3>(1000));
1815
1816 assert_eq!(Fixed::<5, 4>::MAX, Fixed::<5, 4>(99999));
1817 assert_eq!(Fixed::<5, 4>::MIN, Fixed::<5, 4>(-99999));
1818 assert_eq!(Fixed::<5, 4>::ZERO, Fixed::<5, 4>(0));
1819 assert_eq!(Fixed::<5, 4>::ONE, Fixed::<5, 4>(10000));
1820
1821 assert_eq!(Fixed::<5, 5>::MAX, Fixed::<5, 5>(99999));
1822 assert_eq!(Fixed::<5, 5>::MIN, Fixed::<5, 5>(-99999));
1823 assert_eq!(Fixed::<5, 5>::ZERO, Fixed::<5, 5>(0));
1824 }
1827
1828 #[test]
1829 fn floor() {
1830 assert_eq!(f(5.0).floor(), f(5.0));
1831 assert_eq!(f(5.1).floor(), f(5.0));
1832 assert_eq!(f(5.5).floor(), f(5.0));
1833 assert_eq!(f(5.9).floor(), f(5.0));
1834 assert_eq!(f(-5.0).floor(), f(-5.0));
1835 assert_eq!(f(-5.1).floor(), f(-6.0));
1836 assert_eq!(f(-5.5).floor(), f(-6.0));
1837 assert_eq!(f(-5.6).floor(), f(-6.0));
1838 assert_eq!(f(4.0).floor(), f(4.0));
1839 assert_eq!(f(4.1).floor(), f(4.0));
1840 assert_eq!(f(4.5).floor(), f(4.0));
1841 assert_eq!(f(4.9).floor(), f(4.0));
1842 assert_eq!(f(-4.0).floor(), f(-4.0));
1843 assert_eq!(f(-4.1).floor(), f(-5.0));
1844 assert_eq!(f(-4.5).floor(), f(-5.0));
1845 assert_eq!(f(-4.6).floor(), f(-5.0));
1846 assert_eq!(f(-99_999_999.0).floor(), f(-99_999_999.0));
1847 assert_eq!(f(-99_999_999.1).checked_floor(), None);
1848 assert_eq!(f(-99_999_999.5).checked_floor(), None);
1849 assert_eq!(f(-99_999_999.6).checked_floor(), None);
1850 }
1851
1852 #[test]
1853 fn ceil() {
1854 assert_eq!(f(5.0).ceil(), f(5.0));
1855 assert_eq!(f(5.1).ceil(), f(6.0));
1856 assert_eq!(f(5.5).ceil(), f(6.0));
1857 assert_eq!(f(5.9).ceil(), f(6.0));
1858 assert_eq!(f(-5.0).ceil(), f(-5.0));
1859 assert_eq!(f(-5.1).ceil(), f(-5.0));
1860 assert_eq!(f(-5.5).ceil(), f(-5.0));
1861 assert_eq!(f(-5.6).ceil(), f(-5.0));
1862 assert_eq!(f(4.0).ceil(), f(4.0));
1863 assert_eq!(f(4.1).ceil(), f(5.0));
1864 assert_eq!(f(4.5).ceil(), f(5.0));
1865 assert_eq!(f(4.9).ceil(), f(5.0));
1866 assert_eq!(f(-4.0).ceil(), f(-4.0));
1867 assert_eq!(f(-4.1).ceil(), f(-4.0));
1868 assert_eq!(f(-4.5).ceil(), f(-4.0));
1869 assert_eq!(f(-4.6).ceil(), f(-4.0));
1870 assert_eq!(f(99_999_999.0).ceil(), f(99_999_999.0));
1871 assert_eq!(f(99_999_999.1).checked_ceil(), None);
1872 assert_eq!(f(99_999_999.5).checked_ceil(), None);
1873 assert_eq!(f(99_999_999.6).checked_ceil(), None);
1874 }
1875
1876 #[test]
1877 fn trunc() {
1878 fn test(x: f64, expected: f64) {
1879 assert_eq!(f(x).trunc(), f(expected));
1880 assert_eq!(f(x).trunc_digits(0), f(expected));
1881 }
1882
1883 test(5.0, 5.0);
1884 test(5.1, 5.0);
1885 test(5.5, 5.0);
1886 test(5.9, 5.0);
1887 test(-5.0, -5.0);
1888 test(-5.1, -5.0);
1889 test(-5.5, -5.0);
1890 test(-5.6, -5.0);
1891 test(4.0, 4.0);
1892 test(4.1, 4.0);
1893 test(4.5, 4.0);
1894 test(4.9, 4.0);
1895 test(-4.0, -4.0);
1896 test(-4.1, -4.0);
1897 test(-4.5, -4.0);
1898 test(-4.6, -4.0);
1899 test(99_999_999.0, 99_999_999.0);
1900 test(99_999_999.1, 99_999_999.0);
1901 test(99_999_999.5, 99_999_999.0);
1902 test(99_999_999.6, 99_999_999.0);
1903 test(-99_999_999.0, -99_999_999.0);
1904 test(-99_999_999.1, -99_999_999.0);
1905 test(-99_999_999.5, -99_999_999.0);
1906 test(-99_999_999.6, -99_999_999.0);
1907 }
1908
1909 #[test]
1910 fn round() {
1911 fn test(x: f64, expected: Option<f64>) {
1912 assert_eq!(f(x).checked_round(0), expected.map(f));
1913 }
1914 type F = Fixed<10, 2>;
1915 fn test1((x, s): (i128, i32), d: i32, expected: Option<(i128, i32)>) {
1916 assert_eq!(
1917 F::new(x, s).unwrap().checked_round(d),
1918 expected.map(|x| F::new(x.0, x.1).unwrap())
1919 );
1920 }
1921
1922 test1((51, 1), 2, Some((51, 1)));
1924 test1((51, 1), 1, Some((51, 1)));
1926 test1((51, 1), 0, Some((50, 1)));
1928 test1((51, 1), -1, Some((10, 0)));
1930
1931 test1((21, 1), 2, Some((21, 1)));
1933 test1((21, 1), 1, Some((21, 1)));
1935 test1((21, 1), 0, Some((20, 1)));
1937 test1((21, 1), -1, Some((0, 0)));
1939
1940 test1((999_999_991, 1), 2, Some((999_999_991, 1)));
1942 test1((999_999_991, 1), 1, Some((999_999_991, 1)));
1944 test1((999_999_991, 1), 0, Some((999_999_990, 1)));
1946 test1((999_999_991, 1), -1, None);
1948
1949 test(5.0, Some(5.0));
1950 test(5.1, Some(5.0));
1951 test(5.5, Some(6.0));
1952 test(5.9, Some(6.0));
1953 test(-5.0, Some(-5.0));
1954 test(-5.1, Some(-5.0));
1955 test(-5.5, Some(-6.0));
1956 test(-5.6, Some(-6.0));
1957 test(4.0, Some(4.0));
1958 test(4.1, Some(4.0));
1959 test(4.5, Some(5.0));
1960 test(4.9, Some(5.0));
1961 test(-4.0, Some(-4.0));
1962 test(-4.1, Some(-4.0));
1963 test(-4.5, Some(-5.0));
1964 test(-4.6, Some(-5.0));
1965 test(99_999_999.0, Some(99_999_999.0));
1966 test(99_999_999.1, Some(99_999_999.0));
1967 test(99_999_999.5, None);
1968 test(99_999_999.6, None);
1969 test(-99_999_999.0, Some(-99_999_999.0));
1970 test(-99_999_999.1, Some(-99_999_999.0));
1971 test(-99_999_999.5, None);
1972 test(-99_999_999.6, None);
1973 }
1974
1975 #[test]
1976 fn trunc_digits() {
1977 let x = Fixed::<10, 4>(245368746);
1978 assert_eq!(x.trunc_digits(5).to_string(), "24536.8746");
1979 assert_eq!(x.trunc_digits(4).to_string(), "24536.8746");
1980 assert_eq!(x.trunc_digits(3).to_string(), "24536.874");
1981 assert_eq!(x.trunc_digits(2).to_string(), "24536.87");
1982 assert_eq!(x.trunc_digits(1).to_string(), "24536.8");
1983 assert_eq!(x.trunc_digits(0).to_string(), "24536");
1984 assert_eq!(x.trunc_digits(-1).to_string(), "24530");
1985 assert_eq!(x.trunc_digits(-2).to_string(), "24500");
1986 assert_eq!(x.trunc_digits(-3).to_string(), "24000");
1987 assert_eq!(x.trunc_digits(-4).to_string(), "20000");
1988 assert_eq!(x.trunc_digits(-5).to_string(), "0");
1989 assert_eq!(x.trunc_digits(-50).to_string(), "0");
1990
1991 let x = -x;
1992 assert_eq!(x.trunc_digits(5).to_string(), "-24536.8746");
1993 assert_eq!(x.trunc_digits(4).to_string(), "-24536.8746");
1994 assert_eq!(x.trunc_digits(3).to_string(), "-24536.874");
1995 assert_eq!(x.trunc_digits(2).to_string(), "-24536.87");
1996 assert_eq!(x.trunc_digits(1).to_string(), "-24536.8");
1997 assert_eq!(x.trunc_digits(0).to_string(), "-24536");
1998 assert_eq!(x.trunc_digits(-1).to_string(), "-24530");
1999 assert_eq!(x.trunc_digits(-2).to_string(), "-24500");
2000 assert_eq!(x.trunc_digits(-3).to_string(), "-24000");
2001 assert_eq!(x.trunc_digits(-4).to_string(), "-20000");
2002 assert_eq!(x.trunc_digits(-5).to_string(), "0");
2003 assert_eq!(x.trunc_digits(-50).to_string(), "0");
2004 }
2005
2006 #[test]
2007 fn sign() {
2008 assert_eq!(f(-0.1).sign(), Fixed::<1, 0>::try_from(-1).unwrap());
2009 assert_eq!(f(0.0).sign(), Fixed::<1, 0>::try_from(0).unwrap());
2010 assert_eq!(f(0.5).sign(), Fixed::<1, 0>::try_from(1).unwrap());
2011 }
2012
2013 #[test]
2014 fn sqrt() {
2015 assert_eq!(f(0.0).sqrt(), f(0.0));
2017 assert_eq!(f(1.0).sqrt(), f(1.0));
2018 assert_eq!(f(2.0).sqrt(), f(1.41));
2019 assert_eq!(f(3.0).sqrt(), f(1.73));
2020 assert_eq!(f(4.0).sqrt(), f(2.0));
2021 assert_eq!(f(-1.0).checked_sqrt(), None);
2022
2023 for a in 0..=999 {
2025 let af: Fixed<10, 2> = Fixed(a);
2026 assert_eq!(af.sqrt(), Fixed::<10, 2>((a * 100).isqrt()));
2027 }
2028 }
2029
2030 #[test]
2031 fn nullable() {
2032 fn nullable_checked_add_generic<
2035 const PA: usize,
2036 const SA: usize,
2037 const PB: usize,
2038 const SB: usize,
2039 const PC: usize,
2040 const SC: usize,
2041 >(
2042 a: Option<Fixed<PA, SA>>,
2043 b: Option<Fixed<PB, SB>>,
2044 ) -> Option<Fixed<PC, SC>> {
2045 a.zip(b).and_then(|(a, b)| a.checked_add_generic(b))
2046 }
2047
2048 let a: Option<Fixed<10, 2>> = Some("1.23".parse().unwrap());
2049 let b: Option<Fixed<5, 4>> = Some("4.5678".parse().unwrap());
2050 let c: Option<Fixed<10, 4>> = nullable_checked_add_generic(a, b);
2051 assert_eq!(c, Some("5.7978".parse().unwrap()));
2052 }
2053
2054 #[test]
2055 fn to_integer() {
2056 for x in -9999..=9999 {
2057 let f = Fixed::<4, 1>(x);
2058 assert_eq!(i128::from(f), x / 10);
2059 assert_eq!(i64::try_from(f).unwrap(), (x / 10) as i64);
2060 assert_eq!(i32::try_from(f).unwrap(), (x / 10) as i32);
2061 assert_eq!(i16::try_from(f).unwrap(), (x / 10) as i16);
2062 assert_eq!(
2063 i8::try_from(f).ok(),
2064 (-1289..=1279).contains(&x).then_some((x / 10) as i8)
2065 );
2066 assert_eq!(
2067 u128::try_from(f).ok(),
2068 (x > -10).then_some((x / 10) as u128)
2069 );
2070 assert_eq!(u64::try_from(f).ok(), (x > -10).then_some((x / 10) as u64));
2071 assert_eq!(u32::try_from(f).ok(), (x > -10).then_some((x / 10) as u32));
2072 assert_eq!(u16::try_from(f).ok(), (x > -10).then_some((x / 10) as u16));
2073 assert_eq!(
2074 u8::try_from(f).ok(),
2075 (-9..=2559).contains(&x).then_some((x / 10) as u8)
2076 );
2077 }
2078 }
2079
2080 #[test]
2081 fn compare_against_fixed() {
2082 fn check_comparisons<const PA: usize, const SA: usize, const PB: usize, const SB: usize>(
2083 fx: Fixed<PA, SA>,
2084 fy: Fixed<PB, SB>,
2085 x: i128,
2086 y: i128,
2087 ) {
2088 assert_eq!(fx == fy, x == y);
2089 assert_eq!(fx != fy, x != y);
2090 assert_eq!(fx > fy, x > y);
2091 assert_eq!(fx >= fy, x >= y);
2092 assert_eq!(fx < fy, x < y);
2093 assert_eq!(fx <= fy, x <= y);
2094 }
2095
2096 for x in -999..=999 {
2097 let fx = Fixed::<3, 1>(x);
2098 for y in -999..=999 {
2099 check_comparisons(fx, Fixed::<3, 0>(y), x, y * 10);
2100 check_comparisons(fx, Fixed::<3, 1>(y), x, y);
2101 check_comparisons(fx, Fixed::<3, 2>(y), x * 10, y);
2102 }
2103 }
2104 }
2105
2106 #[test]
2107 fn compare_against_integers() {
2108 for x in -999..=999 {
2109 let f = Fixed::<3, 1>(x);
2110 for y in -100..=100 {
2111 let expect = x == y * 10;
2112 assert_eq!(f == y as i8, expect);
2113 assert_eq!(f == y as i16, expect);
2114 assert_eq!(f == y as i32, expect);
2115 assert_eq!(f == y as i64, expect);
2116 assert_eq!(f == y, expect);
2117 assert_eq!(f == y as isize, expect);
2118 if y >= 0 {
2119 assert_eq!(f == y as u8, expect);
2120 assert_eq!(f == y as u16, expect);
2121 assert_eq!(f == y as u32, expect);
2122 assert_eq!(f == y as u64, expect);
2123 assert_eq!(f == y as u128, expect);
2124 assert_eq!(f == y as usize, expect);
2125 }
2126 }
2127 }
2128 }
2129
2130 #[test]
2131 fn unsigned_encoding() {
2132 type F = Fixed<3, 1>;
2133 for x in -999..=999 {
2134 let f = Fixed::<3, 1>(x);
2135 assert_eq!(F::from_unsigned_encoding(f.to_unsigned_encoding()), Some(f));
2136 }
2137 assert_eq!(F::MIN.to_unsigned_encoding(), 0);
2138 assert_eq!(F::ZERO.to_unsigned_encoding(), 999);
2139 assert_eq!(F::MAX.to_unsigned_encoding(), 999 * 2);
2140 assert_eq!(F::from_unsigned_encoding(0), Some(F::MIN));
2141 assert_eq!(F::from_unsigned_encoding(999), Some(F::ZERO));
2142 assert_eq!(F::from_unsigned_encoding(999 * 2), Some(F::MAX));
2143 assert_eq!(F::from_unsigned_encoding(999 * 2 + 1), None);
2144 }
2145
2146 #[test]
2147 fn new() {
2148 type F1 = Fixed<11, 1>;
2149 assert_eq!(F1::new(435, -8), None);
2150 assert_eq!(F1::new(435, -7).unwrap().to_string(), "4350000000");
2151 assert_eq!(F1::new(435, -6).unwrap().to_string(), "435000000");
2152 assert_eq!(F1::new(435, -5).unwrap().to_string(), "43500000");
2153 assert_eq!(F1::new(435, -4).unwrap().to_string(), "4350000");
2154 assert_eq!(F1::new(435, -3).unwrap().to_string(), "435000");
2155 assert_eq!(F1::new(435, -2).unwrap().to_string(), "43500");
2156 assert_eq!(F1::new(435, -1).unwrap().to_string(), "4350");
2157 assert_eq!(F1::new(435, 0).unwrap().to_string(), "435");
2158 assert_eq!(F1::new(435, 1).unwrap().to_string(), "43.5");
2159 assert_eq!(F1::new(435, 2).unwrap().to_string(), "4.3");
2160 assert_eq!(F1::new(435, 3).unwrap().to_string(), "0.4");
2161 assert_eq!(F1::new(435, 4).unwrap().to_string(), "0");
2162
2163 type F2 = Fixed<11, 2>;
2164 assert_eq!(F2::new(435, -7), None);
2165 assert_eq!(F2::new(435, -6).unwrap().to_string(), "435000000");
2166 assert_eq!(F2::new(435, -5).unwrap().to_string(), "43500000");
2167 assert_eq!(F2::new(435, -4).unwrap().to_string(), "4350000");
2168 assert_eq!(F2::new(435, -3).unwrap().to_string(), "435000");
2169 assert_eq!(F2::new(435, -2).unwrap().to_string(), "43500");
2170 assert_eq!(F2::new(435, -1).unwrap().to_string(), "4350");
2171 assert_eq!(F2::new(435, 0).unwrap().to_string(), "435");
2172 assert_eq!(F2::new(435, 1).unwrap().to_string(), "43.5");
2173 assert_eq!(F2::new(435, 2).unwrap().to_string(), "4.35");
2174 assert_eq!(F2::new(435, 3).unwrap().to_string(), "0.43");
2175 assert_eq!(F2::new(435, 4).unwrap().to_string(), "0.04");
2176 assert_eq!(F2::new(435, 5).unwrap().to_string(), "0");
2177 }
2178
2179 #[test]
2180 fn new_round_even() {
2181 type F1 = Fixed<11, 1>;
2182 assert_eq!(F1::new_round_even(435, -8), None);
2183 assert_eq!(
2184 F1::new_round_even(435, -7).unwrap().to_string(),
2185 "4350000000"
2186 );
2187 assert_eq!(
2188 F1::new_round_even(435, -6).unwrap().to_string(),
2189 "435000000"
2190 );
2191 assert_eq!(F1::new_round_even(435, -5).unwrap().to_string(), "43500000");
2192 assert_eq!(F1::new_round_even(435, -4).unwrap().to_string(), "4350000");
2193 assert_eq!(F1::new_round_even(435, -3).unwrap().to_string(), "435000");
2194 assert_eq!(F1::new_round_even(435, -2).unwrap().to_string(), "43500");
2195 assert_eq!(F1::new_round_even(435, -1).unwrap().to_string(), "4350");
2196 assert_eq!(F1::new_round_even(435, 0).unwrap().to_string(), "435");
2197 assert_eq!(F1::new_round_even(435, 1).unwrap().to_string(), "43.5");
2198 assert_eq!(F1::new_round_even(435, 2).unwrap().to_string(), "4.4");
2199 assert_eq!(F1::new_round_even(435, 3).unwrap().to_string(), "0.4");
2200 assert_eq!(F1::new_round_even(435, 4).unwrap().to_string(), "0");
2201
2202 type F2 = Fixed<11, 2>;
2203 assert_eq!(F2::new_round_even(435, -7), None);
2204 assert_eq!(
2205 F2::new_round_even(435, -6).unwrap().to_string(),
2206 "435000000"
2207 );
2208 assert_eq!(F2::new_round_even(435, -5).unwrap().to_string(), "43500000");
2209 assert_eq!(F2::new_round_even(435, -4).unwrap().to_string(), "4350000");
2210 assert_eq!(F2::new_round_even(435, -3).unwrap().to_string(), "435000");
2211 assert_eq!(F2::new_round_even(435, -2).unwrap().to_string(), "43500");
2212 assert_eq!(F2::new_round_even(435, -1).unwrap().to_string(), "4350");
2213 assert_eq!(F2::new_round_even(435, 0).unwrap().to_string(), "435");
2214 assert_eq!(F2::new_round_even(435, 1).unwrap().to_string(), "43.5");
2215 assert_eq!(F2::new_round_even(435, 2).unwrap().to_string(), "4.35");
2216 assert_eq!(F2::new_round_even(435, 3).unwrap().to_string(), "0.44");
2217 assert_eq!(F2::new_round_even(435, 4).unwrap().to_string(), "0.04");
2218 assert_eq!(F2::new_round_even(435, 5).unwrap().to_string(), "0");
2219 }
2220}