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
37#if defined(ARCH_COMPILER_MSVC)
39 ARCH_PRAGMA(warning(disable:4018))
40 ARCH_PRAGMA(warning(disable:4804))
43 static_assert(std::is_integral_v<T> && std::is_integral_v<U>);
45 if constexpr (std::is_signed_v<T> == std::is_signed_v<U>) {
48 else if constexpr (std::is_signed_v<T>) {
49 return t < 0 || std::make_unsigned_t<T>(t) < u;
52 return u >= 0 && t < std::make_unsigned_t<U>(u);
55#if defined(ARCH_COMPILER_MSVC)
60enum GfNumericCastFailureType {
61 GfNumericCastPosOverflow,
62 GfNumericCastNegOverflow,
88template <
class To,
class From>
90GfNumericCast(From from, GfNumericCastFailureType *failType =
nullptr)
95 using FromLimits = std::numeric_limits<From>;
96 using ToLimits = std::numeric_limits<To>;
98 auto setFail = [&failType](GfNumericCastFailureType ft) {
105 if constexpr (std::is_integral_v<From> &&
106 std::is_integral_v<To>) {
108 if (GfIntegerCompareLess(from, ToLimits::min())) {
109 setFail(GfNumericCastNegOverflow);
112 if (GfIntegerCompareLess(ToLimits::max(), from)) {
113 setFail(GfNumericCastPosOverflow);
117 return static_cast<To
>(from);
121 std::is_integral_v<To>) {
123 if (std::isnan(from)) {
124 setFail(GfNumericCastNaN);
128 if (std::isinf(from)) {
129 setFail(std::signbit(
static_cast<double>(from))
130 ? GfNumericCastNegOverflow
131 : GfNumericCastPosOverflow);
141 From low =
static_cast<From
>(ToLimits::lowest()) -
static_cast<From
>(1);
142 From high =
static_cast<From
>(ToLimits::max()) +
static_cast<From
>(1);
145 setFail(GfNumericCastNegOverflow);
149 setFail(GfNumericCastPosOverflow);
153 return static_cast<To
>(from);
160 return static_cast<To
>(from);
164PXR_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...