Program Listing for File memUtils.hpp#

Return to documentation for file (librapid/include/librapid/utils/memUtils.hpp)

#ifndef LIBRAPID_UTILS_MEMUTILS_HPP
#define LIBRAPID_UTILS_MEMUTILS_HPP

namespace librapid {
    template<typename To, typename From>
    LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE constexpr To bitCast(const From &val) noexcept {
        static_assert(
          sizeof(To) == sizeof(From),
          "Types have different sizes, and cannot be cast bit-for-bit between each other");

#if defined(__CUDACC__)
        To toOjb; // assumes default-init
        ::std::memcpy(::std::memcpy::addressof(toOjb), ::std::memcpy::addressof(val), sizeof(To));
        return _To_obj;
#elif defined(LIBRAPID_MSVC)
        // MSVC doesn't support std::bit_cast until C++20
        return *(To *)(&val);
#elif defined(LIBRAPID_GCC) || defined(LIBRAPID_CLANG)
#   if __cplusplus > 201703l && __has_builtin(__builtin_bit_cast)
        return __builtin_bit_cast(To, val);
#   else
        // Fallback option
        return *(To *)(&val);
#   endif // __has_builtin(__builtin_bit_cast)
#else
        // Further fallback option
        return *(To *)(&val);
#endif
    }

    template<typename T>
    LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE bool isNaN(const T &val) noexcept {
        return std::isnan(val);
    }

    template<typename T>
    LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE bool isFinite(const T &val) noexcept {
        return std::isfinite(val);
    }

    template<typename T>
    LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE bool isInf(const T &val) noexcept {
        return std::isinf(val);
    }

    template<typename T, typename M>
    LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE T copySign(const T &mag, const M &sign) noexcept {
#if defined(LIBRAPID_MSVC)
        return std::copysign(mag, static_cast<T>(sign));
#else
        if constexpr (std::is_fundamental_v<T> && std::is_fundamental_v<M>) {
            return std::copysign(mag, static_cast<T>(sign));
        } else {
            if (sign < 0) return -mag;
            return mag;
        }
#endif
    }

    template<typename T>
    LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE bool signBit(const T &val) noexcept {
        return signBit((double)val);
    }

    template<>
    LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE bool signBit(const long double &val) noexcept {
        return std::signbit(val);
    }

    template<>
    LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE bool signBit(const double &val) noexcept {
        return std::signbit(val);
    }

    template<>
    LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE bool signBit(const float &val) noexcept {
        return std::signbit(val);
    }

    template<typename T>
    LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE T ldexp(const T &x, const int64_t exp) noexcept {
        return std::ldexp(x, (int)exp);
    }
} // namespace librapid

#endif // LIBRAPID_UTILS_MEMUTILS_HPP