mirror of
https://github.com/fastfloat/fast_float.git
synced 2025-12-06 08:46:49 +08:00
Proto.
This commit is contained in:
parent
052975dd5f
commit
186fb364f2
347
include/fast_float/binary_to_decimal.h
Normal file
347
include/fast_float/binary_to_decimal.h
Normal file
@ -0,0 +1,347 @@
|
||||
#ifndef FASTFLOAT_BINARY_TO_DECIMAL_H
|
||||
#define FASTFLOAT_BINARY_TO_DECIMAL_H
|
||||
|
||||
#include "float_common.h"
|
||||
#include "fast_table.h"
|
||||
#include "decimal_to_binary.h"
|
||||
|
||||
#include <cfloat>
|
||||
#include <cinttypes>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
namespace fast_float {
|
||||
|
||||
namespace detail {
|
||||
typedef struct {
|
||||
uint64_t mantissa_cutoff;
|
||||
int16_t power;
|
||||
} power_conversion;
|
||||
|
||||
static const power_conversion power_conversions[] = {
|
||||
{0xffffffffffffffff, 16},
|
||||
{0xffffffffffffffff, 16},
|
||||
{0xffffffffffffffff, 16},
|
||||
{0x0014000000000000, 16},
|
||||
{0xffffffffffffffff, 15},
|
||||
{0xffffffffffffffff, 15},
|
||||
{0x0019000000000000, 15},
|
||||
{0xffffffffffffffff, 14},
|
||||
{0xffffffffffffffff, 14},
|
||||
{0x001f400000000000, 14},
|
||||
{0xffffffffffffffff, 13},
|
||||
{0xffffffffffffffff, 13},
|
||||
{0xffffffffffffffff, 13},
|
||||
{0x0013880000000000, 13},
|
||||
{0xffffffffffffffff, 12},
|
||||
{0xffffffffffffffff, 12},
|
||||
{0x00186a0000000000, 12},
|
||||
{0xffffffffffffffff, 11},
|
||||
{0xffffffffffffffff, 11},
|
||||
{0x001e848000000000, 11},
|
||||
{0xffffffffffffffff, 10},
|
||||
{0xffffffffffffffff, 10},
|
||||
{0xffffffffffffffff, 10},
|
||||
{0x001312d000000000, 10},
|
||||
{0xffffffffffffffff, 9},
|
||||
{0xffffffffffffffff, 9},
|
||||
{0x0017d78400000000, 9},
|
||||
{0xffffffffffffffff, 8},
|
||||
{0xffffffffffffffff, 8},
|
||||
{0x001dcd6500000000, 8},
|
||||
{0xffffffffffffffff, 7},
|
||||
{0xffffffffffffffff, 7},
|
||||
{0xffffffffffffffff, 7},
|
||||
{0x0012a05f20000000, 7},
|
||||
{0xffffffffffffffff, 6},
|
||||
{0xffffffffffffffff, 6},
|
||||
{0x00174876e8000000, 6},
|
||||
{0xffffffffffffffff, 5},
|
||||
{0xffffffffffffffff, 5},
|
||||
{0x001d1a94a2000000, 5},
|
||||
{0xffffffffffffffff, 4},
|
||||
{0xffffffffffffffff, 4},
|
||||
{0xffffffffffffffff, 4},
|
||||
{0x0012309ce5400000, 4},
|
||||
{0xffffffffffffffff, 3},
|
||||
{0xffffffffffffffff, 3},
|
||||
{0x0016bcc41e900000, 3},
|
||||
{0xffffffffffffffff, 2},
|
||||
{0xffffffffffffffff, 2},
|
||||
{0x001c6bf526340000, 2},
|
||||
{0xffffffffffffffff, 1},
|
||||
{0xffffffffffffffff, 1},
|
||||
{0xffffffffffffffff, 1},
|
||||
{0x0011c37937e08000, 1},
|
||||
{0xffffffffffffffff, 0},
|
||||
{0xffffffffffffffff, 0},
|
||||
{0x0016345785d8a000, 0},
|
||||
{0xffffffffffffffff, -1},
|
||||
{0xffffffffffffffff, -1},
|
||||
{0x001bc16d674ec800, -1},
|
||||
{0xffffffffffffffff, -2},
|
||||
{0xffffffffffffffff, -2},
|
||||
{0xffffffffffffffff, -2},
|
||||
{0x001158e460913d00, -2},
|
||||
{0xffffffffffffffff, -3},
|
||||
{0xffffffffffffffff, -3},
|
||||
{0x0015af1d78b58c40, -3},
|
||||
{0xffffffffffffffff, -4},
|
||||
{0xffffffffffffffff, -4},
|
||||
{0x001b1ae4d6e2ef50, -4},
|
||||
{0xffffffffffffffff, -5},
|
||||
{0xffffffffffffffff, -5},
|
||||
{0xffffffffffffffff, -5},
|
||||
{0x0010f0cf064dd592, -5},
|
||||
{0xffffffffffffffff, -6},
|
||||
{0xffffffffffffffff, -6},
|
||||
{0x00152d02c7e14af6, -6},
|
||||
{0xffffffffffffffff, -7},
|
||||
{0xffffffffffffffff, -7},
|
||||
{0x001a784379d99db4, -7},
|
||||
{0xffffffffffffffff, -8},
|
||||
{0xffffffffffffffff, -8},
|
||||
{0xffffffffffffffff, -8},
|
||||
{0x00108b2a2c280291, -8},
|
||||
{0xffffffffffffffff, -9},
|
||||
{0xffffffffffffffff, -9},
|
||||
{0x0014adf4b7320335, -9},
|
||||
{0xffffffffffffffff, -10},
|
||||
{0xffffffffffffffff, -10},
|
||||
{0x0019d971e4fe8402, -10},
|
||||
{0xffffffffffffffff, -11},
|
||||
{0xffffffffffffffff, -11},
|
||||
{0xffffffffffffffff, -11},
|
||||
{0x001027e72f1f1281, -11},
|
||||
{0xffffffffffffffff, -12},
|
||||
{0xffffffffffffffff, -12},
|
||||
{0x001431e0fae6d721, -12},
|
||||
{0xffffffffffffffff, -13},
|
||||
{0xffffffffffffffff, -13},
|
||||
{0x00193e5939a08cea, -13},
|
||||
{0xffffffffffffffff, -14},
|
||||
{0xffffffffffffffff, -14},
|
||||
{0x001f8def8808b024, -14},
|
||||
{0xffffffffffffffff, -15},
|
||||
{0xffffffffffffffff, -15},
|
||||
{0xffffffffffffffff, -15},
|
||||
{0x0013b8b5b5056e17, -15},
|
||||
{0xffffffffffffffff, -16},
|
||||
{0xffffffffffffffff, -16},
|
||||
{0x0018a6e32246c99c, -16},
|
||||
{0xffffffffffffffff, -17},
|
||||
{0xffffffffffffffff, -17},
|
||||
{0x001ed09bead87c03, -17},
|
||||
{0xffffffffffffffff, -18},
|
||||
{0xffffffffffffffff, -18},
|
||||
{0xffffffffffffffff, -18},
|
||||
{0x0013426172c74d82, -18},
|
||||
{0xffffffffffffffff, -19},
|
||||
{0xffffffffffffffff, -19},
|
||||
{0x001812f9cf7920e3, -19},
|
||||
{0xffffffffffffffff, -20},
|
||||
{0xffffffffffffffff, -20},
|
||||
{0x001e17b84357691b, -20},
|
||||
{0xffffffffffffffff, -21},
|
||||
{0xffffffffffffffff, -21},
|
||||
{0xffffffffffffffff, -21},
|
||||
{0x0012ced32a16a1b1, -21},
|
||||
{0xffffffffffffffff, -22},
|
||||
{0xffffffffffffffff, -22},
|
||||
{0x00178287f49c4a1d, -22},
|
||||
{0xffffffffffffffff, -23},
|
||||
{0xffffffffffffffff, -23},
|
||||
{0x001d6329f1c35ca5, -23},
|
||||
{0xffffffffffffffff, -24},
|
||||
{0xffffffffffffffff, -24},
|
||||
{0xffffffffffffffff, -24},
|
||||
{0x00125dfa371a19e7, -24},
|
||||
{0xffffffffffffffff, -25},
|
||||
{0xffffffffffffffff, -25},
|
||||
{0x0016f578c4e0a061, -25},
|
||||
{0xffffffffffffffff, -26},
|
||||
{0xffffffffffffffff, -26},
|
||||
{0x001cb2d6f618c879, -26},
|
||||
{0xffffffffffffffff, -27},
|
||||
{0xffffffffffffffff, -27},
|
||||
{0xffffffffffffffff, -27},
|
||||
{0x0011efc659cf7d4c, -27},
|
||||
{0xffffffffffffffff, -28},
|
||||
{0xffffffffffffffff, -28},
|
||||
{0x00166bb7f0435c9e, -28},
|
||||
{0xffffffffffffffff, -29},
|
||||
{0xffffffffffffffff, -29},
|
||||
{0x001c06a5ec5433c6, -29},
|
||||
{0xffffffffffffffff, -30},
|
||||
{0xffffffffffffffff, -30},
|
||||
{0xffffffffffffffff, -30},
|
||||
{0x00118427b3b4a05c, -30},
|
||||
{0xffffffffffffffff, -31},
|
||||
{0xffffffffffffffff, -31},
|
||||
{0x0015e531a0a1c873, -31},
|
||||
{0xffffffffffffffff, -32},
|
||||
{0xffffffffffffffff, -32},
|
||||
{0x001b5e7e08ca3a8f, -32},
|
||||
{0xffffffffffffffff, -33},
|
||||
{0xffffffffffffffff, -33},
|
||||
{0xffffffffffffffff, -33},
|
||||
{0x00111b0ec57e649a, -33},
|
||||
{0xffffffffffffffff, -34},
|
||||
{0xffffffffffffffff, -34},
|
||||
{0x001561d276ddfdc0, -34},
|
||||
{0xffffffffffffffff, -35},
|
||||
{0xffffffffffffffff, -35},
|
||||
{0x001aba4714957d30, -35},
|
||||
{0xffffffffffffffff, -36},
|
||||
{0xffffffffffffffff, -36},
|
||||
{0xffffffffffffffff, -36},
|
||||
{0x0010b46c6cdd6e3e, -36},
|
||||
{0xffffffffffffffff, -37},
|
||||
{0xffffffffffffffff, -37},
|
||||
{0x0014e1878814c9ce, -37},
|
||||
{0xffffffffffffffff, -38},
|
||||
{0xffffffffffffffff, -38},
|
||||
{0x001a19e96a19fc41, -38},
|
||||
{0xffffffffffffffff, -39},
|
||||
{0xffffffffffffffff, -39},
|
||||
{0xffffffffffffffff, -39},
|
||||
{0x00105031e2503da9, -39},
|
||||
{0xffffffffffffffff, -40},
|
||||
{0xffffffffffffffff, -40},
|
||||
{0x0014643e5ae44d13, -40},
|
||||
{0xffffffffffffffff, -41},
|
||||
{0xffffffffffffffff, -41},
|
||||
{0x00197d4df19d6057, -41},
|
||||
{0xffffffffffffffff, -42},
|
||||
{0xffffffffffffffff, -42},
|
||||
{0x001fdca16e04b86d, -42},
|
||||
{0xffffffffffffffff, -43},
|
||||
{0xffffffffffffffff, -43},
|
||||
{0xffffffffffffffff, -43},
|
||||
{0x0013e9e4e4c2f344, -43},
|
||||
{0xffffffffffffffff, -44}
|
||||
};
|
||||
|
||||
// do better! (todo)
|
||||
void fast_four_digits(uint16_t value, char *buffer) {
|
||||
buffer[0] = char(value / 1000) + '0';
|
||||
value %= 1000;
|
||||
buffer[1] = char(value / 100) + '0';
|
||||
value %= 100;
|
||||
buffer[2] = char(value / 10) + '0';
|
||||
value %= 10;
|
||||
buffer[3] = char(value) + '0';
|
||||
}
|
||||
char * fast_dynamic_three_digits(uint16_t value, char *buffer) {
|
||||
if(value >= 100) {
|
||||
*(buffer++) = char(value / 100) + '0';
|
||||
value %= 100;
|
||||
*(buffer++) = char(value / 10) + '0';
|
||||
value %= 10;
|
||||
*(buffer++) =char(value) + '0';
|
||||
} else if(value >= 10) {
|
||||
*(buffer++) = char(value / 10) + '0';
|
||||
value %= 10;
|
||||
*(buffer++) =char(value) + '0';
|
||||
} else {
|
||||
*(buffer++) =char(value) + '0';
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
} // detail
|
||||
|
||||
|
||||
void serialize(double d, char *buffer) {
|
||||
char* orig = buffer;
|
||||
// TODO: include integer fast path?
|
||||
// Decompose double
|
||||
uint64_t bits{0};
|
||||
::memcpy(&bits, &d, sizeof(d));
|
||||
uint64_t mantissa = (bits & ((~0ULL) >> 12)) | (1ULL << 52);
|
||||
int exp = ((bits >> 52) & 0x7FF) - 1023;
|
||||
|
||||
// Handle uncommon cases here (todo)
|
||||
|
||||
// Handle if negative
|
||||
bool isNegative = bits >> 63;
|
||||
if (isNegative) {
|
||||
buffer[0] = '-';
|
||||
buffer++;
|
||||
}
|
||||
// e.g., 0.232 = 8358680908399641*2**-(55)
|
||||
std::cout << "we have "<< mantissa << " * 2^ " << exp << std::endl;
|
||||
|
||||
// Compute product
|
||||
detail::power_conversion conversion = detail::power_conversions[exp];
|
||||
int16_t pow10 = conversion.power;
|
||||
//pow10+=53-35;
|
||||
if (mantissa > conversion.mantissa_cutoff) { pow10--; }
|
||||
std::cout << "we have pow10= "<< pow10 << std::endl;
|
||||
|
||||
// todo: the <64> is weird and probably wrong.
|
||||
value128 total_product = compute_product_approximation<64>(pow10, mantissa);
|
||||
// todo : handle error
|
||||
uint64_t product = total_product.high;
|
||||
std::cout << "product is "<< product << std::endl;
|
||||
// Write out digits
|
||||
uint64_t first = product / 10000000000000000ULL;
|
||||
std::cout << "first:" <<first << std::endl;
|
||||
|
||||
product -= first * 10000000000000000ULL;
|
||||
std::cout << "first:" <<char('0' + char(first)) << std::endl;
|
||||
(*buffer++) = '0' + char(first);
|
||||
(*buffer++) = '.';
|
||||
std::cout <<"buffer comma="<<orig<<std::endl;
|
||||
|
||||
uint32_t lo8 = (uint32_t)(product % 100000000);
|
||||
uint32_t hi8 = (uint32_t)(product / 100000000);
|
||||
uint16_t lolo4 = uint16_t(lo8 % 10000);
|
||||
uint16_t lohi4 = uint16_t(lo8 / 10000);
|
||||
uint16_t hilo4 = uint16_t(hi8 % 10000);
|
||||
uint16_t hihi4 = uint16_t(hi8 / 10000);
|
||||
std::cout <<"hihi4="<<hihi4<<std::endl;
|
||||
detail::fast_four_digits(hihi4, buffer);
|
||||
std::cout <<"hihi4text="<<orig<<std::endl;
|
||||
|
||||
std::cout <<"hilo4="<<hilo4<<std::endl;
|
||||
detail::fast_four_digits(hilo4, buffer + 4);
|
||||
std::cout <<"lohi4="<<lohi4<<std::endl;
|
||||
detail::fast_four_digits(lohi4, buffer + 8);
|
||||
std::cout <<"lolo4="<<lohi4<<std::endl;
|
||||
detail::fast_four_digits(lolo4, buffer + 12);
|
||||
std::cout <<"hbufferihi4="<<orig<<std::endl;
|
||||
|
||||
// Remove trailing zeros
|
||||
char *mantissa_end = buffer - 1; // Remove '.' if unnecessary
|
||||
for (int i = 15; i >= 0; i--) {
|
||||
if (buffer[i] != '0') {
|
||||
mantissa_end = buffer + i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
std::cout << "digits = " <<(mantissa_end - buffer) << std::endl;
|
||||
buffer = mantissa_end; // Just overwrite what we had
|
||||
|
||||
// Add exponent
|
||||
int32_t target = -pow10 + 17 - 1 /* account for digit to left of decimal */;
|
||||
if (target == 0) {
|
||||
*buffer = '\0';
|
||||
return;
|
||||
}
|
||||
(*buffer++) = 'e';
|
||||
if (target < 0) {
|
||||
(*buffer++) = '-';
|
||||
target = -target;
|
||||
}
|
||||
std::cout << "target = " << target << std::endl;
|
||||
buffer = detail::fast_dynamic_three_digits(uint16_t(target),buffer);
|
||||
*buffer = '\0';
|
||||
|
||||
}
|
||||
|
||||
} // namespace fast_float
|
||||
|
||||
#endif
|
||||
@ -26,7 +26,7 @@ value128 compute_product_approximation(int64_t q, uint64_t w) {
|
||||
value128 firstproduct = full_multiplication(w, powers::power_of_five_128[index]);
|
||||
static_assert((bit_precision >= 0) && (bit_precision <= 64), " precision should be in (0,64]");
|
||||
constexpr uint64_t precision_mask = (bit_precision < 64) ?
|
||||
(uint64_t(0xFFFFFFFFFFFFFFFF) >> bit_precision)
|
||||
(uint64_t(0xFFFFFFFFFFFFFFFF) >> (bit_precision%64))
|
||||
: uint64_t(0xFFFFFFFFFFFFFFFF);
|
||||
if((firstproduct.high & precision_mask) == precision_mask) { // could further guard with (lower + w < lower)
|
||||
// regarding the second product, we only need secondproduct.high, but our expectation is that the compiler will optimize this extra work away if needed.
|
||||
|
||||
@ -52,7 +52,7 @@ function(fast_float_add_cpp_test TEST_NAME)
|
||||
endif()
|
||||
endfunction(fast_float_add_cpp_test)
|
||||
|
||||
|
||||
fast_float_add_cpp_test(serialization_test)
|
||||
fast_float_add_cpp_test(example_test)
|
||||
fast_float_add_cpp_test(example_comma_test)
|
||||
fast_float_add_cpp_test(basictest)
|
||||
|
||||
14
tests/serialization_test.cpp
Normal file
14
tests/serialization_test.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
#include "fast_float/binary_to_decimal.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
int main() {
|
||||
std::cout << "serialization test" << std::endl;
|
||||
char buffer[20];
|
||||
for(size_t i = 0; i < 20; i++) {
|
||||
buffer[i] = '\0';
|
||||
}
|
||||
fast_float::serialize(12345,buffer);
|
||||
std::cout << buffer << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user