1use crate::arith::derive_arith;
19use crate::bigint::div::div_rem;
20use num::cast::AsPrimitive;
21use num::{BigInt, FromPrimitive, ToPrimitive};
22use std::cmp::Ordering;
23use std::num::ParseIntError;
24use std::ops::{BitAnd, BitOr, BitXor, Neg, Shl, Shr};
25use std::str::FromStr;
26
27mod div;
28
29#[derive(Debug)]
31pub struct ParseI256Error {}
32
33impl From<ParseIntError> for ParseI256Error {
34 fn from(_: ParseIntError) -> Self {
35 Self {}
36 }
37}
38
39impl std::fmt::Display for ParseI256Error {
40 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41 write!(f, "Failed to parse as i256")
42 }
43}
44impl std::error::Error for ParseI256Error {}
45
46enum DivRemError {
48 DivideByZero,
50 DivideOverflow,
52}
53
54#[allow(non_camel_case_types)]
56#[derive(Copy, Clone, Default, Eq, PartialEq, Hash)]
57#[repr(C)]
58pub struct i256 {
59 low: u128,
60 high: i128,
61}
62
63impl std::fmt::Debug for i256 {
64 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65 write!(f, "{self}")
66 }
67}
68
69impl std::fmt::Display for i256 {
70 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71 write!(f, "{}", BigInt::from_signed_bytes_le(&self.to_le_bytes()))
72 }
73}
74
75impl FromStr for i256 {
76 type Err = ParseI256Error;
77
78 fn from_str(s: &str) -> Result<Self, Self::Err> {
79 if s.len() <= 38 {
81 return Ok(Self::from_i128(i128::from_str(s)?));
82 }
83
84 let (negative, s) = match s.as_bytes()[0] {
85 b'-' => (true, &s[1..]),
86 b'+' => (false, &s[1..]),
87 _ => (false, s),
88 };
89
90 let s = s.trim_start_matches('0');
92 if s.is_empty() {
93 return Ok(i256::ZERO);
94 }
95
96 if !s.as_bytes()[0].is_ascii_digit() {
97 return Err(ParseI256Error {});
99 }
100
101 parse_impl(s, negative)
102 }
103}
104
105impl From<i8> for i256 {
106 fn from(value: i8) -> Self {
107 Self::from_i128(value.into())
108 }
109}
110
111impl From<i16> for i256 {
112 fn from(value: i16) -> Self {
113 Self::from_i128(value.into())
114 }
115}
116
117impl From<i32> for i256 {
118 fn from(value: i32) -> Self {
119 Self::from_i128(value.into())
120 }
121}
122
123impl From<i64> for i256 {
124 fn from(value: i64) -> Self {
125 Self::from_i128(value.into())
126 }
127}
128
129fn parse_impl(s: &str, negative: bool) -> Result<i256, ParseI256Error> {
131 if s.len() <= 38 {
132 let low = i128::from_str(s)?;
133 return Ok(match negative {
134 true => i256::from_parts(low.neg() as _, -1),
135 false => i256::from_parts(low as _, 0),
136 });
137 }
138
139 let split = s.len() - 38;
140 if !s.as_bytes()[split].is_ascii_digit() {
141 return Err(ParseI256Error {});
143 }
144 let (hs, ls) = s.split_at(split);
145
146 let mut low = i128::from_str(ls)?;
147 let high = parse_impl(hs, negative)?;
148
149 if negative {
150 low = -low;
151 }
152
153 let low = i256::from_i128(low);
154
155 high.checked_mul(i256::from_i128(10_i128.pow(38)))
156 .and_then(|high| high.checked_add(low))
157 .ok_or(ParseI256Error {})
158}
159
160impl PartialOrd for i256 {
161 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
162 Some(self.cmp(other))
163 }
164}
165
166impl Ord for i256 {
167 fn cmp(&self, other: &Self) -> Ordering {
168 self.high.cmp(&other.high).then(self.low.cmp(&other.low))
171 }
172}
173
174impl i256 {
175 pub const ZERO: Self = i256 { low: 0, high: 0 };
177
178 pub const ONE: Self = i256 { low: 1, high: 0 };
180
181 pub const MINUS_ONE: Self = i256 {
183 low: u128::MAX,
184 high: -1,
185 };
186
187 pub const MAX: Self = i256 {
189 low: u128::MAX,
190 high: i128::MAX,
191 };
192
193 pub const MIN: Self = i256 {
195 low: u128::MIN,
196 high: i128::MIN,
197 };
198
199 #[inline]
201 pub const fn from_le_bytes(b: [u8; 32]) -> Self {
202 let (low, high) = split_array(b);
203 Self {
204 high: i128::from_le_bytes(high),
205 low: u128::from_le_bytes(low),
206 }
207 }
208
209 #[inline]
211 pub const fn from_be_bytes(b: [u8; 32]) -> Self {
212 let (high, low) = split_array(b);
213 Self {
214 high: i128::from_be_bytes(high),
215 low: u128::from_be_bytes(low),
216 }
217 }
218
219 pub const fn from_i128(v: i128) -> Self {
221 Self::from_parts(v as u128, v >> 127)
222 }
223
224 #[inline]
226 pub fn from_string(value_str: &str) -> Option<Self> {
227 value_str.parse().ok()
228 }
229
230 pub fn from_f64(v: f64) -> Option<Self> {
233 BigInt::from_f64(v).and_then(|i| {
234 let (integer, overflow) = i256::from_bigint_with_overflow(i);
235 if overflow {
236 None
237 } else {
238 Some(integer)
239 }
240 })
241 }
242
243 #[inline]
245 pub const fn from_parts(low: u128, high: i128) -> Self {
246 Self { low, high }
247 }
248
249 pub const fn to_parts(self) -> (u128, i128) {
251 (self.low, self.high)
252 }
253
254 pub fn to_i128(self) -> Option<i128> {
257 let as_i128 = self.low as i128;
258
259 let high_negative = self.high < 0;
260 let low_negative = as_i128 < 0;
261 let high_valid = self.high == -1 || self.high == 0;
262
263 (high_negative == low_negative && high_valid).then_some(self.low as i128)
264 }
265
266 pub fn as_i128(self) -> i128 {
268 self.low as i128
269 }
270
271 #[inline]
273 pub const fn to_le_bytes(self) -> [u8; 32] {
274 let low = self.low.to_le_bytes();
275 let high = self.high.to_le_bytes();
276 let mut t = [0; 32];
277 let mut i = 0;
278 while i != 16 {
279 t[i] = low[i];
280 t[i + 16] = high[i];
281 i += 1;
282 }
283 t
284 }
285
286 #[inline]
288 pub const fn to_be_bytes(self) -> [u8; 32] {
289 let low = self.low.to_be_bytes();
290 let high = self.high.to_be_bytes();
291 let mut t = [0; 32];
292 let mut i = 0;
293 while i != 16 {
294 t[i] = high[i];
295 t[i + 16] = low[i];
296 i += 1;
297 }
298 t
299 }
300
301 fn from_bigint_with_overflow(v: BigInt) -> (Self, bool) {
304 let v_bytes = v.to_signed_bytes_le();
305 match v_bytes.len().cmp(&32) {
306 Ordering::Less => {
307 let mut bytes = if num::Signed::is_negative(&v) {
308 [255_u8; 32]
309 } else {
310 [0; 32]
311 };
312 bytes[0..v_bytes.len()].copy_from_slice(&v_bytes[..v_bytes.len()]);
313 (Self::from_le_bytes(bytes), false)
314 }
315 Ordering::Equal => (Self::from_le_bytes(v_bytes.try_into().unwrap()), false),
316 Ordering::Greater => (Self::from_le_bytes(v_bytes[..32].try_into().unwrap()), true),
317 }
318 }
319
320 #[inline]
322 pub fn wrapping_abs(self) -> Self {
323 let sa = self.high >> 127;
325 let sa = Self::from_parts(sa as u128, sa);
326
327 Self::from_parts(self.low ^ sa.low, self.high ^ sa.high).wrapping_sub(sa)
329 }
330
331 #[inline]
333 pub fn checked_abs(self) -> Option<Self> {
334 (self != Self::MIN).then(|| self.wrapping_abs())
335 }
336
337 #[inline]
339 pub fn wrapping_neg(self) -> Self {
340 Self::from_parts(!self.low, !self.high).wrapping_add(i256::ONE)
341 }
342
343 #[inline]
345 pub fn checked_neg(self) -> Option<Self> {
346 (self != Self::MIN).then(|| self.wrapping_neg())
347 }
348
349 #[inline]
351 pub fn wrapping_add(self, other: Self) -> Self {
352 let (low, carry) = self.low.overflowing_add(other.low);
353 let high = self.high.wrapping_add(other.high).wrapping_add(carry as _);
354 Self { low, high }
355 }
356
357 #[inline]
359 pub fn checked_add(self, other: Self) -> Option<Self> {
360 let r = self.wrapping_add(other);
361 ((other.is_negative() && r < self) || (!other.is_negative() && r >= self)).then_some(r)
362 }
363
364 #[inline]
366 pub fn wrapping_sub(self, other: Self) -> Self {
367 let (low, carry) = self.low.overflowing_sub(other.low);
368 let high = self.high.wrapping_sub(other.high).wrapping_sub(carry as _);
369 Self { low, high }
370 }
371
372 #[inline]
374 pub fn checked_sub(self, other: Self) -> Option<Self> {
375 let r = self.wrapping_sub(other);
376 ((other.is_negative() && r > self) || (!other.is_negative() && r <= self)).then_some(r)
377 }
378
379 #[inline]
381 pub fn wrapping_mul(self, other: Self) -> Self {
382 let (low, high) = mulx(self.low, other.low);
383
384 let hl = self.high.wrapping_mul(other.low as i128);
386 let lh = (self.low as i128).wrapping_mul(other.high);
387
388 Self {
389 low,
390 high: (high as i128).wrapping_add(hl).wrapping_add(lh),
391 }
392 }
393
394 #[inline]
396 pub fn checked_mul(self, other: Self) -> Option<Self> {
397 if self == i256::ZERO || other == i256::ZERO {
398 return Some(i256::ZERO);
399 }
400
401 let l_sa = self.high >> 127;
403 let r_sa = other.high >> 127;
404 let out_sa = (l_sa ^ r_sa) as u128;
405
406 let l_abs = self.wrapping_abs();
408 let r_abs = other.wrapping_abs();
409
410 if l_abs.high != 0 && r_abs.high != 0 {
412 return None;
413 }
414
415 let (low, high) = mulx(l_abs.low, r_abs.low);
417
418 let hl = (l_abs.high as u128).checked_mul(r_abs.low)?;
420 let lh = l_abs.low.checked_mul(r_abs.high as u128)?;
421
422 let high = high.checked_add(hl)?.checked_add(lh)?;
423
424 let (low, c) = (low ^ out_sa).overflowing_sub(out_sa);
426 let high = (high ^ out_sa).wrapping_sub(out_sa).wrapping_sub(c as u128) as i128;
427
428 (high.is_negative() == (self.is_negative() ^ other.is_negative()))
430 .then_some(Self { low, high })
431 }
432
433 #[inline]
436 fn div_rem(self, other: Self) -> Result<(Self, Self), DivRemError> {
437 if other == Self::ZERO {
438 return Err(DivRemError::DivideByZero);
439 }
440 if other == Self::MINUS_ONE && self == Self::MIN {
441 return Err(DivRemError::DivideOverflow);
442 }
443
444 let a = self.wrapping_abs();
445 let b = other.wrapping_abs();
446
447 let (div, rem) = div_rem(&a.as_digits(), &b.as_digits());
448 let div = Self::from_digits(div);
449 let rem = Self::from_digits(rem);
450
451 Ok((
452 if self.is_negative() == other.is_negative() {
453 div
454 } else {
455 div.wrapping_neg()
456 },
457 if self.is_negative() {
458 rem.wrapping_neg()
459 } else {
460 rem
461 },
462 ))
463 }
464
465 fn as_digits(self) -> [u64; 4] {
467 [
468 self.low as u64,
469 (self.low >> 64) as u64,
470 self.high as u64,
471 (self.high as u128 >> 64) as u64,
472 ]
473 }
474
475 fn from_digits(digits: [u64; 4]) -> Self {
477 Self::from_parts(
478 digits[0] as u128 | ((digits[1] as u128) << 64),
479 digits[2] as i128 | ((digits[3] as i128) << 64),
480 )
481 }
482
483 #[inline]
485 pub fn wrapping_div(self, other: Self) -> Self {
486 match self.div_rem(other) {
487 Ok((v, _)) => v,
488 Err(DivRemError::DivideByZero) => panic!("attempt to divide by zero"),
489 Err(_) => Self::MIN,
490 }
491 }
492
493 #[inline]
495 pub fn checked_div(self, other: Self) -> Option<Self> {
496 self.div_rem(other).map(|(v, _)| v).ok()
497 }
498
499 #[inline]
501 pub fn wrapping_rem(self, other: Self) -> Self {
502 match self.div_rem(other) {
503 Ok((_, v)) => v,
504 Err(DivRemError::DivideByZero) => panic!("attempt to divide by zero"),
505 Err(_) => Self::ZERO,
506 }
507 }
508
509 #[inline]
511 pub fn checked_rem(self, other: Self) -> Option<Self> {
512 self.div_rem(other).map(|(_, v)| v).ok()
513 }
514
515 #[inline]
517 pub fn checked_pow(self, mut exp: u32) -> Option<Self> {
518 if exp == 0 {
519 return Some(i256::from_i128(1));
520 }
521
522 let mut base = self;
523 let mut acc: Self = i256::from_i128(1);
524
525 while exp > 1 {
526 if (exp & 1) == 1 {
527 acc = acc.checked_mul(base)?;
528 }
529 exp /= 2;
530 base = base.checked_mul(base)?;
531 }
532 acc.checked_mul(base)
537 }
538
539 #[inline]
541 pub fn wrapping_pow(self, mut exp: u32) -> Self {
542 if exp == 0 {
543 return i256::from_i128(1);
544 }
545
546 let mut base = self;
547 let mut acc: Self = i256::from_i128(1);
548
549 while exp > 1 {
550 if (exp & 1) == 1 {
551 acc = acc.wrapping_mul(base);
552 }
553 exp /= 2;
554 base = base.wrapping_mul(base);
555 }
556
557 acc.wrapping_mul(base)
562 }
563
564 pub const fn signum(self) -> Self {
570 if self.is_positive() {
571 i256::ONE
572 } else if self.is_negative() {
573 i256::MINUS_ONE
574 } else {
575 i256::ZERO
576 }
577 }
578
579 #[inline]
581 pub const fn is_negative(self) -> bool {
582 self.high.is_negative()
583 }
584
585 pub const fn is_positive(self) -> bool {
587 self.high.is_positive() || self.high == 0 && self.low != 0
588 }
589}
590
591const fn split_array<const N: usize, const M: usize>(vals: [u8; N]) -> ([u8; M], [u8; M]) {
594 let mut a = [0; M];
595 let mut b = [0; M];
596 let mut i = 0;
597 while i != M {
598 a[i] = vals[i];
599 b[i] = vals[i + M];
600 i += 1;
601 }
602 (a, b)
603}
604
605#[inline]
611fn mulx(a: u128, b: u128) -> (u128, u128) {
612 let split = |a: u128| (a & (u64::MAX as u128), a >> 64);
613
614 const MASK: u128 = u64::MAX as _;
615
616 let (a_low, a_high) = split(a);
617 let (b_low, b_high) = split(b);
618
619 let (mut low, mut carry) = split(a_low * b_low);
621 carry += a_high * b_low;
622
623 low += carry << 64;
625 let mut high = carry >> 64;
626
627 carry = low >> 64;
629 low &= MASK;
630
631 carry += b_high * a_low;
633
634 low += carry << 64;
636 high += carry >> 64;
637
638 high += a_high * b_high;
640
641 (low, high)
642}
643
644derive_arith!(
645 i256,
646 Add,
647 AddAssign,
648 add,
649 add_assign,
650 wrapping_add,
651 checked_add
652);
653derive_arith!(
654 i256,
655 Sub,
656 SubAssign,
657 sub,
658 sub_assign,
659 wrapping_sub,
660 checked_sub
661);
662derive_arith!(
663 i256,
664 Mul,
665 MulAssign,
666 mul,
667 mul_assign,
668 wrapping_mul,
669 checked_mul
670);
671derive_arith!(
672 i256,
673 Div,
674 DivAssign,
675 div,
676 div_assign,
677 wrapping_div,
678 checked_div
679);
680derive_arith!(
681 i256,
682 Rem,
683 RemAssign,
684 rem,
685 rem_assign,
686 wrapping_rem,
687 checked_rem
688);
689
690impl Neg for i256 {
691 type Output = i256;
692
693 #[cfg(debug_assertions)]
694 fn neg(self) -> Self::Output {
695 self.checked_neg().expect("i256 overflow")
696 }
697
698 #[cfg(not(debug_assertions))]
699 fn neg(self) -> Self::Output {
700 self.wrapping_neg()
701 }
702}
703
704impl BitAnd for i256 {
705 type Output = i256;
706
707 #[inline]
708 fn bitand(self, rhs: Self) -> Self::Output {
709 Self {
710 low: self.low & rhs.low,
711 high: self.high & rhs.high,
712 }
713 }
714}
715
716impl BitOr for i256 {
717 type Output = i256;
718
719 #[inline]
720 fn bitor(self, rhs: Self) -> Self::Output {
721 Self {
722 low: self.low | rhs.low,
723 high: self.high | rhs.high,
724 }
725 }
726}
727
728impl BitXor for i256 {
729 type Output = i256;
730
731 #[inline]
732 fn bitxor(self, rhs: Self) -> Self::Output {
733 Self {
734 low: self.low ^ rhs.low,
735 high: self.high ^ rhs.high,
736 }
737 }
738}
739
740impl Shl<u8> for i256 {
741 type Output = i256;
742
743 #[inline]
744 fn shl(self, rhs: u8) -> Self::Output {
745 if rhs == 0 {
746 self
747 } else if rhs < 128 {
748 Self {
749 high: (self.high << rhs) | (self.low >> (128 - rhs)) as i128,
750 low: self.low << rhs,
751 }
752 } else {
753 Self {
754 high: (self.low << (rhs - 128)) as i128,
755 low: 0,
756 }
757 }
758 }
759}
760
761impl Shr<u8> for i256 {
762 type Output = i256;
763
764 #[inline]
765 fn shr(self, rhs: u8) -> Self::Output {
766 if rhs == 0 {
767 self
768 } else if rhs < 128 {
769 Self {
770 high: self.high >> rhs,
771 low: (self.low >> rhs) | ((self.high as u128) << (128 - rhs)),
772 }
773 } else {
774 Self {
775 high: self.high >> 127,
776 low: (self.high >> (rhs - 128)) as u128,
777 }
778 }
779 }
780}
781
782macro_rules! define_as_primitive {
783 ($native_ty:ty) => {
784 impl AsPrimitive<i256> for $native_ty {
785 fn as_(self) -> i256 {
786 i256::from_i128(self as i128)
787 }
788 }
789 };
790}
791
792define_as_primitive!(i8);
793define_as_primitive!(i16);
794define_as_primitive!(i32);
795define_as_primitive!(i64);
796define_as_primitive!(u8);
797define_as_primitive!(u16);
798define_as_primitive!(u32);
799define_as_primitive!(u64);
800
801impl ToPrimitive for i256 {
802 fn to_i64(&self) -> Option<i64> {
803 let as_i128 = self.low as i128;
804
805 let high_negative = self.high < 0;
806 let low_negative = as_i128 < 0;
807 let high_valid = self.high == -1 || self.high == 0;
808
809 if high_negative == low_negative && high_valid {
810 let (low_bytes, high_bytes) = split_array(u128::to_le_bytes(self.low));
811 let high = i64::from_le_bytes(high_bytes);
812 let low = i64::from_le_bytes(low_bytes);
813
814 let high_negative = high < 0;
815 let low_negative = low < 0;
816 let high_valid = self.high == -1 || self.high == 0;
817
818 (high_negative == low_negative && high_valid).then_some(low)
819 } else {
820 None
821 }
822 }
823
824 fn to_f64(&self) -> Option<f64> {
825 let mag = if let Some(u) = self.checked_abs() {
826 let (low, high) = u.to_parts();
827 (high as f64) * 2_f64.powi(128) + (low as f64)
828 } else {
829 2_f64.powi(255)
831 };
832 if *self < i256::ZERO {
833 Some(-mag)
834 } else {
835 Some(mag)
836 }
837 }
838 fn to_u64(&self) -> Option<u64> {
839 let as_i128 = self.low as i128;
840
841 let high_negative = self.high < 0;
842 let low_negative = as_i128 < 0;
843 let high_valid = self.high == -1 || self.high == 0;
844
845 if high_negative == low_negative && high_valid {
846 self.low.to_u64()
847 } else {
848 None
849 }
850 }
851}
852
853#[cfg(all(test, not(miri)))] mod tests {
855 use super::*;
856 use num::Signed;
857 use rand::{rng, Rng};
858
859 #[test]
860 fn test_signed_cmp() {
861 let a = i256::from_parts(i128::MAX as u128, 12);
862 let b = i256::from_parts(i128::MIN as u128, 12);
863 assert!(a < b);
864
865 let a = i256::from_parts(i128::MAX as u128, 12);
866 let b = i256::from_parts(i128::MIN as u128, -12);
867 assert!(a > b);
868 }
869
870 #[test]
871 fn test_to_i128() {
872 let vals = [
873 BigInt::from_i128(-1).unwrap(),
874 BigInt::from_i128(i128::MAX).unwrap(),
875 BigInt::from_i128(i128::MIN).unwrap(),
876 BigInt::from_u128(u128::MIN).unwrap(),
877 BigInt::from_u128(u128::MAX).unwrap(),
878 ];
879
880 for v in vals {
881 let (t, overflow) = i256::from_bigint_with_overflow(v.clone());
882 assert!(!overflow);
883 assert_eq!(t.to_i128(), v.to_i128(), "{v} vs {t}");
884 }
885 }
886
887 fn test_ops(il: i256, ir: i256) {
889 let bl = BigInt::from_signed_bytes_le(&il.to_le_bytes());
890 let br = BigInt::from_signed_bytes_le(&ir.to_le_bytes());
891
892 assert_eq!(il.cmp(&ir), bl.cmp(&br), "{bl} cmp {br}");
894
895 assert_eq!(i256::from_le_bytes(il.to_le_bytes()), il);
897 assert_eq!(i256::from_be_bytes(il.to_be_bytes()), il);
898 assert_eq!(i256::from_le_bytes(ir.to_le_bytes()), ir);
899 assert_eq!(i256::from_be_bytes(ir.to_be_bytes()), ir);
900
901 assert_eq!(il.to_i128(), bl.to_i128(), "{bl}");
903 assert_eq!(ir.to_i128(), br.to_i128(), "{br}");
904
905 let (abs, overflow) = i256::from_bigint_with_overflow(bl.abs());
907 assert_eq!(il.wrapping_abs(), abs);
908 assert_eq!(il.checked_abs().is_none(), overflow);
909
910 let (abs, overflow) = i256::from_bigint_with_overflow(br.abs());
911 assert_eq!(ir.wrapping_abs(), abs);
912 assert_eq!(ir.checked_abs().is_none(), overflow);
913
914 let (neg, overflow) = i256::from_bigint_with_overflow(bl.clone().neg());
916 assert_eq!(il.wrapping_neg(), neg);
917 assert_eq!(il.checked_neg().is_none(), overflow);
918
919 let (neg, overflow) = i256::from_bigint_with_overflow(br.clone().neg());
921 assert_eq!(ir.wrapping_neg(), neg);
922 assert_eq!(ir.checked_neg().is_none(), overflow);
923
924 let actual = il.wrapping_add(ir);
926 let (expected, overflow) = i256::from_bigint_with_overflow(bl.clone() + br.clone());
927 assert_eq!(actual, expected);
928
929 let checked = il.checked_add(ir);
930 match overflow {
931 true => assert!(checked.is_none()),
932 false => assert_eq!(checked, Some(actual)),
933 }
934
935 let actual = il.wrapping_sub(ir);
937 let (expected, overflow) = i256::from_bigint_with_overflow(bl.clone() - br.clone());
938 assert_eq!(actual.to_string(), expected.to_string());
939
940 let checked = il.checked_sub(ir);
941 match overflow {
942 true => assert!(checked.is_none()),
943 false => assert_eq!(checked, Some(actual), "{bl} - {br} = {expected}"),
944 }
945
946 let actual = il.wrapping_mul(ir);
948 let (expected, overflow) = i256::from_bigint_with_overflow(bl.clone() * br.clone());
949 assert_eq!(actual.to_string(), expected.to_string());
950
951 let checked = il.checked_mul(ir);
952 match overflow {
953 true => assert!(
954 checked.is_none(),
955 "{il} * {ir} = {actual} vs {bl} * {br} = {expected}"
956 ),
957 false => assert_eq!(
958 checked,
959 Some(actual),
960 "{il} * {ir} = {actual} vs {bl} * {br} = {expected}"
961 ),
962 }
963
964 if ir != i256::ZERO {
966 let actual = il.wrapping_div(ir);
967 let expected = bl.clone() / br.clone();
968 let checked = il.checked_div(ir);
969
970 if ir == i256::MINUS_ONE && il == i256::MIN {
971 assert_eq!(actual, i256::MIN);
973 assert!(checked.is_none());
974 } else {
975 assert_eq!(actual.to_string(), expected.to_string());
976 assert_eq!(checked.unwrap().to_string(), expected.to_string());
977 }
978 } else {
979 assert!(il.checked_div(ir).is_none());
981 }
982
983 if ir != i256::ZERO {
985 let actual = il.wrapping_rem(ir);
986 let expected = bl.clone() % br.clone();
987 let checked = il.checked_rem(ir);
988
989 assert_eq!(actual.to_string(), expected.to_string(), "{il} % {ir}");
990
991 if ir == i256::MINUS_ONE && il == i256::MIN {
992 assert!(checked.is_none());
993 } else {
994 assert_eq!(checked.unwrap().to_string(), expected.to_string());
995 }
996 } else {
997 assert!(il.checked_rem(ir).is_none());
999 }
1000
1001 for exp in vec![0, 1, 2, 3, 8, 100].into_iter() {
1003 let actual = il.wrapping_pow(exp);
1004 let (expected, overflow) = i256::from_bigint_with_overflow(bl.clone().pow(exp));
1005 assert_eq!(actual.to_string(), expected.to_string());
1006
1007 let checked = il.checked_pow(exp);
1008 match overflow {
1009 true => assert!(
1010 checked.is_none(),
1011 "{il} ^ {exp} = {actual} vs {bl} * {exp} = {expected}"
1012 ),
1013 false => assert_eq!(
1014 checked,
1015 Some(actual),
1016 "{il} ^ {exp} = {actual} vs {bl} ^ {exp} = {expected}"
1017 ),
1018 }
1019 }
1020
1021 let actual = il & ir;
1023 let (expected, _) = i256::from_bigint_with_overflow(bl.clone() & br.clone());
1024 assert_eq!(actual.to_string(), expected.to_string());
1025
1026 let actual = il | ir;
1027 let (expected, _) = i256::from_bigint_with_overflow(bl.clone() | br.clone());
1028 assert_eq!(actual.to_string(), expected.to_string());
1029
1030 let actual = il ^ ir;
1031 let (expected, _) = i256::from_bigint_with_overflow(bl.clone() ^ br);
1032 assert_eq!(actual.to_string(), expected.to_string());
1033
1034 for shift in [0_u8, 1, 4, 126, 128, 129, 254, 255] {
1035 let actual = il << shift;
1036 let (expected, _) = i256::from_bigint_with_overflow(bl.clone() << shift);
1037 assert_eq!(actual.to_string(), expected.to_string());
1038
1039 let actual = il >> shift;
1040 let (expected, _) = i256::from_bigint_with_overflow(bl.clone() >> shift);
1041 assert_eq!(actual.to_string(), expected.to_string());
1042 }
1043 }
1044
1045 #[test]
1046 fn test_i256() {
1047 let candidates = [
1048 i256::ZERO,
1049 i256::ONE,
1050 i256::MINUS_ONE,
1051 i256::from_i128(2),
1052 i256::from_i128(-2),
1053 i256::from_parts(u128::MAX, 1),
1054 i256::from_parts(u128::MAX, -1),
1055 i256::from_parts(0, 1),
1056 i256::from_parts(0, -1),
1057 i256::from_parts(1, -1),
1058 i256::from_parts(1, 1),
1059 i256::from_parts(0, i128::MAX),
1060 i256::from_parts(0, i128::MIN),
1061 i256::from_parts(1, i128::MAX),
1062 i256::from_parts(1, i128::MIN),
1063 i256::from_parts(u128::MAX, i128::MIN),
1064 i256::from_parts(100, 32),
1065 i256::MIN,
1066 i256::MAX,
1067 i256::MIN >> 1,
1068 i256::MAX >> 1,
1069 i256::ONE << 127,
1070 i256::ONE << 128,
1071 i256::ONE << 129,
1072 i256::MINUS_ONE << 127,
1073 i256::MINUS_ONE << 128,
1074 i256::MINUS_ONE << 129,
1075 ];
1076
1077 for il in candidates {
1078 for ir in candidates {
1079 test_ops(il, ir)
1080 }
1081 }
1082 }
1083
1084 #[test]
1085 fn test_signed_ops() {
1086 assert_eq!(i256::from_i128(1).signum(), i256::ONE);
1088 assert_eq!(i256::from_i128(0).signum(), i256::ZERO);
1089 assert_eq!(i256::from_i128(-0).signum(), i256::ZERO);
1090 assert_eq!(i256::from_i128(-1).signum(), i256::MINUS_ONE);
1091
1092 assert!(i256::from_i128(1).is_positive());
1094 assert!(!i256::from_i128(0).is_positive());
1095 assert!(!i256::from_i128(-0).is_positive());
1096 assert!(!i256::from_i128(-1).is_positive());
1097
1098 assert!(!i256::from_i128(1).is_negative());
1100 assert!(!i256::from_i128(0).is_negative());
1101 assert!(!i256::from_i128(-0).is_negative());
1102 assert!(i256::from_i128(-1).is_negative());
1103 }
1104
1105 #[test]
1106 #[cfg_attr(miri, ignore)]
1107 fn test_i256_fuzz() {
1108 let mut rng = rng();
1109
1110 for _ in 0..1000 {
1111 let mut l = [0_u8; 32];
1112 let len = rng.random_range(0..32);
1113 l.iter_mut().take(len).for_each(|x| *x = rng.random());
1114
1115 let mut r = [0_u8; 32];
1116 let len = rng.random_range(0..32);
1117 r.iter_mut().take(len).for_each(|x| *x = rng.random());
1118
1119 test_ops(i256::from_le_bytes(l), i256::from_le_bytes(r))
1120 }
1121 }
1122
1123 #[test]
1124 fn test_i256_to_primitive() {
1125 let a = i256::MAX;
1126 assert!(a.to_i64().is_none());
1127 assert!(a.to_u64().is_none());
1128
1129 let a = i256::from_i128(i128::MAX);
1130 assert!(a.to_i64().is_none());
1131 assert!(a.to_u64().is_none());
1132
1133 let a = i256::from_i128(i64::MAX as i128);
1134 assert_eq!(a.to_i64().unwrap(), i64::MAX);
1135 assert_eq!(a.to_u64().unwrap(), i64::MAX as u64);
1136
1137 let a = i256::from_i128(i64::MAX as i128 + 1);
1138 assert!(a.to_i64().is_none());
1139 assert_eq!(a.to_u64().unwrap(), i64::MAX as u64 + 1);
1140
1141 let a = i256::MIN;
1142 assert!(a.to_i64().is_none());
1143 assert!(a.to_u64().is_none());
1144
1145 let a = i256::from_i128(i128::MIN);
1146 assert!(a.to_i64().is_none());
1147 assert!(a.to_u64().is_none());
1148
1149 let a = i256::from_i128(i64::MIN as i128);
1150 assert_eq!(a.to_i64().unwrap(), i64::MIN);
1151 assert!(a.to_u64().is_none());
1152
1153 let a = i256::from_i128(i64::MIN as i128 - 1);
1154 assert!(a.to_i64().is_none());
1155 assert!(a.to_u64().is_none());
1156 }
1157
1158 #[test]
1159 fn test_i256_as_i128() {
1160 let a = i256::from_i128(i128::MAX).wrapping_add(i256::from_i128(1));
1161 let i128 = a.as_i128();
1162 assert_eq!(i128, i128::MIN);
1163
1164 let a = i256::from_i128(i128::MAX).wrapping_add(i256::from_i128(2));
1165 let i128 = a.as_i128();
1166 assert_eq!(i128, i128::MIN + 1);
1167
1168 let a = i256::from_i128(i128::MIN).wrapping_sub(i256::from_i128(1));
1169 let i128 = a.as_i128();
1170 assert_eq!(i128, i128::MAX);
1171
1172 let a = i256::from_i128(i128::MIN).wrapping_sub(i256::from_i128(2));
1173 let i128 = a.as_i128();
1174 assert_eq!(i128, i128::MAX - 1);
1175 }
1176
1177 #[test]
1178 fn test_string_roundtrip() {
1179 let roundtrip_cases = [
1180 i256::ZERO,
1181 i256::ONE,
1182 i256::MINUS_ONE,
1183 i256::from_i128(123456789),
1184 i256::from_i128(-123456789),
1185 i256::from_i128(i128::MIN),
1186 i256::from_i128(i128::MAX),
1187 i256::MIN,
1188 i256::MAX,
1189 ];
1190 for case in roundtrip_cases {
1191 let formatted = case.to_string();
1192 let back: i256 = formatted.parse().unwrap();
1193 assert_eq!(case, back);
1194 }
1195 }
1196
1197 #[test]
1198 fn test_from_string() {
1199 let cases = [
1200 (
1201 "000000000000000000000000000000000000000011",
1202 Some(i256::from_i128(11)),
1203 ),
1204 (
1205 "-000000000000000000000000000000000000000011",
1206 Some(i256::from_i128(-11)),
1207 ),
1208 (
1209 "-0000000000000000000000000000000000000000123456789",
1210 Some(i256::from_i128(-123456789)),
1211 ),
1212 ("-", None),
1213 ("+", None),
1214 ("--1", None),
1215 ("-+1", None),
1216 ("000000000000000000000000000000000000000", Some(i256::ZERO)),
1217 ("0000000000000000000000000000000000000000-11", None),
1218 ("11-1111111111111111111111111111111111111", None),
1219 (
1220 "115792089237316195423570985008687907853269984665640564039457584007913129639936",
1221 None,
1222 ),
1223 ];
1224 for (case, expected) in cases {
1225 assert_eq!(i256::from_string(case), expected)
1226 }
1227 }
1228
1229 #[allow(clippy::op_ref)]
1230 fn test_reference_op(il: i256, ir: i256) {
1231 let r1 = il + ir;
1232 let r2 = &il + ir;
1233 let r3 = il + &ir;
1234 let r4 = &il + &ir;
1235 assert_eq!(r1, r2);
1236 assert_eq!(r1, r3);
1237 assert_eq!(r1, r4);
1238
1239 let r1 = il - ir;
1240 let r2 = &il - ir;
1241 let r3 = il - &ir;
1242 let r4 = &il - &ir;
1243 assert_eq!(r1, r2);
1244 assert_eq!(r1, r3);
1245 assert_eq!(r1, r4);
1246
1247 let r1 = il * ir;
1248 let r2 = &il * ir;
1249 let r3 = il * &ir;
1250 let r4 = &il * &ir;
1251 assert_eq!(r1, r2);
1252 assert_eq!(r1, r3);
1253 assert_eq!(r1, r4);
1254
1255 let r1 = il / ir;
1256 let r2 = &il / ir;
1257 let r3 = il / &ir;
1258 let r4 = &il / &ir;
1259 assert_eq!(r1, r2);
1260 assert_eq!(r1, r3);
1261 assert_eq!(r1, r4);
1262 }
1263
1264 #[test]
1265 fn test_i256_reference_op() {
1266 let candidates = [
1267 i256::ONE,
1268 i256::MINUS_ONE,
1269 i256::from_i128(2),
1270 i256::from_i128(-2),
1271 i256::from_i128(3),
1272 i256::from_i128(-3),
1273 ];
1274
1275 for il in candidates {
1276 for ir in candidates {
1277 test_reference_op(il, ir)
1278 }
1279 }
1280 }
1281
1282 #[test]
1283 fn test_decimal256_to_f64_typical_values() {
1284 let v = i256::from_i128(42_i128);
1285 assert_eq!(v.to_f64().unwrap(), 42.0);
1286
1287 let v = i256::from_i128(-123456789012345678i128);
1288 assert_eq!(v.to_f64().unwrap(), -123456789012345678.0);
1289 }
1290
1291 #[test]
1292 fn test_decimal256_to_f64_large_positive_value() {
1293 let max_f = f64::MAX;
1294 let big = i256::from_f64(max_f * 2.0).unwrap_or(i256::MAX);
1295 let out = big.to_f64().unwrap();
1296 assert!(out.is_finite() && out.is_sign_positive());
1297 }
1298
1299 #[test]
1300 fn test_decimal256_to_f64_large_negative_value() {
1301 let max_f = f64::MAX;
1302 let big_neg = i256::from_f64(-(max_f * 2.0)).unwrap_or(i256::MIN);
1303 let out = big_neg.to_f64().unwrap();
1304 assert!(out.is_finite() && out.is_sign_negative());
1305 }
1306}