Merge pull request #328 from toughengineer/int_multiplication_by_power_of_10

Added template overloads for `integer_times_pow10()`
diff --git a/README.md b/README.md
index b3dba46..4ad0ca8 100644
--- a/README.md
+++ b/README.md
@@ -401,6 +401,23 @@
 underflows to zero or overflows to infinity when the resulting value is
 out of range.
 
+You can use template overloads to get the result converted to different
+supported floating-point types: `float`, `double`, etc.
+For example, to get result as `float` use
+`fast_float::integer_times_pow10<float>()` specialization:
+```C++
+const uint64_t W = 12345678;
+const int Q = 23;
+const float result = fast_float::integer_times_pow10<float>(W, Q);
+std::cout.precision(9);
+std::cout << "float: " << W << " * 10^" << Q << " = " << result << " ("
+          << (result == 12345678e23f ? "==" : "!=") << "expected)\n";
+```
+outputs
+```
+float: 12345678 * 10^23 = 1.23456782e+30 (==expected)
+```
+
 Overloads of `fast_float::integer_times_pow10()` are provided for
 signed and unsigned integer types: `int64_t`, `uint64_t`, etc.
 
diff --git a/include/fast_float/fast_float.h b/include/fast_float/fast_float.h
index a190d7c..eb822f5 100644
--- a/include/fast_float/fast_float.h
+++ b/include/fast_float/fast_float.h
@@ -64,6 +64,20 @@
 integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept;
 
 /**
+ * This function is a template overload of `integer_times_pow10()`
+ * that returns a floating-point value of type `T` that is one of
+ * supported floating-point types (e.g. `double`, `float`).
+ */
+template <typename T>
+FASTFLOAT_CONSTEXPR20
+    typename std::enable_if<is_supported_float_type<T>::value, T>::type
+    integer_times_pow10(uint64_t mantissa, int decimal_exponent) noexcept;
+template <typename T>
+FASTFLOAT_CONSTEXPR20
+    typename std::enable_if<is_supported_float_type<T>::value, T>::type
+    integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept;
+
+/**
  * from_chars for integer types.
  */
 template <typename T, typename UC = char,
diff --git a/include/fast_float/float_common.h b/include/fast_float/float_common.h
index 62d199c..34eaa01 100644
--- a/include/fast_float/float_common.h
+++ b/include/fast_float/float_common.h
@@ -198,12 +198,16 @@
 
 #ifndef FASTFLOAT_ASSERT
 #define FASTFLOAT_ASSERT(x)                                                    \
-  { ((void)(x)); }
+  {                                                                            \
+    ((void)(x));                                                               \
+  }
 #endif
 
 #ifndef FASTFLOAT_DEBUG_ASSERT
 #define FASTFLOAT_DEBUG_ASSERT(x)                                              \
-  { ((void)(x)); }
+  {                                                                            \
+    ((void)(x));                                                               \
+  }
 #endif
 
 // rust style `try!()` macro, or `?` operator
@@ -1166,6 +1170,9 @@
 static_assert(
     std::numeric_limits<std::float64_t>::is_iec559,
     "std::float64_t must fulfill the requirements of IEC 559 (IEEE 754)");
+
+template <>
+struct binary_format<std::float64_t> : public binary_format<double> {};
 #endif // __STDCPP_FLOAT64_T__
 
 #ifdef __STDCPP_FLOAT32_T__
@@ -1174,6 +1181,9 @@
 static_assert(
     std::numeric_limits<std::float32_t>::is_iec559,
     "std::float32_t must fulfill the requirements of IEC 559 (IEEE 754)");
+
+template <>
+struct binary_format<std::float32_t> : public binary_format<float> {};
 #endif // __STDCPP_FLOAT32_T__
 
 #ifdef __STDCPP_FLOAT16_T__
@@ -1245,7 +1255,6 @@
       ;
 }
 } // namespace detail
-
 } // namespace fast_float
 
 #endif
diff --git a/include/fast_float/parse_number.h b/include/fast_float/parse_number.h
index a44fef0..d453c14 100644
--- a/include/fast_float/parse_number.h
+++ b/include/fast_float/parse_number.h
@@ -344,44 +344,79 @@
   return from_chars_advanced(first, last, value, options);
 }
 
-FASTFLOAT_CONSTEXPR20 inline double
-integer_times_pow10(uint64_t mantissa, int decimal_exponent) noexcept {
-  double value;
+template <typename T>
+FASTFLOAT_CONSTEXPR20
+    typename std::enable_if<is_supported_float_type<T>::value, T>::type
+    integer_times_pow10(uint64_t mantissa, int decimal_exponent) noexcept {
+  T value;
   if (clinger_fast_path_impl(mantissa, decimal_exponent, false, value))
     return value;
 
   adjusted_mantissa am =
-      compute_float<binary_format<double>>(decimal_exponent, mantissa);
+      compute_float<binary_format<T>>(decimal_exponent, mantissa);
   to_float(false, am, value);
   return value;
 }
 
-FASTFLOAT_CONSTEXPR20 inline double
-integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept {
+template <typename T>
+FASTFLOAT_CONSTEXPR20
+    typename std::enable_if<is_supported_float_type<T>::value, T>::type
+    integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept {
   const bool is_negative = mantissa < 0;
   const uint64_t m = static_cast<uint64_t>(is_negative ? -mantissa : mantissa);
 
-  double value;
+  T value;
   if (clinger_fast_path_impl(m, decimal_exponent, is_negative, value))
     return value;
 
-  adjusted_mantissa am =
-      compute_float<binary_format<double>>(decimal_exponent, m);
+  adjusted_mantissa am = compute_float<binary_format<T>>(decimal_exponent, m);
   to_float(is_negative, am, value);
   return value;
 }
 
+FASTFLOAT_CONSTEXPR20 inline double
+integer_times_pow10(uint64_t mantissa, int decimal_exponent) noexcept {
+  return integer_times_pow10<double>(mantissa, decimal_exponent);
+}
+
+FASTFLOAT_CONSTEXPR20 inline double
+integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept {
+  return integer_times_pow10<double>(mantissa, decimal_exponent);
+}
+
 // the following overloads are here to avoid surprising ambiguity for int,
 // unsigned, etc.
+template <typename T, typename Int>
+FASTFLOAT_CONSTEXPR20
+    typename std::enable_if<is_supported_float_type<T>::value &&
+                                std::is_integral<Int>::value &&
+                                !std::is_signed<Int>::value,
+                            T>::type
+    integer_times_pow10(Int mantissa, int decimal_exponent) noexcept {
+  return integer_times_pow10<T>(static_cast<uint64_t>(mantissa),
+                                decimal_exponent);
+}
+
+template <typename T, typename Int>
+FASTFLOAT_CONSTEXPR20
+    typename std::enable_if<is_supported_float_type<T>::value &&
+                                std::is_integral<Int>::value &&
+                                std::is_signed<Int>::value,
+                            T>::type
+    integer_times_pow10(Int mantissa, int decimal_exponent) noexcept {
+  return integer_times_pow10<T>(static_cast<int64_t>(mantissa),
+                                decimal_exponent);
+}
+
 template <typename Int>
-FASTFLOAT_CONSTEXPR20 inline typename std::enable_if<
+FASTFLOAT_CONSTEXPR20 typename std::enable_if<
     std::is_integral<Int>::value && !std::is_signed<Int>::value, double>::type
 integer_times_pow10(Int mantissa, int decimal_exponent) noexcept {
   return integer_times_pow10(static_cast<uint64_t>(mantissa), decimal_exponent);
 }
 
 template <typename Int>
-FASTFLOAT_CONSTEXPR20 inline typename std::enable_if<
+FASTFLOAT_CONSTEXPR20 typename std::enable_if<
     std::is_integral<Int>::value && std::is_signed<Int>::value, double>::type
 integer_times_pow10(Int mantissa, int decimal_exponent) noexcept {
   return integer_times_pow10(static_cast<int64_t>(mantissa), decimal_exponent);
diff --git a/tests/basictest.cpp b/tests/basictest.cpp
index dc11752..15ab344 100644
--- a/tests/basictest.cpp
+++ b/tests/basictest.cpp
@@ -1507,9 +1507,20 @@
          std::errc::result_out_of_range);
   verify("3.5028234666e38", std::numeric_limits<float>::infinity(),
          std::errc::result_out_of_range);
+  // FLT_MAX + 0.00000007e38
+  verify("3.40282357e38", std::numeric_limits<float>::infinity(),
+         std::errc::result_out_of_range);
+  // FLT_MAX + 0.0000001e38
+  verify("3.4028236e38", std::numeric_limits<float>::infinity(),
+         std::errc::result_out_of_range);
 }
 
 TEST_CASE("float.general") {
+  // FLT_TRUE_MIN / 2
+  verify("0.7006492e-45", 0.f, std::errc::result_out_of_range);
+  // FLT_TRUE_MIN / 2 + 0.0000001e-45
+  verify("0.7006493e-45", 0x1p-149f);
+
   // max
   verify("340282346638528859811704183484516925440", 0x1.fffffep+127f);
   // -max
@@ -2086,12 +2097,11 @@
 }
 #endif
 
-template <typename Int>
-void verify_integer_multiplication_by_power_of_10(Int mantissa,
-                                                  int decimal_exponent,
-                                                  double expected) {
-  const double actual =
-      fast_float::integer_times_pow10(mantissa, decimal_exponent);
+template <typename Int, typename T, typename U>
+void verify_integer_times_pow10_result(Int mantissa, int decimal_exponent,
+                                       T actual, U expected) {
+  static_assert(std::is_same<T, U>::value,
+                "expected and actual types must match");
 
   INFO("m * 10^e=" << mantissa << " * 10^" << decimal_exponent
                    << "\n"
@@ -2105,45 +2115,173 @@
   CHECK_EQ(actual, expected);
 }
 
-template <typename Int>
-void verify_integer_multiplication_by_power_of_10(Int mantissa,
-                                                  int decimal_exponent) {
+template <typename T, typename Int>
+T calculate_integer_times_pow10_expected_result(Int mantissa,
+                                                int decimal_exponent) {
   std::string constructed_string =
       std::to_string(mantissa) + "e" + std::to_string(decimal_exponent);
-  double expected_result;
+  T expected_result;
   const auto result = fast_float::from_chars(
       constructed_string.data(),
       constructed_string.data() + constructed_string.size(), expected_result);
   if (result.ec != std::errc())
     INFO("Failed to parse: " << constructed_string);
-  verify_integer_multiplication_by_power_of_10(mantissa, decimal_exponent,
-                                               expected_result);
+  return expected_result;
 }
 
+template <typename Int>
+void verify_integer_times_pow10_dflt(Int mantissa, int decimal_exponent,
+                                     double expected) {
+  static_assert(std::is_integral<Int>::value);
+
+  // the "default" overload
+  const double actual =
+      fast_float::integer_times_pow10(mantissa, decimal_exponent);
+
+  verify_integer_times_pow10_result(mantissa, decimal_exponent, actual,
+                                    expected);
+}
+
+template <typename Int>
+void verify_integer_times_pow10_dflt(Int mantissa, int decimal_exponent) {
+  static_assert(std::is_integral<Int>::value);
+
+  const auto expected_result =
+      calculate_integer_times_pow10_expected_result<double>(mantissa,
+                                                            decimal_exponent);
+
+  verify_integer_times_pow10_dflt(mantissa, decimal_exponent, expected_result);
+}
+
+template <typename T, typename Int>
+void verify_integer_times_pow10(Int mantissa, int decimal_exponent,
+                                T expected) {
+  static_assert(std::is_floating_point<T>::value);
+  static_assert(std::is_integral<Int>::value);
+
+  // explicit specialization
+  const auto actual =
+      fast_float::integer_times_pow10<T>(mantissa, decimal_exponent);
+
+  verify_integer_times_pow10_result(mantissa, decimal_exponent, actual,
+                                    expected);
+}
+
+template <typename T, typename Int>
+void verify_integer_times_pow10(Int mantissa, int decimal_exponent) {
+  static_assert(std::is_floating_point<T>::value);
+  static_assert(std::is_integral<Int>::value);
+
+  const auto expected_result = calculate_integer_times_pow10_expected_result<T>(
+      mantissa, decimal_exponent);
+
+  verify_integer_times_pow10(mantissa, decimal_exponent, expected_result);
+}
+
+namespace all_supported_types {
+template <typename Int>
+void verify_integer_times_pow10(Int mantissa, int decimal_exponent) {
+  static_assert(std::is_integral<Int>::value);
+
+  // verify the "default" overload
+  verify_integer_times_pow10_dflt(mantissa, decimal_exponent);
+
+  // verify explicit specializations
+  ::verify_integer_times_pow10<double>(mantissa, decimal_exponent);
+  ::verify_integer_times_pow10<float>(mantissa, decimal_exponent);
+#if defined(__STDCPP_FLOAT64_T__)
+  ::verify_integer_times_pow10<std::float64_t>(mantissa, decimal_exponent);
+#endif
+#if defined(__STDCPP_FLOAT32_T__)
+  ::verify_integer_times_pow10<std::float32_t>(mantissa, decimal_exponent);
+#endif
+#if defined(__STDCPP_FLOAT16_T__)
+  ::verify_integer_times_pow10<std::float16_t>(mantissa, decimal_exponent);
+#endif
+#if defined(__STDCPP_BFLOAT16_T__)
+  ::verify_integer_times_pow10<std::bfloat16_t>(mantissa, decimal_exponent);
+#endif
+}
+} // namespace all_supported_types
+
 TEST_CASE("integer_times_pow10") {
-  // explicitly verifying API with different types of integers
-  verify_integer_multiplication_by_power_of_10<int8_t>(31, -1, 3.1);
-  verify_integer_multiplication_by_power_of_10<int8_t>(-31, -1, -3.1);
-  verify_integer_multiplication_by_power_of_10<uint8_t>(31, -1, 3.1);
-  verify_integer_multiplication_by_power_of_10<int16_t>(31415, -4, 3.1415);
-  verify_integer_multiplication_by_power_of_10<int16_t>(-31415, -4, -3.1415);
-  verify_integer_multiplication_by_power_of_10<uint16_t>(31415, -4, 3.1415);
-  verify_integer_multiplication_by_power_of_10<int32_t>(314159265, -8,
-                                                        3.14159265);
-  verify_integer_multiplication_by_power_of_10<int32_t>(-314159265, -8,
-                                                        -3.14159265);
-  verify_integer_multiplication_by_power_of_10<uint32_t>(3141592653, -9,
-                                                         3.141592653);
-  verify_integer_multiplication_by_power_of_10<int64_t>(
+  /* explicitly verifying API with different types of integers */
+  // double (the "default" overload)
+  verify_integer_times_pow10_dflt<int8_t>(31, -1, 3.1);
+  verify_integer_times_pow10_dflt<int8_t>(-31, -1, -3.1);
+  verify_integer_times_pow10_dflt<uint8_t>(31, -1, 3.1);
+  verify_integer_times_pow10_dflt<int16_t>(31415, -4, 3.1415);
+  verify_integer_times_pow10_dflt<int16_t>(-31415, -4, -3.1415);
+  verify_integer_times_pow10_dflt<uint16_t>(31415, -4, 3.1415);
+  verify_integer_times_pow10_dflt<int32_t>(314159265, -8, 3.14159265);
+  verify_integer_times_pow10_dflt<int32_t>(-314159265, -8, -3.14159265);
+  verify_integer_times_pow10_dflt<uint32_t>(3141592653, -9, 3.141592653);
+  verify_integer_times_pow10_dflt<long>(314159265, -8, 3.14159265);
+  verify_integer_times_pow10_dflt<long>(-314159265, -8, -3.14159265);
+  verify_integer_times_pow10_dflt<unsigned long>(3141592653, -9, 3.141592653);
+  verify_integer_times_pow10_dflt<int64_t>(3141592653589793238, -18,
+                                           3.141592653589793238);
+  verify_integer_times_pow10_dflt<int64_t>(-3141592653589793238, -18,
+                                           -3.141592653589793238);
+  verify_integer_times_pow10_dflt<uint64_t>(3141592653589793238, -18,
+                                            3.141592653589793238);
+  verify_integer_times_pow10_dflt<long long>(3141592653589793238, -18,
+                                             3.141592653589793238);
+  verify_integer_times_pow10_dflt<long long>(-3141592653589793238, -18,
+                                             -3.141592653589793238);
+  verify_integer_times_pow10_dflt<unsigned long long>(3141592653589793238, -18,
+                                                      3.141592653589793238);
+  // double (explicit specialization)
+  verify_integer_times_pow10<double, int8_t>(31, -1, 3.1);
+  verify_integer_times_pow10<double, int8_t>(-31, -1, -3.1);
+  verify_integer_times_pow10<double, uint8_t>(31, -1, 3.1);
+  verify_integer_times_pow10<double, int16_t>(31415, -4, 3.1415);
+  verify_integer_times_pow10<double, int16_t>(-31415, -4, -3.1415);
+  verify_integer_times_pow10<double, uint16_t>(31415, -4, 3.1415);
+  verify_integer_times_pow10<double, int32_t>(314159265, -8, 3.14159265);
+  verify_integer_times_pow10<double, int32_t>(-314159265, -8, -3.14159265);
+  verify_integer_times_pow10<double, uint32_t>(3141592653, -9, 3.141592653);
+  verify_integer_times_pow10<double, long>(314159265, -8, 3.14159265);
+  verify_integer_times_pow10<double, long>(-314159265, -8, -3.14159265);
+  verify_integer_times_pow10<double, unsigned long>(3141592653, -9,
+                                                    3.141592653);
+  verify_integer_times_pow10<double, int64_t>(3141592653589793238, -18,
+                                              3.141592653589793238);
+  verify_integer_times_pow10<double, int64_t>(-3141592653589793238, -18,
+                                              -3.141592653589793238);
+  verify_integer_times_pow10<double, uint64_t>(3141592653589793238, -18,
+                                               3.141592653589793238);
+  verify_integer_times_pow10<double, long long>(3141592653589793238, -18,
+                                                3.141592653589793238);
+  verify_integer_times_pow10<double, long long>(-3141592653589793238, -18,
+                                                -3.141592653589793238);
+  verify_integer_times_pow10<double, unsigned long long>(
       3141592653589793238, -18, 3.141592653589793238);
-  verify_integer_multiplication_by_power_of_10<int64_t>(
-      -3141592653589793238, -18, -3.141592653589793238);
-  verify_integer_multiplication_by_power_of_10<uint64_t>(
-      3141592653589793238, -18, 3.141592653589793238);
-  verify_integer_multiplication_by_power_of_10<long long>(
-      -3141592653589793238, -18, -3.141592653589793238);
-  verify_integer_multiplication_by_power_of_10<unsigned long long>(
-      3141592653589793238, -18, 3.141592653589793238);
+  // float (explicit specialization)
+  verify_integer_times_pow10<float, int8_t>(31, -1, 3.1f);
+  verify_integer_times_pow10<float, int8_t>(-31, -1, -3.1f);
+  verify_integer_times_pow10<float, uint8_t>(31, -1, 3.1f);
+  verify_integer_times_pow10<float, int16_t>(31415, -4, 3.1415f);
+  verify_integer_times_pow10<float, int16_t>(-31415, -4, -3.1415f);
+  verify_integer_times_pow10<float, uint16_t>(31415, -4, 3.1415f);
+  verify_integer_times_pow10<float, int32_t>(314159265, -8, 3.14159265f);
+  verify_integer_times_pow10<float, int32_t>(-314159265, -8, -3.14159265f);
+  verify_integer_times_pow10<float, uint32_t>(3141592653, -9, 3.14159265f);
+  verify_integer_times_pow10<float, long>(314159265, -8, 3.14159265f);
+  verify_integer_times_pow10<float, long>(-314159265, -8, -3.14159265f);
+  verify_integer_times_pow10<float, unsigned long>(3141592653, -9, 3.14159265f);
+  verify_integer_times_pow10<float, int64_t>(3141592653589793238, -18,
+                                             3.141592653589793238f);
+  verify_integer_times_pow10<float, int64_t>(-3141592653589793238, -18,
+                                             -3.141592653589793238f);
+  verify_integer_times_pow10<float, uint64_t>(3141592653589793238, -18,
+                                              3.141592653589793238f);
+  verify_integer_times_pow10<float, long long>(3141592653589793238, -18,
+                                               3.141592653589793238f);
+  verify_integer_times_pow10<float, long long>(-3141592653589793238, -18,
+                                               -3.141592653589793238f);
+  verify_integer_times_pow10<float, unsigned long long>(
+      3141592653589793238, -18, 3.141592653589793238f);
 
   for (int mode : {FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO, FE_TONEAREST}) {
     fesetround(mode);
@@ -2153,87 +2291,122 @@
       ~Guard() { fesetround(FE_TONEAREST); }
     } guard;
 
-    verify_integer_multiplication_by_power_of_10(0, 0);
-    verify_integer_multiplication_by_power_of_10(1, 0);
-    verify_integer_multiplication_by_power_of_10(0, 1);
-    verify_integer_multiplication_by_power_of_10(1, 1);
-    verify_integer_multiplication_by_power_of_10(-1, 0);
-    verify_integer_multiplication_by_power_of_10(0, -1);
-    verify_integer_multiplication_by_power_of_10(-1, -1);
-    verify_integer_multiplication_by_power_of_10(-1, 1);
-    verify_integer_multiplication_by_power_of_10(1, -1);
+    namespace all = all_supported_types;
 
-    verify_integer_multiplication_by_power_of_10(
+    all::verify_integer_times_pow10(0, 0);
+    all::verify_integer_times_pow10(1, 0);
+    all::verify_integer_times_pow10(0, 1);
+    all::verify_integer_times_pow10(1, 1);
+    all::verify_integer_times_pow10(-1, 0);
+    all::verify_integer_times_pow10(0, -1);
+    all::verify_integer_times_pow10(-1, -1);
+    all::verify_integer_times_pow10(-1, 1);
+    all::verify_integer_times_pow10(1, -1);
+
+    /* denormal min */
+    verify_integer_times_pow10_dflt(49406564584124654, -340,
+                                    std::numeric_limits<double>::denorm_min());
+    verify_integer_times_pow10<double>(
         49406564584124654, -340, std::numeric_limits<double>::denorm_min());
-    verify_integer_multiplication_by_power_of_10(
-        22250738585072014, -324, std::numeric_limits<double>::min());
-    verify_integer_multiplication_by_power_of_10(
-        17976931348623158, 292, std::numeric_limits<double>::max());
+    verify_integer_times_pow10<float>(14012984, -52,
+                                      std::numeric_limits<float>::denorm_min());
 
-    // DBL_TRUE_MIN / 2 underflows to 0
-    verify_integer_multiplication_by_power_of_10(49406564584124654 / 2, -340,
-                                                 0.);
+    /* normal min */
+    verify_integer_times_pow10_dflt(22250738585072014, -324,
+                                    std::numeric_limits<double>::min());
+    verify_integer_times_pow10<double>(22250738585072014, -324,
+                                       std::numeric_limits<double>::min());
+    verify_integer_times_pow10<float>(11754944, -45,
+                                      std::numeric_limits<float>::min());
 
-    // DBL_TRUE_MIN / 2 + 0.0000000000000001e-324 rounds to DBL_TRUE_MIN
-    verify_integer_multiplication_by_power_of_10(
+    /* max */
+    verify_integer_times_pow10_dflt(17976931348623158, 292,
+                                    std::numeric_limits<double>::max());
+    verify_integer_times_pow10<double>(17976931348623158, 292,
+                                       std::numeric_limits<double>::max());
+    verify_integer_times_pow10<float>(34028235, 31,
+                                      std::numeric_limits<float>::max());
+
+    /* underflow */
+    // (DBL_TRUE_MIN / 2) underflows to 0
+    verify_integer_times_pow10_dflt(49406564584124654 / 2, -340, 0.);
+    verify_integer_times_pow10<double>(49406564584124654 / 2, -340, 0.);
+    // (FLT_TRUE_MIN / 2) underflows to 0
+    verify_integer_times_pow10<float>(14012984 / 2, -52, 0.f);
+
+    /* rounding to denormal min */
+    // (DBL_TRUE_MIN / 2 + 0.0000000000000001e-324) rounds to DBL_TRUE_MIN
+    verify_integer_times_pow10_dflt(49406564584124654 / 2 + 1, -340,
+                                    std::numeric_limits<double>::denorm_min());
+    verify_integer_times_pow10<double>(
         49406564584124654 / 2 + 1, -340,
         std::numeric_limits<double>::denorm_min());
+    // (FLT_TRUE_MIN / 2 + 0.0000001e-45) rounds to FLT_TRUE_MIN
+    verify_integer_times_pow10<float>(14012984 / 2 + 1, -52,
+                                      std::numeric_limits<float>::denorm_min());
 
-    // DBL_MAX + 0.0000000000000001e308 overflows to infinity
-    verify_integer_multiplication_by_power_of_10(
-        17976931348623158 + 1, 292, std::numeric_limits<double>::infinity());
-    // DBL_MAX + 0.00000000000000001e308 overflows to infinity
-    verify_integer_multiplication_by_power_of_10(
-        179769313486231580 + 1, 291, std::numeric_limits<double>::infinity());
+    /* overflow */
+    // (DBL_MAX + 0.0000000000000001e308) overflows to infinity
+    verify_integer_times_pow10_dflt(17976931348623158 + 1, 292,
+                                    std::numeric_limits<double>::infinity());
+    verify_integer_times_pow10<double>(17976931348623158 + 1, 292,
+                                       std::numeric_limits<double>::infinity());
+    // (DBL_MAX + 0.00000000000000001e308) overflows to infinity
+    verify_integer_times_pow10_dflt(179769313486231580 + 1, 291,
+                                    std::numeric_limits<double>::infinity());
+    verify_integer_times_pow10<double>(179769313486231580 + 1, 291,
+                                       std::numeric_limits<double>::infinity());
+    // (FLT_MAX + 0.0000001e38) overflows to infinity
+    verify_integer_times_pow10<float>(34028235 + 1, 31,
+                                      std::numeric_limits<float>::infinity());
+    // (FLT_MAX + 0.00000007e38) overflows to infinity
+    verify_integer_times_pow10<float>(340282350 + 7, 30,
+                                      std::numeric_limits<float>::infinity());
 
     // loosely verifying correct rounding of 1 to 64 bits
     // worth of significant digits
-    verify_integer_multiplication_by_power_of_10(1, 42);
-    verify_integer_multiplication_by_power_of_10(1, -42);
-    verify_integer_multiplication_by_power_of_10(12, 42);
-    verify_integer_multiplication_by_power_of_10(12, -42);
-    verify_integer_multiplication_by_power_of_10(123, 42);
-    verify_integer_multiplication_by_power_of_10(123, -42);
-    verify_integer_multiplication_by_power_of_10(1234, 42);
-    verify_integer_multiplication_by_power_of_10(1234, -42);
-    verify_integer_multiplication_by_power_of_10(12345, 42);
-    verify_integer_multiplication_by_power_of_10(12345, -42);
-    verify_integer_multiplication_by_power_of_10(123456, 42);
-    verify_integer_multiplication_by_power_of_10(123456, -42);
-    verify_integer_multiplication_by_power_of_10(1234567, 42);
-    verify_integer_multiplication_by_power_of_10(1234567, -42);
-    verify_integer_multiplication_by_power_of_10(12345678, 42);
-    verify_integer_multiplication_by_power_of_10(12345678, -42);
-    verify_integer_multiplication_by_power_of_10(123456789, 42);
-    verify_integer_multiplication_by_power_of_10(1234567890, 42);
-    verify_integer_multiplication_by_power_of_10(1234567890, -42);
-    verify_integer_multiplication_by_power_of_10(12345678901, 42);
-    verify_integer_multiplication_by_power_of_10(12345678901, -42);
-    verify_integer_multiplication_by_power_of_10(123456789012, 42);
-    verify_integer_multiplication_by_power_of_10(123456789012, -42);
-    verify_integer_multiplication_by_power_of_10(1234567890123, 42);
-    verify_integer_multiplication_by_power_of_10(1234567890123, -42);
-    verify_integer_multiplication_by_power_of_10(12345678901234, 42);
-    verify_integer_multiplication_by_power_of_10(12345678901234, -42);
-    verify_integer_multiplication_by_power_of_10(123456789012345, 42);
-    verify_integer_multiplication_by_power_of_10(123456789012345, -42);
-    verify_integer_multiplication_by_power_of_10(1234567890123456, 42);
-    verify_integer_multiplication_by_power_of_10(1234567890123456, -42);
-    verify_integer_multiplication_by_power_of_10(12345678901234567, 42);
-    verify_integer_multiplication_by_power_of_10(12345678901234567, -42);
-    verify_integer_multiplication_by_power_of_10(123456789012345678, 42);
-    verify_integer_multiplication_by_power_of_10(123456789012345678, -42);
-    verify_integer_multiplication_by_power_of_10(1234567890123456789, 42);
-    verify_integer_multiplication_by_power_of_10(1234567890123456789, -42);
-    verify_integer_multiplication_by_power_of_10(12345678901234567890ull, 42);
-    verify_integer_multiplication_by_power_of_10(12345678901234567890ull, -42);
-    verify_integer_multiplication_by_power_of_10(
-        std::numeric_limits<int64_t>::max(), 42);
-    verify_integer_multiplication_by_power_of_10(
-        std::numeric_limits<int64_t>::max(), -42);
-    verify_integer_multiplication_by_power_of_10(
-        std::numeric_limits<uint64_t>::max(), 42);
-    verify_integer_multiplication_by_power_of_10(
-        std::numeric_limits<uint64_t>::max(), -42);
+    all::verify_integer_times_pow10(1, 42);
+    all::verify_integer_times_pow10(1, -42);
+    all::verify_integer_times_pow10(12, 42);
+    all::verify_integer_times_pow10(12, -42);
+    all::verify_integer_times_pow10(123, 42);
+    all::verify_integer_times_pow10(123, -42);
+    all::verify_integer_times_pow10(1234, 42);
+    all::verify_integer_times_pow10(1234, -42);
+    all::verify_integer_times_pow10(12345, 42);
+    all::verify_integer_times_pow10(12345, -42);
+    all::verify_integer_times_pow10(123456, 42);
+    all::verify_integer_times_pow10(123456, -42);
+    all::verify_integer_times_pow10(1234567, 42);
+    all::verify_integer_times_pow10(1234567, -42);
+    all::verify_integer_times_pow10(12345678, 42);
+    all::verify_integer_times_pow10(12345678, -42);
+    all::verify_integer_times_pow10(123456789, 42);
+    all::verify_integer_times_pow10(1234567890, 42);
+    all::verify_integer_times_pow10(1234567890, -42);
+    all::verify_integer_times_pow10(12345678901, 42);
+    all::verify_integer_times_pow10(12345678901, -42);
+    all::verify_integer_times_pow10(123456789012, 42);
+    all::verify_integer_times_pow10(123456789012, -42);
+    all::verify_integer_times_pow10(1234567890123, 42);
+    all::verify_integer_times_pow10(1234567890123, -42);
+    all::verify_integer_times_pow10(12345678901234, 42);
+    all::verify_integer_times_pow10(12345678901234, -42);
+    all::verify_integer_times_pow10(123456789012345, 42);
+    all::verify_integer_times_pow10(123456789012345, -42);
+    all::verify_integer_times_pow10(1234567890123456, 42);
+    all::verify_integer_times_pow10(1234567890123456, -42);
+    all::verify_integer_times_pow10(12345678901234567, 42);
+    all::verify_integer_times_pow10(12345678901234567, -42);
+    all::verify_integer_times_pow10(123456789012345678, 42);
+    all::verify_integer_times_pow10(123456789012345678, -42);
+    all::verify_integer_times_pow10(1234567890123456789, 42);
+    all::verify_integer_times_pow10(1234567890123456789, -42);
+    all::verify_integer_times_pow10(12345678901234567890ull, 42);
+    all::verify_integer_times_pow10(12345678901234567890ull, -42);
+    all::verify_integer_times_pow10(std::numeric_limits<int64_t>::max(), 42);
+    all::verify_integer_times_pow10(std::numeric_limits<int64_t>::max(), -42);
+    all::verify_integer_times_pow10(std::numeric_limits<uint64_t>::max(), 42);
+    all::verify_integer_times_pow10(std::numeric_limits<uint64_t>::max(), -42);
   }
 }
\ No newline at end of file
diff --git a/tests/example_integer_times_pow10.cpp b/tests/example_integer_times_pow10.cpp
index 3e86826..0205c27 100644
--- a/tests/example_integer_times_pow10.cpp
+++ b/tests/example_integer_times_pow10.cpp
@@ -2,7 +2,7 @@
 

 #include <iostream>

 

-int main() {

+void default_overload() {

   const uint64_t W = 12345678901234567;

   const int Q = 23;

   const double result = fast_float::integer_times_pow10(W, Q);

@@ -10,3 +10,27 @@
   std::cout << W << " * 10^" << Q << " = " << result << " ("

             << (result == 12345678901234567e23 ? "==" : "!=") << "expected)\n";

 }

+

+void double_specialization() {

+  const uint64_t W = 12345678901234567;

+  const int Q = 23;

+  const double result = fast_float::integer_times_pow10<double>(W, Q);

+  std::cout.precision(17);

+  std::cout << "double: " << W << " * 10^" << Q << " = " << result << " ("

+            << (result == 12345678901234567e23 ? "==" : "!=") << "expected)\n";

+}

+

+void float_specialization() {

+  const uint64_t W = 12345678;

+  const int Q = 23;

+  const float result = fast_float::integer_times_pow10<float>(W, Q);

+  std::cout.precision(9);

+  std::cout << "float: " << W << " * 10^" << Q << " = " << result << " ("

+            << (result == 12345678e23f ? "==" : "!=") << "expected)\n";

+}

+

+int main() {

+  default_overload();

+  double_specialization();

+  float_specialization();

+}