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