Program Listing for File vecOps.hpp#

Return to documentation for file (librapid/include/librapid/simd/vecOps.hpp)

#ifndef LIBRAPID_SIMD_TRIGONOMETRY
#define LIBRAPID_SIMD_TRIGONOMETRY

namespace librapid {
    namespace typetraits {
        template<typename T>
        struct IsSIMD : std::false_type {};

        template<typename T, typename U>
        struct IsSIMD<xsimd::batch<T, U>> : std::true_type {};

        template<typename T>
        struct IsSIMD<xsimd::batch_element_reference<T>> : std::true_type {};

        template<typename T>
        concept SIMD = IsSIMD<T>::value;
    } // namespace typetraits

#define IS_FLOATING(TYPE)  std::is_floating_point_v<TYPE>

#define SIMD_OP_IMPL(OP)                                                                           \
    using Scalar = typename typetraits::TypeInfo<T>::Scalar;                                       \
    if constexpr (IS_FLOATING(Scalar)) {                                                           \
        return xsimd::OP(x);                                                                       \
    } else {                                                                                       \
        T result;                                                                                  \
        constexpr uint64_t packetWidth = typetraits::TypeInfo<Scalar>::packetWidth;                \
        for (size_t i = 0; i < packetWidth; ++i) { result.set(i, std::OP(x.get(i))); }             \
        return result;                                                                             \
    }

    template<typename T>
        requires(typetraits::SIMD<T>)
    LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto sin(const T &x) {
        SIMD_OP_IMPL(sin)
    }

    template<typename T>
        requires(typetraits::SIMD<T>)
    LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto cos(const T &x) {
        SIMD_OP_IMPL(cos)
    }

    template<typename T>
        requires(typetraits::SIMD<T>)
    LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto tan(const T &x) {
        SIMD_OP_IMPL(tan)
    }

    template<typename T>
        requires(typetraits::SIMD<T>)
    LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto asin(const T &x) {
        SIMD_OP_IMPL(asin)
    }

    template<typename T>
        requires(typetraits::SIMD<T>)
    LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto acos(const T &x) {
        SIMD_OP_IMPL(acos)
    }

    template<typename T>
        requires(typetraits::SIMD<T>)
    LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto atan(const T &x) {
        SIMD_OP_IMPL(atan)
    }

    template<typename T>
        requires(typetraits::SIMD<T>)
    LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto sinh(const T &x) {
        SIMD_OP_IMPL(sinh)
    }

    template<typename T>
        requires(typetraits::SIMD<T>)
    LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto cosh(const T &x) {
        SIMD_OP_IMPL(cosh)
    }

    template<typename T>
        requires(typetraits::SIMD<T>)
    LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto tanh(const T &x) {
        SIMD_OP_IMPL(tanh)
    }

    template<typename T>
        requires(typetraits::SIMD<T>)
    LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto exp(const T &x) {
        SIMD_OP_IMPL(exp)
    }

    template<typename T>
        requires(typetraits::SIMD<T>)
    LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto log(const T &x) {
        SIMD_OP_IMPL(log)
    }

    template<typename T>
        requires(typetraits::SIMD<T>)
    LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto log2(const T &x) {
        SIMD_OP_IMPL(log2)
    }

    template<typename T>
        requires(typetraits::SIMD<T>)
    LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto log10(const T &x) {
        SIMD_OP_IMPL(log10)
    }

    template<typename T>
        requires(typetraits::SIMD<T>)
    LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto sqrt(const T &x) {
        SIMD_OP_IMPL(sqrt)
    }

    template<typename T>
        requires(typetraits::SIMD<T>)
    LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto cbrt(const T &x) {
        SIMD_OP_IMPL(cbrt)
    }

    template<typename T>
        requires(typetraits::SIMD<T>)
    LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto abs(const T &x) {
        SIMD_OP_IMPL(abs)
    }

    template<typename T>
        requires(typetraits::SIMD<T>)
    LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto floor(const T &x) {
        SIMD_OP_IMPL(floor)
    }

    template<typename T>
        requires(typetraits::SIMD<T>)
    LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto ceil(const T &x) {
        SIMD_OP_IMPL(ceil)
    }
} // namespace librapid

#endif // LIBRAPID_SIMD_TRIGONOMETRY