Path: blob/main/crates/polars-compute/src/arithmetic/unsigned.rs
6939 views
use arrow::array::{PrimitiveArray as PArr, StaticArray};1use arrow::compute::utils::{combine_validities_and, combine_validities_and3};2use strength_reduce::*;34use super::PrimitiveArithmeticKernelImpl;5use crate::arity::{prim_binary_values, prim_unary_values};6use crate::comparisons::TotalEqKernel;78macro_rules! impl_unsigned_arith_kernel {9($T:ty, $StrRed:ty) => {10impl PrimitiveArithmeticKernelImpl for $T {11type TrueDivT = f64;1213fn prim_wrapping_abs(lhs: PArr<$T>) -> PArr<$T> {14lhs15}1617fn prim_wrapping_neg(lhs: PArr<$T>) -> PArr<$T> {18prim_unary_values(lhs, |x| x.wrapping_neg())19}2021fn prim_wrapping_add(lhs: PArr<$T>, other: PArr<$T>) -> PArr<$T> {22prim_binary_values(lhs, other, |a, b| a.wrapping_add(b))23}2425fn prim_wrapping_sub(lhs: PArr<$T>, other: PArr<$T>) -> PArr<$T> {26prim_binary_values(lhs, other, |a, b| a.wrapping_sub(b))27}2829fn prim_wrapping_mul(lhs: PArr<$T>, other: PArr<$T>) -> PArr<$T> {30prim_binary_values(lhs, other, |a, b| a.wrapping_mul(b))31}3233fn prim_wrapping_floor_div(mut lhs: PArr<$T>, mut other: PArr<$T>) -> PArr<$T> {34let mask = other.tot_ne_kernel_broadcast(&0);35let valid = combine_validities_and3(36lhs.take_validity().as_ref(), // Take validity so we don't37other.take_validity().as_ref(), // compute combination twice.38Some(&mask),39);40let ret = prim_binary_values(lhs, other, |a, b| if b != 0 { a / b } else { 0 });41ret.with_validity(valid)42}4344fn prim_wrapping_trunc_div(lhs: PArr<$T>, rhs: PArr<$T>) -> PArr<$T> {45Self::prim_wrapping_floor_div(lhs, rhs)46}4748fn prim_wrapping_mod(mut lhs: PArr<$T>, mut other: PArr<$T>) -> PArr<$T> {49let mask = other.tot_ne_kernel_broadcast(&0);50let valid = combine_validities_and3(51lhs.take_validity().as_ref(), // Take validity so we don't52other.take_validity().as_ref(), // compute combination twice.53Some(&mask),54);55let ret = prim_binary_values(lhs, other, |a, b| if b != 0 { a % b } else { 0 });56ret.with_validity(valid)57}5859fn prim_wrapping_add_scalar(lhs: PArr<$T>, rhs: $T) -> PArr<$T> {60prim_unary_values(lhs, |x| x.wrapping_add(rhs))61}6263fn prim_wrapping_sub_scalar(lhs: PArr<$T>, rhs: $T) -> PArr<$T> {64Self::prim_wrapping_add_scalar(lhs, rhs.wrapping_neg())65}6667fn prim_wrapping_sub_scalar_lhs(lhs: $T, rhs: PArr<$T>) -> PArr<$T> {68prim_unary_values(rhs, |x| lhs.wrapping_sub(x))69}7071fn prim_wrapping_mul_scalar(lhs: PArr<$T>, rhs: $T) -> PArr<$T> {72if rhs == 0 {73lhs.fill_with(0)74} else if rhs == 1 {75lhs76} else if rhs.is_power_of_two() {77// Power of two.78let shift = rhs.trailing_zeros();79prim_unary_values(lhs, |x| x << shift)80} else {81prim_unary_values(lhs, |x| x.wrapping_mul(rhs))82}83}8485fn prim_wrapping_floor_div_scalar(lhs: PArr<$T>, rhs: $T) -> PArr<$T> {86if rhs == 0 {87PArr::full_null(lhs.len(), lhs.dtype().clone())88} else if rhs == 1 {89lhs90} else {91let red = <$StrRed>::new(rhs);92prim_unary_values(lhs, |x| x / red)93}94}9596fn prim_wrapping_floor_div_scalar_lhs(lhs: $T, rhs: PArr<$T>) -> PArr<$T> {97let mask = rhs.tot_ne_kernel_broadcast(&0);98let valid = combine_validities_and(rhs.validity(), Some(&mask));99let ret = if lhs == 0 {100rhs.fill_with(0)101} else {102prim_unary_values(rhs, |x| if x != 0 { lhs / x } else { 0 })103};104ret.with_validity(valid)105}106107fn prim_wrapping_trunc_div_scalar(lhs: PArr<$T>, rhs: $T) -> PArr<$T> {108Self::prim_wrapping_floor_div_scalar(lhs, rhs)109}110111fn prim_wrapping_trunc_div_scalar_lhs(lhs: $T, rhs: PArr<$T>) -> PArr<$T> {112Self::prim_wrapping_floor_div_scalar_lhs(lhs, rhs)113}114115fn prim_wrapping_mod_scalar(lhs: PArr<$T>, rhs: $T) -> PArr<$T> {116if rhs == 0 {117PArr::full_null(lhs.len(), lhs.dtype().clone())118} else if rhs == 1 {119lhs.fill_with(0)120} else {121let red = <$StrRed>::new(rhs);122prim_unary_values(lhs, |x| x % red)123}124}125126fn prim_wrapping_mod_scalar_lhs(lhs: $T, rhs: PArr<$T>) -> PArr<$T> {127let mask = rhs.tot_ne_kernel_broadcast(&0);128let valid = combine_validities_and(rhs.validity(), Some(&mask));129let ret = if lhs == 0 {130rhs.fill_with(0)131} else {132prim_unary_values(rhs, |x| if x != 0 { lhs % x } else { 0 })133};134ret.with_validity(valid)135}136137fn prim_checked_mul_scalar(lhs: PArr<$T>, rhs: $T) -> PArr<$T> {138super::prim_checked_mul_scalar(&lhs, rhs)139}140141fn prim_true_div(lhs: PArr<$T>, other: PArr<$T>) -> PArr<Self::TrueDivT> {142prim_binary_values(lhs, other, |a, b| a as f64 / b as f64)143}144145fn prim_true_div_scalar(lhs: PArr<$T>, rhs: $T) -> PArr<Self::TrueDivT> {146let inv = 1.0 / rhs as f64;147prim_unary_values(lhs, |x| x as f64 * inv)148}149150fn prim_true_div_scalar_lhs(lhs: $T, rhs: PArr<$T>) -> PArr<Self::TrueDivT> {151prim_unary_values(rhs, |x| lhs as f64 / x as f64)152}153}154};155}156157impl_unsigned_arith_kernel!(u8, StrengthReducedU8);158impl_unsigned_arith_kernel!(u16, StrengthReducedU16);159impl_unsigned_arith_kernel!(u32, StrengthReducedU32);160impl_unsigned_arith_kernel!(u64, StrengthReducedU64);161impl_unsigned_arith_kernel!(u128, StrengthReducedU128);162163164