Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions datafusion/common/src/scalar/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@

// Constants defined for scalar construction.

use arrow::datatypes::{Decimal32Type, Decimal64Type, Decimal128Type, DecimalType};
use arrow::datatypes::{Decimal256Type, i256};

// Next F16 value above π (upper bound)
pub(super) const PI_UPPER_F16: half::f16 = half::f16::from_bits(0x4249);

Expand Down Expand Up @@ -54,3 +57,60 @@ pub(super) const NEGATIVE_FRAC_PI_2_LOWER_F32: f32 =
// Next f64 value below -π/2 (lower bound)
pub(super) const NEGATIVE_FRAC_PI_2_LOWER_F64: f64 =
(-std::f64::consts::FRAC_PI_2).next_down();

// Generate lookup table for 1 values of decimals (1, 10, 100, etc.)
macro_rules! decimal_ones_lut {
() => {{
let mut values = [1; _];
let mut i = 1;
while i < values.len() {
values[i] = values[i - 1] * 10;
i += 1;
}
values
}};
}

// 1, 10, 100 values meant to be indexed by scale. We omit handling for MAX_SCALE
// itself (we don't go to MAX_SCALE + 1) since we can't represent a 1 value at
// that scale.
pub(super) const DECIMAL32_ONES: [i32; Decimal32Type::MAX_SCALE as usize] =
decimal_ones_lut!();
pub(super) const DECIMAL64_ONES: [i64; Decimal64Type::MAX_SCALE as usize] =
decimal_ones_lut!();
pub(super) const DECIMAL128_ONES: [i128; Decimal128Type::MAX_SCALE as usize] =
decimal_ones_lut!();
pub(super) const DECIMAL256_ONES: [i256; Decimal256Type::MAX_SCALE as usize] = {
// This code was generated by codex and frankly I don't know how it works,
// but the test below verifies it outputs the correct values so ¯\_(ツ)_/¯
//
// This is mainly a shortcut for not needing to manually list out each value
// anyway.
let mut values = [i256::ONE; _];
let mut i = 1;
while i < values.len() {
let (low, high) = values[i - 1].to_parts();
let low_product = (low as u64 as u128) * 10;
let high_product = (low >> 64) * 10 + (low_product >> 64);
let low = ((high_product as u64 as u128) << 64) | low_product as u64 as u128;
let carry = (high_product >> 64) as i128;
values[i] = i256::from_parts(low, high * 10 + carry);
i += 1;
}
values
};

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_ensure_correct_decimal256_ones() {
for (scale, val) in DECIMAL256_ONES.iter().enumerate() {
let zeros = "0".repeat(scale);
let num = "1".to_string() + &zeros;
let num = i256::from_string(&num).unwrap();
assert_eq!(num, *val, "{scale}");
}
}
}
Loading
Loading