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