vortex_scalar/bigint/
mod.rs

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