Skip to main content

arrow_buffer/bigint/
mod.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use crate::arith::derive_arith;
19use crate::bigint::div::div_rem;
20use num_bigint::BigInt;
21use num_traits::{
22    Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedShl, CheckedShr,
23    CheckedSub, ConstOne, ConstZero, FromPrimitive, MulAdd, MulAddAssign, Num, One, SaturatingAdd,
24    SaturatingMul, SaturatingSub, Signed, ToPrimitive, WrappingAdd, WrappingMul, WrappingNeg,
25    WrappingShl, WrappingShr, WrappingSub, Zero, cast::AsPrimitive,
26};
27use std::cmp::Ordering;
28use std::num::ParseIntError;
29use std::ops::{BitAnd, BitOr, BitXor, Neg, Not, Shl, Shr};
30use std::str::FromStr;
31
32mod div;
33
34/// An opaque error similar to [`std::num::ParseIntError`]
35#[derive(Debug)]
36pub struct ParseI256Error {}
37
38impl From<ParseIntError> for ParseI256Error {
39    fn from(_: ParseIntError) -> Self {
40        Self {}
41    }
42}
43
44impl std::fmt::Display for ParseI256Error {
45    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46        write!(f, "Failed to parse as i256")
47    }
48}
49impl std::error::Error for ParseI256Error {}
50
51/// Error returned by i256::DivRem
52enum DivRemError {
53    /// Division by zero
54    DivideByZero,
55    /// Division overflow
56    DivideOverflow,
57}
58
59/// A signed 256-bit integer
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        // i128 can store up to 38 decimal digits
84        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        // Trim leading 0s
95        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            // Ensures no duplicate sign
102            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
133impl From<i128> for i256 {
134    fn from(value: i128) -> Self {
135        Self::from_i128(value)
136    }
137}
138
139/// Parse `s` with any sign and leading 0s removed
140fn parse_impl(s: &str, negative: bool) -> Result<i256, ParseI256Error> {
141    if s.len() <= 38 {
142        let low = i128::from_str(s)?;
143        return Ok(match negative {
144            true => i256::from_parts(low.neg() as _, -1),
145            false => i256::from_parts(low as _, 0),
146        });
147    }
148
149    let split = s.len() - 38;
150    if !s.as_bytes()[split].is_ascii_digit() {
151        // Ensures not splitting codepoint and no sign
152        return Err(ParseI256Error {});
153    }
154    let (hs, ls) = s.split_at(split);
155
156    let mut low = i128::from_str(ls)?;
157    let high = parse_impl(hs, negative)?;
158
159    if negative {
160        low = -low;
161    }
162
163    let low = i256::from_i128(low);
164
165    high.checked_mul(i256::from_i128(10_i128.pow(38)))
166        .and_then(|high| high.checked_add(low))
167        .ok_or(ParseI256Error {})
168}
169
170impl PartialOrd for i256 {
171    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
172        Some(self.cmp(other))
173    }
174}
175
176impl Ord for i256 {
177    fn cmp(&self, other: &Self) -> Ordering {
178        // This is 25x faster than using a variable length encoding such
179        // as BigInt as it avoids allocation and branching
180        self.high.cmp(&other.high).then(self.low.cmp(&other.low))
181    }
182}
183
184impl i256 {
185    /// The additive identity for this integer type, i.e. `0`.
186    pub const ZERO: Self = i256 { low: 0, high: 0 };
187
188    /// The multiplicative identity for this integer type, i.e. `1`.
189    pub const ONE: Self = i256 { low: 1, high: 0 };
190
191    /// The multiplicative inverse for this integer type, i.e. `-1`.
192    pub const MINUS_ONE: Self = i256 {
193        low: u128::MAX,
194        high: -1,
195    };
196
197    /// The maximum value that can be represented by this integer type
198    pub const MAX: Self = i256 {
199        low: u128::MAX,
200        high: i128::MAX,
201    };
202
203    /// The minimum value that can be represented by this integer type
204    pub const MIN: Self = i256 {
205        low: u128::MIN,
206        high: i128::MIN,
207    };
208
209    /// Create an integer value from its representation as a byte array in little-endian.
210    #[inline]
211    pub const fn from_le_bytes(b: [u8; 32]) -> Self {
212        let (low, high) = split_array(b);
213        Self {
214            high: i128::from_le_bytes(high),
215            low: u128::from_le_bytes(low),
216        }
217    }
218
219    /// Create an integer value from its representation as a byte array in big-endian.
220    #[inline]
221    pub const fn from_be_bytes(b: [u8; 32]) -> Self {
222        let (high, low) = split_array(b);
223        Self {
224            high: i128::from_be_bytes(high),
225            low: u128::from_be_bytes(low),
226        }
227    }
228
229    /// Create an `i256` value from a 128-bit value.
230    pub const fn from_i128(v: i128) -> Self {
231        Self::from_parts(v as u128, v >> 127)
232    }
233
234    /// Create an integer value from its representation as string.
235    #[inline]
236    pub fn from_string(value_str: &str) -> Option<Self> {
237        value_str.parse().ok()
238    }
239
240    /// Create an optional i256 from the provided `f64`. Returning `None`
241    /// if overflow occurred
242    pub fn from_f64(v: f64) -> Option<Self> {
243        BigInt::from_f64(v).and_then(|i| {
244            let (integer, overflow) = i256::from_bigint_with_overflow(i);
245            if overflow { None } else { Some(integer) }
246        })
247    }
248
249    /// Create an i256 from the provided low u128 and high i128
250    #[inline]
251    pub const fn from_parts(low: u128, high: i128) -> Self {
252        Self { low, high }
253    }
254
255    /// Returns this `i256` as a low u128 and high i128
256    pub const fn to_parts(self) -> (u128, i128) {
257        (self.low, self.high)
258    }
259
260    /// Converts this `i256` into an `i128` returning `None` if this would result
261    /// in truncation/overflow
262    pub const fn to_i128(self) -> Option<i128> {
263        let as_i128 = self.low as i128;
264
265        let high_negative = self.high < 0;
266        let low_negative = as_i128 < 0;
267        let high_valid = self.high == -1 || self.high == 0;
268
269        if (high_negative == low_negative) && high_valid {
270            Some(self.low as i128)
271        } else {
272            None
273        }
274    }
275
276    /// Wraps this `i256` into an `i128`
277    pub const fn as_i128(self) -> i128 {
278        self.low as i128
279    }
280
281    /// Return the memory representation of this integer as a byte array in little-endian byte order.
282    #[inline]
283    pub const fn to_le_bytes(self) -> [u8; 32] {
284        let low = self.low.to_le_bytes();
285        let high = self.high.to_le_bytes();
286        let mut t = [0; 32];
287        let mut i = 0;
288        while i != 16 {
289            t[i] = low[i];
290            t[i + 16] = high[i];
291            i += 1;
292        }
293        t
294    }
295
296    /// Return the memory representation of this integer as a byte array in big-endian byte order.
297    #[inline]
298    pub const fn to_be_bytes(self) -> [u8; 32] {
299        let low = self.low.to_be_bytes();
300        let high = self.high.to_be_bytes();
301        let mut t = [0; 32];
302        let mut i = 0;
303        while i != 16 {
304            t[i] = high[i];
305            t[i + 16] = low[i];
306            i += 1;
307        }
308        t
309    }
310
311    /// Create an i256 from the provided [`BigInt`] returning a bool indicating
312    /// if overflow occurred
313    fn from_bigint_with_overflow(v: BigInt) -> (Self, bool) {
314        let v_bytes = v.to_signed_bytes_le();
315        match v_bytes.len().cmp(&32) {
316            Ordering::Less => {
317                let mut bytes = if num_traits::Signed::is_negative(&v) {
318                    [255_u8; 32]
319                } else {
320                    [0; 32]
321                };
322                bytes[0..v_bytes.len()].copy_from_slice(&v_bytes[..v_bytes.len()]);
323                (Self::from_le_bytes(bytes), false)
324            }
325            Ordering::Equal => (Self::from_le_bytes(v_bytes.try_into().unwrap()), false),
326            Ordering::Greater => (Self::from_le_bytes(v_bytes[..32].try_into().unwrap()), true),
327        }
328    }
329
330    /// Computes the absolute value of this i256
331    #[inline]
332    pub const fn wrapping_abs(self) -> Self {
333        // -1 if negative, otherwise 0
334        let sa = self.high >> 127;
335        let sa = Self::from_parts(sa as u128, sa);
336
337        // Inverted if negative
338        Self::from_parts(self.low ^ sa.low, self.high ^ sa.high).wrapping_sub(sa)
339    }
340
341    /// Computes the absolute value of this i256 returning `None` if `Self == Self::MIN`
342    #[inline]
343    pub const fn checked_abs(self) -> Option<Self> {
344        if !self.is_eq(Self::MIN) {
345            Some(self.wrapping_abs())
346        } else {
347            None
348        }
349    }
350
351    /// Negates this i256
352    #[inline]
353    pub const fn wrapping_neg(self) -> Self {
354        Self::from_parts(!self.low, !self.high).wrapping_add(i256::ONE)
355    }
356
357    /// Negates this i256 returning `None` if `Self == Self::MIN`
358    #[inline]
359    pub const fn checked_neg(self) -> Option<Self> {
360        if !self.is_eq(Self::MIN) {
361            Some(self.wrapping_neg())
362        } else {
363            None
364        }
365    }
366
367    /// Performs wrapping addition
368    #[inline]
369    pub const fn wrapping_add(self, other: Self) -> Self {
370        let (low, carry) = self.low.overflowing_add(other.low);
371        let high = self.high.wrapping_add(other.high).wrapping_add(carry as _);
372        Self { low, high }
373    }
374
375    /// Performs checked addition
376    #[inline]
377    pub const fn checked_add(self, other: Self) -> Option<Self> {
378        let (r, overflow) = self.overflowing_add(other);
379
380        if overflow { None } else { Some(r) }
381    }
382
383    /// Performs wrapping subtraction
384    #[inline]
385    pub const fn wrapping_sub(self, other: Self) -> Self {
386        let (low, carry) = self.low.overflowing_sub(other.low);
387        let high = self.high.wrapping_sub(other.high).wrapping_sub(carry as _);
388        Self { low, high }
389    }
390
391    /// Performs checked subtraction
392    #[inline]
393    pub const fn checked_sub(self, other: Self) -> Option<Self> {
394        let (r, overflow) = self.overflowing_sub(other);
395
396        if overflow { None } else { Some(r) }
397    }
398
399    /// Performs wrapping multiplication
400    #[inline]
401    pub const fn wrapping_mul(self, other: Self) -> Self {
402        let (low, high) = mulx(self.low, other.low);
403
404        // Compute the high multiples, only impacting the high 128-bits
405        let hl = self.high.wrapping_mul(other.low as i128);
406        let lh = (self.low as i128).wrapping_mul(other.high);
407
408        Self {
409            low,
410            high: (high as i128).wrapping_add(hl).wrapping_add(lh),
411        }
412    }
413
414    /// Const helper to check equality of two `i256` instances
415    const fn is_eq(&self, other: Self) -> bool {
416        (self.high == other.high) && (self.low == other.low)
417    }
418
419    /// Performs checked multiplication
420    #[inline]
421    pub const fn checked_mul(self, other: Self) -> Option<Self> {
422        if self.is_eq(Self::ZERO) || other.is_eq(Self::ZERO) {
423            return Some(i256::ZERO);
424        }
425
426        // Shift sign bit down to construct mask of all set bits if negative
427        let l_sa = self.high >> 127;
428        let r_sa = other.high >> 127;
429        let out_sa = (l_sa ^ r_sa) as u128;
430
431        // Compute absolute values
432        let l_abs = self.wrapping_abs();
433        let r_abs = other.wrapping_abs();
434
435        // Overflow if both high parts are non-zero
436        if l_abs.high != 0 && r_abs.high != 0 {
437            return None;
438        }
439
440        // Perform checked multiplication on absolute values
441        let (low, high) = mulx(l_abs.low, r_abs.low);
442
443        // Compute the high multiples, only impacting the high 128-bits
444        let Some(hl) = (l_abs.high as u128).checked_mul(r_abs.low) else {
445            return None;
446        };
447        let Some(lh) = l_abs.low.checked_mul(r_abs.high as u128) else {
448            return None;
449        };
450
451        let Some(high) = high.checked_add(hl) else {
452            return None;
453        };
454        let Some(high) = high.checked_add(lh) else {
455            return None;
456        };
457
458        // Reverse absolute value, if necessary
459        let (low, c) = (low ^ out_sa).overflowing_sub(out_sa);
460        let high = (high ^ out_sa).wrapping_sub(out_sa).wrapping_sub(c as u128) as i128;
461
462        // Check for overflow in final conversion
463        if high.is_negative() == (self.is_negative() ^ other.is_negative()) {
464            Some(Self { low, high })
465        } else {
466            None
467        }
468    }
469
470    /// Division operation, returns (quotient, remainder).
471    /// This basically implements [Long division]: `<https://en.wikipedia.org/wiki/Division_algorithm>`
472    #[inline]
473    fn div_rem(self, other: Self) -> Result<(Self, Self), DivRemError> {
474        if other == Self::ZERO {
475            return Err(DivRemError::DivideByZero);
476        }
477        if other == Self::MINUS_ONE && self == Self::MIN {
478            return Err(DivRemError::DivideOverflow);
479        }
480
481        let a = self.wrapping_abs();
482        let b = other.wrapping_abs();
483
484        let (div, rem) = div_rem(&a.as_digits(), &b.as_digits());
485        let div = Self::from_digits(div);
486        let rem = Self::from_digits(rem);
487
488        Ok((
489            if self.is_negative() == other.is_negative() {
490                div
491            } else {
492                div.wrapping_neg()
493            },
494            if self.is_negative() {
495                rem.wrapping_neg()
496            } else {
497                rem
498            },
499        ))
500    }
501
502    /// Interpret this [`i256`] as 4 `u64` digits, least significant first
503    fn as_digits(self) -> [u64; 4] {
504        [
505            self.low as u64,
506            (self.low >> 64) as u64,
507            self.high as u64,
508            (self.high as u128 >> 64) as u64,
509        ]
510    }
511
512    /// Interpret 4 `u64` digits, least significant first, as a [`i256`]
513    fn from_digits(digits: [u64; 4]) -> Self {
514        Self::from_parts(
515            digits[0] as u128 | ((digits[1] as u128) << 64),
516            digits[2] as i128 | ((digits[3] as i128) << 64),
517        )
518    }
519
520    /// Performs wrapping division
521    #[inline]
522    pub fn wrapping_div(self, other: Self) -> Self {
523        match self.div_rem(other) {
524            Ok((v, _)) => v,
525            Err(DivRemError::DivideByZero) => panic!("attempt to divide by zero"),
526            Err(_) => Self::MIN,
527        }
528    }
529
530    /// Performs checked division
531    #[inline]
532    pub fn checked_div(self, other: Self) -> Option<Self> {
533        self.div_rem(other).map(|(v, _)| v).ok()
534    }
535
536    /// Performs wrapping remainder
537    #[inline]
538    pub fn wrapping_rem(self, other: Self) -> Self {
539        match self.div_rem(other) {
540            Ok((_, v)) => v,
541            Err(DivRemError::DivideByZero) => panic!("attempt to divide by zero"),
542            Err(_) => Self::ZERO,
543        }
544    }
545
546    /// Performs checked remainder
547    #[inline]
548    pub fn checked_rem(self, other: Self) -> Option<Self> {
549        self.div_rem(other).map(|(_, v)| v).ok()
550    }
551
552    /// Performs checked exponentiation
553    #[inline]
554    pub const fn checked_pow(self, mut exp: u32) -> Option<Self> {
555        if exp == 0 {
556            return Some(i256::from_i128(1));
557        }
558
559        let mut base = self;
560        let mut acc: Self = i256::from_i128(1);
561
562        while exp > 1 {
563            if (exp & 1) == 1 {
564                let Some(next) = acc.checked_mul(base) else {
565                    return None;
566                };
567                acc = next;
568            }
569            exp /= 2;
570            let Some(next) = base.checked_mul(base) else {
571                return None;
572            };
573            base = next;
574        }
575        // since exp!=0, finally the exp must be 1.
576        // Deal with the final bit of the exponent separately, since
577        // squaring the base afterwards is not necessary and may cause a
578        // needless overflow.
579        acc.checked_mul(base)
580    }
581
582    /// Performs wrapping exponentiation
583    #[inline]
584    pub const fn wrapping_pow(self, mut exp: u32) -> Self {
585        if exp == 0 {
586            return i256::from_i128(1);
587        }
588
589        let mut base = self;
590        let mut acc: Self = i256::from_i128(1);
591
592        while exp > 1 {
593            if (exp & 1) == 1 {
594                acc = acc.wrapping_mul(base);
595            }
596            exp /= 2;
597            base = base.wrapping_mul(base);
598        }
599
600        // since exp!=0, finally the exp must be 1.
601        // Deal with the final bit of the exponent separately, since
602        // squaring the base afterwards is not necessary and may cause a
603        // needless overflow.
604        acc.wrapping_mul(base)
605    }
606
607    /// Returns a number [`i256`] representing sign of this [`i256`].
608    ///
609    /// 0 if the number is zero
610    /// 1 if the number is positive
611    /// -1 if the number is negative
612    pub const fn signum(self) -> Self {
613        if self.is_positive() {
614            i256::ONE
615        } else if self.is_negative() {
616            i256::MINUS_ONE
617        } else {
618            i256::ZERO
619        }
620    }
621
622    /// Returns `true` if this [`i256`] is negative
623    #[inline]
624    pub const fn is_negative(self) -> bool {
625        self.high.is_negative()
626    }
627
628    /// Returns `true` if this [`i256`] is positive
629    pub const fn is_positive(self) -> bool {
630        self.high.is_positive() || self.high == 0 && self.low != 0
631    }
632
633    /// Returns the number of leading zeros in the binary representation of this [`i256`].
634    pub const fn leading_zeros(&self) -> u32 {
635        match self.high {
636            0 => u128::BITS + self.low.leading_zeros(),
637            _ => self.high.leading_zeros(),
638        }
639    }
640
641    /// Returns the number of trailing zeros in the binary representation of this [`i256`].
642    pub const fn trailing_zeros(&self) -> u32 {
643        match self.low {
644            0 => u128::BITS + self.high.trailing_zeros(),
645            _ => self.low.trailing_zeros(),
646        }
647    }
648
649    fn redundant_leading_sign_bits_i256(n: i256) -> u8 {
650        let mask = n >> 255; // all ones or all zeros
651        ((n ^ mask).leading_zeros() - 1) as u8 // we only need one sign bit
652    }
653
654    fn i256_to_f64(input: i256) -> f64 {
655        let k = i256::redundant_leading_sign_bits_i256(input);
656        let n = input << k; // left-justify (no redundant sign bits)
657        let n = (n.high >> 64) as i64; // throw away the lower 192 bits
658        (n as f64) * f64::powi(2.0, 192 - (k as i32)) // convert to f64 and scale it, as we left-shift k bit previous, so we need to scale it by 2^(192-k)
659    }
660
661    /// Computes the `base` logarithm of the number `self`
662    /// Returns `None` if `self` is less than or equal to zero, or if `base` is less than 2.
663    #[inline]
664    pub fn checked_ilog(self, base: i256) -> Option<u32> {
665        if base == Self::from(10) {
666            // Faster implementation for base 10
667            return self.checked_ilog10();
668        }
669
670        if self <= Self::ZERO {
671            return None;
672        }
673        if base <= Self::ONE {
674            return None;
675        }
676        if self < base {
677            return Some(0);
678        }
679
680        let mut val = 1;
681        let mut base_exp = base;
682
683        let boundary = self.checked_div(base)?;
684        while base_exp <= boundary {
685            val += 1;
686            base_exp = base_exp.checked_mul(base)?;
687        }
688        Some(val)
689    }
690
691    /// Computes the `base` logarithm of the number `self`
692    /// Panic if `self` is less than or equal to zero, or if `base` is less than 2.
693    #[inline]
694    pub fn ilog(self, base: i256) -> u32 {
695        self.checked_ilog(base)
696            .unwrap_or_else(|| panic!("ilog overflow with {self} and base {base}"))
697    }
698
699    /// Computes the decimal logarithm of the number `self`
700    /// Returns `None` if `self` is less than or equal to zero.
701    #[inline]
702    pub fn checked_ilog10(self) -> Option<u32> {
703        if self <= Self::ZERO {
704            return None;
705        }
706        if self < Self::from(10) {
707            return Some(0);
708        }
709
710        // Layered approach to calculate logarithm using i128 log operations only
711        // Consult int_log10.rs stdlib implementiation for u128
712        let pow_64: i256 = i256::from(10).checked_pow(64).unwrap();
713        let pow_32: i256 = i256::from(10).checked_pow(32).unwrap();
714        if self >= pow_64 {
715            let value = self.checked_div(pow_64)?;
716            // self is between 10^64 and 10^77 (~i256::MAX).
717            // `value` is 14 digits max (10^77 / 10^64 = 10^13),
718            // so it fits to `low` u128
719            debug_assert!(value.high == 0);
720            Some(64 + value.low.checked_ilog10()?)
721        } else if self >= pow_32 {
722            let value = self.checked_div(pow_32)?;
723            // self is between 10^32 and 10^64.
724            // `value` is 33 digits max (10^64/10^32=10^32)
725            // so it fits to `low` 128-bit value
726            debug_assert!(value.high == 0);
727            Some(32 + value.low.checked_ilog10()?)
728        } else {
729            // self fits within u128 (high == 0 and self > 0).
730            self.low.checked_ilog10()
731        }
732    }
733
734    /// Computes the decimal logarithm of the number `self`
735    /// Panics if `self` is less than or equal to zero.
736    #[inline]
737    pub fn ilog10(self) -> u32 {
738        self.checked_ilog10()
739            .unwrap_or_else(|| panic!("ilog10 overflow with {self}"))
740    }
741
742    /// Computes the binary logarithm of the number `self`
743    /// Returns `None` if `self` is less than or equal to zero.
744    #[inline]
745    pub fn checked_ilog2(self) -> Option<u32> {
746        self.checked_ilog(i256::from(2))
747    }
748
749    /// Computes the base 2 logarithm of the number, rounded down.
750    #[inline]
751    pub fn ilog2(self) -> u32 {
752        self.checked_ilog2()
753            .unwrap_or_else(|| panic!("ilog2 overflow with {self}"))
754    }
755
756    /// Calculates `self + rhs`.
757    ///
758    /// Returns the wrapping sum and a boolean indicating whether arithmetic overflow occurred.
759    /// The returned sum wraps around the bounds of [`i256`] when overflow occurs.
760    #[inline]
761    pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
762        // Add the low limbs and capture the carry into the high limb.
763        let (low, carry) = self.low.overflowing_add(rhs.low);
764
765        // Treat the high limbs as raw two's-complement bit patterns.
766        let high = (self.high as u128)
767            .wrapping_add(rhs.high as u128)
768            .wrapping_add(carry as u128) as i128;
769
770        let result = Self { low, high };
771
772        // Signed overflow occurs when:
773        // - both operands have the same sign, and
774        // - the result has the opposite sign.
775        let overflow = (self.high < 0) == (rhs.high < 0) && (high < 0) != (self.high < 0);
776
777        (result, overflow)
778    }
779
780    /// Calculates `self - rhs`.
781    ///
782    /// Returns the wrapping difference and a boolean indicating whether arithmetic overflow
783    /// occurred. The returned difference wraps around the bounds of [`i256`] when overflow occurs.
784    #[inline]
785    pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
786        // Subtract the low limbs and determine whether we borrowed.
787        let (low, borrow) = self.low.overflowing_sub(rhs.low);
788
789        // Subtract the high limbs as raw bit patterns, including the borrow.
790        let high = (self.high as u128)
791            .wrapping_sub(rhs.high as u128)
792            .wrapping_sub(borrow as u128) as i128;
793
794        let result = Self { low, high };
795
796        // Signed overflow occurs when:
797        // - operands have opposite signs, and
798        // - the result's sign differs from the left operand's sign.
799        let overflow = (self.high < 0) != (rhs.high < 0) && (high < 0) != (self.high < 0);
800
801        (result, overflow)
802    }
803}
804
805/// Temporary workaround due to lack of stable const array slicing
806/// See <https://github.com/rust-lang/rust/issues/90091>
807const fn split_array<const N: usize, const M: usize>(vals: [u8; N]) -> ([u8; M], [u8; M]) {
808    let mut a = [0; M];
809    let mut b = [0; M];
810    let mut i = 0;
811    while i != M {
812        a[i] = vals[i];
813        b[i] = vals[i + M];
814        i += 1;
815    }
816    (a, b)
817}
818
819/// Performs an unsigned multiplication of `a * b` returning a tuple of
820/// `(low, high)` where `low` contains the lower 128-bits of the result
821/// and `high` the higher 128-bits
822///
823/// This mirrors the x86 mulx instruction but for 128-bit types
824#[inline]
825const fn mulx(a: u128, b: u128) -> (u128, u128) {
826    const fn split(a: u128) -> (u128, u128) {
827        (a & (u64::MAX as u128), a >> 64)
828    }
829
830    const MASK: u128 = u64::MAX as _;
831
832    let (a_low, a_high) = split(a);
833    let (b_low, b_high) = split(b);
834
835    // Carry stores the upper 64-bits of low and lower 64-bits of high
836    let (mut low, mut carry) = split(a_low * b_low);
837    carry += a_high * b_low;
838
839    // Update low and high with corresponding parts of carry
840    low += carry << 64;
841    let mut high = carry >> 64;
842
843    // Update carry with overflow from low
844    carry = low >> 64;
845    low &= MASK;
846
847    // Perform multiply including overflow from low
848    carry += b_high * a_low;
849
850    // Update low and high with values from carry
851    low += carry << 64;
852    high += carry >> 64;
853
854    // Perform 4th multiplication
855    high += a_high * b_high;
856
857    (low, high)
858}
859
860derive_arith!(
861    i256,
862    Add,
863    AddAssign,
864    add,
865    add_assign,
866    wrapping_add,
867    checked_add
868);
869derive_arith!(
870    i256,
871    Sub,
872    SubAssign,
873    sub,
874    sub_assign,
875    wrapping_sub,
876    checked_sub
877);
878derive_arith!(
879    i256,
880    Mul,
881    MulAssign,
882    mul,
883    mul_assign,
884    wrapping_mul,
885    checked_mul
886);
887derive_arith!(
888    i256,
889    Div,
890    DivAssign,
891    div,
892    div_assign,
893    wrapping_div,
894    checked_div
895);
896derive_arith!(
897    i256,
898    Rem,
899    RemAssign,
900    rem,
901    rem_assign,
902    wrapping_rem,
903    checked_rem
904);
905
906impl Neg for i256 {
907    type Output = i256;
908
909    #[cfg(debug_assertions)]
910    fn neg(self) -> Self::Output {
911        self.checked_neg().expect("i256 overflow")
912    }
913
914    #[cfg(not(debug_assertions))]
915    fn neg(self) -> Self::Output {
916        self.wrapping_neg()
917    }
918}
919
920impl BitAnd for i256 {
921    type Output = i256;
922
923    #[inline]
924    fn bitand(self, rhs: Self) -> Self::Output {
925        Self {
926            low: self.low & rhs.low,
927            high: self.high & rhs.high,
928        }
929    }
930}
931
932impl BitOr for i256 {
933    type Output = i256;
934
935    #[inline]
936    fn bitor(self, rhs: Self) -> Self::Output {
937        Self {
938            low: self.low | rhs.low,
939            high: self.high | rhs.high,
940        }
941    }
942}
943
944impl BitXor for i256 {
945    type Output = i256;
946
947    #[inline]
948    fn bitxor(self, rhs: Self) -> Self::Output {
949        Self {
950            low: self.low ^ rhs.low,
951            high: self.high ^ rhs.high,
952        }
953    }
954}
955
956impl Shl<u8> for i256 {
957    type Output = i256;
958
959    #[inline]
960    fn shl(self, rhs: u8) -> Self::Output {
961        if rhs == 0 {
962            self
963        } else if rhs < 128 {
964            Self {
965                high: (self.high << rhs) | (self.low >> (128 - rhs)) as i128,
966                low: self.low << rhs,
967            }
968        } else {
969            Self {
970                high: (self.low << (rhs - 128)) as i128,
971                low: 0,
972            }
973        }
974    }
975}
976
977impl Shr<u8> for i256 {
978    type Output = i256;
979
980    #[inline]
981    fn shr(self, rhs: u8) -> Self::Output {
982        if rhs == 0 {
983            self
984        } else if rhs < 128 {
985            Self {
986                high: self.high >> rhs,
987                low: (self.low >> rhs) | ((self.high as u128) << (128 - rhs)),
988            }
989        } else {
990            Self {
991                high: self.high >> 127,
992                low: (self.high >> (rhs - 128)) as u128,
993            }
994        }
995    }
996}
997
998impl WrappingShl for i256 {
999    #[inline]
1000    fn wrapping_shl(&self, rhs: u32) -> i256 {
1001        // Limit shift to 256 (max valid shift for i256)
1002        (*self).shl(rhs as u8)
1003    }
1004}
1005
1006impl WrappingShr for i256 {
1007    #[inline]
1008    fn wrapping_shr(&self, rhs: u32) -> i256 {
1009        // Limit shift to 256 (max valid shift for i256)
1010        (*self).shr(rhs as u8)
1011    }
1012}
1013
1014// Define Shl<T> and Shr<T> for specified integer types using
1015// an existing Shl<u8> and Shr<u8> implementation
1016macro_rules! define_standard_shift {
1017    // Handle multiple types
1018    ($trait_name:ident, $method:ident, [$($t:ty),+]) => {
1019        $(define_standard_shift!($trait_name, $method, $t);)+
1020    };
1021    // Handle single type
1022    ($trait_name:ident, $method:ident, $t:ty) => {
1023        impl $trait_name<$t> for i256 {
1024            type Output = i256;
1025
1026            #[inline]
1027            fn $method(self, rhs: $t) -> Self::Output {
1028                let rhs = u8::try_from(rhs).expect("rhs overflow for shift");
1029                // Other possible overflows are handled by Shl<u8> implementation
1030                self.$method(rhs)
1031            }
1032        }
1033    };
1034}
1035
1036define_standard_shift!(
1037    Shl,
1038    shl,
1039    [u16, u32, u64, u128, usize, i16, i32, i64, i128, isize]
1040);
1041define_standard_shift!(
1042    Shr,
1043    shr,
1044    [u16, u32, u64, u128, usize, i16, i32, i64, i128, isize]
1045);
1046
1047macro_rules! define_as_primitive {
1048    ($native_ty:ty) => {
1049        impl AsPrimitive<i256> for $native_ty {
1050            fn as_(self) -> i256 {
1051                i256::from_i128(self as i128)
1052            }
1053        }
1054    };
1055}
1056
1057define_as_primitive!(i8);
1058define_as_primitive!(i16);
1059define_as_primitive!(i32);
1060define_as_primitive!(i64);
1061define_as_primitive!(u8);
1062define_as_primitive!(u16);
1063define_as_primitive!(u32);
1064define_as_primitive!(u64);
1065
1066impl ToPrimitive for i256 {
1067    fn to_i64(&self) -> Option<i64> {
1068        let as_i128 = self.low as i128;
1069
1070        let high_negative = self.high < 0;
1071        let low_negative = as_i128 < 0;
1072        let high_valid = self.high == -1 || self.high == 0;
1073
1074        if high_negative == low_negative && high_valid {
1075            let (low_bytes, high_bytes) = split_array(u128::to_le_bytes(self.low));
1076            let high = i64::from_le_bytes(high_bytes);
1077            let low = i64::from_le_bytes(low_bytes);
1078
1079            let high_negative = high < 0;
1080            let low_negative = low < 0;
1081            let high_valid = self.high == -1 || self.high == 0;
1082
1083            (high_negative == low_negative && high_valid).then_some(low)
1084        } else {
1085            None
1086        }
1087    }
1088
1089    fn to_f64(&self) -> Option<f64> {
1090        match *self {
1091            Self::MIN => Some(-2_f64.powi(255)),
1092            Self::ZERO => Some(0f64),
1093            Self::ONE => Some(1f64),
1094            n => Some(Self::i256_to_f64(n)),
1095        }
1096    }
1097
1098    fn to_u64(&self) -> Option<u64> {
1099        let as_i128 = self.low as i128;
1100
1101        let high_negative = self.high < 0;
1102        let low_negative = as_i128 < 0;
1103        let high_valid = self.high == -1 || self.high == 0;
1104
1105        if high_negative == low_negative && high_valid {
1106            self.low.to_u64()
1107        } else {
1108            None
1109        }
1110    }
1111}
1112
1113// num_traits checked implementations
1114
1115impl CheckedNeg for i256 {
1116    fn checked_neg(&self) -> Option<Self> {
1117        (*self).checked_neg()
1118    }
1119}
1120
1121impl CheckedAdd for i256 {
1122    fn checked_add(&self, v: &i256) -> Option<Self> {
1123        (*self).checked_add(*v)
1124    }
1125}
1126
1127impl CheckedSub for i256 {
1128    fn checked_sub(&self, v: &i256) -> Option<Self> {
1129        (*self).checked_sub(*v)
1130    }
1131}
1132
1133impl CheckedDiv for i256 {
1134    fn checked_div(&self, v: &i256) -> Option<Self> {
1135        (*self).checked_div(*v)
1136    }
1137}
1138
1139impl CheckedMul for i256 {
1140    fn checked_mul(&self, v: &i256) -> Option<Self> {
1141        (*self).checked_mul(*v)
1142    }
1143}
1144
1145impl CheckedRem for i256 {
1146    fn checked_rem(&self, v: &i256) -> Option<Self> {
1147        (*self).checked_rem(*v)
1148    }
1149}
1150
1151impl CheckedShl for i256 {
1152    fn checked_shl(&self, rhs: u32) -> Option<Self> {
1153        let rhs = u8::try_from(rhs).ok()?;
1154        Some(self.shl(rhs))
1155    }
1156}
1157
1158impl CheckedShr for i256 {
1159    fn checked_shr(&self, rhs: u32) -> Option<Self> {
1160        let rhs = u8::try_from(rhs).ok()?;
1161        Some(self.shr(rhs))
1162    }
1163}
1164
1165// num_traits wrapping implementations
1166
1167impl WrappingAdd for i256 {
1168    fn wrapping_add(&self, v: &Self) -> Self {
1169        (*self).wrapping_add(*v)
1170    }
1171}
1172
1173impl WrappingSub for i256 {
1174    fn wrapping_sub(&self, v: &Self) -> Self {
1175        (*self).wrapping_sub(*v)
1176    }
1177}
1178
1179impl WrappingMul for i256 {
1180    fn wrapping_mul(&self, v: &Self) -> Self {
1181        (*self).wrapping_mul(*v)
1182    }
1183}
1184
1185impl WrappingNeg for i256 {
1186    fn wrapping_neg(&self) -> Self {
1187        (*self).wrapping_neg()
1188    }
1189}
1190
1191// num_traits saturating implementations
1192
1193impl SaturatingAdd for i256 {
1194    fn saturating_add(&self, v: &Self) -> Self {
1195        self.checked_add(v).unwrap_or_else(|| {
1196            if v.is_negative() {
1197                i256::MIN
1198            } else {
1199                i256::MAX
1200            }
1201        })
1202    }
1203}
1204
1205impl SaturatingSub for i256 {
1206    fn saturating_sub(&self, v: &Self) -> Self {
1207        self.checked_sub(v).unwrap_or_else(|| {
1208            if v.is_negative() {
1209                i256::MAX
1210            } else {
1211                i256::MIN
1212            }
1213        })
1214    }
1215}
1216
1217impl SaturatingMul for i256 {
1218    fn saturating_mul(&self, v: &Self) -> Self {
1219        self.checked_mul(v).unwrap_or_else(|| {
1220            if v.is_negative() == self.is_negative() {
1221                i256::MAX
1222            } else {
1223                i256::MIN
1224            }
1225        })
1226    }
1227}
1228
1229impl MulAdd for i256 {
1230    type Output = i256;
1231
1232    fn mul_add(self, a: Self, b: Self) -> Self::Output {
1233        (self * a) + b
1234    }
1235}
1236
1237impl MulAddAssign for i256 {
1238    fn mul_add_assign(&mut self, a: Self, b: Self) {
1239        *self = self.mul_add(a, b)
1240    }
1241}
1242
1243impl Zero for i256 {
1244    fn zero() -> Self {
1245        i256::ZERO
1246    }
1247
1248    fn is_zero(&self) -> bool {
1249        *self == i256::ZERO
1250    }
1251}
1252
1253impl ConstZero for i256 {
1254    const ZERO: Self = i256::ZERO;
1255}
1256
1257impl One for i256 {
1258    fn one() -> Self {
1259        i256::ONE
1260    }
1261
1262    fn is_one(&self) -> bool {
1263        *self == i256::ONE
1264    }
1265}
1266
1267impl ConstOne for i256 {
1268    const ONE: Self = i256::ONE;
1269}
1270
1271impl Num for i256 {
1272    type FromStrRadixErr = ParseI256Error;
1273
1274    fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
1275        if radix == 10 {
1276            str.parse()
1277        } else {
1278            // Parsing from non-10 baseseeÃŽ is not supported
1279            Err(ParseI256Error {})
1280        }
1281    }
1282}
1283
1284impl Signed for i256 {
1285    fn abs(&self) -> Self {
1286        self.wrapping_abs()
1287    }
1288
1289    fn abs_sub(&self, other: &Self) -> Self {
1290        if self > other {
1291            self.wrapping_sub(other)
1292        } else {
1293            i256::ZERO
1294        }
1295    }
1296
1297    fn signum(&self) -> Self {
1298        (*self).signum()
1299    }
1300
1301    fn is_positive(&self) -> bool {
1302        (*self).is_positive()
1303    }
1304
1305    fn is_negative(&self) -> bool {
1306        (*self).is_negative()
1307    }
1308}
1309
1310impl Bounded for i256 {
1311    fn min_value() -> Self {
1312        i256::MIN
1313    }
1314
1315    fn max_value() -> Self {
1316        i256::MAX
1317    }
1318}
1319
1320impl Not for i256 {
1321    type Output = i256;
1322
1323    #[inline]
1324    fn not(self) -> Self::Output {
1325        Self::from_parts(!self.low, !self.high)
1326    }
1327}
1328
1329#[cfg(test)]
1330mod tests {
1331    use super::*;
1332    use num_traits::Signed;
1333    use rand::{RngExt, rng};
1334
1335    #[test]
1336    fn test_signed_cmp() {
1337        let a = i256::from_parts(i128::MAX as u128, 12);
1338        let b = i256::from_parts(i128::MIN as u128, 12);
1339        assert!(a < b);
1340
1341        let a = i256::from_parts(i128::MAX as u128, 12);
1342        let b = i256::from_parts(i128::MIN as u128, -12);
1343        assert!(a > b);
1344    }
1345
1346    #[test]
1347    fn test_to_i128() {
1348        let vals = [
1349            BigInt::from_i128(-1).unwrap(),
1350            BigInt::from_i128(i128::MAX).unwrap(),
1351            BigInt::from_i128(i128::MIN).unwrap(),
1352            BigInt::from_u128(u128::MIN).unwrap(),
1353            BigInt::from_u128(u128::MAX).unwrap(),
1354        ];
1355
1356        for v in vals {
1357            let (t, overflow) = i256::from_bigint_with_overflow(v.clone());
1358            assert!(!overflow);
1359            assert_eq!(t.to_i128(), v.to_i128(), "{v} vs {t}");
1360        }
1361    }
1362
1363    /// Tests operations against the two provided [`i256`]
1364    fn test_ops(il: i256, ir: i256) {
1365        let bl = BigInt::from_signed_bytes_le(&il.to_le_bytes());
1366        let br = BigInt::from_signed_bytes_le(&ir.to_le_bytes());
1367
1368        // Comparison
1369        assert_eq!(il.cmp(&ir), bl.cmp(&br), "{bl} cmp {br}");
1370
1371        // Conversions
1372        assert_eq!(i256::from_le_bytes(il.to_le_bytes()), il);
1373        assert_eq!(i256::from_be_bytes(il.to_be_bytes()), il);
1374        assert_eq!(i256::from_le_bytes(ir.to_le_bytes()), ir);
1375        assert_eq!(i256::from_be_bytes(ir.to_be_bytes()), ir);
1376
1377        // To i128
1378        assert_eq!(il.to_i128(), bl.to_i128(), "{bl}");
1379        assert_eq!(ir.to_i128(), br.to_i128(), "{br}");
1380
1381        // Absolute value
1382        let (abs, overflow) = i256::from_bigint_with_overflow(bl.abs());
1383        assert_eq!(il.wrapping_abs(), abs);
1384        assert_eq!(il.checked_abs().is_none(), overflow);
1385
1386        let (abs, overflow) = i256::from_bigint_with_overflow(br.abs());
1387        assert_eq!(ir.wrapping_abs(), abs);
1388        assert_eq!(ir.checked_abs().is_none(), overflow);
1389
1390        // Negation
1391        let (neg, overflow) = i256::from_bigint_with_overflow(bl.clone().neg());
1392        assert_eq!(il.wrapping_neg(), neg);
1393        assert_eq!(il.checked_neg().is_none(), overflow);
1394
1395        // Negation
1396        let (neg, overflow) = i256::from_bigint_with_overflow(br.clone().neg());
1397        assert_eq!(ir.wrapping_neg(), neg);
1398        assert_eq!(ir.checked_neg().is_none(), overflow);
1399
1400        // Addition
1401        let actual = il.wrapping_add(ir);
1402        let (expected, overflow) = i256::from_bigint_with_overflow(bl.clone() + br.clone());
1403        assert_eq!(actual, expected);
1404        assert_eq!(il.overflowing_add(ir), (expected, overflow));
1405
1406        let checked = il.checked_add(ir);
1407        match overflow {
1408            true => assert!(checked.is_none()),
1409            false => assert_eq!(checked, Some(actual)),
1410        }
1411
1412        // Subtraction
1413        let actual = il.wrapping_sub(ir);
1414        let (expected, overflow) = i256::from_bigint_with_overflow(bl.clone() - br.clone());
1415        assert_eq!(actual.to_string(), expected.to_string());
1416        assert_eq!(il.overflowing_sub(ir), (expected, overflow));
1417
1418        let checked = il.checked_sub(ir);
1419        match overflow {
1420            true => assert!(checked.is_none()),
1421            false => assert_eq!(checked, Some(actual), "{bl} - {br} = {expected}"),
1422        }
1423
1424        // Multiplication
1425        let actual = il.wrapping_mul(ir);
1426        let (expected, overflow) = i256::from_bigint_with_overflow(bl.clone() * br.clone());
1427        assert_eq!(actual.to_string(), expected.to_string());
1428
1429        let checked = il.checked_mul(ir);
1430        match overflow {
1431            true => assert!(
1432                checked.is_none(),
1433                "{il} * {ir} = {actual} vs {bl} * {br} = {expected}"
1434            ),
1435            false => assert_eq!(
1436                checked,
1437                Some(actual),
1438                "{il} * {ir} = {actual} vs {bl} * {br} = {expected}"
1439            ),
1440        }
1441
1442        // Division
1443        if ir != i256::ZERO {
1444            let actual = il.wrapping_div(ir);
1445            let expected = bl.clone() / br.clone();
1446            let checked = il.checked_div(ir);
1447
1448            if ir == i256::MINUS_ONE && il == i256::MIN {
1449                // BigInt produces an integer over i256::MAX
1450                assert_eq!(actual, i256::MIN);
1451                assert!(checked.is_none());
1452            } else {
1453                assert_eq!(actual.to_string(), expected.to_string());
1454                assert_eq!(checked.unwrap().to_string(), expected.to_string());
1455            }
1456        } else {
1457            // `wrapping_div` panics on division by zero
1458            assert!(il.checked_div(ir).is_none());
1459        }
1460
1461        // Remainder
1462        if ir != i256::ZERO {
1463            let actual = il.wrapping_rem(ir);
1464            let expected = bl.clone() % br.clone();
1465            let checked = il.checked_rem(ir);
1466
1467            assert_eq!(actual.to_string(), expected.to_string(), "{il} % {ir}");
1468
1469            if ir == i256::MINUS_ONE && il == i256::MIN {
1470                assert!(checked.is_none());
1471            } else {
1472                assert_eq!(checked.unwrap().to_string(), expected.to_string());
1473            }
1474        } else {
1475            // `wrapping_rem` panics on division by zero
1476            assert!(il.checked_rem(ir).is_none());
1477        }
1478
1479        // Exponentiation
1480        for exp in [0, 1, 2, 3, 8, 100] {
1481            let actual = il.wrapping_pow(exp);
1482            let (expected, overflow) = i256::from_bigint_with_overflow(bl.clone().pow(exp));
1483            assert_eq!(actual.to_string(), expected.to_string());
1484
1485            let checked = il.checked_pow(exp);
1486            match overflow {
1487                true => assert!(
1488                    checked.is_none(),
1489                    "{il} ^ {exp} = {actual} vs {bl} * {exp} = {expected}"
1490                ),
1491                false => assert_eq!(
1492                    checked,
1493                    Some(actual),
1494                    "{il} ^ {exp} = {actual} vs {bl} ^ {exp} = {expected}"
1495                ),
1496            }
1497        }
1498
1499        // Bit operations
1500        let actual = il & ir;
1501        let (expected, _) = i256::from_bigint_with_overflow(bl.clone() & br.clone());
1502        assert_eq!(actual.to_string(), expected.to_string());
1503
1504        let actual = il | ir;
1505        let (expected, _) = i256::from_bigint_with_overflow(bl.clone() | br.clone());
1506        assert_eq!(actual.to_string(), expected.to_string());
1507
1508        let actual = il ^ ir;
1509        let (expected, _) = i256::from_bigint_with_overflow(bl.clone() ^ br);
1510        assert_eq!(actual.to_string(), expected.to_string());
1511
1512        for shift in [0_u8, 1, 4, 126, 128, 129, 254, 255] {
1513            let actual = il << shift;
1514            let (expected, _) = i256::from_bigint_with_overflow(bl.clone() << shift);
1515            assert_eq!(actual.to_string(), expected.to_string());
1516
1517            let wrapping_actual = <i256 as WrappingShl>::wrapping_shl(&il, shift as u32);
1518            assert_eq!(wrapping_actual.to_string(), expected.to_string());
1519
1520            let actual = il >> shift;
1521            let (expected, _) = i256::from_bigint_with_overflow(bl.clone() >> shift);
1522            assert_eq!(actual.to_string(), expected.to_string());
1523
1524            let wrapping_actual = <i256 as WrappingShr>::wrapping_shr(&il, shift as u32);
1525            assert_eq!(wrapping_actual.to_string(), expected.to_string());
1526
1527            // Check wrapping of the shift argument
1528            let wrapping_actual = <i256 as WrappingShr>::wrapping_shr(&il, 512 + shift as u32);
1529            assert_eq!(wrapping_actual.to_string(), expected.to_string());
1530        }
1531    }
1532
1533    #[test]
1534    fn test_overflowing_add() {
1535        const POSITIVE_OVERFLOW: (i256, bool) = i256::MAX.overflowing_add(i256::ONE);
1536        const NEGATIVE_OVERFLOW: (i256, bool) = i256::MIN.overflowing_add(i256::MINUS_ONE);
1537
1538        assert_eq!(POSITIVE_OVERFLOW, (i256::MIN, true));
1539        assert_eq!(NEGATIVE_OVERFLOW, (i256::MAX, true));
1540        assert_eq!(
1541            i256::from_parts(u128::MAX, 0).overflowing_add(i256::ONE),
1542            (i256::from_parts(0, 1), false)
1543        );
1544        assert_eq!(
1545            i256::ONE.overflowing_add(i256::from_i128(2)),
1546            (i256::from_i128(3), false)
1547        );
1548    }
1549
1550    #[test]
1551    fn test_overflowing_sub() {
1552        const NEGATIVE_OVERFLOW: (i256, bool) = i256::MIN.overflowing_sub(i256::ONE);
1553        const POSITIVE_OVERFLOW: (i256, bool) = i256::MAX.overflowing_sub(i256::MINUS_ONE);
1554
1555        assert_eq!(NEGATIVE_OVERFLOW, (i256::MAX, true));
1556        assert_eq!(POSITIVE_OVERFLOW, (i256::MIN, true));
1557        assert_eq!(
1558            i256::from_parts(0, 1).overflowing_sub(i256::ONE),
1559            (i256::from_parts(u128::MAX, 0), false)
1560        );
1561        assert_eq!(
1562            i256::from_i128(3).overflowing_sub(i256::from_i128(2)),
1563            (i256::ONE, false)
1564        );
1565    }
1566
1567    #[test]
1568    #[cfg_attr(miri, ignore)]
1569    fn test_i256() {
1570        let candidates = [
1571            i256::ZERO,
1572            i256::ONE,
1573            i256::MINUS_ONE,
1574            ConstZero::ZERO,
1575            ConstOne::ONE,
1576            i256::from_i128(2),
1577            i256::from_i128(-2),
1578            i256::from_parts(u128::MAX, 1),
1579            i256::from_parts(u128::MAX, -1),
1580            i256::from_parts(0, 1),
1581            i256::from_parts(0, -1),
1582            i256::from_parts(1, -1),
1583            i256::from_parts(1, 1),
1584            i256::from_parts(0, i128::MAX),
1585            i256::from_parts(0, i128::MIN),
1586            i256::from_parts(1, i128::MAX),
1587            i256::from_parts(1, i128::MIN),
1588            i256::from_parts(u128::MAX, i128::MIN),
1589            i256::from_parts(100, 32),
1590            i256::MIN,
1591            i256::MAX,
1592            i256::MIN >> 1,
1593            i256::MAX >> 1,
1594            i256::ONE << 127,
1595            i256::ONE << 128,
1596            i256::ONE << 129,
1597            i256::MINUS_ONE << 127,
1598            i256::MINUS_ONE << 128,
1599            i256::MINUS_ONE << 129,
1600        ];
1601
1602        for il in candidates {
1603            for ir in candidates {
1604                test_ops(il, ir)
1605            }
1606        }
1607    }
1608
1609    #[test]
1610    fn test_signed_ops() {
1611        // signum
1612        assert_eq!(i256::from_i128(1).signum(), i256::ONE);
1613        assert_eq!(i256::from_i128(0).signum(), i256::ZERO);
1614        assert_eq!(i256::from_i128(-0).signum(), i256::ZERO);
1615        assert_eq!(i256::from_i128(-1).signum(), i256::MINUS_ONE);
1616
1617        // is_positive
1618        assert!(i256::from_i128(1).is_positive());
1619        assert!(!i256::from_i128(0).is_positive());
1620        assert!(!i256::from_i128(-0).is_positive());
1621        assert!(!i256::from_i128(-1).is_positive());
1622
1623        // is_negative
1624        assert!(!i256::from_i128(1).is_negative());
1625        assert!(!i256::from_i128(0).is_negative());
1626        assert!(!i256::from_i128(-0).is_negative());
1627        assert!(i256::from_i128(-1).is_negative());
1628    }
1629
1630    #[test]
1631    #[cfg_attr(miri, ignore)]
1632    fn test_i256_fuzz() {
1633        let mut rng = rng();
1634
1635        for _ in 0..1000 {
1636            let mut l = [0_u8; 32];
1637            let len = rng.random_range(0..32);
1638            l.iter_mut().take(len).for_each(|x| *x = rng.random());
1639
1640            let mut r = [0_u8; 32];
1641            let len = rng.random_range(0..32);
1642            r.iter_mut().take(len).for_each(|x| *x = rng.random());
1643
1644            test_ops(i256::from_le_bytes(l), i256::from_le_bytes(r))
1645        }
1646    }
1647
1648    #[test]
1649    fn test_i256_to_primitive() {
1650        let a = i256::MAX;
1651        assert!(a.to_i64().is_none());
1652        assert!(a.to_u64().is_none());
1653
1654        let a = i256::from_i128(i128::MAX);
1655        assert!(a.to_i64().is_none());
1656        assert!(a.to_u64().is_none());
1657
1658        let a = i256::from_i128(i64::MAX as i128);
1659        assert_eq!(a.to_i64().unwrap(), i64::MAX);
1660        assert_eq!(a.to_u64().unwrap(), i64::MAX as u64);
1661
1662        let a = i256::from_i128(i64::MAX as i128 + 1);
1663        assert!(a.to_i64().is_none());
1664        assert_eq!(a.to_u64().unwrap(), i64::MAX as u64 + 1);
1665
1666        let a = i256::MIN;
1667        assert!(a.to_i64().is_none());
1668        assert!(a.to_u64().is_none());
1669
1670        let a = i256::from_i128(i128::MIN);
1671        assert!(a.to_i64().is_none());
1672        assert!(a.to_u64().is_none());
1673
1674        let a = i256::from_i128(i64::MIN as i128);
1675        assert_eq!(a.to_i64().unwrap(), i64::MIN);
1676        assert!(a.to_u64().is_none());
1677
1678        let a = i256::from_i128(i64::MIN as i128 - 1);
1679        assert!(a.to_i64().is_none());
1680        assert!(a.to_u64().is_none());
1681    }
1682
1683    #[test]
1684    fn test_i256_as_i128() {
1685        let a = i256::from_i128(i128::MAX).wrapping_add(i256::from_i128(1));
1686        let i128 = a.as_i128();
1687        assert_eq!(i128, i128::MIN);
1688
1689        let a = i256::from_i128(i128::MAX).wrapping_add(i256::from_i128(2));
1690        let i128 = a.as_i128();
1691        assert_eq!(i128, i128::MIN + 1);
1692
1693        let a = i256::from_i128(i128::MIN).wrapping_sub(i256::from_i128(1));
1694        let i128 = a.as_i128();
1695        assert_eq!(i128, i128::MAX);
1696
1697        let a = i256::from_i128(i128::MIN).wrapping_sub(i256::from_i128(2));
1698        let i128 = a.as_i128();
1699        assert_eq!(i128, i128::MAX - 1);
1700    }
1701
1702    #[test]
1703    fn test_string_roundtrip() {
1704        let roundtrip_cases = [
1705            i256::ZERO,
1706            i256::ONE,
1707            i256::MINUS_ONE,
1708            i256::from_i128(123456789),
1709            i256::from_i128(-123456789),
1710            i256::from_i128(i128::MIN),
1711            i256::from_i128(i128::MAX),
1712            i256::MIN,
1713            i256::MAX,
1714        ];
1715        for case in roundtrip_cases {
1716            let formatted = case.to_string();
1717            let back: i256 = formatted.parse().unwrap();
1718            assert_eq!(case, back);
1719        }
1720    }
1721
1722    #[test]
1723    fn test_from_string() {
1724        let cases = [
1725            (
1726                "000000000000000000000000000000000000000011",
1727                Some(i256::from_i128(11)),
1728            ),
1729            (
1730                "-000000000000000000000000000000000000000011",
1731                Some(i256::from_i128(-11)),
1732            ),
1733            (
1734                "-0000000000000000000000000000000000000000123456789",
1735                Some(i256::from_i128(-123456789)),
1736            ),
1737            ("-", None),
1738            ("+", None),
1739            ("--1", None),
1740            ("-+1", None),
1741            ("000000000000000000000000000000000000000", Some(i256::ZERO)),
1742            ("0000000000000000000000000000000000000000-11", None),
1743            ("11-1111111111111111111111111111111111111", None),
1744            (
1745                "115792089237316195423570985008687907853269984665640564039457584007913129639936",
1746                None,
1747            ),
1748        ];
1749        for (case, expected) in cases {
1750            assert_eq!(i256::from_string(case), expected)
1751        }
1752    }
1753
1754    #[expect(clippy::op_ref)]
1755    fn test_reference_op(il: i256, ir: i256) {
1756        let r1 = il + ir;
1757        let r2 = &il + ir;
1758        let r3 = il + &ir;
1759        let r4 = &il + &ir;
1760        assert_eq!(r1, r2);
1761        assert_eq!(r1, r3);
1762        assert_eq!(r1, r4);
1763
1764        let r1 = il - ir;
1765        let r2 = &il - ir;
1766        let r3 = il - &ir;
1767        let r4 = &il - &ir;
1768        assert_eq!(r1, r2);
1769        assert_eq!(r1, r3);
1770        assert_eq!(r1, r4);
1771
1772        let r1 = il * ir;
1773        let r2 = &il * ir;
1774        let r3 = il * &ir;
1775        let r4 = &il * &ir;
1776        assert_eq!(r1, r2);
1777        assert_eq!(r1, r3);
1778        assert_eq!(r1, r4);
1779
1780        let r1 = il / ir;
1781        let r2 = &il / ir;
1782        let r3 = il / &ir;
1783        let r4 = &il / &ir;
1784        assert_eq!(r1, r2);
1785        assert_eq!(r1, r3);
1786        assert_eq!(r1, r4);
1787    }
1788
1789    #[test]
1790    fn test_i256_reference_op() {
1791        let candidates = [
1792            i256::ONE,
1793            i256::MINUS_ONE,
1794            i256::from_i128(2),
1795            i256::from_i128(-2),
1796            i256::from_i128(3),
1797            i256::from_i128(-3),
1798        ];
1799
1800        for il in candidates {
1801            for ir in candidates {
1802                test_reference_op(il, ir)
1803            }
1804        }
1805    }
1806
1807    #[test]
1808    #[cfg_attr(miri, ignore)]
1809    fn test_decimal256_to_f64_typical_values() {
1810        let v = i256::from_i128(42_i128);
1811        assert_eq!(v.to_f64().unwrap(), 42.0);
1812
1813        let v = i256::from_i128(-123456789012345678i128);
1814        assert_eq!(v.to_f64().unwrap(), -123_456_789_012_345_680.0);
1815
1816        let v = i256::from_string("0").unwrap();
1817        assert_eq!(v.to_f64().unwrap(), 0.0);
1818
1819        let v = i256::from_string("1").unwrap();
1820        assert_eq!(v.to_f64().unwrap(), 1.0);
1821
1822        let mut rng = rng();
1823        for _ in 0..10 {
1824            let f64_value =
1825                (rng.random_range(i128::MIN..i128::MAX) as f64) * rng.random_range(0.0..1.0);
1826            let big = i256::from_f64(f64_value).unwrap();
1827            assert_eq!(big.to_f64().unwrap(), f64_value);
1828        }
1829    }
1830
1831    #[test]
1832    fn test_decimal256_to_f64_large_positive_value() {
1833        let max_f = f64::MAX;
1834        let big = i256::from_f64(max_f * 2.0).unwrap_or(i256::MAX);
1835        let out = big.to_f64().unwrap();
1836        assert!(out.is_finite() && out.is_sign_positive());
1837    }
1838
1839    #[test]
1840    fn test_decimal256_to_f64_large_negative_value() {
1841        let max_f = f64::MAX;
1842        let big_neg = i256::from_f64(-(max_f * 2.0)).unwrap_or(i256::MIN);
1843        let out = big_neg.to_f64().unwrap();
1844        assert!(out.is_finite() && out.is_sign_negative());
1845    }
1846
1847    #[test]
1848    fn test_num_traits() {
1849        let value = i256::from_i128(-5);
1850        assert_eq!(
1851            <i256 as CheckedNeg>::checked_neg(&value),
1852            Some(i256::from(5))
1853        );
1854
1855        assert_eq!(
1856            <i256 as CheckedAdd>::checked_add(&value, &value),
1857            Some(i256::from(-10))
1858        );
1859
1860        assert_eq!(
1861            <i256 as CheckedSub>::checked_sub(&value, &value),
1862            Some(i256::from(0))
1863        );
1864
1865        assert_eq!(
1866            <i256 as CheckedMul>::checked_mul(&value, &value),
1867            Some(i256::from(25))
1868        );
1869
1870        assert_eq!(
1871            <i256 as CheckedDiv>::checked_div(&value, &value),
1872            Some(i256::from(1))
1873        );
1874
1875        assert_eq!(
1876            <i256 as CheckedRem>::checked_rem(&value, &value),
1877            Some(i256::from(0))
1878        );
1879
1880        assert_eq!(
1881            <i256 as WrappingAdd>::wrapping_add(&value, &value),
1882            i256::from(-10)
1883        );
1884
1885        assert_eq!(
1886            <i256 as WrappingSub>::wrapping_sub(&value, &value),
1887            i256::from(0)
1888        );
1889
1890        assert_eq!(
1891            <i256 as WrappingMul>::wrapping_mul(&value, &value),
1892            i256::from(25)
1893        );
1894
1895        assert_eq!(<i256 as WrappingNeg>::wrapping_neg(&value), i256::from(5));
1896
1897        // A single check for wrapping behavior, rely on trait implementation for others
1898        let result = <i256 as WrappingAdd>::wrapping_add(&i256::MAX, &i256::ONE);
1899        assert_eq!(result, i256::MIN);
1900
1901        // Saturating operations
1902        assert_eq!(i256::MAX.saturating_add(&i256::ONE), i256::MAX);
1903        assert_eq!(i256::MIN.saturating_sub(&i256::ONE), i256::MIN);
1904        assert_eq!(i256::MIN.saturating_add(&i256::MINUS_ONE), i256::MIN);
1905        assert_eq!(i256::MAX.saturating_sub(&i256::MINUS_ONE), i256::MAX);
1906        assert_eq!(i256::MAX.saturating_mul(&i256::MAX), i256::MAX);
1907        assert_eq!(i256::MAX.saturating_mul(&i256::MIN), i256::MIN);
1908        assert_eq!(i256::MIN.saturating_mul(&i256::MAX), i256::MIN);
1909        assert_eq!(i256::MIN.saturating_mul(&i256::MIN), i256::MAX);
1910        assert_eq!(i256::MIN.saturating_mul(&i256::ONE), i256::MIN);
1911        assert_eq!(i256::MIN.saturating_mul(&i256::MINUS_ONE), i256::MAX);
1912        assert_eq!(
1913            i256::from(20).saturating_add(&i256::from(5)),
1914            i256::from(25)
1915        );
1916        assert_eq!(
1917            i256::from(20).saturating_sub(&i256::from(5)),
1918            i256::from(15)
1919        );
1920        assert_eq!(
1921            i256::from(20).saturating_mul(&i256::from(5)),
1922            i256::from(100)
1923        );
1924
1925        // Mul-add
1926        assert_eq!(
1927            i256::from(20).mul_add(i256::from(5), i256::from(10)),
1928            i256::from(110)
1929        );
1930
1931        let mut mul_add_value = i256::from(20);
1932        mul_add_value.mul_add_assign(i256::from(5), i256::from(10));
1933        assert_eq!(mul_add_value, i256::from(110));
1934
1935        let value = i256::from(-5);
1936        assert_eq!(<i256 as Signed>::abs(&value), i256::from(5));
1937
1938        assert_eq!(<i256 as One>::one(), i256::from(1));
1939        assert_eq!(<i256 as Zero>::zero(), i256::from(0));
1940
1941        assert_eq!(<i256 as Bounded>::min_value(), i256::MIN);
1942        assert_eq!(<i256 as Bounded>::max_value(), i256::MAX);
1943
1944        // Bitwise not
1945        assert_eq!(!i256::ZERO, i256::MINUS_ONE);
1946        assert_eq!(!i256::MINUS_ONE, i256::ZERO);
1947        assert_eq!(!i256::ONE, i256::from_parts(u128::MAX - 1, -1));
1948    }
1949
1950    #[should_panic(expected = "rhs overflow for shift")]
1951    #[test]
1952    fn test_shl_panic_on_arg_overflow() {
1953        let value = i256::from(123);
1954        let rhs = std::hint::black_box(500);
1955        let _ = value << rhs;
1956    }
1957
1958    #[test]
1959    fn test_numtraits_from_str_radix() {
1960        assert_eq!(
1961            i256::from_str_radix("123456789", 10).expect("parsed"),
1962            i256::from(123456789)
1963        );
1964        assert_eq!(
1965            i256::from_str_radix("0", 10).expect("parsed"),
1966            i256::from(0)
1967        );
1968        assert!(i256::from_str_radix("abc", 10).is_err());
1969        assert!(i256::from_str_radix("0", 16).is_err());
1970    }
1971
1972    #[test]
1973    fn test_leading_zeros() {
1974        // Without high part
1975        assert_eq!(i256::from(0).leading_zeros(), 256);
1976        assert_eq!(i256::from(1).leading_zeros(), 256 - 1);
1977        assert_eq!(i256::from(16).leading_zeros(), 256 - 5);
1978        assert_eq!(i256::from(17).leading_zeros(), 256 - 5);
1979
1980        // With high part
1981        assert_eq!(i256::from_parts(2, 16).leading_zeros(), 128 - 5);
1982        assert_eq!(i256::from_parts(2, i128::MAX).leading_zeros(), 1);
1983
1984        assert_eq!(i256::MAX.leading_zeros(), 1);
1985        assert_eq!(i256::from(-1).leading_zeros(), 0);
1986    }
1987
1988    #[test]
1989    fn test_trailing_zeros() {
1990        // Without high part
1991        assert_eq!(i256::from(0).trailing_zeros(), 256);
1992        assert_eq!(i256::from(2).trailing_zeros(), 1);
1993        assert_eq!(i256::from(16).trailing_zeros(), 4);
1994        assert_eq!(i256::from(17).trailing_zeros(), 0);
1995        // With high part
1996        assert_eq!(i256::from_parts(0, i128::MAX).trailing_zeros(), 128);
1997        assert_eq!(i256::from_parts(0, 16).trailing_zeros(), 128 + 4);
1998        assert_eq!(i256::from_parts(2, i128::MAX).trailing_zeros(), 1);
1999
2000        assert_eq!(i256::MAX.trailing_zeros(), 0);
2001        assert_eq!(i256::from(-1).trailing_zeros(), 0);
2002    }
2003
2004    #[test]
2005    fn test_ilog() {
2006        let value = i256::from(128);
2007
2008        // log2
2009        assert_eq!(value.ilog(i256::from(2)), 7);
2010        assert_eq!(value.ilog2(), 7);
2011
2012        // log10
2013        assert_eq!(value.ilog(i256::from(10)), 2);
2014        assert_eq!(value.ilog10(), 2);
2015
2016        // negative base
2017        assert_eq!(value.checked_ilog(i256::from(-2)), None);
2018        assert_eq!(value.checked_ilog(i256::from(-10)), None);
2019        assert_eq!(value.checked_ilog(i256::from(0)), None);
2020        assert_eq!(value.checked_ilog(i256::from(1)), None);
2021
2022        // negative self
2023        let neg_value = i256::from(-128);
2024        assert_eq!(neg_value.checked_ilog(i256::from(2)), None);
2025        assert_eq!(neg_value.checked_ilog(i256::from(10)), None);
2026        assert_eq!(neg_value.checked_ilog10(), None);
2027        assert_eq!(neg_value.checked_ilog2(), None);
2028
2029        // zero self
2030        assert_eq!(i256::ZERO.checked_ilog(i256::from(2)), None);
2031        assert_eq!(i256::ZERO.checked_ilog(i256::from(10)), None);
2032        assert_eq!(i256::ZERO.checked_ilog10(), None);
2033        assert_eq!(i256::ZERO.checked_ilog2(), None);
2034
2035        // self == base, matches std: `n.ilog(n) == 1`
2036        assert_eq!(i256::from(2).checked_ilog(i256::from(2)), Some(1));
2037        assert_eq!(i256::from(3).checked_ilog(i256::from(3)), Some(1));
2038        assert_eq!(i256::from(5).checked_ilog(i256::from(5)), Some(1));
2039        assert_eq!(i256::from(1000).checked_ilog(i256::from(1000)), Some(1));
2040        assert_eq!(i256::from(2).checked_ilog2(), Some(1));
2041        assert_eq!(i256::from(2).ilog2(), 1);
2042        // base 10 goes through the checked_ilog10 fast path
2043        assert_eq!(i256::from(10).checked_ilog(i256::from(10)), Some(1));
2044
2045        // self < base is 0
2046        assert_eq!(i256::from(3).checked_ilog(i256::from(5)), Some(0));
2047
2048        // cross-check small results (0 and 1) against u128::ilog
2049        for base in [2i64, 3, 5, 7, 1000] {
2050            for v in 1i64..64 {
2051                let want = (v as u128).ilog(base as u128);
2052                assert_eq!(
2053                    i256::from(v).checked_ilog(i256::from(base)),
2054                    Some(want),
2055                    "checked_ilog({v}, {base})"
2056                );
2057            }
2058        }
2059
2060        let value = i256::from_parts(100000000, 1234);
2061        assert_eq!(value.checked_ilog(i256::from(10)), Some(41));
2062        assert_eq!(value.checked_ilog10(), Some(41));
2063
2064        // Large i256 values
2065        let large = i256::from_parts(100000000, i128::MAX);
2066        // log2 of 2 powered to approximately 255 should be 254
2067        assert_eq!(large.checked_ilog(i256::from(2)), Some(254));
2068
2069        // log10(large)=76
2070        assert_eq!(large.checked_ilog(i256::from(10)), Some(76));
2071        assert_eq!(large.checked_ilog10(), Some(76));
2072
2073        // log5(large)
2074        assert_eq!(large.checked_ilog(i256::from(5)), Some(109));
2075
2076        // Maximum representable value is 2^254
2077        assert!(i256::from(2).checked_pow(255).is_none());
2078        let value = i256::from(2).checked_pow(254).expect("construct");
2079        assert_eq!(value.checked_ilog(i256::from(2)), Some(254));
2080
2081        // Logarithm of a maximum representable value is 254
2082        assert_eq!(i256::MAX.checked_ilog(i256::from(2)), Some(254));
2083    }
2084
2085    #[test]
2086    fn test_ilog10() {
2087        // Edge cases
2088        assert_eq!(i256::ZERO.checked_ilog10(), None);
2089        assert_eq!(i256::MINUS_ONE.checked_ilog10(), None);
2090        assert_eq!(i256::MAX.checked_ilog10(), Some(76));
2091        assert_eq!(i256::from(10).checked_ilog10(), Some(1));
2092
2093        // small values
2094        assert_eq!(i256::from(1).checked_ilog10(), Some(0));
2095        assert_eq!(i256::from(9).checked_ilog10(), Some(0));
2096
2097        // case with high == 0
2098        assert_eq!(i256::from(100).checked_ilog10(), Some(2));
2099        // case with high == 0 and full low
2100        assert_eq!(i256::from_parts(u128::MAX, 0).checked_ilog10(), Some(38));
2101
2102        // case with high > 0
2103        assert_eq!(i256::from_parts(0, 1).checked_ilog10(), Some(38));
2104
2105        // case with non-null high and low, slow branch
2106        let pow50 = i256::from(10).checked_pow(50).unwrap();
2107        assert_eq!(pow50.checked_ilog10(), Some(50));
2108
2109        // case with non-null high and low, fast branch
2110        let pow64 = i256::from(10).checked_pow(64).unwrap();
2111        assert_eq!(pow64.checked_ilog10(), Some(64));
2112    }
2113
2114    #[test]
2115    #[should_panic(expected = "ilog10 overflow")]
2116    fn test_ilog10_zero_panics() {
2117        let _ = i256::ZERO.ilog10();
2118    }
2119
2120    #[test]
2121    #[should_panic(expected = "ilog overflow")]
2122    fn test_ilog_zero_panics() {
2123        let _ = i256::ZERO.ilog(i256::from(5));
2124    }
2125
2126    #[test]
2127    #[should_panic(expected = "ilog2 overflow")]
2128    fn test_ilog2_zero_panics() {
2129        let _ = i256::ZERO.ilog2();
2130    }
2131}