1use crate::arith::derive_arith;
19use crate::bigint::div::div_rem;
20use num_bigint::BigInt;
21use num_traits::{
22 Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedSub, FromPrimitive,
23 Num, One, Signed, ToPrimitive, WrappingAdd, WrappingMul, WrappingNeg, WrappingShl, WrappingShr,
24 WrappingSub, Zero, cast::AsPrimitive,
25};
26use std::cmp::Ordering;
27use std::num::ParseIntError;
28use std::ops::{BitAnd, BitOr, BitXor, Neg, Shl, Shr};
29use std::str::FromStr;
30
31mod div;
32
33#[derive(Debug)]
35pub struct ParseI256Error {}
36
37impl From<ParseIntError> for ParseI256Error {
38 fn from(_: ParseIntError) -> Self {
39 Self {}
40 }
41}
42
43impl std::fmt::Display for ParseI256Error {
44 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45 write!(f, "Failed to parse as i256")
46 }
47}
48impl std::error::Error for ParseI256Error {}
49
50enum DivRemError {
52 DivideByZero,
54 DivideOverflow,
56}
57
58#[allow(non_camel_case_types)]
60#[derive(Copy, Clone, Default, Eq, PartialEq, Hash)]
61#[repr(C)]
62pub struct i256 {
63 low: u128,
64 high: i128,
65}
66
67impl std::fmt::Debug for i256 {
68 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69 write!(f, "{self}")
70 }
71}
72
73impl std::fmt::Display for i256 {
74 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75 write!(f, "{}", BigInt::from_signed_bytes_le(&self.to_le_bytes()))
76 }
77}
78
79impl FromStr for i256 {
80 type Err = ParseI256Error;
81
82 fn from_str(s: &str) -> Result<Self, Self::Err> {
83 if s.len() <= 38 {
85 return Ok(Self::from_i128(i128::from_str(s)?));
86 }
87
88 let (negative, s) = match s.as_bytes()[0] {
89 b'-' => (true, &s[1..]),
90 b'+' => (false, &s[1..]),
91 _ => (false, s),
92 };
93
94 let s = s.trim_start_matches('0');
96 if s.is_empty() {
97 return Ok(i256::ZERO);
98 }
99
100 if !s.as_bytes()[0].is_ascii_digit() {
101 return Err(ParseI256Error {});
103 }
104
105 parse_impl(s, negative)
106 }
107}
108
109impl From<i8> for i256 {
110 fn from(value: i8) -> Self {
111 Self::from_i128(value.into())
112 }
113}
114
115impl From<i16> for i256 {
116 fn from(value: i16) -> Self {
117 Self::from_i128(value.into())
118 }
119}
120
121impl From<i32> for i256 {
122 fn from(value: i32) -> Self {
123 Self::from_i128(value.into())
124 }
125}
126
127impl From<i64> for i256 {
128 fn from(value: i64) -> Self {
129 Self::from_i128(value.into())
130 }
131}
132
133fn parse_impl(s: &str, negative: bool) -> Result<i256, ParseI256Error> {
135 if s.len() <= 38 {
136 let low = i128::from_str(s)?;
137 return Ok(match negative {
138 true => i256::from_parts(low.neg() as _, -1),
139 false => i256::from_parts(low as _, 0),
140 });
141 }
142
143 let split = s.len() - 38;
144 if !s.as_bytes()[split].is_ascii_digit() {
145 return Err(ParseI256Error {});
147 }
148 let (hs, ls) = s.split_at(split);
149
150 let mut low = i128::from_str(ls)?;
151 let high = parse_impl(hs, negative)?;
152
153 if negative {
154 low = -low;
155 }
156
157 let low = i256::from_i128(low);
158
159 high.checked_mul(i256::from_i128(10_i128.pow(38)))
160 .and_then(|high| high.checked_add(low))
161 .ok_or(ParseI256Error {})
162}
163
164impl PartialOrd for i256 {
165 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
166 Some(self.cmp(other))
167 }
168}
169
170impl Ord for i256 {
171 fn cmp(&self, other: &Self) -> Ordering {
172 self.high.cmp(&other.high).then(self.low.cmp(&other.low))
175 }
176}
177
178impl i256 {
179 pub const ZERO: Self = i256 { low: 0, high: 0 };
181
182 pub const ONE: Self = i256 { low: 1, high: 0 };
184
185 pub const MINUS_ONE: Self = i256 {
187 low: u128::MAX,
188 high: -1,
189 };
190
191 pub const MAX: Self = i256 {
193 low: u128::MAX,
194 high: i128::MAX,
195 };
196
197 pub const MIN: Self = i256 {
199 low: u128::MIN,
200 high: i128::MIN,
201 };
202
203 #[inline]
205 pub const fn from_le_bytes(b: [u8; 32]) -> Self {
206 let (low, high) = split_array(b);
207 Self {
208 high: i128::from_le_bytes(high),
209 low: u128::from_le_bytes(low),
210 }
211 }
212
213 #[inline]
215 pub const fn from_be_bytes(b: [u8; 32]) -> Self {
216 let (high, low) = split_array(b);
217 Self {
218 high: i128::from_be_bytes(high),
219 low: u128::from_be_bytes(low),
220 }
221 }
222
223 pub const fn from_i128(v: i128) -> Self {
225 Self::from_parts(v as u128, v >> 127)
226 }
227
228 #[inline]
230 pub fn from_string(value_str: &str) -> Option<Self> {
231 value_str.parse().ok()
232 }
233
234 pub fn from_f64(v: f64) -> Option<Self> {
237 BigInt::from_f64(v).and_then(|i| {
238 let (integer, overflow) = i256::from_bigint_with_overflow(i);
239 if overflow { None } else { Some(integer) }
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_traits::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 pub const fn leading_zeros(&self) -> u32 {
592 match self.high {
593 0 => u128::BITS + self.low.leading_zeros(),
594 _ => self.high.leading_zeros(),
595 }
596 }
597
598 pub const fn trailing_zeros(&self) -> u32 {
600 match self.low {
601 0 => u128::BITS + self.high.trailing_zeros(),
602 _ => self.low.trailing_zeros(),
603 }
604 }
605
606 fn redundant_leading_sign_bits_i256(n: i256) -> u8 {
607 let mask = n >> 255; ((n ^ mask).leading_zeros() - 1) as u8 }
610
611 fn i256_to_f64(input: i256) -> f64 {
612 let k = i256::redundant_leading_sign_bits_i256(input);
613 let n = input << k; let n = (n.high >> 64) as i64; (n as f64) * f64::powi(2.0, 192 - (k as i32)) }
617
618 #[inline]
621 pub fn checked_ilog(self, base: i256) -> Option<u32> {
622 if base == Self::from(10) {
623 return self.checked_ilog10();
625 }
626
627 if self <= Self::ZERO {
628 return None;
629 }
630 if base <= Self::ONE {
631 return None;
632 }
633 if self < base {
634 return Some(0);
635 }
636
637 let mut val = 1;
638 let mut base_exp = base;
639
640 let boundary = self.checked_div(base)?;
641 while base_exp <= boundary {
642 val += 1;
643 base_exp = base_exp.checked_mul(base)?;
644 }
645 Some(val)
646 }
647
648 #[inline]
651 pub fn ilog(self, base: i256) -> u32 {
652 self.checked_ilog(base)
653 .unwrap_or_else(|| panic!("ilog overflow with {self} and base {base}"))
654 }
655
656 #[inline]
659 pub fn checked_ilog10(self) -> Option<u32> {
660 if self <= Self::ZERO {
661 return None;
662 }
663 if self < Self::from(10) {
664 return Some(0);
665 }
666
667 let pow_64: i256 = i256::from(10).checked_pow(64).unwrap();
670 let pow_32: i256 = i256::from(10).checked_pow(32).unwrap();
671 if self >= pow_64 {
672 let value = self.checked_div(pow_64)?;
673 debug_assert!(value.high == 0);
677 Some(64 + value.low.checked_ilog10()?)
678 } else if self >= pow_32 {
679 let value = self.checked_div(pow_32)?;
680 debug_assert!(value.high == 0);
684 Some(32 + value.low.checked_ilog10()?)
685 } else {
686 self.low.checked_ilog10()
688 }
689 }
690
691 #[inline]
694 pub fn ilog10(self) -> u32 {
695 self.checked_ilog10()
696 .unwrap_or_else(|| panic!("ilog10 overflow with {self}"))
697 }
698
699 #[inline]
702 pub fn checked_ilog2(self) -> Option<u32> {
703 self.checked_ilog(i256::from(2))
704 }
705
706 #[inline]
708 pub fn ilog2(self) -> u32 {
709 self.checked_ilog2()
710 .unwrap_or_else(|| panic!("ilog2 overflow with {self}"))
711 }
712}
713
714const fn split_array<const N: usize, const M: usize>(vals: [u8; N]) -> ([u8; M], [u8; M]) {
717 let mut a = [0; M];
718 let mut b = [0; M];
719 let mut i = 0;
720 while i != M {
721 a[i] = vals[i];
722 b[i] = vals[i + M];
723 i += 1;
724 }
725 (a, b)
726}
727
728#[inline]
734fn mulx(a: u128, b: u128) -> (u128, u128) {
735 let split = |a: u128| (a & (u64::MAX as u128), a >> 64);
736
737 const MASK: u128 = u64::MAX as _;
738
739 let (a_low, a_high) = split(a);
740 let (b_low, b_high) = split(b);
741
742 let (mut low, mut carry) = split(a_low * b_low);
744 carry += a_high * b_low;
745
746 low += carry << 64;
748 let mut high = carry >> 64;
749
750 carry = low >> 64;
752 low &= MASK;
753
754 carry += b_high * a_low;
756
757 low += carry << 64;
759 high += carry >> 64;
760
761 high += a_high * b_high;
763
764 (low, high)
765}
766
767derive_arith!(
768 i256,
769 Add,
770 AddAssign,
771 add,
772 add_assign,
773 wrapping_add,
774 checked_add
775);
776derive_arith!(
777 i256,
778 Sub,
779 SubAssign,
780 sub,
781 sub_assign,
782 wrapping_sub,
783 checked_sub
784);
785derive_arith!(
786 i256,
787 Mul,
788 MulAssign,
789 mul,
790 mul_assign,
791 wrapping_mul,
792 checked_mul
793);
794derive_arith!(
795 i256,
796 Div,
797 DivAssign,
798 div,
799 div_assign,
800 wrapping_div,
801 checked_div
802);
803derive_arith!(
804 i256,
805 Rem,
806 RemAssign,
807 rem,
808 rem_assign,
809 wrapping_rem,
810 checked_rem
811);
812
813impl Neg for i256 {
814 type Output = i256;
815
816 #[cfg(debug_assertions)]
817 fn neg(self) -> Self::Output {
818 self.checked_neg().expect("i256 overflow")
819 }
820
821 #[cfg(not(debug_assertions))]
822 fn neg(self) -> Self::Output {
823 self.wrapping_neg()
824 }
825}
826
827impl BitAnd for i256 {
828 type Output = i256;
829
830 #[inline]
831 fn bitand(self, rhs: Self) -> Self::Output {
832 Self {
833 low: self.low & rhs.low,
834 high: self.high & rhs.high,
835 }
836 }
837}
838
839impl BitOr for i256 {
840 type Output = i256;
841
842 #[inline]
843 fn bitor(self, rhs: Self) -> Self::Output {
844 Self {
845 low: self.low | rhs.low,
846 high: self.high | rhs.high,
847 }
848 }
849}
850
851impl BitXor for i256 {
852 type Output = i256;
853
854 #[inline]
855 fn bitxor(self, rhs: Self) -> Self::Output {
856 Self {
857 low: self.low ^ rhs.low,
858 high: self.high ^ rhs.high,
859 }
860 }
861}
862
863impl Shl<u8> for i256 {
864 type Output = i256;
865
866 #[inline]
867 fn shl(self, rhs: u8) -> Self::Output {
868 if rhs == 0 {
869 self
870 } else if rhs < 128 {
871 Self {
872 high: (self.high << rhs) | (self.low >> (128 - rhs)) as i128,
873 low: self.low << rhs,
874 }
875 } else {
876 Self {
877 high: (self.low << (rhs - 128)) as i128,
878 low: 0,
879 }
880 }
881 }
882}
883
884impl Shr<u8> for i256 {
885 type Output = i256;
886
887 #[inline]
888 fn shr(self, rhs: u8) -> Self::Output {
889 if rhs == 0 {
890 self
891 } else if rhs < 128 {
892 Self {
893 high: self.high >> rhs,
894 low: (self.low >> rhs) | ((self.high as u128) << (128 - rhs)),
895 }
896 } else {
897 Self {
898 high: self.high >> 127,
899 low: (self.high >> (rhs - 128)) as u128,
900 }
901 }
902 }
903}
904
905impl WrappingShl for i256 {
906 #[inline]
907 fn wrapping_shl(&self, rhs: u32) -> i256 {
908 (*self).shl(rhs as u8)
910 }
911}
912
913impl WrappingShr for i256 {
914 #[inline]
915 fn wrapping_shr(&self, rhs: u32) -> i256 {
916 (*self).shr(rhs as u8)
918 }
919}
920
921macro_rules! define_standard_shift {
924 ($trait_name:ident, $method:ident, [$($t:ty),+]) => {
926 $(define_standard_shift!($trait_name, $method, $t);)+
927 };
928 ($trait_name:ident, $method:ident, $t:ty) => {
930 impl $trait_name<$t> for i256 {
931 type Output = i256;
932
933 #[inline]
934 fn $method(self, rhs: $t) -> Self::Output {
935 let rhs = u8::try_from(rhs).expect("rhs overflow for shift");
936 self.$method(rhs)
938 }
939 }
940 };
941}
942
943define_standard_shift!(
944 Shl,
945 shl,
946 [u16, u32, u64, u128, usize, i16, i32, i64, i128, isize]
947);
948define_standard_shift!(
949 Shr,
950 shr,
951 [u16, u32, u64, u128, usize, i16, i32, i64, i128, isize]
952);
953
954macro_rules! define_as_primitive {
955 ($native_ty:ty) => {
956 impl AsPrimitive<i256> for $native_ty {
957 fn as_(self) -> i256 {
958 i256::from_i128(self as i128)
959 }
960 }
961 };
962}
963
964define_as_primitive!(i8);
965define_as_primitive!(i16);
966define_as_primitive!(i32);
967define_as_primitive!(i64);
968define_as_primitive!(u8);
969define_as_primitive!(u16);
970define_as_primitive!(u32);
971define_as_primitive!(u64);
972
973impl ToPrimitive for i256 {
974 fn to_i64(&self) -> Option<i64> {
975 let as_i128 = self.low as i128;
976
977 let high_negative = self.high < 0;
978 let low_negative = as_i128 < 0;
979 let high_valid = self.high == -1 || self.high == 0;
980
981 if high_negative == low_negative && high_valid {
982 let (low_bytes, high_bytes) = split_array(u128::to_le_bytes(self.low));
983 let high = i64::from_le_bytes(high_bytes);
984 let low = i64::from_le_bytes(low_bytes);
985
986 let high_negative = high < 0;
987 let low_negative = low < 0;
988 let high_valid = self.high == -1 || self.high == 0;
989
990 (high_negative == low_negative && high_valid).then_some(low)
991 } else {
992 None
993 }
994 }
995
996 fn to_f64(&self) -> Option<f64> {
997 match *self {
998 Self::MIN => Some(-2_f64.powi(255)),
999 Self::ZERO => Some(0f64),
1000 Self::ONE => Some(1f64),
1001 n => Some(Self::i256_to_f64(n)),
1002 }
1003 }
1004
1005 fn to_u64(&self) -> Option<u64> {
1006 let as_i128 = self.low as i128;
1007
1008 let high_negative = self.high < 0;
1009 let low_negative = as_i128 < 0;
1010 let high_valid = self.high == -1 || self.high == 0;
1011
1012 if high_negative == low_negative && high_valid {
1013 self.low.to_u64()
1014 } else {
1015 None
1016 }
1017 }
1018}
1019
1020impl CheckedNeg for i256 {
1023 fn checked_neg(&self) -> Option<Self> {
1024 (*self).checked_neg()
1025 }
1026}
1027
1028impl CheckedAdd for i256 {
1029 fn checked_add(&self, v: &i256) -> Option<Self> {
1030 (*self).checked_add(*v)
1031 }
1032}
1033
1034impl CheckedSub for i256 {
1035 fn checked_sub(&self, v: &i256) -> Option<Self> {
1036 (*self).checked_sub(*v)
1037 }
1038}
1039
1040impl CheckedDiv for i256 {
1041 fn checked_div(&self, v: &i256) -> Option<Self> {
1042 (*self).checked_div(*v)
1043 }
1044}
1045
1046impl CheckedMul for i256 {
1047 fn checked_mul(&self, v: &i256) -> Option<Self> {
1048 (*self).checked_mul(*v)
1049 }
1050}
1051
1052impl CheckedRem for i256 {
1053 fn checked_rem(&self, v: &i256) -> Option<Self> {
1054 (*self).checked_rem(*v)
1055 }
1056}
1057
1058impl WrappingAdd for i256 {
1059 fn wrapping_add(&self, v: &Self) -> Self {
1060 (*self).wrapping_add(*v)
1061 }
1062}
1063
1064impl WrappingSub for i256 {
1065 fn wrapping_sub(&self, v: &Self) -> Self {
1066 (*self).wrapping_sub(*v)
1067 }
1068}
1069
1070impl WrappingMul for i256 {
1071 fn wrapping_mul(&self, v: &Self) -> Self {
1072 (*self).wrapping_mul(*v)
1073 }
1074}
1075
1076impl WrappingNeg for i256 {
1077 fn wrapping_neg(&self) -> Self {
1078 (*self).wrapping_neg()
1079 }
1080}
1081
1082impl Zero for i256 {
1083 fn zero() -> Self {
1084 i256::ZERO
1085 }
1086
1087 fn is_zero(&self) -> bool {
1088 *self == i256::ZERO
1089 }
1090}
1091
1092impl One for i256 {
1093 fn one() -> Self {
1094 i256::ONE
1095 }
1096
1097 fn is_one(&self) -> bool {
1098 *self == i256::ONE
1099 }
1100}
1101
1102impl Num for i256 {
1103 type FromStrRadixErr = ParseI256Error;
1104
1105 fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
1106 if radix == 10 {
1107 str.parse()
1108 } else {
1109 Err(ParseI256Error {})
1111 }
1112 }
1113}
1114
1115impl Signed for i256 {
1116 fn abs(&self) -> Self {
1117 self.wrapping_abs()
1118 }
1119
1120 fn abs_sub(&self, other: &Self) -> Self {
1121 if self > other {
1122 self.wrapping_sub(other)
1123 } else {
1124 i256::ZERO
1125 }
1126 }
1127
1128 fn signum(&self) -> Self {
1129 (*self).signum()
1130 }
1131
1132 fn is_positive(&self) -> bool {
1133 (*self).is_positive()
1134 }
1135
1136 fn is_negative(&self) -> bool {
1137 (*self).is_negative()
1138 }
1139}
1140
1141impl Bounded for i256 {
1142 fn min_value() -> Self {
1143 i256::MIN
1144 }
1145
1146 fn max_value() -> Self {
1147 i256::MAX
1148 }
1149}
1150
1151#[cfg(all(test, not(miri)))] mod tests {
1153 use super::*;
1154 use num_traits::Signed;
1155 use rand::{Rng, rng};
1156
1157 #[test]
1158 fn test_signed_cmp() {
1159 let a = i256::from_parts(i128::MAX as u128, 12);
1160 let b = i256::from_parts(i128::MIN as u128, 12);
1161 assert!(a < b);
1162
1163 let a = i256::from_parts(i128::MAX as u128, 12);
1164 let b = i256::from_parts(i128::MIN as u128, -12);
1165 assert!(a > b);
1166 }
1167
1168 #[test]
1169 fn test_to_i128() {
1170 let vals = [
1171 BigInt::from_i128(-1).unwrap(),
1172 BigInt::from_i128(i128::MAX).unwrap(),
1173 BigInt::from_i128(i128::MIN).unwrap(),
1174 BigInt::from_u128(u128::MIN).unwrap(),
1175 BigInt::from_u128(u128::MAX).unwrap(),
1176 ];
1177
1178 for v in vals {
1179 let (t, overflow) = i256::from_bigint_with_overflow(v.clone());
1180 assert!(!overflow);
1181 assert_eq!(t.to_i128(), v.to_i128(), "{v} vs {t}");
1182 }
1183 }
1184
1185 fn test_ops(il: i256, ir: i256) {
1187 let bl = BigInt::from_signed_bytes_le(&il.to_le_bytes());
1188 let br = BigInt::from_signed_bytes_le(&ir.to_le_bytes());
1189
1190 assert_eq!(il.cmp(&ir), bl.cmp(&br), "{bl} cmp {br}");
1192
1193 assert_eq!(i256::from_le_bytes(il.to_le_bytes()), il);
1195 assert_eq!(i256::from_be_bytes(il.to_be_bytes()), il);
1196 assert_eq!(i256::from_le_bytes(ir.to_le_bytes()), ir);
1197 assert_eq!(i256::from_be_bytes(ir.to_be_bytes()), ir);
1198
1199 assert_eq!(il.to_i128(), bl.to_i128(), "{bl}");
1201 assert_eq!(ir.to_i128(), br.to_i128(), "{br}");
1202
1203 let (abs, overflow) = i256::from_bigint_with_overflow(bl.abs());
1205 assert_eq!(il.wrapping_abs(), abs);
1206 assert_eq!(il.checked_abs().is_none(), overflow);
1207
1208 let (abs, overflow) = i256::from_bigint_with_overflow(br.abs());
1209 assert_eq!(ir.wrapping_abs(), abs);
1210 assert_eq!(ir.checked_abs().is_none(), overflow);
1211
1212 let (neg, overflow) = i256::from_bigint_with_overflow(bl.clone().neg());
1214 assert_eq!(il.wrapping_neg(), neg);
1215 assert_eq!(il.checked_neg().is_none(), overflow);
1216
1217 let (neg, overflow) = i256::from_bigint_with_overflow(br.clone().neg());
1219 assert_eq!(ir.wrapping_neg(), neg);
1220 assert_eq!(ir.checked_neg().is_none(), overflow);
1221
1222 let actual = il.wrapping_add(ir);
1224 let (expected, overflow) = i256::from_bigint_with_overflow(bl.clone() + br.clone());
1225 assert_eq!(actual, expected);
1226
1227 let checked = il.checked_add(ir);
1228 match overflow {
1229 true => assert!(checked.is_none()),
1230 false => assert_eq!(checked, Some(actual)),
1231 }
1232
1233 let actual = il.wrapping_sub(ir);
1235 let (expected, overflow) = i256::from_bigint_with_overflow(bl.clone() - br.clone());
1236 assert_eq!(actual.to_string(), expected.to_string());
1237
1238 let checked = il.checked_sub(ir);
1239 match overflow {
1240 true => assert!(checked.is_none()),
1241 false => assert_eq!(checked, Some(actual), "{bl} - {br} = {expected}"),
1242 }
1243
1244 let actual = il.wrapping_mul(ir);
1246 let (expected, overflow) = i256::from_bigint_with_overflow(bl.clone() * br.clone());
1247 assert_eq!(actual.to_string(), expected.to_string());
1248
1249 let checked = il.checked_mul(ir);
1250 match overflow {
1251 true => assert!(
1252 checked.is_none(),
1253 "{il} * {ir} = {actual} vs {bl} * {br} = {expected}"
1254 ),
1255 false => assert_eq!(
1256 checked,
1257 Some(actual),
1258 "{il} * {ir} = {actual} vs {bl} * {br} = {expected}"
1259 ),
1260 }
1261
1262 if ir != i256::ZERO {
1264 let actual = il.wrapping_div(ir);
1265 let expected = bl.clone() / br.clone();
1266 let checked = il.checked_div(ir);
1267
1268 if ir == i256::MINUS_ONE && il == i256::MIN {
1269 assert_eq!(actual, i256::MIN);
1271 assert!(checked.is_none());
1272 } else {
1273 assert_eq!(actual.to_string(), expected.to_string());
1274 assert_eq!(checked.unwrap().to_string(), expected.to_string());
1275 }
1276 } else {
1277 assert!(il.checked_div(ir).is_none());
1279 }
1280
1281 if ir != i256::ZERO {
1283 let actual = il.wrapping_rem(ir);
1284 let expected = bl.clone() % br.clone();
1285 let checked = il.checked_rem(ir);
1286
1287 assert_eq!(actual.to_string(), expected.to_string(), "{il} % {ir}");
1288
1289 if ir == i256::MINUS_ONE && il == i256::MIN {
1290 assert!(checked.is_none());
1291 } else {
1292 assert_eq!(checked.unwrap().to_string(), expected.to_string());
1293 }
1294 } else {
1295 assert!(il.checked_rem(ir).is_none());
1297 }
1298
1299 for exp in vec![0, 1, 2, 3, 8, 100].into_iter() {
1301 let actual = il.wrapping_pow(exp);
1302 let (expected, overflow) = i256::from_bigint_with_overflow(bl.clone().pow(exp));
1303 assert_eq!(actual.to_string(), expected.to_string());
1304
1305 let checked = il.checked_pow(exp);
1306 match overflow {
1307 true => assert!(
1308 checked.is_none(),
1309 "{il} ^ {exp} = {actual} vs {bl} * {exp} = {expected}"
1310 ),
1311 false => assert_eq!(
1312 checked,
1313 Some(actual),
1314 "{il} ^ {exp} = {actual} vs {bl} ^ {exp} = {expected}"
1315 ),
1316 }
1317 }
1318
1319 let actual = il & ir;
1321 let (expected, _) = i256::from_bigint_with_overflow(bl.clone() & br.clone());
1322 assert_eq!(actual.to_string(), expected.to_string());
1323
1324 let actual = il | ir;
1325 let (expected, _) = i256::from_bigint_with_overflow(bl.clone() | br.clone());
1326 assert_eq!(actual.to_string(), expected.to_string());
1327
1328 let actual = il ^ ir;
1329 let (expected, _) = i256::from_bigint_with_overflow(bl.clone() ^ br);
1330 assert_eq!(actual.to_string(), expected.to_string());
1331
1332 for shift in [0_u8, 1, 4, 126, 128, 129, 254, 255] {
1333 let actual = il << shift;
1334 let (expected, _) = i256::from_bigint_with_overflow(bl.clone() << shift);
1335 assert_eq!(actual.to_string(), expected.to_string());
1336
1337 let wrapping_actual = <i256 as WrappingShl>::wrapping_shl(&il, shift as u32);
1338 assert_eq!(wrapping_actual.to_string(), expected.to_string());
1339
1340 let actual = il >> shift;
1341 let (expected, _) = i256::from_bigint_with_overflow(bl.clone() >> shift);
1342 assert_eq!(actual.to_string(), expected.to_string());
1343
1344 let wrapping_actual = <i256 as WrappingShr>::wrapping_shr(&il, shift as u32);
1345 assert_eq!(wrapping_actual.to_string(), expected.to_string());
1346
1347 let wrapping_actual = <i256 as WrappingShr>::wrapping_shr(&il, 512 + shift as u32);
1349 assert_eq!(wrapping_actual.to_string(), expected.to_string());
1350 }
1351 }
1352
1353 #[test]
1354 fn test_i256() {
1355 let candidates = [
1356 i256::ZERO,
1357 i256::ONE,
1358 i256::MINUS_ONE,
1359 i256::from_i128(2),
1360 i256::from_i128(-2),
1361 i256::from_parts(u128::MAX, 1),
1362 i256::from_parts(u128::MAX, -1),
1363 i256::from_parts(0, 1),
1364 i256::from_parts(0, -1),
1365 i256::from_parts(1, -1),
1366 i256::from_parts(1, 1),
1367 i256::from_parts(0, i128::MAX),
1368 i256::from_parts(0, i128::MIN),
1369 i256::from_parts(1, i128::MAX),
1370 i256::from_parts(1, i128::MIN),
1371 i256::from_parts(u128::MAX, i128::MIN),
1372 i256::from_parts(100, 32),
1373 i256::MIN,
1374 i256::MAX,
1375 i256::MIN >> 1,
1376 i256::MAX >> 1,
1377 i256::ONE << 127,
1378 i256::ONE << 128,
1379 i256::ONE << 129,
1380 i256::MINUS_ONE << 127,
1381 i256::MINUS_ONE << 128,
1382 i256::MINUS_ONE << 129,
1383 ];
1384
1385 for il in candidates {
1386 for ir in candidates {
1387 test_ops(il, ir)
1388 }
1389 }
1390 }
1391
1392 #[test]
1393 fn test_signed_ops() {
1394 assert_eq!(i256::from_i128(1).signum(), i256::ONE);
1396 assert_eq!(i256::from_i128(0).signum(), i256::ZERO);
1397 assert_eq!(i256::from_i128(-0).signum(), i256::ZERO);
1398 assert_eq!(i256::from_i128(-1).signum(), i256::MINUS_ONE);
1399
1400 assert!(i256::from_i128(1).is_positive());
1402 assert!(!i256::from_i128(0).is_positive());
1403 assert!(!i256::from_i128(-0).is_positive());
1404 assert!(!i256::from_i128(-1).is_positive());
1405
1406 assert!(!i256::from_i128(1).is_negative());
1408 assert!(!i256::from_i128(0).is_negative());
1409 assert!(!i256::from_i128(-0).is_negative());
1410 assert!(i256::from_i128(-1).is_negative());
1411 }
1412
1413 #[test]
1414 #[cfg_attr(miri, ignore)]
1415 fn test_i256_fuzz() {
1416 let mut rng = rng();
1417
1418 for _ in 0..1000 {
1419 let mut l = [0_u8; 32];
1420 let len = rng.random_range(0..32);
1421 l.iter_mut().take(len).for_each(|x| *x = rng.random());
1422
1423 let mut r = [0_u8; 32];
1424 let len = rng.random_range(0..32);
1425 r.iter_mut().take(len).for_each(|x| *x = rng.random());
1426
1427 test_ops(i256::from_le_bytes(l), i256::from_le_bytes(r))
1428 }
1429 }
1430
1431 #[test]
1432 fn test_i256_to_primitive() {
1433 let a = i256::MAX;
1434 assert!(a.to_i64().is_none());
1435 assert!(a.to_u64().is_none());
1436
1437 let a = i256::from_i128(i128::MAX);
1438 assert!(a.to_i64().is_none());
1439 assert!(a.to_u64().is_none());
1440
1441 let a = i256::from_i128(i64::MAX as i128);
1442 assert_eq!(a.to_i64().unwrap(), i64::MAX);
1443 assert_eq!(a.to_u64().unwrap(), i64::MAX as u64);
1444
1445 let a = i256::from_i128(i64::MAX as i128 + 1);
1446 assert!(a.to_i64().is_none());
1447 assert_eq!(a.to_u64().unwrap(), i64::MAX as u64 + 1);
1448
1449 let a = i256::MIN;
1450 assert!(a.to_i64().is_none());
1451 assert!(a.to_u64().is_none());
1452
1453 let a = i256::from_i128(i128::MIN);
1454 assert!(a.to_i64().is_none());
1455 assert!(a.to_u64().is_none());
1456
1457 let a = i256::from_i128(i64::MIN as i128);
1458 assert_eq!(a.to_i64().unwrap(), i64::MIN);
1459 assert!(a.to_u64().is_none());
1460
1461 let a = i256::from_i128(i64::MIN as i128 - 1);
1462 assert!(a.to_i64().is_none());
1463 assert!(a.to_u64().is_none());
1464 }
1465
1466 #[test]
1467 fn test_i256_as_i128() {
1468 let a = i256::from_i128(i128::MAX).wrapping_add(i256::from_i128(1));
1469 let i128 = a.as_i128();
1470 assert_eq!(i128, i128::MIN);
1471
1472 let a = i256::from_i128(i128::MAX).wrapping_add(i256::from_i128(2));
1473 let i128 = a.as_i128();
1474 assert_eq!(i128, i128::MIN + 1);
1475
1476 let a = i256::from_i128(i128::MIN).wrapping_sub(i256::from_i128(1));
1477 let i128 = a.as_i128();
1478 assert_eq!(i128, i128::MAX);
1479
1480 let a = i256::from_i128(i128::MIN).wrapping_sub(i256::from_i128(2));
1481 let i128 = a.as_i128();
1482 assert_eq!(i128, i128::MAX - 1);
1483 }
1484
1485 #[test]
1486 fn test_string_roundtrip() {
1487 let roundtrip_cases = [
1488 i256::ZERO,
1489 i256::ONE,
1490 i256::MINUS_ONE,
1491 i256::from_i128(123456789),
1492 i256::from_i128(-123456789),
1493 i256::from_i128(i128::MIN),
1494 i256::from_i128(i128::MAX),
1495 i256::MIN,
1496 i256::MAX,
1497 ];
1498 for case in roundtrip_cases {
1499 let formatted = case.to_string();
1500 let back: i256 = formatted.parse().unwrap();
1501 assert_eq!(case, back);
1502 }
1503 }
1504
1505 #[test]
1506 fn test_from_string() {
1507 let cases = [
1508 (
1509 "000000000000000000000000000000000000000011",
1510 Some(i256::from_i128(11)),
1511 ),
1512 (
1513 "-000000000000000000000000000000000000000011",
1514 Some(i256::from_i128(-11)),
1515 ),
1516 (
1517 "-0000000000000000000000000000000000000000123456789",
1518 Some(i256::from_i128(-123456789)),
1519 ),
1520 ("-", None),
1521 ("+", None),
1522 ("--1", None),
1523 ("-+1", None),
1524 ("000000000000000000000000000000000000000", Some(i256::ZERO)),
1525 ("0000000000000000000000000000000000000000-11", None),
1526 ("11-1111111111111111111111111111111111111", None),
1527 (
1528 "115792089237316195423570985008687907853269984665640564039457584007913129639936",
1529 None,
1530 ),
1531 ];
1532 for (case, expected) in cases {
1533 assert_eq!(i256::from_string(case), expected)
1534 }
1535 }
1536
1537 #[allow(clippy::op_ref)]
1538 fn test_reference_op(il: i256, ir: i256) {
1539 let r1 = il + ir;
1540 let r2 = &il + ir;
1541 let r3 = il + &ir;
1542 let r4 = &il + &ir;
1543 assert_eq!(r1, r2);
1544 assert_eq!(r1, r3);
1545 assert_eq!(r1, r4);
1546
1547 let r1 = il - ir;
1548 let r2 = &il - ir;
1549 let r3 = il - &ir;
1550 let r4 = &il - &ir;
1551 assert_eq!(r1, r2);
1552 assert_eq!(r1, r3);
1553 assert_eq!(r1, r4);
1554
1555 let r1 = il * ir;
1556 let r2 = &il * ir;
1557 let r3 = il * &ir;
1558 let r4 = &il * &ir;
1559 assert_eq!(r1, r2);
1560 assert_eq!(r1, r3);
1561 assert_eq!(r1, r4);
1562
1563 let r1 = il / ir;
1564 let r2 = &il / ir;
1565 let r3 = il / &ir;
1566 let r4 = &il / &ir;
1567 assert_eq!(r1, r2);
1568 assert_eq!(r1, r3);
1569 assert_eq!(r1, r4);
1570 }
1571
1572 #[test]
1573 fn test_i256_reference_op() {
1574 let candidates = [
1575 i256::ONE,
1576 i256::MINUS_ONE,
1577 i256::from_i128(2),
1578 i256::from_i128(-2),
1579 i256::from_i128(3),
1580 i256::from_i128(-3),
1581 ];
1582
1583 for il in candidates {
1584 for ir in candidates {
1585 test_reference_op(il, ir)
1586 }
1587 }
1588 }
1589
1590 #[test]
1591 fn test_decimal256_to_f64_typical_values() {
1592 let v = i256::from_i128(42_i128);
1593 assert_eq!(v.to_f64().unwrap(), 42.0);
1594
1595 let v = i256::from_i128(-123456789012345678i128);
1596 assert_eq!(v.to_f64().unwrap(), -123456789012345678.0);
1597
1598 let v = i256::from_string("0").unwrap();
1599 assert_eq!(v.to_f64().unwrap(), 0.0);
1600
1601 let v = i256::from_string("1").unwrap();
1602 assert_eq!(v.to_f64().unwrap(), 1.0);
1603
1604 let mut rng = rng();
1605 for _ in 0..10 {
1606 let f64_value =
1607 (rng.random_range(i128::MIN..i128::MAX) as f64) * rng.random_range(0.0..1.0);
1608 let big = i256::from_f64(f64_value).unwrap();
1609 assert_eq!(big.to_f64().unwrap(), f64_value);
1610 }
1611 }
1612
1613 #[test]
1614 fn test_decimal256_to_f64_large_positive_value() {
1615 let max_f = f64::MAX;
1616 let big = i256::from_f64(max_f * 2.0).unwrap_or(i256::MAX);
1617 let out = big.to_f64().unwrap();
1618 assert!(out.is_finite() && out.is_sign_positive());
1619 }
1620
1621 #[test]
1622 fn test_decimal256_to_f64_large_negative_value() {
1623 let max_f = f64::MAX;
1624 let big_neg = i256::from_f64(-(max_f * 2.0)).unwrap_or(i256::MIN);
1625 let out = big_neg.to_f64().unwrap();
1626 assert!(out.is_finite() && out.is_sign_negative());
1627 }
1628
1629 #[test]
1630 fn test_num_traits() {
1631 let value = i256::from_i128(-5);
1632 assert_eq!(
1633 <i256 as CheckedNeg>::checked_neg(&value),
1634 Some(i256::from(5))
1635 );
1636
1637 assert_eq!(
1638 <i256 as CheckedAdd>::checked_add(&value, &value),
1639 Some(i256::from(-10))
1640 );
1641
1642 assert_eq!(
1643 <i256 as CheckedSub>::checked_sub(&value, &value),
1644 Some(i256::from(0))
1645 );
1646
1647 assert_eq!(
1648 <i256 as CheckedMul>::checked_mul(&value, &value),
1649 Some(i256::from(25))
1650 );
1651
1652 assert_eq!(
1653 <i256 as CheckedDiv>::checked_div(&value, &value),
1654 Some(i256::from(1))
1655 );
1656
1657 assert_eq!(
1658 <i256 as CheckedRem>::checked_rem(&value, &value),
1659 Some(i256::from(0))
1660 );
1661
1662 assert_eq!(
1663 <i256 as WrappingAdd>::wrapping_add(&value, &value),
1664 i256::from(-10)
1665 );
1666
1667 assert_eq!(
1668 <i256 as WrappingSub>::wrapping_sub(&value, &value),
1669 i256::from(0)
1670 );
1671
1672 assert_eq!(
1673 <i256 as WrappingMul>::wrapping_mul(&value, &value),
1674 i256::from(25)
1675 );
1676
1677 assert_eq!(<i256 as WrappingNeg>::wrapping_neg(&value), i256::from(5));
1678
1679 let result = <i256 as WrappingAdd>::wrapping_add(&i256::MAX, &i256::ONE);
1681 assert_eq!(result, i256::MIN);
1682
1683 assert_eq!(<i256 as Signed>::abs(&value), i256::from(5));
1684
1685 assert_eq!(<i256 as One>::one(), i256::from(1));
1686 assert_eq!(<i256 as Zero>::zero(), i256::from(0));
1687
1688 assert_eq!(<i256 as Bounded>::min_value(), i256::MIN);
1689 assert_eq!(<i256 as Bounded>::max_value(), i256::MAX);
1690 }
1691
1692 #[should_panic]
1693 #[test]
1694 fn test_shl_panic_on_arg_overflow() {
1695 let value = i256::from(123);
1696 let rhs = std::hint::black_box(500);
1697 let _ = value << rhs;
1698 }
1699
1700 #[test]
1701 fn test_numtraits_from_str_radix() {
1702 assert_eq!(
1703 i256::from_str_radix("123456789", 10).expect("parsed"),
1704 i256::from(123456789)
1705 );
1706 assert_eq!(
1707 i256::from_str_radix("0", 10).expect("parsed"),
1708 i256::from(0)
1709 );
1710 assert!(i256::from_str_radix("abc", 10).is_err());
1711 assert!(i256::from_str_radix("0", 16).is_err());
1712 }
1713
1714 #[test]
1715 fn test_leading_zeros() {
1716 assert_eq!(i256::from(0).leading_zeros(), 256);
1718 assert_eq!(i256::from(1).leading_zeros(), 256 - 1);
1719 assert_eq!(i256::from(16).leading_zeros(), 256 - 5);
1720 assert_eq!(i256::from(17).leading_zeros(), 256 - 5);
1721
1722 assert_eq!(i256::from_parts(2, 16).leading_zeros(), 128 - 5);
1724 assert_eq!(i256::from_parts(2, i128::MAX).leading_zeros(), 1);
1725
1726 assert_eq!(i256::MAX.leading_zeros(), 1);
1727 assert_eq!(i256::from(-1).leading_zeros(), 0);
1728 }
1729
1730 #[test]
1731 fn test_trailing_zeros() {
1732 assert_eq!(i256::from(0).trailing_zeros(), 256);
1734 assert_eq!(i256::from(2).trailing_zeros(), 1);
1735 assert_eq!(i256::from(16).trailing_zeros(), 4);
1736 assert_eq!(i256::from(17).trailing_zeros(), 0);
1737 assert_eq!(i256::from_parts(0, i128::MAX).trailing_zeros(), 128);
1739 assert_eq!(i256::from_parts(0, 16).trailing_zeros(), 128 + 4);
1740 assert_eq!(i256::from_parts(2, i128::MAX).trailing_zeros(), 1);
1741
1742 assert_eq!(i256::MAX.trailing_zeros(), 0);
1743 assert_eq!(i256::from(-1).trailing_zeros(), 0);
1744 }
1745
1746 #[test]
1747 fn test_ilog() {
1748 let value = i256::from(128);
1749
1750 assert_eq!(value.ilog(i256::from(2)), 7);
1752 assert_eq!(value.ilog2(), 7);
1753
1754 assert_eq!(value.ilog(i256::from(10)), 2);
1756 assert_eq!(value.ilog10(), 2);
1757
1758 assert_eq!(value.checked_ilog(i256::from(-2)), None);
1760 assert_eq!(value.checked_ilog(i256::from(-10)), None);
1761 assert_eq!(value.checked_ilog(i256::from(0)), None);
1762 assert_eq!(value.checked_ilog(i256::from(1)), None);
1763
1764 let neg_value = i256::from(-128);
1766 assert_eq!(neg_value.checked_ilog(i256::from(2)), None);
1767 assert_eq!(neg_value.checked_ilog(i256::from(10)), None);
1768 assert_eq!(neg_value.checked_ilog10(), None);
1769 assert_eq!(neg_value.checked_ilog2(), None);
1770
1771 assert_eq!(i256::ZERO.checked_ilog(i256::from(2)), None);
1773 assert_eq!(i256::ZERO.checked_ilog(i256::from(10)), None);
1774 assert_eq!(i256::ZERO.checked_ilog10(), None);
1775 assert_eq!(i256::ZERO.checked_ilog2(), None);
1776
1777 assert_eq!(i256::from(2).checked_ilog(i256::from(2)), Some(1));
1779 assert_eq!(i256::from(3).checked_ilog(i256::from(3)), Some(1));
1780 assert_eq!(i256::from(5).checked_ilog(i256::from(5)), Some(1));
1781 assert_eq!(i256::from(1000).checked_ilog(i256::from(1000)), Some(1));
1782 assert_eq!(i256::from(2).checked_ilog2(), Some(1));
1783 assert_eq!(i256::from(2).ilog2(), 1);
1784 assert_eq!(i256::from(10).checked_ilog(i256::from(10)), Some(1));
1786
1787 assert_eq!(i256::from(3).checked_ilog(i256::from(5)), Some(0));
1789
1790 for base in [2i64, 3, 5, 7, 1000] {
1792 for v in 1i64..64 {
1793 let want = (v as u128).ilog(base as u128);
1794 assert_eq!(
1795 i256::from(v).checked_ilog(i256::from(base)),
1796 Some(want),
1797 "checked_ilog({v}, {base})"
1798 );
1799 }
1800 }
1801
1802 let value = i256::from_parts(100000000, 1234);
1803 assert_eq!(value.checked_ilog(i256::from(10)), Some(41));
1804 assert_eq!(value.checked_ilog10(), Some(41));
1805
1806 let large = i256::from_parts(100000000, i128::MAX);
1808 assert_eq!(large.checked_ilog(i256::from(2)), Some(254));
1810
1811 assert_eq!(large.checked_ilog(i256::from(10)), Some(76));
1813 assert_eq!(large.checked_ilog10(), Some(76));
1814
1815 assert_eq!(large.checked_ilog(i256::from(5)), Some(109));
1817
1818 assert!(i256::from(2).checked_pow(255).is_none());
1820 let value = i256::from(2).checked_pow(254).expect("construct");
1821 assert_eq!(value.checked_ilog(i256::from(2)), Some(254));
1822
1823 assert_eq!(i256::MAX.checked_ilog(i256::from(2)), Some(254));
1825 }
1826
1827 #[test]
1828 fn test_ilog10() {
1829 assert_eq!(i256::ZERO.checked_ilog10(), None);
1831 assert_eq!(i256::MINUS_ONE.checked_ilog10(), None);
1832 assert_eq!(i256::MAX.checked_ilog10(), Some(76));
1833 assert_eq!(i256::from(10).checked_ilog10(), Some(1));
1834
1835 assert_eq!(i256::from(1).checked_ilog10(), Some(0));
1837 assert_eq!(i256::from(9).checked_ilog10(), Some(0));
1838
1839 assert_eq!(i256::from(100).checked_ilog10(), Some(2));
1841 assert_eq!(i256::from_parts(u128::MAX, 0).checked_ilog10(), Some(38));
1843
1844 assert_eq!(i256::from_parts(0, 1).checked_ilog10(), Some(38));
1846
1847 let pow50 = i256::from(10).checked_pow(50).unwrap();
1849 assert_eq!(pow50.checked_ilog10(), Some(50));
1850
1851 let pow64 = i256::from(10).checked_pow(64).unwrap();
1853 assert_eq!(pow64.checked_ilog10(), Some(64));
1854 }
1855
1856 #[test]
1857 #[should_panic(expected = "ilog10 overflow")]
1858 fn test_ilog10_zero_panics() {
1859 let _ = i256::ZERO.ilog10();
1860 }
1861
1862 #[test]
1863 #[should_panic(expected = "ilog overflow")]
1864 fn test_ilog_zero_panics() {
1865 let _ = i256::ZERO.ilog(i256::from(5));
1866 }
1867
1868 #[test]
1869 #[should_panic(expected = "ilog2 overflow")]
1870 fn test_ilog2_zero_panics() {
1871 let _ = i256::ZERO.ilog2();
1872 }
1873}