Skip to content

Commit

Permalink
Implements rint
Browse files Browse the repository at this point in the history
Functions implemented:

- ccm::rint(float)
- ccm::rint(double)
- ccm::rint(long double)
- ccm::rintl(long double)
- ccm::rintf(float)

- ccm::lrint(float)
- ccm::lrint(double)
- ccm::lrint(long double)
- ccm::lrintl(long double)
- ccm::lrintf(float)

- ccm::llrint(float)
- ccm::llrint(double)
- ccm::llrint(long double)
- ccm::llrintl(long double)
- ccm::llrintf(long double)

Tests written for:

- Common and edge case conditions for `float`, `double`, and `long
  double` inputs.
- Assert that FE_INVALID is raised for +/- infinity values and NaN
  values.
- Asserts that functions can be evaluated at compile time.
  • Loading branch information
khurd21 committed Sep 1, 2024
1 parent 6ac5359 commit 719e2dd
Show file tree
Hide file tree
Showing 3 changed files with 641 additions and 0 deletions.
232 changes: 232 additions & 0 deletions include/ccmath/math/nearest/rint.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,239 @@

#pragma once

#include <ccmath/internal/support/fenv/fenv_support.hpp>
#include <ccmath/internal/support/fenv/rounding_mode.hpp>
#include <ccmath/internal/support/fp/directional_rounding_utils.hpp>
#include <ccmath/math/compare/isinf.hpp>
#include <ccmath/math/compare/isnan.hpp>
#include <type_traits>

namespace ccm
{
/**
* @brief Rounds the floating-point argument num to an integer value (in floating-point format), using the current rounding mode. The library provides
* overloads of std::rint for all cv-unqualified floating-point types as the type of the parameter num.
* @tparam T The type of the number.
* @param num A floating-point value.
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
*/
template <class T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
constexpr T rint(T num)
{
if (ccm::isinf(num) || ccm::isnan(num)) { ccm::support::fenv::raise_except_if_required(FE_INVALID); }
constexpr auto rounding_mode{ccm::support::fenv::get_rounding_mode()};
return ccm::support::fp::directional_round(num, rounding_mode);
}

/**
* @brief Additional overloads are provided for all integer types, which are treated as double.
* @tparam Integer The type of the integral value.
* @param num An integral value.
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
*/
template <class Integer, std::enable_if_t<std::is_integral_v<Integer>, bool> = true>
constexpr double rint(Integer num)
{
return static_cast<double>(num);
}

/**
* @brief Additional overloads are provided for all integer types, which are treated as double.
* @tparam Integer The type of the integral value.
* @param num An integral value.
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
*/
template <class Integer, std::enable_if_t<std::is_integral_v<Integer>, bool> = true>
constexpr long lrint(Integer num)
{
return static_cast<long>(num);
}

/**
* @brief Additional overloads are provided for all integer types, which are treated as double.
* @tparam Integer The type of the integral value.
* @param num An integral value.
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
*/
template <class Integer, std::enable_if_t<std::is_integral_v<Integer>, bool> = true>
constexpr long long llrint(Integer num)
{
return static_cast<long long>(num);
}

/**
* @brief Rounds the floating-point argument num to an integer value (in floating-point format), using the current rounding mode. The library provides
* overloads of std::rint for all cv-unqualified floating-point types as the type of the parameter num.
* @param num A floating-point value.
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
*/
constexpr float rint(float num)
{
return ccm::rint<float>(num);
}

/**
* @brief Rounds the floating-point argument num to an integer value (in floating-point format), using the current rounding mode. The library provides
* overloads of std::rint for all cv-unqualified floating-point types as the type of the parameter num.
* @param num A floating-point value.
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
*/
constexpr double rint(double num)
{
return ccm::rint<double>(num);
}

/**
* @brief Rounds the floating-point argument num to an integer value (in floating-point format), using the current rounding mode. The library provides
* overloads of std::rint for all cv-unqualified floating-point types as the type of the parameter num.
* @param num A floating-point value.
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
*/
constexpr long double rint(long double num)
{
return ccm::rint<long double>(num);
}

/**
* @brief Rounds the floating-point argument num to an integer value (in floating-point format), using the current rounding mode. The library provides
* overloads of std::rint for all cv-unqualified floating-point types as the type of the parameter num.
* @param num A floating-point value.
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
*/
constexpr float rintf(float num)
{
return ccm::rint<float>(num);
}

/**
* @brief Rounds the floating-point argument num to an integer value (in floating-point format), using the current rounding mode. The library provides
* overloads of std::rint for all cv-unqualified floating-point types as the type of the parameter num.
* @param num A floating-point value.
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
*/
constexpr long double rintl(long double num)
{
return ccm::rint<long double>(num);
}

/**
* @brief Rounds the floating-point argument num to an integer value, using the current rounding mode. The library provides overloads of std::lrint and
* std::llrint for all cv-unqualified floating-point types as the type of the parameter num.(
* @param num A floating-point value.
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
*/
constexpr long lrint(float num)
{
return static_cast<long>(ccm::rint(num));
}

/**
* @brief Rounds the floating-point argument num to an integer value, using the current rounding mode. The library provides overloads of std::lrint and
* std::llrint for all cv-unqualified floating-point types as the type of the parameter num.(
* @param num A floating-point value.
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
*/
constexpr long lrint(double num)
{
if (ccm::isnan(num))
{
ccm::support::fenv::raise_except_if_required(FE_INVALID);
return std::numeric_limits<long>::min();
}
return static_cast<long>(ccm::rint(num));
}

/**
* @brief Rounds the floating-point argument num to an integer value, using the current rounding mode. The library provides overloads of std::lrint and
* std::llrint for all cv-unqualified floating-point types as the type of the parameter num.(
* @param num A floating-point value.
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
*/
constexpr long lrint(long double num)
{
return static_cast<long>(ccm::rint(num));
}

/**
* @brief Rounds the floating-point argument num to an integer value, using the current rounding mode. The library provides overloads of std::lrint and
* std::llrint for all cv-unqualified floating-point types as the type of the parameter num.(
* @param num A floating-point value.
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
*/
constexpr long lrintf(float num)
{
return static_cast<long>(ccm::rint(num));
}

/**
* @brief Rounds the floating-point argument num to an integer value, using the current rounding mode. The library provides overloads of std::lrint and
* std::llrint for all cv-unqualified floating-point types as the type of the parameter num.(
* @param num A floating-point value.
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
*/
constexpr long lrintl(long double num)
{
return static_cast<long>(ccm::rint(num));
}

/**
* @brief Rounds the floating-point argument num to an integer value, using the current rounding mode. The library provides overloads of std::lrint and
* std::llrint for all cv-unqualified floating-point types as the type of the parameter num.(
* @param num A floating-point value.
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
*/
constexpr long long llrint(float num)
{
return static_cast<long long>(ccm::rint(num));
}

/**
* @brief Rounds the floating-point argument num to an integer value, using the current rounding mode. The library provides overloads of std::lrint and
* std::llrint for all cv-unqualified floating-point types as the type of the parameter num.(
* @param num A floating-point value.
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
*/
constexpr long long llrint(double num)
{
if (ccm::isnan(num))
{
ccm::support::fenv::raise_except_if_required(FE_INVALID);
return std::numeric_limits<long long>::min();
}
return static_cast<long long>(ccm::rint(num));
}

/**
* @brief Rounds the floating-point argument num to an integer value, using the current rounding mode. The library provides overloads of std::lrint and
* std::llrint for all cv-unqualified floating-point types as the type of the parameter num.(
* @param num A floating-point value.
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
*/
constexpr long long llrint(long double num)
{
return static_cast<long long>(ccm::rint(num));
}

/**
* @brief Rounds the floating-point argument num to an integer value, using the current rounding mode. The library provides overloads of std::lrint and
* std::llrint for all cv-unqualified floating-point types as the type of the parameter num.(
* @param num A floating-point value.
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
*/
constexpr long long llrintf(float num)
{
return static_cast<long long>(ccm::rint(num));
}

/**
* @brief Rounds the floating-point argument num to an integer value, using the current rounding mode. The library provides overloads of std::lrint and
* std::llrint for all cv-unqualified floating-point types as the type of the parameter num.(
* @param num A floating-point value.
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
*/
constexpr long long llrintl(long double num)
{
return static_cast<long long>(ccm::rint(num));
}

} // namespace ccm
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ add_executable(${PROJECT_NAME}-nearest)
target_sources(${PROJECT_NAME}-nearest PRIVATE
nearest/floor_test.cpp
nearest/nearbyint_test.cpp
nearest/rint_test.cpp
nearest/trunc_test.cpp

)
Expand Down
Loading

0 comments on commit 719e2dd

Please sign in to comment.