arrow2/compute/arithmetics/basic/
rem.rs1use std::ops::Rem;
2
3use num_traits::{CheckedRem, NumCast};
4
5use crate::datatypes::PrimitiveType;
6use crate::{
7 array::{Array, PrimitiveArray},
8 compute::{
9 arithmetics::{ArrayCheckedRem, ArrayRem},
10 arity::{binary, binary_checked, unary, unary_checked},
11 },
12};
13use strength_reduce::{
14 StrengthReducedU16, StrengthReducedU32, StrengthReducedU64, StrengthReducedU8,
15};
16
17use super::NativeArithmetics;
18
19pub fn rem<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> PrimitiveArray<T>
34where
35 T: NativeArithmetics + Rem<Output = T>,
36{
37 binary(lhs, rhs, lhs.data_type().clone(), |a, b| a % b)
38}
39
40pub fn checked_rem<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> PrimitiveArray<T>
56where
57 T: NativeArithmetics + CheckedRem<Output = T>,
58{
59 let op = move |a: T, b: T| a.checked_rem(&b);
60
61 binary_checked(lhs, rhs, lhs.data_type().clone(), op)
62}
63
64impl<T> ArrayRem<PrimitiveArray<T>> for PrimitiveArray<T>
65where
66 T: NativeArithmetics + Rem<Output = T>,
67{
68 fn rem(&self, rhs: &PrimitiveArray<T>) -> Self {
69 rem(self, rhs)
70 }
71}
72
73impl<T> ArrayCheckedRem<PrimitiveArray<T>> for PrimitiveArray<T>
74where
75 T: NativeArithmetics + CheckedRem<Output = T>,
76{
77 fn checked_rem(&self, rhs: &PrimitiveArray<T>) -> Self {
78 checked_rem(self, rhs)
79 }
80}
81
82pub fn rem_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> PrimitiveArray<T>
96where
97 T: NativeArithmetics + Rem<Output = T> + NumCast,
98{
99 let rhs = *rhs;
100
101 match T::PRIMITIVE {
102 PrimitiveType::UInt64 => {
103 let lhs = lhs.as_any().downcast_ref::<PrimitiveArray<u64>>().unwrap();
104 let rhs = rhs.to_u64().unwrap();
105
106 let reduced_rem = StrengthReducedU64::new(rhs);
107
108 let r = unary(lhs, |a| a % reduced_rem, lhs.data_type().clone());
110 (&r as &dyn Array)
111 .as_any()
112 .downcast_ref::<PrimitiveArray<T>>()
113 .unwrap()
114 .clone()
115 }
116 PrimitiveType::UInt32 => {
117 let lhs = lhs.as_any().downcast_ref::<PrimitiveArray<u32>>().unwrap();
118 let rhs = rhs.to_u32().unwrap();
119
120 let reduced_rem = StrengthReducedU32::new(rhs);
121
122 let r = unary(lhs, |a| a % reduced_rem, lhs.data_type().clone());
123 (&r as &dyn Array)
125 .as_any()
126 .downcast_ref::<PrimitiveArray<T>>()
127 .unwrap()
128 .clone()
129 }
130 PrimitiveType::UInt16 => {
131 let lhs = lhs.as_any().downcast_ref::<PrimitiveArray<u16>>().unwrap();
132 let rhs = rhs.to_u16().unwrap();
133
134 let reduced_rem = StrengthReducedU16::new(rhs);
135
136 let r = unary(lhs, |a| a % reduced_rem, lhs.data_type().clone());
137 (&r as &dyn Array)
139 .as_any()
140 .downcast_ref::<PrimitiveArray<T>>()
141 .unwrap()
142 .clone()
143 }
144 PrimitiveType::UInt8 => {
145 let lhs = lhs.as_any().downcast_ref::<PrimitiveArray<u8>>().unwrap();
146 let rhs = rhs.to_u8().unwrap();
147
148 let reduced_rem = StrengthReducedU8::new(rhs);
149
150 let r = unary(lhs, |a| a % reduced_rem, lhs.data_type().clone());
151 (&r as &dyn Array)
153 .as_any()
154 .downcast_ref::<PrimitiveArray<T>>()
155 .unwrap()
156 .clone()
157 }
158 _ => unary(lhs, |a| a % rhs, lhs.data_type().clone()),
159 }
160}
161
162pub fn checked_rem_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> PrimitiveArray<T>
176where
177 T: NativeArithmetics + CheckedRem<Output = T>,
178{
179 let rhs = *rhs;
180 let op = move |a: T| a.checked_rem(&rhs);
181
182 unary_checked(lhs, op, lhs.data_type().clone())
183}
184
185impl<T> ArrayRem<T> for PrimitiveArray<T>
186where
187 T: NativeArithmetics + Rem<Output = T> + NumCast,
188{
189 fn rem(&self, rhs: &T) -> Self {
190 rem_scalar(self, rhs)
191 }
192}
193
194impl<T> ArrayCheckedRem<T> for PrimitiveArray<T>
195where
196 T: NativeArithmetics + CheckedRem<Output = T>,
197{
198 fn checked_rem(&self, rhs: &T) -> Self {
199 checked_rem_scalar(self, rhs)
200 }
201}