@@ -648,7 +648,10 @@ template <> class FloatToString<long double> {
648
648
static constexpr size_t EXTRA_INT_WIDTH =
649
649
internal::div_ceil (sizeof (long double ) * 8 , 64 ) * 64 ;
650
650
651
- cpp::UInt<FLOAT_AS_INT_WIDTH + EXTRA_INT_WIDTH> float_as_int = 0 ;
651
+ // float_as_fixed represents the floating point number as a fixed point number
652
+ // with the point EXTRA_INT_WIDTH bits from the left of the number. This can
653
+ // store any number with a negative exponent.
654
+ cpp::UInt<FLOAT_AS_INT_WIDTH + EXTRA_INT_WIDTH> float_as_fixed = 0 ;
652
655
int int_block_index = 0 ;
653
656
654
657
static constexpr size_t BLOCK_BUFFER_LEN =
@@ -675,20 +678,25 @@ template <> class FloatToString<long double> {
675
678
}
676
679
}
677
680
681
+ // init_convert initializes float_as_int, cur_block, and block_buffer based on
682
+ // the mantissa and exponent of the initial number. Calling it will always
683
+ // return the class to the starting state.
678
684
LIBC_INLINE constexpr void init_convert () {
679
- // This initializes float_as_int, cur_block, and block_buffer.
680
-
681
- float_as_int = mantissa;
682
-
683
685
// No calculation necessary for the 0 case.
684
686
if (mantissa == 0 && exponent == 0 ) {
685
687
return ;
686
688
}
687
689
688
690
if (exponent > 0 ) {
689
691
// if the exponent is positive, then the number is fully above the decimal
690
- // point. Shift left by exponent to get the integer representation of this
691
- // number.
692
+ // point. In this case we represent the float as an integer, then divide
693
+ // by 10^BLOCK_SIZE and take the remainder as our next block. This
694
+ // generates the digits from right to left, but the digits will be written
695
+ // from left to right, so it caches the results so they can be read in
696
+ // reverse order.
697
+
698
+ cpp::UInt<FLOAT_AS_INT_WIDTH + EXTRA_INT_WIDTH> float_as_int = mantissa;
699
+
692
700
float_as_int.shift_left (exponent);
693
701
int_block_index = 0 ;
694
702
@@ -701,17 +709,18 @@ template <> class FloatToString<long double> {
701
709
702
710
} else {
703
711
// if the exponent is not positive, then the number is at least partially
704
- // below the decimal point. Shift left to make the int a fixed point
705
- // representation with the decimal point after the top EXTRA_INT_WIDTH
706
- // bits.
712
+ // below the decimal point. In this case we represent the float as a fixed
713
+ // point number with the decimal point after the top EXTRA_INT_WIDTH bits.
714
+ float_as_fixed = mantissa;
715
+
707
716
const int SHIFT_AMOUNT = FLOAT_AS_INT_WIDTH + exponent;
708
717
static_assert (EXTRA_INT_WIDTH >= sizeof (long double ) * 8 );
709
- float_as_int .shift_left (SHIFT_AMOUNT);
718
+ float_as_fixed .shift_left (SHIFT_AMOUNT);
710
719
711
720
// If there are still digits above the decimal point, handle those.
712
- if (float_as_int .clz () < EXTRA_INT_WIDTH) {
721
+ if (float_as_fixed .clz () < EXTRA_INT_WIDTH) {
713
722
cpp::UInt<EXTRA_INT_WIDTH> above_decimal_point =
714
- float_as_int >> FLOAT_AS_INT_WIDTH;
723
+ float_as_fixed >> FLOAT_AS_INT_WIDTH;
715
724
716
725
size_t positive_int_block_index = 0 ;
717
726
while (above_decimal_point > 0 ) {
@@ -722,7 +731,7 @@ template <> class FloatToString<long double> {
722
731
block_buffer_valid = positive_int_block_index;
723
732
724
733
// Zero all digits above the decimal point.
725
- zero_leading_digits (float_as_int );
734
+ zero_leading_digits (float_as_fixed );
726
735
int_block_index = 0 ;
727
736
}
728
737
}
@@ -822,14 +831,14 @@ template <> class FloatToString<long double> {
822
831
// If we are currently before the requested block. Step until we reach the
823
832
// requested block. This is likely to only be one step.
824
833
while (block_index < int_block_index) {
825
- zero_leading_digits (float_as_int );
826
- float_as_int .mul (1000000000 );
834
+ zero_leading_digits (float_as_fixed );
835
+ float_as_fixed .mul (1000000000 );
827
836
--int_block_index;
828
837
}
829
838
830
839
// We're currently on the requested block, return the current block.
831
840
BlockInt cur_block =
832
- static_cast <BlockInt>(float_as_int >> FLOAT_AS_INT_WIDTH);
841
+ static_cast <BlockInt>(float_as_fixed >> FLOAT_AS_INT_WIDTH);
833
842
return cur_block;
834
843
}
835
844
0 commit comments