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