diff --git a/include/ccmath/basic.hpp b/include/ccmath/basic.hpp index 9408790..81ae7a4 100644 --- a/include/ccmath/basic.hpp +++ b/include/ccmath/basic.hpp @@ -14,6 +14,6 @@ #include "ccmath/math/basic/fmod.hpp" #include "ccmath/math/basic/max.hpp" #include "ccmath/math/basic/min.hpp" +#include "ccmath/math/basic/nan.hpp" #include "ccmath/math/basic/remainder.hpp" #include "ccmath/math/basic/remquo.hpp" -#include "ccmath/math/basic/nan.hpp" diff --git a/include/ccmath/math/basic/abs.hpp b/include/ccmath/math/basic/abs.hpp index 6f3bdd4..5ce3c5a 100644 --- a/include/ccmath/math/basic/abs.hpp +++ b/include/ccmath/math/basic/abs.hpp @@ -8,11 +8,11 @@ #pragma once -#include "ccmath/math/compare/isnan.hpp" -#include "ccmath/internal/predef/unlikely.hpp" -#include "ccmath/math/compare/isinf.hpp" #include #include +#include "ccmath/internal/predef/unlikely.hpp" +#include "ccmath/math/compare/isinf.hpp" +#include "ccmath/math/compare/isnan.hpp" namespace ccm { @@ -25,8 +25,8 @@ namespace ccm template && !std::is_unsigned_v, bool> = true> constexpr T abs(T num) noexcept { - // If num is NaN, return a quiet NaN. - if (CCM_UNLIKELY(ccm::isnan(num))) { return std::numeric_limits::quiet_NaN(); } + // If num is NaN, return a quiet NaN. + if (CCM_UNLIKELY(ccm::isnan(num))) { return std::numeric_limits::quiet_NaN(); } // If num is equal to ±zero, return +zero. if (static_cast(0) == num) { return static_cast(0); } @@ -82,16 +82,16 @@ namespace ccm } /** - * @brief Computes the absolute value of a number. - * @tparam Integer Integer type. - * @param x Integer value. - * @return If successful, returns the absolute value of arg (|arg|). The value returned is exact and does not depend on any rounding modes. - */ + * @brief Computes the absolute value of a number. + * @tparam Integer Integer type. + * @param x Integer value. + * @return If successful, returns the absolute value of arg (|arg|). The value returned is exact and does not depend on any rounding modes. + */ template , bool> = true> constexpr double fabs(Integer num) noexcept - { - return abs(static_cast(num)); - } + { + return abs(static_cast(num)); + } /** * @brief Computes the absolute value of a number. @@ -114,24 +114,24 @@ namespace ccm } /** - * @brief Computes the absolute value of a number. - * @param x Integer value. - * @return If successful, returns the absolute value of arg (|arg|). The value returned is exact and does not depend on any rounding modes. - */ + * @brief Computes the absolute value of a number. + * @param x Integer value. + * @return If successful, returns the absolute value of arg (|arg|). The value returned is exact and does not depend on any rounding modes. + */ inline constexpr long labs(long num) noexcept - { - return abs(num); - } + { + return abs(num); + } /** - * @brief Computes the absolute value of a number. - * @param x Integer value. - * @return If successful, returns the absolute value of arg (|arg|). The value returned is exact and does not depend on any rounding modes. - */ + * @brief Computes the absolute value of a number. + * @param x Integer value. + * @return If successful, returns the absolute value of arg (|arg|). The value returned is exact and does not depend on any rounding modes. + */ inline constexpr long long llabs(long long num) noexcept - { - return abs(num); - } + { + return abs(num); + } } // namespace ccm /// @ingroup basic diff --git a/include/ccmath/math/basic/fdim.hpp b/include/ccmath/math/basic/fdim.hpp index af6ab27..db74ddb 100644 --- a/include/ccmath/math/basic/fdim.hpp +++ b/include/ccmath/math/basic/fdim.hpp @@ -8,10 +8,10 @@ #pragma once -#include "ccmath/math/compare/isnan.hpp" -#include "ccmath/internal/predef/unlikely.hpp" #include #include +#include "ccmath/internal/predef/unlikely.hpp" +#include "ccmath/math/compare/isnan.hpp" namespace ccm { @@ -25,8 +25,8 @@ namespace ccm template , int> = 0> inline constexpr T fdim(T x, T y) { - if (CCM_UNLIKELY(ccm::isnan(x))) { return x; } - if (CCM_UNLIKELY(ccm::isnan(y))) { return y; } + if (CCM_UNLIKELY(ccm::isnan(x))) { return x; } + if (CCM_UNLIKELY(ccm::isnan(y))) { return y; } if (x <= y) { return static_cast(+0.0); } if ((y < static_cast(0.0)) && (x > (std::numeric_limits::max() + y))) { return std::numeric_limits::infinity(); } return x - y; diff --git a/include/ccmath/math/basic/fma.hpp b/include/ccmath/math/basic/fma.hpp index e82b40f..ff4397d 100644 --- a/include/ccmath/math/basic/fma.hpp +++ b/include/ccmath/math/basic/fma.hpp @@ -23,7 +23,7 @@ namespace ccm inline constexpr T new_fma(T x, T y, T z) noexcept { if constexpr (std::is_same_v) { return ccm::internal::impl::fma_float_impl(x, y, z); } - else { return ccm::internal::impl::fma_double_impl(x, y, z); } + else { return ccm::internal::impl::fma_double_impl(x, y, z); } } /** @@ -38,16 +38,19 @@ namespace ccm template , bool> = true> inline constexpr T fma(T x, T y, T z) noexcept { - // Handle infinity - if (CCM_UNLIKELY((x == static_cast(0) && ccm::isinf(y)) || (y == T{0} && ccm::isinf(x)))) { return std::numeric_limits::quiet_NaN(); } - if (CCM_UNLIKELY(x * y == std::numeric_limits::infinity() && z == -std::numeric_limits::infinity())) { return std::numeric_limits::infinity(); } - - // Handle NaN - if (CCM_UNLIKELY(ccm::isnan(x) || ccm::isnan(y))) { return std::numeric_limits::quiet_NaN(); } - if (CCM_UNLIKELY(ccm::isnan(z) && (x * y != 0 * std::numeric_limits::infinity() || x * y != std::numeric_limits::infinity() * 0))) - { - return std::numeric_limits::quiet_NaN(); - } + // Handle infinity + if (CCM_UNLIKELY((x == static_cast(0) && ccm::isinf(y)) || (y == T{0} && ccm::isinf(x)))) { return std::numeric_limits::quiet_NaN(); } + if (CCM_UNLIKELY(x * y == std::numeric_limits::infinity() && z == -std::numeric_limits::infinity())) + { + return std::numeric_limits::infinity(); + } + + // Handle NaN + if (CCM_UNLIKELY(ccm::isnan(x) || ccm::isnan(y))) { return std::numeric_limits::quiet_NaN(); } + if (CCM_UNLIKELY(ccm::isnan(z) && (x * y != 0 * std::numeric_limits::infinity() || x * y != std::numeric_limits::infinity() * 0))) + { + return std::numeric_limits::quiet_NaN(); + } // We have to hope the compiler optimizes this. Currently there is no builtin fma that works with static_assert. return (x * y) + z; diff --git a/include/ccmath/math/basic/fmod.hpp b/include/ccmath/math/basic/fmod.hpp index 514ef99..87ce8b8 100644 --- a/include/ccmath/math/basic/fmod.hpp +++ b/include/ccmath/math/basic/fmod.hpp @@ -70,7 +70,7 @@ namespace ccm } } // namespace impl - } // namespace + } // namespace /// @endcond /** diff --git a/include/ccmath/math/basic/impl/fma_double_impl.hpp b/include/ccmath/math/basic/impl/fma_double_impl.hpp index 154d93f..655f632 100644 --- a/include/ccmath/math/basic/impl/fma_double_impl.hpp +++ b/include/ccmath/math/basic/impl/fma_double_impl.hpp @@ -8,10 +8,10 @@ #pragma once -#include "ccmath/internal/predef/unlikely.hpp" -#include "ccmath/internal/support/bits.hpp" #include #include +#include "ccmath/internal/predef/unlikely.hpp" +#include "ccmath/internal/support/bits.hpp" namespace ccm::internal { @@ -20,12 +20,12 @@ namespace ccm::internal namespace impl { inline constexpr double fma_double_impl(double x, double y, double z) noexcept - { + { -//#pragma STDC FENV_ACCESS ON + // #pragma STDC FENV_ACCESS ON return 0; - } + } } // namespace impl } // namespace } // namespace ccm::internal diff --git a/include/ccmath/math/basic/impl/fma_float_impl.hpp b/include/ccmath/math/basic/impl/fma_float_impl.hpp index 0214428..c8005d7 100644 --- a/include/ccmath/math/basic/impl/fma_float_impl.hpp +++ b/include/ccmath/math/basic/impl/fma_float_impl.hpp @@ -1,28 +1,24 @@ /* -* Copyright (c) 2024-Present Ian Pike -* Copyright (c) 2024-Present ccmath contributors -* -* This library is provided under the MIT License. -* See LICENSE for more information. -*/ + * Copyright (c) 2024-Present Ian Pike + * Copyright (c) 2024-Present ccmath contributors + * + * This library is provided under the MIT License. + * See LICENSE for more information. + */ #pragma once namespace ccm::internal { - namespace - { - namespace impl - { - inline constexpr double fma_float_impl(double x, double y, double z) noexcept - { + namespace + { + namespace impl + { + inline constexpr double fma_float_impl(double x, double y, double z) noexcept + { - - - - - return 0; - } - } // namespace impl - } // namespace + return 0; + } + } // namespace impl + } // namespace } // namespace ccm::internal diff --git a/include/ccmath/math/basic/impl/fma_ldouble_impl.hpp b/include/ccmath/math/basic/impl/fma_ldouble_impl.hpp index 154d93f..655f632 100644 --- a/include/ccmath/math/basic/impl/fma_ldouble_impl.hpp +++ b/include/ccmath/math/basic/impl/fma_ldouble_impl.hpp @@ -8,10 +8,10 @@ #pragma once -#include "ccmath/internal/predef/unlikely.hpp" -#include "ccmath/internal/support/bits.hpp" #include #include +#include "ccmath/internal/predef/unlikely.hpp" +#include "ccmath/internal/support/bits.hpp" namespace ccm::internal { @@ -20,12 +20,12 @@ namespace ccm::internal namespace impl { inline constexpr double fma_double_impl(double x, double y, double z) noexcept - { + { -//#pragma STDC FENV_ACCESS ON + // #pragma STDC FENV_ACCESS ON return 0; - } + } } // namespace impl } // namespace } // namespace ccm::internal diff --git a/include/ccmath/math/basic/impl/nan_double_impl.hpp b/include/ccmath/math/basic/impl/nan_double_impl.hpp index ec594ec..663436e 100644 --- a/include/ccmath/math/basic/impl/nan_double_impl.hpp +++ b/include/ccmath/math/basic/impl/nan_double_impl.hpp @@ -21,22 +21,22 @@ namespace ccm::internal namespace impl { - inline constexpr double nan_double_impl(const char* arg) noexcept - { + inline constexpr double nan_double_impl(const char * arg) noexcept + { static_assert(std::numeric_limits::is_iec559, "IEEE-754 representation required for this implementation"); - std::uint64_t dbl_bits {0}; - bool has_hex_been_detected {false}; + std::uint64_t dbl_bits{0}; + bool has_hex_been_detected{false}; if (arg == nullptr) - { - return std::numeric_limits::quiet_NaN(); // Default NaN - } + { + return std::numeric_limits::quiet_NaN(); // Default NaN + } if (arg[0] == '\0') - { - return std::numeric_limits::quiet_NaN(); // Default NaN - } + { + return std::numeric_limits::quiet_NaN(); // Default NaN + } // NOLINTBEGIN @@ -47,7 +47,7 @@ namespace ccm::internal has_hex_been_detected = true; } - bool msvc_one_digit_patch {false}; + bool msvc_one_digit_patch{false}; #if defined(_MSC_VER) && !defined(__clang__) // For some reason when passing '1' or '0x1' with msvc will cause it to adds on an extra bit to the number. @@ -59,7 +59,7 @@ namespace ccm::internal #endif if (!has_hex_been_detected) - { + { // Check that all of are characters are numbers. If we detect a non-number, return the default NaN. for (std::size_t i = 0; arg[i] != '\0'; ++i) // NOLINT { @@ -68,51 +68,54 @@ namespace ccm::internal return std::numeric_limits::quiet_NaN(); // Default NaN } } - } + } if (has_hex_been_detected) { // Calculate tag_value by handling wrapping for numbers larger than 8 digits - for (std::size_t i = 0; arg[i] != '\0'; ++i) { - dbl_bits *= 16; - dbl_bits += static_cast(ccm::helpers::digit_to_int(arg[i])); // Convert ASCII to numeric value - if (i >= 15) { - dbl_bits %= static_cast(1e18); // Wrap around for numbers larger than 8 digits - } - } + for (std::size_t i = 0; arg[i] != '\0'; ++i) + { + dbl_bits *= 16; + dbl_bits += static_cast(ccm::helpers::digit_to_int(arg[i])); // Convert ASCII to numeric value + if (i >= 15) + { + dbl_bits %= static_cast(1e18); // Wrap around for numbers larger than 8 digits + } + } } else - { - // Calculate tag_value by handling wrapping for numbers larger than 8 digits - for (std::size_t i = 0; arg[i] != '\0'; ++i) { - dbl_bits *= 10; - dbl_bits += static_cast(arg[i] - '0'); // Convert ASCII to numeric value - if (i >= 15) { - dbl_bits %= static_cast(1e18); // Wrap around for numbers larger than 8 digits - } - } - } + { + // Calculate tag_value by handling wrapping for numbers larger than 8 digits + for (std::size_t i = 0; arg[i] != '\0'; ++i) + { + dbl_bits *= 10; + dbl_bits += static_cast(arg[i] - '0'); // Convert ASCII to numeric value + if (i >= 15) + { + dbl_bits %= static_cast(1e18); // Wrap around for numbers larger than 8 digits + } + } + } // NOLINTEND // Set the tag bits for NaN - //dbl_bits |= UINT64_C(0x7FF8000000000000); + // dbl_bits |= UINT64_C(0x7FF8000000000000); dbl_bits |= ccm::helpers::bit_cast(std::numeric_limits::quiet_NaN()); // Subtract 1 bit from the number if the msvc patch is active if (msvc_one_digit_patch) - { + { // TODO: Make this more efficient // Currently, MSVC always returns a Quiet NaN with no additional bits set. // This feature applies no matter what the input is. return std::numeric_limits::quiet_NaN(); // Default NaN - } - - //dbl_bits -= 1; + } + // dbl_bits -= 1; // Convert the uint64_t tag into a double NaN return ccm::helpers::bit_cast(dbl_bits); - } + } } // namespace impl } // namespace } // namespace ccm::internal diff --git a/include/ccmath/math/basic/impl/nan_float_impl.hpp b/include/ccmath/math/basic/impl/nan_float_impl.hpp index e70f07b..a1713e6 100644 --- a/include/ccmath/math/basic/impl/nan_float_impl.hpp +++ b/include/ccmath/math/basic/impl/nan_float_impl.hpp @@ -21,66 +21,70 @@ namespace ccm::internal namespace impl { - inline constexpr float nan_float_impl(const char* arg) noexcept - { + inline constexpr float nan_float_impl(const char * arg) noexcept + { static_assert(std::numeric_limits::is_iec559, "IEEE-754 representation required for this implementation"); - std::uint32_t flt_bits {0}; - bool has_hex_been_detected {false}; + std::uint32_t flt_bits{0}; + bool has_hex_been_detected{false}; // NOLINTBEGIN // Check for a hex prefix and if its detected, skip the prefix and set the flag. if (arg[0] == '0' && (arg[1] == 'x' || arg[1] == 'X')) - { - arg += 2; - has_hex_been_detected = true; - } + { + arg += 2; + has_hex_been_detected = true; + } if (!has_hex_been_detected) - { + { // Check that all of are characters are numbers. If we detect a non-number, return the default NaN. for (std::size_t i = 0; arg[i] != '\0'; ++i) // NOLINT - { - if (arg[i] < '0' || arg[i] > '9') - { - return std::numeric_limits::quiet_NaN(); // Default NaN - } - } - } + { + if (arg[i] < '0' || arg[i] > '9') + { + return std::numeric_limits::quiet_NaN(); // Default NaN + } + } + } if (has_hex_been_detected) - { - // Calculate tag_value by handling wrapping for numbers larger than 8 digits - for (std::size_t i = 0; arg[i] != '\0'; ++i) { - flt_bits *= 16; - flt_bits += static_cast(ccm::helpers::digit_to_int(arg[i])); // Convert ASCII to numeric value - if (i >= 7) { - flt_bits %= static_cast(1e8); // Wrap around for numbers larger than 8 digits - } - } - } + { + // Calculate tag_value by handling wrapping for numbers larger than 8 digits + for (std::size_t i = 0; arg[i] != '\0'; ++i) + { + flt_bits *= 16; + flt_bits += static_cast(ccm::helpers::digit_to_int(arg[i])); // Convert ASCII to numeric value + if (i >= 7) + { + flt_bits %= static_cast(1e8); // Wrap around for numbers larger than 8 digits + } + } + } else - { - // Calculate tag_value by handling wrapping for numbers larger than 8 digits - for (std::size_t i = 0; arg[i] != '\0'; ++i) { - flt_bits *= 10; - flt_bits += static_cast(ccm::helpers::digit_to_int(arg[i])); // Convert ASCII to numeric value - if (i >= 7) { - flt_bits %= static_cast(1e8); // Wrap around for numbers larger than 8 digits - } - } - } + { + // Calculate tag_value by handling wrapping for numbers larger than 8 digits + for (std::size_t i = 0; arg[i] != '\0'; ++i) + { + flt_bits *= 10; + flt_bits += static_cast(ccm::helpers::digit_to_int(arg[i])); // Convert ASCII to numeric value + if (i >= 7) + { + flt_bits %= static_cast(1e8); // Wrap around for numbers larger than 8 digits + } + } + } // NOLINTEND // Set the tag bits for NaN - //flt_bits |= UINT32_C(0x7F800000); + // flt_bits |= UINT32_C(0x7F800000); flt_bits |= ccm::helpers::bit_cast(std::numeric_limits::quiet_NaN()); // Convert the bits to a float return ccm::helpers::bit_cast(flt_bits); - } + } } // namespace impl } // namespace } // namespace ccm::internal diff --git a/include/ccmath/math/basic/impl/remquo_double_impl.hpp b/include/ccmath/math/basic/impl/remquo_double_impl.hpp index 152919c..61108c1 100644 --- a/include/ccmath/math/basic/impl/remquo_double_impl.hpp +++ b/include/ccmath/math/basic/impl/remquo_double_impl.hpp @@ -55,7 +55,10 @@ namespace ccm::internal // clang-format on // If x is not finite or y is NaN. - if (CCM_UNLIKELY(x_i64 >= 0x7ff0000000000000ULL || y_i64 > 0x7ff0000000000000ULL)) { return (x * y) / (x * y); } // NOLINT(readability-simplify-boolean-expr) + if (CCM_UNLIKELY(x_i64 >= 0x7ff0000000000000ULL || y_i64 > 0x7ff0000000000000ULL)) + { + return (x * y) / (x * y); + } // NOLINT(readability-simplify-boolean-expr) // b (or bit 54) represents the highest bit we can compare against for both signed and unsigned integers without causing an overflow. // Here we are checking that if y_i64 is within the range of signed 64-bit integers that can be represented without setting the MSB (i.e., @@ -127,7 +130,7 @@ namespace ccm::internal return x; } } // namespace impl - } // namespace + } // namespace template >> inline constexpr T remquo_double(T x, T y, int * quo) noexcept diff --git a/include/ccmath/math/basic/impl/remquo_float_impl.hpp b/include/ccmath/math/basic/impl/remquo_float_impl.hpp index 47e6a28..7fea474 100644 --- a/include/ccmath/math/basic/impl/remquo_float_impl.hpp +++ b/include/ccmath/math/basic/impl/remquo_float_impl.hpp @@ -109,7 +109,7 @@ namespace ccm::internal return x; } } // namespace impl - } // namespace + } // namespace template >> inline constexpr T remquo_float(T x, T y, int * quo) noexcept diff --git a/include/ccmath/math/basic/impl/remquo_ldouble_impl.hpp b/include/ccmath/math/basic/impl/remquo_ldouble_impl.hpp index 0bea2e5..1b9207f 100644 --- a/include/ccmath/math/basic/impl/remquo_ldouble_impl.hpp +++ b/include/ccmath/math/basic/impl/remquo_ldouble_impl.hpp @@ -30,13 +30,12 @@ namespace ccm::internal std::int32_t y_int32{}; std::uint32_t x_sign{}; - std::uint32_t y_msb{}; + std::uint32_t y_msb{}; std::uint32_t x_lsb{}; int quotient_sign{}; int computed_quotient{}; - // TODO: For the time being this is mega on hold until we have access to // necessary implementations of int128_t. Without them extracting the // needed bits to perform the necessary operations would be extremely challenging @@ -45,7 +44,7 @@ namespace ccm::internal return 0; } } // namespace impl - } // namespace + } // namespace template >> inline constexpr T remquo_ldouble(T x, T y, int * quo) noexcept diff --git a/include/ccmath/math/basic/max.hpp b/include/ccmath/math/basic/max.hpp index 7316b6a..4ad7818 100644 --- a/include/ccmath/math/basic/max.hpp +++ b/include/ccmath/math/basic/max.hpp @@ -8,8 +8,8 @@ #pragma once -#include "ccmath/math/compare/isnan.hpp" #include "ccmath/internal/predef/unlikely.hpp" +#include "ccmath/math/compare/isnan.hpp" #include #include diff --git a/include/ccmath/math/basic/min.hpp b/include/ccmath/math/basic/min.hpp index ea8db3c..006cddf 100644 --- a/include/ccmath/math/basic/min.hpp +++ b/include/ccmath/math/basic/min.hpp @@ -8,9 +8,9 @@ #pragma once -#include "ccmath/math/compare/isnan.hpp" -#include "ccmath/internal/predef/unlikely.hpp" #include +#include "ccmath/internal/predef/unlikely.hpp" +#include "ccmath/math/compare/isnan.hpp" namespace ccm { @@ -37,7 +37,7 @@ namespace ccm /** * @brief Computes the smaller of the two values. * @tparam T Left-hand type of the left-hand value to compare. - * @tparam U Right-hand type of the right-hand value to compare. + * @tparam U Right-hand type of the right-hand value to compare. * @param x Left-hand side of the comparison. * @param y Right-hand side of the comparison. * @return If successful, returns the smaller of two floating point values. The value returned is exact and does not depend on any rounding modes. diff --git a/include/ccmath/math/basic/nan.hpp b/include/ccmath/math/basic/nan.hpp index f94cd41..1d95214 100644 --- a/include/ccmath/math/basic/nan.hpp +++ b/include/ccmath/math/basic/nan.hpp @@ -18,17 +18,17 @@ namespace ccm * @param arg * @return */ - constexpr double nan(const char* arg) noexcept + constexpr double nan(const char * arg) noexcept { return ccm::internal::impl::nan_double_impl(arg); } - constexpr float nanf(const char* arg) noexcept + constexpr float nanf(const char * arg) noexcept { return ccm::internal::impl::nan_float_impl(arg); } - constexpr long double nanl([[maybe_unused]] const char* arg) noexcept + constexpr long double nanl([[maybe_unused]] const char * arg) noexcept { // Currently we do not yet support long double for ccm::nan // Idk if we ever will, but for the time being if someone calls the function. Just return a quiet NaN. diff --git a/include/ccmath/math/basic/remainder.hpp b/include/ccmath/math/basic/remainder.hpp index c7b104e..437d96b 100644 --- a/include/ccmath/math/basic/remainder.hpp +++ b/include/ccmath/math/basic/remainder.hpp @@ -8,10 +8,10 @@ #pragma once +#include "ccmath/internal/predef/unlikely.hpp" #include "ccmath/math/compare/isinf.hpp" #include "ccmath/math/compare/isnan.hpp" #include "ccmath/math/nearest/trunc.hpp" -#include "ccmath/internal/predef/unlikely.hpp" namespace ccm { @@ -25,14 +25,14 @@ namespace ccm template , int> = 0> inline constexpr T remainder(T x, T y) { - // If x is ±∞ and y is not NaN, NaN is returned. - // If y is ±0 and x is not NaN, NaN is returned. - // If either argument is NaN, NaN is returned. - if (CCM_UNLIKELY((ccm::isinf(x) && !ccm::isnan(y)) || (y == 0 && !ccm::isnan(x)) || (ccm::isnan(x) || ccm::isnan(y)))) - { - // All major compilers return -NaN. - return -std::numeric_limits::quiet_NaN(); - } + // If x is ±∞ and y is not NaN, NaN is returned. + // If y is ±0 and x is not NaN, NaN is returned. + // If either argument is NaN, NaN is returned. + if (CCM_UNLIKELY((ccm::isinf(x) && !ccm::isnan(y)) || (y == 0 && !ccm::isnan(x)) || (ccm::isnan(x) || ccm::isnan(y)))) + { + // All major compilers return -NaN. + return -std::numeric_limits::quiet_NaN(); + } return static_cast(x - (ccm::trunc(x / y) * y)); } diff --git a/include/ccmath/math/compare/fpclassify.hpp b/include/ccmath/math/compare/fpclassify.hpp index ee2096e..234aa8f 100644 --- a/include/ccmath/math/compare/fpclassify.hpp +++ b/include/ccmath/math/compare/fpclassify.hpp @@ -8,8 +8,8 @@ #pragma once -#include "ccmath/math/basic/abs.hpp" #include "ccmath/internal/helpers/fpclassify_helper.hpp" +#include "ccmath/math/basic/abs.hpp" #include "ccmath/math/compare/isinf.hpp" #include "ccmath/math/compare/isnan.hpp" diff --git a/include/ccmath/math/compare/isgreater.hpp b/include/ccmath/math/compare/isgreater.hpp index 825c7aa..f1cd043 100644 --- a/include/ccmath/math/compare/isgreater.hpp +++ b/include/ccmath/math/compare/isgreater.hpp @@ -21,9 +21,9 @@ namespace ccm */ template inline constexpr bool isgreater(T x, T y) noexcept - { - return x > y; - } + { + return x > y; + } /** * @brief Checks if the first argument is greater than the second. @@ -34,14 +34,14 @@ namespace ccm * @return true if the first argument is greater than the second, false otherwise. */ template - inline constexpr bool isgreater(T x, U y) noexcept - { + inline constexpr bool isgreater(T x, U y) noexcept + { // Find the common type of the two arguments using shared_type = std::common_type_t; // Then cast the arguments to the common type and call the single argument version return static_cast(isgreater(static_cast(x), static_cast(y))); - } + } } // namespace ccm /// @ingroup compare diff --git a/include/ccmath/math/compare/isgreaterequal.hpp b/include/ccmath/math/compare/isgreaterequal.hpp index d04a0be..9b720cb 100644 --- a/include/ccmath/math/compare/isgreaterequal.hpp +++ b/include/ccmath/math/compare/isgreaterequal.hpp @@ -13,35 +13,35 @@ namespace ccm { /** - * @brief Checks if the first argument is greater than or equal to the second. - * @tparam T Type of the values to compare. - * @param x A floating-point or integer value. - * @param y A floating-point or integer value. - * @return true if the first argument is greater than or equal to the second, false otherwise. - */ + * @brief Checks if the first argument is greater than or equal to the second. + * @tparam T Type of the values to compare. + * @param x A floating-point or integer value. + * @param y A floating-point or integer value. + * @return true if the first argument is greater than or equal to the second, false otherwise. + */ template inline constexpr bool isgreaterequal(T x, T y) noexcept - { - return x >= y; - } + { + return x >= y; + } /** - * @brief Checks if the first argument is greater than or equal to the second. - * @tparam T Type of the left-hand side. - * @tparam U Type of the right-hand side. - * @param x Value of the left-hand side of the comparison. - * @param y Value of the right-hand side of the comparison. - * @return true if the first argument is greater than or equal to the second, false otherwise. - */ + * @brief Checks if the first argument is greater than or equal to the second. + * @tparam T Type of the left-hand side. + * @tparam U Type of the right-hand side. + * @param x Value of the left-hand side of the comparison. + * @param y Value of the right-hand side of the comparison. + * @return true if the first argument is greater than or equal to the second, false otherwise. + */ template inline constexpr bool isgreaterequal(T x, U y) noexcept - { + { // Find the common type of the two arguments using shared_type = std::common_type_t; // Then cast the arguments to the common type and call the single argument version return static_cast(isgreaterequal(static_cast(x), static_cast(y))); - } + } } // namespace ccm /// @ingroup compare diff --git a/include/ccmath/math/compare/isless.hpp b/include/ccmath/math/compare/isless.hpp index efe5291..d21c06b 100644 --- a/include/ccmath/math/compare/isless.hpp +++ b/include/ccmath/math/compare/isless.hpp @@ -13,35 +13,35 @@ namespace ccm { /** - * @brief Checks if the first argument is less than the second. - * @tparam T Type of the values to compare. - * @param x A floating-point or integer value. - * @param y A floating-point or integer value. - * @return true if the first argument is less than the second, false otherwise. - */ - template - inline constexpr bool isless(T x, T y) noexcept - { - return x < y; - } + * @brief Checks if the first argument is less than the second. + * @tparam T Type of the values to compare. + * @param x A floating-point or integer value. + * @param y A floating-point or integer value. + * @return true if the first argument is less than the second, false otherwise. + */ + template + inline constexpr bool isless(T x, T y) noexcept + { + return x < y; + } - /** - * @brief Checks if the first argument is less than the second. - * @tparam T Type of the left-hand side. - * @tparam U Type of the right-hand side. - * @param x Value of the left-hand side of the comparison. - * @param y Value of the right-hand side of the comparison. - * @return true if the first argument is less than the second, false otherwise. - */ - template - inline constexpr bool isless(T x, U y) noexcept - { - // Find the common type of the two arguments - using shared_type = std::common_type_t; + /** + * @brief Checks if the first argument is less than the second. + * @tparam T Type of the left-hand side. + * @tparam U Type of the right-hand side. + * @param x Value of the left-hand side of the comparison. + * @param y Value of the right-hand side of the comparison. + * @return true if the first argument is less than the second, false otherwise. + */ + template + inline constexpr bool isless(T x, U y) noexcept + { + // Find the common type of the two arguments + using shared_type = std::common_type_t; - // Then cast the arguments to the common type and call the single argument version - return static_cast(isless(static_cast(x), static_cast(y))); - } + // Then cast the arguments to the common type and call the single argument version + return static_cast(isless(static_cast(x), static_cast(y))); + } } // namespace ccm /// @ingroup compare diff --git a/include/ccmath/math/compare/islessequal.hpp b/include/ccmath/math/compare/islessequal.hpp index 68c0775..5b43b78 100644 --- a/include/ccmath/math/compare/islessequal.hpp +++ b/include/ccmath/math/compare/islessequal.hpp @@ -13,35 +13,35 @@ namespace ccm { /** - * @brief Checks if the first argument is less than or equal to the second. - * @tparam T Type of the values to compare. - * @param x A floating-point or integer value. - * @param y A floating-point or integer value. - * @return true if the first argument is less than or equal to the second, false otherwise. - */ - template - inline constexpr bool islessequal(T x, T y) noexcept - { - return x <= y; - } + * @brief Checks if the first argument is less than or equal to the second. + * @tparam T Type of the values to compare. + * @param x A floating-point or integer value. + * @param y A floating-point or integer value. + * @return true if the first argument is less than or equal to the second, false otherwise. + */ + template + inline constexpr bool islessequal(T x, T y) noexcept + { + return x <= y; + } - /** - * @brief Checks if the first argument is less than or equal to the second. - * @tparam T Type of the left-hand side. - * @tparam U Type of the right-hand side. - * @param x Value of the left-hand side of the comparison. - * @param y Value of the right-hand side of the comparison. - * @return true if the first argument is less than or equal to the second, false otherwise. - */ - template - inline constexpr bool islessequal(T x, U y) noexcept - { - // Find the common type of the two arguments - using shared_type = std::common_type_t; + /** + * @brief Checks if the first argument is less than or equal to the second. + * @tparam T Type of the left-hand side. + * @tparam U Type of the right-hand side. + * @param x Value of the left-hand side of the comparison. + * @param y Value of the right-hand side of the comparison. + * @return true if the first argument is less than or equal to the second, false otherwise. + */ + template + inline constexpr bool islessequal(T x, U y) noexcept + { + // Find the common type of the two arguments + using shared_type = std::common_type_t; - // Then cast the arguments to the common type and call the single argument version - return static_cast(islessequal(static_cast(x), static_cast(y))); - } + // Then cast the arguments to the common type and call the single argument version + return static_cast(islessequal(static_cast(x), static_cast(y))); + } } // namespace ccm /// @ingroup compare diff --git a/include/ccmath/math/compare/islessgreater.hpp b/include/ccmath/math/compare/islessgreater.hpp index 7499d8b..34b0ab3 100644 --- a/include/ccmath/math/compare/islessgreater.hpp +++ b/include/ccmath/math/compare/islessgreater.hpp @@ -13,32 +13,32 @@ namespace ccm { /** - * @brief Checks if the first argument is less than the second or greater than the second. - * @tparam T Type of the values to compare. - * @param x A floating-point or integer value. - * @param y A floating-point or integer value. - * @return true if the first argument is less than the second or greater than the second, false otherwise. - */ + * @brief Checks if the first argument is less than the second or greater than the second. + * @tparam T Type of the values to compare. + * @param x A floating-point or integer value. + * @param y A floating-point or integer value. + * @return true if the first argument is less than the second or greater than the second, false otherwise. + */ template inline constexpr bool islessgreater(T x, T y) noexcept - { + { return x < y || x > y; } /** - * @brief Checks if the first argument is less than the second or greater than the second. - * @tparam T Type of the left-hand side. - * @tparam U Type of the right-hand side. - * @param x Value of the left-hand side of the comparison. - * @param y Value of the right-hand side of the comparison. - * @return true if the first argument is less than the second or greater than the second, false otherwise. - */ + * @brief Checks if the first argument is less than the second or greater than the second. + * @tparam T Type of the left-hand side. + * @tparam U Type of the right-hand side. + * @param x Value of the left-hand side of the comparison. + * @param y Value of the right-hand side of the comparison. + * @return true if the first argument is less than the second or greater than the second, false otherwise. + */ template - inline constexpr bool islessgreater(T x, U y) noexcept - { - using shared_type = std::common_type_t; - return static_cast(islessgreater(static_cast(x), static_cast(y))); - } + inline constexpr bool islessgreater(T x, U y) noexcept + { + using shared_type = std::common_type_t; + return static_cast(islessgreater(static_cast(x), static_cast(y))); + } } // namespace ccm /// @ingroup compare diff --git a/include/ccmath/math/compare/isnormal.hpp b/include/ccmath/math/compare/isnormal.hpp index fce4847..f139127 100644 --- a/include/ccmath/math/compare/isnormal.hpp +++ b/include/ccmath/math/compare/isnormal.hpp @@ -8,34 +8,34 @@ #pragma once -#include "ccmath/math/compare/isinf.hpp" #include "ccmath/math/basic/abs.hpp" +#include "ccmath/math/compare/isinf.hpp" #include "ccmath/math/compare/isnan.hpp" namespace ccm { /** - * @brief Checks if the given number has a normal value. - * @tparam T The type of the number. - * @param x A floating-point or integer value - * @return true if the number has a normal value, false otherwise. - */ + * @brief Checks if the given number has a normal value. + * @tparam T The type of the number. + * @param x A floating-point or integer value + * @return true if the number has a normal value, false otherwise. + */ template , bool> = true> inline constexpr bool isnormal(T num) noexcept - { - return num != static_cast(0) && !ccm::isnan(num) && !ccm::isinf(num) && ccm::abs(num) >= std::numeric_limits::min(); - } + { + return num != static_cast(0) && !ccm::isnan(num) && !ccm::isinf(num) && ccm::abs(num) >= std::numeric_limits::min(); + } /** - * @brief Checks if the given number has a normal value. - * @tparam Integer The type of the integer. - * @param x A integer value to check. - * @return true if the number has a normal value, false otherwise. - */ + * @brief Checks if the given number has a normal value. + * @tparam Integer The type of the integer. + * @param x A integer value to check. + * @return true if the number has a normal value, false otherwise. + */ template , bool> = true> inline constexpr bool isnormal(Integer num) noexcept - { - return num != static_cast(0); - } + { + return num != static_cast(0); + } } // namespace ccm diff --git a/include/ccmath/math/compare/isunordered.hpp b/include/ccmath/math/compare/isunordered.hpp index 1e71c3b..b33c99a 100644 --- a/include/ccmath/math/compare/isunordered.hpp +++ b/include/ccmath/math/compare/isunordered.hpp @@ -8,31 +8,31 @@ #pragma once -#include "ccmath/math/compare/isnan.hpp" #include +#include "ccmath/math/compare/isnan.hpp" namespace ccm { /** - * @brief Checks if the given number is unordered, that is, one or both are NaN and thus cannot be meaningfully compared with each other. - * @tparam T The type of the number. - * @param x A floating-point or integer value - * @param y A floating-point or integer value - * @return true if either x or y is NaN, false otherwise. + * @brief Checks if the given number is unordered, that is, one or both are NaN and thus cannot be meaningfully compared with each other. + * @tparam T The type of the number. + * @param x A floating-point or integer value + * @param y A floating-point or integer value + * @return true if either x or y is NaN, false otherwise. */ template , bool> = true> inline constexpr bool isunordered(T x, T y) noexcept - { - return ccm::isnan(x) || ccm::isnan(y); - } + { + return ccm::isnan(x) || ccm::isnan(y); + } /** - * @brief Checks if the given number is unordered, that is, one or both are NaN and thus cannot be meaningfully compared with each other. - * @tparam Integer The type of the integer. - * @param x A integer value to check. - * @param y A integer value to check. - * @return false, as all integers are ordered. - */ + * @brief Checks if the given number is unordered, that is, one or both are NaN and thus cannot be meaningfully compared with each other. + * @tparam Integer The type of the integer. + * @param x A integer value to check. + * @param y A integer value to check. + * @return false, as all integers are ordered. + */ template , bool> = true> inline constexpr bool isunordered(Integer /* x */, Integer /* y */) noexcept { @@ -40,19 +40,19 @@ namespace ccm } /** - * @brief Checks if the given number is unordered, that is, one or both are NaN and thus cannot be meaningfully compared with each other. - * @tparam T Type of the left-hand side. - * @tparam U Type of the right-hand side. - * @param x Value of the left-hand side of the comparison. - * @param y Value of the right-hand side of the comparison. - * @return true if either x or y is NaN, false otherwise. - */ + * @brief Checks if the given number is unordered, that is, one or both are NaN and thus cannot be meaningfully compared with each other. + * @tparam T Type of the left-hand side. + * @tparam U Type of the right-hand side. + * @param x Value of the left-hand side of the comparison. + * @param y Value of the right-hand side of the comparison. + * @return true if either x or y is NaN, false otherwise. + */ template - inline constexpr bool isunordered(T x, U y) noexcept - { + inline constexpr bool isunordered(T x, U y) noexcept + { using shared_type = std::common_type_t; return static_cast(isunordered(static_cast(x), static_cast(y))); - } + } } // namespace ccm /// @ingroup compare diff --git a/include/ccmath/math/exponential/exp.hpp b/include/ccmath/math/exponential/exp.hpp index 8543995..36245e6 100644 --- a/include/ccmath/math/exponential/exp.hpp +++ b/include/ccmath/math/exponential/exp.hpp @@ -14,10 +14,10 @@ namespace ccm { /** - * @brief Computes e raised to the given power - * @tparam T floating-point or integer type - * @param num floating-point or integer value - * @return If no errors occur, the base-e exponential of num (e^num) is returned. + * @brief Computes e raised to the given power + * @tparam T floating-point or integer type + * @param num floating-point or integer value + * @return If no errors occur, the base-e exponential of num (e^num) is returned. */ template , bool> = true> inline constexpr T exp(T num) @@ -27,35 +27,35 @@ namespace ccm } /** - * @brief Computes e raised to the given power - * @tparam Integer integer type - * @param num integer value - * @return If no errors occur, the base-e exponential of num (e^num) is returned as double. + * @brief Computes e raised to the given power + * @tparam Integer integer type + * @param num integer value + * @return If no errors occur, the base-e exponential of num (e^num) is returned as double. */ template , bool> = true> inline constexpr double exp(Integer num) - { - return ccm::exp(static_cast(num)); - } + { + return ccm::exp(static_cast(num)); + } - /** - * @brief Computes e raised to the given power - * @param num floating-point value - * @return If no errors occur, the base-e exponential of num (e^num) is returned as float. - */ + /** + * @brief Computes e raised to the given power + * @param num floating-point value + * @return If no errors occur, the base-e exponential of num (e^num) is returned as float. + */ inline constexpr float expf(float num) - { - return ccm::internal::impl::exp_float_impl(num); - } + { + return ccm::internal::impl::exp_float_impl(num); + } /** - * @brief Computes e raised to the given power - * @param num floating-point value - * @return If no errors occur, the base-e exponential of num (e^num) is returned as double. - */ + * @brief Computes e raised to the given power + * @param num floating-point value + * @return If no errors occur, the base-e exponential of num (e^num) is returned as double. + */ inline constexpr long double expl(long double num) - { - return static_cast(ccm::exp(static_cast(num))); - } + { + return static_cast(ccm::exp(static_cast(num))); + } } // namespace ccm diff --git a/include/ccmath/math/exponential/exp2.hpp b/include/ccmath/math/exponential/exp2.hpp index 12ae10f..8fbf291 100644 --- a/include/ccmath/math/exponential/exp2.hpp +++ b/include/ccmath/math/exponential/exp2.hpp @@ -10,10 +10,10 @@ namespace ccm { - template - inline constexpr T exp2([[maybe_unused]] T x) - { - return 0; - } + template + inline constexpr T exp2([[maybe_unused]] T x) + { + return 0; + } } // namespace ccm diff --git a/include/ccmath/math/exponential/impl/exp2_data.hpp b/include/ccmath/math/exponential/impl/exp2_data.hpp index f31ab52..436cf57 100644 --- a/include/ccmath/math/exponential/impl/exp2_data.hpp +++ b/include/ccmath/math/exponential/impl/exp2_data.hpp @@ -21,9 +21,9 @@ namespace ccm::internal constexpr std::size_t k_exp2_poly_order_flt = 3; // Double constants - constexpr std::size_t k_exp_table_bits_dbl = 7; - constexpr std::size_t k_exp_poly_order_dbl = 5; - constexpr std::size_t k_exp2_poly_order_dbl = 5; + constexpr std::size_t k_exp_table_bits_dbl = 7; + constexpr std::size_t k_exp_poly_order_dbl = 5; + constexpr std::size_t k_exp2_poly_order_dbl = 5; template , int> = 0> struct exp_data; diff --git a/include/ccmath/math/exponential/impl/exp_data.hpp b/include/ccmath/math/exponential/impl/exp_data.hpp index 4cb8bcb..2de4107 100644 --- a/include/ccmath/math/exponential/impl/exp_data.hpp +++ b/include/ccmath/math/exponential/impl/exp_data.hpp @@ -17,12 +17,12 @@ namespace ccm::internal { // Float constants - constexpr std::size_t k_exp_table_bits_flt = 5; + constexpr std::size_t k_exp_table_bits_flt = 5; constexpr std::size_t k_exp_poly_order_flt = 3; // Double constants - constexpr std::size_t k_exp_table_bits_dbl = 7; - constexpr std::size_t k_exp_poly_order_dbl = 5; + constexpr std::size_t k_exp_table_bits_dbl = 7; + constexpr std::size_t k_exp_poly_order_dbl = 5; template , int> = 0> struct exp_data; @@ -30,16 +30,13 @@ namespace ccm::internal template <> struct exp_data { - double invln2_scaled {0x1.71547652b82fep0 * (1 << k_exp_table_bits_flt)}; - double shift {0x1.8p+52}; + double invln2_scaled{0x1.71547652b82fep0 * (1 << k_exp_table_bits_flt)}; + double shift{0x1.8p+52}; std::array tab = { - 0x3ff0000000000000, 0x3fefd9b0d3158574, 0x3fefb5586cf9890f, 0x3fef9301d0125b51, - 0x3fef72b83c7d517b, 0x3fef54873168b9aa, 0x3fef387a6e756238, 0x3fef1e9df51fdee1, - 0x3fef06fe0a31b715, 0x3feef1a7373aa9cb, 0x3feedea64c123422, 0x3feece086061892d, - 0x3feebfdad5362a27, 0x3feeb42b569d4f82, 0x3feeab07dd485429, 0x3feea47eb03a5585, - 0x3feea09e667f3bcd, 0x3fee9f75e8ec5f74, 0x3feea11473eb0187, 0x3feea589994cce13, - 0x3feeace5422aa0db, 0x3feeb737b0cdc5e5, 0x3feec49182a3f090, 0x3feed503b23e255d, - 0x3feee89f995ad3ad, 0x3feeff76f2fb5e47, 0x3fef199bdd85529c, 0x3fef3720dcef9069, + 0x3ff0000000000000, 0x3fefd9b0d3158574, 0x3fefb5586cf9890f, 0x3fef9301d0125b51, 0x3fef72b83c7d517b, 0x3fef54873168b9aa, 0x3fef387a6e756238, + 0x3fef1e9df51fdee1, 0x3fef06fe0a31b715, 0x3feef1a7373aa9cb, 0x3feedea64c123422, 0x3feece086061892d, 0x3feebfdad5362a27, 0x3feeb42b569d4f82, + 0x3feeab07dd485429, 0x3feea47eb03a5585, 0x3feea09e667f3bcd, 0x3fee9f75e8ec5f74, 0x3feea11473eb0187, 0x3feea589994cce13, 0x3feeace5422aa0db, + 0x3feeb737b0cdc5e5, 0x3feec49182a3f090, 0x3feed503b23e255d, 0x3feee89f995ad3ad, 0x3feeff76f2fb5e47, 0x3fef199bdd85529c, 0x3fef3720dcef9069, 0x3fef5818dcfba487, 0x3fef7c97337b9b5f, 0x3fefa4afa2a490da, 0x3fefd0765b6e4540, }; @@ -47,7 +44,7 @@ namespace ccm::internal 0x1.c6af84b912394p-5 / (1 << k_exp_table_bits_flt) / (1 << k_exp_table_bits_flt) / (1 << k_exp_table_bits_flt), 0x1.ebfce50fac4f3p-3 / (1 << k_exp_table_bits_flt) / (1 << k_exp_table_bits_flt), 0x1.62e42ff0c52d6p-1 / (1 << k_exp_table_bits_flt), - }; + }; }; template <> diff --git a/include/ccmath/math/exponential/impl/exp_double_impl.hpp b/include/ccmath/math/exponential/impl/exp_double_impl.hpp index 34b6422..6c8c910 100644 --- a/include/ccmath/math/exponential/impl/exp_double_impl.hpp +++ b/include/ccmath/math/exponential/impl/exp_double_impl.hpp @@ -8,12 +8,12 @@ #pragma once +#include +#include #include "ccmath/internal/helpers/exp_helpers.hpp" #include "ccmath/internal/predef/unlikely.hpp" #include "ccmath/internal/types/fp_types.hpp" #include "ccmath/math/exponential/impl/exp_data.hpp" -#include -#include namespace ccm::internal { @@ -22,16 +22,16 @@ namespace ccm::internal namespace impl { constexpr ccm::internal::exp_data internal_exp_data_dbl = ccm::internal::exp_data(); - constexpr auto exp_invLn2N_dbl = internal_exp_data_dbl.invln2N; - constexpr auto exp_negLn2HiN_dbl = internal_exp_data_dbl.negln2hiN; - constexpr auto exp_negLn2LoN_dbl = internal_exp_data_dbl.negln2loN; - constexpr auto exp_shift_dbl = internal_exp_data_dbl.shift; - constexpr auto exp_tab_dbl = internal_exp_data_dbl.tab; - constexpr auto exp_poly_coeff_one_dbl = internal_exp_data_dbl.poly[5 - k_exp_poly_order_dbl]; - constexpr auto exp_poly_coeff_two_dbl = internal_exp_data_dbl.poly[6 - k_exp_poly_order_dbl]; - constexpr auto exp_poly_coeff_three_dbl = internal_exp_data_dbl.poly[7 - k_exp_poly_order_dbl]; - constexpr auto exp_poly_coeff_four_dbl = internal_exp_data_dbl.poly[8 - k_exp_poly_order_dbl]; - constexpr auto k_exp_table_n_dbl = (1 << ccm::internal::k_exp_table_bits_dbl); + constexpr auto exp_invLn2N_dbl = internal_exp_data_dbl.invln2N; + constexpr auto exp_negLn2HiN_dbl = internal_exp_data_dbl.negln2hiN; + constexpr auto exp_negLn2LoN_dbl = internal_exp_data_dbl.negln2loN; + constexpr auto exp_shift_dbl = internal_exp_data_dbl.shift; + constexpr auto exp_tab_dbl = internal_exp_data_dbl.tab; + constexpr auto exp_poly_coeff_one_dbl = internal_exp_data_dbl.poly[5 - k_exp_poly_order_dbl]; + constexpr auto exp_poly_coeff_two_dbl = internal_exp_data_dbl.poly[6 - k_exp_poly_order_dbl]; + constexpr auto exp_poly_coeff_three_dbl = internal_exp_data_dbl.poly[7 - k_exp_poly_order_dbl]; + constexpr auto exp_poly_coeff_four_dbl = internal_exp_data_dbl.poly[8 - k_exp_poly_order_dbl]; + constexpr auto k_exp_table_n_dbl = (1 << ccm::internal::k_exp_table_bits_dbl); inline constexpr double handle_special_case(ccm::double_t tmp, std::uint64_t sign_bits, std::uint64_t exponent_int64) // NOLINT { diff --git a/include/ccmath/math/exponential/impl/exp_float_impl.hpp b/include/ccmath/math/exponential/impl/exp_float_impl.hpp index f681205..10cf31e 100644 --- a/include/ccmath/math/exponential/impl/exp_float_impl.hpp +++ b/include/ccmath/math/exponential/impl/exp_float_impl.hpp @@ -20,8 +20,8 @@ namespace ccm::internal namespace impl { constexpr ccm::internal::exp_data internal_exp_data_flt = ccm::internal::exp_data(); - constexpr auto exp_inv_ln2_N_flt = internal_exp_data_flt.invln2_scaled; - constexpr auto exp_shift_flt = internal_exp_data_flt.shift; + constexpr auto exp_inv_ln2_N_flt = internal_exp_data_flt.invln2_scaled; + constexpr auto exp_shift_flt = internal_exp_data_flt.shift; constexpr auto exp_tab_flt = internal_exp_data_flt.tab; constexpr auto exp_poly_scaled_flt = internal_exp_data_flt.poly_scaled; constexpr auto k_exp_table_n_flt = (1 << ccm::internal::k_exp_table_bits_flt); @@ -44,17 +44,11 @@ namespace ccm::internal abs_top = ccm::helpers::top12_bits_of_float(x) & 0x7ff; if (CCM_UNLIKELY(abs_top >= ccm::helpers::top12_bits_of_float(88.0F))) - { + { // |x| >= 88 or x is nan. - if (ccm::helpers::float_to_uint32(x) == ccm::helpers::float_to_uint32(-std::numeric_limits::infinity())) - { - return 0.0F; - } + if (ccm::helpers::float_to_uint32(x) == ccm::helpers::float_to_uint32(-std::numeric_limits::infinity())) { return 0.0F; } - if (abs_top >= ccm::helpers::top12_bits_of_float(std::numeric_limits::infinity())) - { - return x + x; - } + if (abs_top >= ccm::helpers::top12_bits_of_float(std::numeric_limits::infinity())) { return x + x; } // Handle overflow if (x > 0x1.62e42ep6F) // x > log(0x1p128) ~= 88.72 @@ -77,21 +71,20 @@ namespace ccm::internal * ideally ties-to-even rule is used, otherwise the magnitude of r * can be bigger which gives larger approximation error. */ - expo = ccm::helpers::narrow_eval(static_cast(scaled_input + exp_shift_flt)); // Must be double + expo = ccm::helpers::narrow_eval(static_cast(scaled_input + exp_shift_flt)); // Must be double expo_int64 = ccm::helpers::double_to_uint64(expo); expo -= exp_shift_flt; rem = scaled_input - expo; - // exp(x) = 2^(k/N) * 2^(r/N) ~= s * (C0*r^3 + C1*r^2 + C2*r + 1) tmp = static_cast(exp_tab_flt.at(expo_int64 % k_exp_table_n_flt)); tmp += (expo_int64 << (52 - ccm::internal::k_exp_table_bits_flt)); - scale = ccm::helpers::uint64_to_double(tmp); + scale = ccm::helpers::uint64_to_double(tmp); scaled_input = exp_poly_scaled_flt.at(0) * rem + exp_poly_scaled_flt.at(1); - remSqr = rem * rem; - result = exp_poly_scaled_flt.at(2) * rem + 1.0F; - result = scaled_input * remSqr + result; - result = scale * result; + remSqr = rem * rem; + result = exp_poly_scaled_flt.at(2) * rem + 1.0F; + result = scaled_input * remSqr + result; + result = scale * result; return static_cast(result); } diff --git a/include/ccmath/math/exponential/impl/log2_data.hpp b/include/ccmath/math/exponential/impl/log2_data.hpp index c4ebbb8..ab648d9 100644 --- a/include/ccmath/math/exponential/impl/log2_data.hpp +++ b/include/ccmath/math/exponential/impl/log2_data.hpp @@ -52,7 +52,6 @@ namespace ccm::internal -0x1.715479ffae3dep-1, 0x1.715475f35c8b8p0, - }}; }; diff --git a/include/ccmath/math/exponential/impl/log2_float_impl.hpp b/include/ccmath/math/exponential/impl/log2_float_impl.hpp index 9f95ed5..6f61915 100644 --- a/include/ccmath/math/exponential/impl/log2_float_impl.hpp +++ b/include/ccmath/math/exponential/impl/log2_float_impl.hpp @@ -98,7 +98,7 @@ namespace ccm::internal return result; } } // namespace impl - } // namespace + } // namespace template [[nodiscard]] inline constexpr T log2_float(T num) noexcept diff --git a/include/ccmath/math/exponential/impl/log_double_impl.hpp b/include/ccmath/math/exponential/impl/log_double_impl.hpp index 89926fb..8404a8d 100644 --- a/include/ccmath/math/exponential/impl/log_double_impl.hpp +++ b/include/ccmath/math/exponential/impl/log_double_impl.hpp @@ -123,7 +123,8 @@ namespace ccm::internal // Calculate intermediate value for logarithm computation // log(x) = log1p(normVal/c-1) + log(c) + expo*Ln2. // r ~= z/c - 1, |r| < 1/(2*N) - rem = (normVal - log_tab2_values_dbl.at(static_cast(i)).chi - log_tab2_values_dbl.at(static_cast(i)).clo) * inverseCoeff; + rem = (normVal - log_tab2_values_dbl.at(static_cast(i)).chi - log_tab2_values_dbl.at(static_cast(i)).clo) * + inverseCoeff; scaleFactor = static_cast(expo); // Calculate high and low parts of logarithm @@ -144,7 +145,7 @@ namespace ccm::internal return static_cast(result); } } // namespace impl - } // namespace + } // namespace template [[nodiscard]] inline constexpr T log_double(T num) noexcept diff --git a/include/ccmath/math/exponential/impl/log_float_impl.hpp b/include/ccmath/math/exponential/impl/log_float_impl.hpp index 1758741..6eb07f6 100644 --- a/include/ccmath/math/exponential/impl/log_float_impl.hpp +++ b/include/ccmath/math/exponential/impl/log_float_impl.hpp @@ -87,7 +87,7 @@ namespace ccm::internal } } // namespace impl - } // namespace + } // namespace template [[nodiscard]] inline constexpr T log_float(T num) noexcept diff --git a/include/ccmath/math/fmanip/copysign.hpp b/include/ccmath/math/fmanip/copysign.hpp index 321791a..690b680 100644 --- a/include/ccmath/math/fmanip/copysign.hpp +++ b/include/ccmath/math/fmanip/copysign.hpp @@ -48,21 +48,21 @@ namespace ccm } /** - * @brief Copies the sign of a floating point value. - * @param x A floating-point. - * @param y A floating-point. - * @return If no errors occur, the floating point value with the magnitude of mag and the sign of sgn is returned. - */ + * @brief Copies the sign of a floating point value. + * @param x A floating-point. + * @param y A floating-point. + * @return If no errors occur, the floating point value with the magnitude of mag and the sign of sgn is returned. + */ inline constexpr float copysignf(float mag, float sgn) { return copysign(mag, sgn); } /** - * @brief Copies the sign of a floating point value. - * @param x A floating-point. - * @param y A floating-point. - * @return If no errors occur, the floating point value with the magnitude of mag and the sign of sgn is returned. + * @brief Copies the sign of a floating point value. + * @param x A floating-point. + * @param y A floating-point. + * @return If no errors occur, the floating point value with the magnitude of mag and the sign of sgn is returned. */ inline constexpr long double copysignl(long double mag, long double sgn) { diff --git a/include/ccmath/math/fmanip/impl/scalbn_double_impl.hpp b/include/ccmath/math/fmanip/impl/scalbn_double_impl.hpp index 5dc1f4b..3736e99 100644 --- a/include/ccmath/math/fmanip/impl/scalbn_double_impl.hpp +++ b/include/ccmath/math/fmanip/impl/scalbn_double_impl.hpp @@ -9,6 +9,7 @@ #pragma once #include "ccmath/internal/support/bits.hpp" +#include "ccmath/internal/types/fp_types.hpp" #include "ccmath/math/compare/isinf.hpp" #include "ccmath/math/compare/isnan.hpp" @@ -22,40 +23,34 @@ namespace ccm::internal namespace impl { inline constexpr double scalbn_double_impl(double arg, int exp) noexcept - { + { ccm::double_t tmp = arg; if (exp > 1023) - { + { tmp *= 0x1p1023; - exp -= 1023; - if (exp > 1023) - { + exp -= 1023; + if (exp > 1023) + { tmp *= 0x1p1023; - exp -= 1023; - if (exp > 1023) - { - exp = 1023; - } - } + exp -= 1023; + if (exp > 1023) { exp = 1023; } + } } else if (exp < -1022) - { - tmp *= 0x1p-1022 * 0x1p53; - exp += 1022 - 53; - if (exp < -1022) - { - tmp *= 0x1p-1022 * 0x1p53; - exp += 1022 - 53; - if (exp < -1022) - { - exp = -1022; - } - } - } + { + tmp *= 0x1p-1022 * 0x1p53; + exp += 1022 - 53; + if (exp < -1022) + { + tmp *= 0x1p-1022 * 0x1p53; + exp += 1022 - 53; + if (exp < -1022) { exp = -1022; } + } + } const std::uint64_t bits = ccm::helpers::bit_cast(1023 + static_cast(exp)) << 52; - arg = tmp * ccm::helpers::bit_cast(bits); + arg = tmp * ccm::helpers::bit_cast(bits); return arg; } diff --git a/include/ccmath/math/fmanip/impl/scalbn_float_impl.hpp b/include/ccmath/math/fmanip/impl/scalbn_float_impl.hpp index ffa9a6a..4a8002d 100644 --- a/include/ccmath/math/fmanip/impl/scalbn_float_impl.hpp +++ b/include/ccmath/math/fmanip/impl/scalbn_float_impl.hpp @@ -30,36 +30,30 @@ namespace ccm::internal tmp *= 0x1p127F; exp -= 127; if (exp > 127) - { + { tmp *= 0x1p127F; - exp -= 127; - if (exp > 127) - { - exp = 127; - } - } + exp -= 127; + if (exp > 127) { exp = 127; } + } } else if (exp < -126) - { + { tmp *= 0x1p-126F * 0x1p24F; - exp += 126 - 24; - if (exp < -126) - { + exp += 126 - 24; + if (exp < -126) + { tmp *= 0x1p-126F * 0x1p24F; - exp += 126 - 24; - if (exp < -126) - { - exp = -126; - } - } - } + exp += 126 - 24; + if (exp < -126) { exp = -126; } + } + } const std::uint32_t bits = ccm::helpers::bit_cast(127 + exp) << 23; - arg = tmp * ccm::helpers::bit_cast(bits); + arg = tmp * ccm::helpers::bit_cast(bits); return arg; } } // namespace impl - } // namespace + } // namespace } // namespace ccm::internal diff --git a/include/ccmath/math/fmanip/impl/scalbn_ldouble_impl.hpp b/include/ccmath/math/fmanip/impl/scalbn_ldouble_impl.hpp index 072a3f3..e8937d8 100644 --- a/include/ccmath/math/fmanip/impl/scalbn_ldouble_impl.hpp +++ b/include/ccmath/math/fmanip/impl/scalbn_ldouble_impl.hpp @@ -42,6 +42,6 @@ namespace ccm::internal return 0; } #endif - } // namespace impl - } // namespace + } // namespace impl +} // namespace } // namespace ccm::internal diff --git a/include/ccmath/math/fmanip/scalbn.hpp b/include/ccmath/math/fmanip/scalbn.hpp index 45e490d..19ae5c1 100644 --- a/include/ccmath/math/fmanip/scalbn.hpp +++ b/include/ccmath/math/fmanip/scalbn.hpp @@ -8,18 +8,18 @@ #pragma once -#include "ccmath/math/fmanip/impl/scalbn_float_impl.hpp" #include "ccmath/math/fmanip/impl/scalbn_double_impl.hpp" +#include "ccmath/math/fmanip/impl/scalbn_float_impl.hpp" #include "ccmath/math/fmanip/impl/scalbn_ldouble_impl.hpp" namespace ccm { template inline constexpr T scalbn(T x, int n) noexcept - { + { if constexpr (std::is_same_v) { return ccm::internal::impl::scalbn_float_impl(x, n); } - if constexpr (std::is_same_v) { return ccm::internal::impl::scalbn_ldouble_impl(x, n); } - return ccm::internal::impl::scalbn_double_impl(x, n); - } + if constexpr (std::is_same_v) { return ccm::internal::impl::scalbn_ldouble_impl(x, n); } + return ccm::internal::impl::scalbn_double_impl(x, n); + } } // namespace ccm diff --git a/include/ccmath/math/lerp.hpp b/include/ccmath/math/lerp.hpp index 1acc085..3360b73 100644 --- a/include/ccmath/math/lerp.hpp +++ b/include/ccmath/math/lerp.hpp @@ -8,49 +8,41 @@ #pragma once -#include "ccmath/math/basic/fma.hpp" #include "ccmath/internal/predef/unlikely.hpp" +#include "ccmath/math/basic/fma.hpp" namespace ccm { template inline constexpr T lerp(T a, T b, T t) noexcept { - // Optimized version of lerp - // https://developer.nvidia.com/blog/lerp-faster-cuda/ - // TODO: Validate this works for all cases of a lerp. - return ccm::fma(t, b, ccm::fma(-t, a, a)); + // Optimized version of lerp + // https://developer.nvidia.com/blog/lerp-faster-cuda/ + // TODO: Validate this works for all cases of a lerp. + return ccm::fma(t, b, ccm::fma(-t, a, a)); } template - inline constexpr typename std::enable_if_t && std::is_arithmetic_v && std::is_arithmetic_v, std::common_type_t > + inline constexpr typename std::enable_if_t && std::is_arithmetic_v && std::is_arithmetic_v, std::common_type_t> lerp(T a, U b, V t) noexcept - { + { typedef typename std::common_type_t result_type; static_assert(!(std::is_same_v && std::is_same_v && std::is_same_v)); return lerp(static_cast(a), static_cast(b), static_cast(t)); - } + } // TODO: Remove this once we confirm the new lerp is 100% stable template - [[deprecated("Do not use ccm::lerp_old it is only being kept as a fallback until ccm::lerp has been validated as conforming to std::lerp")]] - inline constexpr T lerp_old(T a, T b, T t) noexcept + [[deprecated( + "Do not use ccm::lerp_old it is only being kept as a fallback until ccm::lerp has been validated as conforming to std::lerp")]] inline constexpr T + lerp_old(T a, T b, T t) noexcept { - if ((a <= 0 && b >= 0) || (a >= 0 && b <= 0)) - { - return t * b + (1 - t) * a; - } + if ((a <= 0 && b >= 0) || (a >= 0 && b <= 0)) { return t * b + (1 - t) * a; } - if (t == 1) - { - return b; - } + if (t == 1) { return b; } const T x = a + t * (b - a); - if ((t > 1) == (b > a)) - { - return b < x ? x : b; - } + if ((t > 1) == (b > a)) { return b < x ? x : b; } return x < b ? x : b; } diff --git a/include/ccmath/math/nearest/floor.hpp b/include/ccmath/math/nearest/floor.hpp index bbaeb78..08dc457 100644 --- a/include/ccmath/math/nearest/floor.hpp +++ b/include/ccmath/math/nearest/floor.hpp @@ -17,37 +17,31 @@ namespace ccm { /** - * @brief Computes the largest integer value not greater than num. - * @tparam T The type of the number. - * @param num A floating-point or integer value. - * @return If no errors occur, the largest integer value not greater than num, that is ⌊num⌋, is returned. + * @brief Computes the largest integer value not greater than num. + * @tparam T The type of the number. + * @param num A floating-point or integer value. + * @return If no errors occur, the largest integer value not greater than num, that is ⌊num⌋, is returned. */ template inline constexpr T floor(T num) noexcept - { + { if constexpr (std::is_floating_point_v) { // If num is NaN, NaN is returned. - if (ccm::isnan(num)) - { - return std::numeric_limits::quiet_NaN(); - } + if (ccm::isnan(num)) { return std::numeric_limits::quiet_NaN(); } // If num is ±∞ or ±0, num is returned, unmodified. - if (ccm::isinf(num) || num == static_cast(0)) - { - return num; - } - } + if (ccm::isinf(num) || num == static_cast(0)) { return num; } + } // Compute the largest integer value not greater than num. return static_cast(static_cast(num)); - } + } /** - * @brief Computes the largest integer value not greater than num. - * @param num A integer value. - * @return If no errors occur, the largest integer value not greater than num, that is ⌊num⌋, is returned. + * @brief Computes the largest integer value not greater than num. + * @param num A integer value. + * @return If no errors occur, the largest integer value not greater than num, that is ⌊num⌋, is returned. */ template , bool> = true> inline constexpr double floor(Integer num) noexcept @@ -56,24 +50,24 @@ namespace ccm } /** - * @brief Computes the largest integer value not greater than num. - * @param num A floating-point value. - * @return If no errors occur, the largest integer value not greater than num, that is ⌊num⌋, is returned. + * @brief Computes the largest integer value not greater than num. + * @param num A floating-point value. + * @return If no errors occur, the largest integer value not greater than num, that is ⌊num⌋, is returned. */ inline constexpr float floorf(float num) noexcept - { - return floor(num); - } + { + return floor(num); + } /** - * @brief Computes the largest integer value not greater than num. - * @param num A floating-point value. - * @return If no errors occur, the largest integer value not greater than num, that is ⌊num⌋, is returned. + * @brief Computes the largest integer value not greater than num. + * @param num A floating-point value. + * @return If no errors occur, the largest integer value not greater than num, that is ⌊num⌋, is returned. */ inline constexpr double floorl(double num) noexcept - { - return floor(num); - } + { + return floor(num); + } } // namespace ccm /// @ingroup nearest diff --git a/include/ccmath/math/nearest/trunc.hpp b/include/ccmath/math/nearest/trunc.hpp index 2aed146..9ea1b13 100644 --- a/include/ccmath/math/nearest/trunc.hpp +++ b/include/ccmath/math/nearest/trunc.hpp @@ -24,18 +24,18 @@ namespace ccm template , int> = 0> inline constexpr T trunc(T x) noexcept { - // If x is NaN then return Positive NaN or Negative NaN depending on the sign of x - if (ccm::isnan(x)) - { - if (ccm::signbit(x)) { return -std::numeric_limits::quiet_NaN(); } - return std::numeric_limits::quiet_NaN(); - } + // If x is NaN then return Positive NaN or Negative NaN depending on the sign of x + if (ccm::isnan(x)) + { + if (ccm::signbit(x)) { return -std::numeric_limits::quiet_NaN(); } + return std::numeric_limits::quiet_NaN(); + } - // If x == ±∞ then return x - if (x == std::numeric_limits::infinity() || x == -std::numeric_limits::infinity()) { return x; } + // If x == ±∞ then return x + if (x == std::numeric_limits::infinity() || x == -std::numeric_limits::infinity()) { return x; } - // If x == ±0 then return x - if (x == static_cast(0.0)) { return x; } + // If x == ±0 then return x + if (x == static_cast(0.0)) { return x; } return static_cast(static_cast(x)); } diff --git a/include/ccmath/math/power/pow.hpp b/include/ccmath/math/power/pow.hpp index c7d9cf7..37a2626 100644 --- a/include/ccmath/math/power/pow.hpp +++ b/include/ccmath/math/power/pow.hpp @@ -8,19 +8,18 @@ #pragma once +#include +#include #include "ccmath/ccmath.hpp" #include "ccmath/math/exponential/exp.hpp" #include "ccmath/math/exponential/log.hpp" -#include -#include - namespace ccm { template inline constexpr T pow(T x, T y) noexcept - { - return 0; - } + { + return 0; + } } // namespace ccm diff --git a/include/ccmath/numbers.hpp b/include/ccmath/numbers.hpp index 7894f81..2537663 100644 --- a/include/ccmath/numbers.hpp +++ b/include/ccmath/numbers.hpp @@ -59,17 +59,17 @@ namespace ccm::numbers template , bool> = true> inline constexpr Real phi_v = Real{1.618033988749894848204586834365638}; - inline constexpr double e = e_v; - inline constexpr double log2e = log2e_v; - inline constexpr double log10e = log10e_v; - inline constexpr double pi = pi_v; - inline constexpr double inv_pi = inv_pi_v; + inline constexpr double e = e_v; + inline constexpr double log2e = log2e_v; + inline constexpr double log10e = log10e_v; + inline constexpr double pi = pi_v; + inline constexpr double inv_pi = inv_pi_v; inline constexpr double inv_sqrtpi = inv_sqrtpi_v; - inline constexpr double ln2 = ln2_v; - inline constexpr double ln10 = ln10_v; - inline constexpr double sqrt2 = sqrt2_v; - inline constexpr double sqrt3 = sqrt3_v; - inline constexpr double inv_sqrt3 = inv_sqrt3_v; - inline constexpr double egamma = egamma_v; - inline constexpr double phi = phi_v; + inline constexpr double ln2 = ln2_v; + inline constexpr double ln10 = ln10_v; + inline constexpr double sqrt2 = sqrt2_v; + inline constexpr double sqrt3 = sqrt3_v; + inline constexpr double inv_sqrt3 = inv_sqrt3_v; + inline constexpr double egamma = egamma_v; + inline constexpr double phi = phi_v; } // namespace ccm::numbers diff --git a/include/ccmath/power.hpp b/include/ccmath/power.hpp index a6746ca..6778c95 100644 --- a/include/ccmath/power.hpp +++ b/include/ccmath/power.hpp @@ -12,4 +12,3 @@ #include "ccmath/math/power/hypot.hpp" #include "ccmath/math/power/pow.hpp" #include "ccmath/math/power/sqrt.hpp" -