Skip to content

Commit fd06b4f

Browse files
committed
Implements rint
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.
1 parent 6ac5359 commit fd06b4f

File tree

4 files changed

+689
-1
lines changed

4 files changed

+689
-1
lines changed

include/ccmath/math/nearest/rint.hpp

+232
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,239 @@
1010

1111
#pragma once
1212

13+
#include <ccmath/internal/support/fenv/fenv_support.hpp>
14+
#include <ccmath/internal/support/fenv/rounding_mode.hpp>
15+
#include <ccmath/internal/support/fp/directional_rounding_utils.hpp>
16+
#include <ccmath/math/compare/isinf.hpp>
17+
#include <ccmath/math/compare/isnan.hpp>
18+
#include <type_traits>
19+
1320
namespace ccm
1421
{
22+
/**
23+
* @brief Rounds the floating-point argument num to an integer value (in floating-point format), using the current rounding mode. The library provides
24+
* overloads of std::rint for all cv-unqualified floating-point types as the type of the parameter num.
25+
* @tparam T The type of the number.
26+
* @param num A floating-point value.
27+
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
28+
*/
29+
template <class T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
30+
constexpr T rint(T num)
31+
{
32+
if (ccm::isinf(num) || ccm::isnan(num)) { ccm::support::fenv::raise_except_if_required(FE_INVALID); }
33+
const auto rounding_mode{ccm::support::fenv::get_rounding_mode()};
34+
return ccm::support::fp::directional_round(num, rounding_mode);
35+
}
36+
37+
/**
38+
* @brief Additional overloads are provided for all integer types, which are treated as double.
39+
* @tparam Integer The type of the integral value.
40+
* @param num An integral value.
41+
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
42+
*/
43+
template <class Integer, std::enable_if_t<std::is_integral_v<Integer>, bool> = true>
44+
constexpr double rint(Integer num)
45+
{
46+
return static_cast<double>(num);
47+
}
48+
49+
/**
50+
* @brief Additional overloads are provided for all integer types, which are treated as double.
51+
* @tparam Integer The type of the integral value.
52+
* @param num An integral value.
53+
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
54+
*/
55+
template <class Integer, std::enable_if_t<std::is_integral_v<Integer>, bool> = true>
56+
constexpr long lrint(Integer num)
57+
{
58+
return static_cast<long>(num);
59+
}
60+
61+
/**
62+
* @brief Additional overloads are provided for all integer types, which are treated as double.
63+
* @tparam Integer The type of the integral value.
64+
* @param num An integral value.
65+
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
66+
*/
67+
template <class Integer, std::enable_if_t<std::is_integral_v<Integer>, bool> = true>
68+
constexpr long long llrint(Integer num)
69+
{
70+
return static_cast<long long>(num);
71+
}
72+
73+
/**
74+
* @brief Rounds the floating-point argument num to an integer value (in floating-point format), using the current rounding mode. The library provides
75+
* overloads of std::rint for all cv-unqualified floating-point types as the type of the parameter num.
76+
* @param num A floating-point value.
77+
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
78+
*/
79+
constexpr float rint(float num)
80+
{
81+
return ccm::rint<float>(num);
82+
}
83+
84+
/**
85+
* @brief Rounds the floating-point argument num to an integer value (in floating-point format), using the current rounding mode. The library provides
86+
* overloads of std::rint for all cv-unqualified floating-point types as the type of the parameter num.
87+
* @param num A floating-point value.
88+
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
89+
*/
90+
constexpr double rint(double num)
91+
{
92+
return ccm::rint<double>(num);
93+
}
94+
95+
/**
96+
* @brief Rounds the floating-point argument num to an integer value (in floating-point format), using the current rounding mode. The library provides
97+
* overloads of std::rint for all cv-unqualified floating-point types as the type of the parameter num.
98+
* @param num A floating-point value.
99+
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
100+
*/
101+
constexpr long double rint(long double num)
102+
{
103+
return ccm::rint<long double>(num);
104+
}
105+
106+
/**
107+
* @brief Rounds the floating-point argument num to an integer value (in floating-point format), using the current rounding mode. The library provides
108+
* overloads of std::rint for all cv-unqualified floating-point types as the type of the parameter num.
109+
* @param num A floating-point value.
110+
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
111+
*/
112+
constexpr float rintf(float num)
113+
{
114+
return ccm::rint<float>(num);
115+
}
116+
117+
/**
118+
* @brief Rounds the floating-point argument num to an integer value (in floating-point format), using the current rounding mode. The library provides
119+
* overloads of std::rint for all cv-unqualified floating-point types as the type of the parameter num.
120+
* @param num A floating-point value.
121+
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
122+
*/
123+
constexpr long double rintl(long double num)
124+
{
125+
return ccm::rint<long double>(num);
126+
}
127+
128+
/**
129+
* @brief Rounds the floating-point argument num to an integer value, using the current rounding mode. The library provides overloads of std::lrint and
130+
* std::llrint for all cv-unqualified floating-point types as the type of the parameter num.(
131+
* @param num A floating-point value.
132+
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
133+
*/
134+
constexpr long lrint(float num)
135+
{
136+
return static_cast<long>(ccm::rint(num));
137+
}
138+
139+
/**
140+
* @brief Rounds the floating-point argument num to an integer value, using the current rounding mode. The library provides overloads of std::lrint and
141+
* std::llrint for all cv-unqualified floating-point types as the type of the parameter num.(
142+
* @param num A floating-point value.
143+
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
144+
*/
145+
constexpr long lrint(double num)
146+
{
147+
if (ccm::isnan(num))
148+
{
149+
ccm::support::fenv::raise_except_if_required(FE_INVALID);
150+
return std::numeric_limits<long>::min();
151+
}
152+
return static_cast<long>(ccm::rint(num));
153+
}
154+
155+
/**
156+
* @brief Rounds the floating-point argument num to an integer value, using the current rounding mode. The library provides overloads of std::lrint and
157+
* std::llrint for all cv-unqualified floating-point types as the type of the parameter num.(
158+
* @param num A floating-point value.
159+
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
160+
*/
161+
constexpr long lrint(long double num)
162+
{
163+
return static_cast<long>(ccm::rint(num));
164+
}
165+
166+
/**
167+
* @brief Rounds the floating-point argument num to an integer value, using the current rounding mode. The library provides overloads of std::lrint and
168+
* std::llrint for all cv-unqualified floating-point types as the type of the parameter num.(
169+
* @param num A floating-point value.
170+
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
171+
*/
172+
constexpr long lrintf(float num)
173+
{
174+
return static_cast<long>(ccm::rint(num));
175+
}
176+
177+
/**
178+
* @brief Rounds the floating-point argument num to an integer value, using the current rounding mode. The library provides overloads of std::lrint and
179+
* std::llrint for all cv-unqualified floating-point types as the type of the parameter num.(
180+
* @param num A floating-point value.
181+
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
182+
*/
183+
constexpr long lrintl(long double num)
184+
{
185+
return static_cast<long>(ccm::rint(num));
186+
}
187+
188+
/**
189+
* @brief Rounds the floating-point argument num to an integer value, using the current rounding mode. The library provides overloads of std::lrint and
190+
* std::llrint for all cv-unqualified floating-point types as the type of the parameter num.(
191+
* @param num A floating-point value.
192+
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
193+
*/
194+
constexpr long long llrint(float num)
195+
{
196+
return static_cast<long long>(ccm::rint(num));
197+
}
198+
199+
/**
200+
* @brief Rounds the floating-point argument num to an integer value, using the current rounding mode. The library provides overloads of std::lrint and
201+
* std::llrint for all cv-unqualified floating-point types as the type of the parameter num.(
202+
* @param num A floating-point value.
203+
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
204+
*/
205+
constexpr long long llrint(double num)
206+
{
207+
if (ccm::isnan(num))
208+
{
209+
ccm::support::fenv::raise_except_if_required(FE_INVALID);
210+
return std::numeric_limits<long long>::min();
211+
}
212+
return static_cast<long long>(ccm::rint(num));
213+
}
214+
215+
/**
216+
* @brief Rounds the floating-point argument num to an integer value, using the current rounding mode. The library provides overloads of std::lrint and
217+
* std::llrint for all cv-unqualified floating-point types as the type of the parameter num.(
218+
* @param num A floating-point value.
219+
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
220+
*/
221+
constexpr long long llrint(long double num)
222+
{
223+
return static_cast<long long>(ccm::rint(num));
224+
}
225+
226+
/**
227+
* @brief Rounds the floating-point argument num to an integer value, using the current rounding mode. The library provides overloads of std::lrint and
228+
* std::llrint for all cv-unqualified floating-point types as the type of the parameter num.(
229+
* @param num A floating-point value.
230+
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
231+
*/
232+
constexpr long long llrintf(float num)
233+
{
234+
return static_cast<long long>(ccm::rint(num));
235+
}
236+
237+
/**
238+
* @brief Rounds the floating-point argument num to an integer value, using the current rounding mode. The library provides overloads of std::lrint and
239+
* std::llrint for all cv-unqualified floating-point types as the type of the parameter num.(
240+
* @param num A floating-point value.
241+
* @return If no errors occur, the nearest integer value to num, according to the current rounding mode, is returned.
242+
*/
243+
constexpr long long llrintl(long double num)
244+
{
245+
return static_cast<long long>(ccm::rint(num));
246+
}
15247

16248
} // namespace ccm

test/CMakeLists.txt

+22-1
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,32 @@ target_link_libraries(${PROJECT_NAME}-fmanip PRIVATE
9292
)
9393

9494
add_executable(${PROJECT_NAME}-nearest)
95+
set(ROUNDING_MODES
96+
FE_DOWNWARD
97+
FE_UPWARD
98+
FE_TONEAREST
99+
FE_TOWARDZERO
100+
)
101+
set(GENERATED_SOURCES)
102+
foreach(MODE IN LISTS ROUNDING_MODES)
103+
# Set the output file name based on the rounding mode
104+
string(REPLACE "FE_" "" MODE_SUFFIX ${MODE})
105+
set(OUTPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/rounding_${MODE_SUFFIX}.cpp")
106+
set(ROUNDING_MODE "FE_${MODE_SUFFIX}")
107+
# Configure the template file to generate the specific cpp file
108+
configure_file(
109+
${CMAKE_CURRENT_SOURCE_DIR}/nearest/rint_test.cpp.in
110+
${OUTPUT_FILE}
111+
@ONLY
112+
)
113+
list(APPEND GENERATED_SOURCES ${OUTPUT_FILE})
114+
endforeach()
95115
target_sources(${PROJECT_NAME}-nearest PRIVATE
96116
nearest/floor_test.cpp
97117
nearest/nearbyint_test.cpp
98118
nearest/trunc_test.cpp
99-
119+
nearest/rint_test_compile_time.cpp
120+
${GENERATED_SOURCES}
100121
)
101122
target_link_libraries(${PROJECT_NAME}-nearest PRIVATE
102123
ccmath::test

0 commit comments

Comments
 (0)