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
}