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 use array::ArrayFunction;
83#[cfg(feature = "cov")]
84pub use correlation::CorrelationMethod;
85#[cfg(feature = "fused")]
86pub use fused::FusedOperator;
87pub use list::ListFunction;
88pub use polars_core::datatypes::ReshapeDimension;
89use polars_core::prelude::*;
90#[cfg(feature = "random")]
91pub use random::RandomMethod;
92use schema::FieldsMapper;
93#[cfg(feature = "serde")]
94use serde::{Deserialize, Serialize};
95
96pub use self::binary::BinaryFunction;
97#[cfg(feature = "bitwise")]
98pub use self::bitwise::BitwiseFunction;
99pub use self::boolean::BooleanFunction;
100#[cfg(feature = "business")]
101pub 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 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(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 mode: RoundMode,
273 },
274 #[cfg(feature = "round_series")]
275 RoundSF {
276 digits: i32,
277 },
278 #[cfg(feature = "round_series")]
279 Floor,
280 #[cfg(feature = "round_series")]
281 Ceil,
282 UpperBound,
283 LowerBound,
284 #[cfg(feature = "fused")]
285 Fused(fused::FusedOperator),
286 ConcatExpr(bool),
287 #[cfg(feature = "cov")]
288 Correlation {
289 method: correlation::CorrelationMethod,
290 },
291 #[cfg(feature = "peaks")]
292 PeakMin,
293 #[cfg(feature = "peaks")]
294 PeakMax,
295 #[cfg(feature = "cutqcut")]
296 Cut {
297 breaks: Vec<f64>,
298 labels: Option<Vec<PlSmallStr>>,
299 left_closed: bool,
300 include_breaks: bool,
301 },
302 #[cfg(feature = "cutqcut")]
303 QCut {
304 probs: Vec<f64>,
305 labels: Option<Vec<PlSmallStr>>,
306 left_closed: bool,
307 allow_duplicates: bool,
308 include_breaks: bool,
309 },
310 #[cfg(feature = "rle")]
311 RLE,
312 #[cfg(feature = "rle")]
313 RLEID,
314 ToPhysical,
315 #[cfg(feature = "random")]
316 Random {
317 method: random::RandomMethod,
318 seed: Option<u64>,
319 },
320 SetSortedFlag(IsSorted),
321 #[cfg(feature = "ffi_plugin")]
322 FfiPlugin {
325 flags: FunctionOptions,
326 lib: PlSmallStr,
328 symbol: PlSmallStr,
330 kwargs: Arc<[u8]>,
332 },
333 MaxHorizontal,
334 MinHorizontal,
335 SumHorizontal {
336 ignore_nulls: bool,
337 },
338 MeanHorizontal {
339 ignore_nulls: bool,
340 },
341 #[cfg(feature = "ewma")]
342 EwmMean {
343 options: EWMOptions,
344 },
345 #[cfg(feature = "ewma_by")]
346 EwmMeanBy {
347 half_life: Duration,
348 },
349 #[cfg(feature = "ewma")]
350 EwmStd {
351 options: EWMOptions,
352 },
353 #[cfg(feature = "ewma")]
354 EwmVar {
355 options: EWMOptions,
356 },
357 #[cfg(feature = "replace")]
358 Replace,
359 #[cfg(feature = "replace")]
360 ReplaceStrict {
361 return_dtype: Option<DataType>,
362 },
363 GatherEvery {
364 n: usize,
365 offset: usize,
366 },
367 #[cfg(feature = "reinterpret")]
368 Reinterpret(bool),
369 ExtendConstant,
370}
371
372impl Hash for FunctionExpr {
373 fn hash<H: Hasher>(&self, state: &mut H) {
374 std::mem::discriminant(self).hash(state);
375 use FunctionExpr::*;
376 match self {
377 #[cfg(feature = "dtype-array")]
379 ArrayExpr(f) => f.hash(state),
380 BinaryExpr(f) => f.hash(state),
381 #[cfg(feature = "dtype-categorical")]
382 Categorical(f) => f.hash(state),
383 ListExpr(f) => f.hash(state),
384 #[cfg(feature = "strings")]
385 StringExpr(f) => f.hash(state),
386 #[cfg(feature = "dtype-struct")]
387 StructExpr(f) => f.hash(state),
388 #[cfg(feature = "temporal")]
389 TemporalExpr(f) => f.hash(state),
390 #[cfg(feature = "bitwise")]
391 Bitwise(f) => f.hash(state),
392
393 Boolean(f) => f.hash(state),
395 #[cfg(feature = "business")]
396 Business(f) => f.hash(state),
397 Pow(f) => f.hash(state),
398 #[cfg(feature = "index_of")]
399 IndexOf => {},
400 #[cfg(feature = "search_sorted")]
401 SearchSorted(f) => f.hash(state),
402 #[cfg(feature = "random")]
403 Random { method, .. } => method.hash(state),
404 #[cfg(feature = "cov")]
405 Correlation { method, .. } => method.hash(state),
406 #[cfg(feature = "range")]
407 Range(f) => f.hash(state),
408 #[cfg(feature = "trigonometry")]
409 Trigonometry(f) => f.hash(state),
410 #[cfg(feature = "fused")]
411 Fused(f) => f.hash(state),
412 #[cfg(feature = "diff")]
413 Diff(null_behavior) => null_behavior.hash(state),
414 #[cfg(feature = "interpolate")]
415 Interpolate(f) => f.hash(state),
416 #[cfg(feature = "interpolate_by")]
417 InterpolateBy => {},
418 #[cfg(feature = "ffi_plugin")]
419 FfiPlugin {
420 flags: _,
421 lib,
422 symbol,
423 kwargs,
424 } => {
425 kwargs.hash(state);
426 lib.hash(state);
427 symbol.hash(state);
428 },
429 MaxHorizontal
430 | MinHorizontal
431 | SumHorizontal { .. }
432 | MeanHorizontal { .. }
433 | DropNans
434 | DropNulls
435 | Reverse
436 | ArgUnique
437 | Shift
438 | ShiftAndFill => {},
439 #[cfg(feature = "mode")]
440 Mode => {},
441 #[cfg(feature = "abs")]
442 Abs => {},
443 Negate => {},
444 NullCount => {},
445 #[cfg(feature = "arg_where")]
446 ArgWhere => {},
447 #[cfg(feature = "trigonometry")]
448 Atan2 => {},
449 #[cfg(feature = "dtype-struct")]
450 AsStruct => {},
451 #[cfg(feature = "sign")]
452 Sign => {},
453 #[cfg(feature = "row_hash")]
454 Hash(a, b, c, d) => (a, b, c, d).hash(state),
455 FillNull => {},
456 #[cfg(feature = "rolling_window")]
457 RollingExpr(f) => {
458 f.hash(state);
459 },
460 #[cfg(feature = "rolling_window_by")]
461 RollingExprBy(f) => {
462 f.hash(state);
463 },
464 #[cfg(feature = "moment")]
465 Skew(a) => a.hash(state),
466 #[cfg(feature = "moment")]
467 Kurtosis(a, b) => {
468 a.hash(state);
469 b.hash(state);
470 },
471 Repeat => {},
472 #[cfg(feature = "rank")]
473 Rank { options, seed } => {
474 options.hash(state);
475 seed.hash(state);
476 },
477 #[cfg(feature = "round_series")]
478 Clip { has_min, has_max } => {
479 has_min.hash(state);
480 has_max.hash(state);
481 },
482 #[cfg(feature = "top_k")]
483 TopK { descending } => descending.hash(state),
484 #[cfg(feature = "cum_agg")]
485 CumCount { reverse } => reverse.hash(state),
486 #[cfg(feature = "cum_agg")]
487 CumSum { reverse } => reverse.hash(state),
488 #[cfg(feature = "cum_agg")]
489 CumProd { reverse } => reverse.hash(state),
490 #[cfg(feature = "cum_agg")]
491 CumMin { reverse } => reverse.hash(state),
492 #[cfg(feature = "cum_agg")]
493 CumMax { reverse } => reverse.hash(state),
494 #[cfg(feature = "dtype-struct")]
495 ValueCounts {
496 sort,
497 parallel,
498 name,
499 normalize,
500 } => {
501 sort.hash(state);
502 parallel.hash(state);
503 name.hash(state);
504 normalize.hash(state);
505 },
506 #[cfg(feature = "unique_counts")]
507 UniqueCounts => {},
508 #[cfg(feature = "approx_unique")]
509 ApproxNUnique => {},
510 Coalesce => {},
511 ShrinkType => {},
512 #[cfg(feature = "pct_change")]
513 PctChange => {},
514 #[cfg(feature = "log")]
515 Entropy { base, normalize } => {
516 base.to_bits().hash(state);
517 normalize.hash(state);
518 },
519 #[cfg(feature = "log")]
520 Log { base } => base.to_bits().hash(state),
521 #[cfg(feature = "log")]
522 Log1p => {},
523 #[cfg(feature = "log")]
524 Exp => {},
525 Unique(a) => a.hash(state),
526 #[cfg(feature = "round_series")]
527 Round { decimals, mode } => {
528 decimals.hash(state);
529 mode.hash(state);
530 },
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 #[cfg(feature = "ewma")]
583 EwmMean { options } => options.hash(state),
584 #[cfg(feature = "ewma_by")]
585 EwmMeanBy { half_life } => (half_life).hash(state),
586 #[cfg(feature = "ewma")]
587 EwmStd { options } => options.hash(state),
588 #[cfg(feature = "ewma")]
589 EwmVar { options } => options.hash(state),
590 #[cfg(feature = "hist")]
591 Hist {
592 bin_count,
593 include_category,
594 include_breakpoint,
595 } => {
596 bin_count.hash(state);
597 include_category.hash(state);
598 include_breakpoint.hash(state);
599 },
600 #[cfg(feature = "replace")]
601 Replace => {},
602 #[cfg(feature = "replace")]
603 ReplaceStrict { return_dtype } => return_dtype.hash(state),
604 FillNullWithStrategy(strategy) => strategy.hash(state),
605 GatherEvery { n, offset } => (n, offset).hash(state),
606 #[cfg(feature = "reinterpret")]
607 Reinterpret(signed) => signed.hash(state),
608 ExtendConstant => {},
609 #[cfg(feature = "top_k")]
610 TopKBy { descending } => descending.hash(state),
611 }
612 }
613}
614
615impl Display for FunctionExpr {
616 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
617 use FunctionExpr::*;
618 let s = match self {
619 #[cfg(feature = "dtype-array")]
621 ArrayExpr(func) => return write!(f, "{func}"),
622 BinaryExpr(func) => return write!(f, "{func}"),
623 #[cfg(feature = "dtype-categorical")]
624 Categorical(func) => return write!(f, "{func}"),
625 ListExpr(func) => return write!(f, "{func}"),
626 #[cfg(feature = "strings")]
627 StringExpr(func) => return write!(f, "{func}"),
628 #[cfg(feature = "dtype-struct")]
629 StructExpr(func) => return write!(f, "{func}"),
630 #[cfg(feature = "temporal")]
631 TemporalExpr(func) => return write!(f, "{func}"),
632 #[cfg(feature = "bitwise")]
633 Bitwise(func) => return write!(f, "bitwise_{func}"),
634
635 Boolean(func) => return write!(f, "{func}"),
637 #[cfg(feature = "business")]
638 Business(func) => return write!(f, "{func}"),
639 #[cfg(feature = "abs")]
640 Abs => "abs",
641 Negate => "negate",
642 NullCount => "null_count",
643 Pow(func) => return write!(f, "{func}"),
644 #[cfg(feature = "row_hash")]
645 Hash(_, _, _, _) => "hash",
646 #[cfg(feature = "arg_where")]
647 ArgWhere => "arg_where",
648 #[cfg(feature = "index_of")]
649 IndexOf => "index_of",
650 #[cfg(feature = "search_sorted")]
651 SearchSorted(_) => "search_sorted",
652 #[cfg(feature = "range")]
653 Range(func) => return write!(f, "{func}"),
654 #[cfg(feature = "trigonometry")]
655 Trigonometry(func) => return write!(f, "{func}"),
656 #[cfg(feature = "trigonometry")]
657 Atan2 => return write!(f, "arctan2"),
658 #[cfg(feature = "sign")]
659 Sign => "sign",
660 FillNull => "fill_null",
661 #[cfg(feature = "rolling_window")]
662 RollingExpr(func, ..) => return write!(f, "{func}"),
663 #[cfg(feature = "rolling_window_by")]
664 RollingExprBy(func, ..) => return write!(f, "{func}"),
665 ShiftAndFill => "shift_and_fill",
666 DropNans => "drop_nans",
667 DropNulls => "drop_nulls",
668 #[cfg(feature = "mode")]
669 Mode => "mode",
670 #[cfg(feature = "moment")]
671 Skew(_) => "skew",
672 #[cfg(feature = "moment")]
673 Kurtosis(..) => "kurtosis",
674 ArgUnique => "arg_unique",
675 Repeat => "repeat",
676 #[cfg(feature = "rank")]
677 Rank { .. } => "rank",
678 #[cfg(feature = "round_series")]
679 Clip { has_min, has_max } => match (has_min, has_max) {
680 (true, true) => "clip",
681 (false, true) => "clip_max",
682 (true, false) => "clip_min",
683 _ => unreachable!(),
684 },
685 #[cfg(feature = "dtype-struct")]
686 AsStruct => "as_struct",
687 #[cfg(feature = "top_k")]
688 TopK { descending } => {
689 if *descending {
690 "bottom_k"
691 } else {
692 "top_k"
693 }
694 },
695 #[cfg(feature = "top_k")]
696 TopKBy { .. } => "top_k_by",
697 Shift => "shift",
698 #[cfg(feature = "cum_agg")]
699 CumCount { .. } => "cum_count",
700 #[cfg(feature = "cum_agg")]
701 CumSum { .. } => "cum_sum",
702 #[cfg(feature = "cum_agg")]
703 CumProd { .. } => "cum_prod",
704 #[cfg(feature = "cum_agg")]
705 CumMin { .. } => "cum_min",
706 #[cfg(feature = "cum_agg")]
707 CumMax { .. } => "cum_max",
708 #[cfg(feature = "dtype-struct")]
709 ValueCounts { .. } => "value_counts",
710 #[cfg(feature = "unique_counts")]
711 UniqueCounts => "unique_counts",
712 Reverse => "reverse",
713 #[cfg(feature = "approx_unique")]
714 ApproxNUnique => "approx_n_unique",
715 Coalesce => "coalesce",
716 ShrinkType => "shrink_dtype",
717 #[cfg(feature = "diff")]
718 Diff(_) => "diff",
719 #[cfg(feature = "pct_change")]
720 PctChange => "pct_change",
721 #[cfg(feature = "interpolate")]
722 Interpolate(_) => "interpolate",
723 #[cfg(feature = "interpolate_by")]
724 InterpolateBy => "interpolate_by",
725 #[cfg(feature = "log")]
726 Entropy { .. } => "entropy",
727 #[cfg(feature = "log")]
728 Log { .. } => "log",
729 #[cfg(feature = "log")]
730 Log1p => "log1p",
731 #[cfg(feature = "log")]
732 Exp => "exp",
733 Unique(stable) => {
734 if *stable {
735 "unique_stable"
736 } else {
737 "unique"
738 }
739 },
740 #[cfg(feature = "round_series")]
741 Round { .. } => "round",
742 #[cfg(feature = "round_series")]
743 RoundSF { .. } => "round_sig_figs",
744 #[cfg(feature = "round_series")]
745 Floor => "floor",
746 #[cfg(feature = "round_series")]
747 Ceil => "ceil",
748 UpperBound => "upper_bound",
749 LowerBound => "lower_bound",
750 #[cfg(feature = "fused")]
751 Fused(fused) => return Display::fmt(fused, f),
752 ConcatExpr(_) => "concat_expr",
753 #[cfg(feature = "cov")]
754 Correlation { method, .. } => return Display::fmt(method, f),
755 #[cfg(feature = "peaks")]
756 PeakMin => "peak_min",
757 #[cfg(feature = "peaks")]
758 PeakMax => "peak_max",
759 #[cfg(feature = "cutqcut")]
760 Cut { .. } => "cut",
761 #[cfg(feature = "cutqcut")]
762 QCut { .. } => "qcut",
763 #[cfg(feature = "dtype-array")]
764 Reshape(_) => "reshape",
765 #[cfg(feature = "repeat_by")]
766 RepeatBy => "repeat_by",
767 #[cfg(feature = "rle")]
768 RLE => "rle",
769 #[cfg(feature = "rle")]
770 RLEID => "rle_id",
771 ToPhysical => "to_physical",
772 #[cfg(feature = "random")]
773 Random { method, .. } => method.into(),
774 SetSortedFlag(_) => "set_sorted",
775 #[cfg(feature = "ffi_plugin")]
776 FfiPlugin { lib, symbol, .. } => return write!(f, "{lib}:{symbol}"),
777 MaxHorizontal => "max_horizontal",
778 MinHorizontal => "min_horizontal",
779 SumHorizontal { .. } => "sum_horizontal",
780 MeanHorizontal { .. } => "mean_horizontal",
781 #[cfg(feature = "ewma")]
782 EwmMean { .. } => "ewm_mean",
783 #[cfg(feature = "ewma_by")]
784 EwmMeanBy { .. } => "ewm_mean_by",
785 #[cfg(feature = "ewma")]
786 EwmStd { .. } => "ewm_std",
787 #[cfg(feature = "ewma")]
788 EwmVar { .. } => "ewm_var",
789 #[cfg(feature = "hist")]
790 Hist { .. } => "hist",
791 #[cfg(feature = "replace")]
792 Replace => "replace",
793 #[cfg(feature = "replace")]
794 ReplaceStrict { .. } => "replace_strict",
795 FillNullWithStrategy(_) => "fill_null_with_strategy",
796 GatherEvery { .. } => "gather_every",
797 #[cfg(feature = "reinterpret")]
798 Reinterpret(_) => "reinterpret",
799 ExtendConstant => "extend_constant",
800 };
801 write!(f, "{s}")
802 }
803}
804
805#[macro_export]
806macro_rules! wrap {
807 ($e:expr) => {
808 SpecialEq::new(Arc::new($e))
809 };
810
811 ($e:expr, $($args:expr),*) => {{
812 let f = move |s: &mut [Column]| {
813 $e(s, $($args),*)
814 };
815
816 SpecialEq::new(Arc::new(f))
817 }};
818}
819
820#[macro_export]
824macro_rules! map_as_slice {
825 ($func:path) => {{
826 let f = move |s: &mut [Column]| {
827 $func(s).map(Some)
828 };
829
830 SpecialEq::new(Arc::new(f))
831 }};
832
833 ($func:path, $($args:expr),*) => {{
834 let f = move |s: &mut [Column]| {
835 $func(s, $($args),*).map(Some)
836 };
837
838 SpecialEq::new(Arc::new(f))
839 }};
840}
841
842#[macro_export]
845macro_rules! map_owned {
846 ($func:path) => {{
847 let f = move |c: &mut [Column]| {
848 let c = std::mem::take(&mut c[0]);
849 $func(c).map(Some)
850 };
851
852 SpecialEq::new(Arc::new(f))
853 }};
854
855 ($func:path, $($args:expr),*) => {{
856 let f = move |c: &mut [Column]| {
857 let c = std::mem::take(&mut c[0]);
858 $func(c, $($args),*).map(Some)
859 };
860
861 SpecialEq::new(Arc::new(f))
862 }};
863}
864
865#[macro_export]
867macro_rules! map {
868 ($func:path) => {{
869 let f = move |c: &mut [Column]| {
870 let c = &c[0];
871 $func(c).map(Some)
872 };
873
874 SpecialEq::new(Arc::new(f))
875 }};
876
877 ($func:path, $($args:expr),*) => {{
878 let f = move |c: &mut [Column]| {
879 let c = &c[0];
880 $func(c, $($args),*).map(Some)
881 };
882
883 SpecialEq::new(Arc::new(f))
884 }};
885}
886
887impl From<FunctionExpr> for SpecialEq<Arc<dyn ColumnsUdf>> {
888 fn from(func: FunctionExpr) -> Self {
889 use FunctionExpr::*;
890 match func {
891 #[cfg(feature = "dtype-array")]
893 ArrayExpr(func) => func.into(),
894 BinaryExpr(func) => func.into(),
895 #[cfg(feature = "dtype-categorical")]
896 Categorical(func) => func.into(),
897 ListExpr(func) => func.into(),
898 #[cfg(feature = "strings")]
899 StringExpr(func) => func.into(),
900 #[cfg(feature = "dtype-struct")]
901 StructExpr(func) => func.into(),
902 #[cfg(feature = "temporal")]
903 TemporalExpr(func) => func.into(),
904 #[cfg(feature = "bitwise")]
905 Bitwise(func) => func.into(),
906
907 Boolean(func) => func.into(),
909 #[cfg(feature = "business")]
910 Business(func) => func.into(),
911 #[cfg(feature = "abs")]
912 Abs => map!(abs::abs),
913 Negate => map!(dispatch::negate),
914 NullCount => {
915 let f = |s: &mut [Column]| {
916 let s = &s[0];
917 Ok(Some(Column::new(
918 s.name().clone(),
919 [s.null_count() as IdxSize],
920 )))
921 };
922 wrap!(f)
923 },
924 Pow(func) => match func {
925 PowFunction::Generic => wrap!(pow::pow),
926 PowFunction::Sqrt => map!(pow::sqrt),
927 PowFunction::Cbrt => map!(pow::cbrt),
928 },
929 #[cfg(feature = "row_hash")]
930 Hash(k0, k1, k2, k3) => {
931 map!(row_hash::row_hash, k0, k1, k2, k3)
932 },
933 #[cfg(feature = "arg_where")]
934 ArgWhere => {
935 wrap!(arg_where::arg_where)
936 },
937 #[cfg(feature = "index_of")]
938 IndexOf => {
939 map_as_slice!(index_of::index_of)
940 },
941 #[cfg(feature = "search_sorted")]
942 SearchSorted(side) => {
943 map_as_slice!(search_sorted::search_sorted_impl, side)
944 },
945 #[cfg(feature = "range")]
946 Range(func) => func.into(),
947
948 #[cfg(feature = "trigonometry")]
949 Trigonometry(trig_function) => {
950 map!(trigonometry::apply_trigonometric_function, trig_function)
951 },
952 #[cfg(feature = "trigonometry")]
953 Atan2 => {
954 wrap!(trigonometry::apply_arctan2)
955 },
956
957 #[cfg(feature = "sign")]
958 Sign => {
959 map!(sign::sign)
960 },
961 FillNull => {
962 map_as_slice!(fill_null::fill_null)
963 },
964 #[cfg(feature = "rolling_window")]
965 RollingExpr(f) => {
966 use RollingFunction::*;
967 match f {
968 Min(options) => map!(rolling::rolling_min, options.clone()),
969 Max(options) => map!(rolling::rolling_max, options.clone()),
970 Mean(options) => map!(rolling::rolling_mean, options.clone()),
971 Sum(options) => map!(rolling::rolling_sum, options.clone()),
972 Quantile(options) => map!(rolling::rolling_quantile, options.clone()),
973 Var(options) => map!(rolling::rolling_var, options.clone()),
974 Std(options) => map!(rolling::rolling_std, options.clone()),
975 #[cfg(feature = "moment")]
976 Skew(options) => map!(rolling::rolling_skew, options.clone()),
977 #[cfg(feature = "moment")]
978 Kurtosis(options) => map!(rolling::rolling_kurtosis, options.clone()),
979 #[cfg(feature = "cov")]
980 CorrCov {
981 rolling_options,
982 corr_cov_options,
983 is_corr,
984 } => {
985 map_as_slice!(
986 rolling::rolling_corr_cov,
987 rolling_options.clone(),
988 corr_cov_options,
989 is_corr
990 )
991 },
992 }
993 },
994 #[cfg(feature = "rolling_window_by")]
995 RollingExprBy(f) => {
996 use RollingFunctionBy::*;
997 match f {
998 MinBy(options) => map_as_slice!(rolling_by::rolling_min_by, options.clone()),
999 MaxBy(options) => map_as_slice!(rolling_by::rolling_max_by, options.clone()),
1000 MeanBy(options) => map_as_slice!(rolling_by::rolling_mean_by, options.clone()),
1001 SumBy(options) => map_as_slice!(rolling_by::rolling_sum_by, options.clone()),
1002 QuantileBy(options) => {
1003 map_as_slice!(rolling_by::rolling_quantile_by, options.clone())
1004 },
1005 VarBy(options) => map_as_slice!(rolling_by::rolling_var_by, options.clone()),
1006 StdBy(options) => map_as_slice!(rolling_by::rolling_std_by, options.clone()),
1007 }
1008 },
1009 #[cfg(feature = "hist")]
1010 Hist {
1011 bin_count,
1012 include_category,
1013 include_breakpoint,
1014 } => {
1015 map_as_slice!(
1016 dispatch::hist,
1017 bin_count,
1018 include_category,
1019 include_breakpoint
1020 )
1021 },
1022 ShiftAndFill => {
1023 map_as_slice!(shift_and_fill::shift_and_fill)
1024 },
1025 DropNans => map_owned!(nan::drop_nans),
1026 DropNulls => map!(dispatch::drop_nulls),
1027 #[cfg(feature = "round_series")]
1028 Clip { has_min, has_max } => {
1029 map_as_slice!(clip::clip, has_min, has_max)
1030 },
1031 #[cfg(feature = "mode")]
1032 Mode => map!(dispatch::mode),
1033 #[cfg(feature = "moment")]
1034 Skew(bias) => map!(dispatch::skew, bias),
1035 #[cfg(feature = "moment")]
1036 Kurtosis(fisher, bias) => map!(dispatch::kurtosis, fisher, bias),
1037 ArgUnique => map!(dispatch::arg_unique),
1038 Repeat => map_as_slice!(repeat::repeat),
1039 #[cfg(feature = "rank")]
1040 Rank { options, seed } => map!(dispatch::rank, options, seed),
1041 #[cfg(feature = "dtype-struct")]
1042 AsStruct => {
1043 map_as_slice!(coerce::as_struct)
1044 },
1045 #[cfg(feature = "top_k")]
1046 TopK { descending } => {
1047 map_as_slice!(top_k, descending)
1048 },
1049 #[cfg(feature = "top_k")]
1050 TopKBy { descending } => map_as_slice!(top_k_by, descending.clone()),
1051 Shift => map_as_slice!(shift_and_fill::shift),
1052 #[cfg(feature = "cum_agg")]
1053 CumCount { reverse } => map!(cum::cum_count, reverse),
1054 #[cfg(feature = "cum_agg")]
1055 CumSum { reverse } => map!(cum::cum_sum, reverse),
1056 #[cfg(feature = "cum_agg")]
1057 CumProd { reverse } => map!(cum::cum_prod, reverse),
1058 #[cfg(feature = "cum_agg")]
1059 CumMin { reverse } => map!(cum::cum_min, reverse),
1060 #[cfg(feature = "cum_agg")]
1061 CumMax { reverse } => map!(cum::cum_max, reverse),
1062 #[cfg(feature = "dtype-struct")]
1063 ValueCounts {
1064 sort,
1065 parallel,
1066 name,
1067 normalize,
1068 } => map!(
1069 dispatch::value_counts,
1070 sort,
1071 parallel,
1072 name.clone(),
1073 normalize
1074 ),
1075 #[cfg(feature = "unique_counts")]
1076 UniqueCounts => map!(dispatch::unique_counts),
1077 Reverse => map!(dispatch::reverse),
1078 #[cfg(feature = "approx_unique")]
1079 ApproxNUnique => map!(dispatch::approx_n_unique),
1080 Coalesce => map_as_slice!(fill_null::coalesce),
1081 ShrinkType => map_owned!(shrink_type::shrink),
1082 #[cfg(feature = "diff")]
1083 Diff(null_behavior) => map_as_slice!(dispatch::diff, null_behavior),
1084 #[cfg(feature = "pct_change")]
1085 PctChange => map_as_slice!(dispatch::pct_change),
1086 #[cfg(feature = "interpolate")]
1087 Interpolate(method) => {
1088 map!(dispatch::interpolate, method)
1089 },
1090 #[cfg(feature = "interpolate_by")]
1091 InterpolateBy => {
1092 map_as_slice!(dispatch::interpolate_by)
1093 },
1094 #[cfg(feature = "log")]
1095 Entropy { base, normalize } => map!(log::entropy, base, normalize),
1096 #[cfg(feature = "log")]
1097 Log { base } => map!(log::log, base),
1098 #[cfg(feature = "log")]
1099 Log1p => map!(log::log1p),
1100 #[cfg(feature = "log")]
1101 Exp => map!(log::exp),
1102 Unique(stable) => map!(unique::unique, stable),
1103 #[cfg(feature = "round_series")]
1104 Round { decimals, mode } => map!(round::round, decimals, mode),
1105 #[cfg(feature = "round_series")]
1106 RoundSF { digits } => map!(round::round_sig_figs, digits),
1107 #[cfg(feature = "round_series")]
1108 Floor => map!(round::floor),
1109 #[cfg(feature = "round_series")]
1110 Ceil => map!(round::ceil),
1111 UpperBound => map!(bounds::upper_bound),
1112 LowerBound => map!(bounds::lower_bound),
1113 #[cfg(feature = "fused")]
1114 Fused(op) => map_as_slice!(fused::fused, op),
1115 ConcatExpr(rechunk) => map_as_slice!(concat::concat_expr, rechunk),
1116 #[cfg(feature = "cov")]
1117 Correlation { method } => map_as_slice!(correlation::corr, method),
1118 #[cfg(feature = "peaks")]
1119 PeakMin => map!(peaks::peak_min),
1120 #[cfg(feature = "peaks")]
1121 PeakMax => map!(peaks::peak_max),
1122 #[cfg(feature = "repeat_by")]
1123 RepeatBy => map_as_slice!(dispatch::repeat_by),
1124 #[cfg(feature = "dtype-array")]
1125 Reshape(dims) => map!(dispatch::reshape, &dims),
1126 #[cfg(feature = "cutqcut")]
1127 Cut {
1128 breaks,
1129 labels,
1130 left_closed,
1131 include_breaks,
1132 } => map!(
1133 cut::cut,
1134 breaks.clone(),
1135 labels.clone(),
1136 left_closed,
1137 include_breaks
1138 ),
1139 #[cfg(feature = "cutqcut")]
1140 QCut {
1141 probs,
1142 labels,
1143 left_closed,
1144 allow_duplicates,
1145 include_breaks,
1146 } => map!(
1147 cut::qcut,
1148 probs.clone(),
1149 labels.clone(),
1150 left_closed,
1151 allow_duplicates,
1152 include_breaks
1153 ),
1154 #[cfg(feature = "rle")]
1155 RLE => map!(rle),
1156 #[cfg(feature = "rle")]
1157 RLEID => map!(rle_id),
1158 ToPhysical => map!(dispatch::to_physical),
1159 #[cfg(feature = "random")]
1160 Random { method, seed } => {
1161 use RandomMethod::*;
1162 match method {
1163 Shuffle => map!(random::shuffle, seed),
1164 Sample {
1165 is_fraction,
1166 with_replacement,
1167 shuffle,
1168 } => {
1169 if is_fraction {
1170 map_as_slice!(random::sample_frac, with_replacement, shuffle, seed)
1171 } else {
1172 map_as_slice!(random::sample_n, with_replacement, shuffle, seed)
1173 }
1174 },
1175 }
1176 },
1177 SetSortedFlag(sorted) => map!(dispatch::set_sorted_flag, sorted),
1178 #[cfg(feature = "ffi_plugin")]
1179 FfiPlugin {
1180 flags: _,
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 MaxHorizontal => wrap!(dispatch::max_horizontal),
1193 MinHorizontal => wrap!(dispatch::min_horizontal),
1194 SumHorizontal { ignore_nulls } => wrap!(dispatch::sum_horizontal, ignore_nulls),
1195 MeanHorizontal { ignore_nulls } => wrap!(dispatch::mean_horizontal, ignore_nulls),
1196 #[cfg(feature = "ewma")]
1197 EwmMean { options } => map!(ewm::ewm_mean, options),
1198 #[cfg(feature = "ewma_by")]
1199 EwmMeanBy { half_life } => map_as_slice!(ewm_by::ewm_mean_by, half_life),
1200 #[cfg(feature = "ewma")]
1201 EwmStd { options } => map!(ewm::ewm_std, options),
1202 #[cfg(feature = "ewma")]
1203 EwmVar { options } => map!(ewm::ewm_var, options),
1204 #[cfg(feature = "replace")]
1205 Replace => {
1206 map_as_slice!(dispatch::replace)
1207 },
1208 #[cfg(feature = "replace")]
1209 ReplaceStrict { return_dtype } => {
1210 map_as_slice!(dispatch::replace_strict, return_dtype.clone())
1211 },
1212
1213 FillNullWithStrategy(strategy) => map!(dispatch::fill_null_with_strategy, strategy),
1214 GatherEvery { n, offset } => map!(dispatch::gather_every, n, offset),
1215 #[cfg(feature = "reinterpret")]
1216 Reinterpret(signed) => map!(dispatch::reinterpret, signed),
1217 ExtendConstant => map_as_slice!(dispatch::extend_constant),
1218 }
1219 }
1220}
1221
1222impl FunctionExpr {
1223 pub fn function_options(&self) -> FunctionOptions {
1224 use FunctionExpr as F;
1225 match self {
1226 #[cfg(feature = "dtype-array")]
1227 F::ArrayExpr(e) => e.function_options(),
1228 F::BinaryExpr(e) => e.function_options(),
1229 #[cfg(feature = "dtype-categorical")]
1230 F::Categorical(e) => e.function_options(),
1231 F::ListExpr(e) => e.function_options(),
1232 #[cfg(feature = "strings")]
1233 F::StringExpr(e) => e.function_options(),
1234 #[cfg(feature = "dtype-struct")]
1235 F::StructExpr(e) => e.function_options(),
1236 #[cfg(feature = "temporal")]
1237 F::TemporalExpr(e) => e.function_options(),
1238 #[cfg(feature = "bitwise")]
1239 F::Bitwise(e) => e.function_options(),
1240 F::Boolean(e) => e.function_options(),
1241 #[cfg(feature = "business")]
1242 F::Business(e) => e.function_options(),
1243 F::Pow(e) => e.function_options(),
1244 #[cfg(feature = "range")]
1245 F::Range(e) => e.function_options(),
1246 #[cfg(feature = "abs")]
1247 F::Abs => FunctionOptions::elementwise(),
1248 F::Negate => FunctionOptions::elementwise(),
1249 #[cfg(feature = "hist")]
1250 F::Hist { .. } => FunctionOptions::groupwise(),
1251 F::NullCount => FunctionOptions::aggregation(),
1252 #[cfg(feature = "row_hash")]
1253 F::Hash(_, _, _, _) => FunctionOptions::elementwise(),
1254 #[cfg(feature = "arg_where")]
1255 F::ArgWhere => FunctionOptions::groupwise(),
1256 #[cfg(feature = "index_of")]
1257 F::IndexOf => {
1258 FunctionOptions::aggregation().with_casting_rules(CastingRules::FirstArgLossless)
1259 },
1260 #[cfg(feature = "search_sorted")]
1261 F::SearchSorted(_) => FunctionOptions::groupwise().with_supertyping(
1262 (SuperTypeFlags::default() & !SuperTypeFlags::ALLOW_PRIMITIVE_TO_STRING).into(),
1263 ),
1264 #[cfg(feature = "trigonometry")]
1265 F::Trigonometry(_) => FunctionOptions::elementwise(),
1266 #[cfg(feature = "trigonometry")]
1267 F::Atan2 => FunctionOptions::elementwise(),
1268 #[cfg(feature = "sign")]
1269 F::Sign => FunctionOptions::elementwise(),
1270 F::FillNull => FunctionOptions::elementwise().with_supertyping(Default::default()),
1271 F::FillNullWithStrategy(strategy) if strategy.is_elementwise() => {
1272 FunctionOptions::elementwise()
1273 },
1274 F::FillNullWithStrategy(_) => FunctionOptions::groupwise(),
1275 #[cfg(feature = "rolling_window")]
1276 F::RollingExpr(_) => FunctionOptions::length_preserving(),
1277 #[cfg(feature = "rolling_window_by")]
1278 F::RollingExprBy(_) => FunctionOptions::length_preserving(),
1279 F::ShiftAndFill => FunctionOptions::length_preserving(),
1280 F::Shift => FunctionOptions::length_preserving(),
1281 F::DropNans => FunctionOptions::row_separable(),
1282 F::DropNulls => FunctionOptions::row_separable()
1283 .with_flags(|f| f | FunctionFlags::ALLOW_EMPTY_INPUTS),
1284 #[cfg(feature = "mode")]
1285 F::Mode => FunctionOptions::groupwise(),
1286 #[cfg(feature = "moment")]
1287 F::Skew(_) => FunctionOptions::aggregation(),
1288 #[cfg(feature = "moment")]
1289 F::Kurtosis(_, _) => FunctionOptions::aggregation(),
1290 #[cfg(feature = "dtype-array")]
1291 F::Reshape(_) => FunctionOptions::groupwise(),
1292 #[cfg(feature = "repeat_by")]
1293 F::RepeatBy => FunctionOptions::elementwise(),
1294 F::ArgUnique => FunctionOptions::groupwise(),
1295 #[cfg(feature = "rank")]
1296 F::Rank { .. } => FunctionOptions::groupwise(),
1297 F::Repeat => {
1298 FunctionOptions::groupwise().with_flags(|f| f | FunctionFlags::ALLOW_RENAME)
1299 },
1300 #[cfg(feature = "round_series")]
1301 F::Clip { .. } => FunctionOptions::elementwise(),
1302 #[cfg(feature = "dtype-struct")]
1303 F::AsStruct => FunctionOptions::elementwise().with_flags(|f| {
1304 f | FunctionFlags::PASS_NAME_TO_APPLY | FunctionFlags::INPUT_WILDCARD_EXPANSION
1305 }),
1306 #[cfg(feature = "top_k")]
1307 F::TopK { .. } => FunctionOptions::groupwise(),
1308 #[cfg(feature = "top_k")]
1309 F::TopKBy { .. } => FunctionOptions::groupwise(),
1310 #[cfg(feature = "cum_agg")]
1311 F::CumCount { .. }
1312 | F::CumSum { .. }
1313 | F::CumProd { .. }
1314 | F::CumMin { .. }
1315 | F::CumMax { .. } => FunctionOptions::length_preserving(),
1316 F::Reverse => FunctionOptions::length_preserving(),
1317 #[cfg(feature = "dtype-struct")]
1318 F::ValueCounts { .. } => {
1319 FunctionOptions::groupwise().with_flags(|f| f | FunctionFlags::PASS_NAME_TO_APPLY)
1320 },
1321 #[cfg(feature = "unique_counts")]
1322 F::UniqueCounts => FunctionOptions::groupwise(),
1323 #[cfg(feature = "approx_unique")]
1324 F::ApproxNUnique => FunctionOptions::aggregation(),
1325 F::Coalesce => FunctionOptions::elementwise()
1326 .with_flags(|f| f | FunctionFlags::INPUT_WILDCARD_EXPANSION)
1327 .with_supertyping(Default::default()),
1328 F::ShrinkType => FunctionOptions::length_preserving(),
1329 #[cfg(feature = "diff")]
1330 F::Diff(NullBehavior::Drop) => FunctionOptions::groupwise(),
1331 #[cfg(feature = "diff")]
1332 F::Diff(NullBehavior::Ignore) => FunctionOptions::length_preserving(),
1333 #[cfg(feature = "pct_change")]
1334 F::PctChange => FunctionOptions::length_preserving(),
1335 #[cfg(feature = "interpolate")]
1336 F::Interpolate(_) => FunctionOptions::length_preserving(),
1337 #[cfg(feature = "interpolate_by")]
1338 F::InterpolateBy => FunctionOptions::length_preserving(),
1339 #[cfg(feature = "log")]
1340 F::Log { .. } | F::Log1p | F::Exp => FunctionOptions::elementwise(),
1341 #[cfg(feature = "log")]
1342 F::Entropy { .. } => FunctionOptions::aggregation(),
1343 F::Unique(_) => FunctionOptions::groupwise(),
1344 #[cfg(feature = "round_series")]
1345 F::Round { .. } | F::RoundSF { .. } | F::Floor | F::Ceil => {
1346 FunctionOptions::elementwise()
1347 },
1348 F::UpperBound | F::LowerBound => FunctionOptions::aggregation(),
1349 #[cfg(feature = "fused")]
1350 F::Fused(_) => FunctionOptions::elementwise(),
1351 F::ConcatExpr(_) => FunctionOptions::groupwise()
1352 .with_flags(|f| f | FunctionFlags::INPUT_WILDCARD_EXPANSION)
1353 .with_supertyping(Default::default()),
1354 #[cfg(feature = "cov")]
1355 F::Correlation { .. } => {
1356 FunctionOptions::aggregation().with_supertyping(Default::default())
1357 },
1358 #[cfg(feature = "peaks")]
1359 F::PeakMin | F::PeakMax => FunctionOptions::length_preserving(),
1360 #[cfg(feature = "cutqcut")]
1361 F::Cut { .. } | F::QCut { .. } => FunctionOptions::length_preserving()
1362 .with_flags(|f| f | FunctionFlags::PASS_NAME_TO_APPLY),
1363 #[cfg(feature = "rle")]
1364 F::RLE => FunctionOptions::groupwise(),
1365 #[cfg(feature = "rle")]
1366 F::RLEID => FunctionOptions::length_preserving(),
1367 F::ToPhysical => FunctionOptions::elementwise(),
1368 #[cfg(feature = "random")]
1369 F::Random {
1370 method: RandomMethod::Sample { .. },
1371 ..
1372 } => FunctionOptions::groupwise(),
1373 #[cfg(feature = "random")]
1374 F::Random {
1375 method: RandomMethod::Shuffle,
1376 ..
1377 } => FunctionOptions::length_preserving(),
1378 F::SetSortedFlag(_) => FunctionOptions::elementwise(),
1379 #[cfg(feature = "ffi_plugin")]
1380 F::FfiPlugin { flags, .. } => *flags,
1381 F::MaxHorizontal | F::MinHorizontal => FunctionOptions::elementwise().with_flags(|f| {
1382 f | FunctionFlags::INPUT_WILDCARD_EXPANSION | FunctionFlags::ALLOW_RENAME
1383 }),
1384 F::MeanHorizontal { .. } | F::SumHorizontal { .. } => FunctionOptions::elementwise()
1385 .with_flags(|f| f | FunctionFlags::INPUT_WILDCARD_EXPANSION),
1386 #[cfg(feature = "ewma")]
1387 F::EwmMean { .. } | F::EwmStd { .. } | F::EwmVar { .. } => {
1388 FunctionOptions::length_preserving()
1389 },
1390 #[cfg(feature = "ewma_by")]
1391 F::EwmMeanBy { .. } => FunctionOptions::length_preserving(),
1392 #[cfg(feature = "replace")]
1393 F::Replace => FunctionOptions::elementwise(),
1394 #[cfg(feature = "replace")]
1395 F::ReplaceStrict { .. } => FunctionOptions::elementwise(),
1396 F::GatherEvery { .. } => FunctionOptions::groupwise(),
1397 #[cfg(feature = "reinterpret")]
1398 F::Reinterpret(_) => FunctionOptions::elementwise(),
1399 F::ExtendConstant => FunctionOptions::groupwise(),
1400 }
1401 }
1402}