7#ifndef PXR_BASE_GF_NUMERIC_CAST_H
8#define PXR_BASE_GF_NUMERIC_CAST_H
12#include "pxr/base/gf/traits.h"
19PXR_NAMESPACE_OPEN_SCOPE
28template <
class T,
class U>
30GfIntegerCompareLess(T t, U u)
noexcept
32 static_assert(std::is_integral_v<T> && std::is_integral_v<U>);
34 if constexpr (std::is_signed_v<T> == std::is_signed_v<U>) {
37 else if constexpr (std::is_signed_v<T>) {
38 return t < 0 || std::make_unsigned_t<T>(t) < u;
41 return u >= 0 && t < std::make_unsigned_t<U>(u);
45enum GfNumericCastFailureType {
46 GfNumericCastPosOverflow,
47 GfNumericCastNegOverflow,
73template <
class To,
class From>
75GfNumericCast(From from, GfNumericCastFailureType *failType =
nullptr)
80 using FromLimits = std::numeric_limits<From>;
81 using ToLimits = std::numeric_limits<To>;
83 auto setFail = [&failType](GfNumericCastFailureType ft) {
90 if constexpr (std::is_integral_v<From> &&
91 std::is_integral_v<To>) {
93 if (GfIntegerCompareLess(from, ToLimits::min())) {
94 setFail(GfNumericCastNegOverflow);
97 if (GfIntegerCompareLess(ToLimits::max(), from)) {
98 setFail(GfNumericCastPosOverflow);
102 return static_cast<To
>(from);
106 std::is_integral_v<To>) {
108 if (std::isnan(from)) {
109 setFail(GfNumericCastNaN);
113 if (std::isinf(from)) {
114 setFail(std::signbit(
static_cast<double>(from))
115 ? GfNumericCastNegOverflow
116 : GfNumericCastPosOverflow);
126 From low =
static_cast<From
>(ToLimits::lowest()) -
static_cast<From
>(1);
127 From high =
static_cast<From
>(ToLimits::max()) +
static_cast<From
>(1);
130 setFail(GfNumericCastNegOverflow);
134 setFail(GfNumericCastPosOverflow);
138 return static_cast<To
>(from);
145 return static_cast<To
>(from);
149PXR_NAMESPACE_CLOSE_SCOPE
A metafunction which is equivalent to std::arithmetic but also includes any specializations from GfIs...
A metafunction which is equivalent to std::is_floating_point but allows for additional specialization...