Path: blob/main/crates/polars-compute/src/arithmetic/pl_num.rs
8421 views
use core::any::TypeId;12use arrow::types::NativeType;3use polars_utils::float16::pf16;4use polars_utils::floor_divmod::FloorDivMod;56/// Implements basic arithmetic between scalars with the same behavior as `ArithmeticKernel`.7///8/// Note, however, that the user is responsible for setting the validity of9/// results for e.g. div/mod operations with 0 in the denominator.10///11/// This is intended as a low-level utility for custom arithmetic loops12/// (e.g. in list arithmetic). In most cases prefer using `ArithmeticKernel` or13/// `ArithmeticChunked` instead.14pub trait PlNumArithmetic: Sized + Copy + 'static {15type TrueDivT: NativeType;1617fn wrapping_abs(self) -> Self;18fn wrapping_neg(self) -> Self;19fn wrapping_add(self, rhs: Self) -> Self;20fn wrapping_sub(self, rhs: Self) -> Self;21fn wrapping_mul(self, rhs: Self) -> Self;22fn wrapping_floor_div(self, rhs: Self) -> Self;23fn wrapping_trunc_div(self, rhs: Self) -> Self;24fn wrapping_mod(self, rhs: Self) -> Self;2526fn true_div(self, rhs: Self) -> Self::TrueDivT;2728#[inline(always)]29fn legacy_div(self, rhs: Self) -> Self {30if TypeId::of::<Self>() == TypeId::of::<Self::TrueDivT>() {31let ret = self.true_div(rhs);32unsafe { core::mem::transmute_copy(&ret) }33} else {34self.wrapping_floor_div(rhs)35}36}37}3839macro_rules! impl_signed_pl_num_arith {40($T:ty) => {41impl PlNumArithmetic for $T {42type TrueDivT = f64;4344#[inline(always)]45fn wrapping_abs(self) -> Self {46self.wrapping_abs()47}4849#[inline(always)]50fn wrapping_neg(self) -> Self {51self.wrapping_neg()52}5354#[inline(always)]55fn wrapping_add(self, rhs: Self) -> Self {56self.wrapping_add(rhs)57}5859#[inline(always)]60fn wrapping_sub(self, rhs: Self) -> Self {61self.wrapping_sub(rhs)62}6364#[inline(always)]65fn wrapping_mul(self, rhs: Self) -> Self {66self.wrapping_mul(rhs)67}6869#[inline(always)]70fn wrapping_floor_div(self, rhs: Self) -> Self {71self.wrapping_floor_div_mod(rhs).072}7374#[inline(always)]75fn wrapping_trunc_div(self, rhs: Self) -> Self {76if rhs != 0 { self.wrapping_div(rhs) } else { 0 }77}7879#[inline(always)]80fn wrapping_mod(self, rhs: Self) -> Self {81self.wrapping_floor_div_mod(rhs).182}8384#[inline(always)]85fn true_div(self, rhs: Self) -> Self::TrueDivT {86self as f64 / rhs as f6487}88}89};90}9192impl_signed_pl_num_arith!(i8);93impl_signed_pl_num_arith!(i16);94impl_signed_pl_num_arith!(i32);95impl_signed_pl_num_arith!(i64);96impl_signed_pl_num_arith!(i128);9798macro_rules! impl_unsigned_pl_num_arith {99($T:ty) => {100impl PlNumArithmetic for $T {101type TrueDivT = f64;102103#[inline(always)]104fn wrapping_abs(self) -> Self {105self106}107108#[inline(always)]109fn wrapping_neg(self) -> Self {110self.wrapping_neg()111}112113#[inline(always)]114fn wrapping_add(self, rhs: Self) -> Self {115self.wrapping_add(rhs)116}117118#[inline(always)]119fn wrapping_sub(self, rhs: Self) -> Self {120self.wrapping_sub(rhs)121}122123#[inline(always)]124fn wrapping_mul(self, rhs: Self) -> Self {125self.wrapping_mul(rhs)126}127128#[inline(always)]129fn wrapping_floor_div(self, rhs: Self) -> Self {130if rhs != 0 { self / rhs } else { 0 }131}132133#[inline(always)]134fn wrapping_trunc_div(self, rhs: Self) -> Self {135self.wrapping_floor_div(rhs)136}137138#[inline(always)]139fn wrapping_mod(self, rhs: Self) -> Self {140if rhs != 0 { self % rhs } else { 0 }141}142143#[inline(always)]144fn true_div(self, rhs: Self) -> Self::TrueDivT {145self as f64 / rhs as f64146}147}148};149}150151impl_unsigned_pl_num_arith!(u8);152impl_unsigned_pl_num_arith!(u16);153impl_unsigned_pl_num_arith!(u32);154impl_unsigned_pl_num_arith!(u64);155impl_unsigned_pl_num_arith!(u128);156157macro_rules! impl_float_pl_num_arith {158($T:ty) => {159impl PlNumArithmetic for $T {160type TrueDivT = $T;161162#[inline(always)]163fn wrapping_abs(self) -> Self {164self.abs()165}166167#[inline(always)]168fn wrapping_neg(self) -> Self {169-self170}171172#[inline(always)]173fn wrapping_add(self, rhs: Self) -> Self {174self + rhs175}176177#[inline(always)]178fn wrapping_sub(self, rhs: Self) -> Self {179self - rhs180}181182#[inline(always)]183fn wrapping_mul(self, rhs: Self) -> Self {184self * rhs185}186187#[inline(always)]188fn wrapping_floor_div(self, rhs: Self) -> Self {189let l = self;190let r = rhs;191(l / r).floor()192}193194#[inline(always)]195fn wrapping_trunc_div(self, rhs: Self) -> Self {196let l = self;197let r = rhs;198(l / r).trunc()199}200201#[inline(always)]202fn wrapping_mod(self, rhs: Self) -> Self {203let l = self;204let r = rhs;205l - r * (l / r).floor()206}207208#[inline(always)]209fn true_div(self, rhs: Self) -> Self::TrueDivT {210self / rhs211}212}213};214}215216impl_float_pl_num_arith!(pf16);217impl_float_pl_num_arith!(f32);218impl_float_pl_num_arith!(f64);219220221