## Coverage Report

#### Created: 2025-08-26 07:03

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

    /Users/andrewlamb/Software/arrow-rs/arrow-array/src/arithmetic.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
    use arrow_buffer::{i256, ArrowNativeType, IntervalDayTime, IntervalMonthDayNano};
    19
    use arrow_schema::ArrowError;
    20
    use half::f16;
    21
    use num::complex::ComplexFloat;
    22
    use std::cmp::Ordering;
    23
    24
    /// Trait for [`ArrowNativeType`] that adds checked and unchecked arithmetic operations,
    25
    /// and totally ordered comparison operations
    26
    ///
    27
    /// The APIs with `_wrapping` suffix do not perform overflow-checking. For integer
    28
    /// types they will wrap around the boundary of the type. For floating point types they
    29
    /// will overflow to INF or -INF preserving the expected sign value
    30
    ///
    31
    /// Note `div_wrapping` and `mod_wrapping` will panic for integer types if `rhs` is zero
    32
    /// although this may be subject to change <https://github.com/apache/arrow-rs/issues/2647>
    33
    ///
    34
    /// The APIs with `_checked` suffix perform overflow-checking. For integer types
    35
    /// these will return `Err` instead of wrapping. For floating point types they will
    36
    /// overflow to INF or -INF preserving the expected sign value
    37
    ///
    38
    /// Comparison of integer types is as per normal integer comparison rules, floating
    39
    /// point values are compared as per IEEE 754's totalOrder predicate see [`f32::total_cmp`]
    40
    ///
    41
    pub trait ArrowNativeTypeOp: ArrowNativeType {
    42
        /// The additive identity
    43
        const ZERO: Self;
    44
    45
        /// The multiplicative identity
    46
        const ONE: Self;
    47
    48
        /// The minimum value and identity for the `max` aggregation.
    49
        /// Note that the aggregation uses the total order predicate for floating point values,
    50
        /// which means that this value is a negative NaN.
    51
        const MIN_TOTAL_ORDER: Self;
    52
    53
        /// The maximum value and identity for the `min` aggregation.
    54
        /// Note that the aggregation uses the total order predicate for floating point values,
    55
        /// which means that this value is a positive NaN.
    56
        const MAX_TOTAL_ORDER: Self;
    57
    58
        /// Checked addition operation
    59
        fn add_checked(self, rhs: Self) -> Result<Self, ArrowError>;
    60
    61
        /// Wrapping addition operation
    62
        fn add_wrapping(self, rhs: Self) -> Self;
    63
    64
        /// Checked subtraction operation
    65
        fn sub_checked(self, rhs: Self) -> Result<Self, ArrowError>;
    66
    67
        /// Wrapping subtraction operation
    68
        fn sub_wrapping(self, rhs: Self) -> Self;
    69
    70
        /// Checked multiplication operation
    71
        fn mul_checked(self, rhs: Self) -> Result<Self, ArrowError>;
    72
    73
        /// Wrapping multiplication operation
    74
        fn mul_wrapping(self, rhs: Self) -> Self;
    75
    76
        /// Checked division operation
    77
        fn div_checked(self, rhs: Self) -> Result<Self, ArrowError>;
    78
    79
        /// Wrapping division operation
    80
        fn div_wrapping(self, rhs: Self) -> Self;
    81
    82
        /// Checked remainder operation
    83
        fn mod_checked(self, rhs: Self) -> Result<Self, ArrowError>;
    84
    85
        /// Wrapping remainder operation
    86
        fn mod_wrapping(self, rhs: Self) -> Self;
    87
    88
        /// Checked negation operation
    89
        fn neg_checked(self) -> Result<Self, ArrowError>;
    90
    91
        /// Wrapping negation operation
    92
        fn neg_wrapping(self) -> Self;
    93
    94
        /// Checked exponentiation operation
    95
        fn pow_checked(self, exp: u32) -> Result<Self, ArrowError>;
    96
    97
        /// Wrapping exponentiation operation
    98
        fn pow_wrapping(self, exp: u32) -> Self;
    99
    100
        /// Returns true if zero else false
    101
        fn is_zero(self) -> bool;
    102
    103
        /// Compare operation
    104
        fn compare(self, rhs: Self) -> Ordering;
    105
    106
        /// Equality operation
    107
        fn is_eq(self, rhs: Self) -> bool;
    108
    109
        /// Not equal operation
    110
        #[inline]
    111
        fn is_ne(self, rhs: Self) -> bool {
    112
            !self.is_eq(rhs)
    113
        }
    114
    115
        /// Less than operation
    116
        #[inline]
    117
    51
        fn is_lt(self, rhs: Self) -> bool {
    118
    51
            self.compare(rhs).is_lt()
    119
    51
        }
    120
    121
        /// Less than equals operation
    122
        #[inline]
    123
        fn is_le(self, rhs: Self) -> bool {
    124
            self.compare(rhs).is_le()
    125
        }
    126
    127
        /// Greater than operation
    128
        #[inline]
    129
        fn is_gt(self, rhs: Self) -> bool {
    130
            self.compare(rhs).is_gt()
    131
        }
    132
    133
        /// Greater than equals operation
    134
        #[inline]
    135
        fn is_ge(self, rhs: Self) -> bool {
    136
            self.compare(rhs).is_ge()
    137
        }
    138
    }
    139
    140
    macro_rules! native_type_op {
    141
        ($t:tt) => {
    142
            native_type_op!($t, 0, 1);
    143
        };
    144
        ($t:tt, $zero:expr, $one: expr) => {
    145
            native_type_op!($t, $zero, $one, $t::MIN, $t::MAX);
    146
        };
    147
        ($t:tt, $zero:expr, $one: expr, $min: expr, $max: expr) => {
    148
            impl ArrowNativeTypeOp for $t {
    149
                const ZERO: Self = $zero;
    150
                const ONE: Self = $one;
    151
                const MIN_TOTAL_ORDER: Self = $min;
    152
                const MAX_TOTAL_ORDER: Self = $max;
    153
    154
                #[inline]
    155
    0
                fn add_checked(self, rhs: Self) -> Result<Self, ArrowError> {
    156
    0
                    self.checked_add(rhs).ok_or_else(|| {
    157
    0
                        ArrowError::ArithmeticOverflow(format!(
    158
    0
                            "Overflow happened on: {:?} + {:?}",
    159
    0
                            self, rhs
    160
    0
                        ))
    161
    0
                    })
    162
    0
                }
    163
    164
                #[inline]
    165
    0
                fn add_wrapping(self, rhs: Self) -> Self {
    166
    0
                    self.wrapping_add(rhs)
    167
    0
                }
    168
    169
                #[inline]
    170
    0
                fn sub_checked(self, rhs: Self) -> Result<Self, ArrowError> {
    171
    0
                    self.checked_sub(rhs).ok_or_else(|| {
    172
    0
                        ArrowError::ArithmeticOverflow(format!(
    173
    0
                            "Overflow happened on: {:?} - {:?}",
    174
    0
                            self, rhs
    175
    0
                        ))
    176
    0
                    })
    177
    0
                }
    178
    179
                #[inline]
    180
    0
                fn sub_wrapping(self, rhs: Self) -> Self {
    181
    0
                    self.wrapping_sub(rhs)
    182
    0
                }
    183
    184
                #[inline]
    185
    0
                fn mul_checked(self, rhs: Self) -> Result<Self, ArrowError> {
    186
    0
                    self.checked_mul(rhs).ok_or_else(|| {
    187
    0
                        ArrowError::ArithmeticOverflow(format!(
    188
    0
                            "Overflow happened on: {:?} * {:?}",
    189
    0
                            self, rhs
    190
    0
                        ))
    191
    0
                    })
    192
    0
                }
    193
    194
                #[inline]
    195
    0
                fn mul_wrapping(self, rhs: Self) -> Self {
    196
    0
                    self.wrapping_mul(rhs)
    197
    0
                }
    198
    199
                #[inline]
    200
    0
                fn div_checked(self, rhs: Self) -> Result<Self, ArrowError> {
    201
    0
                    if rhs.is_zero() {
    202
    0
                        Err(ArrowError::DivideByZero)
    203
                    } else {
    204
    0
                        self.checked_div(rhs).ok_or_else(|| {
    205
    0
                            ArrowError::ArithmeticOverflow(format!(
    206
    0
                                "Overflow happened on: {:?} / {:?}",
    207
    0
                                self, rhs
    208
    0
                            ))
    209
    0
                        })
    210
                    }
    211
    0
                }
    212
    213
                #[inline]
    214
    0
                fn div_wrapping(self, rhs: Self) -> Self {
    215
    0
                    self.wrapping_div(rhs)
    216
    0
                }
    217
    218
                #[inline]
    219
    0
                fn mod_checked(self, rhs: Self) -> Result<Self, ArrowError> {
    220
    0
                    if rhs.is_zero() {
    221
    0
                        Err(ArrowError::DivideByZero)
    222
                    } else {
    223
    0
                        self.checked_rem(rhs).ok_or_else(|| {
    224
    0
                            ArrowError::ArithmeticOverflow(format!(
    225
    0
                                "Overflow happened on: {:?} % {:?}",
    226
    0
                                self, rhs
    227
    0
                            ))
    228
    0
                        })
    229
                    }
    230
    0
                }
    231
    232
                #[inline]
    233
    0
                fn mod_wrapping(self, rhs: Self) -> Self {
    234
    0
                    self.wrapping_rem(rhs)
    235
    0
                }
    236
    237
                #[inline]
    238
    0
                fn neg_checked(self) -> Result<Self, ArrowError> {
    239
    0
                    self.checked_neg().ok_or_else(|| {
    240
    0
                        ArrowError::ArithmeticOverflow(format!("Overflow happened on: - {:?}", self))
    241
    0
                    })
    242
    0
                }
    243
    244
                #[inline]
    245
    0
                fn pow_checked(self, exp: u32) -> Result<Self, ArrowError> {
    246
    0
                    self.checked_pow(exp).ok_or_else(|| {
    247
    0
                        ArrowError::ArithmeticOverflow(format!(
    248
    0
                            "Overflow happened on: {:?} ^ {exp:?}",
    249
    0
                            self
    250
    0
                        ))
    251
    0
                    })
    252
    0
                }
    253
    254
                #[inline]
    255
    0
                fn pow_wrapping(self, exp: u32) -> Self {
    256
    0
                    self.wrapping_pow(exp)
    257
    0
                }
    258
    259
                #[inline]
    260
    0
                fn neg_wrapping(self) -> Self {
    261
    0
                    self.wrapping_neg()
    262
    0
                }
    263
    264
                #[inline]
    265
    0
                fn is_zero(self) -> bool {
    266
    0
                    self == Self::ZERO
    267
    0
                }
    268
    269
                #[inline]
    270
    51
                fn compare(self, rhs: Self) -> Ordering {
    271
    51
                    self.cmp(&rhs)
    272
    51
                }
    273
    274
                #[inline]
    275
    0
                fn is_eq(self, rhs: Self) -> bool {
    276
    0
                    self == rhs
    277
    0
                }
    278
            }
    279
        };
    280
    }
    281
    282
    native_type_op!(i8);
    283
    native_type_op!(i16);
    284
    native_type_op!(i32);
    285
    native_type_op!(i64);
    286
    native_type_op!(i128);
    287
    native_type_op!(u8);
    288
    native_type_op!(u16);
    289
    native_type_op!(u32);
    290
    native_type_op!(u64);
    291
    native_type_op!(i256, i256::ZERO, i256::ONE, i256::MIN, i256::MAX);
    292
    293
    native_type_op!(IntervalDayTime, IntervalDayTime::ZERO, IntervalDayTime::ONE);
    294
    native_type_op!(
    295
        IntervalMonthDayNano,
    296
        IntervalMonthDayNano::ZERO,
    297
        IntervalMonthDayNano::ONE
    298
    );
    299
    300
    macro_rules! native_type_float_op {
    301
        ($t:tt, $zero:expr, $one:expr, $min:expr, $max:expr) => {
    302
            impl ArrowNativeTypeOp for $t {
    303
                const ZERO: Self = $zero;
    304
                const ONE: Self = $one;
    305
                const MIN_TOTAL_ORDER: Self = $min;
    306
                const MAX_TOTAL_ORDER: Self = $max;
    307
    308
                #[inline]
    309
                fn add_checked(self, rhs: Self) -> Result<Self, ArrowError> {
    310
                    Ok(self + rhs)
    311
                }
    312
    313
                #[inline]
    314
    0
                fn add_wrapping(self, rhs: Self) -> Self {
    315
    0
                    self + rhs
    316
    0
                }
    317
    318
                #[inline]
    319
                fn sub_checked(self, rhs: Self) -> Result<Self, ArrowError> {
    320
                    Ok(self - rhs)
    321
                }
    322
    323
                #[inline]
    324
    0
                fn sub_wrapping(self, rhs: Self) -> Self {
    325
    0
                    self - rhs
    326
    0
                }
    327
    328
                #[inline]
    329
                fn mul_checked(self, rhs: Self) -> Result<Self, ArrowError> {
    330
                    Ok(self * rhs)
    331
                }
    332
    333
                #[inline]
    334
    0
                fn mul_wrapping(self, rhs: Self) -> Self {
    335
    0
                    self * rhs
    336
    0
                }
    337
    338
                #[inline]
    339
                fn div_checked(self, rhs: Self) -> Result<Self, ArrowError> {
    340
                    if rhs.is_zero() {
    341
                        Err(ArrowError::DivideByZero)
    342
                    } else {
    343
                        Ok(self / rhs)
    344
                    }
    345
                }
    346
    347
                #[inline]
    348
    0
                fn div_wrapping(self, rhs: Self) -> Self {
    349
    0
                    self / rhs
    350
    0
                }
    351
    352
                #[inline]
    353
                fn mod_checked(self, rhs: Self) -> Result<Self, ArrowError> {
    354
                    if rhs.is_zero() {
    355
                        Err(ArrowError::DivideByZero)
    356
                    } else {
    357
                        Ok(self % rhs)
    358
                    }
    359
                }
    360
    361
                #[inline]
    362
    0
                fn mod_wrapping(self, rhs: Self) -> Self {
    363
    0
                    self % rhs
    364
    0
                }
    365
    366
                #[inline]
    367
                fn neg_checked(self) -> Result<Self, ArrowError> {
    368
                    Ok(-self)
    369
                }
    370
    371
                #[inline]
    372
    0
                fn neg_wrapping(self) -> Self {
    373
    0
                    -self
    374
    0
                }
    375
    376
                #[inline]
    377
                fn pow_checked(self, exp: u32) -> Result<Self, ArrowError> {
    378
                    Ok(self.powi(exp as i32))
    379
                }
    380
    381
                #[inline]
    382
                fn pow_wrapping(self, exp: u32) -> Self {
    383
                    self.powi(exp as i32)
    384
                }
    385
    386
                #[inline]
    387
                fn is_zero(self) -> bool {
    388
                    self == $zero
    389
                }
    390
    391
                #[inline]
    392
    0
                fn compare(self, rhs: Self) -> Ordering {
    393
    0
                    <$t>::total_cmp(&self, &rhs)
    394
    0
                }
    395
    396
                #[inline]
    397
    0
                fn is_eq(self, rhs: Self) -> bool {
    398
                    // Equivalent to `self.total_cmp(&rhs).is_eq()`
    399
                    // but LLVM isn't able to realise this is bitwise equality
    400
                    // https://rust.godbolt.org/z/347nWGxoW
    401
    0
                    self.to_bits() == rhs.to_bits()
    402
    0
                }
    403
            }
    404
        };
    405
    }
    406
    407
    // the smallest/largest bit patterns for floating point numbers are NaN, but differ from the canonical NAN constants.
    408
    // See test_float_total_order_min_max for details.
    409
    native_type_float_op!(
    410
        f16,
    411
        f16::ZERO,
    412
        f16::ONE,
    413
        f16::from_bits(-1 as _),
    414
        f16::from_bits(i16::MAX as _)
    415
    );
    416
    // from_bits is not yet stable as const fn, see https://github.com/rust-lang/rust/issues/72447
    417
    native_type_float_op!(
    418
        f32,
    419
        0.,
    420
        1.,
    421
        unsafe {
    422
            // Need to allow in clippy because
    423
            // current MSRV (Minimum Supported Rust Version) is `1.84.0` but this item is stable since `1.87.0`
    424
            #[allow(unnecessary_transmutes)]
    425
            std::mem::transmute(-1_i32)
    426
        },
    427
        unsafe {
    428
            // Need to allow in clippy because
    429
            // current MSRV (Minimum Supported Rust Version) is `1.84.0` but this item is stable since `1.87.0`
    430
            #[allow(unnecessary_transmutes)]
    431
            std::mem::transmute(i32::MAX)
    432
        }
    433
    );
    434
    native_type_float_op!(
    435
        f64,
    436
        0.,
    437
        1.,
    438
        unsafe {
    439
            // Need to allow in clippy because
    440
            // current MSRV (Minimum Supported Rust Version) is `1.84.0` but this item is stable since `1.87.0`
    441
            #[allow(unnecessary_transmutes)]
    442
            std::mem::transmute(-1_i64)
    443
        },
    444
        unsafe {
    445
            // Need to allow in clippy because
    446
            // current MSRV (Minimum Supported Rust Version) is `1.84.0` but this item is stable since `1.87.0`
    447
            #[allow(unnecessary_transmutes)]
    448
            std::mem::transmute(i64::MAX)
    449
        }
    450
    );
    451
    452
    #[cfg(test)]
    453
    mod tests {
    454
        use super::*;
    455
    456
        macro_rules! assert_approx_eq {
    457
            ( $x: expr, $y: expr ) => {{
    458
                assert_approx_eq!($x, $y, 1.0e-4)
    459
            }};
    460
            ( $x: expr, $y: expr, $tol: expr ) => {{
    461
                let x_val = $x;
    462
                let y_val = $y;
    463
                let diff = f64::from((x_val - y_val).abs());
    464
                assert!(
    465
                    diff <= $tol,
    466
                    "{} != {} (with tolerance = {})",
    467
                    x_val,
    468
                    y_val,
    469
                    $tol
    470
                );
    471
            }};
    472
        }
    473
    474
        #[test]
    475
        fn test_native_type_is_zero() {
    476
            assert!(0_i8.is_zero());
    477
            assert!(0_i16.is_zero());
    478
            assert!(0_i32.is_zero());
    479
            assert!(0_i64.is_zero());
    480
            assert!(0_i128.is_zero());
    481
            assert!(i256::ZERO.is_zero());
    482
            assert!(0_u8.is_zero());
    483
            assert!(0_u16.is_zero());
    484
            assert!(0_u32.is_zero());
    485
            assert!(0_u64.is_zero());
    486
            assert!(f16::ZERO.is_zero());
    487
            assert!(0.0_f32.is_zero());
    488
            assert!(0.0_f64.is_zero());
    489
        }
    490
    491
        #[test]
    492
        fn test_native_type_comparison() {
    493
            // is_eq
    494
            assert!(8_i8.is_eq(8_i8));
    495
            assert!(8_i16.is_eq(8_i16));
    496
            assert!(8_i32.is_eq(8_i32));
    497
            assert!(8_i64.is_eq(8_i64));
    498
            assert!(8_i128.is_eq(8_i128));
    499
            assert!(i256::from_parts(8, 0).is_eq(i256::from_parts(8, 0)));
    500
            assert!(8_u8.is_eq(8_u8));
    501
            assert!(8_u16.is_eq(8_u16));
    502
            assert!(8_u32.is_eq(8_u32));
    503
            assert!(8_u64.is_eq(8_u64));
    504
            assert!(f16::from_f32(8.0).is_eq(f16::from_f32(8.0)));
    505
            assert!(8.0_f32.is_eq(8.0_f32));
    506
            assert!(8.0_f64.is_eq(8.0_f64));
    507
    508
            // is_ne
    509
            assert!(8_i8.is_ne(1_i8));
    510
            assert!(8_i16.is_ne(1_i16));
    511
            assert!(8_i32.is_ne(1_i32));
    512
            assert!(8_i64.is_ne(1_i64));
    513
            assert!(8_i128.is_ne(1_i128));
    514
            assert!(i256::from_parts(8, 0).is_ne(i256::from_parts(1, 0)));
    515
            assert!(8_u8.is_ne(1_u8));
    516
            assert!(8_u16.is_ne(1_u16));
    517
            assert!(8_u32.is_ne(1_u32));
    518
            assert!(8_u64.is_ne(1_u64));
    519
            assert!(f16::from_f32(8.0).is_ne(f16::from_f32(1.0)));
    520
            assert!(8.0_f32.is_ne(1.0_f32));
    521
            assert!(8.0_f64.is_ne(1.0_f64));
    522
    523
            // is_lt
    524
            assert!(8_i8.is_lt(10_i8));
    525
            assert!(8_i16.is_lt(10_i16));
    526
            assert!(8_i32.is_lt(10_i32));
    527
            assert!(8_i64.is_lt(10_i64));
    528
            assert!(8_i128.is_lt(10_i128));
    529
            assert!(i256::from_parts(8, 0).is_lt(i256::from_parts(10, 0)));
    530
            assert!(8_u8.is_lt(10_u8));
    531
            assert!(8_u16.is_lt(10_u16));
    532
            assert!(8_u32.is_lt(10_u32));
    533
            assert!(8_u64.is_lt(10_u64));
    534
            assert!(f16::from_f32(8.0).is_lt(f16::from_f32(10.0)));
    535
            assert!(8.0_f32.is_lt(10.0_f32));
    536
            assert!(8.0_f64.is_lt(10.0_f64));
    537
    538
            // is_gt
    539
            assert!(8_i8.is_gt(1_i8));
    540
            assert!(8_i16.is_gt(1_i16));
    541
            assert!(8_i32.is_gt(1_i32));
    542
            assert!(8_i64.is_gt(1_i64));
    543
            assert!(8_i128.is_gt(1_i128));
    544
            assert!(i256::from_parts(8, 0).is_gt(i256::from_parts(1, 0)));
    545
            assert!(8_u8.is_gt(1_u8));
    546
            assert!(8_u16.is_gt(1_u16));
    547
            assert!(8_u32.is_gt(1_u32));
    548
            assert!(8_u64.is_gt(1_u64));
    549
            assert!(f16::from_f32(8.0).is_gt(f16::from_f32(1.0)));
    550
            assert!(8.0_f32.is_gt(1.0_f32));
    551
            assert!(8.0_f64.is_gt(1.0_f64));
    552
        }
    553
    554
        #[test]
    555
        fn test_native_type_add() {
    556
            // add_wrapping
    557
            assert_eq!(8_i8.add_wrapping(2_i8), 10_i8);
    558
            assert_eq!(8_i16.add_wrapping(2_i16), 10_i16);
    559
            assert_eq!(8_i32.add_wrapping(2_i32), 10_i32);
    560
            assert_eq!(8_i64.add_wrapping(2_i64), 10_i64);
    561
            assert_eq!(8_i128.add_wrapping(2_i128), 10_i128);
    562
            assert_eq!(
    563
                i256::from_parts(8, 0).add_wrapping(i256::from_parts(2, 0)),
    564
                i256::from_parts(10, 0)
    565
            );
    566
            assert_eq!(8_u8.add_wrapping(2_u8), 10_u8);
    567
            assert_eq!(8_u16.add_wrapping(2_u16), 10_u16);
    568
            assert_eq!(8_u32.add_wrapping(2_u32), 10_u32);
    569
            assert_eq!(8_u64.add_wrapping(2_u64), 10_u64);
    570
            assert_eq!(
    571
                f16::from_f32(8.0).add_wrapping(f16::from_f32(2.0)),
    572
                f16::from_f32(10.0)
    573
            );
    574
            assert_eq!(8.0_f32.add_wrapping(2.0_f32), 10_f32);
    575
            assert_eq!(8.0_f64.add_wrapping(2.0_f64), 10_f64);
    576
    577
            // add_checked
    578
            assert_eq!(8_i8.add_checked(2_i8).unwrap(), 10_i8);
    579
            assert_eq!(8_i16.add_checked(2_i16).unwrap(), 10_i16);
    580
            assert_eq!(8_i32.add_checked(2_i32).unwrap(), 10_i32);
    581
            assert_eq!(8_i64.add_checked(2_i64).unwrap(), 10_i64);
    582
            assert_eq!(8_i128.add_checked(2_i128).unwrap(), 10_i128);
    583
            assert_eq!(
    584
                i256::from_parts(8, 0)
    585
                    .add_checked(i256::from_parts(2, 0))
    586
                    .unwrap(),
    587
                i256::from_parts(10, 0)
    588
            );
    589
            assert_eq!(8_u8.add_checked(2_u8).unwrap(), 10_u8);
    590
            assert_eq!(8_u16.add_checked(2_u16).unwrap(), 10_u16);
    591
            assert_eq!(8_u32.add_checked(2_u32).unwrap(), 10_u32);
    592
            assert_eq!(8_u64.add_checked(2_u64).unwrap(), 10_u64);
    593
            assert_eq!(
    594
                f16::from_f32(8.0).add_checked(f16::from_f32(2.0)).unwrap(),
    595
                f16::from_f32(10.0)
    596
            );
    597
            assert_eq!(8.0_f32.add_checked(2.0_f32).unwrap(), 10_f32);
    598
            assert_eq!(8.0_f64.add_checked(2.0_f64).unwrap(), 10_f64);
    599
        }
    600
    601
        #[test]
    602
        fn test_native_type_sub() {
    603
            // sub_wrapping
    604
            assert_eq!(8_i8.sub_wrapping(2_i8), 6_i8);
    605
            assert_eq!(8_i16.sub_wrapping(2_i16), 6_i16);
    606
            assert_eq!(8_i32.sub_wrapping(2_i32), 6_i32);
    607
            assert_eq!(8_i64.sub_wrapping(2_i64), 6_i64);
    608
            assert_eq!(8_i128.sub_wrapping(2_i128), 6_i128);
    609
            assert_eq!(
    610
                i256::from_parts(8, 0).sub_wrapping(i256::from_parts(2, 0)),
    611
                i256::from_parts(6, 0)
    612
            );
    613
            assert_eq!(8_u8.sub_wrapping(2_u8), 6_u8);
    614
            assert_eq!(8_u16.sub_wrapping(2_u16), 6_u16);
    615
            assert_eq!(8_u32.sub_wrapping(2_u32), 6_u32);
    616
            assert_eq!(8_u64.sub_wrapping(2_u64), 6_u64);
    617
            assert_eq!(
    618
                f16::from_f32(8.0).sub_wrapping(f16::from_f32(2.0)),
    619
                f16::from_f32(6.0)
    620
            );
    621
            assert_eq!(8.0_f32.sub_wrapping(2.0_f32), 6_f32);
    622
            assert_eq!(8.0_f64.sub_wrapping(2.0_f64), 6_f64);
    623
    624
            // sub_checked
    625
            assert_eq!(8_i8.sub_checked(2_i8).unwrap(), 6_i8);
    626
            assert_eq!(8_i16.sub_checked(2_i16).unwrap(), 6_i16);
    627
            assert_eq!(8_i32.sub_checked(2_i32).unwrap(), 6_i32);
    628
            assert_eq!(8_i64.sub_checked(2_i64).unwrap(), 6_i64);
    629
            assert_eq!(8_i128.sub_checked(2_i128).unwrap(), 6_i128);
    630
            assert_eq!(
    631
                i256::from_parts(8, 0)
    632
                    .sub_checked(i256::from_parts(2, 0))
    633
                    .unwrap(),
    634
                i256::from_parts(6, 0)
    635
            );
    636
            assert_eq!(8_u8.sub_checked(2_u8).unwrap(), 6_u8);
    637
            assert_eq!(8_u16.sub_checked(2_u16).unwrap(), 6_u16);
    638
            assert_eq!(8_u32.sub_checked(2_u32).unwrap(), 6_u32);
    639
            assert_eq!(8_u64.sub_checked(2_u64).unwrap(), 6_u64);
    640
            assert_eq!(
    641
                f16::from_f32(8.0).sub_checked(f16::from_f32(2.0)).unwrap(),
    642
                f16::from_f32(6.0)
    643
            );
    644
            assert_eq!(8.0_f32.sub_checked(2.0_f32).unwrap(), 6_f32);
    645
            assert_eq!(8.0_f64.sub_checked(2.0_f64).unwrap(), 6_f64);
    646
        }
    647
    648
        #[test]
    649
        fn test_native_type_mul() {
    650
            // mul_wrapping
    651
            assert_eq!(8_i8.mul_wrapping(2_i8), 16_i8);
    652
            assert_eq!(8_i16.mul_wrapping(2_i16), 16_i16);
    653
            assert_eq!(8_i32.mul_wrapping(2_i32), 16_i32);
    654
            assert_eq!(8_i64.mul_wrapping(2_i64), 16_i64);
    655
            assert_eq!(8_i128.mul_wrapping(2_i128), 16_i128);
    656
            assert_eq!(
    657
                i256::from_parts(8, 0).mul_wrapping(i256::from_parts(2, 0)),
    658
                i256::from_parts(16, 0)
    659
            );
    660
            assert_eq!(8_u8.mul_wrapping(2_u8), 16_u8);
    661
            assert_eq!(8_u16.mul_wrapping(2_u16), 16_u16);
    662
            assert_eq!(8_u32.mul_wrapping(2_u32), 16_u32);
    663
            assert_eq!(8_u64.mul_wrapping(2_u64), 16_u64);
    664
            assert_eq!(
    665
                f16::from_f32(8.0).mul_wrapping(f16::from_f32(2.0)),
    666
                f16::from_f32(16.0)
    667
            );
    668
            assert_eq!(8.0_f32.mul_wrapping(2.0_f32), 16_f32);
    669
            assert_eq!(8.0_f64.mul_wrapping(2.0_f64), 16_f64);
    670
    671
            // mul_checked
    672
            assert_eq!(8_i8.mul_checked(2_i8).unwrap(), 16_i8);
    673
            assert_eq!(8_i16.mul_checked(2_i16).unwrap(), 16_i16);
    674
            assert_eq!(8_i32.mul_checked(2_i32).unwrap(), 16_i32);
    675
            assert_eq!(8_i64.mul_checked(2_i64).unwrap(), 16_i64);
    676
            assert_eq!(8_i128.mul_checked(2_i128).unwrap(), 16_i128);
    677
            assert_eq!(
    678
                i256::from_parts(8, 0)
    679
                    .mul_checked(i256::from_parts(2, 0))
    680
                    .unwrap(),
    681
                i256::from_parts(16, 0)
    682
            );
    683
            assert_eq!(8_u8.mul_checked(2_u8).unwrap(), 16_u8);
    684
            assert_eq!(8_u16.mul_checked(2_u16).unwrap(), 16_u16);
    685
            assert_eq!(8_u32.mul_checked(2_u32).unwrap(), 16_u32);
    686
            assert_eq!(8_u64.mul_checked(2_u64).unwrap(), 16_u64);
    687
            assert_eq!(
    688
                f16::from_f32(8.0).mul_checked(f16::from_f32(2.0)).unwrap(),
    689
                f16::from_f32(16.0)
    690
            );
    691
            assert_eq!(8.0_f32.mul_checked(2.0_f32).unwrap(), 16_f32);
    692
            assert_eq!(8.0_f64.mul_checked(2.0_f64).unwrap(), 16_f64);
    693
        }
    694
    695
        #[test]
    696
        fn test_native_type_div() {
    697
            // div_wrapping
    698
            assert_eq!(8_i8.div_wrapping(2_i8), 4_i8);
    699
            assert_eq!(8_i16.div_wrapping(2_i16), 4_i16);
    700
            assert_eq!(8_i32.div_wrapping(2_i32), 4_i32);
    701
            assert_eq!(8_i64.div_wrapping(2_i64), 4_i64);
    702
            assert_eq!(8_i128.div_wrapping(2_i128), 4_i128);
    703
            assert_eq!(
    704
                i256::from_parts(8, 0).div_wrapping(i256::from_parts(2, 0)),
    705
                i256::from_parts(4, 0)
    706
            );
    707
            assert_eq!(8_u8.div_wrapping(2_u8), 4_u8);
    708
            assert_eq!(8_u16.div_wrapping(2_u16), 4_u16);
    709
            assert_eq!(8_u32.div_wrapping(2_u32), 4_u32);
    710
            assert_eq!(8_u64.div_wrapping(2_u64), 4_u64);
    711
            assert_eq!(
    712
                f16::from_f32(8.0).div_wrapping(f16::from_f32(2.0)),
    713
                f16::from_f32(4.0)
    714
            );
    715
            assert_eq!(8.0_f32.div_wrapping(2.0_f32), 4_f32);
    716
            assert_eq!(8.0_f64.div_wrapping(2.0_f64), 4_f64);
    717
    718
            // div_checked
    719
            assert_eq!(8_i8.div_checked(2_i8).unwrap(), 4_i8);
    720
            assert_eq!(8_i16.div_checked(2_i16).unwrap(), 4_i16);
    721
            assert_eq!(8_i32.div_checked(2_i32).unwrap(), 4_i32);
    722
            assert_eq!(8_i64.div_checked(2_i64).unwrap(), 4_i64);
    723
            assert_eq!(8_i128.div_checked(2_i128).unwrap(), 4_i128);
    724
            assert_eq!(
    725
                i256::from_parts(8, 0)
    726
                    .div_checked(i256::from_parts(2, 0))
    727
                    .unwrap(),
    728
                i256::from_parts(4, 0)
    729
            );
    730
            assert_eq!(8_u8.div_checked(2_u8).unwrap(), 4_u8);
    731
            assert_eq!(8_u16.div_checked(2_u16).unwrap(), 4_u16);
    732
            assert_eq!(8_u32.div_checked(2_u32).unwrap(), 4_u32);
    733
            assert_eq!(8_u64.div_checked(2_u64).unwrap(), 4_u64);
    734
            assert_eq!(
    735
                f16::from_f32(8.0).div_checked(f16::from_f32(2.0)).unwrap(),
    736
                f16::from_f32(4.0)
    737
            );
    738
            assert_eq!(8.0_f32.div_checked(2.0_f32).unwrap(), 4_f32);
    739
            assert_eq!(8.0_f64.div_checked(2.0_f64).unwrap(), 4_f64);
    740
        }
    741
    742
        #[test]
    743
        fn test_native_type_mod() {
    744
            // mod_wrapping
    745
            assert_eq!(9_i8.mod_wrapping(2_i8), 1_i8);
    746
            assert_eq!(9_i16.mod_wrapping(2_i16), 1_i16);
    747
            assert_eq!(9_i32.mod_wrapping(2_i32), 1_i32);
    748
            assert_eq!(9_i64.mod_wrapping(2_i64), 1_i64);
    749
            assert_eq!(9_i128.mod_wrapping(2_i128), 1_i128);
    750
            assert_eq!(
    751
                i256::from_parts(9, 0).mod_wrapping(i256::from_parts(2, 0)),
    752
                i256::from_parts(1, 0)
    753
            );
    754
            assert_eq!(9_u8.mod_wrapping(2_u8), 1_u8);
    755
            assert_eq!(9_u16.mod_wrapping(2_u16), 1_u16);
    756
            assert_eq!(9_u32.mod_wrapping(2_u32), 1_u32);
    757
            assert_eq!(9_u64.mod_wrapping(2_u64), 1_u64);
    758
            assert_eq!(
    759
                f16::from_f32(9.0).mod_wrapping(f16::from_f32(2.0)),
    760
                f16::from_f32(1.0)
    761
            );
    762
            assert_eq!(9.0_f32.mod_wrapping(2.0_f32), 1_f32);
    763
            assert_eq!(9.0_f64.mod_wrapping(2.0_f64), 1_f64);
    764
    765
            // mod_checked
    766
            assert_eq!(9_i8.mod_checked(2_i8).unwrap(), 1_i8);
    767
            assert_eq!(9_i16.mod_checked(2_i16).unwrap(), 1_i16);
    768
            assert_eq!(9_i32.mod_checked(2_i32).unwrap(), 1_i32);
    769
            assert_eq!(9_i64.mod_checked(2_i64).unwrap(), 1_i64);
    770
            assert_eq!(9_i128.mod_checked(2_i128).unwrap(), 1_i128);
    771
            assert_eq!(
    772
                i256::from_parts(9, 0)
    773
                    .mod_checked(i256::from_parts(2, 0))
    774
                    .unwrap(),
    775
                i256::from_parts(1, 0)
    776
            );
    777
            assert_eq!(9_u8.mod_checked(2_u8).unwrap(), 1_u8);
    778
            assert_eq!(9_u16.mod_checked(2_u16).unwrap(), 1_u16);
    779
            assert_eq!(9_u32.mod_checked(2_u32).unwrap(), 1_u32);
    780
            assert_eq!(9_u64.mod_checked(2_u64).unwrap(), 1_u64);
    781
            assert_eq!(
    782
                f16::from_f32(9.0).mod_checked(f16::from_f32(2.0)).unwrap(),
    783
                f16::from_f32(1.0)
    784
            );
    785
            assert_eq!(9.0_f32.mod_checked(2.0_f32).unwrap(), 1_f32);
    786
            assert_eq!(9.0_f64.mod_checked(2.0_f64).unwrap(), 1_f64);
    787
        }
    788
    789
        #[test]
    790
        fn test_native_type_neg() {
    791
            // neg_wrapping
    792
            assert_eq!(8_i8.neg_wrapping(), -8_i8);
    793
            assert_eq!(8_i16.neg_wrapping(), -8_i16);
    794
            assert_eq!(8_i32.neg_wrapping(), -8_i32);
    795
            assert_eq!(8_i64.neg_wrapping(), -8_i64);
    796
            assert_eq!(8_i128.neg_wrapping(), -8_i128);
    797
            assert_eq!(i256::from_parts(8, 0).neg_wrapping(), i256::from_i128(-8));
    798
            assert_eq!(8_u8.neg_wrapping(), u8::MAX - 7_u8);
    799
            assert_eq!(8_u16.neg_wrapping(), u16::MAX - 7_u16);
    800
            assert_eq!(8_u32.neg_wrapping(), u32::MAX - 7_u32);
    801
            assert_eq!(8_u64.neg_wrapping(), u64::MAX - 7_u64);
    802
            assert_eq!(f16::from_f32(8.0).neg_wrapping(), f16::from_f32(-8.0));
    803
            assert_eq!(8.0_f32.neg_wrapping(), -8_f32);
    804
            assert_eq!(8.0_f64.neg_wrapping(), -8_f64);
    805
    806
            // neg_checked
    807
            assert_eq!(8_i8.neg_checked().unwrap(), -8_i8);
    808
            assert_eq!(8_i16.neg_checked().unwrap(), -8_i16);
    809
            assert_eq!(8_i32.neg_checked().unwrap(), -8_i32);
    810
            assert_eq!(8_i64.neg_checked().unwrap(), -8_i64);
    811
            assert_eq!(8_i128.neg_checked().unwrap(), -8_i128);
    812
            assert_eq!(
    813
                i256::from_parts(8, 0).neg_checked().unwrap(),
    814
                i256::from_i128(-8)
    815
            );
    816
            assert!(8_u8.neg_checked().is_err());
    817
            assert!(8_u16.neg_checked().is_err());
    818
            assert!(8_u32.neg_checked().is_err());
    819
            assert!(8_u64.neg_checked().is_err());
    820
            assert_eq!(
    821
                f16::from_f32(8.0).neg_checked().unwrap(),
    822
                f16::from_f32(-8.0)
    823
            );
    824
            assert_eq!(8.0_f32.neg_checked().unwrap(), -8_f32);
    825
            assert_eq!(8.0_f64.neg_checked().unwrap(), -8_f64);
    826
        }
    827
    828
        #[test]
    829
        fn test_native_type_pow() {
    830
            // pow_wrapping
    831
            assert_eq!(8_i8.pow_wrapping(2_u32), 64_i8);
    832
            assert_eq!(8_i16.pow_wrapping(2_u32), 64_i16);
    833
            assert_eq!(8_i32.pow_wrapping(2_u32), 64_i32);
    834
            assert_eq!(8_i64.pow_wrapping(2_u32), 64_i64);
    835
            assert_eq!(8_i128.pow_wrapping(2_u32), 64_i128);
    836
            assert_eq!(
    837
                i256::from_parts(8, 0).pow_wrapping(2_u32),
    838
                i256::from_parts(64, 0)
    839
            );
    840
            assert_eq!(8_u8.pow_wrapping(2_u32), 64_u8);
    841
            assert_eq!(8_u16.pow_wrapping(2_u32), 64_u16);
    842
            assert_eq!(8_u32.pow_wrapping(2_u32), 64_u32);
    843
            assert_eq!(8_u64.pow_wrapping(2_u32), 64_u64);
    844
            assert_approx_eq!(f16::from_f32(8.0).pow_wrapping(2_u32), f16::from_f32(64.0));
    845
            assert_approx_eq!(8.0_f32.pow_wrapping(2_u32), 64_f32);
    846
            assert_approx_eq!(8.0_f64.pow_wrapping(2_u32), 64_f64);
    847
    848
            // pow_checked
    849
            assert_eq!(8_i8.pow_checked(2_u32).unwrap(), 64_i8);
    850
            assert_eq!(8_i16.pow_checked(2_u32).unwrap(), 64_i16);
    851
            assert_eq!(8_i32.pow_checked(2_u32).unwrap(), 64_i32);
    852
            assert_eq!(8_i64.pow_checked(2_u32).unwrap(), 64_i64);
    853
            assert_eq!(8_i128.pow_checked(2_u32).unwrap(), 64_i128);
    854
            assert_eq!(
    855
                i256::from_parts(8, 0).pow_checked(2_u32).unwrap(),
    856
                i256::from_parts(64, 0)
    857
            );
    858
            assert_eq!(8_u8.pow_checked(2_u32).unwrap(), 64_u8);
    859
            assert_eq!(8_u16.pow_checked(2_u32).unwrap(), 64_u16);
    860
            assert_eq!(8_u32.pow_checked(2_u32).unwrap(), 64_u32);
    861
            assert_eq!(8_u64.pow_checked(2_u32).unwrap(), 64_u64);
    862
            assert_approx_eq!(
    863
                f16::from_f32(8.0).pow_checked(2_u32).unwrap(),
    864
                f16::from_f32(64.0)
    865
            );
    866
            assert_approx_eq!(8.0_f32.pow_checked(2_u32).unwrap(), 64_f32);
    867
            assert_approx_eq!(8.0_f64.pow_checked(2_u32).unwrap(), 64_f64);
    868
        }
    869
    870
        #[test]
    871
        fn test_float_total_order_min_max() {
    872
            assert!(<f64 as ArrowNativeTypeOp>::MIN_TOTAL_ORDER.is_lt(f64::NEG_INFINITY));
    873
            assert!(<f64 as ArrowNativeTypeOp>::MAX_TOTAL_ORDER.is_gt(f64::INFINITY));
    874
    875
            assert!(<f64 as ArrowNativeTypeOp>::MIN_TOTAL_ORDER.is_nan());
    876
            assert!(<f64 as ArrowNativeTypeOp>::MIN_TOTAL_ORDER.is_sign_negative());
    877
            assert!(<f64 as ArrowNativeTypeOp>::MIN_TOTAL_ORDER.is_lt(-f64::NAN));
    878
    879
            assert!(<f64 as ArrowNativeTypeOp>::MAX_TOTAL_ORDER.is_nan());
    880
            assert!(<f64 as ArrowNativeTypeOp>::MAX_TOTAL_ORDER.is_sign_positive());
    881
            assert!(<f64 as ArrowNativeTypeOp>::MAX_TOTAL_ORDER.is_gt(f64::NAN));
    882
    883
            assert!(<f32 as ArrowNativeTypeOp>::MIN_TOTAL_ORDER.is_lt(f32::NEG_INFINITY));
    884
            assert!(<f32 as ArrowNativeTypeOp>::MAX_TOTAL_ORDER.is_gt(f32::INFINITY));
    885
    886
            assert!(<f32 as ArrowNativeTypeOp>::MIN_TOTAL_ORDER.is_nan());
    887
            assert!(<f32 as ArrowNativeTypeOp>::MIN_TOTAL_ORDER.is_sign_negative());
    888
            assert!(<f32 as ArrowNativeTypeOp>::MIN_TOTAL_ORDER.is_lt(-f32::NAN));
    889
    890
            assert!(<f32 as ArrowNativeTypeOp>::MAX_TOTAL_ORDER.is_nan());
    891
            assert!(<f32 as ArrowNativeTypeOp>::MAX_TOTAL_ORDER.is_sign_positive());
    892
            assert!(<f32 as ArrowNativeTypeOp>::MAX_TOTAL_ORDER.is_gt(f32::NAN));
    893
    894
            assert!(<f16 as ArrowNativeTypeOp>::MIN_TOTAL_ORDER.is_lt(f16::NEG_INFINITY));
    895
            assert!(<f16 as ArrowNativeTypeOp>::MAX_TOTAL_ORDER.is_gt(f16::INFINITY));
    896
    897
            assert!(<f16 as ArrowNativeTypeOp>::MIN_TOTAL_ORDER.is_nan());
    898
            assert!(<f16 as ArrowNativeTypeOp>::MIN_TOTAL_ORDER.is_sign_negative());
    899
            assert!(<f16 as ArrowNativeTypeOp>::MIN_TOTAL_ORDER.is_lt(-f16::NAN));
    900
    901
            assert!(<f16 as ArrowNativeTypeOp>::MAX_TOTAL_ORDER.is_nan());
    902
            assert!(<f16 as ArrowNativeTypeOp>::MAX_TOTAL_ORDER.is_sign_positive());
    903
            assert!(<f16 as ArrowNativeTypeOp>::MAX_TOTAL_ORDER.is_gt(f16::NAN));
    904
        }
    905
    }