polars_compute/arithmetic/
pl_num.rs1use core::any::TypeId;
2
3use arrow::types::NativeType;
4use polars_utils::floor_divmod::FloorDivMod;
5
6pub trait PlNumArithmetic: Sized + Copy + 'static {
15 type TrueDivT: NativeType;
16
17 fn wrapping_abs(self) -> Self;
18 fn wrapping_neg(self) -> Self;
19 fn wrapping_add(self, rhs: Self) -> Self;
20 fn wrapping_sub(self, rhs: Self) -> Self;
21 fn wrapping_mul(self, rhs: Self) -> Self;
22 fn wrapping_floor_div(self, rhs: Self) -> Self;
23 fn wrapping_trunc_div(self, rhs: Self) -> Self;
24 fn wrapping_mod(self, rhs: Self) -> Self;
25
26 fn true_div(self, rhs: Self) -> Self::TrueDivT;
27
28 #[inline(always)]
29 fn legacy_div(self, rhs: Self) -> Self {
30 if TypeId::of::<Self>() == TypeId::of::<Self::TrueDivT>() {
31 let ret = self.true_div(rhs);
32 unsafe { core::mem::transmute_copy(&ret) }
33 } else {
34 self.wrapping_floor_div(rhs)
35 }
36 }
37}
38
39macro_rules! impl_signed_pl_num_arith {
40 ($T:ty) => {
41 impl PlNumArithmetic for $T {
42 type TrueDivT = f64;
43
44 #[inline(always)]
45 fn wrapping_abs(self) -> Self {
46 self.wrapping_abs()
47 }
48
49 #[inline(always)]
50 fn wrapping_neg(self) -> Self {
51 self.wrapping_neg()
52 }
53
54 #[inline(always)]
55 fn wrapping_add(self, rhs: Self) -> Self {
56 self.wrapping_add(rhs)
57 }
58
59 #[inline(always)]
60 fn wrapping_sub(self, rhs: Self) -> Self {
61 self.wrapping_sub(rhs)
62 }
63
64 #[inline(always)]
65 fn wrapping_mul(self, rhs: Self) -> Self {
66 self.wrapping_mul(rhs)
67 }
68
69 #[inline(always)]
70 fn wrapping_floor_div(self, rhs: Self) -> Self {
71 self.wrapping_floor_div_mod(rhs).0
72 }
73
74 #[inline(always)]
75 fn wrapping_trunc_div(self, rhs: Self) -> Self {
76 if rhs != 0 { self.wrapping_div(rhs) } else { 0 }
77 }
78
79 #[inline(always)]
80 fn wrapping_mod(self, rhs: Self) -> Self {
81 self.wrapping_floor_div_mod(rhs).1
82 }
83
84 #[inline(always)]
85 fn true_div(self, rhs: Self) -> Self::TrueDivT {
86 self as f64 / rhs as f64
87 }
88 }
89 };
90}
91
92impl_signed_pl_num_arith!(i8);
93impl_signed_pl_num_arith!(i16);
94impl_signed_pl_num_arith!(i32);
95impl_signed_pl_num_arith!(i64);
96impl_signed_pl_num_arith!(i128);
97
98macro_rules! impl_unsigned_pl_num_arith {
99 ($T:ty) => {
100 impl PlNumArithmetic for $T {
101 type TrueDivT = f64;
102
103 #[inline(always)]
104 fn wrapping_abs(self) -> Self {
105 self
106 }
107
108 #[inline(always)]
109 fn wrapping_neg(self) -> Self {
110 self.wrapping_neg()
111 }
112
113 #[inline(always)]
114 fn wrapping_add(self, rhs: Self) -> Self {
115 self.wrapping_add(rhs)
116 }
117
118 #[inline(always)]
119 fn wrapping_sub(self, rhs: Self) -> Self {
120 self.wrapping_sub(rhs)
121 }
122
123 #[inline(always)]
124 fn wrapping_mul(self, rhs: Self) -> Self {
125 self.wrapping_mul(rhs)
126 }
127
128 #[inline(always)]
129 fn wrapping_floor_div(self, rhs: Self) -> Self {
130 if rhs != 0 { self / rhs } else { 0 }
131 }
132
133 #[inline(always)]
134 fn wrapping_trunc_div(self, rhs: Self) -> Self {
135 self.wrapping_floor_div(rhs)
136 }
137
138 #[inline(always)]
139 fn wrapping_mod(self, rhs: Self) -> Self {
140 if rhs != 0 { self % rhs } else { 0 }
141 }
142
143 #[inline(always)]
144 fn true_div(self, rhs: Self) -> Self::TrueDivT {
145 self as f64 / rhs as f64
146 }
147 }
148 };
149}
150
151impl_unsigned_pl_num_arith!(u8);
152impl_unsigned_pl_num_arith!(u16);
153impl_unsigned_pl_num_arith!(u32);
154impl_unsigned_pl_num_arith!(u64);
155impl_unsigned_pl_num_arith!(u128);
156
157macro_rules! impl_float_pl_num_arith {
158 ($T:ty) => {
159 impl PlNumArithmetic for $T {
160 type TrueDivT = $T;
161
162 #[inline(always)]
163 fn wrapping_abs(self) -> Self {
164 self.abs()
165 }
166
167 #[inline(always)]
168 fn wrapping_neg(self) -> Self {
169 -self
170 }
171
172 #[inline(always)]
173 fn wrapping_add(self, rhs: Self) -> Self {
174 self + rhs
175 }
176
177 #[inline(always)]
178 fn wrapping_sub(self, rhs: Self) -> Self {
179 self - rhs
180 }
181
182 #[inline(always)]
183 fn wrapping_mul(self, rhs: Self) -> Self {
184 self * rhs
185 }
186
187 #[inline(always)]
188 fn wrapping_floor_div(self, rhs: Self) -> Self {
189 let l = self;
190 let r = rhs;
191 (l / r).floor()
192 }
193
194 #[inline(always)]
195 fn wrapping_trunc_div(self, rhs: Self) -> Self {
196 let l = self;
197 let r = rhs;
198 (l / r).trunc()
199 }
200
201 #[inline(always)]
202 fn wrapping_mod(self, rhs: Self) -> Self {
203 let l = self;
204 let r = rhs;
205 l - r * (l / r).floor()
206 }
207
208 #[inline(always)]
209 fn true_div(self, rhs: Self) -> Self::TrueDivT {
210 self / rhs
211 }
212 }
213 };
214}
215
216impl_float_pl_num_arith!(f32);
217impl_float_pl_num_arith!(f64);