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