Skip to content

Commit 23f16ad

Browse files
authored
Merge pull request #328 from toughengineer/int_multiplication_by_power_of_10
Added template overloads for `integer_times_pow10()`
2 parents 04e8e54 + fd98fd6 commit 23f16ad

File tree

6 files changed

+397
-125
lines changed

6 files changed

+397
-125
lines changed

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,23 @@ except `fast_float::integer_times_pow10()` does not report out-of-range errors,
401401
underflows to zero or overflows to infinity when the resulting value is
402402
out of range.
403403

404+
You can use template overloads to get the result converted to different
405+
supported floating-point types: `float`, `double`, etc.
406+
For example, to get result as `float` use
407+
`fast_float::integer_times_pow10<float>()` specialization:
408+
```C++
409+
const uint64_t W = 12345678;
410+
const int Q = 23;
411+
const float result = fast_float::integer_times_pow10<float>(W, Q);
412+
std::cout.precision(9);
413+
std::cout << "float: " << W << " * 10^" << Q << " = " << result << " ("
414+
<< (result == 12345678e23f ? "==" : "!=") << "expected)\n";
415+
```
416+
outputs
417+
```
418+
float: 12345678 * 10^23 = 1.23456782e+30 (==expected)
419+
```
420+
404421
Overloads of `fast_float::integer_times_pow10()` are provided for
405422
signed and unsigned integer types: `int64_t`, `uint64_t`, etc.
406423

include/fast_float/fast_float.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,20 @@ integer_times_pow10(uint64_t mantissa, int decimal_exponent) noexcept;
6363
FASTFLOAT_CONSTEXPR20 inline double
6464
integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept;
6565

66+
/**
67+
* This function is a template overload of `integer_times_pow10()`
68+
* that returns a floating-point value of type `T` that is one of
69+
* supported floating-point types (e.g. `double`, `float`).
70+
*/
71+
template <typename T>
72+
FASTFLOAT_CONSTEXPR20
73+
typename std::enable_if<is_supported_float_type<T>::value, T>::type
74+
integer_times_pow10(uint64_t mantissa, int decimal_exponent) noexcept;
75+
template <typename T>
76+
FASTFLOAT_CONSTEXPR20
77+
typename std::enable_if<is_supported_float_type<T>::value, T>::type
78+
integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept;
79+
6680
/**
6781
* from_chars for integer types.
6882
*/

include/fast_float/float_common.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -198,12 +198,16 @@ using parse_options = parse_options_t<char>;
198198

199199
#ifndef FASTFLOAT_ASSERT
200200
#define FASTFLOAT_ASSERT(x) \
201-
{ ((void)(x)); }
201+
{ \
202+
((void)(x)); \
203+
}
202204
#endif
203205

204206
#ifndef FASTFLOAT_DEBUG_ASSERT
205207
#define FASTFLOAT_DEBUG_ASSERT(x) \
206-
{ ((void)(x)); }
208+
{ \
209+
((void)(x)); \
210+
}
207211
#endif
208212

209213
// rust style `try!()` macro, or `?` operator
@@ -1166,6 +1170,9 @@ static_assert(std::is_same<equiv_uint_t<std::float64_t>, uint64_t>::value,
11661170
static_assert(
11671171
std::numeric_limits<std::float64_t>::is_iec559,
11681172
"std::float64_t must fulfill the requirements of IEC 559 (IEEE 754)");
1173+
1174+
template <>
1175+
struct binary_format<std::float64_t> : public binary_format<double> {};
11691176
#endif // __STDCPP_FLOAT64_T__
11701177

11711178
#ifdef __STDCPP_FLOAT32_T__
@@ -1174,6 +1181,9 @@ static_assert(std::is_same<equiv_uint_t<std::float32_t>, uint32_t>::value,
11741181
static_assert(
11751182
std::numeric_limits<std::float32_t>::is_iec559,
11761183
"std::float32_t must fulfill the requirements of IEC 559 (IEEE 754)");
1184+
1185+
template <>
1186+
struct binary_format<std::float32_t> : public binary_format<float> {};
11771187
#endif // __STDCPP_FLOAT32_T__
11781188

11791189
#ifdef __STDCPP_FLOAT16_T__
@@ -1245,7 +1255,6 @@ constexpr chars_format adjust_for_feature_macros(chars_format fmt) {
12451255
;
12461256
}
12471257
} // namespace detail
1248-
12491258
} // namespace fast_float
12501259

12511260
#endif

include/fast_float/parse_number.h

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -344,44 +344,79 @@ from_chars(UC const *first, UC const *last, T &value, int base) noexcept {
344344
return from_chars_advanced(first, last, value, options);
345345
}
346346

347-
FASTFLOAT_CONSTEXPR20 inline double
348-
integer_times_pow10(uint64_t mantissa, int decimal_exponent) noexcept {
349-
double value;
347+
template <typename T>
348+
FASTFLOAT_CONSTEXPR20
349+
typename std::enable_if<is_supported_float_type<T>::value, T>::type
350+
integer_times_pow10(uint64_t mantissa, int decimal_exponent) noexcept {
351+
T value;
350352
if (clinger_fast_path_impl(mantissa, decimal_exponent, false, value))
351353
return value;
352354

353355
adjusted_mantissa am =
354-
compute_float<binary_format<double>>(decimal_exponent, mantissa);
356+
compute_float<binary_format<T>>(decimal_exponent, mantissa);
355357
to_float(false, am, value);
356358
return value;
357359
}
358360

359-
FASTFLOAT_CONSTEXPR20 inline double
360-
integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept {
361+
template <typename T>
362+
FASTFLOAT_CONSTEXPR20
363+
typename std::enable_if<is_supported_float_type<T>::value, T>::type
364+
integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept {
361365
const bool is_negative = mantissa < 0;
362366
const uint64_t m = static_cast<uint64_t>(is_negative ? -mantissa : mantissa);
363367

364-
double value;
368+
T value;
365369
if (clinger_fast_path_impl(m, decimal_exponent, is_negative, value))
366370
return value;
367371

368-
adjusted_mantissa am =
369-
compute_float<binary_format<double>>(decimal_exponent, m);
372+
adjusted_mantissa am = compute_float<binary_format<T>>(decimal_exponent, m);
370373
to_float(is_negative, am, value);
371374
return value;
372375
}
373376

377+
FASTFLOAT_CONSTEXPR20 inline double
378+
integer_times_pow10(uint64_t mantissa, int decimal_exponent) noexcept {
379+
return integer_times_pow10<double>(mantissa, decimal_exponent);
380+
}
381+
382+
FASTFLOAT_CONSTEXPR20 inline double
383+
integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept {
384+
return integer_times_pow10<double>(mantissa, decimal_exponent);
385+
}
386+
374387
// the following overloads are here to avoid surprising ambiguity for int,
375388
// unsigned, etc.
389+
template <typename T, typename Int>
390+
FASTFLOAT_CONSTEXPR20
391+
typename std::enable_if<is_supported_float_type<T>::value &&
392+
std::is_integral<Int>::value &&
393+
!std::is_signed<Int>::value,
394+
T>::type
395+
integer_times_pow10(Int mantissa, int decimal_exponent) noexcept {
396+
return integer_times_pow10<T>(static_cast<uint64_t>(mantissa),
397+
decimal_exponent);
398+
}
399+
400+
template <typename T, typename Int>
401+
FASTFLOAT_CONSTEXPR20
402+
typename std::enable_if<is_supported_float_type<T>::value &&
403+
std::is_integral<Int>::value &&
404+
std::is_signed<Int>::value,
405+
T>::type
406+
integer_times_pow10(Int mantissa, int decimal_exponent) noexcept {
407+
return integer_times_pow10<T>(static_cast<int64_t>(mantissa),
408+
decimal_exponent);
409+
}
410+
376411
template <typename Int>
377-
FASTFLOAT_CONSTEXPR20 inline typename std::enable_if<
412+
FASTFLOAT_CONSTEXPR20 typename std::enable_if<
378413
std::is_integral<Int>::value && !std::is_signed<Int>::value, double>::type
379414
integer_times_pow10(Int mantissa, int decimal_exponent) noexcept {
380415
return integer_times_pow10(static_cast<uint64_t>(mantissa), decimal_exponent);
381416
}
382417

383418
template <typename Int>
384-
FASTFLOAT_CONSTEXPR20 inline typename std::enable_if<
419+
FASTFLOAT_CONSTEXPR20 typename std::enable_if<
385420
std::is_integral<Int>::value && std::is_signed<Int>::value, double>::type
386421
integer_times_pow10(Int mantissa, int decimal_exponent) noexcept {
387422
return integer_times_pow10(static_cast<int64_t>(mantissa), decimal_exponent);

0 commit comments

Comments
 (0)