cfavml 0.2.0

CF's Accelerated Vector Math Library providing SIMD optimzied routines for vector operations
Documentation
use core::intrinsics;

use super::{Math, StdMath};

/// Basic math operations backed by fast-math intrinsics.
pub struct FastMath;

impl Math<f32> for FastMath {
    #[inline(always)]
    fn zero() -> f32 {
        0.0
    }

    #[inline(always)]
    fn one() -> f32 {
        1.0
    }

    #[inline(always)]
    fn max() -> f32 {
        f32::INFINITY
    }

    #[inline(always)]
    fn min() -> f32 {
        f32::NEG_INFINITY
    }

    #[inline(always)]
    fn sqrt(a: f32) -> f32 {
        StdMath::sqrt(a)
    }

    #[inline(always)]
    fn abs(a: f32) -> f32 {
        StdMath::abs(a)
    }

    #[inline(always)]
    fn cmp_eq(a: f32, b: f32) -> bool {
        a == b
    }

    #[inline(always)]
    fn cmp_min(a: f32, b: f32) -> f32 {
        a.min(b)
    }

    #[inline(always)]
    fn cmp_max(a: f32, b: f32) -> f32 {
        a.max(b)
    }

    #[inline(always)]
    fn add(a: f32, b: f32) -> f32 {
        if cfg!(miri) {
            a + b
        } else {
            intrinsics::fadd_algebraic(a, b)
        }
    }

    #[inline(always)]
    fn sub(a: f32, b: f32) -> f32 {
        if cfg!(miri) {
            a - b
        } else {
            intrinsics::fsub_algebraic(a, b)
        }
    }

    #[inline(always)]
    fn mul(a: f32, b: f32) -> f32 {
        if cfg!(miri) {
            a * b
        } else {
            intrinsics::fmul_algebraic(a, b)
        }
    }

    #[inline(always)]
    fn div(a: f32, b: f32) -> f32 {
        if cfg!(miri) {
            a / b
        } else {
            intrinsics::fdiv_algebraic(a, b)
        }
    }

    #[cfg(test)]
    fn is_close(a: f32, b: f32) -> bool {
        let max = a.max(b);
        let min = a.min(b);
        let diff = max - min;
        diff <= 0.00015
    }
}

impl Math<f64> for FastMath {
    #[inline(always)]
    fn zero() -> f64 {
        0.0
    }

    #[inline(always)]
    fn one() -> f64 {
        1.0
    }

    #[inline(always)]
    fn max() -> f64 {
        f64::INFINITY
    }

    #[inline(always)]
    fn min() -> f64 {
        f64::NEG_INFINITY
    }

    #[inline(always)]
    fn sqrt(a: f64) -> f64 {
        StdMath::sqrt(a)
    }

    #[inline(always)]
    fn abs(a: f64) -> f64 {
        StdMath::abs(a)
    }

    #[inline(always)]
    fn cmp_eq(a: f64, b: f64) -> bool {
        a == b
    }

    #[inline(always)]
    fn cmp_min(a: f64, b: f64) -> f64 {
        a.min(b)
    }

    #[inline(always)]
    fn cmp_max(a: f64, b: f64) -> f64 {
        a.max(b)
    }

    #[inline(always)]
    fn add(a: f64, b: f64) -> f64 {
        if cfg!(miri) {
            a + b
        } else {
            intrinsics::fadd_algebraic(a, b)
        }
    }

    #[inline(always)]
    fn sub(a: f64, b: f64) -> f64 {
        if cfg!(miri) {
            a - b
        } else {
            intrinsics::fsub_algebraic(a, b)
        }
    }

    #[inline(always)]
    fn mul(a: f64, b: f64) -> f64 {
        if cfg!(miri) {
            a * b
        } else {
            intrinsics::fmul_algebraic(a, b)
        }
    }

    #[inline(always)]
    fn div(a: f64, b: f64) -> f64 {
        if cfg!(miri) {
            a / b
        } else {
            intrinsics::fdiv_algebraic(a, b)
        }
    }

    #[cfg(test)]
    fn is_close(a: f64, b: f64) -> bool {
        let max = a.max(b);
        let min = a.min(b);
        let diff = max - min;
        diff <= 0.00015
    }
}

macro_rules! define_int_ops {
    ($t:ident) => {
        impl Math<$t> for FastMath {
            #[inline(always)]
            fn zero() -> $t {
                0
            }

            #[inline(always)]
            fn one() -> $t {
                1
            }

            #[inline(always)]
            fn max() -> $t {
                $t::MAX
            }

            #[inline(always)]
            fn min() -> $t {
                $t::MIN
            }

            #[inline(always)]
            fn sqrt(a: $t) -> $t {
                FastMath::sqrt(a as f64) as $t
            }

            #[inline(always)]
            fn abs(a: $t) -> $t {
                a.abs()
            }

            #[inline(always)]
            fn cmp_eq(a: $t, b: $t) -> bool {
                a == b
            }

            #[inline(always)]
            fn cmp_min(a: $t, b: $t) -> $t {
                a.min(b)
            }

            #[inline(always)]
            fn cmp_max(a: $t, b: $t) -> $t {
                a.max(b)
            }

            #[inline(always)]
            fn add(a: $t, b: $t) -> $t {
                a.wrapping_add(b)
            }

            #[inline(always)]
            fn sub(a: $t, b: $t) -> $t {
                a.wrapping_sub(b)
            }

            #[inline(always)]
            fn mul(a: $t, b: $t) -> $t {
                a.wrapping_mul(b)
            }

            #[inline(always)]
            fn div(a: $t, b: $t) -> $t {
                a.wrapping_div(b)
            }

            #[cfg(test)]
            fn is_close(a: $t, b: $t) -> bool {
                a == b
            }
        }
    };
    (unsigned $t:ident) => {
        impl Math<$t> for FastMath {
            #[inline(always)]
            fn zero() -> $t {
                0
            }

            #[inline(always)]
            fn one() -> $t {
                1
            }

            #[inline(always)]
            fn max() -> $t {
                $t::MAX
            }

            #[inline(always)]
            fn min() -> $t {
                $t::MIN
            }

            #[inline(always)]
            fn sqrt(a: $t) -> $t {
                FastMath::sqrt(a as f64) as $t
            }

            #[inline(always)]
            fn abs(a: $t) -> $t {
                a
            }

            #[inline(always)]
            fn cmp_eq(a: $t, b: $t) -> bool {
                a == b
            }

            #[inline(always)]
            fn cmp_min(a: $t, b: $t) -> $t {
                a.min(b)
            }

            #[inline(always)]
            fn cmp_max(a: $t, b: $t) -> $t {
                a.max(b)
            }

            #[inline(always)]
            fn add(a: $t, b: $t) -> $t {
                a.wrapping_add(b)
            }

            #[inline(always)]
            fn sub(a: $t, b: $t) -> $t {
                a.wrapping_sub(b)
            }

            #[inline(always)]
            fn mul(a: $t, b: $t) -> $t {
                a.wrapping_mul(b)
            }

            #[inline(always)]
            fn div(a: $t, b: $t) -> $t {
                a.wrapping_div(b)
            }

            #[cfg(test)]
            fn is_close(a: $t, b: $t) -> bool {
                a == b
            }
        }
    };
}

define_int_ops!(i8);
define_int_ops!(i16);
define_int_ops!(i32);
define_int_ops!(i64);

define_int_ops!(unsigned u8);
define_int_ops!(unsigned u16);
define_int_ops!(unsigned u32);
define_int_ops!(unsigned u64);