## Coverage Report

#### Created: 2025-08-26 07:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)

    /Users/andrewlamb/Software/arrow-rs/arrow-buffer/src/bigint/mod.rs

    Line
    Count
    Source
    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
    18
    use crate::arith::derive_arith;
    19
    use crate::bigint::div::div_rem;
    20
    use num::cast::AsPrimitive;
    21
    use num::{BigInt, FromPrimitive, ToPrimitive};
    22
    use std::cmp::Ordering;
    23
    use std::num::ParseIntError;
    24
    use std::ops::{BitAnd, BitOr, BitXor, Neg, Shl, Shr};
    25
    use std::str::FromStr;
    26
    27
    mod div;
    28
    29
    /// An opaque error similar to [`std::num::ParseIntError`]
    30
    #[derive(Debug)]
    31
    pub struct ParseI256Error {}
    32
    33
    impl From<ParseIntError> for ParseI256Error {
    34
    0
        fn from(_: ParseIntError) -> Self {
    35
    0
            Self {}
    36
    0
        }
    37
    }
    38
    39
    impl std::fmt::Display for ParseI256Error {
    40
    0
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    41
    0
            write!(f, "Failed to parse as i256")
    42
    0
        }
    43
    }
    44
    impl std::error::Error for ParseI256Error {}
    45
    46
    /// Error returned by i256::DivRem
    47
    enum DivRemError {
    48
        /// Division by zero
    49
        DivideByZero,
    50
        /// Division overflow
    51
        DivideOverflow,
    52
    }
    53
    54
    /// A signed 256-bit integer
    55
    #[allow(non_camel_case_types)]
    56
    #[derive(Copy, Clone, Default, Eq, PartialEq, Hash)]
    57
    #[repr(C)]
    58
    pub struct i256 {
    59
        low: u128,
    60
        high: i128,
    61
    }
    62
    63
    impl std::fmt::Debug for i256 {
    64
    0
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    65
    0
            write!(f, "{self}")
    66
    0
        }
    67
    }
    68
    69
    impl std::fmt::Display for i256 {
    70
    2
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    71
    2
            write!(f, "{}", BigInt::from_signed_bytes_le(&self.to_le_bytes()))
    72
    2
        }
    73
    }
    74
    75
    impl FromStr for i256 {
    76
        type Err = ParseI256Error;
    77
    78
    0
        fn from_str(s: &str) -> Result<Self, Self::Err> {
    79
            // i128 can store up to 38 decimal digits
    80
    0
            if s.len() <= 38 {
    81
    0
                return Ok(Self::from_i128(i128::from_str(s)?));
    82
    0
            }
    83
    84
    0
            let (negative, s) = match s.as_bytes()[0] {
    85
    0
                b'-' => (true, &s[1..]),
    86
    0
                b'+' => (false, &s[1..]),
    87
    0
                _ => (false, s),
    88
            };
    89
    90
            // Trim leading 0s
    91
    0
            let s = s.trim_start_matches('0');
    92
    0
            if s.is_empty() {
    93
    0
                return Ok(i256::ZERO);
    94
    0
            }
    95
    96
    0
            if !s.as_bytes()[0].is_ascii_digit() {
    97
                // Ensures no duplicate sign
    98
    0
                return Err(ParseI256Error {});
    99
    0
            }
    100
    101
    0
            parse_impl(s, negative)
    102
    0
        }
    103
    }
    104
    105
    impl From<i8> for i256 {
    106
    0
        fn from(value: i8) -> Self {
    107
    0
            Self::from_i128(value.into())
    108
    0
        }
    109
    }
    110
    111
    impl From<i16> for i256 {
    112
    0
        fn from(value: i16) -> Self {
    113
    0
            Self::from_i128(value.into())
    114
    0
        }
    115
    }
    116
    117
    impl From<i32> for i256 {
    118
    0
        fn from(value: i32) -> Self {
    119
    0
            Self::from_i128(value.into())
    120
    0
        }
    121
    }
    122
    123
    impl From<i64> for i256 {
    124
    0
        fn from(value: i64) -> Self {
    125
    0
            Self::from_i128(value.into())
    126
    0
        }
    127
    }
    128
    129
    /// Parse `s` with any sign and leading 0s removed
    130
    0
    fn parse_impl(s: &str, negative: bool) -> Result<i256, ParseI256Error> {
    131
    0
        if s.len() <= 38 {
    132
    0
            let low = i128::from_str(s)?;
    133
    0
            return Ok(match negative {
    134
    0
                true => i256::from_parts(low.neg() as _, -1),
    135
    0
                false => i256::from_parts(low as _, 0),
    136
            });
    137
    0
        }
    138
    139
    0
        let split = s.len() - 38;
    140
    0
        if !s.as_bytes()[split].is_ascii_digit() {
    141
            // Ensures not splitting codepoint and no sign
    142
    0
            return Err(ParseI256Error {});
    143
    0
        }
    144
    0
        let (hs, ls) = s.split_at(split);
    145
    146
    0
        let mut low = i128::from_str(ls)?;
    147
    0
        let high = parse_impl(hs, negative)?;
    148
    149
    0
        if negative {
    150
    0
            low = -low;
    151
    0
        }
    152
    153
    0
        let low = i256::from_i128(low);
    154
    155
    0
        high.checked_mul(i256::from_i128(10_i128.pow(38)))
    156
    0
            .and_then(|high| high.checked_add(low))
    157
    0
            .ok_or(ParseI256Error {})
    158
    0
    }
    159
    160
    impl PartialOrd for i256 {
    161
    0
        fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
    162
    0
            Some(self.cmp(other))
    163
    0
        }
    164
    }
    165
    166
    impl Ord for i256 {
    167
    0
        fn cmp(&self, other: &Self) -> Ordering {
    168
            // This is 25x faster than using a variable length encoding such
    169
            // as BigInt as it avoids allocation and branching
    170
    0
            self.high.cmp(&other.high).then(self.low.cmp(&other.low))
    171
    0
        }
    172
    }
    173
    174
    impl i256 {
    175
        /// The additive identity for this integer type, i.e. `0`.
    176
        pub const ZERO: Self = i256 { low: 0, high: 0 };
    177
    178
        /// The multiplicative identity for this integer type, i.e. `1`.
    179
        pub const ONE: Self = i256 { low: 1, high: 0 };
    180
    181
        /// The multiplicative inverse for this integer type, i.e. `-1`.
    182
        pub const MINUS_ONE: Self = i256 {
    183
            low: u128::MAX,
    184
            high: -1,
    185
        };
    186
    187
        /// The maximum value that can be represented by this integer type
    188
        pub const MAX: Self = i256 {
    189
            low: u128::MAX,
    190
            high: i128::MAX,
    191
        };
    192
    193
        /// The minimum value that can be represented by this integer type
    194
        pub const MIN: Self = i256 {
    195
            low: u128::MIN,
    196
            high: i128::MIN,
    197
        };
    198
    199
        /// Create an integer value from its representation as a byte array in little-endian.
    200
        #[inline]
    201
    0
        pub const fn from_le_bytes(b: [u8; 32]) -> Self {
    202
    0
            let (low, high) = split_array(b);
    203
    0
            Self {
    204
    0
                high: i128::from_le_bytes(high),
    205
    0
                low: u128::from_le_bytes(low),
    206
    0
            }
    207
    0
        }
    208
    209
        /// Create an integer value from its representation as a byte array in big-endian.
    210
        #[inline]
    211
    2
        pub const fn from_be_bytes(b: [u8; 32]) -> Self {
    212
    2
            let (high, low) = split_array(b);
    213
    2
            Self {
    214
    2
                high: i128::from_be_bytes(high),
    215
    2
                low: u128::from_be_bytes(low),
    216
    2
            }
    217
    2
        }
    218
    219
        /// Create an `i256` value from a 128-bit value.
    220
    0
        pub const fn from_i128(v: i128) -> Self {
    221
    0
            Self::from_parts(v as u128, v >> 127)
    222
    0
        }
    223
    224
        /// Create an integer value from its representation as string.
    225
        #[inline]
    226
    0
        pub fn from_string(value_str: &str) -> Option<Self> {
    227
    0
            value_str.parse().ok()
    228
    0
        }
    229
    230
        /// Create an optional i256 from the provided `f64`. Returning `None`
    231
        /// if overflow occurred
    232
    0
        pub fn from_f64(v: f64) -> Option<Self> {
    233
    0
            BigInt::from_f64(v).and_then(|i| {
    234
    0
                let (integer, overflow) = i256::from_bigint_with_overflow(i);
    235
    0
                if overflow {
    236
    0
                    None
    237
                } else {
    238
    0
                    Some(integer)
    239
                }
    240
    0
            })
    241
    0
        }
    242
    243
        /// Create an i256 from the provided low u128 and high i128
    244
        #[inline]
    245
    0
        pub const fn from_parts(low: u128, high: i128) -> Self {
    246
    0
            Self { low, high }
    247
    0
        }
    248
    249
        /// Returns this `i256` as a low u128 and high i128
    250
    0
        pub const fn to_parts(self) -> (u128, i128) {
    251
    0
            (self.low, self.high)
    252
    0
        }
    253
    254
        /// Converts this `i256` into an `i128` returning `None` if this would result
    255
        /// in truncation/overflow
    256
    0
        pub fn to_i128(self) -> Option<i128> {
    257
    0
            let as_i128 = self.low as i128;
    258
    259
    0
            let high_negative = self.high < 0;
    260
    0
            let low_negative = as_i128 < 0;
    261
    0
            let high_valid = self.high == -1 || self.high == 0;
    262
    263
    0
            (high_negative == low_negative && high_valid).then_some(self.low as i128)
    264
    0
        }
    265
    266
        /// Wraps this `i256` into an `i128`
    267
    0
        pub fn as_i128(self) -> i128 {
    268
    0
            self.low as i128
    269
    0
        }
    270
    271
        /// Return the memory representation of this integer as a byte array in little-endian byte order.
    272
        #[inline]
    273
    2
        pub const fn to_le_bytes(self) -> [u8; 32] {
    274
    2
            let low = self.low.to_le_bytes();
    275
    2
            let high = self.high.to_le_bytes();
    276
    2
            let mut t = [0; 32];
    277
    2
            let mut i = 0;
    278
    34
            while i != 16 {
    279
    32
                t[i] = low[i];
    280
    32
                t[i + 16] = high[i];
    281
    32
                i += 1;
    282
    32
            }
    283
    2
            t
    284
    2
        }
    285
    286
        /// Return the memory representation of this integer as a byte array in big-endian byte order.
    287
        #[inline]
    288
    0
        pub const fn to_be_bytes(self) -> [u8; 32] {
    289
    0
            let low = self.low.to_be_bytes();
    290
    0
            let high = self.high.to_be_bytes();
    291
    0
            let mut t = [0; 32];
    292
    0
            let mut i = 0;
    293
    0
            while i != 16 {
    294
    0
                t[i] = high[i];
    295
    0
                t[i + 16] = low[i];
    296
    0
                i += 1;
    297
    0
            }
    298
    0
            t
    299
    0
        }
    300
    301
        /// Create an i256 from the provided [`BigInt`] returning a bool indicating
    302
        /// if overflow occurred
    303
    0
        fn from_bigint_with_overflow(v: BigInt) -> (Self, bool) {
    304
    0
            let v_bytes = v.to_signed_bytes_le();
    305
    0
            match v_bytes.len().cmp(&32) {
    306
                Ordering::Less => {
    307
    0
                    let mut bytes = if num::Signed::is_negative(&v) {
    308
    0
                        [255_u8; 32]
    309
                    } else {
    310
    0
                        [0; 32]
    311
                    };
    312
    0
                    bytes[0..v_bytes.len()].copy_from_slice(&v_bytes[..v_bytes.len()]);
    313
    0
                    (Self::from_le_bytes(bytes), false)
    314
                }
    315
    0
                Ordering::Equal => (Self::from_le_bytes(v_bytes.try_into().unwrap()), false),
    316
    0
                Ordering::Greater => (Self::from_le_bytes(v_bytes[..32].try_into().unwrap()), true),
    317
            }
    318
    0
        }
    319
    320
        /// Computes the absolute value of this i256
    321
        #[inline]
    322
    0
        pub fn wrapping_abs(self) -> Self {
    323
            // -1 if negative, otherwise 0
    324
    0
            let sa = self.high >> 127;
    325
    0
            let sa = Self::from_parts(sa as u128, sa);
    326
    327
            // Inverted if negative
    328
    0
            Self::from_parts(self.low ^ sa.low, self.high ^ sa.high).wrapping_sub(sa)
    329
    0
        }
    330
    331
        /// Computes the absolute value of this i256 returning `None` if `Self == Self::MIN`
    332
        #[inline]
    333
    0
        pub fn checked_abs(self) -> Option<Self> {
    334
    0
            (self != Self::MIN).then(|| self.wrapping_abs())
    335
    0
        }
    336
    337
        /// Negates this i256
    338
        #[inline]
    339
    0
        pub fn wrapping_neg(self) -> Self {
    340
    0
            Self::from_parts(!self.low, !self.high).wrapping_add(i256::ONE)
    341
    0
        }
    342
    343
        /// Negates this i256 returning `None` if `Self == Self::MIN`
    344
        #[inline]
    345
    0
        pub fn checked_neg(self) -> Option<Self> {
    346
    0
            (self != Self::MIN).then(|| self.wrapping_neg())
    347
    0
        }
    348
    349
        /// Performs wrapping addition
    350
        #[inline]
    351
    0
        pub fn wrapping_add(self, other: Self) -> Self {
    352
    0
            let (low, carry) = self.low.overflowing_add(other.low);
    353
    0
            let high = self.high.wrapping_add(other.high).wrapping_add(carry as _);
    354
    0
            Self { low, high }
    355
    0
        }
    356
    357
        /// Performs checked addition
    358
        #[inline]
    359
    0
        pub fn checked_add(self, other: Self) -> Option<Self> {
    360
    0
            let r = self.wrapping_add(other);
    361
    0
            ((other.is_negative() && r < self) || (!other.is_negative() && r >= self)).then_some(r)
    362
    0
        }
    363
    364
        /// Performs wrapping subtraction
    365
        #[inline]
    366
    0
        pub fn wrapping_sub(self, other: Self) -> Self {
    367
    0
            let (low, carry) = self.low.overflowing_sub(other.low);
    368
    0
            let high = self.high.wrapping_sub(other.high).wrapping_sub(carry as _);
    369
    0
            Self { low, high }
    370
    0
        }
    371
    372
        /// Performs checked subtraction
    373
        #[inline]
    374
    0
        pub fn checked_sub(self, other: Self) -> Option<Self> {
    375
    0
            let r = self.wrapping_sub(other);
    376
    0
            ((other.is_negative() && r > self) || (!other.is_negative() && r <= self)).then_some(r)
    377
    0
        }
    378
    379
        /// Performs wrapping multiplication
    380
        #[inline]
    381
    0
        pub fn wrapping_mul(self, other: Self) -> Self {
    382
    0
            let (low, high) = mulx(self.low, other.low);
    383
    384
            // Compute the high multiples, only impacting the high 128-bits
    385
    0
            let hl = self.high.wrapping_mul(other.low as i128);
    386
    0
            let lh = (self.low as i128).wrapping_mul(other.high);
    387
    388
    0
            Self {
    389
    0
                low,
    390
    0
                high: (high as i128).wrapping_add(hl).wrapping_add(lh),
    391
    0
            }
    392
    0
        }
    393
    394
        /// Performs checked multiplication
    395
        #[inline]
    396
    0
        pub fn checked_mul(self, other: Self) -> Option<Self> {
    397
    0
            if self == i256::ZERO || other == i256::ZERO {
    398
    0
                return Some(i256::ZERO);
    399
    0
            }
    400
    401
            // Shift sign bit down to construct mask of all set bits if negative
    402
    0
            let l_sa = self.high >> 127;
    403
    0
            let r_sa = other.high >> 127;
    404
    0
            let out_sa = (l_sa ^ r_sa) as u128;
    405
    406
            // Compute absolute values
    407
    0
            let l_abs = self.wrapping_abs();
    408
    0
            let r_abs = other.wrapping_abs();
    409
    410
            // Overflow if both high parts are non-zero
    411
    0
            if l_abs.high != 0 && r_abs.high != 0 {
    412
    0
                return None;
    413
    0
            }
    414
    415
            // Perform checked multiplication on absolute values
    416
    0
            let (low, high) = mulx(l_abs.low, r_abs.low);
    417
    418
            // Compute the high multiples, only impacting the high 128-bits
    419
    0
            let hl = (l_abs.high as u128).checked_mul(r_abs.low)?;
    420
    0
            let lh = l_abs.low.checked_mul(r_abs.high as u128)?;
    421
    422
    0
            let high = high.checked_add(hl)?.checked_add(lh)?;
    423
    424
            // Reverse absolute value, if necessary
    425
    0
            let (low, c) = (low ^ out_sa).overflowing_sub(out_sa);
    426
    0
            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
    0
            (high.is_negative() == (self.is_negative() ^ other.is_negative()))
    430
    0
                .then_some(Self { low, high })
    431
    0
        }
    432
    433
        /// Division operation, returns (quotient, remainder).
    434
        /// This basically implements [Long division]: `<https://en.wikipedia.org/wiki/Division_algorithm>`
    435
        #[inline]
    436
    0
        fn div_rem(self, other: Self) -> Result<(Self, Self), DivRemError> {
    437
    0
            if other == Self::ZERO {
    438
    0
                return Err(DivRemError::DivideByZero);
    439
    0
            }
    440
    0
            if other == Self::MINUS_ONE && self == Self::MIN {
    441
    0
                return Err(DivRemError::DivideOverflow);
    442
    0
            }
    443
    444
    0
            let a = self.wrapping_abs();
    445
    0
            let b = other.wrapping_abs();
    446
    447
    0
            let (div, rem) = div_rem(&a.as_digits(), &b.as_digits());
    448
    0
            let div = Self::from_digits(div);
    449
    0
            let rem = Self::from_digits(rem);
    450
    451
            Ok((
    452
    0
                if self.is_negative() == other.is_negative() {
    453
    0
                    div
    454
                } else {
    455
    0
                    div.wrapping_neg()
    456
                },
    457
    0
                if self.is_negative() {
    458
    0
                    rem.wrapping_neg()
    459
                } else {
    460
    0
                    rem
    461
                },
    462
            ))
    463
    0
        }
    464
    465
        /// Interpret this [`i256`] as 4 `u64` digits, least significant first
    466
    0
        fn as_digits(self) -> [u64; 4] {
    467
    0
            [
    468
    0
                self.low as u64,
    469
    0
                (self.low >> 64) as u64,
    470
    0
                self.high as u64,
    471
    0
                (self.high as u128 >> 64) as u64,
    472
    0
            ]
    473
    0
        }
    474
    475
        /// Interpret 4 `u64` digits, least significant first, as a [`i256`]
    476
    0
        fn from_digits(digits: [u64; 4]) -> Self {
    477
    0
            Self::from_parts(
    478
    0
                digits[0] as u128 | ((digits[1] as u128) << 64),
    479
    0
                digits[2] as i128 | ((digits[3] as i128) << 64),
    480
            )
    481
    0
        }
    482
    483
        /// Performs wrapping division
    484
        #[inline]
    485
    0
        pub fn wrapping_div(self, other: Self) -> Self {
    486
    0
            match self.div_rem(other) {
    487
    0
                Ok((v, _)) => v,
    488
    0
                Err(DivRemError::DivideByZero) => panic!("attempt to divide by zero"),
    489
    0
                Err(_) => Self::MIN,
    490
            }
    491
    0
        }
    492
    493
        /// Performs checked division
    494
        #[inline]
    495
    0
        pub fn checked_div(self, other: Self) -> Option<Self> {
    496
    0
            self.div_rem(other).map(|(v, _)| v).ok()
    497
    0
        }
    498
    499
        /// Performs wrapping remainder
    500
        #[inline]
    501
    0
        pub fn wrapping_rem(self, other: Self) -> Self {
    502
    0
            match self.div_rem(other) {
    503
    0
                Ok((_, v)) => v,
    504
    0
                Err(DivRemError::DivideByZero) => panic!("attempt to divide by zero"),
    505
    0
                Err(_) => Self::ZERO,
    506
            }
    507
    0
        }
    508
    509
        /// Performs checked remainder
    510
        #[inline]
    511
    0
        pub fn checked_rem(self, other: Self) -> Option<Self> {
    512
    0
            self.div_rem(other).map(|(_, v)| v).ok()
    513
    0
        }
    514
    515
        /// Performs checked exponentiation
    516
        #[inline]
    517
    0
        pub fn checked_pow(self, mut exp: u32) -> Option<Self> {
    518
    0
            if exp == 0 {
    519
    0
                return Some(i256::from_i128(1));
    520
    0
            }
    521
    522
    0
            let mut base = self;
    523
    0
            let mut acc: Self = i256::from_i128(1);
    524
    525
    0
            while exp > 1 {
    526
    0
                if (exp & 1) == 1 {
    527
    0
                    acc = acc.checked_mul(base)?;
    528
    0
                }
    529
    0
                exp /= 2;
    530
    0
                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
    0
            acc.checked_mul(base)
    537
    0
        }
    538
    539
        /// Performs wrapping exponentiation
    540
        #[inline]
    541
    0
        pub fn wrapping_pow(self, mut exp: u32) -> Self {
    542
    0
            if exp == 0 {
    543
    0
                return i256::from_i128(1);
    544
    0
            }
    545
    546
    0
            let mut base = self;
    547
    0
            let mut acc: Self = i256::from_i128(1);
    548
    549
    0
            while exp > 1 {
    550
    0
                if (exp & 1) == 1 {
    551
    0
                    acc = acc.wrapping_mul(base);
    552
    0
                }
    553
    0
                exp /= 2;
    554
    0
                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
    0
            acc.wrapping_mul(base)
    562
    0
        }
    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
    0
        pub const fn signum(self) -> Self {
    570
    0
            if self.is_positive() {
    571
    0
                i256::ONE
    572
    0
            } else if self.is_negative() {
    573
    0
                i256::MINUS_ONE
    574
            } else {
    575
    0
                i256::ZERO
    576
            }
    577
    0
        }
    578
    579
        /// Returns `true` if this [`i256`] is negative
    580
        #[inline]
    581
    0
        pub const fn is_negative(self) -> bool {
    582
    0
            self.high.is_negative()
    583
    0
        }
    584
    585
        /// Returns `true` if this [`i256`] is positive
    586
    0
        pub const fn is_positive(self) -> bool {
    587
    0
            self.high.is_positive() || self.high == 0 && self.low != 0
    588
    0
        }
    589
    }
    590
    591
    /// Temporary workaround due to lack of stable const array slicing
    592
    /// See <https://github.com/rust-lang/rust/issues/90091>
    593
    2
    const fn split_array<const N: usize, const M: usize>(vals: [u8; N]) -> ([u8; M], [u8; M]) {
    594
    2
        let mut a = [0; M];
    595
    2
        let mut b = [0; M];
    596
    2
        let mut i = 0;
    597
    34
        while i != M {
    598
    32
            a[i] = vals[i];
    599
    32
            b[i] = vals[i + M];
    600
    32
            i += 1;
    601
    32
        }
    602
    2
        (a, b)
    603
    2
    }
    604
    605
    /// Performs an unsigned multiplication of `a * b` returning a tuple of
    606
    /// `(low, high)` where `low` contains the lower 128-bits of the result
    607
    /// and `high` the higher 128-bits
    608
    ///
    609
    /// This mirrors the x86 mulx instruction but for 128-bit types
    610
    #[inline]
    611
    0
    fn mulx(a: u128, b: u128) -> (u128, u128) {
    612
    0
        let split = |a: u128| (a & (u64::MAX as u128), a >> 64);
    613
    614
        const MASK: u128 = u64::MAX as _;
    615
    616
    0
        let (a_low, a_high) = split(a);
    617
    0
        let (b_low, b_high) = split(b);
    618
    619
        // Carry stores the upper 64-bits of low and lower 64-bits of high
    620
    0
        let (mut low, mut carry) = split(a_low * b_low);
    621
    0
        carry += a_high * b_low;
    622
    623
        // Update low and high with corresponding parts of carry
    624
    0
        low += carry << 64;
    625
    0
        let mut high = carry >> 64;
    626
    627
        // Update carry with overflow from low
    628
    0
        carry = low >> 64;
    629
    0
        low &= MASK;
    630
    631
        // Perform multiply including overflow from low
    632
    0
        carry += b_high * a_low;
    633
    634
        // Update low and high with values from carry
    635
    0
        low += carry << 64;
    636
    0
        high += carry >> 64;
    637
    638
        // Perform 4th multiplication
    639
    0
        high += a_high * b_high;
    640
    641
    0
        (low, high)
    642
    0
    }
    643
    644
    derive_arith!(
    645
        i256,
    646
        Add,
    647
        AddAssign,
    648
        add,
    649
        add_assign,
    650
        wrapping_add,
    651
        checked_add
    652
    );
    653
    derive_arith!(
    654
        i256,
    655
        Sub,
    656
        SubAssign,
    657
        sub,
    658
        sub_assign,
    659
        wrapping_sub,
    660
        checked_sub
    661
    );
    662
    derive_arith!(
    663
        i256,
    664
        Mul,
    665
        MulAssign,
    666
        mul,
    667
        mul_assign,
    668
        wrapping_mul,
    669
        checked_mul
    670
    );
    671
    derive_arith!(
    672
        i256,
    673
        Div,
    674
        DivAssign,
    675
        div,
    676
        div_assign,
    677
        wrapping_div,
    678
        checked_div
    679
    );
    680
    derive_arith!(
    681
        i256,
    682
        Rem,
    683
        RemAssign,
    684
        rem,
    685
        rem_assign,
    686
        wrapping_rem,
    687
        checked_rem
    688
    );
    689
    690
    impl Neg for i256 {
    691
        type Output = i256;
    692
    693
        #[cfg(debug_assertions)]
    694
    0
        fn neg(self) -> Self::Output {
    695
    0
            self.checked_neg().expect("i256 overflow")
    696
    0
        }
    697
    698
        #[cfg(not(debug_assertions))]
    699
        fn neg(self) -> Self::Output {
    700
            self.wrapping_neg()
    701
        }
    702
    }
    703
    704
    impl BitAnd for i256 {
    705
        type Output = i256;
    706
    707
        #[inline]
    708
        fn bitand(self, rhs: Self) -> Self::Output {
    709
            Self {
    710
                low: self.low & rhs.low,
    711
                high: self.high & rhs.high,
    712
            }
    713
        }
    714
    }
    715
    716
    impl BitOr for i256 {
    717
        type Output = i256;
    718
    719
        #[inline]
    720
        fn bitor(self, rhs: Self) -> Self::Output {
    721
            Self {
    722
                low: self.low | rhs.low,
    723
                high: self.high | rhs.high,
    724
            }
    725
        }
    726
    }
    727
    728
    impl BitXor for i256 {
    729
        type Output = i256;
    730
    731
        #[inline]
    732
        fn bitxor(self, rhs: Self) -> Self::Output {
    733
            Self {
    734
                low: self.low ^ rhs.low,
    735
                high: self.high ^ rhs.high,
    736
            }
    737
        }
    738
    }
    739
    740
    impl Shl<u8> for i256 {
    741
        type Output = i256;
    742
    743
        #[inline]
    744
        fn shl(self, rhs: u8) -> Self::Output {
    745
            if rhs == 0 {
    746
                self
    747
            } else if rhs < 128 {
    748
                Self {
    749
                    high: (self.high << rhs) | (self.low >> (128 - rhs)) as i128,
    750
                    low: self.low << rhs,
    751
                }
    752
            } else {
    753
                Self {
    754
                    high: (self.low << (rhs - 128)) as i128,
    755
                    low: 0,
    756
                }
    757
            }
    758
        }
    759
    }
    760
    761
    impl Shr<u8> for i256 {
    762
        type Output = i256;
    763
    764
        #[inline]
    765
        fn shr(self, rhs: u8) -> Self::Output {
    766
            if rhs == 0 {
    767
                self
    768
            } else if rhs < 128 {
    769
                Self {
    770
                    high: self.high >> rhs,
    771
                    low: (self.low >> rhs) | ((self.high as u128) << (128 - rhs)),
    772
                }
    773
            } else {
    774
                Self {
    775
                    high: self.high >> 127,
    776
                    low: (self.high >> (rhs - 128)) as u128,
    777
                }
    778
            }
    779
        }
    780
    }
    781
    782
    macro_rules! define_as_primitive {
    783
        ($native_ty:ty) => {
    784
            impl AsPrimitive<i256> for $native_ty {
    785
    0
                fn as_(self) -> i256 {
    786
    0
                    i256::from_i128(self as i128)
    787
    0
                }
    788
            }
    789
        };
    790
    }
    791
    792
    define_as_primitive!(i8);
    793
    define_as_primitive!(i16);
    794
    define_as_primitive!(i32);
    795
    define_as_primitive!(i64);
    796
    define_as_primitive!(u8);
    797
    define_as_primitive!(u16);
    798
    define_as_primitive!(u32);
    799
    define_as_primitive!(u64);
    800
    801
    impl ToPrimitive for i256 {
    802
    0
        fn to_i64(&self) -> Option<i64> {
    803
    0
            let as_i128 = self.low as i128;
    804
    805
    0
            let high_negative = self.high < 0;
    806
    0
            let low_negative = as_i128 < 0;
    807
    0
            let high_valid = self.high == -1 || self.high == 0;
    808
    809
    0
            if high_negative == low_negative && high_valid {
    810
    0
                let (low_bytes, high_bytes) = split_array(u128::to_le_bytes(self.low));
    811
    0
                let high = i64::from_le_bytes(high_bytes);
    812
    0
                let low = i64::from_le_bytes(low_bytes);
    813
    814
    0
                let high_negative = high < 0;
    815
    0
                let low_negative = low < 0;
    816
    0
                let high_valid = self.high == -1 || self.high == 0;
    817
    818
    0
                (high_negative == low_negative && high_valid).then_some(low)
    819
            } else {
    820
    0
                None
    821
            }
    822
    0
        }
    823
    824
    0
        fn to_f64(&self) -> Option<f64> {
    825
    0
            let mag = if let Some(u) = self.checked_abs() {
    826
    0
                let (low, high) = u.to_parts();
    827
    0
                (high as f64) * 2_f64.powi(128) + (low as f64)
    828
            } else {
    829
                // self == MIN
    830
    0
                2_f64.powi(255)
    831
            };
    832
    0
            if *self < i256::ZERO {
    833
    0
                Some(-mag)
    834
            } else {
    835
    0
                Some(mag)
    836
            }
    837
    0
        }
    838
    0
        fn to_u64(&self) -> Option<u64> {
    839
    0
            let as_i128 = self.low as i128;
    840
    841
    0
            let high_negative = self.high < 0;
    842
    0
            let low_negative = as_i128 < 0;
    843
    0
            let high_valid = self.high == -1 || self.high == 0;
    844
    845
    0
            if high_negative == low_negative && high_valid {
    846
    0
                self.low.to_u64()
    847
            } else {
    848
    0
                None
    849
            }
    850
    0
        }
    851
    }
    852
    853
    #[cfg(all(test, not(miri)))] // llvm.x86.subborrow.64 not supported by MIRI
    854
    mod tests {
    855
        use super::*;
    856
        use num::Signed;
    857
        use rand::{rng, Rng};
    858
    859
        #[test]
    860
        fn test_signed_cmp() {
    861
            let a = i256::from_parts(i128::MAX as u128, 12);
    862
            let b = i256::from_parts(i128::MIN as u128, 12);
    863
            assert!(a < b);
    864
    865
            let a = i256::from_parts(i128::MAX as u128, 12);
    866
            let b = i256::from_parts(i128::MIN as u128, -12);
    867
            assert!(a > b);
    868
        }
    869
    870
        #[test]
    871
        fn test_to_i128() {
    872
            let vals = [
    873
                BigInt::from_i128(-1).unwrap(),
    874
                BigInt::from_i128(i128::MAX).unwrap(),
    875
                BigInt::from_i128(i128::MIN).unwrap(),
    876
                BigInt::from_u128(u128::MIN).unwrap(),
    877
                BigInt::from_u128(u128::MAX).unwrap(),
    878
            ];
    879
    880
            for v in vals {
    881
                let (t, overflow) = i256::from_bigint_with_overflow(v.clone());
    882
                assert!(!overflow);
    883
                assert_eq!(t.to_i128(), v.to_i128(), "{v} vs {t}");
    884
            }
    885
        }
    886
    887
        /// Tests operations against the two provided [`i256`]
    888
        fn test_ops(il: i256, ir: i256) {
    889
            let bl = BigInt::from_signed_bytes_le(&il.to_le_bytes());
    890
            let br = BigInt::from_signed_bytes_le(&ir.to_le_bytes());
    891
    892
            // Comparison
    893
            assert_eq!(il.cmp(&ir), bl.cmp(&br), "{bl} cmp {br}");
    894
    895
            // Conversions
    896
            assert_eq!(i256::from_le_bytes(il.to_le_bytes()), il);
    897
            assert_eq!(i256::from_be_bytes(il.to_be_bytes()), il);
    898
            assert_eq!(i256::from_le_bytes(ir.to_le_bytes()), ir);
    899
            assert_eq!(i256::from_be_bytes(ir.to_be_bytes()), ir);
    900
    901
            // To i128
    902
            assert_eq!(il.to_i128(), bl.to_i128(), "{bl}");
    903
            assert_eq!(ir.to_i128(), br.to_i128(), "{br}");
    904
    905
            // Absolute value
    906
            let (abs, overflow) = i256::from_bigint_with_overflow(bl.abs());
    907
            assert_eq!(il.wrapping_abs(), abs);
    908
            assert_eq!(il.checked_abs().is_none(), overflow);
    909
    910
            let (abs, overflow) = i256::from_bigint_with_overflow(br.abs());
    911
            assert_eq!(ir.wrapping_abs(), abs);
    912
            assert_eq!(ir.checked_abs().is_none(), overflow);
    913
    914
            // Negation
    915
            let (neg, overflow) = i256::from_bigint_with_overflow(bl.clone().neg());
    916
            assert_eq!(il.wrapping_neg(), neg);
    917
            assert_eq!(il.checked_neg().is_none(), overflow);
    918
    919
            // Negation
    920
            let (neg, overflow) = i256::from_bigint_with_overflow(br.clone().neg());
    921
            assert_eq!(ir.wrapping_neg(), neg);
    922
            assert_eq!(ir.checked_neg().is_none(), overflow);
    923
    924
            // Addition
    925
            let actual = il.wrapping_add(ir);
    926
            let (expected, overflow) = i256::from_bigint_with_overflow(bl.clone() + br.clone());
    927
            assert_eq!(actual, expected);
    928
    929
            let checked = il.checked_add(ir);
    930
            match overflow {
    931
                true => assert!(checked.is_none()),
    932
                false => assert_eq!(checked, Some(actual)),
    933
            }
    934
    935
            // Subtraction
    936
            let actual = il.wrapping_sub(ir);
    937
            let (expected, overflow) = i256::from_bigint_with_overflow(bl.clone() - br.clone());
    938
            assert_eq!(actual.to_string(), expected.to_string());
    939
    940
            let checked = il.checked_sub(ir);
    941
            match overflow {
    942
                true => assert!(checked.is_none()),
    943
                false => assert_eq!(checked, Some(actual), "{bl} - {br} = {expected}"),
    944
            }
    945
    946
            // Multiplication
    947
            let actual = il.wrapping_mul(ir);
    948
            let (expected, overflow) = i256::from_bigint_with_overflow(bl.clone() * br.clone());
    949
            assert_eq!(actual.to_string(), expected.to_string());
    950
    951
            let checked = il.checked_mul(ir);
    952
            match overflow {
    953
                true => assert!(
    954
                    checked.is_none(),
    955
                    "{il} * {ir} = {actual} vs {bl} * {br} = {expected}"
    956
                ),
    957
                false => assert_eq!(
    958
                    checked,
    959
                    Some(actual),
    960
                    "{il} * {ir} = {actual} vs {bl} * {br} = {expected}"
    961
                ),
    962
            }
    963
    964
            // Division
    965
            if ir != i256::ZERO {
    966
                let actual = il.wrapping_div(ir);
    967
                let expected = bl.clone() / br.clone();
    968
                let checked = il.checked_div(ir);
    969
    970
                if ir == i256::MINUS_ONE && il == i256::MIN {
    971
                    // BigInt produces an integer over i256::MAX
    972
                    assert_eq!(actual, i256::MIN);
    973
                    assert!(checked.is_none());
    974
                } else {
    975
                    assert_eq!(actual.to_string(), expected.to_string());
    976
                    assert_eq!(checked.unwrap().to_string(), expected.to_string());
    977
                }
    978
            } else {
    979
                // `wrapping_div` panics on division by zero
    980
                assert!(il.checked_div(ir).is_none());
    981
            }
    982
    983
            // Remainder
    984
            if ir != i256::ZERO {
    985
                let actual = il.wrapping_rem(ir);
    986
                let expected = bl.clone() % br.clone();
    987
                let checked = il.checked_rem(ir);
    988
    989
                assert_eq!(actual.to_string(), expected.to_string(), "{il} % {ir}");
    990
    991
                if ir == i256::MINUS_ONE && il == i256::MIN {
    992
                    assert!(checked.is_none());
    993
                } else {
    994
                    assert_eq!(checked.unwrap().to_string(), expected.to_string());
    995
                }
    996
            } else {
    997
                // `wrapping_rem` panics on division by zero
    998
                assert!(il.checked_rem(ir).is_none());
    999
            }
    1000
    1001
            // Exponentiation
    1002
            for exp in vec![0, 1, 2, 3, 8, 100].into_iter() {
    1003
                let actual = il.wrapping_pow(exp);
    1004
                let (expected, overflow) = i256::from_bigint_with_overflow(bl.clone().pow(exp));
    1005
                assert_eq!(actual.to_string(), expected.to_string());
    1006
    1007
                let checked = il.checked_pow(exp);
    1008
                match overflow {
    1009
                    true => assert!(
    1010
                        checked.is_none(),
    1011
                        "{il} ^ {exp} = {actual} vs {bl} * {exp} = {expected}"
    1012
                    ),
    1013
                    false => assert_eq!(
    1014
                        checked,
    1015
                        Some(actual),
    1016
                        "{il} ^ {exp} = {actual} vs {bl} ^ {exp} = {expected}"
    1017
                    ),
    1018
                }
    1019
            }
    1020
    1021
            // Bit operations
    1022
            let actual = il & ir;
    1023
            let (expected, _) = i256::from_bigint_with_overflow(bl.clone() & br.clone());
    1024
            assert_eq!(actual.to_string(), expected.to_string());
    1025
    1026
            let actual = il | ir;
    1027
            let (expected, _) = i256::from_bigint_with_overflow(bl.clone() | br.clone());
    1028
            assert_eq!(actual.to_string(), expected.to_string());
    1029
    1030
            let actual = il ^ ir;
    1031
            let (expected, _) = i256::from_bigint_with_overflow(bl.clone() ^ br);
    1032
            assert_eq!(actual.to_string(), expected.to_string());
    1033
    1034
            for shift in [0_u8, 1, 4, 126, 128, 129, 254, 255] {
    1035
                let actual = il << shift;
    1036
                let (expected, _) = i256::from_bigint_with_overflow(bl.clone() << shift);
    1037
                assert_eq!(actual.to_string(), expected.to_string());
    1038
    1039
                let actual = il >> shift;
    1040
                let (expected, _) = i256::from_bigint_with_overflow(bl.clone() >> shift);
    1041
                assert_eq!(actual.to_string(), expected.to_string());
    1042
            }
    1043
        }
    1044
    1045
        #[test]
    1046
        fn test_i256() {
    1047
            let candidates = [
    1048
                i256::ZERO,
    1049
                i256::ONE,
    1050
                i256::MINUS_ONE,
    1051
                i256::from_i128(2),
    1052
                i256::from_i128(-2),
    1053
                i256::from_parts(u128::MAX, 1),
    1054
                i256::from_parts(u128::MAX, -1),
    1055
                i256::from_parts(0, 1),
    1056
                i256::from_parts(0, -1),
    1057
                i256::from_parts(1, -1),
    1058
                i256::from_parts(1, 1),
    1059
                i256::from_parts(0, i128::MAX),
    1060
                i256::from_parts(0, i128::MIN),
    1061
                i256::from_parts(1, i128::MAX),
    1062
                i256::from_parts(1, i128::MIN),
    1063
                i256::from_parts(u128::MAX, i128::MIN),
    1064
                i256::from_parts(100, 32),
    1065
                i256::MIN,
    1066
                i256::MAX,
    1067
                i256::MIN >> 1,
    1068
                i256::MAX >> 1,
    1069
                i256::ONE << 127,
    1070
                i256::ONE << 128,
    1071
                i256::ONE << 129,
    1072
                i256::MINUS_ONE << 127,
    1073
                i256::MINUS_ONE << 128,
    1074
                i256::MINUS_ONE << 129,
    1075
            ];
    1076
    1077
            for il in candidates {
    1078
                for ir in candidates {
    1079
                    test_ops(il, ir)
    1080
                }
    1081
            }
    1082
        }
    1083
    1084
        #[test]
    1085
        fn test_signed_ops() {
    1086
            // signum
    1087
            assert_eq!(i256::from_i128(1).signum(), i256::ONE);
    1088
            assert_eq!(i256::from_i128(0).signum(), i256::ZERO);
    1089
            assert_eq!(i256::from_i128(-0).signum(), i256::ZERO);
    1090
            assert_eq!(i256::from_i128(-1).signum(), i256::MINUS_ONE);
    1091
    1092
            // is_positive
    1093
            assert!(i256::from_i128(1).is_positive());
    1094
            assert!(!i256::from_i128(0).is_positive());
    1095
            assert!(!i256::from_i128(-0).is_positive());
    1096
            assert!(!i256::from_i128(-1).is_positive());
    1097
    1098
            // is_negative
    1099
            assert!(!i256::from_i128(1).is_negative());
    1100
            assert!(!i256::from_i128(0).is_negative());
    1101
            assert!(!i256::from_i128(-0).is_negative());
    1102
            assert!(i256::from_i128(-1).is_negative());
    1103
        }
    1104
    1105
        #[test]
    1106
        #[cfg_attr(miri, ignore)]
    1107
        fn test_i256_fuzz() {
    1108
            let mut rng = rng();
    1109
    1110
            for _ in 0..1000 {
    1111
                let mut l = [0_u8; 32];
    1112
                let len = rng.random_range(0..32);
    1113
                l.iter_mut().take(len).for_each(|x| *x = rng.random());
    1114
    1115
                let mut r = [0_u8; 32];
    1116
                let len = rng.random_range(0..32);
    1117
                r.iter_mut().take(len).for_each(|x| *x = rng.random());
    1118
    1119
                test_ops(i256::from_le_bytes(l), i256::from_le_bytes(r))
    1120
            }
    1121
        }
    1122
    1123
        #[test]
    1124
        fn test_i256_to_primitive() {
    1125
            let a = i256::MAX;
    1126
            assert!(a.to_i64().is_none());
    1127
            assert!(a.to_u64().is_none());
    1128
    1129
            let a = i256::from_i128(i128::MAX);
    1130
            assert!(a.to_i64().is_none());
    1131
            assert!(a.to_u64().is_none());
    1132
    1133
            let a = i256::from_i128(i64::MAX as i128);
    1134
            assert_eq!(a.to_i64().unwrap(), i64::MAX);
    1135
            assert_eq!(a.to_u64().unwrap(), i64::MAX as u64);
    1136
    1137
            let a = i256::from_i128(i64::MAX as i128 + 1);
    1138
            assert!(a.to_i64().is_none());
    1139
            assert_eq!(a.to_u64().unwrap(), i64::MAX as u64 + 1);
    1140
    1141
            let a = i256::MIN;
    1142
            assert!(a.to_i64().is_none());
    1143
            assert!(a.to_u64().is_none());
    1144
    1145
            let a = i256::from_i128(i128::MIN);
    1146
            assert!(a.to_i64().is_none());
    1147
            assert!(a.to_u64().is_none());
    1148
    1149
            let a = i256::from_i128(i64::MIN as i128);
    1150
            assert_eq!(a.to_i64().unwrap(), i64::MIN);
    1151
            assert!(a.to_u64().is_none());
    1152
    1153
            let a = i256::from_i128(i64::MIN as i128 - 1);
    1154
            assert!(a.to_i64().is_none());
    1155
            assert!(a.to_u64().is_none());
    1156
        }
    1157
    1158
        #[test]
    1159
        fn test_i256_as_i128() {
    1160
            let a = i256::from_i128(i128::MAX).wrapping_add(i256::from_i128(1));
    1161
            let i128 = a.as_i128();
    1162
            assert_eq!(i128, i128::MIN);
    1163
    1164
            let a = i256::from_i128(i128::MAX).wrapping_add(i256::from_i128(2));
    1165
            let i128 = a.as_i128();
    1166
            assert_eq!(i128, i128::MIN + 1);
    1167
    1168
            let a = i256::from_i128(i128::MIN).wrapping_sub(i256::from_i128(1));
    1169
            let i128 = a.as_i128();
    1170
            assert_eq!(i128, i128::MAX);
    1171
    1172
            let a = i256::from_i128(i128::MIN).wrapping_sub(i256::from_i128(2));
    1173
            let i128 = a.as_i128();
    1174
            assert_eq!(i128, i128::MAX - 1);
    1175
        }
    1176
    1177
        #[test]
    1178
        fn test_string_roundtrip() {
    1179
            let roundtrip_cases = [
    1180
                i256::ZERO,
    1181
                i256::ONE,
    1182
                i256::MINUS_ONE,
    1183
                i256::from_i128(123456789),
    1184
                i256::from_i128(-123456789),
    1185
                i256::from_i128(i128::MIN),
    1186
                i256::from_i128(i128::MAX),
    1187
                i256::MIN,
    1188
                i256::MAX,
    1189
            ];
    1190
            for case in roundtrip_cases {
    1191
                let formatted = case.to_string();
    1192
                let back: i256 = formatted.parse().unwrap();
    1193
                assert_eq!(case, back);
    1194
            }
    1195
        }
    1196
    1197
        #[test]
    1198
        fn test_from_string() {
    1199
            let cases = [
    1200
                (
    1201
                    "000000000000000000000000000000000000000011",
    1202
                    Some(i256::from_i128(11)),
    1203
                ),
    1204
                (
    1205
                    "-000000000000000000000000000000000000000011",
    1206
                    Some(i256::from_i128(-11)),
    1207
                ),
    1208
                (
    1209
                    "-0000000000000000000000000000000000000000123456789",
    1210
                    Some(i256::from_i128(-123456789)),
    1211
                ),
    1212
                ("-", None),
    1213
                ("+", None),
    1214
                ("--1", None),
    1215
                ("-+1", None),
    1216
                ("000000000000000000000000000000000000000", Some(i256::ZERO)),
    1217
                ("0000000000000000000000000000000000000000-11", None),
    1218
                ("11-1111111111111111111111111111111111111", None),
    1219
                (
    1220
                    "115792089237316195423570985008687907853269984665640564039457584007913129639936",
    1221
                    None,
    1222
                ),
    1223
            ];
    1224
            for (case, expected) in cases {
    1225
                assert_eq!(i256::from_string(case), expected)
    1226
            }
    1227
        }
    1228
    1229
        #[allow(clippy::op_ref)]
    1230
        fn test_reference_op(il: i256, ir: i256) {
    1231
            let r1 = il + ir;
    1232
            let r2 = &il + ir;
    1233
            let r3 = il + &ir;
    1234
            let r4 = &il + &ir;
    1235
            assert_eq!(r1, r2);
    1236
            assert_eq!(r1, r3);
    1237
            assert_eq!(r1, r4);
    1238
    1239
            let r1 = il - ir;
    1240
            let r2 = &il - ir;
    1241
            let r3 = il - &ir;
    1242
            let r4 = &il - &ir;
    1243
            assert_eq!(r1, r2);
    1244
            assert_eq!(r1, r3);
    1245
            assert_eq!(r1, r4);
    1246
    1247
            let r1 = il * ir;
    1248
            let r2 = &il * ir;
    1249
            let r3 = il * &ir;
    1250
            let r4 = &il * &ir;
    1251
            assert_eq!(r1, r2);
    1252
            assert_eq!(r1, r3);
    1253
            assert_eq!(r1, r4);
    1254
    1255
            let r1 = il / ir;
    1256
            let r2 = &il / ir;
    1257
            let r3 = il / &ir;
    1258
            let r4 = &il / &ir;
    1259
            assert_eq!(r1, r2);
    1260
            assert_eq!(r1, r3);
    1261
            assert_eq!(r1, r4);
    1262
        }
    1263
    1264
        #[test]
    1265
        fn test_i256_reference_op() {
    1266
            let candidates = [
    1267
                i256::ONE,
    1268
                i256::MINUS_ONE,
    1269
                i256::from_i128(2),
    1270
                i256::from_i128(-2),
    1271
                i256::from_i128(3),
    1272
                i256::from_i128(-3),
    1273
            ];
    1274
    1275
            for il in candidates {
    1276
                for ir in candidates {
    1277
                    test_reference_op(il, ir)
    1278
                }
    1279
            }
    1280
        }
    1281
    1282
        #[test]
    1283
        fn test_decimal256_to_f64_typical_values() {
    1284
            let v = i256::from_i128(42_i128);
    1285
            assert_eq!(v.to_f64().unwrap(), 42.0);
    1286
    1287
            let v = i256::from_i128(-123456789012345678i128);
    1288
            assert_eq!(v.to_f64().unwrap(), -123456789012345678.0);
    1289
        }
    1290
    1291
        #[test]
    1292
        fn test_decimal256_to_f64_large_positive_value() {
    1293
            let max_f = f64::MAX;
    1294
            let big = i256::from_f64(max_f * 2.0).unwrap_or(i256::MAX);
    1295
            let out = big.to_f64().unwrap();
    1296
            assert!(out.is_finite() && out.is_sign_positive());
    1297
        }
    1298
    1299
        #[test]
    1300
        fn test_decimal256_to_f64_large_negative_value() {
    1301
            let max_f = f64::MAX;
    1302
            let big_neg = i256::from_f64(-(max_f * 2.0)).unwrap_or(i256::MIN);
    1303
            let out = big_neg.to_f64().unwrap();
    1304
            assert!(out.is_finite() && out.is_sign_negative());
    1305
        }
    1306
    }