Skip to content

Commit 70fb6cc

Browse files
authored
Merge pull request #1782 from evoskuil/master
Add bool to_integer(Integer& out, Float value).
2 parents 76612b1 + 09ffd21 commit 70fb6cc

2 files changed

Lines changed: 31 additions & 0 deletions

File tree

include/bitcoin/system/impl/math/cast.ipp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#ifndef LIBBITCOIN_SYSTEM_MATH_CAST_IPP
2020
#define LIBBITCOIN_SYSTEM_MATH_CAST_IPP
2121

22+
#include <cmath>
2223
#include <bitcoin/system/define.hpp>
2324

2425
namespace libbitcoin {
@@ -209,6 +210,30 @@ constexpr Unsigned to_unsigned(Unsigned value) NOEXCEPT
209210
// Floating point casts.
210211
// ----------------------------------------------------------------------------
211212

213+
template <typename Integer, typename Float,
214+
if_integral_integer<Integer>,
215+
if_floating_point<Float>>
216+
constexpr bool to_integer(Integer& out, Float value) NOEXCEPT
217+
{
218+
if (!std::isfinite(value))
219+
return false;
220+
221+
Float integer{};
222+
const Float fractional = std::modf(value, &integer);
223+
if (fractional != 0.0)
224+
return false;
225+
226+
if (integer > static_cast<Float>(std::numeric_limits<Integer>::max()) ||
227+
integer < static_cast<Float>(std::numeric_limits<Integer>::min()))
228+
return false;
229+
230+
// Floating point conversion in c++ requires explicit or implicit cast.
231+
BC_PUSH_WARNING(NO_CASTS_FOR_ARITHMETIC_CONVERSION)
232+
out = static_cast<Integer>(integer);
233+
BC_POP_WARNING()
234+
return true;
235+
}
236+
212237
template <typename Integer, typename Float,
213238
if_integral_integer<Integer>,
214239
if_floating_point<Float>>

include/bitcoin/system/math/cast.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,12 @@ constexpr Unsigned to_unsigned(Unsigned value) NOEXCEPT;
142142
/// Floating point casts.
143143
/// ---------------------------------------------------------------------------
144144

145+
/// Cast floating point to integral integer, overflow guarded.
146+
template <typename Integer = size_t, typename Float,
147+
if_integral_integer<Integer> = true,
148+
if_floating_point<Float> = true>
149+
constexpr bool to_integer(Integer& out, Float value) NOEXCEPT;
150+
145151
/// Cast floating point to integral integer, overflow unguarded.
146152
template <typename Integer = size_t, typename Float,
147153
if_integral_integer<Integer> = true,

0 commit comments

Comments
 (0)