11
11
12
12
#include < stdint.h>
13
13
14
+ #include " src/__support/CPP/limits.h"
14
15
#include " src/__support/CPP/type_traits.h"
15
16
#include " src/__support/FPUtil/FPBits.h"
16
17
#include " src/__support/FPUtil/dyadic_float.h"
@@ -108,6 +109,8 @@ namespace LIBC_NAMESPACE {
108
109
109
110
using BlockInt = uint32_t ;
110
111
constexpr uint32_t BLOCK_SIZE = 9 ;
112
+ constexpr uint64_t EXP5_9 = 1953125 ;
113
+ constexpr uint64_t EXP10_9 = 1000000000 ;
111
114
112
115
using FPBits = fputil::FPBits<long double >;
113
116
@@ -118,7 +121,7 @@ constexpr size_t CALC_SHIFT_CONST = 128;
118
121
namespace internal {
119
122
120
123
// Returns floor(log_10(2^e)); requires 0 <= e <= 42039.
121
- LIBC_INLINE constexpr uint32_t log10_pow2 (const uint64_t e) {
124
+ LIBC_INLINE constexpr uint32_t log10_pow2 (uint64_t e) {
122
125
LIBC_ASSERT (e <= 42039 &&
123
126
" Incorrect exponent to perform log10_pow2 approximation." );
124
127
// This approximation is based on the float value for log_10(2). It first
@@ -144,27 +147,26 @@ LIBC_INLINE constexpr uint32_t log10_pow2(const uint64_t e) {
144
147
}
145
148
146
149
// Same as above, but with different constants.
147
- LIBC_INLINE constexpr uint32_t log2_pow5 (const uint64_t e) {
150
+ LIBC_INLINE constexpr uint32_t log2_pow5 (uint64_t e) {
148
151
return static_cast <uint32_t >((e * 0x12934f0979bll ) >> 39 );
149
152
}
150
153
151
154
// Returns 1 + floor(log_10(2^e). This could technically be off by 1 if any
152
155
// power of 2 was also a power of 10, but since that doesn't exist this is
153
156
// always accurate. This is used to calculate the maximum number of base-10
154
157
// digits a given e-bit number could have.
155
- LIBC_INLINE constexpr uint32_t ceil_log10_pow2 (const uint32_t e) {
158
+ LIBC_INLINE constexpr uint32_t ceil_log10_pow2 (uint32_t e) {
156
159
return log10_pow2 (e) + 1 ;
157
160
}
158
161
159
- LIBC_INLINE constexpr uint32_t div_ceil (const uint32_t num,
160
- const uint32_t denom) {
162
+ LIBC_INLINE constexpr uint32_t div_ceil (uint32_t num, uint32_t denom) {
161
163
return (num + (denom - 1 )) / denom;
162
164
}
163
165
164
166
// Returns the maximum number of 9 digit blocks a number described by the given
165
167
// index (which is ceil(exponent/16)) and mantissa width could need.
166
- LIBC_INLINE constexpr uint32_t length_for_num (const uint32_t idx,
167
- const uint32_t mantissa_width) {
168
+ LIBC_INLINE constexpr uint32_t length_for_num (uint32_t idx,
169
+ uint32_t mantissa_width) {
168
170
return div_ceil (ceil_log10_pow2 (idx) + ceil_log10_pow2 (mantissa_width + 1 ),
169
171
BLOCK_SIZE);
170
172
}
@@ -194,24 +196,21 @@ LIBC_INLINE constexpr cpp::UInt<MID_INT_SIZE> get_table_positive(int exponent,
194
196
// can get, since it needs to be small enough to fit in the result UInt,
195
197
// otherwise we'll get truncation on return.
196
198
constexpr cpp::UInt<INT_SIZE> MOD_SIZE =
197
- (cpp::UInt<INT_SIZE>(1000000000 )
199
+ (cpp::UInt<INT_SIZE>(EXP10_9 )
198
200
<< (CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0 )));
199
201
200
- constexpr uint64_t FIVE_EXP_NINE = 1953125 ;
201
-
202
202
num = cpp::UInt<INT_SIZE>(1 ) << (shift_amount);
203
203
if (i > 0 ) {
204
- cpp::UInt<INT_SIZE> fives (FIVE_EXP_NINE );
204
+ cpp::UInt<INT_SIZE> fives (EXP5_9 );
205
205
fives.pow_n (i);
206
206
num = num / fives;
207
207
}
208
208
209
209
num = num + 1 ;
210
210
if (num > MOD_SIZE) {
211
- auto rem =
212
- num.div_uint32_times_pow_2 (
213
- 1000000000 , CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0 ))
214
- .value ();
211
+ auto rem = num.div_uint32_times_pow_2 (
212
+ EXP10_9, CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0 ))
213
+ .value ();
215
214
num = rem;
216
215
}
217
216
return num;
@@ -235,7 +234,7 @@ LIBC_INLINE cpp::UInt<MID_INT_SIZE> get_table_positive_df(int exponent,
235
234
}
236
235
fputil::DyadicFloat<INT_SIZE> num (false , 0 , 1 );
237
236
constexpr cpp::UInt<INT_SIZE> MOD_SIZE =
238
- (cpp::UInt<INT_SIZE>(1000000000 )
237
+ (cpp::UInt<INT_SIZE>(EXP10_9 )
239
238
<< (CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0 )));
240
239
241
240
constexpr cpp::UInt<INT_SIZE> FIVE_EXP_MINUS_NINE_MANT{
@@ -256,8 +255,8 @@ LIBC_INLINE cpp::UInt<MID_INT_SIZE> get_table_positive_df(int exponent,
256
255
if (int_num > MOD_SIZE) {
257
256
auto rem =
258
257
int_num
259
- .div_uint32_times_pow_2 (
260
- 1000000000 , CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0 ))
258
+ .div_uint32_times_pow_2 (EXP10_9, CALC_SHIFT_CONST +
259
+ (IDX_SIZE > 1 ? IDX_SIZE : 0 ))
261
260
.value ();
262
261
int_num = rem;
263
262
}
@@ -280,11 +279,9 @@ LIBC_INLINE cpp::UInt<MID_INT_SIZE> get_table_negative(int exponent, size_t i) {
280
279
int shift_amount = CALC_SHIFT_CONST - exponent;
281
280
cpp::UInt<INT_SIZE> num (1 );
282
281
constexpr cpp::UInt<INT_SIZE> MOD_SIZE =
283
- (cpp::UInt<INT_SIZE>(1000000000 )
282
+ (cpp::UInt<INT_SIZE>(EXP10_9 )
284
283
<< (CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0 )));
285
284
286
- constexpr uint64_t TEN_EXP_NINE = 1000000000 ;
287
- constexpr uint64_t FIVE_EXP_NINE = 1953125 ;
288
285
size_t ten_blocks = i;
289
286
size_t five_blocks = 0 ;
290
287
if (shift_amount < 0 ) {
@@ -301,12 +298,12 @@ LIBC_INLINE cpp::UInt<MID_INT_SIZE> get_table_negative(int exponent, size_t i) {
301
298
}
302
299
303
300
if (five_blocks > 0 ) {
304
- cpp::UInt<INT_SIZE> fives (FIVE_EXP_NINE );
301
+ cpp::UInt<INT_SIZE> fives (EXP5_9 );
305
302
fives.pow_n (five_blocks);
306
303
num = fives;
307
304
}
308
305
if (ten_blocks > 0 ) {
309
- cpp::UInt<INT_SIZE> tens (TEN_EXP_NINE );
306
+ cpp::UInt<INT_SIZE> tens (EXP10_9 );
310
307
tens.pow_n (ten_blocks);
311
308
if (five_blocks <= 0 ) {
312
309
num = tens;
@@ -321,10 +318,9 @@ LIBC_INLINE cpp::UInt<MID_INT_SIZE> get_table_negative(int exponent, size_t i) {
321
318
num = num >> (-shift_amount);
322
319
}
323
320
if (num > MOD_SIZE) {
324
- auto rem =
325
- num.div_uint32_times_pow_2 (
326
- 1000000000 , CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0 ))
327
- .value ();
321
+ auto rem = num.div_uint32_times_pow_2 (
322
+ EXP10_9, CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0 ))
323
+ .value ();
328
324
num = rem;
329
325
}
330
326
return num;
@@ -346,10 +342,10 @@ LIBC_INLINE cpp::UInt<MID_INT_SIZE> get_table_negative_df(int exponent,
346
342
347
343
fputil::DyadicFloat<INT_SIZE> num (false , 0 , 1 );
348
344
constexpr cpp::UInt<INT_SIZE> MOD_SIZE =
349
- (cpp::UInt<INT_SIZE>(1000000000 )
345
+ (cpp::UInt<INT_SIZE>(EXP10_9 )
350
346
<< (CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0 )));
351
347
352
- constexpr cpp::UInt<INT_SIZE> TEN_EXP_NINE_MANT (1000000000 );
348
+ constexpr cpp::UInt<INT_SIZE> TEN_EXP_NINE_MANT (EXP10_9 );
353
349
354
350
static const fputil::DyadicFloat<INT_SIZE> TEN_EXP_NINE (false , 0 ,
355
351
TEN_EXP_NINE_MANT);
@@ -364,8 +360,8 @@ LIBC_INLINE cpp::UInt<MID_INT_SIZE> get_table_negative_df(int exponent,
364
360
if (int_num > MOD_SIZE) {
365
361
auto rem =
366
362
int_num
367
- .div_uint32_times_pow_2 (
368
- 1000000000 , CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0 ))
363
+ .div_uint32_times_pow_2 (EXP10_9, CALC_SHIFT_CONST +
364
+ (IDX_SIZE > 1 ? IDX_SIZE : 0 ))
369
365
.value ();
370
366
int_num = rem;
371
367
}
@@ -385,16 +381,15 @@ LIBC_INLINE uint32_t fast_uint_mod_1e9(const cpp::UInt<MID_INT_SIZE> &val) {
385
381
const uint64_t result = static_cast <uint64_t >(middle[2 ]);
386
382
const uint64_t shifted = result >> 29 ;
387
383
return static_cast <uint32_t >(static_cast <uint32_t >(val) -
388
- (1000000000 * shifted));
384
+ (EXP10_9 * shifted));
389
385
}
390
386
391
387
LIBC_INLINE uint32_t mul_shift_mod_1e9 (const FPBits::StorageType mantissa,
392
388
const cpp::UInt<MID_INT_SIZE> &large,
393
389
const int32_t shift_amount) {
394
390
cpp::UInt<MID_INT_SIZE + FPBits::STORAGE_LEN> val (large);
395
391
val = (val * mantissa) >> shift_amount;
396
- return static_cast <uint32_t >(
397
- val.div_uint32_times_pow_2 (1000000000 , 0 ).value ());
392
+ return static_cast <uint32_t >(val.div_uint32_times_pow_2 (EXP10_9, 0 ).value ());
398
393
}
399
394
400
395
} // namespace internal
@@ -623,6 +618,11 @@ class FloatToString {
623
618
!defined(LIBC_COPT_FLOAT_TO_STR_NO_SPECIALIZE_LD)
624
619
// --------------------------- LONG DOUBLE FUNCTIONS ---------------------------
625
620
621
+ // this algorithm will work exactly the same for 80 bit and 128 bit long
622
+ // doubles. They have the same max exponent, but even if they didn't the
623
+ // constants should be calculated to be correct for any provided floating point
624
+ // type.
625
+
626
626
template <> class FloatToString <long double > {
627
627
fputil::FPBits<long double > float_bits;
628
628
bool is_negative = 0 ;
@@ -631,19 +631,23 @@ template <> class FloatToString<long double> {
631
631
632
632
static constexpr int FRACTION_LEN = fputil::FPBits<long double >::FRACTION_LEN;
633
633
static constexpr int EXP_BIAS = fputil::FPBits<long double >::EXP_BIAS;
634
+ static constexpr size_t UINT_WORD_SIZE = 64 ;
634
635
635
636
static constexpr size_t FLOAT_AS_INT_WIDTH =
636
637
internal::div_ceil (fputil::FPBits<long double >::MAX_BIASED_EXPONENT -
637
638
FPBits::EXP_BIAS,
638
- 64 ) *
639
- 64 ;
639
+ UINT_WORD_SIZE ) *
640
+ UINT_WORD_SIZE ;
640
641
static constexpr size_t EXTRA_INT_WIDTH =
641
- internal::div_ceil (sizeof (long double ) * 8 , 64 ) * 64 ;
642
+ internal::div_ceil (sizeof (long double ) * CHAR_BIT, UINT_WORD_SIZE) *
643
+ UINT_WORD_SIZE;
644
+
645
+ using wide_int = cpp::UInt<FLOAT_AS_INT_WIDTH + EXTRA_INT_WIDTH>;
642
646
643
647
// float_as_fixed represents the floating point number as a fixed point number
644
648
// with the point EXTRA_INT_WIDTH bits from the left of the number. This can
645
649
// store any number with a negative exponent.
646
- cpp::UInt<FLOAT_AS_INT_WIDTH + EXTRA_INT_WIDTH> float_as_fixed = 0 ;
650
+ wide_int float_as_fixed = 0 ;
647
651
int int_block_index = 0 ;
648
652
649
653
static constexpr size_t BLOCK_BUFFER_LEN =
@@ -653,19 +657,18 @@ template <> class FloatToString<long double> {
653
657
654
658
template <size_t Bits>
655
659
LIBC_INLINE static constexpr BlockInt grab_digits (cpp::UInt<Bits> &int_num) {
656
- auto wide_result = int_num.div_uint32_times_pow_2 (1953125 , 9 );
660
+ auto wide_result = int_num.div_uint32_times_pow_2 (EXP5_9 , 9 );
657
661
// the optional only comes into effect when dividing by 0, which will
658
662
// never happen here. Thus, we just assert that it has value.
659
663
LIBC_ASSERT (wide_result.has_value ());
660
664
return static_cast <BlockInt>(wide_result.value ());
661
665
}
662
666
663
- LIBC_INLINE static constexpr void zero_leading_digits (
664
- cpp::UInt<FLOAT_AS_INT_WIDTH + EXTRA_INT_WIDTH> &int_num) {
667
+ LIBC_INLINE static constexpr void zero_leading_digits (wide_int &int_num) {
665
668
// WORD_SIZE is the width of the numbers used to internally represent the
666
669
// UInt
667
- for (size_t i = 0 ; i < EXTRA_INT_WIDTH / int_num. WORD_SIZE ; ++i)
668
- int_num[i + (FLOAT_AS_INT_WIDTH / int_num. WORD_SIZE )] = 0 ;
670
+ for (size_t i = 0 ; i < EXTRA_INT_WIDTH / wide_int:: WORD_SIZE; ++i)
671
+ int_num[i + (FLOAT_AS_INT_WIDTH / wide_int:: WORD_SIZE)] = 0 ;
669
672
}
670
673
671
674
// init_convert initializes float_as_int, cur_block, and block_buffer based on
@@ -684,7 +687,7 @@ template <> class FloatToString<long double> {
684
687
// from left to right, so it caches the results so they can be read in
685
688
// reverse order.
686
689
687
- cpp::UInt<FLOAT_AS_INT_WIDTH + EXTRA_INT_WIDTH> float_as_int = mantissa;
690
+ wide_int float_as_int = mantissa;
688
691
689
692
float_as_int.shift_left (exponent);
690
693
int_block_index = 0 ;
@@ -812,7 +815,7 @@ template <> class FloatToString<long double> {
812
815
// requested block. This is likely to only be one step.
813
816
while (block_index < int_block_index) {
814
817
zero_leading_digits (float_as_fixed);
815
- float_as_fixed.mul (1000000000 );
818
+ float_as_fixed.mul (EXP10_9 );
816
819
--int_block_index;
817
820
}
818
821
0 commit comments