1#[cfg(feature = "abs")]
2mod abs;
3#[cfg(feature = "arg_where")]
4mod arg_where;
5#[cfg(feature = "dtype-array")]
6mod array;
7mod binary;
8#[cfg(feature = "bitwise")]
9mod bitwise;
10mod boolean;
11mod bounds;
12#[cfg(feature = "business")]
13mod business;
14#[cfg(feature = "dtype-categorical")]
15pub mod cat;
16#[cfg(feature = "round_series")]
17mod clip;
18#[cfg(feature = "dtype-struct")]
19mod coerce;
20mod concat;
21#[cfg(feature = "cov")]
22mod correlation;
23#[cfg(feature = "cum_agg")]
24mod cum;
25#[cfg(feature = "cutqcut")]
26mod cut;
27#[cfg(feature = "temporal")]
28mod datetime;
29mod dispatch;
30#[cfg(feature = "ewma")]
31mod ewm;
32#[cfg(feature = "ewma_by")]
33mod ewm_by;
34mod fill_null;
35#[cfg(feature = "fused")]
36mod fused;
37#[cfg(feature = "index_of")]
38mod index_of;
39mod list;
40#[cfg(feature = "log")]
41mod log;
42mod nan;
43#[cfg(feature = "peaks")]
44mod peaks;
45#[cfg(feature = "ffi_plugin")]
46mod plugin;
47pub mod pow;
48#[cfg(feature = "random")]
49mod random;
50#[cfg(feature = "range")]
51mod range;
52mod repeat;
53#[cfg(feature = "rolling_window")]
54pub mod rolling;
55#[cfg(feature = "rolling_window_by")]
56pub mod rolling_by;
57#[cfg(feature = "round_series")]
58mod round;
59#[cfg(feature = "row_hash")]
60mod row_hash;
61pub(super) mod schema;
62#[cfg(feature = "search_sorted")]
63mod search_sorted;
64mod shift_and_fill;
65mod shrink_type;
66#[cfg(feature = "sign")]
67mod sign;
68#[cfg(feature = "strings")]
69mod strings;
70#[cfg(feature = "dtype-struct")]
71mod struct_;
72#[cfg(feature = "temporal")]
73mod temporal;
74#[cfg(feature = "trigonometry")]
75pub mod trigonometry;
76mod unique;
77
78use std::fmt::{Display, Formatter};
79use std::hash::{Hash, Hasher};
80
81#[cfg(feature = "dtype-array")]
82pub(crate) use array::ArrayFunction;
83#[cfg(feature = "cov")]
84pub(crate) use correlation::CorrelationMethod;
85#[cfg(feature = "fused")]
86pub(crate) use fused::FusedOperator;
87pub(crate) use list::ListFunction;
88use polars_core::datatypes::ReshapeDimension;
89use polars_core::prelude::*;
90#[cfg(feature = "random")]
91pub(crate) use random::RandomMethod;
92use schema::FieldsMapper;
93#[cfg(feature = "serde")]
94use serde::{Deserialize, Serialize};
95
96pub(crate) use self::binary::BinaryFunction;
97#[cfg(feature = "bitwise")]
98pub use self::bitwise::BitwiseFunction;
99pub use self::boolean::BooleanFunction;
100#[cfg(feature = "business")]
101pub(super) use self::business::BusinessFunction;
102#[cfg(feature = "dtype-categorical")]
103pub use self::cat::CategoricalFunction;
104#[cfg(feature = "temporal")]
105pub use self::datetime::TemporalFunction;
106pub use self::pow::PowFunction;
107#[cfg(feature = "range")]
108pub(super) use self::range::RangeFunction;
109#[cfg(feature = "rolling_window")]
110pub(super) use self::rolling::RollingFunction;
111#[cfg(feature = "rolling_window_by")]
112pub(super) use self::rolling_by::RollingFunctionBy;
113#[cfg(feature = "strings")]
114pub use self::strings::StringFunction;
115#[cfg(feature = "dtype-struct")]
116pub use self::struct_::StructFunction;
117#[cfg(feature = "trigonometry")]
118pub(super) use self::trigonometry::TrigonometricFunction;
119use super::*;
120
121#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
122#[derive(Clone, PartialEq, Debug)]
123pub enum FunctionExpr {
124 #[cfg(feature = "dtype-array")]
126 ArrayExpr(ArrayFunction),
127 BinaryExpr(BinaryFunction),
128 #[cfg(feature = "dtype-categorical")]
129 Categorical(CategoricalFunction),
130 ListExpr(ListFunction),
131 #[cfg(feature = "strings")]
132 StringExpr(StringFunction),
133 #[cfg(feature = "dtype-struct")]
134 StructExpr(StructFunction),
135 #[cfg(feature = "temporal")]
136 TemporalExpr(TemporalFunction),
137 #[cfg(feature = "bitwise")]
138 Bitwise(BitwiseFunction),
139
140 Boolean(BooleanFunction),
142 #[cfg(feature = "business")]
143 Business(BusinessFunction),
144 #[cfg(feature = "abs")]
145 Abs,
146 Negate,
147 #[cfg(feature = "hist")]
148 Hist {
149 bin_count: Option<usize>,
150 include_category: bool,
151 include_breakpoint: bool,
152 },
153 NullCount,
154 Pow(PowFunction),
155 #[cfg(feature = "row_hash")]
156 Hash(u64, u64, u64, u64),
157 #[cfg(feature = "arg_where")]
158 ArgWhere,
159 #[cfg(feature = "index_of")]
160 IndexOf,
161 #[cfg(feature = "search_sorted")]
162 SearchSorted(SearchSortedSide),
163 #[cfg(feature = "range")]
164 Range(RangeFunction),
165 #[cfg(feature = "trigonometry")]
166 Trigonometry(TrigonometricFunction),
167 #[cfg(feature = "trigonometry")]
168 Atan2,
169 #[cfg(feature = "sign")]
170 Sign,
171 FillNull,
172 FillNullWithStrategy(FillNullStrategy),
173 #[cfg(feature = "rolling_window")]
174 RollingExpr(RollingFunction),
175 #[cfg(feature = "rolling_window_by")]
176 RollingExprBy(RollingFunctionBy),
177 ShiftAndFill,
178 Shift,
179 DropNans,
180 DropNulls,
181 #[cfg(feature = "mode")]
182 Mode,
183 #[cfg(feature = "moment")]
184 Skew(bool),
185 #[cfg(feature = "moment")]
186 Kurtosis(bool, bool),
187 #[cfg(feature = "dtype-array")]
188 Reshape(Vec<ReshapeDimension>),
189 #[cfg(feature = "repeat_by")]
190 RepeatBy,
191 ArgUnique,
192 #[cfg(feature = "rank")]
193 Rank {
194 options: RankOptions,
195 seed: Option<u64>,
196 },
197 Repeat,
198 #[cfg(feature = "round_series")]
199 Clip {
200 has_min: bool,
201 has_max: bool,
202 },
203 #[cfg(feature = "dtype-struct")]
204 AsStruct,
205 #[cfg(feature = "top_k")]
206 TopK {
207 descending: bool,
208 },
209 #[cfg(feature = "top_k")]
210 TopKBy {
211 descending: Vec<bool>,
212 },
213 #[cfg(feature = "cum_agg")]
214 CumCount {
215 reverse: bool,
216 },
217 #[cfg(feature = "cum_agg")]
218 CumSum {
219 reverse: bool,
220 },
221 #[cfg(feature = "cum_agg")]
222 CumProd {
223 reverse: bool,
224 },
225 #[cfg(feature = "cum_agg")]
226 CumMin {
227 reverse: bool,
228 },
229 #[cfg(feature = "cum_agg")]
230 CumMax {
231 reverse: bool,
232 },
233 Reverse,
234 #[cfg(feature = "dtype-struct")]
235 ValueCounts {
236 sort: bool,
237 parallel: bool,
238 name: PlSmallStr,
239 normalize: bool,
240 },
241 #[cfg(feature = "unique_counts")]
242 UniqueCounts,
243 #[cfg(feature = "approx_unique")]
244 ApproxNUnique,
245 Coalesce,
246 ShrinkType,
247 #[cfg(feature = "diff")]
248 Diff(i64, NullBehavior),
249 #[cfg(feature = "pct_change")]
250 PctChange,
251 #[cfg(feature = "interpolate")]
252 Interpolate(InterpolationMethod),
253 #[cfg(feature = "interpolate_by")]
254 InterpolateBy,
255 #[cfg(feature = "log")]
256 Entropy {
257 base: f64,
258 normalize: bool,
259 },
260 #[cfg(feature = "log")]
261 Log {
262 base: f64,
263 },
264 #[cfg(feature = "log")]
265 Log1p,
266 #[cfg(feature = "log")]
267 Exp,
268 Unique(bool),
269 #[cfg(feature = "round_series")]
270 Round {
271 decimals: u32,
272 },
273 #[cfg(feature = "round_series")]
274 RoundSF {
275 digits: i32,
276 },
277 #[cfg(feature = "round_series")]
278 Floor,
279 #[cfg(feature = "round_series")]
280 Ceil,
281 UpperBound,
282 LowerBound,
283 #[cfg(feature = "fused")]
284 Fused(fused::FusedOperator),
285 ConcatExpr(bool),
286 #[cfg(feature = "cov")]
287 Correlation {
288 method: correlation::CorrelationMethod,
289 },
290 #[cfg(feature = "peaks")]
291 PeakMin,
292 #[cfg(feature = "peaks")]
293 PeakMax,
294 #[cfg(feature = "cutqcut")]
295 Cut {
296 breaks: Vec<f64>,
297 labels: Option<Vec<PlSmallStr>>,
298 left_closed: bool,
299 include_breaks: bool,
300 },
301 #[cfg(feature = "cutqcut")]
302 QCut {
303 probs: Vec<f64>,
304 labels: Option<Vec<PlSmallStr>>,
305 left_closed: bool,
306 allow_duplicates: bool,
307 include_breaks: bool,
308 },
309 #[cfg(feature = "rle")]
310 RLE,
311 #[cfg(feature = "rle")]
312 RLEID,
313 ToPhysical,
314 #[cfg(feature = "random")]
315 Random {
316 method: random::RandomMethod,
317 seed: Option<u64>,
318 },
319 SetSortedFlag(IsSorted),
320 #[cfg(feature = "ffi_plugin")]
321 FfiPlugin {
324 lib: PlSmallStr,
326 symbol: PlSmallStr,
328 kwargs: Arc<[u8]>,
330 },
331 BackwardFill {
332 limit: FillNullLimit,
333 },
334 ForwardFill {
335 limit: FillNullLimit,
336 },
337 MaxHorizontal,
338 MinHorizontal,
339 SumHorizontal {
340 ignore_nulls: bool,
341 },
342 MeanHorizontal {
343 ignore_nulls: bool,
344 },
345 #[cfg(feature = "ewma")]
346 EwmMean {
347 options: EWMOptions,
348 },
349 #[cfg(feature = "ewma_by")]
350 EwmMeanBy {
351 half_life: Duration,
352 },
353 #[cfg(feature = "ewma")]
354 EwmStd {
355 options: EWMOptions,
356 },
357 #[cfg(feature = "ewma")]
358 EwmVar {
359 options: EWMOptions,
360 },
361 #[cfg(feature = "replace")]
362 Replace,
363 #[cfg(feature = "replace")]
364 ReplaceStrict {
365 return_dtype: Option<DataType>,
366 },
367 GatherEvery {
368 n: usize,
369 offset: usize,
370 },
371 #[cfg(feature = "reinterpret")]
372 Reinterpret(bool),
373 ExtendConstant,
374}
375
376impl Hash for FunctionExpr {
377 fn hash<H: Hasher>(&self, state: &mut H) {
378 std::mem::discriminant(self).hash(state);
379 use FunctionExpr::*;
380 match self {
381 #[cfg(feature = "dtype-array")]
383 ArrayExpr(f) => f.hash(state),
384 BinaryExpr(f) => f.hash(state),
385 #[cfg(feature = "dtype-categorical")]
386 Categorical(f) => f.hash(state),
387 ListExpr(f) => f.hash(state),
388 #[cfg(feature = "strings")]
389 StringExpr(f) => f.hash(state),
390 #[cfg(feature = "dtype-struct")]
391 StructExpr(f) => f.hash(state),
392 #[cfg(feature = "temporal")]
393 TemporalExpr(f) => f.hash(state),
394 #[cfg(feature = "bitwise")]
395 Bitwise(f) => f.hash(state),
396
397 Boolean(f) => f.hash(state),
399 #[cfg(feature = "business")]
400 Business(f) => f.hash(state),
401 Pow(f) => f.hash(state),
402 #[cfg(feature = "index_of")]
403 IndexOf => {},
404 #[cfg(feature = "search_sorted")]
405 SearchSorted(f) => f.hash(state),
406 #[cfg(feature = "random")]
407 Random { method, .. } => method.hash(state),
408 #[cfg(feature = "cov")]
409 Correlation { method, .. } => method.hash(state),
410 #[cfg(feature = "range")]
411 Range(f) => f.hash(state),
412 #[cfg(feature = "trigonometry")]
413 Trigonometry(f) => f.hash(state),
414 #[cfg(feature = "fused")]
415 Fused(f) => f.hash(state),
416 #[cfg(feature = "diff")]
417 Diff(_, null_behavior) => null_behavior.hash(state),
418 #[cfg(feature = "interpolate")]
419 Interpolate(f) => f.hash(state),
420 #[cfg(feature = "interpolate_by")]
421 InterpolateBy => {},
422 #[cfg(feature = "ffi_plugin")]
423 FfiPlugin {
424 lib,
425 symbol,
426 kwargs,
427 } => {
428 kwargs.hash(state);
429 lib.hash(state);
430 symbol.hash(state);
431 },
432 MaxHorizontal
433 | MinHorizontal
434 | SumHorizontal { .. }
435 | MeanHorizontal { .. }
436 | DropNans
437 | DropNulls
438 | Reverse
439 | ArgUnique
440 | Shift
441 | ShiftAndFill => {},
442 #[cfg(feature = "mode")]
443 Mode => {},
444 #[cfg(feature = "abs")]
445 Abs => {},
446 Negate => {},
447 NullCount => {},
448 #[cfg(feature = "arg_where")]
449 ArgWhere => {},
450 #[cfg(feature = "trigonometry")]
451 Atan2 => {},
452 #[cfg(feature = "dtype-struct")]
453 AsStruct => {},
454 #[cfg(feature = "sign")]
455 Sign => {},
456 #[cfg(feature = "row_hash")]
457 Hash(a, b, c, d) => (a, b, c, d).hash(state),
458 FillNull => {},
459 #[cfg(feature = "rolling_window")]
460 RollingExpr(f) => {
461 f.hash(state);
462 },
463 #[cfg(feature = "rolling_window_by")]
464 RollingExprBy(f) => {
465 f.hash(state);
466 },
467 #[cfg(feature = "moment")]
468 Skew(a) => a.hash(state),
469 #[cfg(feature = "moment")]
470 Kurtosis(a, b) => {
471 a.hash(state);
472 b.hash(state);
473 },
474 Repeat => {},
475 #[cfg(feature = "rank")]
476 Rank { options, seed } => {
477 options.hash(state);
478 seed.hash(state);
479 },
480 #[cfg(feature = "round_series")]
481 Clip { has_min, has_max } => {
482 has_min.hash(state);
483 has_max.hash(state);
484 },
485 #[cfg(feature = "top_k")]
486 TopK { descending } => descending.hash(state),
487 #[cfg(feature = "cum_agg")]
488 CumCount { reverse } => reverse.hash(state),
489 #[cfg(feature = "cum_agg")]
490 CumSum { reverse } => reverse.hash(state),
491 #[cfg(feature = "cum_agg")]
492 CumProd { reverse } => reverse.hash(state),
493 #[cfg(feature = "cum_agg")]
494 CumMin { reverse } => reverse.hash(state),
495 #[cfg(feature = "cum_agg")]
496 CumMax { reverse } => reverse.hash(state),
497 #[cfg(feature = "dtype-struct")]
498 ValueCounts {
499 sort,
500 parallel,
501 name,
502 normalize,
503 } => {
504 sort.hash(state);
505 parallel.hash(state);
506 name.hash(state);
507 normalize.hash(state);
508 },
509 #[cfg(feature = "unique_counts")]
510 UniqueCounts => {},
511 #[cfg(feature = "approx_unique")]
512 ApproxNUnique => {},
513 Coalesce => {},
514 ShrinkType => {},
515 #[cfg(feature = "pct_change")]
516 PctChange => {},
517 #[cfg(feature = "log")]
518 Entropy { base, normalize } => {
519 base.to_bits().hash(state);
520 normalize.hash(state);
521 },
522 #[cfg(feature = "log")]
523 Log { base } => base.to_bits().hash(state),
524 #[cfg(feature = "log")]
525 Log1p => {},
526 #[cfg(feature = "log")]
527 Exp => {},
528 Unique(a) => a.hash(state),
529 #[cfg(feature = "round_series")]
530 Round { decimals } => decimals.hash(state),
531 #[cfg(feature = "round_series")]
532 FunctionExpr::RoundSF { digits } => digits.hash(state),
533 #[cfg(feature = "round_series")]
534 FunctionExpr::Floor => {},
535 #[cfg(feature = "round_series")]
536 Ceil => {},
537 UpperBound => {},
538 LowerBound => {},
539 ConcatExpr(a) => a.hash(state),
540 #[cfg(feature = "peaks")]
541 PeakMin => {},
542 #[cfg(feature = "peaks")]
543 PeakMax => {},
544 #[cfg(feature = "cutqcut")]
545 Cut {
546 breaks,
547 labels,
548 left_closed,
549 include_breaks,
550 } => {
551 let slice = bytemuck::cast_slice::<_, u64>(breaks);
552 slice.hash(state);
553 labels.hash(state);
554 left_closed.hash(state);
555 include_breaks.hash(state);
556 },
557 #[cfg(feature = "dtype-array")]
558 Reshape(dims) => dims.hash(state),
559 #[cfg(feature = "repeat_by")]
560 RepeatBy => {},
561 #[cfg(feature = "cutqcut")]
562 QCut {
563 probs,
564 labels,
565 left_closed,
566 allow_duplicates,
567 include_breaks,
568 } => {
569 let slice = bytemuck::cast_slice::<_, u64>(probs);
570 slice.hash(state);
571 labels.hash(state);
572 left_closed.hash(state);
573 allow_duplicates.hash(state);
574 include_breaks.hash(state);
575 },
576 #[cfg(feature = "rle")]
577 RLE => {},
578 #[cfg(feature = "rle")]
579 RLEID => {},
580 ToPhysical => {},
581 SetSortedFlag(is_sorted) => is_sorted.hash(state),
582 BackwardFill { limit } | ForwardFill { limit } => limit.hash(state),
583 #[cfg(feature = "ewma")]
584 EwmMean { options } => options.hash(state),
585 #[cfg(feature = "ewma_by")]
586 EwmMeanBy { half_life } => (half_life).hash(state),
587 #[cfg(feature = "ewma")]
588 EwmStd { options } => options.hash(state),
589 #[cfg(feature = "ewma")]
590 EwmVar { options } => options.hash(state),
591 #[cfg(feature = "hist")]
592 Hist {
593 bin_count,
594 include_category,
595 include_breakpoint,
596 } => {
597 bin_count.hash(state);
598 include_category.hash(state);
599 include_breakpoint.hash(state);
600 },
601 #[cfg(feature = "replace")]
602 Replace => {},
603 #[cfg(feature = "replace")]
604 ReplaceStrict { return_dtype } => return_dtype.hash(state),
605 FillNullWithStrategy(strategy) => strategy.hash(state),
606 GatherEvery { n, offset } => (n, offset).hash(state),
607 #[cfg(feature = "reinterpret")]
608 Reinterpret(signed) => signed.hash(state),
609 ExtendConstant => {},
610 #[cfg(feature = "top_k")]
611 TopKBy { descending } => descending.hash(state),
612 }
613 }
614}
615
616impl Display for FunctionExpr {
617 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
618 use FunctionExpr::*;
619 let s = match self {
620 #[cfg(feature = "dtype-array")]
622 ArrayExpr(func) => return write!(f, "{func}"),
623 BinaryExpr(func) => return write!(f, "{func}"),
624 #[cfg(feature = "dtype-categorical")]
625 Categorical(func) => return write!(f, "{func}"),
626 ListExpr(func) => return write!(f, "{func}"),
627 #[cfg(feature = "strings")]
628 StringExpr(func) => return write!(f, "{func}"),
629 #[cfg(feature = "dtype-struct")]
630 StructExpr(func) => return write!(f, "{func}"),
631 #[cfg(feature = "temporal")]
632 TemporalExpr(func) => return write!(f, "{func}"),
633 #[cfg(feature = "bitwise")]
634 Bitwise(func) => return write!(f, "bitwise_{func}"),
635
636 Boolean(func) => return write!(f, "{func}"),
638 #[cfg(feature = "business")]
639 Business(func) => return write!(f, "{func}"),
640 #[cfg(feature = "abs")]
641 Abs => "abs",
642 Negate => "negate",
643 NullCount => "null_count",
644 Pow(func) => return write!(f, "{func}"),
645 #[cfg(feature = "row_hash")]
646 Hash(_, _, _, _) => "hash",
647 #[cfg(feature = "arg_where")]
648 ArgWhere => "arg_where",
649 #[cfg(feature = "index_of")]
650 IndexOf => "index_of",
651 #[cfg(feature = "search_sorted")]
652 SearchSorted(_) => "search_sorted",
653 #[cfg(feature = "range")]
654 Range(func) => return write!(f, "{func}"),
655 #[cfg(feature = "trigonometry")]
656 Trigonometry(func) => return write!(f, "{func}"),
657 #[cfg(feature = "trigonometry")]
658 Atan2 => return write!(f, "arctan2"),
659 #[cfg(feature = "sign")]
660 Sign => "sign",
661 FillNull { .. } => "fill_null",
662 #[cfg(feature = "rolling_window")]
663 RollingExpr(func, ..) => return write!(f, "{func}"),
664 #[cfg(feature = "rolling_window_by")]
665 RollingExprBy(func, ..) => return write!(f, "{func}"),
666 ShiftAndFill => "shift_and_fill",
667 DropNans => "drop_nans",
668 DropNulls => "drop_nulls",
669 #[cfg(feature = "mode")]
670 Mode => "mode",
671 #[cfg(feature = "moment")]
672 Skew(_) => "skew",
673 #[cfg(feature = "moment")]
674 Kurtosis(..) => "kurtosis",
675 ArgUnique => "arg_unique",
676 Repeat => "repeat",
677 #[cfg(feature = "rank")]
678 Rank { .. } => "rank",
679 #[cfg(feature = "round_series")]
680 Clip { has_min, has_max } => match (has_min, has_max) {
681 (true, true) => "clip",
682 (false, true) => "clip_max",
683 (true, false) => "clip_min",
684 _ => unreachable!(),
685 },
686 #[cfg(feature = "dtype-struct")]
687 AsStruct => "as_struct",
688 #[cfg(feature = "top_k")]
689 TopK { descending } => {
690 if *descending {
691 "bottom_k"
692 } else {
693 "top_k"
694 }
695 },
696 #[cfg(feature = "top_k")]
697 TopKBy { .. } => "top_k_by",
698 Shift => "shift",
699 #[cfg(feature = "cum_agg")]
700 CumCount { .. } => "cum_count",
701 #[cfg(feature = "cum_agg")]
702 CumSum { .. } => "cum_sum",
703 #[cfg(feature = "cum_agg")]
704 CumProd { .. } => "cum_prod",
705 #[cfg(feature = "cum_agg")]
706 CumMin { .. } => "cum_min",
707 #[cfg(feature = "cum_agg")]
708 CumMax { .. } => "cum_max",
709 #[cfg(feature = "dtype-struct")]
710 ValueCounts { .. } => "value_counts",
711 #[cfg(feature = "unique_counts")]
712 UniqueCounts => "unique_counts",
713 Reverse => "reverse",
714 #[cfg(feature = "approx_unique")]
715 ApproxNUnique => "approx_n_unique",
716 Coalesce => "coalesce",
717 ShrinkType => "shrink_dtype",
718 #[cfg(feature = "diff")]
719 Diff(_, _) => "diff",
720 #[cfg(feature = "pct_change")]
721 PctChange => "pct_change",
722 #[cfg(feature = "interpolate")]
723 Interpolate(_) => "interpolate",
724 #[cfg(feature = "interpolate_by")]
725 InterpolateBy => "interpolate_by",
726 #[cfg(feature = "log")]
727 Entropy { .. } => "entropy",
728 #[cfg(feature = "log")]
729 Log { .. } => "log",
730 #[cfg(feature = "log")]
731 Log1p => "log1p",
732 #[cfg(feature = "log")]
733 Exp => "exp",
734 Unique(stable) => {
735 if *stable {
736 "unique_stable"
737 } else {
738 "unique"
739 }
740 },
741 #[cfg(feature = "round_series")]
742 Round { .. } => "round",
743 #[cfg(feature = "round_series")]
744 RoundSF { .. } => "round_sig_figs",
745 #[cfg(feature = "round_series")]
746 Floor => "floor",
747 #[cfg(feature = "round_series")]
748 Ceil => "ceil",
749 UpperBound => "upper_bound",
750 LowerBound => "lower_bound",
751 #[cfg(feature = "fused")]
752 Fused(fused) => return Display::fmt(fused, f),
753 ConcatExpr(_) => "concat_expr",
754 #[cfg(feature = "cov")]
755 Correlation { method, .. } => return Display::fmt(method, f),
756 #[cfg(feature = "peaks")]
757 PeakMin => "peak_min",
758 #[cfg(feature = "peaks")]
759 PeakMax => "peak_max",
760 #[cfg(feature = "cutqcut")]
761 Cut { .. } => "cut",
762 #[cfg(feature = "cutqcut")]
763 QCut { .. } => "qcut",
764 #[cfg(feature = "dtype-array")]
765 Reshape(_) => "reshape",
766 #[cfg(feature = "repeat_by")]
767 RepeatBy => "repeat_by",
768 #[cfg(feature = "rle")]
769 RLE => "rle",
770 #[cfg(feature = "rle")]
771 RLEID => "rle_id",
772 ToPhysical => "to_physical",
773 #[cfg(feature = "random")]
774 Random { method, .. } => method.into(),
775 SetSortedFlag(_) => "set_sorted",
776 #[cfg(feature = "ffi_plugin")]
777 FfiPlugin { lib, symbol, .. } => return write!(f, "{lib}:{symbol}"),
778 BackwardFill { .. } => "backward_fill",
779 ForwardFill { .. } => "forward_fill",
780 MaxHorizontal => "max_horizontal",
781 MinHorizontal => "min_horizontal",
782 SumHorizontal { .. } => "sum_horizontal",
783 MeanHorizontal { .. } => "mean_horizontal",
784 #[cfg(feature = "ewma")]
785 EwmMean { .. } => "ewm_mean",
786 #[cfg(feature = "ewma_by")]
787 EwmMeanBy { .. } => "ewm_mean_by",
788 #[cfg(feature = "ewma")]
789 EwmStd { .. } => "ewm_std",
790 #[cfg(feature = "ewma")]
791 EwmVar { .. } => "ewm_var",
792 #[cfg(feature = "hist")]
793 Hist { .. } => "hist",
794 #[cfg(feature = "replace")]
795 Replace => "replace",
796 #[cfg(feature = "replace")]
797 ReplaceStrict { .. } => "replace_strict",
798 FillNullWithStrategy(_) => "fill_null_with_strategy",
799 GatherEvery { .. } => "gather_every",
800 #[cfg(feature = "reinterpret")]
801 Reinterpret(_) => "reinterpret",
802 ExtendConstant => "extend_constant",
803 };
804 write!(f, "{s}")
805 }
806}
807
808#[macro_export]
809macro_rules! wrap {
810 ($e:expr) => {
811 SpecialEq::new(Arc::new($e))
812 };
813
814 ($e:expr, $($args:expr),*) => {{
815 let f = move |s: &mut [Column]| {
816 $e(s, $($args),*)
817 };
818
819 SpecialEq::new(Arc::new(f))
820 }};
821}
822
823#[macro_export]
827macro_rules! map_as_slice {
828 ($func:path) => {{
829 let f = move |s: &mut [Column]| {
830 $func(s).map(Some)
831 };
832
833 SpecialEq::new(Arc::new(f))
834 }};
835
836 ($func:path, $($args:expr),*) => {{
837 let f = move |s: &mut [Column]| {
838 $func(s, $($args),*).map(Some)
839 };
840
841 SpecialEq::new(Arc::new(f))
842 }};
843}
844
845#[macro_export]
848macro_rules! map_owned {
849 ($func:path) => {{
850 let f = move |c: &mut [Column]| {
851 let c = std::mem::take(&mut c[0]);
852 $func(c).map(Some)
853 };
854
855 SpecialEq::new(Arc::new(f))
856 }};
857
858 ($func:path, $($args:expr),*) => {{
859 let f = move |c: &mut [Column]| {
860 let c = std::mem::take(&mut c[0]);
861 $func(c, $($args),*).map(Some)
862 };
863
864 SpecialEq::new(Arc::new(f))
865 }};
866}
867
868#[macro_export]
870macro_rules! map {
871 ($func:path) => {{
872 let f = move |c: &mut [Column]| {
873 let c = &c[0];
874 $func(c).map(Some)
875 };
876
877 SpecialEq::new(Arc::new(f))
878 }};
879
880 ($func:path, $($args:expr),*) => {{
881 let f = move |c: &mut [Column]| {
882 let c = &c[0];
883 $func(c, $($args),*).map(Some)
884 };
885
886 SpecialEq::new(Arc::new(f))
887 }};
888}
889
890impl From<FunctionExpr> for SpecialEq<Arc<dyn ColumnsUdf>> {
891 fn from(func: FunctionExpr) -> Self {
892 use FunctionExpr::*;
893 match func {
894 #[cfg(feature = "dtype-array")]
896 ArrayExpr(func) => func.into(),
897 BinaryExpr(func) => func.into(),
898 #[cfg(feature = "dtype-categorical")]
899 Categorical(func) => func.into(),
900 ListExpr(func) => func.into(),
901 #[cfg(feature = "strings")]
902 StringExpr(func) => func.into(),
903 #[cfg(feature = "dtype-struct")]
904 StructExpr(func) => func.into(),
905 #[cfg(feature = "temporal")]
906 TemporalExpr(func) => func.into(),
907 #[cfg(feature = "bitwise")]
908 Bitwise(func) => func.into(),
909
910 Boolean(func) => func.into(),
912 #[cfg(feature = "business")]
913 Business(func) => func.into(),
914 #[cfg(feature = "abs")]
915 Abs => map!(abs::abs),
916 Negate => map!(dispatch::negate),
917 NullCount => {
918 let f = |s: &mut [Column]| {
919 let s = &s[0];
920 Ok(Some(Column::new(
921 s.name().clone(),
922 [s.null_count() as IdxSize],
923 )))
924 };
925 wrap!(f)
926 },
927 Pow(func) => match func {
928 PowFunction::Generic => wrap!(pow::pow),
929 PowFunction::Sqrt => map!(pow::sqrt),
930 PowFunction::Cbrt => map!(pow::cbrt),
931 },
932 #[cfg(feature = "row_hash")]
933 Hash(k0, k1, k2, k3) => {
934 map!(row_hash::row_hash, k0, k1, k2, k3)
935 },
936 #[cfg(feature = "arg_where")]
937 ArgWhere => {
938 wrap!(arg_where::arg_where)
939 },
940 #[cfg(feature = "index_of")]
941 IndexOf => {
942 map_as_slice!(index_of::index_of)
943 },
944 #[cfg(feature = "search_sorted")]
945 SearchSorted(side) => {
946 map_as_slice!(search_sorted::search_sorted_impl, side)
947 },
948 #[cfg(feature = "range")]
949 Range(func) => func.into(),
950
951 #[cfg(feature = "trigonometry")]
952 Trigonometry(trig_function) => {
953 map!(trigonometry::apply_trigonometric_function, trig_function)
954 },
955 #[cfg(feature = "trigonometry")]
956 Atan2 => {
957 wrap!(trigonometry::apply_arctan2)
958 },
959
960 #[cfg(feature = "sign")]
961 Sign => {
962 map!(sign::sign)
963 },
964 FillNull => {
965 map_as_slice!(fill_null::fill_null)
966 },
967 #[cfg(feature = "rolling_window")]
968 RollingExpr(f) => {
969 use RollingFunction::*;
970 match f {
971 Min(options) => map!(rolling::rolling_min, options.clone()),
972 Max(options) => map!(rolling::rolling_max, options.clone()),
973 Mean(options) => map!(rolling::rolling_mean, options.clone()),
974 Sum(options) => map!(rolling::rolling_sum, options.clone()),
975 Quantile(options) => map!(rolling::rolling_quantile, options.clone()),
976 Var(options) => map!(rolling::rolling_var, options.clone()),
977 Std(options) => map!(rolling::rolling_std, options.clone()),
978 #[cfg(feature = "moment")]
979 Skew(window_size, bias) => map!(rolling::rolling_skew, window_size, bias),
980 #[cfg(feature = "cov")]
981 CorrCov {
982 rolling_options,
983 corr_cov_options,
984 is_corr,
985 } => {
986 map_as_slice!(
987 rolling::rolling_corr_cov,
988 rolling_options.clone(),
989 corr_cov_options,
990 is_corr
991 )
992 },
993 }
994 },
995 #[cfg(feature = "rolling_window_by")]
996 RollingExprBy(f) => {
997 use RollingFunctionBy::*;
998 match f {
999 MinBy(options) => map_as_slice!(rolling_by::rolling_min_by, options.clone()),
1000 MaxBy(options) => map_as_slice!(rolling_by::rolling_max_by, options.clone()),
1001 MeanBy(options) => map_as_slice!(rolling_by::rolling_mean_by, options.clone()),
1002 SumBy(options) => map_as_slice!(rolling_by::rolling_sum_by, options.clone()),
1003 QuantileBy(options) => {
1004 map_as_slice!(rolling_by::rolling_quantile_by, options.clone())
1005 },
1006 VarBy(options) => map_as_slice!(rolling_by::rolling_var_by, options.clone()),
1007 StdBy(options) => map_as_slice!(rolling_by::rolling_std_by, options.clone()),
1008 }
1009 },
1010 #[cfg(feature = "hist")]
1011 Hist {
1012 bin_count,
1013 include_category,
1014 include_breakpoint,
1015 } => {
1016 map_as_slice!(
1017 dispatch::hist,
1018 bin_count,
1019 include_category,
1020 include_breakpoint
1021 )
1022 },
1023 ShiftAndFill => {
1024 map_as_slice!(shift_and_fill::shift_and_fill)
1025 },
1026 DropNans => map_owned!(nan::drop_nans),
1027 DropNulls => map!(dispatch::drop_nulls),
1028 #[cfg(feature = "round_series")]
1029 Clip { has_min, has_max } => {
1030 map_as_slice!(clip::clip, has_min, has_max)
1031 },
1032 #[cfg(feature = "mode")]
1033 Mode => map!(dispatch::mode),
1034 #[cfg(feature = "moment")]
1035 Skew(bias) => map!(dispatch::skew, bias),
1036 #[cfg(feature = "moment")]
1037 Kurtosis(fisher, bias) => map!(dispatch::kurtosis, fisher, bias),
1038 ArgUnique => map!(dispatch::arg_unique),
1039 Repeat => map_as_slice!(repeat::repeat),
1040 #[cfg(feature = "rank")]
1041 Rank { options, seed } => map!(dispatch::rank, options, seed),
1042 #[cfg(feature = "dtype-struct")]
1043 AsStruct => {
1044 map_as_slice!(coerce::as_struct)
1045 },
1046 #[cfg(feature = "top_k")]
1047 TopK { descending } => {
1048 map_as_slice!(top_k, descending)
1049 },
1050 #[cfg(feature = "top_k")]
1051 TopKBy { descending } => map_as_slice!(top_k_by, descending.clone()),
1052 Shift => map_as_slice!(shift_and_fill::shift),
1053 #[cfg(feature = "cum_agg")]
1054 CumCount { reverse } => map!(cum::cum_count, reverse),
1055 #[cfg(feature = "cum_agg")]
1056 CumSum { reverse } => map!(cum::cum_sum, reverse),
1057 #[cfg(feature = "cum_agg")]
1058 CumProd { reverse } => map!(cum::cum_prod, reverse),
1059 #[cfg(feature = "cum_agg")]
1060 CumMin { reverse } => map!(cum::cum_min, reverse),
1061 #[cfg(feature = "cum_agg")]
1062 CumMax { reverse } => map!(cum::cum_max, reverse),
1063 #[cfg(feature = "dtype-struct")]
1064 ValueCounts {
1065 sort,
1066 parallel,
1067 name,
1068 normalize,
1069 } => map!(
1070 dispatch::value_counts,
1071 sort,
1072 parallel,
1073 name.clone(),
1074 normalize
1075 ),
1076 #[cfg(feature = "unique_counts")]
1077 UniqueCounts => map!(dispatch::unique_counts),
1078 Reverse => map!(dispatch::reverse),
1079 #[cfg(feature = "approx_unique")]
1080 ApproxNUnique => map!(dispatch::approx_n_unique),
1081 Coalesce => map_as_slice!(fill_null::coalesce),
1082 ShrinkType => map_owned!(shrink_type::shrink),
1083 #[cfg(feature = "diff")]
1084 Diff(n, null_behavior) => map!(dispatch::diff, n, null_behavior),
1085 #[cfg(feature = "pct_change")]
1086 PctChange => map_as_slice!(dispatch::pct_change),
1087 #[cfg(feature = "interpolate")]
1088 Interpolate(method) => {
1089 map!(dispatch::interpolate, method)
1090 },
1091 #[cfg(feature = "interpolate_by")]
1092 InterpolateBy => {
1093 map_as_slice!(dispatch::interpolate_by)
1094 },
1095 #[cfg(feature = "log")]
1096 Entropy { base, normalize } => map!(log::entropy, base, normalize),
1097 #[cfg(feature = "log")]
1098 Log { base } => map!(log::log, base),
1099 #[cfg(feature = "log")]
1100 Log1p => map!(log::log1p),
1101 #[cfg(feature = "log")]
1102 Exp => map!(log::exp),
1103 Unique(stable) => map!(unique::unique, stable),
1104 #[cfg(feature = "round_series")]
1105 Round { decimals } => map!(round::round, decimals),
1106 #[cfg(feature = "round_series")]
1107 RoundSF { digits } => map!(round::round_sig_figs, digits),
1108 #[cfg(feature = "round_series")]
1109 Floor => map!(round::floor),
1110 #[cfg(feature = "round_series")]
1111 Ceil => map!(round::ceil),
1112 UpperBound => map!(bounds::upper_bound),
1113 LowerBound => map!(bounds::lower_bound),
1114 #[cfg(feature = "fused")]
1115 Fused(op) => map_as_slice!(fused::fused, op),
1116 ConcatExpr(rechunk) => map_as_slice!(concat::concat_expr, rechunk),
1117 #[cfg(feature = "cov")]
1118 Correlation { method } => map_as_slice!(correlation::corr, method),
1119 #[cfg(feature = "peaks")]
1120 PeakMin => map!(peaks::peak_min),
1121 #[cfg(feature = "peaks")]
1122 PeakMax => map!(peaks::peak_max),
1123 #[cfg(feature = "repeat_by")]
1124 RepeatBy => map_as_slice!(dispatch::repeat_by),
1125 #[cfg(feature = "dtype-array")]
1126 Reshape(dims) => map!(dispatch::reshape, &dims),
1127 #[cfg(feature = "cutqcut")]
1128 Cut {
1129 breaks,
1130 labels,
1131 left_closed,
1132 include_breaks,
1133 } => map!(
1134 cut::cut,
1135 breaks.clone(),
1136 labels.clone(),
1137 left_closed,
1138 include_breaks
1139 ),
1140 #[cfg(feature = "cutqcut")]
1141 QCut {
1142 probs,
1143 labels,
1144 left_closed,
1145 allow_duplicates,
1146 include_breaks,
1147 } => map!(
1148 cut::qcut,
1149 probs.clone(),
1150 labels.clone(),
1151 left_closed,
1152 allow_duplicates,
1153 include_breaks
1154 ),
1155 #[cfg(feature = "rle")]
1156 RLE => map!(rle),
1157 #[cfg(feature = "rle")]
1158 RLEID => map!(rle_id),
1159 ToPhysical => map!(dispatch::to_physical),
1160 #[cfg(feature = "random")]
1161 Random { method, seed } => {
1162 use RandomMethod::*;
1163 match method {
1164 Shuffle => map!(random::shuffle, seed),
1165 Sample {
1166 is_fraction,
1167 with_replacement,
1168 shuffle,
1169 } => {
1170 if is_fraction {
1171 map_as_slice!(random::sample_frac, with_replacement, shuffle, seed)
1172 } else {
1173 map_as_slice!(random::sample_n, with_replacement, shuffle, seed)
1174 }
1175 },
1176 }
1177 },
1178 SetSortedFlag(sorted) => map!(dispatch::set_sorted_flag, sorted),
1179 #[cfg(feature = "ffi_plugin")]
1180 FfiPlugin {
1181 lib,
1182 symbol,
1183 kwargs,
1184 } => unsafe {
1185 map_as_slice!(
1186 plugin::call_plugin,
1187 lib.as_ref(),
1188 symbol.as_ref(),
1189 kwargs.as_ref()
1190 )
1191 },
1192 BackwardFill { limit } => map!(dispatch::backward_fill, limit),
1193 ForwardFill { limit } => map!(dispatch::forward_fill, limit),
1194 MaxHorizontal => wrap!(dispatch::max_horizontal),
1195 MinHorizontal => wrap!(dispatch::min_horizontal),
1196 SumHorizontal { ignore_nulls } => wrap!(dispatch::sum_horizontal, ignore_nulls),
1197 MeanHorizontal { ignore_nulls } => wrap!(dispatch::mean_horizontal, ignore_nulls),
1198 #[cfg(feature = "ewma")]
1199 EwmMean { options } => map!(ewm::ewm_mean, options),
1200 #[cfg(feature = "ewma_by")]
1201 EwmMeanBy { half_life } => map_as_slice!(ewm_by::ewm_mean_by, half_life),
1202 #[cfg(feature = "ewma")]
1203 EwmStd { options } => map!(ewm::ewm_std, options),
1204 #[cfg(feature = "ewma")]
1205 EwmVar { options } => map!(ewm::ewm_var, options),
1206 #[cfg(feature = "replace")]
1207 Replace => {
1208 map_as_slice!(dispatch::replace)
1209 },
1210 #[cfg(feature = "replace")]
1211 ReplaceStrict { return_dtype } => {
1212 map_as_slice!(dispatch::replace_strict, return_dtype.clone())
1213 },
1214
1215 FillNullWithStrategy(strategy) => map!(dispatch::fill_null_with_strategy, strategy),
1216 GatherEvery { n, offset } => map!(dispatch::gather_every, n, offset),
1217 #[cfg(feature = "reinterpret")]
1218 Reinterpret(signed) => map!(dispatch::reinterpret, signed),
1219 ExtendConstant => map_as_slice!(dispatch::extend_constant),
1220 }
1221 }
1222}