Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pola-rs
GitHub Repository: pola-rs/polars
Path: blob/main/crates/polars-core/src/series/implementations/time.rs
8424 views
1
//! This module exists to reduce compilation times.
2
//!
3
//! All the data types are backed by a physical type in memory e.g. Date -> i32, Datetime-> i64.
4
//!
5
//! Series lead to code implementations of all traits. Whereas there are a lot of duplicates due to
6
//! data types being backed by the same physical type. In this module we reduce compile times by
7
//! opting for a little more run time cost. We cast to the physical type -> apply the operation and
8
//! (depending on the result) cast back to the original type
9
//!
10
11
use super::*;
12
#[cfg(feature = "algorithm_group_by")]
13
use crate::frame::group_by::*;
14
use crate::prelude::*;
15
16
unsafe impl IntoSeries for TimeChunked {
17
fn into_series(self) -> Series {
18
Series(Arc::new(SeriesWrap(self)))
19
}
20
}
21
22
impl private::PrivateSeries for SeriesWrap<TimeChunked> {
23
fn compute_len(&mut self) {
24
self.0.physical_mut().compute_len()
25
}
26
27
fn _field(&self) -> Cow<'_, Field> {
28
Cow::Owned(self.0.field())
29
}
30
31
fn _dtype(&self) -> &DataType {
32
self.0.dtype()
33
}
34
35
fn _get_flags(&self) -> StatisticsFlags {
36
self.0.physical().get_flags()
37
}
38
39
fn _set_flags(&mut self, flags: StatisticsFlags) {
40
self.0.physical_mut().set_flags(flags)
41
}
42
43
#[cfg(feature = "zip_with")]
44
fn zip_with_same_type(&self, mask: &BooleanChunked, other: &Series) -> PolarsResult<Series> {
45
let other = other.to_physical_repr().into_owned();
46
self.0
47
.physical()
48
.zip_with(mask, other.as_ref().as_ref())
49
.map(|ca| ca.into_time().into_series())
50
}
51
52
fn into_total_eq_inner<'a>(&'a self) -> Box<dyn TotalEqInner + 'a> {
53
self.0.physical().into_total_eq_inner()
54
}
55
fn into_total_ord_inner<'a>(&'a self) -> Box<dyn TotalOrdInner + 'a> {
56
self.0.physical().into_total_ord_inner()
57
}
58
59
fn vec_hash(
60
&self,
61
random_state: PlSeedableRandomStateQuality,
62
buf: &mut Vec<u64>,
63
) -> PolarsResult<()> {
64
self.0.physical().vec_hash(random_state, buf)?;
65
Ok(())
66
}
67
68
fn vec_hash_combine(
69
&self,
70
build_hasher: PlSeedableRandomStateQuality,
71
hashes: &mut [u64],
72
) -> PolarsResult<()> {
73
self.0.physical().vec_hash_combine(build_hasher, hashes)?;
74
Ok(())
75
}
76
77
#[cfg(feature = "algorithm_group_by")]
78
unsafe fn agg_min(&self, groups: &GroupsType) -> Series {
79
self.0.physical().agg_min(groups).into_time().into_series()
80
}
81
82
#[cfg(feature = "algorithm_group_by")]
83
unsafe fn agg_max(&self, groups: &GroupsType) -> Series {
84
self.0.physical().agg_max(groups).into_time().into_series()
85
}
86
#[cfg(feature = "algorithm_group_by")]
87
unsafe fn agg_arg_min(&self, groups: &GroupsType) -> Series {
88
self.0.physical().agg_arg_min(groups)
89
}
90
91
#[cfg(feature = "algorithm_group_by")]
92
unsafe fn agg_arg_max(&self, groups: &GroupsType) -> Series {
93
self.0.physical().agg_arg_max(groups)
94
}
95
96
#[cfg(feature = "algorithm_group_by")]
97
unsafe fn agg_list(&self, groups: &GroupsType) -> Series {
98
// we cannot cast and dispatch as the inner type of the list would be incorrect
99
self.0
100
.physical()
101
.agg_list(groups)
102
.cast(&DataType::List(Box::new(self.dtype().clone())))
103
.unwrap()
104
}
105
106
fn subtract(&self, rhs: &Series) -> PolarsResult<Series> {
107
let rhs = rhs.time().map_err(|_| polars_err!(InvalidOperation: "cannot subtract a {} dtype with a series of type: {}", self.dtype(), rhs.dtype()))?;
108
109
let phys = self
110
.0
111
.physical()
112
.subtract(&rhs.physical().clone().into_series())?;
113
114
Ok(phys.into_duration(TimeUnit::Nanoseconds))
115
}
116
117
fn add_to(&self, rhs: &Series) -> PolarsResult<Series> {
118
polars_bail!(opq = add, DataType::Time, rhs.dtype());
119
}
120
121
fn multiply(&self, rhs: &Series) -> PolarsResult<Series> {
122
polars_bail!(opq = mul, self.0.dtype(), rhs.dtype());
123
}
124
125
fn divide(&self, rhs: &Series) -> PolarsResult<Series> {
126
polars_bail!(opq = div, self.0.dtype(), rhs.dtype());
127
}
128
129
fn remainder(&self, rhs: &Series) -> PolarsResult<Series> {
130
polars_bail!(opq = rem, self.0.dtype(), rhs.dtype());
131
}
132
133
#[cfg(feature = "algorithm_group_by")]
134
fn group_tuples(&self, multithreaded: bool, sorted: bool) -> PolarsResult<GroupsType> {
135
self.0.physical().group_tuples(multithreaded, sorted)
136
}
137
138
fn arg_sort_multiple(
139
&self,
140
by: &[Column],
141
options: &SortMultipleOptions,
142
) -> PolarsResult<IdxCa> {
143
self.0.physical().arg_sort_multiple(by, options)
144
}
145
}
146
147
impl SeriesTrait for SeriesWrap<TimeChunked> {
148
fn rename(&mut self, name: PlSmallStr) {
149
self.0.rename(name);
150
}
151
152
fn chunk_lengths(&self) -> ChunkLenIter<'_> {
153
self.0.physical().chunk_lengths()
154
}
155
fn name(&self) -> &PlSmallStr {
156
self.0.name()
157
}
158
159
fn chunks(&self) -> &Vec<ArrayRef> {
160
self.0.physical().chunks()
161
}
162
163
unsafe fn chunks_mut(&mut self) -> &mut Vec<ArrayRef> {
164
self.0.physical_mut().chunks_mut()
165
}
166
167
fn shrink_to_fit(&mut self) {
168
self.0.physical_mut().shrink_to_fit()
169
}
170
171
fn slice(&self, offset: i64, length: usize) -> Series {
172
self.0.slice(offset, length).into_series()
173
}
174
fn split_at(&self, offset: i64) -> (Series, Series) {
175
let (a, b) = self.0.split_at(offset);
176
(a.into_series(), b.into_series())
177
}
178
179
fn _sum_as_f64(&self) -> f64 {
180
self.0.physical()._sum_as_f64()
181
}
182
183
fn mean(&self) -> Option<f64> {
184
self.0.physical().mean()
185
}
186
187
fn median(&self) -> Option<f64> {
188
self.0.physical().median()
189
}
190
191
fn append(&mut self, other: &Series) -> PolarsResult<()> {
192
polars_ensure!(self.0.dtype() == other.dtype(), append);
193
let mut other = other.to_physical_repr().into_owned();
194
self.0
195
.physical_mut()
196
.append_owned(std::mem::take(other._get_inner_mut().as_mut()))
197
}
198
199
fn append_owned(&mut self, mut other: Series) -> PolarsResult<()> {
200
polars_ensure!(self.0.dtype() == other.dtype(), append);
201
self.0.physical_mut().append_owned(std::mem::take(
202
&mut other
203
._get_inner_mut()
204
.as_any_mut()
205
.downcast_mut::<TimeChunked>()
206
.unwrap()
207
.phys,
208
))
209
}
210
211
fn extend(&mut self, other: &Series) -> PolarsResult<()> {
212
polars_ensure!(self.0.dtype() == other.dtype(), extend);
213
// 3 refs
214
// ref Cow
215
// ref SeriesTrait
216
// ref ChunkedArray
217
let other = other.to_physical_repr();
218
self.0
219
.physical_mut()
220
.extend(other.as_ref().as_ref().as_ref())?;
221
Ok(())
222
}
223
224
fn filter(&self, filter: &BooleanChunked) -> PolarsResult<Series> {
225
self.0
226
.physical()
227
.filter(filter)
228
.map(|ca| ca.into_time().into_series())
229
}
230
231
fn take(&self, indices: &IdxCa) -> PolarsResult<Series> {
232
Ok(self.0.physical().take(indices)?.into_time().into_series())
233
}
234
235
unsafe fn take_unchecked(&self, indices: &IdxCa) -> Series {
236
self.0
237
.physical()
238
.take_unchecked(indices)
239
.into_time()
240
.into_series()
241
}
242
243
fn take_slice(&self, indices: &[IdxSize]) -> PolarsResult<Series> {
244
Ok(self.0.physical().take(indices)?.into_time().into_series())
245
}
246
247
unsafe fn take_slice_unchecked(&self, indices: &[IdxSize]) -> Series {
248
self.0
249
.physical()
250
.take_unchecked(indices)
251
.into_time()
252
.into_series()
253
}
254
255
fn deposit(&self, validity: &Bitmap) -> Series {
256
self.0
257
.physical()
258
.deposit(validity)
259
.into_time()
260
.into_series()
261
}
262
263
fn len(&self) -> usize {
264
self.0.len()
265
}
266
267
fn rechunk(&self) -> Series {
268
self.0
269
.physical()
270
.rechunk()
271
.into_owned()
272
.into_time()
273
.into_series()
274
}
275
276
fn new_from_index(&self, index: usize, length: usize) -> Series {
277
self.0
278
.physical()
279
.new_from_index(index, length)
280
.into_time()
281
.into_series()
282
}
283
284
fn cast(&self, dtype: &DataType, cast_options: CastOptions) -> PolarsResult<Series> {
285
match dtype {
286
DataType::String => Ok(self
287
.0
288
.clone()
289
.into_series()
290
.time()
291
.unwrap()
292
.to_string("%T")
293
.into_series()),
294
_ => self.0.cast_with_options(dtype, cast_options),
295
}
296
}
297
298
#[inline]
299
unsafe fn get_unchecked(&self, index: usize) -> AnyValue<'_> {
300
self.0.get_any_value_unchecked(index)
301
}
302
303
fn sort_with(&self, options: SortOptions) -> PolarsResult<Series> {
304
Ok(self
305
.0
306
.physical()
307
.sort_with(options)
308
.into_time()
309
.into_series())
310
}
311
312
fn arg_sort(&self, options: SortOptions) -> IdxCa {
313
self.0.physical().arg_sort(options)
314
}
315
316
fn null_count(&self) -> usize {
317
self.0.null_count()
318
}
319
320
fn has_nulls(&self) -> bool {
321
self.0.has_nulls()
322
}
323
324
#[cfg(feature = "algorithm_group_by")]
325
fn unique(&self) -> PolarsResult<Series> {
326
self.0
327
.physical()
328
.unique()
329
.map(|ca| ca.into_time().into_series())
330
}
331
332
#[cfg(feature = "algorithm_group_by")]
333
fn n_unique(&self) -> PolarsResult<usize> {
334
self.0.physical().n_unique()
335
}
336
337
#[cfg(feature = "algorithm_group_by")]
338
fn arg_unique(&self) -> PolarsResult<IdxCa> {
339
self.0.physical().arg_unique()
340
}
341
342
fn unique_id(&self) -> PolarsResult<(IdxSize, Vec<IdxSize>)> {
343
ChunkUnique::unique_id(self.0.physical())
344
}
345
346
fn is_null(&self) -> BooleanChunked {
347
self.0.is_null()
348
}
349
350
fn is_not_null(&self) -> BooleanChunked {
351
self.0.is_not_null()
352
}
353
354
fn reverse(&self) -> Series {
355
self.0.physical().reverse().into_time().into_series()
356
}
357
358
fn as_single_ptr(&mut self) -> PolarsResult<usize> {
359
self.0.physical_mut().as_single_ptr()
360
}
361
362
fn shift(&self, periods: i64) -> Series {
363
self.0.physical().shift(periods).into_time().into_series()
364
}
365
366
fn max_reduce(&self) -> PolarsResult<Scalar> {
367
let sc = self.0.physical().max_reduce();
368
let av = sc.value().as_time();
369
Ok(Scalar::new(self.dtype().clone(), av))
370
}
371
372
fn min_reduce(&self) -> PolarsResult<Scalar> {
373
let sc = self.0.physical().min_reduce();
374
let av = sc.value().as_time();
375
Ok(Scalar::new(self.dtype().clone(), av))
376
}
377
378
fn mean_reduce(&self) -> PolarsResult<Scalar> {
379
let mean = self.mean().map(|v| v as i64);
380
let av = AnyValue::from(mean).as_time();
381
Ok(Scalar::new(self.dtype().clone(), av))
382
}
383
384
fn median_reduce(&self) -> PolarsResult<Scalar> {
385
let median = self.median().map(|v| v as i64);
386
let av = AnyValue::from(median).as_time();
387
Ok(Scalar::new(self.dtype().clone(), av))
388
}
389
390
fn quantile_reduce(&self, quantile: f64, method: QuantileMethod) -> PolarsResult<Scalar> {
391
let quantile = self.0.physical().quantile_reduce(quantile, method)?;
392
let av = quantile.value().cast(&DataType::Int64);
393
Ok(Scalar::new(self.dtype().clone(), av.as_time()))
394
}
395
396
fn quantiles_reduce(&self, quantiles: &[f64], method: QuantileMethod) -> PolarsResult<Scalar> {
397
let result = self.0.physical().quantiles_reduce(quantiles, method)?;
398
if let AnyValue::List(float_s) = result.value() {
399
let float_ca = float_s.f64().unwrap();
400
let int_s = float_ca
401
.iter()
402
.map(|v: Option<f64>| v.map(|f| f as i64))
403
.collect::<Int64Chunked>()
404
.into_time()
405
.into_series();
406
Ok(Scalar::new(
407
DataType::List(Box::new(self.dtype().clone())),
408
AnyValue::List(int_s),
409
))
410
} else {
411
polars_bail!(ComputeError: "expected list scalar from quantiles_reduce")
412
}
413
}
414
415
#[cfg(feature = "approx_unique")]
416
fn approx_n_unique(&self) -> PolarsResult<IdxSize> {
417
Ok(ChunkApproxNUnique::approx_n_unique(self.0.physical()))
418
}
419
420
fn clone_inner(&self) -> Arc<dyn SeriesTrait> {
421
Arc::new(SeriesWrap(Clone::clone(&self.0)))
422
}
423
424
fn find_validity_mismatch(&self, other: &Series, idxs: &mut Vec<IdxSize>) {
425
self.0.physical().find_validity_mismatch(other, idxs)
426
}
427
428
fn as_any(&self) -> &dyn Any {
429
&self.0
430
}
431
432
fn as_any_mut(&mut self) -> &mut dyn Any {
433
&mut self.0
434
}
435
436
fn as_phys_any(&self) -> &dyn Any {
437
self.0.physical()
438
}
439
440
fn as_arc_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync> {
441
self as _
442
}
443
}
444
445
impl private::PrivateSeriesNumeric for SeriesWrap<TimeChunked> {
446
fn bit_repr(&self) -> Option<BitRepr> {
447
Some(self.0.physical().to_bit_repr())
448
}
449
}
450
451