Path: blob/main/crates/polars-compute/src/arithmetic/pl_num.rs
6939 views
use core::any::TypeId;12use arrow::types::NativeType;3use polars_utils::floor_divmod::FloorDivMod;45/// Implements basic arithmetic between scalars with the same behavior as `ArithmeticKernel`.6///7/// Note, however, that the user is responsible for setting the validity of8/// results for e.g. div/mod operations with 0 in the denominator.9///10/// This is intended as a low-level utility for custom arithmetic loops11/// (e.g. in list arithmetic). In most cases prefer using `ArithmeticKernel` or12/// `ArithmeticChunked` instead.13pub trait PlNumArithmetic: Sized + Copy + 'static {14type TrueDivT: NativeType;1516fn wrapping_abs(self) -> Self;17fn wrapping_neg(self) -> Self;18fn wrapping_add(self, rhs: Self) -> Self;19fn wrapping_sub(self, rhs: Self) -> Self;20fn wrapping_mul(self, rhs: Self) -> Self;21fn wrapping_floor_div(self, rhs: Self) -> Self;22fn wrapping_trunc_div(self, rhs: Self) -> Self;23fn wrapping_mod(self, rhs: Self) -> Self;2425fn true_div(self, rhs: Self) -> Self::TrueDivT;2627#[inline(always)]28fn legacy_div(self, rhs: Self) -> Self {29if TypeId::of::<Self>() == TypeId::of::<Self::TrueDivT>() {30let ret = self.true_div(rhs);31unsafe { core::mem::transmute_copy(&ret) }32} else {33self.wrapping_floor_div(rhs)34}35}36}3738macro_rules! impl_signed_pl_num_arith {39($T:ty) => {40impl PlNumArithmetic for $T {41type TrueDivT = f64;4243#[inline(always)]44fn wrapping_abs(self) -> Self {45self.wrapping_abs()46}4748#[inline(always)]49fn wrapping_neg(self) -> Self {50self.wrapping_neg()51}5253#[inline(always)]54fn wrapping_add(self, rhs: Self) -> Self {55self.wrapping_add(rhs)56}5758#[inline(always)]59fn wrapping_sub(self, rhs: Self) -> Self {60self.wrapping_sub(rhs)61}6263#[inline(always)]64fn wrapping_mul(self, rhs: Self) -> Self {65self.wrapping_mul(rhs)66}6768#[inline(always)]69fn wrapping_floor_div(self, rhs: Self) -> Self {70self.wrapping_floor_div_mod(rhs).071}7273#[inline(always)]74fn wrapping_trunc_div(self, rhs: Self) -> Self {75if rhs != 0 { self.wrapping_div(rhs) } else { 0 }76}7778#[inline(always)]79fn wrapping_mod(self, rhs: Self) -> Self {80self.wrapping_floor_div_mod(rhs).181}8283#[inline(always)]84fn true_div(self, rhs: Self) -> Self::TrueDivT {85self as f64 / rhs as f6486}87}88};89}9091impl_signed_pl_num_arith!(i8);92impl_signed_pl_num_arith!(i16);93impl_signed_pl_num_arith!(i32);94impl_signed_pl_num_arith!(i64);95impl_signed_pl_num_arith!(i128);9697macro_rules! impl_unsigned_pl_num_arith {98($T:ty) => {99impl PlNumArithmetic for $T {100type TrueDivT = f64;101102#[inline(always)]103fn wrapping_abs(self) -> Self {104self105}106107#[inline(always)]108fn wrapping_neg(self) -> Self {109self.wrapping_neg()110}111112#[inline(always)]113fn wrapping_add(self, rhs: Self) -> Self {114self.wrapping_add(rhs)115}116117#[inline(always)]118fn wrapping_sub(self, rhs: Self) -> Self {119self.wrapping_sub(rhs)120}121122#[inline(always)]123fn wrapping_mul(self, rhs: Self) -> Self {124self.wrapping_mul(rhs)125}126127#[inline(always)]128fn wrapping_floor_div(self, rhs: Self) -> Self {129if rhs != 0 { self / rhs } else { 0 }130}131132#[inline(always)]133fn wrapping_trunc_div(self, rhs: Self) -> Self {134self.wrapping_floor_div(rhs)135}136137#[inline(always)]138fn wrapping_mod(self, rhs: Self) -> Self {139if rhs != 0 { self % rhs } else { 0 }140}141142#[inline(always)]143fn true_div(self, rhs: Self) -> Self::TrueDivT {144self as f64 / rhs as f64145}146}147};148}149150impl_unsigned_pl_num_arith!(u8);151impl_unsigned_pl_num_arith!(u16);152impl_unsigned_pl_num_arith!(u32);153impl_unsigned_pl_num_arith!(u64);154impl_unsigned_pl_num_arith!(u128);155156macro_rules! impl_float_pl_num_arith {157($T:ty) => {158impl PlNumArithmetic for $T {159type TrueDivT = $T;160161#[inline(always)]162fn wrapping_abs(self) -> Self {163self.abs()164}165166#[inline(always)]167fn wrapping_neg(self) -> Self {168-self169}170171#[inline(always)]172fn wrapping_add(self, rhs: Self) -> Self {173self + rhs174}175176#[inline(always)]177fn wrapping_sub(self, rhs: Self) -> Self {178self - rhs179}180181#[inline(always)]182fn wrapping_mul(self, rhs: Self) -> Self {183self * rhs184}185186#[inline(always)]187fn wrapping_floor_div(self, rhs: Self) -> Self {188let l = self;189let r = rhs;190(l / r).floor()191}192193#[inline(always)]194fn wrapping_trunc_div(self, rhs: Self) -> Self {195let l = self;196let r = rhs;197(l / r).trunc()198}199200#[inline(always)]201fn wrapping_mod(self, rhs: Self) -> Self {202let l = self;203let r = rhs;204l - r * (l / r).floor()205}206207#[inline(always)]208fn true_div(self, rhs: Self) -> Self::TrueDivT {209self / rhs210}211}212};213}214215impl_float_pl_num_arith!(f32);216impl_float_pl_num_arith!(f64);217218219