@@ -487,9 +487,13 @@ Perl_grok_bin_oct_hex(pTHX_ const char * const start,
487487 break ;
488488 }
489489
490- /* In overflows, this keeps track of how much to multiply the overflowed NV
491- * by as we continue to parse the remaining digits */
492- NV factor = 0.0 ;
490+ /* The loop below accumulates the integral running total of the result,
491+ * digit by digit. If this total overflows, it adds that to an NV
492+ * approximation, and starts looking at the next batch of digits, until
493+ * they overflow, and so on. This variable counts the number of digits
494+ * seen in the current batch. (The initial value is irrelevant, as the
495+ * first batch will end up being multiplied by zero.) */
496+ uint_fast8_t batch_digit_count = 0 ;
493497
494498 bool overflowed = FALSE;
495499 NV value_nv = 0 ;
@@ -512,24 +516,29 @@ Perl_grok_bin_oct_hex(pTHX_ const char * const start,
512516 * slowing those down (it does have unnecessary shifts, ANDSs,
513517 * and additions for those) */
514518 value = (value << shift ) | XDIGIT_VALUE (* s );
515- factor *= base ;
519+ batch_digit_count ++ ;
516520 continue ;
517521 }
518522
519523 /* Bah. We are about to overflow. Instead, add the unoverflowed
520524 * value to an NV that contains an approximation to the correct
521- * value. Each time through the loop we have increased 'factor' so
522- * that it gives how much the current approximation needs to
523- * effectively be shifted to make room for this new value */
524- value_nv *= factor ;
525+ * value. Each time through the loop we have incremented
526+ * 'batch_digit_count' so that it gives how many digits the
527+ * current approximation needs to effectively be shifted to make
528+ * room for this new value */
529+ #ifdef Perl_ldexp
530+ value_nv = Perl_ldexp (value_nv , batch_digit_count * shift );
531+ #else
532+ value_nv *= Perl_pow (base , batch_digit_count );
533+ #endif
525534 value_nv += (NV ) value ;
526535
527536 /* Then we keep accumulating digits, until all are parsed. We
528537 * start over using the current input value. This will be added to
529538 * 'value_nv' eventually, either when all digits are gone, or we
530539 * have overflowed this fresh start. */
531540 value = XDIGIT_VALUE (* s );
532- factor = base ;
541+ batch_digit_count = 1 ;
533542
534543 if (! overflowed ) {
535544 overflowed = TRUE;
@@ -623,7 +632,11 @@ Perl_grok_bin_oct_hex(pTHX_ const char * const start,
623632 }
624633
625634 /* Overflowed: Calculate the final overflow approximation */
626- value_nv *= factor ;
635+ #ifdef Perl_ldexp
636+ value_nv = Perl_ldexp (value_nv , batch_digit_count * shift );
637+ #else
638+ value_nv *= Perl_pow (base , batch_digit_count );
639+ #endif
627640 value_nv += (NV ) value ;
628641
629642 output_non_portable (base );
0 commit comments