use crate::error::{ArrowError, Result};
pub use arrow_array::ArrowPrimitiveType;
pub use arrow_buffer::{ArrowNativeType, ToByteSlice};
use half::f16;
pub trait ArrowNativeTypeOp: ArrowNativeType {
const ZERO: Self;
const ONE: Self;
fn add_checked(self, rhs: Self) -> Result<Self>;
fn add_wrapping(self, rhs: Self) -> Self;
fn sub_checked(self, rhs: Self) -> Result<Self>;
fn sub_wrapping(self, rhs: Self) -> Self;
fn mul_checked(self, rhs: Self) -> Result<Self>;
fn mul_wrapping(self, rhs: Self) -> Self;
fn div_checked(self, rhs: Self) -> Result<Self>;
fn div_wrapping(self, rhs: Self) -> Self;
fn mod_checked(self, rhs: Self) -> Result<Self>;
fn mod_wrapping(self, rhs: Self) -> Self;
fn neg_checked(self) -> Result<Self>;
fn neg_wrapping(self) -> Self;
fn is_zero(self) -> bool;
fn is_eq(self, rhs: Self) -> bool;
fn is_ne(self, rhs: Self) -> bool;
fn is_lt(self, rhs: Self) -> bool;
fn is_le(self, rhs: Self) -> bool;
fn is_gt(self, rhs: Self) -> bool;
fn is_ge(self, rhs: Self) -> bool;
}
macro_rules! native_type_op {
($t:tt) => {
impl ArrowNativeTypeOp for $t {
const ZERO: Self = 0;
const ONE: Self = 1;
fn add_checked(self, rhs: Self) -> Result<Self> {
self.checked_add(rhs).ok_or_else(|| {
ArrowError::ComputeError(format!(
"Overflow happened on: {:?} + {:?}",
self, rhs
))
})
}
fn add_wrapping(self, rhs: Self) -> Self {
self.wrapping_add(rhs)
}
fn sub_checked(self, rhs: Self) -> Result<Self> {
self.checked_sub(rhs).ok_or_else(|| {
ArrowError::ComputeError(format!(
"Overflow happened on: {:?} - {:?}",
self, rhs
))
})
}
fn sub_wrapping(self, rhs: Self) -> Self {
self.wrapping_sub(rhs)
}
fn mul_checked(self, rhs: Self) -> Result<Self> {
self.checked_mul(rhs).ok_or_else(|| {
ArrowError::ComputeError(format!(
"Overflow happened on: {:?} * {:?}",
self, rhs
))
})
}
fn mul_wrapping(self, rhs: Self) -> Self {
self.wrapping_mul(rhs)
}
fn div_checked(self, rhs: Self) -> Result<Self> {
if rhs.is_zero() {
Err(ArrowError::DivideByZero)
} else {
self.checked_div(rhs).ok_or_else(|| {
ArrowError::ComputeError(format!(
"Overflow happened on: {:?} / {:?}",
self, rhs
))
})
}
}
fn div_wrapping(self, rhs: Self) -> Self {
self.wrapping_div(rhs)
}
fn mod_checked(self, rhs: Self) -> Result<Self> {
if rhs.is_zero() {
Err(ArrowError::DivideByZero)
} else {
self.checked_rem(rhs).ok_or_else(|| {
ArrowError::ComputeError(format!(
"Overflow happened on: {:?} % {:?}",
self, rhs
))
})
}
}
fn mod_wrapping(self, rhs: Self) -> Self {
self.wrapping_rem(rhs)
}
fn neg_checked(self) -> Result<Self> {
self.checked_neg().ok_or_else(|| {
ArrowError::ComputeError(format!("Overflow happened on: {:?}", self))
})
}
fn neg_wrapping(self) -> Self {
self.wrapping_neg()
}
fn is_zero(self) -> bool {
self == 0
}
fn is_eq(self, rhs: Self) -> bool {
self == rhs
}
fn is_ne(self, rhs: Self) -> bool {
self != rhs
}
fn is_lt(self, rhs: Self) -> bool {
self < rhs
}
fn is_le(self, rhs: Self) -> bool {
self <= rhs
}
fn is_gt(self, rhs: Self) -> bool {
self > rhs
}
fn is_ge(self, rhs: Self) -> bool {
self >= rhs
}
}
};
}
native_type_op!(i8);
native_type_op!(i16);
native_type_op!(i32);
native_type_op!(i64);
native_type_op!(i128);
native_type_op!(u8);
native_type_op!(u16);
native_type_op!(u32);
native_type_op!(u64);
macro_rules! native_type_float_op {
($t:tt, $zero:expr, $one:expr) => {
impl ArrowNativeTypeOp for $t {
const ZERO: Self = $zero;
const ONE: Self = $one;
fn add_checked(self, rhs: Self) -> Result<Self> {
Ok(self + rhs)
}
fn add_wrapping(self, rhs: Self) -> Self {
self + rhs
}
fn sub_checked(self, rhs: Self) -> Result<Self> {
Ok(self - rhs)
}
fn sub_wrapping(self, rhs: Self) -> Self {
self - rhs
}
fn mul_checked(self, rhs: Self) -> Result<Self> {
Ok(self * rhs)
}
fn mul_wrapping(self, rhs: Self) -> Self {
self * rhs
}
fn div_checked(self, rhs: Self) -> Result<Self> {
if rhs.is_zero() {
Err(ArrowError::DivideByZero)
} else {
Ok(self / rhs)
}
}
fn div_wrapping(self, rhs: Self) -> Self {
self / rhs
}
fn mod_checked(self, rhs: Self) -> Result<Self> {
if rhs.is_zero() {
Err(ArrowError::DivideByZero)
} else {
Ok(self % rhs)
}
}
fn mod_wrapping(self, rhs: Self) -> Self {
self % rhs
}
fn neg_checked(self) -> Result<Self> {
Ok(-self)
}
fn neg_wrapping(self) -> Self {
-self
}
fn is_zero(self) -> bool {
self == $zero
}
fn is_eq(self, rhs: Self) -> bool {
self.total_cmp(&rhs).is_eq()
}
fn is_ne(self, rhs: Self) -> bool {
self.total_cmp(&rhs).is_ne()
}
fn is_lt(self, rhs: Self) -> bool {
self.total_cmp(&rhs).is_lt()
}
fn is_le(self, rhs: Self) -> bool {
self.total_cmp(&rhs).is_le()
}
fn is_gt(self, rhs: Self) -> bool {
self.total_cmp(&rhs).is_gt()
}
fn is_ge(self, rhs: Self) -> bool {
self.total_cmp(&rhs).is_ge()
}
}
};
}
native_type_float_op!(f16, f16::ONE, f16::ZERO);
native_type_float_op!(f32, 0., 1.);
native_type_float_op!(f64, 0., 1.);