## Coverage Report

#### Created: 2025-11-22 06:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)

    /Users/andrewlamb/Software/datafusion/datafusion/functions/src/math/mod.rs

    Line
    Count
    Source
    1
    // Licensed to the Apache Software Foundation (ASF) under one
    2
    // or more contributor license agreements.  See the NOTICE file
    3
    // distributed with this work for additional information
    4
    // regarding copyright ownership.  The ASF licenses this file
    5
    // to you under the Apache License, Version 2.0 (the
    6
    // "License"); you may not use this file except in compliance
    7
    // with the License.  You may obtain a copy of the License at
    8
    //
    9
    //   http://www.apache.org/licenses/LICENSE-2.0
    10
    //
    11
    // Unless required by applicable law or agreed to in writing,
    12
    // software distributed under the License is distributed on an
    13
    // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    14
    // KIND, either express or implied.  See the License for the
    15
    // specific language governing permissions and limitations
    16
    // under the License.
    17
    18
    //! "math" DataFusion functions
    19
    20
    use crate::math::monotonicity::*;
    21
    use datafusion_expr::ScalarUDF;
    22
    use std::sync::Arc;
    23
    24
    pub mod abs;
    25
    pub mod bounds;
    26
    pub mod cot;
    27
    pub mod factorial;
    28
    pub mod gcd;
    29
    pub mod iszero;
    30
    pub mod lcm;
    31
    pub mod log;
    32
    pub mod monotonicity;
    33
    pub mod nans;
    34
    pub mod nanvl;
    35
    pub mod pi;
    36
    pub mod power;
    37
    pub mod random;
    38
    pub mod round;
    39
    pub mod signum;
    40
    pub mod trunc;
    41
    42
    // Create UDFs
    43
    make_udf_function!(abs::AbsFunc, abs);
    44
    make_math_unary_udf!(
    45
        AcosFunc,
    46
        acos,
    47
        acos,
    48
        super::acos_order,
    49
        super::bounds::acos_bounds,
    50
        super::get_acos_doc
    51
    );
    52
    make_math_unary_udf!(
    53
        AcoshFunc,
    54
        acosh,
    55
        acosh,
    56
        super::acosh_order,
    57
        super::bounds::acosh_bounds,
    58
        super::get_acosh_doc
    59
    );
    60
    make_math_unary_udf!(
    61
        AsinFunc,
    62
        asin,
    63
        asin,
    64
        super::asin_order,
    65
        super::bounds::asin_bounds,
    66
        super::get_asin_doc
    67
    );
    68
    make_math_unary_udf!(
    69
        AsinhFunc,
    70
        asinh,
    71
        asinh,
    72
        super::asinh_order,
    73
        super::bounds::unbounded_bounds,
    74
        super::get_asinh_doc
    75
    );
    76
    make_math_unary_udf!(
    77
        AtanFunc,
    78
        atan,
    79
        atan,
    80
        super::atan_order,
    81
        super::bounds::atan_bounds,
    82
        super::get_atan_doc
    83
    );
    84
    make_math_unary_udf!(
    85
        AtanhFunc,
    86
        atanh,
    87
        atanh,
    88
        super::atanh_order,
    89
        super::bounds::unbounded_bounds,
    90
        super::get_atanh_doc
    91
    );
    92
    make_math_binary_udf!(
    93
        Atan2,
    94
        atan2,
    95
        atan2,
    96
        super::atan2_order,
    97
        super::get_atan2_doc
    98
    );
    99
    make_math_unary_udf!(
    100
        CbrtFunc,
    101
        cbrt,
    102
        cbrt,
    103
        super::cbrt_order,
    104
        super::bounds::unbounded_bounds,
    105
        super::get_cbrt_doc
    106
    );
    107
    make_math_unary_udf!(
    108
        CeilFunc,
    109
        ceil,
    110
        ceil,
    111
        super::ceil_order,
    112
        super::bounds::unbounded_bounds,
    113
        super::get_ceil_doc
    114
    );
    115
    make_math_unary_udf!(
    116
        CosFunc,
    117
        cos,
    118
        cos,
    119
        super::cos_order,
    120
        super::bounds::cos_bounds,
    121
        super::get_cos_doc
    122
    );
    123
    make_math_unary_udf!(
    124
        CoshFunc,
    125
        cosh,
    126
        cosh,
    127
        super::cosh_order,
    128
        super::bounds::cosh_bounds,
    129
        super::get_cosh_doc
    130
    );
    131
    make_udf_function!(cot::CotFunc, cot);
    132
    make_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
    );
    140
    make_math_unary_udf!(
    141
        ExpFunc,
    142
        exp,
    143
        exp,
    144
        super::exp_order,
    145
        super::bounds::exp_bounds,
    146
        super::get_exp_doc
    147
    );
    148
    make_udf_function!(factorial::FactorialFunc, factorial);
    149
    make_math_unary_udf!(
    150
        FloorFunc,
    151
        floor,
    152
        floor,
    153
        super::floor_order,
    154
        super::bounds::unbounded_bounds,
    155
        super::get_floor_doc
    156
    );
    157
    make_udf_function!(log::LogFunc, log);
    158
    make_udf_function!(gcd::GcdFunc, gcd);
    159
    make_udf_function!(nans::IsNanFunc, isnan);
    160
    make_udf_function!(iszero::IsZeroFunc, iszero);
    161
    make_udf_function!(lcm::LcmFunc, lcm);
    162
    make_math_unary_udf!(
    163
        LnFunc,
    164
        ln,
    165
        ln,
    166
        super::ln_order,
    167
        super::bounds::unbounded_bounds,
    168
        super::get_ln_doc
    169
    );
    170
    make_math_unary_udf!(
    171
        Log2Func,
    172
        log2,
    173
        log2,
    174
        super::log2_order,
    175
        super::bounds::unbounded_bounds,
    176
        super::get_log2_doc
    177
    );
    178
    make_math_unary_udf!(
    179
        Log10Func,
    180
        log10,
    181
        log10,
    182
        super::log10_order,
    183
        super::bounds::unbounded_bounds,
    184
        super::get_log10_doc
    185
    );
    186
    make_udf_function!(nanvl::NanvlFunc, nanvl);
    187
    make_udf_function!(pi::PiFunc, pi);
    188
    make_udf_function!(power::PowerFunc, power);
    189
    make_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
    );
    197
    make_udf_function!(random::RandomFunc, random);
    198
    make_udf_function!(round::RoundFunc, round);
    199
    make_udf_function!(signum::SignumFunc, signum);
    200
    make_math_unary_udf!(
    201
        SinFunc,
    202
        sin,
    203
        sin,
    204
        super::sin_order,
    205
        super::bounds::sin_bounds,
    206
        super::get_sin_doc
    207
    );
    208
    make_math_unary_udf!(
    209
        SinhFunc,
    210
        sinh,
    211
        sinh,
    212
        super::sinh_order,
    213
        super::bounds::unbounded_bounds,
    214
        super::get_sinh_doc
    215
    );
    216
    make_math_unary_udf!(
    217
        SqrtFunc,
    218
        sqrt,
    219
        sqrt,
    220
        super::sqrt_order,
    221
        super::bounds::sqrt_bounds,
    222
        super::get_sqrt_doc
    223
    );
    224
    make_math_unary_udf!(
    225
        TanFunc,
    226
        tan,
    227
        tan,
    228
        super::tan_order,
    229
        super::bounds::unbounded_bounds,
    230
        super::get_tan_doc
    231
    );
    232
    make_math_unary_udf!(
    233
        TanhFunc,
    234
        tanh,
    235
        tanh,
    236
        super::tanh_order,
    237
        super::bounds::tanh_bounds,
    238
        super::get_tanh_doc
    239
    );
    240
    make_udf_function!(trunc::TruncFunc, trunc);
    241
    242
    pub 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
    285
    /// Returns all DataFusion functions defined in this package
    286
    0
    pub fn functions() -> Vec<Arc<ScalarUDF>> {
    287
    0
        vec![
    288
    0
            abs(),
    289
    0
            acos(),
    290
    0
            acosh(),
    291
    0
            asin(),
    292
    0
            asinh(),
    293
    0
            atan(),
    294
    0
            atan2(),
    295
    0
            atanh(),
    296
    0
            cbrt(),
    297
    0
            ceil(),
    298
    0
            cos(),
    299
    0
            cosh(),
    300
    0
            cot(),
    301
    0
            degrees(),
    302
    0
            exp(),
    303
    0
            factorial(),
    304
    0
            floor(),
    305
    0
            gcd(),
    306
    0
            isnan(),
    307
    0
            iszero(),
    308
    0
            lcm(),
    309
    0
            ln(),
    310
    0
            log(),
    311
    0
            log2(),
    312
    0
            log10(),
    313
    0
            nanvl(),
    314
    0
            pi(),
    315
    0
            power(),
    316
    0
            radians(),
    317
    0
            random(),
    318
    0
            signum(),
    319
    0
            sin(),
    320
    0
            sinh(),
    321
    0
            sqrt(),
    322
    0
            tan(),
    323
    0
            tanh(),
    324
    0
            round(),
    325
    0
            trunc(),
    326
        ]
    327
    0
    }
    328
    329
    #[cfg(test)]
    330
    mod 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
    }