Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pola-rs
GitHub Repository: pola-rs/polars
Path: blob/main/crates/polars-compute/src/arithmetic/pl_num.rs
8421 views
1
use core::any::TypeId;
2
3
use arrow::types::NativeType;
4
use polars_utils::float16::pf16;
5
use polars_utils::floor_divmod::FloorDivMod;
6
7
/// Implements basic arithmetic between scalars with the same behavior as `ArithmeticKernel`.
8
///
9
/// Note, however, that the user is responsible for setting the validity of
10
/// results for e.g. div/mod operations with 0 in the denominator.
11
///
12
/// This is intended as a low-level utility for custom arithmetic loops
13
/// (e.g. in list arithmetic). In most cases prefer using `ArithmeticKernel` or
14
/// `ArithmeticChunked` instead.
15
pub trait PlNumArithmetic: Sized + Copy + 'static {
16
type TrueDivT: NativeType;
17
18
fn wrapping_abs(self) -> Self;
19
fn wrapping_neg(self) -> Self;
20
fn wrapping_add(self, rhs: Self) -> Self;
21
fn wrapping_sub(self, rhs: Self) -> Self;
22
fn wrapping_mul(self, rhs: Self) -> Self;
23
fn wrapping_floor_div(self, rhs: Self) -> Self;
24
fn wrapping_trunc_div(self, rhs: Self) -> Self;
25
fn wrapping_mod(self, rhs: Self) -> Self;
26
27
fn true_div(self, rhs: Self) -> Self::TrueDivT;
28
29
#[inline(always)]
30
fn legacy_div(self, rhs: Self) -> Self {
31
if TypeId::of::<Self>() == TypeId::of::<Self::TrueDivT>() {
32
let ret = self.true_div(rhs);
33
unsafe { core::mem::transmute_copy(&ret) }
34
} else {
35
self.wrapping_floor_div(rhs)
36
}
37
}
38
}
39
40
macro_rules! impl_signed_pl_num_arith {
41
($T:ty) => {
42
impl PlNumArithmetic for $T {
43
type TrueDivT = f64;
44
45
#[inline(always)]
46
fn wrapping_abs(self) -> Self {
47
self.wrapping_abs()
48
}
49
50
#[inline(always)]
51
fn wrapping_neg(self) -> Self {
52
self.wrapping_neg()
53
}
54
55
#[inline(always)]
56
fn wrapping_add(self, rhs: Self) -> Self {
57
self.wrapping_add(rhs)
58
}
59
60
#[inline(always)]
61
fn wrapping_sub(self, rhs: Self) -> Self {
62
self.wrapping_sub(rhs)
63
}
64
65
#[inline(always)]
66
fn wrapping_mul(self, rhs: Self) -> Self {
67
self.wrapping_mul(rhs)
68
}
69
70
#[inline(always)]
71
fn wrapping_floor_div(self, rhs: Self) -> Self {
72
self.wrapping_floor_div_mod(rhs).0
73
}
74
75
#[inline(always)]
76
fn wrapping_trunc_div(self, rhs: Self) -> Self {
77
if rhs != 0 { self.wrapping_div(rhs) } else { 0 }
78
}
79
80
#[inline(always)]
81
fn wrapping_mod(self, rhs: Self) -> Self {
82
self.wrapping_floor_div_mod(rhs).1
83
}
84
85
#[inline(always)]
86
fn true_div(self, rhs: Self) -> Self::TrueDivT {
87
self as f64 / rhs as f64
88
}
89
}
90
};
91
}
92
93
impl_signed_pl_num_arith!(i8);
94
impl_signed_pl_num_arith!(i16);
95
impl_signed_pl_num_arith!(i32);
96
impl_signed_pl_num_arith!(i64);
97
impl_signed_pl_num_arith!(i128);
98
99
macro_rules! impl_unsigned_pl_num_arith {
100
($T:ty) => {
101
impl PlNumArithmetic for $T {
102
type TrueDivT = f64;
103
104
#[inline(always)]
105
fn wrapping_abs(self) -> Self {
106
self
107
}
108
109
#[inline(always)]
110
fn wrapping_neg(self) -> Self {
111
self.wrapping_neg()
112
}
113
114
#[inline(always)]
115
fn wrapping_add(self, rhs: Self) -> Self {
116
self.wrapping_add(rhs)
117
}
118
119
#[inline(always)]
120
fn wrapping_sub(self, rhs: Self) -> Self {
121
self.wrapping_sub(rhs)
122
}
123
124
#[inline(always)]
125
fn wrapping_mul(self, rhs: Self) -> Self {
126
self.wrapping_mul(rhs)
127
}
128
129
#[inline(always)]
130
fn wrapping_floor_div(self, rhs: Self) -> Self {
131
if rhs != 0 { self / rhs } else { 0 }
132
}
133
134
#[inline(always)]
135
fn wrapping_trunc_div(self, rhs: Self) -> Self {
136
self.wrapping_floor_div(rhs)
137
}
138
139
#[inline(always)]
140
fn wrapping_mod(self, rhs: Self) -> Self {
141
if rhs != 0 { self % rhs } else { 0 }
142
}
143
144
#[inline(always)]
145
fn true_div(self, rhs: Self) -> Self::TrueDivT {
146
self as f64 / rhs as f64
147
}
148
}
149
};
150
}
151
152
impl_unsigned_pl_num_arith!(u8);
153
impl_unsigned_pl_num_arith!(u16);
154
impl_unsigned_pl_num_arith!(u32);
155
impl_unsigned_pl_num_arith!(u64);
156
impl_unsigned_pl_num_arith!(u128);
157
158
macro_rules! impl_float_pl_num_arith {
159
($T:ty) => {
160
impl PlNumArithmetic for $T {
161
type TrueDivT = $T;
162
163
#[inline(always)]
164
fn wrapping_abs(self) -> Self {
165
self.abs()
166
}
167
168
#[inline(always)]
169
fn wrapping_neg(self) -> Self {
170
-self
171
}
172
173
#[inline(always)]
174
fn wrapping_add(self, rhs: Self) -> Self {
175
self + rhs
176
}
177
178
#[inline(always)]
179
fn wrapping_sub(self, rhs: Self) -> Self {
180
self - rhs
181
}
182
183
#[inline(always)]
184
fn wrapping_mul(self, rhs: Self) -> Self {
185
self * rhs
186
}
187
188
#[inline(always)]
189
fn wrapping_floor_div(self, rhs: Self) -> Self {
190
let l = self;
191
let r = rhs;
192
(l / r).floor()
193
}
194
195
#[inline(always)]
196
fn wrapping_trunc_div(self, rhs: Self) -> Self {
197
let l = self;
198
let r = rhs;
199
(l / r).trunc()
200
}
201
202
#[inline(always)]
203
fn wrapping_mod(self, rhs: Self) -> Self {
204
let l = self;
205
let r = rhs;
206
l - r * (l / r).floor()
207
}
208
209
#[inline(always)]
210
fn true_div(self, rhs: Self) -> Self::TrueDivT {
211
self / rhs
212
}
213
}
214
};
215
}
216
217
impl_float_pl_num_arith!(pf16);
218
impl_float_pl_num_arith!(f32);
219
impl_float_pl_num_arith!(f64);
220
221