1use super::{
2 Sign, Signed,
3 utils::{handle_overflow, twos_complement},
4};
5use core::{cmp, iter, ops};
6use ruint::Uint;
7
8impl<const BITS: usize, const LIMBS: usize> Signed<BITS, LIMBS> {
10 #[inline]
19 #[track_caller]
20 #[must_use]
21 pub fn abs(self) -> Self {
22 handle_overflow(self.overflowing_abs())
23 }
24
25 #[inline]
32 #[must_use]
33 pub fn overflowing_abs(self) -> (Self, bool) {
34 if BITS == 0 {
35 return (self, false);
36 }
37 if self == Self::MIN { (self, true) } else { (Self(self.unsigned_abs()), false) }
38 }
39
40 #[inline]
43 #[must_use]
44 pub fn checked_abs(self) -> Option<Self> {
45 match self.overflowing_abs() {
46 (value, false) => Some(value),
47 _ => None,
48 }
49 }
50
51 #[inline]
54 #[must_use]
55 pub fn saturating_abs(self) -> Self {
56 match self.overflowing_abs() {
57 (value, false) => value,
58 _ => Self::MAX,
59 }
60 }
61
62 #[inline]
65 #[must_use]
66 pub fn wrapping_abs(self) -> Self {
67 self.overflowing_abs().0
68 }
69
70 #[inline]
72 #[must_use]
73 pub fn unsigned_abs(self) -> Uint<BITS, LIMBS> {
74 self.into_sign_and_abs().1
75 }
76
77 #[inline]
84 #[must_use]
85 pub fn overflowing_neg(self) -> (Self, bool) {
86 if BITS == 0 {
87 return (self, false);
88 }
89 if self == Self::MIN { (self, true) } else { (Self(twos_complement(self.0)), false) }
90 }
91
92 #[inline]
94 #[must_use]
95 pub fn checked_neg(self) -> Option<Self> {
96 match self.overflowing_neg() {
97 (value, false) => Some(value),
98 _ => None,
99 }
100 }
101
102 #[inline]
105 #[must_use]
106 pub fn saturating_neg(self) -> Self {
107 match self.overflowing_neg() {
108 (value, false) => value,
109 _ => Self::MAX,
110 }
111 }
112
113 #[inline]
121 #[must_use]
122 pub fn wrapping_neg(self) -> Self {
123 self.overflowing_neg().0
124 }
125
126 #[inline]
132 #[must_use]
133 pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
134 let (unsigned, _) = self.0.overflowing_add(rhs.0);
135 let result = Self(unsigned);
136
137 let overflow = matches!(
140 (self.sign(), rhs.sign(), result.sign()),
141 (Sign::Positive, Sign::Positive, Sign::Negative)
142 | (Sign::Negative, Sign::Negative, Sign::Positive)
143 );
144
145 (result, overflow)
146 }
147
148 #[inline]
151 #[must_use]
152 pub const fn checked_add(self, rhs: Self) -> Option<Self> {
153 match self.overflowing_add(rhs) {
154 (value, false) => Some(value),
155 _ => None,
156 }
157 }
158
159 #[inline]
162 #[must_use]
163 pub const fn saturating_add(self, rhs: Self) -> Self {
164 let (result, overflow) = self.overflowing_add(rhs);
165 if overflow {
166 match result.sign() {
167 Sign::Positive => Self::MIN,
168 Sign::Negative => Self::MAX,
169 }
170 } else {
171 result
172 }
173 }
174
175 #[inline]
178 #[must_use]
179 pub const fn wrapping_add(self, rhs: Self) -> Self {
180 self.overflowing_add(rhs).0
181 }
182
183 #[inline]
189 #[must_use]
190 pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
191 let (unsigned, _) = self.0.overflowing_sub(rhs.0);
196 let result = Self(unsigned);
197
198 let overflow = matches!(
201 (self.sign(), rhs.sign(), result.sign()),
202 (Sign::Positive, Sign::Negative, Sign::Negative)
203 | (Sign::Negative, Sign::Positive, Sign::Positive)
204 );
205
206 (result, overflow)
207 }
208
209 #[inline]
212 #[must_use]
213 pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
214 match self.overflowing_sub(rhs) {
215 (value, false) => Some(value),
216 _ => None,
217 }
218 }
219
220 #[inline]
223 #[must_use]
224 pub const fn saturating_sub(self, rhs: Self) -> Self {
225 let (result, overflow) = self.overflowing_sub(rhs);
226 if overflow {
227 match result.sign() {
228 Sign::Positive => Self::MIN,
229 Sign::Negative => Self::MAX,
230 }
231 } else {
232 result
233 }
234 }
235
236 #[inline]
239 #[must_use]
240 pub const fn wrapping_sub(self, rhs: Self) -> Self {
241 self.overflowing_sub(rhs).0
242 }
243
244 #[inline]
250 #[must_use]
251 pub fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
252 if self.is_zero() || rhs.is_zero() {
253 return (Self::ZERO, false);
254 }
255 let sign = self.sign() * rhs.sign();
256 let (unsigned, overflow_mul) = self.unsigned_abs().overflowing_mul(rhs.unsigned_abs());
257 let (result, overflow_conv) = Self::overflowing_from_sign_and_abs(sign, unsigned);
258
259 (result, overflow_mul || overflow_conv)
260 }
261
262 #[inline]
265 #[must_use]
266 pub fn checked_mul(self, rhs: Self) -> Option<Self> {
267 match self.overflowing_mul(rhs) {
268 (value, false) => Some(value),
269 _ => None,
270 }
271 }
272
273 #[inline]
276 #[must_use]
277 pub fn saturating_mul(self, rhs: Self) -> Self {
278 let (result, overflow) = self.overflowing_mul(rhs);
279 if overflow {
280 match self.sign() * rhs.sign() {
281 Sign::Positive => Self::MAX,
282 Sign::Negative => Self::MIN,
283 }
284 } else {
285 result
286 }
287 }
288
289 #[inline]
292 #[must_use]
293 pub fn wrapping_mul(self, rhs: Self) -> Self {
294 self.overflowing_mul(rhs).0
295 }
296
297 #[inline]
307 #[track_caller]
308 #[must_use]
309 pub fn overflowing_div(self, rhs: Self) -> (Self, bool) {
310 assert!(!rhs.is_zero(), "attempt to divide by zero");
311 let sign = self.sign() * rhs.sign();
312 let unsigned = self.unsigned_abs() / rhs.unsigned_abs();
314 let (result, overflow_conv) = Self::overflowing_from_sign_and_abs(sign, unsigned);
315
316 (result, overflow_conv && !result.is_zero())
317 }
318
319 #[inline]
322 #[must_use]
323 pub fn checked_div(self, rhs: Self) -> Option<Self> {
324 if rhs.is_zero() || (self == Self::MIN && rhs == Self::MINUS_ONE) {
325 None
326 } else {
327 Some(self.overflowing_div(rhs).0)
328 }
329 }
330
331 #[inline]
338 #[track_caller]
339 #[must_use]
340 pub fn saturating_div(self, rhs: Self) -> Self {
341 match self.overflowing_div(rhs) {
342 (value, false) => value,
343 _ => Self::MAX,
345 }
346 }
347
348 #[inline]
361 #[track_caller]
362 #[must_use]
363 pub fn wrapping_div(self, rhs: Self) -> Self {
364 self.overflowing_div(rhs).0
365 }
366
367 #[inline]
377 #[track_caller]
378 #[must_use]
379 pub fn overflowing_rem(self, rhs: Self) -> (Self, bool) {
380 if self == Self::MIN && rhs == Self::MINUS_ONE {
381 (Self::ZERO, true)
382 } else {
383 let div_res = self / rhs;
384 (self - div_res * rhs, false)
385 }
386 }
387
388 #[inline]
391 #[must_use]
392 pub fn checked_rem(self, rhs: Self) -> Option<Self> {
393 if rhs.is_zero() || (self == Self::MIN && rhs == Self::MINUS_ONE) {
394 None
395 } else {
396 Some(self.overflowing_rem(rhs).0)
397 }
398 }
399
400 #[inline]
412 #[track_caller]
413 #[must_use]
414 pub fn wrapping_rem(self, rhs: Self) -> Self {
415 self.overflowing_rem(rhs).0
416 }
417
418 #[inline]
432 #[track_caller]
433 #[must_use]
434 pub fn div_euclid(self, rhs: Self) -> Self {
435 let q = self / rhs;
436 if (self % rhs).is_negative() {
437 if rhs.is_positive() { q - Self::ONE } else { q + Self::ONE }
438 } else {
439 q
440 }
441 }
442
443 #[inline]
453 #[track_caller]
454 #[must_use]
455 pub fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) {
456 if self == Self::MIN && rhs == Self::MINUS_ONE {
457 (self, true)
458 } else {
459 (self.div_euclid(rhs), false)
460 }
461 }
462
463 #[inline]
466 #[must_use]
467 pub fn checked_div_euclid(self, rhs: Self) -> Option<Self> {
468 if rhs.is_zero() || (self == Self::MIN && rhs == Self::MINUS_ONE) {
469 None
470 } else {
471 Some(self.div_euclid(rhs))
472 }
473 }
474
475 #[inline]
487 #[track_caller]
488 #[must_use]
489 pub fn wrapping_div_euclid(self, rhs: Self) -> Self {
490 self.overflowing_div_euclid(rhs).0
491 }
492
493 #[inline]
503 #[track_caller]
504 #[must_use]
505 pub fn rem_euclid(self, rhs: Self) -> Self {
506 let r = self % rhs;
507 if r < Self::ZERO { if rhs < Self::ZERO { r - rhs } else { r + rhs } } else { r }
508 }
509
510 #[inline]
520 #[track_caller]
521 #[must_use]
522 pub fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) {
523 if self == Self::MIN && rhs == Self::MINUS_ONE {
524 (Self::ZERO, true)
525 } else {
526 (self.rem_euclid(rhs), false)
527 }
528 }
529
530 #[inline]
541 #[track_caller]
542 #[must_use]
543 pub fn wrapping_rem_euclid(self, rhs: Self) -> Self {
544 self.overflowing_rem_euclid(rhs).0
545 }
546
547 #[inline]
550 #[must_use]
551 pub fn checked_rem_euclid(self, rhs: Self) -> Option<Self> {
552 if rhs.is_zero() || (self == Self::MIN && rhs == Self::MINUS_ONE) {
553 None
554 } else {
555 Some(self.rem_euclid(rhs))
556 }
557 }
558
559 #[inline]
567 pub(crate) const fn pow_sign(self, exp: Uint<BITS, LIMBS>) -> Sign {
568 let is_exp_odd = BITS != 0 && exp.as_limbs()[0] % 2 == 1;
569 if is_exp_odd && self.is_negative() { Sign::Negative } else { Sign::Positive }
570 }
571
572 #[inline]
578 #[track_caller]
579 #[must_use]
580 pub fn exp10(n: usize) -> Self {
581 Uint::<BITS, LIMBS>::from(10).pow(Uint::from(n)).try_into().expect("overflow")
582 }
583
584 #[inline]
590 #[track_caller]
591 #[must_use]
592 pub fn pow(self, exp: Uint<BITS, LIMBS>) -> Self {
593 handle_overflow(self.overflowing_pow(exp))
594 }
595
596 #[inline]
601 #[must_use]
602 pub fn overflowing_pow(self, exp: Uint<BITS, LIMBS>) -> (Self, bool) {
603 if BITS == 0 {
604 return (Self::ZERO, false);
605 }
606
607 let sign = self.pow_sign(exp);
608
609 let (unsigned, overflow_pow) = self.unsigned_abs().overflowing_pow(exp);
610 let (result, overflow_conv) = Self::overflowing_from_sign_and_abs(sign, unsigned);
611
612 (result, overflow_pow || overflow_conv)
613 }
614
615 #[inline]
618 #[must_use]
619 pub fn checked_pow(self, exp: Uint<BITS, LIMBS>) -> Option<Self> {
620 let (result, overflow) = self.overflowing_pow(exp);
621 if overflow { None } else { Some(result) }
622 }
623
624 #[inline]
627 #[must_use]
628 pub fn saturating_pow(self, exp: Uint<BITS, LIMBS>) -> Self {
629 let (result, overflow) = self.overflowing_pow(exp);
630 if overflow {
631 match self.pow_sign(exp) {
632 Sign::Positive => Self::MAX,
633 Sign::Negative => Self::MIN,
634 }
635 } else {
636 result
637 }
638 }
639
640 #[inline]
643 #[must_use]
644 pub fn wrapping_pow(self, exp: Uint<BITS, LIMBS>) -> Self {
645 self.overflowing_pow(exp).0
646 }
647
648 #[inline]
654 #[must_use]
655 pub fn overflowing_shl(self, rhs: usize) -> (Self, bool) {
656 if rhs >= 256 { (Self::ZERO, true) } else { (Self(self.0 << rhs), false) }
657 }
658
659 #[inline]
662 #[must_use]
663 pub fn checked_shl(self, rhs: usize) -> Option<Self> {
664 match self.overflowing_shl(rhs) {
665 (value, false) => Some(value),
666 _ => None,
667 }
668 }
669
670 #[inline]
673 #[must_use]
674 pub fn wrapping_shl(self, rhs: usize) -> Self {
675 self.overflowing_shl(rhs).0
676 }
677
678 #[inline]
684 #[must_use]
685 pub fn overflowing_shr(self, rhs: usize) -> (Self, bool) {
686 if rhs >= 256 { (Self::ZERO, true) } else { (Self(self.0 >> rhs), false) }
687 }
688
689 #[inline]
692 #[must_use]
693 pub fn checked_shr(self, rhs: usize) -> Option<Self> {
694 match self.overflowing_shr(rhs) {
695 (value, false) => Some(value),
696 _ => None,
697 }
698 }
699
700 #[inline]
703 #[must_use]
704 pub fn wrapping_shr(self, rhs: usize) -> Self {
705 self.overflowing_shr(rhs).0
706 }
707
708 #[inline]
712 #[must_use]
713 pub fn asr(self, rhs: usize) -> Self {
714 if rhs == 0 || BITS == 0 {
716 return self;
717 }
718
719 if rhs >= BITS - 1 {
720 match self.sign() {
721 Sign::Positive => return Self::ZERO,
722 Sign::Negative => return Self::MINUS_ONE,
723 }
724 }
725
726 match self.sign() {
727 Sign::Positive => self.wrapping_shr(rhs),
729 Sign::Negative => {
730 let two: Uint<BITS, LIMBS> = Uint::from(2);
734 let bitwise_or = Self::from_raw(
735 !(two.pow(Uint::<BITS, LIMBS>::from(BITS - rhs))
736 - Uint::<BITS, LIMBS>::from(1)),
737 );
738 (self.wrapping_shr(rhs)) | bitwise_or
739 }
740 }
741 }
742
743 #[inline]
749 #[must_use]
750 pub fn asl(self, rhs: usize) -> Option<Self> {
751 if rhs == 0 || BITS == 0 {
752 Some(self)
753 } else {
754 let result = self.wrapping_shl(rhs);
755 if result.sign() != self.sign() {
756 None
758 } else {
759 Some(result)
760 }
761 }
762 }
763
764 #[inline]
766 #[must_use]
767 pub fn twos_complement(self) -> Uint<BITS, LIMBS> {
768 let abs = self.into_raw();
769 match self.sign() {
770 Sign::Positive => abs,
771 Sign::Negative => twos_complement(abs),
772 }
773 }
774}
775
776macro_rules! impl_shift {
779 ($($t:ty),+) => {
780 $(
785 impl<const BITS: usize, const LIMBS: usize> ops::Shl<$t> for Signed<BITS, LIMBS> {
786 type Output = Self;
787
788 #[inline]
789 fn shl(self, rhs: $t) -> Self::Output {
790 self.wrapping_shl(rhs as usize)
791 }
792 }
793
794 impl<const BITS: usize, const LIMBS: usize> ops::ShlAssign<$t> for Signed<BITS, LIMBS> {
795 #[inline]
796 fn shl_assign(&mut self, rhs: $t) {
797 *self = *self << rhs;
798 }
799 }
800
801 impl<const BITS: usize, const LIMBS: usize> ops::Shr<$t> for Signed<BITS, LIMBS> {
802 type Output = Self;
803
804 #[inline]
805 fn shr(self, rhs: $t) -> Self::Output {
806 self.wrapping_shr(rhs as usize)
807 }
808 }
809
810 impl<const BITS: usize, const LIMBS: usize> ops::ShrAssign<$t> for Signed<BITS, LIMBS> {
811 #[inline]
812 fn shr_assign(&mut self, rhs: $t) {
813 *self = *self >> rhs;
814 }
815 }
816 )+
817 };
818}
819
820#[cfg(target_pointer_width = "16")]
821impl_shift!(i8, u8, i16, u16, isize, usize);
822
823#[cfg(target_pointer_width = "32")]
824impl_shift!(i8, u8, i16, u16, i32, u32, isize, usize);
825
826#[cfg(target_pointer_width = "64")]
827impl_shift!(i8, u8, i16, u16, i32, u32, i64, u64, isize, usize);
828
829impl<const BITS: usize, const LIMBS: usize> cmp::PartialOrd for Signed<BITS, LIMBS> {
831 #[inline]
832 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
833 Some(self.cmp(other))
834 }
835}
836
837impl<const BITS: usize, const LIMBS: usize> cmp::Ord for Signed<BITS, LIMBS> {
838 #[inline]
839 fn cmp(&self, other: &Self) -> cmp::Ordering {
840 use Sign::*;
844 use cmp::Ordering::*;
845
846 match (self.into_sign_and_abs(), other.into_sign_and_abs()) {
847 ((Positive, _), (Negative, _)) => Greater,
848 ((Negative, _), (Positive, _)) => Less,
849 ((Positive, this), (Positive, other)) => this.cmp(&other),
850 ((Negative, this), (Negative, other)) => other.cmp(&this),
851 }
852 }
853}
854
855impl<T, const BITS: usize, const LIMBS: usize> ops::Add<T> for Signed<BITS, LIMBS>
857where
858 T: Into<Self>,
859{
860 type Output = Self;
861
862 #[inline]
863 #[track_caller]
864 fn add(self, rhs: T) -> Self::Output {
865 handle_overflow(self.overflowing_add(rhs.into()))
866 }
867}
868
869impl<T, const BITS: usize, const LIMBS: usize> ops::AddAssign<T> for Signed<BITS, LIMBS>
870where
871 T: Into<Self>,
872{
873 #[inline]
874 #[track_caller]
875 fn add_assign(&mut self, rhs: T) {
876 *self = *self + rhs;
877 }
878}
879
880impl<T, const BITS: usize, const LIMBS: usize> ops::Sub<T> for Signed<BITS, LIMBS>
881where
882 T: Into<Self>,
883{
884 type Output = Self;
885
886 #[inline]
887 #[track_caller]
888 fn sub(self, rhs: T) -> Self::Output {
889 handle_overflow(self.overflowing_sub(rhs.into()))
890 }
891}
892
893impl<T, const BITS: usize, const LIMBS: usize> ops::SubAssign<T> for Signed<BITS, LIMBS>
894where
895 T: Into<Self>,
896{
897 #[inline]
898 #[track_caller]
899 fn sub_assign(&mut self, rhs: T) {
900 *self = *self - rhs;
901 }
902}
903
904impl<T, const BITS: usize, const LIMBS: usize> ops::Mul<T> for Signed<BITS, LIMBS>
905where
906 T: Into<Self>,
907{
908 type Output = Self;
909
910 #[inline]
911 #[track_caller]
912 fn mul(self, rhs: T) -> Self::Output {
913 handle_overflow(self.overflowing_mul(rhs.into()))
914 }
915}
916
917impl<T, const BITS: usize, const LIMBS: usize> ops::MulAssign<T> for Signed<BITS, LIMBS>
918where
919 T: Into<Self>,
920{
921 #[inline]
922 #[track_caller]
923 fn mul_assign(&mut self, rhs: T) {
924 *self = *self * rhs;
925 }
926}
927
928impl<T, const BITS: usize, const LIMBS: usize> ops::Div<T> for Signed<BITS, LIMBS>
929where
930 T: Into<Self>,
931{
932 type Output = Self;
933
934 #[inline]
935 #[track_caller]
936 fn div(self, rhs: T) -> Self::Output {
937 handle_overflow(self.overflowing_div(rhs.into()))
938 }
939}
940
941impl<T, const BITS: usize, const LIMBS: usize> ops::DivAssign<T> for Signed<BITS, LIMBS>
942where
943 T: Into<Self>,
944{
945 #[inline]
946 #[track_caller]
947 fn div_assign(&mut self, rhs: T) {
948 *self = *self / rhs;
949 }
950}
951
952impl<T, const BITS: usize, const LIMBS: usize> ops::Rem<T> for Signed<BITS, LIMBS>
953where
954 T: Into<Self>,
955{
956 type Output = Self;
957
958 #[inline]
959 #[track_caller]
960 fn rem(self, rhs: T) -> Self::Output {
961 handle_overflow(self.overflowing_rem(rhs.into()))
962 }
963}
964
965impl<T, const BITS: usize, const LIMBS: usize> ops::RemAssign<T> for Signed<BITS, LIMBS>
966where
967 T: Into<Self>,
968{
969 #[inline]
970 #[track_caller]
971 fn rem_assign(&mut self, rhs: T) {
972 *self = *self % rhs;
973 }
974}
975
976impl<T, const BITS: usize, const LIMBS: usize> iter::Sum<T> for Signed<BITS, LIMBS>
977where
978 T: Into<Self>,
979{
980 #[inline]
981 #[track_caller]
982 fn sum<I: Iterator<Item = T>>(iter: I) -> Self {
983 iter.fold(Self::ZERO, |acc, x| acc + x)
984 }
985}
986
987impl<T, const BITS: usize, const LIMBS: usize> iter::Product<T> for Signed<BITS, LIMBS>
988where
989 T: Into<Self>,
990{
991 #[inline]
992 #[track_caller]
993 fn product<I: Iterator<Item = T>>(iter: I) -> Self {
994 iter.fold(Self::ONE, |acc, x| acc * x)
995 }
996}
997
998impl<const BITS: usize, const LIMBS: usize> ops::BitAnd for Signed<BITS, LIMBS> {
1000 type Output = Self;
1001
1002 #[inline]
1003 fn bitand(self, rhs: Self) -> Self::Output {
1004 Self(self.0 & rhs.0)
1005 }
1006}
1007
1008impl<const BITS: usize, const LIMBS: usize> ops::BitAndAssign for Signed<BITS, LIMBS> {
1009 #[inline]
1010 fn bitand_assign(&mut self, rhs: Self) {
1011 *self = *self & rhs;
1012 }
1013}
1014
1015impl<const BITS: usize, const LIMBS: usize> ops::BitOr for Signed<BITS, LIMBS> {
1016 type Output = Self;
1017
1018 #[inline]
1019 fn bitor(self, rhs: Self) -> Self::Output {
1020 Self(self.0 | rhs.0)
1021 }
1022}
1023
1024impl<const BITS: usize, const LIMBS: usize> ops::BitOrAssign for Signed<BITS, LIMBS> {
1025 #[inline]
1026 fn bitor_assign(&mut self, rhs: Self) {
1027 *self = *self | rhs;
1028 }
1029}
1030
1031impl<const BITS: usize, const LIMBS: usize> ops::BitXor for Signed<BITS, LIMBS> {
1032 type Output = Self;
1033
1034 #[inline]
1035 fn bitxor(self, rhs: Self) -> Self::Output {
1036 Self(self.0 ^ rhs.0)
1037 }
1038}
1039
1040impl<const BITS: usize, const LIMBS: usize> ops::BitXorAssign for Signed<BITS, LIMBS> {
1041 #[inline]
1042 fn bitxor_assign(&mut self, rhs: Self) {
1043 *self = *self ^ rhs;
1044 }
1045}
1046
1047impl<const BITS: usize, const LIMBS: usize> ops::Neg for Signed<BITS, LIMBS> {
1049 type Output = Self;
1050
1051 #[inline]
1052 #[track_caller]
1053 fn neg(self) -> Self::Output {
1054 handle_overflow(self.overflowing_neg())
1055 }
1056}
1057
1058impl<const BITS: usize, const LIMBS: usize> ops::Not for Signed<BITS, LIMBS> {
1059 type Output = Self;
1060
1061 #[inline]
1062 fn not(self) -> Self::Output {
1063 Self(!self.0)
1064 }
1065}