1use crate::math::monotonicity::*;
21use datafusion_expr::ScalarUDF;
22use std::sync::Arc;
23
24pub mod abs;
25pub mod bounds;
26pub mod cot;
27pub mod factorial;
28pub mod gcd;
29pub mod iszero;
30pub mod lcm;
31pub mod log;
32pub mod monotonicity;
33pub mod nans;
34pub mod nanvl;
35pub mod pi;
36pub mod power;
37pub mod random;
38pub mod round;
39pub mod signum;
40pub mod trunc;
41
42make_udf_function!(abs::AbsFunc, abs);
44make_math_unary_udf!(
45 AcosFunc,
46 acos,
47 acos,
48 super::acos_order,
49 super::bounds::acos_bounds,
50 super::get_acos_doc
51);
52make_math_unary_udf!(
53 AcoshFunc,
54 acosh,
55 acosh,
56 super::acosh_order,
57 super::bounds::acosh_bounds,
58 super::get_acosh_doc
59);
60make_math_unary_udf!(
61 AsinFunc,
62 asin,
63 asin,
64 super::asin_order,
65 super::bounds::asin_bounds,
66 super::get_asin_doc
67);
68make_math_unary_udf!(
69 AsinhFunc,
70 asinh,
71 asinh,
72 super::asinh_order,
73 super::bounds::unbounded_bounds,
74 super::get_asinh_doc
75);
76make_math_unary_udf!(
77 AtanFunc,
78 atan,
79 atan,
80 super::atan_order,
81 super::bounds::atan_bounds,
82 super::get_atan_doc
83);
84make_math_unary_udf!(
85 AtanhFunc,
86 atanh,
87 atanh,
88 super::atanh_order,
89 super::bounds::unbounded_bounds,
90 super::get_atanh_doc
91);
92make_math_binary_udf!(
93 Atan2,
94 atan2,
95 atan2,
96 super::atan2_order,
97 super::get_atan2_doc
98);
99make_math_unary_udf!(
100 CbrtFunc,
101 cbrt,
102 cbrt,
103 super::cbrt_order,
104 super::bounds::unbounded_bounds,
105 super::get_cbrt_doc
106);
107make_math_unary_udf!(
108 CeilFunc,
109 ceil,
110 ceil,
111 super::ceil_order,
112 super::bounds::unbounded_bounds,
113 super::get_ceil_doc
114);
115make_math_unary_udf!(
116 CosFunc,
117 cos,
118 cos,
119 super::cos_order,
120 super::bounds::cos_bounds,
121 super::get_cos_doc
122);
123make_math_unary_udf!(
124 CoshFunc,
125 cosh,
126 cosh,
127 super::cosh_order,
128 super::bounds::cosh_bounds,
129 super::get_cosh_doc
130);
131make_udf_function!(cot::CotFunc, cot);
132make_math_unary_udf!(
133 DegreesFunc,
134 degrees,
135 to_degrees,
136 super::degrees_order,
137 super::bounds::unbounded_bounds,
138 super::get_degrees_doc
139);
140make_math_unary_udf!(
141 ExpFunc,
142 exp,
143 exp,
144 super::exp_order,
145 super::bounds::exp_bounds,
146 super::get_exp_doc
147);
148make_udf_function!(factorial::FactorialFunc, factorial);
149make_math_unary_udf!(
150 FloorFunc,
151 floor,
152 floor,
153 super::floor_order,
154 super::bounds::unbounded_bounds,
155 super::get_floor_doc
156);
157make_udf_function!(log::LogFunc, log);
158make_udf_function!(gcd::GcdFunc, gcd);
159make_udf_function!(nans::IsNanFunc, isnan);
160make_udf_function!(iszero::IsZeroFunc, iszero);
161make_udf_function!(lcm::LcmFunc, lcm);
162make_math_unary_udf!(
163 LnFunc,
164 ln,
165 ln,
166 super::ln_order,
167 super::bounds::unbounded_bounds,
168 super::get_ln_doc
169);
170make_math_unary_udf!(
171 Log2Func,
172 log2,
173 log2,
174 super::log2_order,
175 super::bounds::unbounded_bounds,
176 super::get_log2_doc
177);
178make_math_unary_udf!(
179 Log10Func,
180 log10,
181 log10,
182 super::log10_order,
183 super::bounds::unbounded_bounds,
184 super::get_log10_doc
185);
186make_udf_function!(nanvl::NanvlFunc, nanvl);
187make_udf_function!(pi::PiFunc, pi);
188make_udf_function!(power::PowerFunc, power);
189make_math_unary_udf!(
190 RadiansFunc,
191 radians,
192 to_radians,
193 super::radians_order,
194 super::bounds::radians_bounds,
195 super::get_radians_doc
196);
197make_udf_function!(random::RandomFunc, random);
198make_udf_function!(round::RoundFunc, round);
199make_udf_function!(signum::SignumFunc, signum);
200make_math_unary_udf!(
201 SinFunc,
202 sin,
203 sin,
204 super::sin_order,
205 super::bounds::sin_bounds,
206 super::get_sin_doc
207);
208make_math_unary_udf!(
209 SinhFunc,
210 sinh,
211 sinh,
212 super::sinh_order,
213 super::bounds::unbounded_bounds,
214 super::get_sinh_doc
215);
216make_math_unary_udf!(
217 SqrtFunc,
218 sqrt,
219 sqrt,
220 super::sqrt_order,
221 super::bounds::sqrt_bounds,
222 super::get_sqrt_doc
223);
224make_math_unary_udf!(
225 TanFunc,
226 tan,
227 tan,
228 super::tan_order,
229 super::bounds::unbounded_bounds,
230 super::get_tan_doc
231);
232make_math_unary_udf!(
233 TanhFunc,
234 tanh,
235 tanh,
236 super::tanh_order,
237 super::bounds::tanh_bounds,
238 super::get_tanh_doc
239);
240make_udf_function!(trunc::TruncFunc, trunc);
241
242pub mod expr_fn {
243 export_functions!(
244 (abs, "returns the absolute value of a given number", num),
245 (acos, "returns the arc cosine or inverse cosine of a number", num),
246 (acosh, "returns inverse hyperbolic cosine", num),
247 (asin, "returns the arc sine or inverse sine of a number", num),
248 (asinh, "returns inverse hyperbolic sine", num),
249 (atan, "returns inverse tangent", num),
250 (atan2, "returns inverse tangent of a division given in the argument", y x),
251 (atanh, "returns inverse hyperbolic tangent", num),
252 (cbrt, "cube root of a number", num),
253 (ceil, "nearest integer greater than or equal to argument", num),
254 (cos, "cosine", num),
255 (cosh, "hyperbolic cosine", num),
256 (cot, "cotangent of a number", num),
257 (degrees, "converts radians to degrees", num),
258 (exp, "exponential", num),
259 (factorial, "factorial", num),
260 (floor, "nearest integer less than or equal to argument", num),
261 (gcd, "greatest common divisor", x y),
262 (isnan, "returns true if a given number is +NaN or -NaN otherwise returns false", num),
263 (iszero, "returns true if a given number is +0.0 or -0.0 otherwise returns false", num),
264 (lcm, "least common multiple", x y),
265 (ln, "natural logarithm (base e) of a number", num),
266 (log, "logarithm of a number for a particular `base`", base num),
267 (log2, "base 2 logarithm of a number", num),
268 (log10, "base 10 logarithm of a number", num),
269 (nanvl, "returns x if x is not NaN otherwise returns y", x y),
270 (pi, "Returns an approximate value of π",),
271 (power, "`base` raised to the power of `exponent`", base exponent),
272 (radians, "converts degrees to radians", num),
273 (random, "Returns a random value in the range 0.0 <= x < 1.0",),
274 (signum, "sign of the argument (-1, 0, +1)", num),
275 (sin, "sine", num),
276 (sinh, "hyperbolic sine", num),
277 (sqrt, "square root of a number", num),
278 (tan, "returns the tangent of a number", num),
279 (tanh, "returns the hyperbolic tangent of a number", num),
280 (round, "round to nearest integer", args,),
281 (trunc, "truncate toward zero, with optional precision", args,)
282 );
283}
284
285pub fn functions() -> Vec<Arc<ScalarUDF>> {
287 vec![
288 abs(),
289 acos(),
290 acosh(),
291 asin(),
292 asinh(),
293 atan(),
294 atan2(),
295 atanh(),
296 cbrt(),
297 ceil(),
298 cos(),
299 cosh(),
300 cot(),
301 degrees(),
302 exp(),
303 factorial(),
304 floor(),
305 gcd(),
306 isnan(),
307 iszero(),
308 lcm(),
309 ln(),
310 log(),
311 log2(),
312 log10(),
313 nanvl(),
314 pi(),
315 power(),
316 radians(),
317 random(),
318 signum(),
319 sin(),
320 sinh(),
321 sqrt(),
322 tan(),
323 tanh(),
324 round(),
325 trunc(),
326 ]
327}
328
329#[cfg(test)]
330mod tests {
331 use arrow::datatypes::DataType;
332 use datafusion_common::ScalarValue;
333 use datafusion_expr::interval_arithmetic::Interval;
334
335 fn unbounded_interval(data_type: &DataType) -> Interval {
336 Interval::make_unbounded(data_type).unwrap()
337 }
338
339 fn one_to_inf_interval(data_type: &DataType) -> Interval {
340 Interval::try_new(
341 ScalarValue::new_one(data_type).unwrap(),
342 ScalarValue::try_from(data_type).unwrap(),
343 )
344 .unwrap()
345 }
346
347 fn zero_to_pi_interval(data_type: &DataType) -> Interval {
348 Interval::try_new(
349 ScalarValue::new_zero(data_type).unwrap(),
350 ScalarValue::new_pi_upper(data_type).unwrap(),
351 )
352 .unwrap()
353 }
354
355 fn assert_udf_evaluates_to_bounds(
356 udf: &datafusion_expr::ScalarUDF,
357 interval: Interval,
358 expected: Interval,
359 ) {
360 let input = vec![&interval];
361 let result = udf.evaluate_bounds(&input).unwrap();
362 assert_eq!(
363 result,
364 expected,
365 "Bounds check failed on UDF: {:?}",
366 udf.name()
367 );
368 }
369
370 #[test]
371 fn test_cases() -> crate::Result<()> {
372 let datatypes = [DataType::Float32, DataType::Float64];
373 let cases = datatypes
374 .iter()
375 .flat_map(|data_type| {
376 vec![
377 (
378 super::acos(),
379 unbounded_interval(data_type),
380 zero_to_pi_interval(data_type),
381 ),
382 (
383 super::acosh(),
384 unbounded_interval(data_type),
385 Interval::make_non_negative_infinity_interval(data_type).unwrap(),
386 ),
387 (
388 super::asin(),
389 unbounded_interval(data_type),
390 Interval::make_symmetric_half_pi_interval(data_type).unwrap(),
391 ),
392 (
393 super::atan(),
394 unbounded_interval(data_type),
395 Interval::make_symmetric_half_pi_interval(data_type).unwrap(),
396 ),
397 (
398 super::cos(),
399 unbounded_interval(data_type),
400 Interval::make_symmetric_unit_interval(data_type).unwrap(),
401 ),
402 (
403 super::cosh(),
404 unbounded_interval(data_type),
405 one_to_inf_interval(data_type),
406 ),
407 (
408 super::sin(),
409 unbounded_interval(data_type),
410 Interval::make_symmetric_unit_interval(data_type).unwrap(),
411 ),
412 (
413 super::exp(),
414 unbounded_interval(data_type),
415 Interval::make_non_negative_infinity_interval(data_type).unwrap(),
416 ),
417 (
418 super::sqrt(),
419 unbounded_interval(data_type),
420 Interval::make_non_negative_infinity_interval(data_type).unwrap(),
421 ),
422 (
423 super::radians(),
424 unbounded_interval(data_type),
425 Interval::make_symmetric_pi_interval(data_type).unwrap(),
426 ),
427 (
428 super::sqrt(),
429 unbounded_interval(data_type),
430 Interval::make_non_negative_infinity_interval(data_type).unwrap(),
431 ),
432 ]
433 })
434 .collect::<Vec<_>>();
435
436 for (udf, interval, expected) in cases {
437 assert_udf_evaluates_to_bounds(&udf, interval, expected);
438 }
439
440 Ok(())
441 }
442}