Skip to content

Commit 873849f

Browse files
chore[fuzzer]: add u256 to implemented Int for i256 correctly (#3576)
Signed-off-by: Joe Isaacs <[email protected]>
1 parent 776742a commit 873849f

File tree

4 files changed

+240
-25
lines changed

4 files changed

+240
-25
lines changed

Cargo.lock

Lines changed: 124 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,18 +124,19 @@ once_cell = "1.21"
124124
opentelemetry = "0.29.0"
125125
opentelemetry-otlp = "0.29.0"
126126
opentelemetry_sdk = "0.29.0"
127+
parking_lot = { version = "0.12.3", features = ["nightly"] }
127128
parquet = "55.1"
128129
paste = "1.0.15"
129130
pco = "0.4.4"
130131
pin-project = "1.1.5"
131132
pin-project-lite = "0.2.15"
133+
primitive-types = { version = "0.13.1" }
132134
prost = "0.13.4"
133135
prost-build = "0.13.4"
134136
prost-types = "0.13.4"
135137
pyo3 = { version = "0.24.1", features = ["extension-module", "abi3-py310"] }
136138
pyo3-log = "0.12.1"
137139
rand = "0.9.0"
138-
parking_lot = { version = "0.12.3", features = ["nightly"] }
139140
rand_distr = "0.5"
140141
ratatui = "0.29"
141142
rayon = "1.10.0"

vortex-scalar/Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ bytes = { workspace = true }
2121
itertools = { workspace = true }
2222
num-traits = { workspace = true }
2323
paste = { workspace = true }
24+
primitive-types = { workspace = true, optional = true, features = [
25+
"arbitrary",
26+
] }
2427
prost = { workspace = true }
2528
vortex-buffer = { workspace = true }
2629
vortex-dtype = { workspace = true, features = ["arrow"] }
@@ -34,4 +37,4 @@ rstest = { workspace = true }
3437
workspace = true
3538

3639
[features]
37-
arbitrary = ["dep:arbitrary"]
40+
arbitrary = ["dep:arbitrary", "primitive-types"]

vortex-scalar/src/arbitrary/decimal.rs

Lines changed: 110 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,118 @@
1+
use std::ops::{BitOr, Rem, Shl, Shr, Sub};
2+
13
use arbitrary::unstructured::Int;
24
use arbitrary::{Result, Unstructured};
35
use num_traits::{CheckedAdd, WrappingAdd, WrappingSub};
6+
use primitive_types::U256;
47
use vortex_dtype::{DECIMAL128_MAX_PRECISION, DecimalDType};
58

69
use crate::{DecimalValue, InnerScalarValue, ScalarValue, i256};
710

11+
/// Generate an arbitrary decimal scalar confined to the bounds of
12+
pub fn random_decimal(u: &mut Unstructured, decimal_type: &DecimalDType) -> Result<ScalarValue> {
13+
let precision = decimal_type.precision();
14+
if precision <= DECIMAL128_MAX_PRECISION {
15+
Ok(ScalarValue(InnerScalarValue::Decimal(DecimalValue::I128(
16+
u.int_in_range(
17+
MIN_DECIMAL128_FOR_EACH_PRECISION[precision as usize]
18+
..=MAX_DECIMAL128_FOR_EACH_PRECISION[precision as usize],
19+
)?,
20+
))))
21+
} else {
22+
Ok(ScalarValue(InnerScalarValue::Decimal(DecimalValue::I256(
23+
u.int_in_range(
24+
MIN_DECIMAL256_FOR_EACH_PRECISION[precision as usize]
25+
..=MAX_DECIMAL256_FOR_EACH_PRECISION[precision as usize],
26+
)?,
27+
))))
28+
}
29+
}
30+
31+
/// Used only internally to implement `Int` for i256
32+
#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
33+
pub struct U256Wrapper(U256);
34+
35+
impl Sub for U256Wrapper {
36+
type Output = Self;
37+
38+
fn sub(self, rhs: Self) -> Self::Output {
39+
U256Wrapper(self.0 - rhs.0)
40+
}
41+
}
42+
43+
impl Rem for U256Wrapper {
44+
type Output = Self;
45+
46+
fn rem(self, rhs: Self) -> Self::Output {
47+
U256Wrapper(self.0 % rhs.0)
48+
}
49+
}
50+
51+
impl Shr for U256Wrapper {
52+
type Output = Self;
53+
54+
fn shr(self, rhs: Self) -> Self::Output {
55+
U256Wrapper(self.0 >> rhs.0)
56+
}
57+
}
58+
59+
impl Shl<usize> for U256Wrapper {
60+
type Output = Self;
61+
62+
fn shl(self, rhs: usize) -> Self::Output {
63+
U256Wrapper(self.0 << rhs)
64+
}
65+
}
66+
67+
impl BitOr for U256Wrapper {
68+
type Output = Self;
69+
70+
fn bitor(self, rhs: Self) -> Self::Output {
71+
U256Wrapper(self.0 | rhs.0)
72+
}
73+
}
74+
75+
impl Int for U256Wrapper {
76+
type Unsigned = Self;
77+
78+
const ZERO: Self = U256Wrapper(U256::zero());
79+
const ONE: Self = U256Wrapper(U256::one());
80+
const MAX: Self = U256Wrapper(U256::max_value());
81+
82+
fn from_u8(b: u8) -> Self {
83+
Self(U256::from(b))
84+
}
85+
86+
fn from_usize(u: usize) -> Self {
87+
Self(U256::from(u))
88+
}
89+
90+
fn checked_add(self, rhs: Self) -> Option<Self> {
91+
self.0.checked_add(rhs.0).map(U256Wrapper)
92+
}
93+
94+
fn wrapping_add(self, rhs: Self) -> Self {
95+
let (v, _) = self.0.overflowing_add(rhs.0);
96+
U256Wrapper(v)
97+
}
98+
99+
fn wrapping_sub(self, rhs: Self) -> Self {
100+
let (v, _) = self.0.overflowing_sub(rhs.0);
101+
U256Wrapper(v)
102+
}
103+
104+
fn to_unsigned(self) -> Self::Unsigned {
105+
self
106+
}
107+
108+
fn from_unsigned(unsigned: Self::Unsigned) -> Self {
109+
unsigned
110+
}
111+
}
112+
8113
#[allow(clippy::same_name_method)]
9114
impl Int for i256 {
10-
type Unsigned = i256;
115+
type Unsigned = U256Wrapper;
11116
const ZERO: Self = i256::ZERO;
12117
const ONE: Self = i256::ONE;
13118
const MAX: Self = i256::MAX;
@@ -33,31 +138,13 @@ impl Int for i256 {
33138
}
34139

35140
fn to_unsigned(self) -> Self::Unsigned {
36-
self
141+
let bytes = self.to_le_bytes(); // or to_be_bytes(), depends on your impl
142+
U256Wrapper(U256::from_little_endian(&bytes))
37143
}
38144

39145
fn from_unsigned(unsigned: Self::Unsigned) -> Self {
40-
unsigned
41-
}
42-
}
43-
44-
/// Generate an arbitrary decimal scalar confined to the bounds of
45-
pub fn random_decimal(u: &mut Unstructured, decimal_type: &DecimalDType) -> Result<ScalarValue> {
46-
let precision = decimal_type.precision();
47-
if precision <= DECIMAL128_MAX_PRECISION {
48-
Ok(ScalarValue(InnerScalarValue::Decimal(DecimalValue::I128(
49-
u.int_in_range(
50-
MIN_DECIMAL128_FOR_EACH_PRECISION[precision as usize]
51-
..=MAX_DECIMAL128_FOR_EACH_PRECISION[precision as usize],
52-
)?,
53-
))))
54-
} else {
55-
Ok(ScalarValue(InnerScalarValue::Decimal(DecimalValue::I256(
56-
u.int_in_range(
57-
MIN_DECIMAL256_FOR_EACH_PRECISION[precision as usize]
58-
..=MAX_DECIMAL256_FOR_EACH_PRECISION[precision as usize],
59-
)?,
60-
))))
146+
let bytes = unsigned.0.to_little_endian();
147+
i256::from_le_bytes(bytes)
61148
}
62149
}
63150

0 commit comments

Comments
 (0)