14#include <lagrange/Logger.h>
15#include <lagrange/utils/Error.h>
16#include <lagrange/utils/warning.h>
49template <
typename TargetType,
typename SourceType>
51 -> std::enable_if_t<!std::is_same<SourceType, TargetType>::value, TargetType>
53 if constexpr (std::is_integral_v<TargetType> && std::is_floating_point_v<SourceType>) {
54 SourceType float_max = std::nextafter(
55 static_cast<SourceType
>(std::numeric_limits<TargetType>::max()),
57 SourceType float_min = std::nextafter(
58 static_cast<SourceType
>(std::numeric_limits<TargetType>::min()),
60 if (value > float_max || value < float_min) {
61 logger().error(
"Casting failed: float cast overflow for float {}", value);
66 TargetType value_2 =
static_cast<TargetType
>(value);
68 if constexpr (std::is_integral_v<SourceType> && std::is_floating_point_v<TargetType>) {
69 TargetType float_max = std::nextafter(
70 static_cast<TargetType
>(std::numeric_limits<SourceType>::max()),
72 TargetType float_min = std::nextafter(
73 static_cast<TargetType
>(std::numeric_limits<SourceType>::min()),
75 if (value_2 > float_max || value_2 < float_min) {
76 logger().error(
"Casting failed: float cast overflow for integer {}", value);
81 SourceType value_3 =
static_cast<SourceType
>(value_2);
83 if ((value_2 >= 0) != (value >= 0)) {
85 logger().error(
"Casting failed: from {} to {} causes a sign change...", value, value_2);
87 }
else if (value_3 == value) {
92 constexpr SourceType EPS =
93 static_cast<SourceType
>(std::numeric_limits<TargetType>::epsilon());
97 LA_DISABLE_WARNING_BEGIN
98 LA_DISABLE_WARNING_MSVC(4146)
99 const SourceType value_abs = value_3 > 0 ? value_3 : -value_3;
100 LA_DISABLE_WARNING_END
102 const SourceType scaled_eps = value_abs >= SourceType(1) ? EPS * value_abs : EPS;
103 if (value_3 > value && value_3 < value + scaled_eps) {
105 }
else if (value_3 < value && value_3 + scaled_eps > value) {
110 "Casting failed: from {} to {} will incur error ({}) larger than {}",
113 value -
static_cast<SourceType
>(value_2),
144template <
typename TargetType>
148 return static_cast<TargetType
>(value);
162template <
typename T,
typename U>
166 std::is_enum_v<T> || std::is_enum_v<U>,
167 "At least one of the types should be an enum");
169 (std::is_enum_v<T> && std::is_enum_v<U>) == std::is_same_v<T, U>,
170 "Casting one enum to another is prohibited");
172 using underlying_t = std::underlying_type_t<std::conditional_t<std::is_enum_v<T>, T, U>>;
173 using enum_t = std::conditional_t<std::is_enum_v<T>, T, U>;
174 using other_t = std::conditional_t<std::is_enum_v<T>, U, T>;
176 if constexpr (std::is_enum_v<T>) {
177 return static_cast<enum_t
>(safe_cast<underlying_t>(u));
179 return safe_cast<other_t>(
static_cast<underlying_t
>(u));
LA_CORE_API spdlog::logger & logger()
Retrieves the current logger.
Definition: Logger.cpp:40
constexpr T safe_cast_enum(const U u)
Casting an enum to scalar and vice versa.
Definition: safe_cast.h:163
constexpr auto safe_cast(SourceType value) -> std::enable_if_t<!std::is_same< SourceType, TargetType >::value, TargetType >
Perform safe cast from SourceType to TargetType, where "safe" means:
Definition: safe_cast.h:50
Main namespace for Lagrange.
Definition: AABBIGL.h:30
An exception of this type is thrown when a lagrange::safe_cast<> fails.
Definition: Error.h:37