aboutsummaryrefslogtreecommitdiff
path: root/base/include/berberis/base/bit_util.h
diff options
context:
space:
mode:
Diffstat (limited to 'base/include/berberis/base/bit_util.h')
-rw-r--r--base/include/berberis/base/bit_util.h110
1 files changed, 107 insertions, 3 deletions
diff --git a/base/include/berberis/base/bit_util.h b/base/include/berberis/base/bit_util.h
index ddf4f91c..b3d287ea 100644
--- a/base/include/berberis/base/bit_util.h
+++ b/base/include/berberis/base/bit_util.h
@@ -271,6 +271,9 @@ class WrappedFloatType;
} // namespace intrinsics
+template <typename T>
+struct TypeTraits;
+
// Raw integers. Used to carry payload, which may be be EXPLICITLY converted to Saturating
// integer, Wrapping integer, or WrappedFloatType.
//
@@ -697,6 +700,12 @@ using UInt128 = Wrapping<unsigned __int128>;
#endif
template <typename IntType>
+[[nodiscard]] auto constexpr BitCastToSigned(Raw<IntType> src) ->
+ typename Wrapping<IntType>::SignedType {
+ return {static_cast<std::make_signed_t<IntType>>(src.value)};
+}
+
+template <typename IntType>
[[nodiscard]] auto constexpr BitCastToSigned(Saturating<IntType> src) ->
typename Saturating<IntType>::SignedType {
return {static_cast<std::make_signed_t<IntType>>(src.value)};
@@ -712,6 +721,12 @@ template <typename T>
using SignedType = decltype(BitCastToSigned(std::declval<T>()));
template <typename IntType>
+[[nodiscard]] auto constexpr BitCastToUnsigned(Raw<IntType> src) ->
+ typename Wrapping<IntType>::UnsignedType {
+ return {static_cast<std::make_unsigned_t<IntType>>(src.value)};
+}
+
+template <typename IntType>
[[nodiscard]] auto constexpr BitCastToUnsigned(Saturating<IntType> src) ->
typename Saturating<IntType>::UnsignedType {
return {static_cast<std::make_unsigned_t<IntType>>(src.value)};
@@ -726,6 +741,86 @@ template <typename IntType>
template <typename T>
using UnsignedType = decltype(BitCastToUnsigned(std::declval<T>()));
+template <typename IntType>
+[[nodiscard]] auto constexpr BitCastToSaturating(Saturating<IntType> src) -> Saturating<IntType> {
+ return src;
+}
+
+template <typename IntType>
+[[nodiscard]] auto constexpr BitCastToSaturating(Wrapping<IntType> src) -> Saturating<IntType> {
+ return {src.value};
+}
+
+template <typename T>
+using SaturatingType = decltype(BitCastToSaturating(std::declval<T>()));
+
+template <typename IntType>
+[[nodiscard]] auto constexpr BitCastToWrapping(Saturating<IntType> src) -> Wrapping<IntType> {
+ return {src.value};
+}
+
+template <typename IntType>
+[[nodiscard]] auto constexpr BitCastToWrapping(Wrapping<IntType> src) -> Wrapping<IntType> {
+ return src;
+}
+
+template <typename T>
+using WrappingType = decltype(BitCastToWrapping(std::declval<T>()));
+
+template <typename IntType>
+[[nodiscard]] auto constexpr BitCastToRaw(Raw<IntType> src) -> Raw<IntType> {
+ return src;
+}
+
+template <typename IntType>
+[[nodiscard]] auto constexpr BitCastToRaw(Saturating<IntType> src)
+ -> Raw<std::make_unsigned_t<IntType>> {
+ return {static_cast<std::make_unsigned_t<IntType>>(src.value)};
+}
+
+template <typename IntType>
+[[nodiscard]] auto constexpr BitCastToRaw(Wrapping<IntType> src)
+ -> Raw<std::make_unsigned_t<IntType>> {
+ return {static_cast<std::make_unsigned_t<IntType>>(src.value)};
+}
+
+template <typename BaseType>
+[[nodiscard]] constexpr auto BitCastToRaw(intrinsics::WrappedFloatType<BaseType> src)
+ -> Raw<std::make_unsigned_t<typename TypeTraits<intrinsics::WrappedFloatType<BaseType>>::Int>> {
+ return {bit_cast<
+ std::make_unsigned_t<typename TypeTraits<intrinsics::WrappedFloatType<BaseType>>::Int>>(src)};
+}
+
+template <typename T>
+using RawType = decltype(BitCastToRaw(std::declval<T>()));
+
+template <typename IntType>
+[[nodiscard]] auto constexpr BitCastToFloat(Raw<IntType> src) ->
+ typename TypeTraits<IntType>::Float {
+ return bit_cast<typename TypeTraits<IntType>::Float>(src.value);
+}
+
+template <typename IntType>
+[[nodiscard]] auto constexpr BitCastToFloat(Saturating<IntType> src) ->
+ typename TypeTraits<IntType>::Float {
+ return bit_cast<typename TypeTraits<IntType>::Float>(src.value);
+}
+
+template <typename IntType>
+[[nodiscard]] auto constexpr BitCastToFloat(Wrapping<IntType> src) ->
+ typename TypeTraits<IntType>::Float {
+ return bit_cast<typename TypeTraits<IntType>::Float>(src.value);
+}
+
+template <typename BaseType>
+[[nodiscard]] constexpr auto BitCastToFloat(intrinsics::WrappedFloatType<BaseType> src)
+ -> intrinsics::WrappedFloatType<BaseType> {
+ return src;
+}
+
+template <typename T>
+using FloatType = decltype(BitCastToFloat(std::declval<T>()));
+
template <typename ResultType, typename IntType>
[[nodiscard]] auto constexpr MaybeTruncateTo(IntType src)
-> std::enable_if_t<std::is_integral_v<IntType> &&
@@ -774,9 +869,6 @@ template <typename ResultType, typename IntType>
return ResultType{static_cast<ResultType::BaseType>(src.value)};
}
-template <typename T>
-struct TypeTraits;
-
template <typename BaseType>
[[nodiscard]] constexpr auto Widen(Saturating<BaseType> source)
-> Saturating<typename TypeTraits<BaseType>::Wide> {
@@ -789,6 +881,12 @@ template <typename BaseType>
return {source.value};
}
+template <typename BaseType>
+[[nodiscard]] constexpr auto Widen(intrinsics::WrappedFloatType<BaseType> source)
+ -> Wrapping<typename TypeTraits<intrinsics::WrappedFloatType<BaseType>>::Wide> {
+ return {source.value};
+}
+
template <typename T>
using WideType = decltype(Widen(std::declval<T>()));
@@ -812,6 +910,12 @@ template <typename BaseType>
return {static_cast<typename TypeTraits<BaseType>::Narrow>(source.value)};
}
+template <typename BaseType>
+[[nodiscard]] constexpr auto Narrow(intrinsics::WrappedFloatType<BaseType> source)
+ -> Wrapping<typename TypeTraits<intrinsics::WrappedFloatType<BaseType>>::Narrow> {
+ return {source.value};
+}
+
template <typename T>
using NarrowType = decltype(Narrow(std::declval<T>()));