38#if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
43#if !defined(ITK_FUTURE_LEGACY_REMOVE)
45# include <vnl/vnl_math.h>
55inline constexpr double e = 2.71828182845904523536;
57inline constexpr double log2e = 1.44269504088896340736;
59inline constexpr double log10e = 0.43429448190325182765;
61inline constexpr double ln2 = 0.69314718055994530942;
63inline constexpr double ln10 = 2.30258509299404568402;
65inline constexpr double pi = 3.14159265358979323846;
67inline constexpr double twopi = 6.28318530717958647693;
69inline constexpr double pi_over_2 = 1.57079632679489661923;
71inline constexpr double pi_over_4 = 0.78539816339744830962;
81inline constexpr double sqrt2pi = 2.50662827463100050242;
87inline constexpr double sqrt2 = 1.41421356237309504880;
89inline constexpr double sqrt1_2 = 0.70710678118654752440;
91inline constexpr double sqrt1_3 = 0.57735026918962576451;
93inline constexpr double euler = 0.57721566490153286061;
95#if defined(__cpp_lib_math_constants)
98static_assert(
e == std::numbers::e);
99static_assert(
log2e == std::numbers::log2e);
100static_assert(
log10e == std::numbers::log10e);
101static_assert(
ln2 == std::numbers::ln2);
102static_assert(
ln10 == std::numbers::ln10);
103static_assert(
pi == std::numbers::pi);
104static_assert(
twopi == 2 * std::numbers::pi);
105static_assert(
pi_over_2 == std::numbers::pi / 2);
106static_assert(
pi_over_4 == std::numbers::pi / 4);
107static_assert(
pi_over_180 == std::numbers::pi / 180);
109static_assert(
two_over_pi == 2 * std::numbers::inv_pi);
110static_assert(
deg_per_rad == 180 * std::numbers::inv_pi);
112static_assert(
sqrt2 == std::numbers::sqrt2);
113static_assert(
sqrt1_2 == std::numbers::sqrt2 / 2);
114static_assert(
sqrt1_3 == std::numbers::inv_sqrt3);
115static_assert(
euler == std::numbers::egamma);
119inline constexpr double eps = std::numeric_limits<double>::epsilon();
124inline constexpr float float_eps = std::numeric_limits<float>::epsilon();
130#define itkTemplateFloatingToIntegerMacro(name) \
131 template <typename TReturn, typename TInput> \
132 inline constexpr auto name(TInput x) \
134 if constexpr (sizeof(TReturn) <= 4) \
136 return static_cast<TReturn>(Detail::name##_32(x)); \
138 else if constexpr (sizeof(TReturn) <= 8) \
140 return static_cast<TReturn>(Detail::name##_64(x)); \
144 return static_cast<TReturn>(Detail::name##_base<TReturn, TInput>(x)); \
200template <typename TReturn, typename TInput>
233#undef itkTemplateFloatingToIntegerMacro
235template <
typename TReturn,
typename TInput>
242 auto ret =
static_cast<TReturn
>(x);
243 if constexpr (
sizeof(TReturn) >
sizeof(TInput) &&
250 else if constexpr (
sizeof(TReturn) >=
sizeof(TInput))
258 else if (
static_cast<TInput
>(ret) != x ||
296 return representOutput.
asFloat;
339 const T absDifference = std::abs(x1 - x2);
340 if (absDifference <= maxAbsoluteDifference)
349 if (std::signbit(x1) != std::signbit(x2))
355 return ulps <= maxUlps;
369 template <
typename TFloatType1,
typename TFloatType2>
376 template <
typename TFloatType1,
typename TFloatType2>
383 template <
typename TFloatType1,
typename TFloatType2>
390 template <
typename TFloatType1,
typename TFloatType2>
397 template <
typename TFloatType1,
typename TFloatType2>
407 template <
typename TFloatType,
typename TIntType>
417 template <
typename TIntType,
typename TFloatType>
427 template <
typename TSignedInt,
typename TUn
signedInt>
431 if (signedVariable < 0)
439 return signedVariable ==
static_cast<TSignedInt
>(unsignedVariable);
445 template <
typename TUn
signedInt,
typename TSignedInt>
455 template <
typename TIntegerType1,
typename TIntegerType2>
466template <
bool TInput1IsIntger,
bool TInput1IsSigned,
bool TInput2IsInteger,
bool TInput2IsSigned>
481struct AlmostEqualsFunctionSelector<false, true, true, true>
488struct AlmostEqualsFunctionSelector<false, true, true, false>
495struct AlmostEqualsFunctionSelector<true, false, false, true>
538template <
typename TInputType1,
typename TInputType2>
539struct AlmostEqualsScalarImplementer
541 static constexpr bool TInputType1IsInteger = std::is_integral_v<TInputType1>;
542 static constexpr bool TInputType1IsSigned = std::is_signed_v<TInputType1>;
543 static constexpr bool TInputType2IsInteger = std::is_integral_v<TInputType2>;
544 static constexpr bool TInputType2IsSigned = std::is_signed_v<TInputType2>;
546 using SelectedVersion =
typename AlmostEqualsFunctionSelector<TInputType1IsInteger,
548 TInputType2IsInteger,
549 TInputType2IsSigned>::SelectedVersion;
555template <
typename TScalarType1,
typename TScalarType2>
557AlmostEqualsScalarComparer(TScalarType1 x1, TScalarType2 x2)
559 return AlmostEqualsScalarImplementer<TScalarType1, TScalarType2>::SelectedVersion::
560 template AlmostEqualsFunction<TScalarType1, TScalarType2>(x1, x2);
567struct AlmostEqualsScalarVsScalar
569 template <
typename TScalarType1,
typename TScalarType2>
571 AlmostEqualsFunction(TScalarType1 x1, TScalarType2 x2)
573 return AlmostEqualsScalarComparer(x1, x2);
579struct AlmostEqualsComplexVsComplex
581 template <
typename TComplexType1,
typename TComplexType2>
583 AlmostEqualsFunction(TComplexType1 x1, TComplexType2 x2)
585 return AlmostEqualsScalarComparer(x1.real(), x2.real()) && AlmostEqualsScalarComparer(x1.imag(), x2.imag());
592struct AlmostEqualsScalarVsComplex
594 template <
typename TScalarType,
typename TComplexType>
596 AlmostEqualsFunction(TScalarType scalarVariable, TComplexType complexVariable)
602 return AlmostEqualsScalarComparer(scalarVariable, complexVariable.real());
606struct AlmostEqualsComplexVsScalar
608 template <
typename TComplexType,
typename TScalarType>
610 AlmostEqualsFunction(TComplexType complexVariable, TScalarType scalarVariable)
612 return AlmostEqualsScalarVsComplex::AlmostEqualsFunction(scalarVariable, complexVariable);
619template <
bool T1IsComplex,
bool T2IsComplex>
620struct AlmostEqualsComplexChooser
622 using ChosenVersion = AlmostEqualsScalarVsScalar;
626struct AlmostEqualsComplexChooser<true, true>
628 using ChosenVersion = AlmostEqualsComplexVsComplex;
632struct AlmostEqualsComplexChooser<false, true>
634 using ChosenVersion = AlmostEqualsScalarVsComplex;
638struct AlmostEqualsComplexChooser<true, false>
640 using ChosenVersion = AlmostEqualsComplexVsScalar;
648template <
typename T1,
typename T2>
649struct AlmostEqualsComplexImplementer
651 static constexpr bool T1IsComplex = NumericTraits<T1>::IsComplex;
652 static constexpr bool T2IsComplex = NumericTraits<T2>::IsComplex;
654 using ChosenVersion =
typename AlmostEqualsComplexChooser<T1IsComplex, T2IsComplex>::ChosenVersion;
703template <
typename T1,
typename T2>
707 return Detail::AlmostEqualsComplexImplementer<T1, T2>::ChosenVersion::AlmostEqualsFunction(x1, x2);
711template <
typename T1,
typename T2>
741template <
typename TInput1,
typename TInput2>
746 ITK_GCC_SUPPRESS_Wfloat_equal
752template <
typename TInput1,
typename TInput2>
765template <
typename T,
typename = std::enable_if_t<std::is_
integral_v<T>>>
776 if (n == 2 || n == 3)
780 if (n % 2 == 0 || n % 3 == 0)
785 for (T x = 5; x <= n / x; x += 6)
787 if (n % x == 0 || n % (x + 2) == 0)
798template <
typename T,
typename = std::enable_if_t<std::is_
integral_v<T>>>
821template <
typename TReturnType = u
intmax_t>
825 static_assert(std::is_unsigned_v<TReturnType>,
"UnsignedProduct only supports unsigned return types");
829 return (a == 0) || (b == 0) ||
830 (((
static_cast<TReturnType
>(a * b) / a) == b) && ((
static_cast<TReturnType
>(a * b) / b) == a))
831 ?
static_cast<TReturnType
>(a * b)
832 : (assert(!
"UnsignedProduct overflow!"), 0);
843template <
typename TReturnType = u
intmax_t>
845UnsignedPower(
const uintmax_t base,
const uintmax_t exponent)
noexcept -> TReturnType
847 static_assert(std::is_unsigned_v<TReturnType>,
"UnsignedPower only supports unsigned return types");
851 return (exponent == 0) ? (assert(base > 0), 1)
852 : (exponent == 1) ? base
870template <
typename T, std::enable_if_t<std::is_arithmetic_v<T>,
int> = 0>
874 return (x != T{}) ? ((x > T{}) ? 1 : -1) : 0;
878template <
typename T, std::enable_if_t<std::is_arithmetic_v<T>,
int> = 0>
882 return (x >= T{}) ? 1 : -1;
891template <
typename T, std::enable_if_t<std::is_arithmetic_v<T>,
int> = 0>
904template <
typename T, std::enable_if_t<std::is_arithmetic_v<T>,
int> = 0>
912constexpr unsigned int
915 return static_cast<unsigned int>(
static_cast<int>(x) *
static_cast<int>(x));
917constexpr unsigned int
920 return static_cast<unsigned int>(
static_cast<int>(x) *
static_cast<int>(x));
922constexpr unsigned int
926 const auto ux =
static_cast<unsigned int>(x);
929constexpr unsigned int
934constexpr unsigned long
937 const auto ux =
static_cast<unsigned long>(x);
940constexpr unsigned long
945constexpr unsigned long long
948 const auto ux =
static_cast<unsigned long long>(x);
951constexpr unsigned long long
973template <
typename T, std::enable_if_t<std::is_
integral_v<T>,
int> = 0>
982 return std::fmod(x, y);
987 return std::fmod(x, y);
992 return std::fmod(x, y);
996template <
typename T, std::enable_if_t<std::is_
integral_v<T> && std::is_
signed_v<T>,
int> = 0>
1002 return (r != 0 && ((r < 0) != (y < 0))) ? r + y : r;
1004template <
typename T, std::enable_if_t<std::is_
integral_v<T> && std::is_
unsigned_v<T>,
int> = 0>
1013 return std::fmod(std::fmod(x, y) + y, y);
1018 return std::fmod(std::fmod(x, y) + y, y);
1023 return std::fmod(std::fmod(x, y) + y, y);
1030 return static_cast<int>(std::lrint(x));
1035 return static_cast<int>(std::lrint(x));
1055 return static_cast<int>(std::lrint(x));
1060 return static_cast<int>(std::lrint(x));
1067 return static_cast<int>(std::floor(x));
1072 return static_cast<int>(std::floor(x));
1079 return static_cast<int>(std::ceil(x));
1084 return static_cast<int>(std::ceil(x));
1091 angle = std::fmod(angle,
twopi);
1094 const double a = angle +
twopi;
1096 return (a <
twopi) ? a : 6.28318530717958575;
1103 angle = std::fmod(angle,
twopi);
1132template <
typename T>
1136 if constexpr (std::is_same_v<T, bool>)
1141 else if constexpr (std::is_integral_v<T>)
1143 if constexpr (std::is_signed_v<T>)
1145 using UnsignedType = std::make_unsigned_t<T>;
1146 using Limits = std::numeric_limits<T>;
1149 constexpr UnsignedType absoluteValueOfMin{ UnsignedType{ Limits::max() } + UnsignedType{ 1 } };
1151 return static_cast<UnsignedType
>((x < 0) ? (x == Limits::min()) ? absoluteValueOfMin : -x : x);
1167 else if constexpr (std::is_floating_point_v<T>)
1174template <
typename T>
1179 return std::abs<T>(x);
1182#if !defined(ITK_FUTURE_LEGACY_REMOVE)
1186template <
typename T>
Define additional traits for native types such as int or float.
static constexpr T max(const T &)
static bool IsPositive(T val)
#define itkConceptMacro(name, concept)
#define itkTemplateFloatingToIntegerMacro(name)
RoundHalfIntegerToEven(TInput x) template< TReturn
Round towards nearest integer.
constexpr int sgn0(T x)
Sign of a value in {-1, +1}; zero maps to +1.
int ceil(float x)
Round toward plus infinity.
constexpr bool cube(bool x)
Cube of a value.
constexpr T GreatestPrimeFactor(T n)
bool AlmostEquals(T1 x1, T2 x2)
Provide consistent equality checks between values of potentially different scalar or complex types.
constexpr T remainder_floored(T x, T y)
Floored remainder: quotient rounded toward minus infinity, result has the sign of y.
constexpr auto UnsignedPower(const uintmax_t base, const uintmax_t exponent) noexcept -> TReturnType
constexpr auto Absolute(T x) noexcept
Returns the absolute value of a number.
double angle_0_to_2pi(double angle)
Normalize an angle (radians) into [0, 2*pi).
TInput TInput auto CastWithRangeCheck(TInput x)
int floor(float x)
Round toward minus infinity.
bool NotAlmostEquals(T1 x1, T2 x2)
TInput Ceil(TInput x) template< typename TReturn
constexpr double pi_over_2
constexpr bool IsPrime(T n)
constexpr bool sqr(bool x)
Square of a value.
int rnd_halfintup(float x)
Round to nearest integer, halfway cases upward (toward plus infinity). Valid only for |x| < INT_MAX /...
constexpr double one_over_sqrt2pi
double angle_minuspi_to_pi(double angle)
Normalize an angle (radians) into (-pi, pi].
constexpr double pi_over_4
TInput RoundHalfIntegerUp(TInput x) template< typename TReturn
Round towards nearest integer (This is a synonym for RoundHalfIntegerUp)
int rnd(float x)
Round to nearest integer; halfway cases follow round-half-to-even.
constexpr bool ExactlyEquals(const TInput1 &x1, const TInput2 &x2)
Return the result of an exact comparison between two scalar values of potentially different types.
constexpr unsigned int squared_magnitude(char x)
Squared magnitude; integer results are unsigned.
constexpr double two_over_sqrtpi
constexpr double one_over_pi
constexpr int sgn(T x)
Sign of a value: -1, 0, or +1.
constexpr auto UnsignedProduct(const uintmax_t a, const uintmax_t b) noexcept
int rnd_halfinttoeven(float x)
Round to nearest integer, halfway cases to the nearest even integer.
Floor(TInput x) template< TReturn
Round towards minus infinity.
constexpr double euler
euler constant
TInput TInput constexpr auto Round(TInput x)
constexpr float float_sqrteps
constexpr float float_eps
constexpr bool NotExactlyEquals(const TInput1 &x1, const TInput2 &x2)
bool FloatAlmostEqual(T x1, T x2, typename Detail::FloatIEEE< T >::IntType maxUlps=4, typename Detail::FloatIEEE< T >::FloatType maxAbsoluteDifference=0.1 *itk::NumericTraits< T >::epsilon())
Compare two floats and return if they are effectively equal.
constexpr double deg_per_rad
constexpr double two_over_pi
constexpr double pi_over_180
constexpr Detail::FloatIEEE< T >::IntType FloatDifferenceULP(T x1, T x2)
Return the signed distance in ULPs (units in the last place) between two floats.
constexpr T remainder_truncated(T x, T y)
Truncated remainder: quotient truncated toward zero, result has the sign of x.
constexpr T FloatAddULP(T x, typename Detail::FloatIEEE< T >::IntType ulps)
Add the given ULPs (units in the last place) to a float.
static bool AlmostEqualsFunction(double x1, double x2)
static bool AlmostEqualsFunction(float x1, double x2)
static bool AlmostEqualsFunction(TFloatType1 x1, TFloatType2 x2)
static bool AlmostEqualsFunction(double x1, float x2)
static bool AlmostEqualsFunction(float x1, float x2)
static bool AlmostEqualsFunction(TFloatType floatingVariable, TIntType integerVariable)
AlmostEqualsPlainOldEquals SelectedVersion
static bool AlmostEqualsFunction(TIntType integerVariable, TFloatType floatingVariable)
static bool AlmostEqualsFunction(TIntegerType1 x1, TIntegerType2 x2)
static bool AlmostEqualsFunction(TSignedInt signedVariable, TUnsignedInt unsignedVariable)
static bool AlmostEqualsFunction(TUnsignedInt unsignedVariable, TSignedInt signedVariable)
constexpr IntType AsULP() const
typename FloatIEEETraits< T >::IntType IntType