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