@@ -188,32 +188,17 @@ from_chars(UC const *first, UC const *last, T &value,
188188 parse_options_t <UC>(fmt));
189189}
190190
191- /* *
192- * This function overload takes parsed_number_string_t structure that is created
193- * and populated either by from_chars_advanced function taking chars range and
194- * parsing options or other parsing custom function implemented by user.
195- */
196- template <typename T, typename UC>
197- FASTFLOAT_CONSTEXPR20 from_chars_result_t <UC>
198- from_chars_advanced (parsed_number_string_t <UC> &pns, T &value) noexcept {
199-
200- static_assert (is_supported_float_type<T>::value,
201- " only some floating-point types are supported" );
202- static_assert (is_supported_char_type<UC>::value,
203- " only char, wchar_t, char16_t and char32_t are supported" );
204-
205- from_chars_result_t <UC> answer;
206-
207- answer.ec = std::errc (); // be optimistic
208- answer.ptr = pns.lastmatch ;
191+ template <typename T>
192+ FASTFLOAT_CONSTEXPR20 bool
193+ clinger_fast_path_impl (uint64_t mantissa, int64_t exponent, bool is_negative,
194+ T &value) noexcept {
209195 // The implementation of the Clinger's fast path is convoluted because
210196 // we want round-to-nearest in all cases, irrespective of the rounding mode
211197 // selected on the thread.
212198 // We proceed optimistically, assuming that detail::rounds_to_nearest()
213199 // returns true.
214- if (binary_format<T>::min_exponent_fast_path () <= pns.exponent &&
215- pns.exponent <= binary_format<T>::max_exponent_fast_path () &&
216- !pns.too_many_digits ) {
200+ if (binary_format<T>::min_exponent_fast_path () <= exponent &&
201+ exponent <= binary_format<T>::max_exponent_fast_path ()) {
217202 // Unfortunately, the conventional Clinger's fast path is only possible
218203 // when the system rounds to the nearest float.
219204 //
@@ -224,41 +209,64 @@ from_chars_advanced(parsed_number_string_t<UC> &pns, T &value) noexcept {
224209 if (!cpp20_and_in_constexpr () && detail::rounds_to_nearest ()) {
225210 // We have that fegetround() == FE_TONEAREST.
226211 // Next is Clinger's fast path.
227- if (pns. mantissa <= binary_format<T>::max_mantissa_fast_path ()) {
228- value = T (pns. mantissa );
229- if (pns. exponent < 0 ) {
230- value = value / binary_format<T>::exact_power_of_ten (-pns. exponent );
212+ if (mantissa <= binary_format<T>::max_mantissa_fast_path ()) {
213+ value = T (mantissa);
214+ if (exponent < 0 ) {
215+ value = value / binary_format<T>::exact_power_of_ten (-exponent);
231216 } else {
232- value = value * binary_format<T>::exact_power_of_ten (pns. exponent );
217+ value = value * binary_format<T>::exact_power_of_ten (exponent);
233218 }
234- if (pns. negative ) {
219+ if (is_negative ) {
235220 value = -value;
236221 }
237- return answer ;
222+ return true ;
238223 }
239224 } else {
240225 // We do not have that fegetround() == FE_TONEAREST.
241226 // Next is a modified Clinger's fast path, inspired by Jakub Jelínek's
242227 // proposal
243- if (pns.exponent >= 0 &&
244- pns.mantissa <=
245- binary_format<T>::max_mantissa_fast_path (pns.exponent )) {
228+ if (exponent >= 0 &&
229+ mantissa <= binary_format<T>::max_mantissa_fast_path (exponent)) {
246230#if defined(__clang__) || defined(FASTFLOAT_32BIT)
247231 // Clang may map 0 to -0.0 when fegetround() == FE_DOWNWARD
248- if (pns. mantissa == 0 ) {
249- value = pns. negative ? T (-0 .) : T (0 .);
250- return answer ;
232+ if (mantissa == 0 ) {
233+ value = is_negative ? T (-0 .) : T (0 .);
234+ return true ;
251235 }
252236#endif
253- value = T (pns.mantissa ) *
254- binary_format<T>::exact_power_of_ten (pns.exponent );
255- if (pns.negative ) {
237+ value = T (mantissa) * binary_format<T>::exact_power_of_ten (exponent);
238+ if (is_negative) {
256239 value = -value;
257240 }
258- return answer ;
241+ return true ;
259242 }
260243 }
261244 }
245+ return false ;
246+ }
247+
248+ /* *
249+ * This function overload takes parsed_number_string_t structure that is created
250+ * and populated either by from_chars_advanced function taking chars range and
251+ * parsing options or other parsing custom function implemented by user.
252+ */
253+ template <typename T, typename UC>
254+ FASTFLOAT_CONSTEXPR20 from_chars_result_t <UC>
255+ from_chars_advanced (parsed_number_string_t <UC> &pns, T &value) noexcept {
256+ static_assert (is_supported_float_type<T>::value,
257+ " only some floating-point types are supported" );
258+ static_assert (is_supported_char_type<UC>::value,
259+ " only char, wchar_t, char16_t and char32_t are supported" );
260+
261+ from_chars_result_t <UC> answer;
262+
263+ answer.ec = std::errc (); // be optimistic
264+ answer.ptr = pns.lastmatch ;
265+
266+ if (!pns.too_many_digits &&
267+ clinger_fast_path_impl (pns.mantissa , pns.exponent , pns.negative , value))
268+ return answer;
269+
262270 adjusted_mantissa am =
263271 compute_float<binary_format<T>>(pns.exponent , pns.mantissa );
264272 if (pns.too_many_digits && am.power2 >= 0 ) {
@@ -336,6 +344,54 @@ from_chars(UC const *first, UC const *last, T &value, int base) noexcept {
336344 return from_chars_advanced (first, last, value, options);
337345}
338346
347+ FASTFLOAT_CONSTEXPR20
348+ typename std::enable_if<is_supported_float_type<double >::value, double >::type
349+ multiply_integer_and_power_of_10 (uint64_t mantissa,
350+ int decimal_exponent) noexcept {
351+ double value;
352+ if (clinger_fast_path_impl (mantissa, decimal_exponent, false , value))
353+ return value;
354+
355+ adjusted_mantissa am =
356+ compute_float<binary_format<double >>(decimal_exponent, mantissa);
357+ to_float (false , am, value);
358+ return value;
359+ }
360+
361+ FASTFLOAT_CONSTEXPR20
362+ typename std::enable_if<is_supported_float_type<double >::value, double >::type
363+ multiply_integer_and_power_of_10 (int64_t mantissa,
364+ int decimal_exponent) noexcept {
365+ const bool is_negative = mantissa < 0 ;
366+ const uint64_t m = static_cast <uint64_t >(is_negative ? -mantissa : mantissa);
367+
368+ double value;
369+ if (clinger_fast_path_impl (m, decimal_exponent, is_negative, value))
370+ return value;
371+
372+ adjusted_mantissa am =
373+ compute_float<binary_format<double >>(decimal_exponent, m);
374+ to_float (is_negative, am, value);
375+ return value;
376+ }
377+
378+ // the following overloads are here to avoid surprising ambiguity for int,
379+ // unsigned, etc.
380+ FASTFLOAT_CONSTEXPR20
381+ typename std::enable_if<is_supported_float_type<double >::value, double >::type
382+ multiply_integer_and_power_of_10 (unsigned mantissa,
383+ int decimal_exponent) noexcept {
384+ return multiply_integer_and_power_of_10 (static_cast <uint64_t >(mantissa),
385+ decimal_exponent);
386+ }
387+
388+ FASTFLOAT_CONSTEXPR20
389+ typename std::enable_if<is_supported_float_type<double >::value, double >::type
390+ multiply_integer_and_power_of_10 (int mantissa, int decimal_exponent) noexcept {
391+ return multiply_integer_and_power_of_10 (static_cast <int64_t >(mantissa),
392+ decimal_exponent);
393+ }
394+
339395template <typename T, typename UC>
340396FASTFLOAT_CONSTEXPR20 from_chars_result_t <UC>
341397from_chars_int_advanced (UC const *first, UC const *last, T &value,
0 commit comments