vortex_scalar/bigint/
mod.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4mod bigcast;
5
6use std::fmt::Display;
7use std::ops::{Add, BitOr, Div, Mul, Rem, Shl, Shr, Sub};
8
9pub use bigcast::*;
10use num_traits::{CheckedAdd, CheckedSub, ConstZero, One, WrappingAdd, WrappingSub, Zero};
11use vortex_error::VortexExpect;
12
13/// Signed 256-bit integer type.
14///
15/// This is one of the physical representations of `DecimalScalar` values and can be safely converted
16/// back and forth with Arrow's [`i256`][arrow_buffer::i256].
17#[repr(transparent)]
18#[allow(non_camel_case_types)]
19#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Hash, PartialOrd, Ord)]
20pub struct i256(arrow_buffer::i256);
21
22#[allow(clippy::same_name_method)]
23impl i256 {
24    /// The zero value for `i256`.
25    pub const ZERO: Self = Self(arrow_buffer::i256::ZERO);
26    /// The one value for `i256`.
27    pub const ONE: Self = Self(arrow_buffer::i256::ONE);
28    /// The maximum value for `i256`.
29    pub const MAX: Self = Self(arrow_buffer::i256::MAX);
30    /// The minimum value for `i256`.
31    pub const MIN: Self = Self(arrow_buffer::i256::MIN);
32
33    /// Construct a new `i256` from an unsigned `lower` bits and a signed `upper` bits.
34    pub const fn from_parts(lower: u128, upper: i128) -> Self {
35        Self(arrow_buffer::i256::from_parts(lower, upper))
36    }
37
38    /// Create an `i256` value from a signed 128-bit value.
39    pub const fn from_i128(i: i128) -> Self {
40        Self(arrow_buffer::i256::from_i128(i))
41    }
42
43    /// Attempts to convert this i256 to an i128.
44    ///
45    /// Returns None if the value is too large to fit in an i128.
46    pub fn maybe_i128(self) -> Option<i128> {
47        self.0.to_i128()
48    }
49
50    /// Create an integer value from its little-endian byte array representation.
51    pub const fn from_le_bytes(bytes: [u8; 32]) -> Self {
52        Self(arrow_buffer::i256::from_le_bytes(bytes))
53    }
54
55    /// Split the 256-bit signed integer value into an unsigned lower bits and a signed upper bits.
56    ///
57    /// This version gives us ownership of the value.
58    pub const fn into_parts(self) -> (u128, i128) {
59        self.0.to_parts()
60    }
61
62    /// Split the 256-bit signed integer value into an unsigned lower bits and a signed upper bits.
63    pub const fn to_parts(&self) -> (u128, i128) {
64        self.0.to_parts()
65    }
66
67    /// Raises self to the power of `exp`, wrapping around on overflow.
68    pub fn wrapping_pow(&self, exp: u32) -> Self {
69        Self(self.0.wrapping_pow(exp))
70    }
71
72    /// Wrapping (modular) addition. Computes `self + other`, wrapping around at the boundary.
73    pub fn wrapping_add(&self, other: Self) -> Self {
74        Self(self.0.wrapping_add(other.0))
75    }
76
77    /// Return the memory representation of this integer as a byte array in little-endian byte order.
78    #[inline]
79    pub const fn to_le_bytes(&self) -> [u8; 32] {
80        self.0.to_le_bytes()
81    }
82
83    /// Return the memory representation of this integer as a byte array in big-endian byte order.
84    #[inline]
85    pub const fn to_be_bytes(&self) -> [u8; 32] {
86        self.0.to_be_bytes()
87    }
88}
89
90impl From<i256> for arrow_buffer::i256 {
91    fn from(i: i256) -> Self {
92        i.0
93    }
94}
95
96impl From<arrow_buffer::i256> for i256 {
97    fn from(i: arrow_buffer::i256) -> Self {
98        Self(i)
99    }
100}
101
102impl Display for i256 {
103    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104        write!(f, "{}", self.0)
105    }
106}
107
108impl Add for i256 {
109    type Output = Self;
110
111    fn add(self, rhs: Self) -> Self::Output {
112        Self(self.0.add(rhs.0))
113    }
114}
115
116impl Sub for i256 {
117    type Output = Self;
118
119    fn sub(self, rhs: Self) -> Self::Output {
120        Self(self.0.sub(rhs.0))
121    }
122}
123
124impl Mul<Self> for i256 {
125    type Output = Self;
126
127    fn mul(self, rhs: Self) -> Self::Output {
128        Self(self.0.mul(rhs.0))
129    }
130}
131
132impl Div<Self> for i256 {
133    type Output = Self;
134
135    fn div(self, rhs: Self) -> Self::Output {
136        Self(self.0.div(rhs.0))
137    }
138}
139
140impl Rem<Self> for i256 {
141    type Output = Self;
142
143    fn rem(self, rhs: Self) -> Self::Output {
144        Self(self.0.rem(rhs.0))
145    }
146}
147
148impl Zero for i256 {
149    fn zero() -> Self {
150        Self::default()
151    }
152
153    fn is_zero(&self) -> bool {
154        *self == Self::zero()
155    }
156}
157
158impl ConstZero for i256 {
159    const ZERO: Self = Self(arrow_buffer::i256::ZERO);
160}
161
162impl One for i256 {
163    fn one() -> Self {
164        Self(arrow_buffer::i256::ONE)
165    }
166}
167
168impl CheckedAdd for i256 {
169    fn checked_add(&self, v: &Self) -> Option<Self> {
170        self.0.checked_add(v.0).map(Self)
171    }
172}
173
174impl WrappingAdd for i256 {
175    fn wrapping_add(&self, v: &Self) -> Self {
176        Self(self.0.wrapping_add(v.0))
177    }
178}
179
180impl CheckedSub for i256 {
181    fn checked_sub(&self, v: &Self) -> Option<Self> {
182        self.0.checked_sub(v.0).map(Self)
183    }
184}
185
186impl WrappingSub for i256 {
187    fn wrapping_sub(&self, v: &Self) -> Self {
188        Self(self.0.wrapping_sub(v.0))
189    }
190}
191
192impl Shr<Self> for i256 {
193    type Output = Self;
194
195    fn shr(self, rhs: Self) -> Self::Output {
196        use num_traits::ToPrimitive;
197
198        Self(
199            self.0.shr(
200                rhs.0
201                    .to_u8()
202                    .vortex_expect("Can't shift more than 256 bits"),
203            ),
204        )
205    }
206}
207
208impl Shl<usize> for i256 {
209    type Output = Self;
210
211    fn shl(self, rhs: usize) -> Self::Output {
212        use num_traits::ToPrimitive;
213        Self(
214            self.0
215                .shl(rhs.to_u8().vortex_expect("Can't shift more than 256 bits")),
216        )
217    }
218}
219
220impl BitOr<Self> for i256 {
221    type Output = Self;
222
223    fn bitor(self, rhs: Self) -> Self::Output {
224        Self(self.0.bitor(rhs.0))
225    }
226}
227
228impl num_traits::ToPrimitive for i256 {
229    fn to_i64(&self) -> Option<i64> {
230        self.maybe_i128().and_then(|v| v.to_i64())
231    }
232
233    fn to_i128(&self) -> Option<i128> {
234        self.maybe_i128()
235    }
236
237    fn to_u64(&self) -> Option<u64> {
238        self.maybe_i128().and_then(|v| v.to_u64())
239    }
240
241    fn to_u128(&self) -> Option<u128> {
242        self.maybe_i128().and_then(|v| v.to_u128())
243    }
244}