1use polars_compute::arithmetic::ArithmeticKernel;
2
3use super::*;
4use crate::chunked_array::arity::{
5 apply_binary_kernel_broadcast, apply_binary_kernel_broadcast_owned, unary_kernel,
6 unary_kernel_owned,
7};
8
9macro_rules! impl_op_overload {
10 ($op: ident, $trait_method: ident, $ca_method: ident, $ca_method_scalar: ident) => {
11 impl<T: PolarsNumericType> $op for ChunkedArray<T> {
12 type Output = ChunkedArray<T>;
13
14 fn $trait_method(self, rhs: Self) -> Self::Output {
15 ArithmeticChunked::$ca_method(self, rhs)
16 }
17 }
18
19 impl<T: PolarsNumericType> $op for &ChunkedArray<T> {
20 type Output = ChunkedArray<T>;
21
22 fn $trait_method(self, rhs: Self) -> Self::Output {
23 ArithmeticChunked::$ca_method(self, rhs)
24 }
25 }
26
27 impl<T: PolarsNumericType, N: Num + ToPrimitive> $op<N> for ChunkedArray<T> {
29 type Output = ChunkedArray<T>;
30
31 fn $trait_method(self, rhs: N) -> Self::Output {
32 let rhs: T::Native = NumCast::from(rhs).unwrap();
33 ArithmeticChunked::$ca_method_scalar(self, rhs)
34 }
35 }
36
37 impl<T: PolarsNumericType, N: Num + ToPrimitive> $op<N> for &ChunkedArray<T> {
38 type Output = ChunkedArray<T>;
39
40 fn $trait_method(self, rhs: N) -> Self::Output {
41 let rhs: T::Native = NumCast::from(rhs).unwrap();
42 ArithmeticChunked::$ca_method_scalar(self, rhs)
43 }
44 }
45 };
46}
47
48impl_op_overload!(Add, add, wrapping_add, wrapping_add_scalar);
49impl_op_overload!(Sub, sub, wrapping_sub, wrapping_sub_scalar);
50impl_op_overload!(Mul, mul, wrapping_mul, wrapping_mul_scalar);
51impl_op_overload!(Div, div, legacy_div, legacy_div_scalar); impl_op_overload!(Rem, rem, wrapping_mod, wrapping_mod_scalar);
53
54pub trait ArithmeticChunked {
55 type Scalar;
56 type Out;
57 type TrueDivOut;
58
59 fn wrapping_abs(self) -> Self::Out;
60 fn wrapping_neg(self) -> Self::Out;
61 fn wrapping_add(self, rhs: Self) -> Self::Out;
62 fn wrapping_sub(self, rhs: Self) -> Self::Out;
63 fn wrapping_mul(self, rhs: Self) -> Self::Out;
64 fn wrapping_floor_div(self, rhs: Self) -> Self::Out;
65 fn wrapping_trunc_div(self, rhs: Self) -> Self::Out;
66 fn wrapping_mod(self, rhs: Self) -> Self::Out;
67
68 fn wrapping_add_scalar(self, rhs: Self::Scalar) -> Self::Out;
69 fn wrapping_sub_scalar(self, rhs: Self::Scalar) -> Self::Out;
70 fn wrapping_sub_scalar_lhs(lhs: Self::Scalar, rhs: Self) -> Self::Out;
71 fn wrapping_mul_scalar(self, rhs: Self::Scalar) -> Self::Out;
72 fn wrapping_floor_div_scalar(self, rhs: Self::Scalar) -> Self::Out;
73 fn wrapping_floor_div_scalar_lhs(lhs: Self::Scalar, rhs: Self) -> Self::Out;
74 fn wrapping_trunc_div_scalar(self, rhs: Self::Scalar) -> Self::Out;
75 fn wrapping_trunc_div_scalar_lhs(lhs: Self::Scalar, rhs: Self) -> Self::Out;
76 fn wrapping_mod_scalar(self, rhs: Self::Scalar) -> Self::Out;
77 fn wrapping_mod_scalar_lhs(lhs: Self::Scalar, rhs: Self) -> Self::Out;
78
79 fn checked_mul_scalar(self, rhs: Self::Scalar) -> Self::Out;
80
81 fn true_div(self, rhs: Self) -> Self::TrueDivOut;
82 fn true_div_scalar(self, rhs: Self::Scalar) -> Self::TrueDivOut;
83 fn true_div_scalar_lhs(lhs: Self::Scalar, rhs: Self) -> Self::TrueDivOut;
84
85 fn legacy_div(self, rhs: Self) -> Self::Out;
88 fn legacy_div_scalar(self, rhs: Self::Scalar) -> Self::Out;
89 fn legacy_div_scalar_lhs(lhs: Self::Scalar, rhs: Self) -> Self::Out;
90}
91
92impl<T: PolarsNumericType> ArithmeticChunked for ChunkedArray<T> {
93 type Scalar = T::Native;
94 type Out = ChunkedArray<T>;
95 type TrueDivOut = ChunkedArray<<T::Native as NumericNative>::TrueDivPolarsType>;
96
97 fn wrapping_abs(self) -> Self::Out {
98 unary_kernel_owned(self, ArithmeticKernel::wrapping_abs)
99 }
100
101 fn wrapping_neg(self) -> Self::Out {
102 unary_kernel_owned(self, ArithmeticKernel::wrapping_neg)
103 }
104
105 fn wrapping_add(self, rhs: Self) -> Self::Out {
106 apply_binary_kernel_broadcast_owned(
107 self,
108 rhs,
109 ArithmeticKernel::wrapping_add,
110 |l, r| ArithmeticKernel::wrapping_add_scalar(r, l),
111 ArithmeticKernel::wrapping_add_scalar,
112 )
113 }
114
115 fn wrapping_sub(self, rhs: Self) -> Self::Out {
116 apply_binary_kernel_broadcast_owned(
117 self,
118 rhs,
119 ArithmeticKernel::wrapping_sub,
120 ArithmeticKernel::wrapping_sub_scalar_lhs,
121 ArithmeticKernel::wrapping_sub_scalar,
122 )
123 }
124
125 fn wrapping_mul(self, rhs: Self) -> Self::Out {
126 apply_binary_kernel_broadcast_owned(
127 self,
128 rhs,
129 ArithmeticKernel::wrapping_mul,
130 |l, r| ArithmeticKernel::wrapping_mul_scalar(r, l),
131 ArithmeticKernel::wrapping_mul_scalar,
132 )
133 }
134
135 fn wrapping_floor_div(self, rhs: Self) -> Self::Out {
136 apply_binary_kernel_broadcast_owned(
137 self,
138 rhs,
139 ArithmeticKernel::wrapping_floor_div,
140 ArithmeticKernel::wrapping_floor_div_scalar_lhs,
141 ArithmeticKernel::wrapping_floor_div_scalar,
142 )
143 }
144
145 fn wrapping_trunc_div(self, rhs: Self) -> Self::Out {
146 apply_binary_kernel_broadcast_owned(
147 self,
148 rhs,
149 ArithmeticKernel::wrapping_trunc_div,
150 ArithmeticKernel::wrapping_trunc_div_scalar_lhs,
151 ArithmeticKernel::wrapping_trunc_div_scalar,
152 )
153 }
154
155 fn wrapping_mod(self, rhs: Self) -> Self::Out {
156 apply_binary_kernel_broadcast_owned(
157 self,
158 rhs,
159 ArithmeticKernel::wrapping_mod,
160 ArithmeticKernel::wrapping_mod_scalar_lhs,
161 ArithmeticKernel::wrapping_mod_scalar,
162 )
163 }
164
165 fn wrapping_add_scalar(self, rhs: Self::Scalar) -> Self::Out {
166 unary_kernel_owned(self, |a| ArithmeticKernel::wrapping_add_scalar(a, rhs))
167 }
168
169 fn wrapping_sub_scalar(self, rhs: Self::Scalar) -> Self::Out {
170 unary_kernel_owned(self, |a| ArithmeticKernel::wrapping_sub_scalar(a, rhs))
171 }
172
173 fn wrapping_sub_scalar_lhs(lhs: Self::Scalar, rhs: Self) -> Self::Out {
174 unary_kernel_owned(rhs, |a| ArithmeticKernel::wrapping_sub_scalar_lhs(lhs, a))
175 }
176
177 fn wrapping_mul_scalar(self, rhs: Self::Scalar) -> Self::Out {
178 unary_kernel_owned(self, |a| ArithmeticKernel::wrapping_mul_scalar(a, rhs))
179 }
180
181 fn wrapping_floor_div_scalar(self, rhs: Self::Scalar) -> Self::Out {
182 unary_kernel_owned(self, |a| {
183 ArithmeticKernel::wrapping_floor_div_scalar(a, rhs)
184 })
185 }
186
187 fn wrapping_floor_div_scalar_lhs(lhs: Self::Scalar, rhs: Self) -> Self::Out {
188 unary_kernel_owned(rhs, |a| {
189 ArithmeticKernel::wrapping_floor_div_scalar_lhs(lhs, a)
190 })
191 }
192
193 fn wrapping_trunc_div_scalar(self, rhs: Self::Scalar) -> Self::Out {
194 unary_kernel_owned(self, |a| {
195 ArithmeticKernel::wrapping_trunc_div_scalar(a, rhs)
196 })
197 }
198
199 fn wrapping_trunc_div_scalar_lhs(lhs: Self::Scalar, rhs: Self) -> Self::Out {
200 unary_kernel_owned(rhs, |a| {
201 ArithmeticKernel::wrapping_trunc_div_scalar_lhs(lhs, a)
202 })
203 }
204
205 fn wrapping_mod_scalar(self, rhs: Self::Scalar) -> Self::Out {
206 unary_kernel_owned(self, |a| ArithmeticKernel::wrapping_mod_scalar(a, rhs))
207 }
208
209 fn wrapping_mod_scalar_lhs(lhs: Self::Scalar, rhs: Self) -> Self::Out {
210 unary_kernel_owned(rhs, |a| ArithmeticKernel::wrapping_mod_scalar_lhs(lhs, a))
211 }
212
213 fn checked_mul_scalar(self, rhs: Self::Scalar) -> Self::Out {
214 unary_kernel_owned(self, |a| ArithmeticKernel::checked_mul_scalar(a, rhs))
215 }
216
217 fn true_div(self, rhs: Self) -> Self::TrueDivOut {
218 apply_binary_kernel_broadcast_owned(
219 self,
220 rhs,
221 ArithmeticKernel::true_div,
222 ArithmeticKernel::true_div_scalar_lhs,
223 ArithmeticKernel::true_div_scalar,
224 )
225 }
226
227 fn true_div_scalar(self, rhs: Self::Scalar) -> Self::TrueDivOut {
228 unary_kernel_owned(self, |a| ArithmeticKernel::true_div_scalar(a, rhs))
229 }
230
231 fn true_div_scalar_lhs(lhs: Self::Scalar, rhs: Self) -> Self::TrueDivOut {
232 unary_kernel_owned(rhs, |a| ArithmeticKernel::true_div_scalar_lhs(lhs, a))
233 }
234
235 fn legacy_div(self, rhs: Self) -> Self::Out {
236 apply_binary_kernel_broadcast_owned(
237 self,
238 rhs,
239 ArithmeticKernel::legacy_div,
240 ArithmeticKernel::legacy_div_scalar_lhs,
241 ArithmeticKernel::legacy_div_scalar,
242 )
243 }
244
245 fn legacy_div_scalar(self, rhs: Self::Scalar) -> Self::Out {
246 unary_kernel_owned(self, |a| ArithmeticKernel::legacy_div_scalar(a, rhs))
247 }
248
249 fn legacy_div_scalar_lhs(lhs: Self::Scalar, rhs: Self) -> Self::Out {
250 unary_kernel_owned(rhs, |a| ArithmeticKernel::legacy_div_scalar_lhs(lhs, a))
251 }
252}
253
254impl<T: PolarsNumericType> ArithmeticChunked for &ChunkedArray<T> {
255 type Scalar = T::Native;
256 type Out = ChunkedArray<T>;
257 type TrueDivOut = ChunkedArray<<T::Native as NumericNative>::TrueDivPolarsType>;
258
259 fn wrapping_abs(self) -> Self::Out {
260 unary_kernel(self, |a| ArithmeticKernel::wrapping_abs(a.clone()))
261 }
262
263 fn wrapping_neg(self) -> Self::Out {
264 unary_kernel(self, |a| ArithmeticKernel::wrapping_neg(a.clone()))
265 }
266
267 fn wrapping_add(self, rhs: Self) -> Self::Out {
268 apply_binary_kernel_broadcast(
269 self,
270 rhs,
271 |l, r| ArithmeticKernel::wrapping_add(l.clone(), r.clone()),
272 |l, r| ArithmeticKernel::wrapping_add_scalar(r.clone(), l),
273 |l, r| ArithmeticKernel::wrapping_add_scalar(l.clone(), r),
274 )
275 }
276
277 fn wrapping_sub(self, rhs: Self) -> Self::Out {
278 apply_binary_kernel_broadcast(
279 self,
280 rhs,
281 |l, r| ArithmeticKernel::wrapping_sub(l.clone(), r.clone()),
282 |l, r| ArithmeticKernel::wrapping_sub_scalar_lhs(l, r.clone()),
283 |l, r| ArithmeticKernel::wrapping_sub_scalar(l.clone(), r),
284 )
285 }
286
287 fn wrapping_mul(self, rhs: Self) -> Self::Out {
288 apply_binary_kernel_broadcast(
289 self,
290 rhs,
291 |l, r| ArithmeticKernel::wrapping_mul(l.clone(), r.clone()),
292 |l, r| ArithmeticKernel::wrapping_mul_scalar(r.clone(), l),
293 |l, r| ArithmeticKernel::wrapping_mul_scalar(l.clone(), r),
294 )
295 }
296
297 fn wrapping_floor_div(self, rhs: Self) -> Self::Out {
298 apply_binary_kernel_broadcast(
299 self,
300 rhs,
301 |l, r| ArithmeticKernel::wrapping_floor_div(l.clone(), r.clone()),
302 |l, r| ArithmeticKernel::wrapping_floor_div_scalar_lhs(l, r.clone()),
303 |l, r| ArithmeticKernel::wrapping_floor_div_scalar(l.clone(), r),
304 )
305 }
306
307 fn wrapping_trunc_div(self, rhs: Self) -> Self::Out {
308 apply_binary_kernel_broadcast(
309 self,
310 rhs,
311 |l, r| ArithmeticKernel::wrapping_trunc_div(l.clone(), r.clone()),
312 |l, r| ArithmeticKernel::wrapping_trunc_div_scalar_lhs(l, r.clone()),
313 |l, r| ArithmeticKernel::wrapping_trunc_div_scalar(l.clone(), r),
314 )
315 }
316
317 fn wrapping_mod(self, rhs: Self) -> Self::Out {
318 apply_binary_kernel_broadcast(
319 self,
320 rhs,
321 |l, r| ArithmeticKernel::wrapping_mod(l.clone(), r.clone()),
322 |l, r| ArithmeticKernel::wrapping_mod_scalar_lhs(l, r.clone()),
323 |l, r| ArithmeticKernel::wrapping_mod_scalar(l.clone(), r),
324 )
325 }
326
327 fn wrapping_add_scalar(self, rhs: Self::Scalar) -> Self::Out {
328 unary_kernel(self, |a| {
329 ArithmeticKernel::wrapping_add_scalar(a.clone(), rhs)
330 })
331 }
332
333 fn wrapping_sub_scalar(self, rhs: Self::Scalar) -> Self::Out {
334 unary_kernel(self, |a| {
335 ArithmeticKernel::wrapping_sub_scalar(a.clone(), rhs)
336 })
337 }
338
339 fn wrapping_sub_scalar_lhs(lhs: Self::Scalar, rhs: Self) -> Self::Out {
340 unary_kernel(rhs, |a| {
341 ArithmeticKernel::wrapping_sub_scalar_lhs(lhs, a.clone())
342 })
343 }
344
345 fn wrapping_mul_scalar(self, rhs: Self::Scalar) -> Self::Out {
346 unary_kernel(self, |a| {
347 ArithmeticKernel::wrapping_mul_scalar(a.clone(), rhs)
348 })
349 }
350
351 fn wrapping_floor_div_scalar(self, rhs: Self::Scalar) -> Self::Out {
352 unary_kernel(self, |a| {
353 ArithmeticKernel::wrapping_floor_div_scalar(a.clone(), rhs)
354 })
355 }
356
357 fn wrapping_floor_div_scalar_lhs(lhs: Self::Scalar, rhs: Self) -> Self::Out {
358 unary_kernel(rhs, |a| {
359 ArithmeticKernel::wrapping_floor_div_scalar_lhs(lhs, a.clone())
360 })
361 }
362
363 fn wrapping_trunc_div_scalar(self, rhs: Self::Scalar) -> Self::Out {
364 unary_kernel(self, |a| {
365 ArithmeticKernel::wrapping_trunc_div_scalar(a.clone(), rhs)
366 })
367 }
368
369 fn wrapping_trunc_div_scalar_lhs(lhs: Self::Scalar, rhs: Self) -> Self::Out {
370 unary_kernel(rhs, |a| {
371 ArithmeticKernel::wrapping_trunc_div_scalar_lhs(lhs, a.clone())
372 })
373 }
374
375 fn wrapping_mod_scalar(self, rhs: Self::Scalar) -> Self::Out {
376 unary_kernel(self, |a| {
377 ArithmeticKernel::wrapping_mod_scalar(a.clone(), rhs)
378 })
379 }
380
381 fn wrapping_mod_scalar_lhs(lhs: Self::Scalar, rhs: Self) -> Self::Out {
382 unary_kernel(rhs, |a| {
383 ArithmeticKernel::wrapping_mod_scalar_lhs(lhs, a.clone())
384 })
385 }
386
387 fn checked_mul_scalar(self, rhs: Self::Scalar) -> Self::Out {
388 unary_kernel(self, |a| {
389 ArithmeticKernel::checked_mul_scalar(a.clone(), rhs)
390 })
391 }
392
393 fn true_div(self, rhs: Self) -> Self::TrueDivOut {
394 apply_binary_kernel_broadcast(
395 self,
396 rhs,
397 |l, r| ArithmeticKernel::true_div(l.clone(), r.clone()),
398 |l, r| ArithmeticKernel::true_div_scalar_lhs(l, r.clone()),
399 |l, r| ArithmeticKernel::true_div_scalar(l.clone(), r),
400 )
401 }
402
403 fn true_div_scalar(self, rhs: Self::Scalar) -> Self::TrueDivOut {
404 unary_kernel(self, |a| ArithmeticKernel::true_div_scalar(a.clone(), rhs))
405 }
406
407 fn true_div_scalar_lhs(lhs: Self::Scalar, rhs: Self) -> Self::TrueDivOut {
408 unary_kernel(rhs, |a| {
409 ArithmeticKernel::true_div_scalar_lhs(lhs, a.clone())
410 })
411 }
412
413 fn legacy_div(self, rhs: Self) -> Self::Out {
414 apply_binary_kernel_broadcast(
415 self,
416 rhs,
417 |l, r| ArithmeticKernel::legacy_div(l.clone(), r.clone()),
418 |l, r| ArithmeticKernel::legacy_div_scalar_lhs(l, r.clone()),
419 |l, r| ArithmeticKernel::legacy_div_scalar(l.clone(), r),
420 )
421 }
422
423 fn legacy_div_scalar(self, rhs: Self::Scalar) -> Self::Out {
424 unary_kernel(self, |a| {
425 ArithmeticKernel::legacy_div_scalar(a.clone(), rhs)
426 })
427 }
428
429 fn legacy_div_scalar_lhs(lhs: Self::Scalar, rhs: Self) -> Self::Out {
430 unary_kernel(rhs, |a| {
431 ArithmeticKernel::legacy_div_scalar_lhs(lhs, a.clone())
432 })
433 }
434}