7#ifndef PXR_BASE_GF_NUMERIC_CAST_H
8#define PXR_BASE_GF_NUMERIC_CAST_H
12#include "pxr/base/gf/traits.h"
20PXR_NAMESPACE_OPEN_SCOPE
29template <
class T,
class U>
31GfIntegerCompareLess(T t, U u)
noexcept
33 static_assert(std::is_integral_v<T> && !std::is_same_v<T, bool> &&
34 std::is_integral_v<U> && !std::is_same_v<U, bool>);
36 if constexpr (std::is_signed_v<T> == std::is_signed_v<U>) {
39 else if constexpr (std::is_signed_v<T>) {
40 return t < 0 || std::make_unsigned_t<T>(t) < u;
43 return u >= 0 && t < std::make_unsigned_t<U>(u);
47enum GfNumericCastFailureType {
48 GfNumericCastPosOverflow,
49 GfNumericCastNegOverflow,
82template <
class To,
class From>
84GfNumericCast(From from, GfNumericCastFailureType *failType =
nullptr)
91#if defined(ARCH_COMPILER_MSVC)
93 ARCH_PRAGMA(warning(disable:4756))
99 using FromLimits = std::numeric_limits<From>;
100 using ToLimits = std::numeric_limits<To>;
102 auto setFail = [&failType](GfNumericCastFailureType ft) {
109 if constexpr (std::is_same_v<From, bool> ||
110 std::is_same_v<To, bool>) {
115 return static_cast<To
>(from);
118 else if constexpr (std::is_integral_v<From> &&
119 std::is_integral_v<To>) {
121 if (GfIntegerCompareLess(from, ToLimits::min())) {
122 setFail(GfNumericCastNegOverflow);
125 if (GfIntegerCompareLess(ToLimits::max(), from)) {
126 setFail(GfNumericCastPosOverflow);
130 return static_cast<To
>(from);
134 std::is_integral_v<To>) {
136 if (std::isnan(from)) {
137 setFail(GfNumericCastNaN);
141 if (std::isinf(from)) {
142 setFail(std::signbit(
static_cast<double>(from))
143 ? GfNumericCastNegOverflow
144 : GfNumericCastPosOverflow);
154 From low =
static_cast<From
>(ToLimits::lowest()) -
static_cast<From
>(1);
155 From high =
static_cast<From
>(ToLimits::max()) +
static_cast<From
>(1);
158 setFail(GfNumericCastNegOverflow);
162 setFail(GfNumericCastPosOverflow);
166 return static_cast<To
>(from);
173 return static_cast<To
>(from);
176#if defined(ARCH_COMPILER_MSVC)
181PXR_NAMESPACE_CLOSE_SCOPE
Pragmas for controlling compiler-specific behaviors.
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...