Merge branch 'main' into dlemire/aqrit_magic

This commit is contained in:
Daniel Lemire 2020-11-23 13:48:06 -05:00
commit 426dd2a4a6
26 changed files with 1003 additions and 541 deletions

View File

@ -35,10 +35,11 @@ jobs:
update: true
msystem: ${{ matrix.msystem }}
install: ${{ matrix.install }}
- name: Build and Test
run: |
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=${{ matrix.type }} -DFASTFLOAT_TEST=ON ..
cmake --build . --verbose
ctest --output-on-failure -R basictest
- name: Prepare build dir
run: mkdir build
- name: Configure
run: cd build && cmake -DCMAKE_BUILD_TYPE=${{ matrix.type }} -DFASTFLOAT_TEST=ON ..
- name: Build
run: cmake --build build
- name: Run basic tests
run: cd build && ctest --output-on-failure -R basictest

View File

@ -1,20 +1,37 @@
name: Ubuntu 18.04 CI (GCC 7)
name: Ubuntu 18.04 CI (GCC 7, 6, 5)
on: [push, pull_request]
jobs:
ubuntu-build:
runs-on: ubuntu-18.04
strategy:
fail-fast: false
matrix:
include:
- {cxx: -DCMAKE_CXX_COMPILER=g++-5, arch: }
- {cxx: -DCMAKE_CXX_COMPILER=g++-6, arch: }
- {cxx: , arch: } # default=gcc7
- {cxx: , arch: -DCMAKE_CXX_FLAGS="-m32"} # default=gcc7
steps:
- uses: actions/checkout@v2
<<<<<<< HEAD
- name: Setup cmake
uses: jwlawson/actions-setup-cmake@v1.0
uses: jwlawson/actions-setup-cmake@v1.4
with:
cmake-version: '3.9.x'
- name: Use cmake
=======
>>>>>>> main
- name: Install older compilers
run: |
mkdir build &&
cd build &&
cmake -DFASTFLOAT_TEST=ON .. &&
cmake --build . &&
ctest --output-on-failure -R basictest
sudo -E dpkg --add-architecture i386
sudo -E apt-get update
sudo -E apt-get install -y --force-yes g++-5 g++-6 g++-5-multilib g++-6-multilib g++-multilib linux-libc-dev:i386 libc6:i386 libc6-dev:i386 libc6-dbg:i386
- name: Prepare build dir
run: mkdir build
- name: Configure
run: cd build && cmake ${{matrix.cxx}} ${{matrix.arch}} -DFASTFLOAT_TEST=ON ..
- name: Build
run: cmake --build build
- name: Run basic tests
run: cd build && ctest --output-on-failure -R basictest

View File

@ -1,20 +1,36 @@
name: Ubuntu 20.04 CI (GCC 9)
name: Ubuntu 20.04 CI (GCC 9, 8)
on: [push, pull_request]
jobs:
ubuntu-build:
runs-on: ubuntu-20.04
strategy:
fail-fast: false
matrix:
include:
- {cxx: -DCMAKE_CXX_COMPILER=g++-8, arch: }
- {cxx: , arch: } # default=gcc9
- {cxx: , arch: -DCMAKE_CXX_FLAGS="-m32"} # default=gcc9
steps:
- uses: actions/checkout@v2
<<<<<<< HEAD
- name: Setup cmake
uses: jwlawson/actions-setup-cmake@v1.0
uses: jwlawson/actions-setup-cmake@v1.4
with:
cmake-version: '3.9.x'
- name: Use cmake
=======
>>>>>>> main
- name: install older compilers
run: |
mkdir build &&
cd build &&
cmake -DFASTFLOAT_TEST=ON .. &&
cmake --build . &&
ctest --output-on-failure -R basictest
sudo -E dpkg --add-architecture i386
sudo -E apt-get update
sudo -E apt-get install -y g++-8 g++-8-multilib g++-multilib linux-libc-dev:i386 libc6:i386 libc6-dev:i386 libc6-dbg:i386
- name: Prepare build dir
run: mkdir build
- name: Configure
run: cd build && cmake ${{matrix.cxx}} ${{matrix.arch}} -DFASTFLOAT_TEST=ON ..
- name: Build
run: cmake --build build
- name: Run basic tests
run: cd build && ctest --output-on-failure -R basictest

View File

@ -6,20 +6,22 @@ jobs:
ci:
name: windows-vs16
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
include:
- {gen: Visual Studio 16 2019, arch: Win32}
- {gen: Visual Studio 16 2019, arch: x64}
steps:
- uses: actions/checkout@v2
- name: 'Run CMake with VS16'
uses: lukka/run-cmake@v2
with:
cmakeListsOrSettingsJson: CMakeListsTxtAdvanced
cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt'
buildDirectory: "${{ github.workspace }}/../../_temp/windows"
cmakeBuildType: Release
buildWithCMake: true
cmakeGenerator: VS16Win64
cmakeAppendedArgs: -DFASTFLOAT_TEST=ON
buildWithCMakeArgs: --config Release
- name: 'Run CTest'
run: ctest -C Release --output-on-failure -R basictest
working-directory: "${{ github.workspace }}/../../_temp/windows"
- name: checkout
uses: actions/checkout@v2
- name: Configure
run: |
mkdir build
cd build && cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -DFASTFLOAT_TEST=ON ..
- name: Build
run: cmake --build build --config Release --parallel
- name: Run basic tests
run: |
cd build
ctest -C Release --output-on-failure -R basictest

View File

@ -6,20 +6,22 @@ jobs:
ci:
name: windows-vs16
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
include:
- {gen: Visual Studio 16 2019, arch: Win32}
- {gen: Visual Studio 16 2019, arch: x64}
steps:
- uses: actions/checkout@v2
- name: 'Run CMake with VS16'
uses: lukka/run-cmake@v2
with:
cmakeListsOrSettingsJson: CMakeListsTxtAdvanced
cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt'
buildDirectory: "${{ github.workspace }}/../../_temp/windows"
cmakeBuildType: Release
buildWithCMake: true
cmakeGenerator: VS16Win64
cmakeAppendedArgs: -T ClangCL -DFASTFLOAT_TEST=ON
buildWithCMakeArgs: --config Release
- name: 'Run CTest'
run: ctest -C Release -R basictest --output-on-failure
working-directory: "${{ github.workspace }}/../../_temp/windows"
- name: checkout
uses: actions/checkout@v2
- name: Configure
run: |
mkdir build
cd build && cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -T ClangCL -DFASTFLOAT_TEST=ON ..
- name: Build
run: cmake --build build --config Release --parallel
- name: Run basic tests
run: |
cd build
ctest -C Release --output-on-failure -R basictest

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
build/*
Testing/*
.cache/
compile_commands.json

225
.travis.yml Normal file
View File

@ -0,0 +1,225 @@
language: cpp
dist: bionic
cache:
directories:
- $HOME/.dep_cache
env:
global:
- fastfloat_DEPENDENCY_CACHE_DIR=$HOME/.dep_cache
# the ppc64le and s390x images use cmake 3.10, but fast_float requires 3.11.
# so we compile cmake from source in those images.
# - tried the kitware ppa but that is using 3.10 as well
# - tried also using snap to get a more recent version but that failed with
# udev errors.
matrix:
include:
- arch: ppc64le
os: linux
env:
- CMAKE_SRC="https://github.com/Kitware/CMake/releases/download/v3.11.4/cmake-3.11.4.tar.gz"
- arch: s390x
os: linux
env:
- CMAKE_SRC="https://github.com/Kitware/CMake/releases/download/v3.11.4/cmake-3.11.4.tar.gz"
- arch: amd64
os: linux
- arch: amd64
os: linux
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-8
env:
- COMPILER="CC=gcc-8 && CXX=g++-8"
compiler: gcc-8
- arch: amd64
os: linux
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-9
env:
- COMPILER="CC=gcc-9 && CXX=g++-9"
compiler: gcc-9
- arch: amd64
os: linux
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-10
env:
- COMPILER="CC=gcc-10 && CXX=g++-10"
compiler: gcc-10
- arch: amd64
os: linux
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-10
env:
- COMPILER="CC=gcc-10 && CXX=g++-10"
- SANITIZE="on"
compiler: gcc-10-sanitize
- arch: amd64
os: linux
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-10
env:
- COMPILER="CC=gcc-10 && CXX=g++-10"
- STATIC="on"
acompiler: gcc-10-static
- arch: amd64
os: linux
addons:
apt:
sources:
- llvm-toolchain-bionic-6.0
packages:
- clang-6.0
env:
- COMPILER="CC=clang-6.0 && CXX=clang++-6.0"
compiler: clang-6
- arch: amd64
os: linux
addons:
apt:
sources:
- llvm-toolchain-bionic-7
packages:
- clang-7
env:
- COMPILER="CC=clang-7 && CXX=clang++-7"
compiler: clang-7
- arch: amd64
os: linux
addons:
apt:
sources:
- llvm-toolchain-bionic-8
packages:
- clang-8
env:
- COMPILER="CC=clang-8 && CXX=clang++-8"
compiler: clang-8
- arch: amd64
os: linux
addons:
apt:
sources:
- llvm-toolchain-bionic-9
packages:
- clang-9
env:
- COMPILER="CC=clang-9 && CXX=clang++-9"
compiler: clang-9
- arch: amd64
os: linux
addons:
apt:
packages:
- clang-10
sources:
- ubuntu-toolchain-r-test
- sourceline: 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main'
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
env:
- COMPILER="CC=clang-10 && CXX=clang++-10"
compiler: clang-10
- arch: amd64
os: linux
addons:
apt:
packages:
- clang-10
sources:
- ubuntu-toolchain-r-test
- sourceline: 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main'
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
env:
- COMPILER="CC=clang-10 && CXX=clang++-10"
- STATIC="on"
compiler: clang-10-static
- arch: amd64
os: linux
addons:
apt:
packages:
- clang-10
sources:
- ubuntu-toolchain-r-test
- sourceline: 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main'
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
env:
- COMPILER="CC=clang-10 && CXX=clang++-10"
- SANITIZE="on"
compiler: clang-10-sanitize
before_install:
- eval "${COMPILER}"
install:
- |
if [ "$CMAKE_SRC" != "" ] ; then
set -x
set -e
sudo -E apt remove --purge cmake
sudo -E apt-get update
sudo -E apt-get install -y build-essential libssl-dev
mkdir cmake_src
pushd cmake_src
wget "$CMAKE_SRC"
tar xfz $(basename "$CMAKE_SRC")
pushd $(basename "$CMAKE_SRC" | sed "s:.tar.gz::")
./bootstrap
make -j2
sudo make install
popd
popd
set +x
fi
- echo ${PATH}
- which cmake
- cmake --version
- which ${CC}
- ${CC} --version
- which ${CXX}
- ${CXX} --version
script:
- mkdir build
- cd build
- cmake -DFASTFLOAT_TEST=ON ..
- make -j2
- ctest --output-on-failure -R basictest

View File

@ -1 +1,2 @@
Daniel Lemire
João Paulo Magalhaes

View File

@ -94,13 +94,15 @@ parsed_number_string parse_number_string(const char *p, const char *pend, chars_
// a multiplication by 10 is cheaper than an arbitrary integer
// multiplication
i = 10 * i +
(*p - '0'); // might overflow, we will handle the overflow later
uint64_t(*p - '0'); // might overflow, we will handle the overflow later
++p;
}
int64_t exponent = 0;
if ((p != pend) && (*p == '.')) {
++p;
const char *first_after_period = p;
#if FASTFLOAT_IS_BIG_ENDIAN == 0
// Fast approach only tested under little endian systems
if ((p + 8 <= pend) && is_made_of_eight_digits_fast(p)) {
i = i * 100000000 + parse_eight_digits_unrolled(p); // in rare cases, this will overflow, but that's ok
p += 8;
@ -109,6 +111,7 @@ parsed_number_string parse_number_string(const char *p, const char *pend, chars_
p += 8;
}
}
#endif
while ((p != pend) && is_integer(*p)) {
uint8_t digit = uint8_t(*p - '0');
++p;
@ -219,6 +222,7 @@ fastfloat_really_inline decimal parse_decimal(const char *p, const char *pend) n
++p;
}
}
#if FASTFLOAT_IS_BIG_ENDIAN == 0
// We expect that this loop will often take the bulk of the running time
// because when a value has lots of digits, these digits often
while ((p + 8 <= pend) && (answer.num_digits + 8 < max_digits)) {
@ -231,6 +235,7 @@ fastfloat_really_inline decimal parse_decimal(const char *p, const char *pend) n
answer.num_digits += 8;
p += 8;
}
#endif
while ((p != pend) && is_integer(*p)) {
if (answer.num_digits < max_digits) {
answer.digits[answer.num_digits] = uint8_t(*p - '0');
@ -259,11 +264,15 @@ fastfloat_really_inline decimal parse_decimal(const char *p, const char *pend) n
}
answer.decimal_point += (neg_exp ? -exp_number : exp_number);
}
answer.decimal_point += answer.num_digits;
answer.decimal_point += int32_t(answer.num_digits);
if(answer.num_digits > max_digits) {
answer.truncated = true;
answer.num_digits = max_digits;
}
// In very rare cases, we may have fewer than 19 digits, we want to be able to reliably
// assume that all digits up to max_digit_without_overflow have been initialized.
for(uint32_t i = answer.num_digits; i < max_digit_without_overflow; i++) { answer.digits[i] = 0; }
return answer;
}
} // namespace fast_float

View File

@ -62,6 +62,7 @@ namespace {
}
} // namespace
// w * 10 ** q
// The returned value should be a valid ieee64 number that simply need to be packed.
// However, in some very rare cases, the computation will fail. In such cases, we
@ -71,13 +72,13 @@ template <typename binary>
fastfloat_really_inline
adjusted_mantissa compute_float(int64_t q, uint64_t w) noexcept {
adjusted_mantissa answer;
if ((w == 0) || (q < smallest_power_of_five)) {
if ((w == 0) || (q < binary::smallest_power_of_ten())) {
answer.power2 = 0;
answer.mantissa = 0;
// result should be zero
return answer;
}
if (q > largest_power_of_five) {
if (q > binary::largest_power_of_ten()) {
// we want to get infinity:
answer.power2 = binary::infinite_power();
answer.mantissa = 0;
@ -93,23 +94,28 @@ adjusted_mantissa compute_float(int64_t q, uint64_t w) noexcept {
// 1. We need the implicit bit
// 2. We need an extra bit for rounding purposes
// 3. We might lose a bit due to the "upperbit" routine (result too small, requiring a shift)
value128 product = compute_product_approximation<binary::mantissa_explicit_bits() + 3>(q, w);
if(product.low == 0xFFFFFFFFFFFFFFFF) { // could guard it further
// In some very rare cases, this could happen, in which case we might need a more accurate
// computation that what we can provide cheaply. This is very, very unlikely.
answer.power2 = -1; // This (a negative value) indicates an error condition.
return answer;
//
const bool inside_safe_exponent = (q >= -27) && (q <= 55); // always good because 5**q <2**128 when q>=0,
// and otherwise, for q<0, we have 5**-q<2**64 and the 128-bit reciprocal allows for exact computation.
if(!inside_safe_exponent) {
answer.power2 = -1; // This (a negative value) indicates an error condition.
return answer;
}
}
// The "compute_product_approximation" function can be slightly slower than a branchless approach:
// value128 product = compute_product(q, w);
// but in practice, we can win big with the compute_product_approximation if its additional branch
// is easily predicted. Which is best is data specific.
uint64_t upperbit = product.high >> 63;
int upperbit = int(product.high >> 63);
answer.mantissa = product.high >> (upperbit + 64 - binary::mantissa_explicit_bits() - 3);
lz += int(1 ^ upperbit);
answer.power2 = power(int(q)) - lz - binary::minimum_exponent() + 1;
answer.power2 = int(power(int(q)) + upperbit - lz - binary::minimum_exponent());
if (answer.power2 <= 0) { // we have a subnormal?
// Here have that answer.power2 <= 0 so -answer.power2 >= 0
if(-answer.power2 + 1 >= 64) { // if we have more than 64 bits below the minimum exponent, you have a zero for sure.
@ -144,7 +150,7 @@ adjusted_mantissa compute_float(int64_t q, uint64_t w) noexcept {
// answer.mantissa = product.high >> (upperbit + 64 - binary::mantissa_explicit_bits() - 3);
// ... we dropped out only zeroes. But if this happened, then we can go back!!!
if((answer.mantissa << (upperbit + 64 - binary::mantissa_explicit_bits() - 3)) == product.high) {
answer.mantissa &= ~1; // flip it so that we do not round up
answer.mantissa &= ~uint64_t(1); // flip it so that we do not round up
}
}

View File

@ -347,16 +347,16 @@ const uint64_t power_of_five_128[]= {
0xa2425ff75e14fc31,0xa1258379a94d028d,
0xcad2f7f5359a3b3e,0x96ee45813a04330,
0xfd87b5f28300ca0d,0x8bca9d6e188853fc,
0x9e74d1b791e07e48,0x775ea264cf55347d,
0xc612062576589dda,0x95364afe032a819d,
0xf79687aed3eec551,0x3a83ddbd83f52204,
0x9abe14cd44753b52,0xc4926a9672793542,
0xc16d9a0095928a27,0x75b7053c0f178293,
0xf1c90080baf72cb1,0x5324c68b12dd6338,
0x971da05074da7bee,0xd3f6fc16ebca5e03,
0xbce5086492111aea,0x88f4bb1ca6bcf584,
0xec1e4a7db69561a5,0x2b31e9e3d06c32e5,
0x9392ee8e921d5d07,0x3aff322e62439fcf,
0x9e74d1b791e07e48,0x775ea264cf55347e,
0xc612062576589dda,0x95364afe032a819e,
0xf79687aed3eec551,0x3a83ddbd83f52205,
0x9abe14cd44753b52,0xc4926a9672793543,
0xc16d9a0095928a27,0x75b7053c0f178294,
0xf1c90080baf72cb1,0x5324c68b12dd6339,
0x971da05074da7bee,0xd3f6fc16ebca5e04,
0xbce5086492111aea,0x88f4bb1ca6bcf585,
0xec1e4a7db69561a5,0x2b31e9e3d06c32e6,
0x9392ee8e921d5d07,0x3aff322e62439fd0,
0xb877aa3236a4b449,0x9befeb9fad487c3,
0xe69594bec44de15b,0x4c2ebe687989a9b4,
0x901d7cf73ab0acd9,0xf9d37014bf60a11,

View File

@ -3,11 +3,56 @@
#include <cfloat>
#include <cstdint>
#include <cassert>
#if (defined(__i386) || defined(__i386__) || defined(_M_IX86) \
|| defined(__arm__) \
|| defined(__MINGW32__))
#define FASTFLOAT_32BIT
#elif (defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) \
|| defined(__amd64) || defined(__aarch64__) || defined(_M_ARM64) \
|| defined(__MINGW64__) \
|| defined(__s390x__) \
|| (defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || defined(__PPC64LE__)))
#define FASTFLOAT_64BIT
#else
#error Unknown platform
#endif
#if ((defined(_WIN32) || defined(_WIN64)) && !defined(__clang__))
#include <intrin.h>
#endif
#if defined(_MSC_VER) && !defined(__clang__)
#define FASTFLOAT_VISUAL_STUDIO 1
#endif
#ifdef _WIN32
#define FASTFLOAT_IS_BIG_ENDIAN 0
#else
#if defined(__APPLE__) || defined(__FreeBSD__)
#include <machine/endian.h>
#else
#include <endian.h>
#endif
#
#ifndef __BYTE_ORDER__
// safe choice
#define FASTFLOAT_IS_BIG_ENDIAN 0
#endif
#
#ifndef __ORDER_LITTLE_ENDIAN__
// safe choice
#define FASTFLOAT_IS_BIG_ENDIAN 0
#endif
#
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define FASTFLOAT_IS_BIG_ENDIAN 0
#else
#define FASTFLOAT_IS_BIG_ENDIAN 1
#endif
#endif
#ifdef FASTFLOAT_VISUAL_STUDIO
#define fastfloat_really_inline __forceinline
#else
@ -61,29 +106,40 @@ struct value128 {
/* result might be undefined when input_num is zero */
fastfloat_really_inline int leading_zeroes(uint64_t input_num) {
assert(input_num > 0);
#ifdef FASTFLOAT_VISUAL_STUDIO
#if defined(_M_X64) || defined(_M_ARM64)
unsigned long leading_zero = 0;
// Search the mask data from most significant bit (MSB)
// to least significant bit (LSB) for a set bit (1).
if (_BitScanReverse64(&leading_zero, input_num))
return (int)(63 - leading_zero);
else
return 64;
_BitScanReverse64(&leading_zero, input_num);
return (int)(63 - leading_zero);
#else
int last_bit = 0;
if(input_num & uint64_t(0xffffffff00000000)) input_num >>= 32, last_bit |= 32;
if(input_num & uint64_t( 0xffff0000)) input_num >>= 16, last_bit |= 16;
if(input_num & uint64_t( 0xff00)) input_num >>= 8, last_bit |= 8;
if(input_num & uint64_t( 0xf0)) input_num >>= 4, last_bit |= 4;
if(input_num & uint64_t( 0xc)) input_num >>= 2, last_bit |= 2;
if(input_num & uint64_t( 0x2)) input_num >>= 1, last_bit |= 1;
return 63 - last_bit;
#endif
#else
return __builtin_clzll(input_num);
#endif
}
#if defined(_WIN32) && !defined(__clang__)
// Note MinGW falls here too
#include <intrin.h>
#ifdef FASTFLOAT_32BIT
#if !defined(_M_X64) && !defined(_M_ARM64) // _umul128 for x86, arm
// this is a slow emulation routine for 32-bit Windows
//
#if (!defined(_WIN32)) || defined(__MINGW32__)
// slow emulation routine for 32-bit
fastfloat_really_inline uint64_t __emulu(uint32_t x, uint32_t y) {
return x * (uint64_t)y;
return x * (uint64_t)y;
}
#endif
// slow emulation routine for 32-bit
#if !defined(__MINGW64__)
fastfloat_really_inline uint64_t _umul128(uint64_t ab, uint64_t cd,
uint64_t *hi) {
uint64_t ad = __emulu((uint32_t)(ab >> 32), (uint32_t)cd);
@ -95,39 +151,35 @@ fastfloat_really_inline uint64_t _umul128(uint64_t ab, uint64_t cd,
(adbc_carry << 32) + !!(lo < bd);
return lo;
}
#endif
#endif // !__MINGW64__
fastfloat_really_inline value128 full_multiplication(uint64_t value1,
uint64_t value2) {
#endif // FASTFLOAT_32BIT
// compute 64-bit a*b
fastfloat_really_inline value128 full_multiplication(uint64_t a,
uint64_t b) {
value128 answer;
#ifdef _M_ARM64
// ARM64 has native support for 64-bit multiplications, no need to emultate
answer.high = __umulh(value1, value2);
answer.low = value1 * value2;
#else
answer.low =
_umul128(value1, value2, &answer.high); // _umul128 not available on ARM64
#endif // _M_ARM64
return answer;
}
#else
// compute value1 * value2
fastfloat_really_inline value128 full_multiplication(uint64_t value1,
uint64_t value2) {
value128 answer;
__uint128_t r = ((__uint128_t)value1) * value2;
// ARM64 has native support for 64-bit multiplications, no need to emulate
answer.high = __umulh(a, b);
answer.low = a * b;
#elif defined(FASTFLOAT_32BIT) || (defined(_WIN64))
answer.low = _umul128(a, b, &answer.high); // _umul128 not available on ARM64
#elif defined(FASTFLOAT_64BIT)
__uint128_t r = ((__uint128_t)a) * b;
answer.low = uint64_t(r);
answer.high = uint64_t(r >> 64);
#else
#error Not implemented
#endif
return answer;
}
#endif
struct adjusted_mantissa {
uint64_t mantissa;
int power2; // a negative value indicate an invalid result
uint64_t mantissa{0};
int power2{0}; // a negative value indicate an invalid result
adjusted_mantissa() = default;
// bool operator==(const adjusted_mantissa &o) const = default;
bool operator==(const adjusted_mantissa &o) const {
@ -136,10 +188,10 @@ struct adjusted_mantissa {
};
struct decimal {
uint32_t num_digits;
int32_t decimal_point;
bool negative;
bool truncated;
uint32_t num_digits{0};
int32_t decimal_point{0};
bool negative{false};
bool truncated{false};
uint8_t digits[max_digits];
decimal() = default;
// Copies are not allowed since this is a fat object.
@ -149,10 +201,19 @@ struct decimal {
// Moves are allowed:
decimal(decimal &&) = default;
decimal &operator=(decimal &&other) = default;
// Generates a mantissa by truncating to 19 digits; this function assumes
// that num_digits >= 19 (the caller is responsible for the check).
// Generates a mantissa by truncating to 19 digits.
// This function should be reasonably fast.
// Note that the user is responsible to ensure that digits are
// initialized to zero when there are fewer than 19.
inline uint64_t to_truncated_mantissa() {
#if FASTFLOAT_IS_BIG_ENDIAN == 1
uint64_t mantissa = 0;
for (uint32_t i = 0; i < max_digit_without_overflow;
i++) {
mantissa = mantissa * 10 + digits[i]; // can be accelerated
}
return mantissa;
#else
uint64_t val;
// 8 first digits
::memcpy(&val, digits, sizeof(uint64_t));
@ -172,10 +233,11 @@ struct decimal {
mantissa = mantissa * 10 + digits[i]; // can be accelerated
}
return mantissa;
#endif
}
// Generate san exponent matching to_truncated_mantissa()
inline int32_t to_truncated_exponent() {
return decimal_point - max_digit_without_overflow;
return decimal_point - int32_t(max_digit_without_overflow);
}
};
@ -195,6 +257,8 @@ template <typename T> struct binary_format {
static constexpr int max_exponent_round_to_even();
static constexpr int min_exponent_round_to_even();
static constexpr uint64_t max_mantissa_fast_path();
static constexpr int largest_power_of_ten();
static constexpr int smallest_power_of_ten();
static constexpr T exact_power_of_ten(int64_t power);
};
@ -277,6 +341,25 @@ constexpr float binary_format<float>::exact_power_of_ten(int64_t power) {
return powers_of_ten_float[power];
}
template <>
constexpr int binary_format<double>::largest_power_of_ten() {
return 308;
}
template <>
constexpr int binary_format<float>::largest_power_of_ten() {
return 38;
}
template <>
constexpr int binary_format<double>::smallest_power_of_ten() {
return -342;
}
template <>
constexpr int binary_format<float>::smallest_power_of_ten() {
return -65;
}
} // namespace fast_float
// for convenience:

View File

@ -77,7 +77,7 @@ from_chars_result from_chars(const char *first, const char *last,
from_chars_result answer;
while ((first != last) && fast_float::is_space(*first)) {
while ((first != last) && fast_float::is_space(uint8_t(*first))) {
first++;
}
if (first == last) {
@ -107,7 +107,16 @@ from_chars_result from_chars(const char *first, const char *last,
word |= uint64_t(am.power2) << binary_format<T>::mantissa_explicit_bits();
word = pns.negative
? word | (uint64_t(1) << binary_format<T>::sign_index()) : word;
::memcpy(&value, &word, sizeof(T));
#if FASTFLOAT_IS_BIG_ENDIAN == 1
if (std::is_same<T, float>::value) {
::memcpy(&value, (char *)&word + 4, sizeof(T)); // extract value at offset 4-7 if float on big-endian
} else {
::memcpy(&value, &word, sizeof(T));
}
#else
// For little-endian systems:
::memcpy(&value, &word, sizeof(T));
#endif
return answer;
}

View File

@ -8,7 +8,7 @@ for q in range(-342,0):
z = 0
while( (1<<z) < power5) :
z += 1
if(q >= -17):
if(q >= -27):
b = z + 127
c = 2 ** b // power5 + 1
format(c)

View File

@ -1,9 +1,33 @@
# FetchContent requires cmake >=3.11
# see https://cmake.org/cmake/help/v3.11/module/FetchContent.html
cmake_minimum_required(VERSION 3.11 FATAL_ERROR)
include(FetchContent)
FetchContent_Declare(doctest
GIT_REPOSITORY https://github.com/onqtam/doctest.git
GIT_TAG 2.4.1)
# FetchContent_MakeAvailable() was only introduced in 3.14
# https://cmake.org/cmake/help/v3.14/release/3.14.html#modules
# FetchContent_MakeAvailable(doctest)
FetchContent_GetProperties(doctest)
if(NOT doctest_POPULATED)
FetchContent_Populate(doctest)
add_subdirectory(${doctest_SOURCE_DIR} ${doctest_BINARY_DIR})
endif()
function(fast_float_add_cpp_test TEST_NAME)
add_executable(${TEST_NAME} ${TEST_NAME}.cpp)
add_test(${TEST_NAME} ${TEST_NAME})
target_link_libraries(${TEST_NAME} PUBLIC fast_float)
if(NOT WIN32)
target_compile_options(${TEST_NAME} PUBLIC -Werror -Wall -Wextra -Weffc++)
target_compile_options(${TEST_NAME} PUBLIC -Wsign-compare -Wshadow -Wwrite-strings -Wpointer-arith -Winit-self -Wconversion -Wsign-conversion)
endif()
target_link_libraries(${TEST_NAME} PUBLIC fast_float doctest)
endfunction(fast_float_add_cpp_test)
fast_float_add_cpp_test(powersoffive_hardround)
fast_float_add_cpp_test(short_random_string)
fast_float_add_cpp_test(exhaustive32_midpoint)
fast_float_add_cpp_test(random_string)

View File

@ -1,120 +1,51 @@
#define DOCTEST_CONFIG_SUPER_FAST_ASSERTS
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include <doctest/doctest.h>
#include "fast_float/fast_float.h"
#include <iomanip>
inline void Assert(bool Assertion) {
if (!Assertion)
throw std::runtime_error("bug");
TEST_CASE("leading_zeroes") {
constexpr const uint64_t bit = 1;
CHECK(fast_float::leading_zeroes(bit << 0) == 63);
CHECK(fast_float::leading_zeroes(bit << 1) == 62);
CHECK(fast_float::leading_zeroes(bit << 2) == 61);
CHECK(fast_float::leading_zeroes(bit << 61) == 2);
CHECK(fast_float::leading_zeroes(bit << 62) == 1);
CHECK(fast_float::leading_zeroes(bit << 63) == 0);
}
template <typename T> std::string to_string(T d) {
std::string s(64, '\0');
auto written = std::snprintf(&s[0], s.size(), "%.*e",
std::numeric_limits<T>::max_digits10 - 1, d);
s.resize(written);
return s;
#define iHexAndDec(v) std::hex << "0x" << (v) << " (" << std::dec << (v) << ")"
#define fHexAndDec(v) std::hexfloat << (v) << " (" << std::defaultfloat << (v) << ")"
void test_full_multiplication(uint64_t lhs, uint64_t rhs, uint64_t expected_lo, uint64_t expected_hi) {
fast_float::value128 v;
v = fast_float::full_multiplication(lhs, rhs);
INFO("lhs=" << iHexAndDec(lhs) << " " << "rhs=" << iHexAndDec(rhs)
<< "\n actualLo=" << iHexAndDec(v.low) << " " << "actualHi=" << iHexAndDec(v.high)
<< "\n expectedLo=" << iHexAndDec(expected_lo) << " " << "expectedHi=" << iHexAndDec(expected_hi));
CHECK_EQ(v.low, expected_lo);
CHECK_EQ(v.high, expected_hi);
v = fast_float::full_multiplication(rhs, lhs);
CHECK_EQ(v.low, expected_lo);
CHECK_EQ(v.high, expected_hi);
}
template <typename T> std::string to_long_string(T d) {
std::string s(4096, '\0');
auto written = std::snprintf(&s[0], s.size(), "%.*e",
std::numeric_limits<T>::max_digits10 * 10, d);
s.resize(written);
return s;
}
bool basic_test_32bit(std::string vals) {
std::cout << " parsing " << vals << std::endl;
float result_value;
auto result = fast_float::from_chars(vals.data(), vals.data() + vals.size(),
result_value);
if (result.ec != std::errc()) {
std::cerr << " I could not parse " << vals << std::endl;
return false;
}
std::cout << std::hexfloat << result_value << std::endl;
std::cout << std::dec;
return true;
}
bool basic_test_32bit(std::string vals, float val) {
std::cout << " parsing " << vals << std::endl;
float result_value;
auto result = fast_float::from_chars(vals.data(), vals.data() + vals.size(),
result_value);
if (result.ec != std::errc()) {
std::cerr << " I could not parse " << vals << std::endl;
return false;
}
if(copysign(1,result_value) != copysign(1,val)) {
std::cerr << vals << std::endl;
std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << val
<< std::endl;
return false;
} else if (std::isnan(val)) {
if (!std::isnan(result_value)) {
std::cerr << vals << std::endl;
std::cerr << "not nan" << result_value << std::endl;
return false;
}
} else if (result_value != val) {
std::cerr << vals << std::endl;
std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << val
<< std::endl;
std::cerr << std::dec;
uint32_t word;
memcpy(&word, &result_value, sizeof(word));
std::cout << "got mantissa = " << (word & ((1<<23)-1)) << std::endl;
memcpy(&word, &val, sizeof(word));
std::cout << "wanted mantissa = " << (word & ((1<<23)-1)) << std::endl;
std::cerr << "string: " << vals << std::endl;
return false;
}
std::cout << std::hexfloat << result_value << " == " << val << std::endl;
std::cout << std::dec;
return true;
}
bool basic_test_32bit(float val) {
std::string long_vals = to_long_string(val);
std::string vals = to_string(val);
return basic_test_32bit(long_vals, val) && basic_test_32bit(vals, val);
}
bool basic_test_64bit(std::string vals, double val) {
std::cout << " parsing " << vals << std::endl;
double result_value;
auto result = fast_float::from_chars(vals.data(), vals.data() + vals.size(),
result_value);
if (result.ec != std::errc()) {
std::cerr << " I could not parse " << vals << std::endl;
return false;
}
if(copysign(1,result_value) != copysign(1,val)) {
std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << val
<< std::endl;
return false;
} else if (std::isnan(val)) {
if (!std::isnan(result_value)) {
std::cerr << vals << std::endl;
std::cerr << "not nan" << result_value << std::endl;
return false;
}
} else if (result_value != val) {
std::cerr << vals << std::endl;
std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << val
<< std::endl;
std::cerr << std::dec;
std::cerr << "string: " << vals << std::endl;
return false;
}
std::cout << std::hexfloat << result_value << " == " << val << std::endl;
return true;
TEST_CASE("full_multiplication") {
constexpr const uint64_t bit = 1;
// lhs rhs lo hi
test_full_multiplication(bit << 0 , bit << 0, 1u , 0u);
test_full_multiplication(bit << 0 , bit << 63, bit << 63, 0u);
test_full_multiplication(bit << 1 , bit << 63, 0u , 1u);
test_full_multiplication(bit << 63, bit << 0, bit << 63, 0u);
test_full_multiplication(bit << 63, bit << 1, 0u , 1u);
test_full_multiplication(bit << 63, bit << 2, 0u , 2u);
test_full_multiplication(bit << 63, bit << 63, 0u , bit << 62);
}
bool issue8() {
std::cout << __func__ << std::endl;
TEST_CASE("issue8") {
const char* s =
"3."
"141592653589793238462643383279502884197169399375105820974944592307816406"
@ -132,99 +63,62 @@ bool issue8() {
// Parse all but the last i chars. We should still get 3.141ish.
double d = 0.0;
auto answer = fast_float::from_chars(s, s + strlen(s) - i, d);
if(answer.ec != std::errc()) { std::cerr << "parsing failure\n"; return false; }
if(d != 0x1.921fb54442d18p+1) {
printf("%.*s\n", int(strlen(s) - i), s);
std::cout << std::hexfloat << d << std::endl;
std::cout << std::defaultfloat << d << std::endl;
return false;
}
CHECK_MESSAGE(answer.ec == std::errc(), "i=" << i);
CHECK_MESSAGE(d == 0x1.921fb54442d18p+1, "i=" << i << "\n"
<< std::string(s, strlen(s) - size_t(i)) << "\n"
<< std::hexfloat << d << "\n"
<< std::defaultfloat << "\n");
}
return true;
}
bool check_behavior() {
std::cout << __func__ << std::endl;
const std::string input = "abc";
double result;
auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result);
if(answer.ec != std::errc()) {
std::cerr << "parsing failure as expected\n";
// specification says ptr should point at first
if(answer.ptr != input.data()) {
std::cerr << "If there is no pattern match, we should have ptr equals first\n";
return false;
}
return true;
}
std::cout << "parsed the number " << result << std::endl;
return false;
}
bool issue19() {
std::cout << __func__ << std::endl;
const std::string input = "3.14e";
double result;
auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result);
if(answer.ec != std::errc()) {
std::cerr << "We want to parse up to 3.14\n";
return false;
}
std::cout << "parsed the number " << result << std::endl;
if(answer.ptr == input.data() + 4) {
std::cout << "Parsed the number and stopped at the right character." << result << std::endl;
return true;
}
std::cout << "stopped after " << (answer.ptr - input.data()) << " characters" << std::endl;
return false;
TEST_CASE("check_behavior") {
const std::string input = "abc";
double result;
auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result);
CHECK_MESSAGE(answer.ec != std::errc(), "expected parse failure");
CHECK_MESSAGE(answer.ptr == input.data(), "If there is no pattern match, we should have ptr equals first");
}
bool test_scientific_only() {
std::cout << __func__ << std::endl;
TEST_CASE("issue19") {
const std::string input = "3.14e";
double result;
auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result);
CHECK_MESSAGE(answer.ec == std::errc(), "We want to parse up to 3.14\n");
CHECK_MESSAGE(answer.ptr == input.data() + 4,
"Parsed the number " << result
<< " and stopped at the wrong character: after " << (answer.ptr - input.data()) << " characters");
}
TEST_CASE("scientific_only") {
// first, we try with something that should fail...
std::string input = "3.14";
double result;
auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result, fast_float::chars_format::scientific);
if(answer.ec == std::errc()) {
std::cerr << "It is not scientific!\n";
return false;
}
CHECK_MESSAGE(answer.ec != std::errc(), "It is not scientific! Parsed: " << result);
input = "3.14e10";
result;
answer = fast_float::from_chars(input.data(), input.data()+input.size(), result, fast_float::chars_format::scientific);
if(answer.ec != std::errc()) {
std::cerr << "It is scientific!\n";
return false;
}
std::cout << "parsed the number " << result << std::endl;
if(answer.ptr == input.data() + input.size()) {
std::cout << "Parsed the number and stopped at the right character." << result << std::endl;
return true;
}
return false;
CHECK_MESSAGE(answer.ec == std::errc(), "It is scientific! Parsed: " << result);
CHECK_MESSAGE(answer.ptr == input.data() + input.size(),
"Parsed the number " << result
<< " and stopped at the wrong character: after " << (answer.ptr - input.data()) << " characters");
}
bool test_fixed_only() {
std::cout << __func__ << std::endl;
TEST_CASE("test_fixed_only") {
const std::string input = "3.14e10";
double result;
auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result, fast_float::chars_format::fixed);
if(answer.ec != std::errc()) {
std::cerr << "We want to parse up to 3.14\n";
return false;
}
std::cout << "parsed the number " << result << std::endl;
if(answer.ptr == input.data() + 4) {
std::cout << "Parsed the number and stopped at the right character." << result << std::endl;
return true;
}
return false;
CHECK_MESSAGE(answer.ec == std::errc(), "We want to parse up to 3.14; parsed: " << result);
CHECK_MESSAGE(answer.ptr == input.data() + 4,
"Parsed the number " << result
<< " and stopped at the wrong character: after " << (answer.ptr - input.data()) << " characters");
}
static const double testing_power_of_ten[] = {
static const double testing_power_of_ten[] = {
1e-307, 1e-306, 1e-305, 1e-304, 1e-303, 1e-302, 1e-301, 1e-300, 1e-299,
1e-298, 1e-297, 1e-296, 1e-295, 1e-294, 1e-293, 1e-292, 1e-291, 1e-290,
1e-289, 1e-288, 1e-287, 1e-286, 1e-285, 1e-284, 1e-283, 1e-282, 1e-281,
@ -296,189 +190,231 @@ bool test_fixed_only() {
1e305, 1e306, 1e307, 1e308};
bool powers_of_ten() {
std::cout << __func__ << std::endl;
TEST_CASE("powers_of_ten") {
char buf[1024];
WARN_MESSAGE(1e-308 == std::pow(10, -308), "On your system, the pow function is busted. Sorry about that.");
bool is_pow_correct{1e-308 == std::pow(10,-308)};
// large negative values should be zero.
int start_point = is_pow_correct ? -1000 : -307;
if(!is_pow_correct) {
std::cout << "On your system, the pow function is busted. Sorry about that. " << std::endl;
}
for (int i = start_point; i <= 308; ++i) {// large negative values should be zero.
std::cout << ".";
std::cout.flush();
size_t n = snprintf(buf, sizeof(buf), "1e%d", i);
if (n >= sizeof(buf)) { abort(); }
for (int i = start_point; i <= 308; ++i) {
INFO("i=" << i);
size_t n = size_t(snprintf(buf, sizeof(buf), "1e%d", i));
REQUIRE(n < sizeof(buf)); // if false, fails the test and exits
double actual;
auto result = fast_float::from_chars(buf, buf + 1000, actual);
if (result.ec != std::errc()) {
std::cerr << " I could not parse " << buf << std::endl;
return false;
}
double expected = ((i >= -307) ? testing_power_of_ten[i + 307]: std::pow(10, i));
if(actual!=expected) {
std::cerr << "String '" << buf << " parsed to " << actual;
return false;
}
CHECK_MESSAGE(result.ec == std::errc(), " I could not parse " << buf);
double expected = ((i >= -307) ? testing_power_of_ten[i + 307] : std::pow(10, i));
CHECK_MESSAGE(actual == expected, "String '" << buf << "'parsed to " << actual);
}
std::cout << std::endl;
std::cout << "Powers of 10 can be parsed exactly.\n";
return true;
}
int main() {
Assert(test_fixed_only());
Assert(test_scientific_only());
Assert(issue8());
Assert(issue19());
Assert(check_behavior());
std::cout << "======= 64 bits " << std::endl;
Assert(basic_test_64bit("INF",std::numeric_limits<double>::infinity()));
Assert(basic_test_64bit("-INF",-std::numeric_limits<double>::infinity()));
Assert(basic_test_64bit("INFINITY",std::numeric_limits<double>::infinity()));
Assert(basic_test_64bit("-INFINITY",-std::numeric_limits<double>::infinity()));
Assert(basic_test_64bit("infinity",std::numeric_limits<double>::infinity()));
Assert(basic_test_64bit("-infinity",-std::numeric_limits<double>::infinity()));
Assert(basic_test_64bit("inf",std::numeric_limits<double>::infinity()));
Assert(basic_test_64bit("-inf",-std::numeric_limits<double>::infinity()));
Assert(basic_test_64bit("9355950000000000000.00000000000000000000000000000000001844674407370955161600000184467440737095516161844674407370955161407370955161618446744073709551616000184467440737095516166000001844674407370955161618446744073709551614073709551616184467440737095516160001844674407370955161601844674407370955674451616184467440737095516140737095516161844674407370955161600018446744073709551616018446744073709551611616000184467440737095001844674407370955161600184467440737095516160018446744073709551168164467440737095516160001844073709551616018446744073709551616184467440737095516160001844674407536910751601611616000184467440737095001844674407370955161600184467440737095516160018446744073709551616184467440737095516160001844955161618446744073709551616000184467440753691075160018446744073709",0x1.03ae05e8fca1cp+63));
Assert(basic_test_64bit("-0",-0.0));
Assert(basic_test_64bit("2.22507385850720212418870147920222032907240528279439037814303133837435107319244194686754406432563881851382188218502438069999947733013005649884107791928741341929297200970481951993067993290969042784064731682041565926728632933630474670123316852983422152744517260835859654566319282835244787787799894310779783833699159288594555213714181128458251145584319223079897504395086859412457230891738946169368372321191373658977977723286698840356390251044443035457396733706583981055420456693824658413747607155981176573877626747665912387199931904006317334709003012790188175203447190250028061277777916798391090578584006464715943810511489154282775041174682194133952466682503431306181587829379004205392375072083366693241580002758391118854188641513168478436313080237596295773983001708984375e-308", 0x1.0000000000002p-1022));
Assert(basic_test_64bit("1.0000000000000006661338147750939242541790008544921875",1.0000000000000007));
Assert(basic_test_64bit("1090544144181609348835077142190",0x1.b8779f2474dfbp+99));
Assert(basic_test_64bit("2.2250738585072013e-308",2.2250738585072013e-308));
Assert(basic_test_64bit("-92666518056446206563E3", -92666518056446206563E3));
Assert(basic_test_64bit("-92666518056446206563E3", -92666518056446206563E3));
Assert(basic_test_64bit("-42823146028335318693e-128",-42823146028335318693e-128));
Assert(basic_test_64bit("90054602635948575728E72",90054602635948575728E72));
Assert(basic_test_64bit("1.00000000000000188558920870223463870174566020691753515394643550663070558368373221972569761144603605635692374830246134201063722058e-309", 1.00000000000000188558920870223463870174566020691753515394643550663070558368373221972569761144603605635692374830246134201063722058e-309));
Assert(basic_test_64bit("0e9999999999999999999999999999", 0));
Assert(basic_test_32bit("1234456789012345678901234567890e9999999999999999999999999999", std::numeric_limits<double>::infinity()));
Assert(basic_test_64bit("-2139879401095466344511101915470454744.9813888656856943E+272", -std::numeric_limits<double>::infinity()));
Assert(basic_test_64bit("-2402844368454405395.2", -2402844368454405395.2));
Assert(basic_test_64bit("2402844368454405395.2", 2402844368454405395.2));
Assert(basic_test_64bit("7.0420557077594588669468784357561207962098443483187940792729600000e+59", 7.0420557077594588669468784357561207962098443483187940792729600000e+59));
Assert(basic_test_64bit("7.0420557077594588669468784357561207962098443483187940792729600000e+59", 7.0420557077594588669468784357561207962098443483187940792729600000e+59));
Assert(basic_test_64bit("-1.7339253062092163730578609458683877051596800000000000000000000000e+42", -1.7339253062092163730578609458683877051596800000000000000000000000e+42));
Assert(basic_test_64bit("-2.0972622234386619214559824785284023792871122537545728000000000000e+52", -2.0972622234386619214559824785284023792871122537545728000000000000e+52));
Assert(basic_test_64bit("-1.0001803374372191849407179462120053338028379051879898808320000000e+57", -1.0001803374372191849407179462120053338028379051879898808320000000e+57));
Assert(basic_test_64bit("-1.8607245283054342363818436991534856973992070520151142825984000000e+58", -1.8607245283054342363818436991534856973992070520151142825984000000e+58));
Assert(basic_test_64bit("-1.9189205311132686907264385602245237137907390376574976000000000000e+52", -1.9189205311132686907264385602245237137907390376574976000000000000e+52));
Assert(basic_test_64bit("-2.8184483231688951563253238886553506793085187889855201280000000000e+54", -2.8184483231688951563253238886553506793085187889855201280000000000e+54));
Assert(basic_test_64bit("-1.7664960224650106892054063261344555646357024359107788800000000000e+53", -1.7664960224650106892054063261344555646357024359107788800000000000e+53));
Assert(basic_test_64bit("-2.1470977154320536489471030463761883783915110400000000000000000000e+45", -2.1470977154320536489471030463761883783915110400000000000000000000e+45));
Assert(basic_test_64bit("-4.4900312744003159009338275160799498340862630046359789166919680000e+61", -4.4900312744003159009338275160799498340862630046359789166919680000e+61));
Assert(basic_test_64bit("+1", 1));
Assert(basic_test_64bit("1.8e308", std::numeric_limits<double>::infinity()));
Assert(basic_test_64bit("1.797693134862315700000000000000001e308", 1.7976931348623157e308));
Assert(basic_test_64bit("1.832312213213213232132132143451234453123412321321312e308", std::numeric_limits<double>::infinity()));
Assert(basic_test_64bit("2e30000000000000000", std::numeric_limits<double>::infinity()));
Assert(basic_test_64bit("2e3000", std::numeric_limits<double>::infinity()));
Assert(basic_test_64bit("1.9e308", std::numeric_limits<double>::infinity()));
Assert(basic_test_64bit("3e-324", 0x0.0000000000001p-1022));
Assert(basic_test_64bit("1.00000006e+09", 0x1.dcd651ep+29));
Assert(basic_test_64bit("4.9406564584124653e-324", 0x0.0000000000001p-1022));
Assert(basic_test_64bit("4.9406564584124654e-324", 0x0.0000000000001p-1022));
Assert(basic_test_64bit("2.2250738585072009e-308", 0x0.fffffffffffffp-1022));
Assert(basic_test_64bit("2.2250738585072014e-308", 0x1p-1022));
Assert(basic_test_64bit("1.7976931348623157e308", 0x1.fffffffffffffp+1023));
Assert(basic_test_64bit("1.7976931348623158e308", 0x1.fffffffffffffp+1023));
Assert(basic_test_64bit("4503599627370496.5", 4503599627370496.5));
Assert(basic_test_64bit("4503599627475352.5", 4503599627475352.5));
Assert(basic_test_64bit("4503599627475353.5", 4503599627475353.5));
Assert(basic_test_64bit("2251799813685248.25", 2251799813685248.25));
Assert(basic_test_64bit("1125899906842624.125", 1125899906842624.125));
Assert(basic_test_64bit("1125899906842901.875", 1125899906842901.875));
Assert(basic_test_64bit("2251799813685803.75", 2251799813685803.75));
Assert(basic_test_64bit("4503599627370497.5", 4503599627370497.5));
Assert(basic_test_64bit("45035996.273704995", 45035996.273704995));
Assert(basic_test_64bit("45035996.273704985", 45035996.273704985));
Assert(basic_test_64bit("0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044501477170144022721148195934182639518696390927032912960468522194496444440421538910330590478162701758282983178260792422137401728773891892910553144148156412434867599762821265346585071045737627442980259622449029037796981144446145705102663115100318287949527959668236039986479250965780342141637013812613333119898765515451440315261253813266652951306000184917766328660755595837392240989947807556594098101021612198814605258742579179000071675999344145086087205681577915435923018910334964869420614052182892431445797605163650903606514140377217442262561590244668525767372446430075513332450079650686719491377688478005309963967709758965844137894433796621993967316936280457084866613206797017728916080020698679408551343728867675409720757232455434770912461317493580281734466552734375", 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044501477170144022721148195934182639518696390927032912960468522194496444440421538910330590478162701758282983178260792422137401728773891892910553144148156412434867599762821265346585071045737627442980259622449029037796981144446145705102663115100318287949527959668236039986479250965780342141637013812613333119898765515451440315261253813266652951306000184917766328660755595837392240989947807556594098101021612198814605258742579179000071675999344145086087205681577915435923018910334964869420614052182892431445797605163650903606514140377217442262561590244668525767372446430075513332450079650686719491377688478005309963967709758965844137894433796621993967316936280457084866613206797017728916080020698679408551343728867675409720757232455434770912461317493580281734466552734375));
Assert(basic_test_64bit("0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022250738585072008890245868760858598876504231122409594654935248025624400092282356951787758888037591552642309780950434312085877387158357291821993020294379224223559819827501242041788969571311791082261043971979604000454897391938079198936081525613113376149842043271751033627391549782731594143828136275113838604094249464942286316695429105080201815926642134996606517803095075913058719846423906068637102005108723282784678843631944515866135041223479014792369585208321597621066375401613736583044193603714778355306682834535634005074073040135602968046375918583163124224521599262546494300836851861719422417646455137135420132217031370496583210154654068035397417906022589503023501937519773030945763173210852507299305089761582519159720757232455434770912461317493580281734466552734375", 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022250738585072008890245868760858598876504231122409594654935248025624400092282356951787758888037591552642309780950434312085877387158357291821993020294379224223559819827501242041788969571311791082261043971979604000454897391938079198936081525613113376149842043271751033627391549782731594143828136275113838604094249464942286316695429105080201815926642134996606517803095075913058719846423906068637102005108723282784678843631944515866135041223479014792369585208321597621066375401613736583044193603714778355306682834535634005074073040135602968046375918583163124224521599262546494300836851861719422417646455137135420132217031370496583210154654068035397417906022589503023501937519773030945763173210852507299305089761582519159720757232455434770912461317493580281734466552734375));
Assert(basic_test_64bit("1438456663141390273526118207642235581183227845246331231162636653790368152091394196930365828634687637948157940776599182791387527135353034738357134110310609455693900824193549772792016543182680519740580354365467985440183598701312257624545562331397018329928613196125590274187720073914818062530830316533158098624984118889298281371812288789537310599037529113415438738954894752124724983067241108764488346454376699018673078404751121414804937224240805993123816932326223683090770561597570457793932985826162604255884529134126396282202126526253389383421806727954588525596114379801269094096329805054803089299736996870951258573010877404407451953846698609198213926882692078557033228265259305481198526059813164469187586693257335779522020407645498684263339921905227556616698129967412891282231685504660671277927198290009824680186319750978665734576683784255802269708917361719466043175201158849097881370477111850171579869056016061666173029059588433776015644439705050377554277696143928278093453792803846252715966016733222646442382892123940052441346822429721593884378212558701004356924243030059517489346646577724622498919752597382095222500311124181823512251071356181769376577651390028297796156208815375089159128394945710515861334486267101797497111125909272505194792870889617179758703442608016143343262159998149700606597792535574457560429226974273443630323818747730771316763398572110874959981923732463076884528677392654150010269822239401993427482376513231389212353583573566376915572650916866553612366187378959554983566712767093372906030188976220169058025354973622211666504549316958271880975697143546564469806791358707318873075708383345004090151974068325838177531266954177406661392229801349994695941509935655355652985723782153570084089560139142231.738475042362596875449154552392299548947138162081694168675340677843807613129780449323363759027012972466987370921816813162658754726545121090545507240267000456594786540949605260722461937870630634874991729398208026467698131898691830012167897399682179601734569071423681e-733", std::numeric_limits<double>::infinity()));
std::cout << std::endl;
std::cout << "======= 32 bits " << std::endl;
Assert(basic_test_32bit("INF",std::numeric_limits<double>::infinity()));
Assert(basic_test_32bit("-INF",-std::numeric_limits<double>::infinity()));
Assert(basic_test_32bit("INFINITY",std::numeric_limits<double>::infinity()));
Assert(basic_test_32bit("-INFINITY",-std::numeric_limits<double>::infinity()));
Assert(basic_test_32bit("infinity",std::numeric_limits<double>::infinity()));
Assert(basic_test_32bit("-infinity",-std::numeric_limits<double>::infinity()));
Assert(basic_test_32bit("inf",std::numeric_limits<double>::infinity()));
Assert(basic_test_32bit("-inf",-std::numeric_limits<double>::infinity()));
Assert(basic_test_32bit("-0",-0.0f));
Assert(basic_test_32bit("1090544144181609348835077142190",0x1.b877ap+99f));
Assert(basic_test_32bit("1.1754943508e-38",1.1754943508e-38f));
Assert(basic_test_32bit("30219.0830078125",30219.0830078125f));
Assert(basic_test_32bit("16252921.5",16252921.5f));
Assert(basic_test_32bit("5322519.25",5322519.25f));
Assert(basic_test_32bit("3900245.875",3900245.875f));
Assert(basic_test_32bit("1510988.3125",1510988.3125f));
Assert(basic_test_32bit("782262.28125",782262.28125f));
Assert(basic_test_32bit("328381.484375",328381.484375f));
Assert(basic_test_32bit("156782.0703125",156782.0703125f));
Assert(basic_test_32bit("85003.24609375",85003.24609375f));
Assert(basic_test_32bit("43827.048828125",43827.048828125f));
Assert(basic_test_32bit("17419.6494140625",17419.6494140625f));
Assert(basic_test_32bit("15498.36376953125",15498.36376953125f));
Assert(basic_test_32bit("6318.580322265625",6318.580322265625f));
Assert(basic_test_32bit("2525.2840576171875",2525.2840576171875f));
Assert(basic_test_32bit("1370.9265747070312",1370.9265747070312f));
Assert(basic_test_32bit("936.3702087402344",936.3702087402344f));
Assert(basic_test_32bit("411.88682556152344",411.88682556152344f));
Assert(basic_test_32bit("206.50310516357422",206.50310516357422f));
Assert(basic_test_32bit("124.16878890991211",124.16878890991211f));
Assert(basic_test_32bit("50.811574935913086",50.811574935913086f));
Assert(basic_test_32bit("17.486443519592285",17.486443519592285f));
Assert(basic_test_32bit("13.91745138168335",13.91745138168335f));
Assert(basic_test_32bit("7.5464513301849365",0x1.e2f90ep+2f));
Assert(basic_test_32bit("2.687217116355896",2.687217116355896f));
Assert(basic_test_32bit("1.1877630352973938",0x1.30113ep+0f));
Assert(basic_test_32bit("0.7622503340244293",0.7622503340244293f));
Assert(basic_test_32bit("0.30531780421733856",0x1.38a53ap-2f));
Assert(basic_test_32bit("0.21791061013936996",0x1.be47eap-3f));
Assert(basic_test_32bit("0.09289376810193062",0x1.7c7e2ep-4f));
Assert(basic_test_32bit("0.03706067614257336",0.03706067614257336f));
Assert(basic_test_32bit("0.028068351559340954",0.028068351559340954f));
Assert(basic_test_32bit("0.012114629615098238",0x1.8cf8e2p-7f));
Assert(basic_test_32bit("0.004221370676532388",0x1.14a6dap-8f));
Assert(basic_test_32bit("0.002153817447833717",0.002153817447833717f));
Assert(basic_test_32bit("0.0015924838953651488",0x1.a175cap-10f));
Assert(basic_test_32bit("0.0008602388261351734",0.0008602388261351734f));
Assert(basic_test_32bit("0.00036393293703440577",0x1.7d9c82p-12f));
Assert(basic_test_32bit("0.00013746770127909258",0.00013746770127909258));
Assert(basic_test_32bit("16407.9462890625", 16407.9462890625f));
Assert(basic_test_32bit("1.1754947011469036e-38", 0x1.000006p-126f));
Assert(basic_test_32bit("7.0064923216240854e-46", 0x1p-149f));
Assert(basic_test_32bit("8388614.5", 8388614.5f));
Assert(basic_test_32bit("0e9999999999999999999999999999", 0));
Assert(basic_test_32bit("1234456789012345678901234567890e9999999999999999999999999999", std::numeric_limits<float>::infinity()));
Assert(basic_test_32bit("4.7019774032891500318749461488889827112746622270883500860350068251e-38",4.7019774032891500318749461488889827112746622270883500860350068251e-38f));
Assert(basic_test_32bit("3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679", 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679));
Assert(basic_test_32bit("2.3509887016445750159374730744444913556373311135441750430175034126e-38", 2.3509887016445750159374730744444913556373311135441750430175034126e-38f));
Assert(basic_test_32bit("+1", 1));
Assert(basic_test_32bit("2e3000", std::numeric_limits<float>::infinity()));
Assert(basic_test_32bit("3.5028234666e38", std::numeric_limits<float>::infinity()));
Assert(basic_test_32bit("7.0060e-46", 0));
Assert(basic_test_32bit(1.00000006e+09f));
Assert(basic_test_32bit(1.4012984643e-45f));
Assert(basic_test_32bit(1.1754942107e-38f));
Assert(basic_test_32bit(1.1754943508e-45f));
Assert(basic_test_32bit("3.4028234664e38", 0x1.fffffep+127f));
Assert(basic_test_32bit("3.4028234665e38", 0x1.fffffep+127f));
Assert(basic_test_32bit("3.4028234666e38", 0x1.fffffep+127f));
Assert(basic_test_32bit("0.000000000000000000000000000000000000011754943508222875079687365372222456778186655567720875215087517062784172594547271728515625", 0.000000000000000000000000000000000000011754943508222875079687365372222456778186655567720875215087517062784172594547271728515625));
Assert(basic_test_32bit("0.00000000000000000000000000000000000000000000140129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125", 0.00000000000000000000000000000000000000000000140129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125));
Assert(basic_test_32bit("0.00000000000000000000000000000000000002350988561514728583455765982071533026645717985517980855365926236850006129930346077117064851336181163787841796875", 0.00000000000000000000000000000000000002350988561514728583455765982071533026645717985517980855365926236850006129930346077117064851336181163787841796875));
Assert(basic_test_32bit("0.00000000000000000000000000000000000001175494210692441075487029444849287348827052428745893333857174530571588870475618904265502351336181163787841796875", 0.00000000000000000000000000000000000001175494210692441075487029444849287348827052428745893333857174530571588870475618904265502351336181163787841796875));
std::cout << std::endl;
Assert(powers_of_ten());
std::cout << "All ok" << std::endl;
return EXIT_SUCCESS;
}
template <typename T> std::string to_string(T d) {
std::string s(64, '\0');
auto written = std::snprintf(&s[0], s.size(), "%.*e",
std::numeric_limits<T>::max_digits10 - 1, d);
s.resize(size_t(written));
return s;
}
template <typename T> std::string to_long_string(T d) {
std::string s(4096, '\0');
auto written = std::snprintf(&s[0], s.size(), "%.*e",
std::numeric_limits<T>::max_digits10 * 10, d);
s.resize(size_t(written));
return s;
}
uint32_t get_mantissa(float f) {
uint32_t m;
memcpy(&m, &f, sizeof(f));
return (m & ((uint32_t(1)<<23)-1));
}
uint64_t get_mantissa(double f) {
uint64_t m;
memcpy(&m, &f, sizeof(f));
return (m & ((uint64_t(1)<<57)-1));
}
template<class T>
void basic_test(std::string str, T expected) {
T actual;
auto result = fast_float::from_chars(str.data(), str.data() + str.size(), actual);
INFO("str=" << str << "\n"
<< " expected=" << fHexAndDec(expected) << "\n"
<< " ..actual=" << fHexAndDec(actual) << "\n"
<< " expected mantissa=" << iHexAndDec(get_mantissa(expected)) << "\n"
<< " ..actual mantissa=" << iHexAndDec(get_mantissa(actual)));
CHECK_EQ(result.ec, std::errc());
CHECK_EQ(copysign(1, actual), copysign(1, expected));
CHECK_EQ(std::isnan(actual), std::isnan(expected));
CHECK_EQ(actual, expected);
}
void basic_test(float val) {
{
std::string long_vals = to_long_string(val);
INFO("long vals: " << long_vals);
basic_test<float>(long_vals, val);
}
{
std::string vals = to_string(val);
INFO("vals: " << vals);
basic_test<float>(vals, val);
}
}
#define verify(lhs, rhs) { INFO(lhs); basic_test(lhs, rhs); }
#define verify32(val) { INFO(#val); basic_test(val); }
TEST_CASE("64bit.inf") {
verify("INF", std::numeric_limits<double>::infinity());
verify("-INF", -std::numeric_limits<double>::infinity());
verify("INFINITY", std::numeric_limits<double>::infinity());
verify("-INFINITY", -std::numeric_limits<double>::infinity());
verify("infinity", std::numeric_limits<double>::infinity());
verify("-infinity", -std::numeric_limits<double>::infinity());
verify("inf", std::numeric_limits<double>::infinity());
verify("-inf", -std::numeric_limits<double>::infinity());
verify("1234456789012345678901234567890e9999999999999999999999999999", std::numeric_limits<double>::infinity());
verify("-2139879401095466344511101915470454744.9813888656856943E+272", -std::numeric_limits<double>::infinity());
verify("1.8e308", std::numeric_limits<double>::infinity());
verify("1.832312213213213232132132143451234453123412321321312e308", std::numeric_limits<double>::infinity());
verify("2e30000000000000000", std::numeric_limits<double>::infinity());
verify("2e3000", std::numeric_limits<double>::infinity());
verify("1.9e308", std::numeric_limits<double>::infinity());
}
TEST_CASE("64bit.general") {
verify("1.1920928955078125e-07", 1.1920928955078125e-07);
verify("9355950000000000000.00000000000000000000000000000000001844674407370955161600000184467440737095516161844674407370955161407370955161618446744073709551616000184467440737095516166000001844674407370955161618446744073709551614073709551616184467440737095516160001844674407370955161601844674407370955674451616184467440737095516140737095516161844674407370955161600018446744073709551616018446744073709551611616000184467440737095001844674407370955161600184467440737095516160018446744073709551168164467440737095516160001844073709551616018446744073709551616184467440737095516160001844674407536910751601611616000184467440737095001844674407370955161600184467440737095516160018446744073709551616184467440737095516160001844955161618446744073709551616000184467440753691075160018446744073709",0x1.03ae05e8fca1cp+63);
verify("-0",-0.0);
verify("2.22507385850720212418870147920222032907240528279439037814303133837435107319244194686754406432563881851382188218502438069999947733013005649884107791928741341929297200970481951993067993290969042784064731682041565926728632933630474670123316852983422152744517260835859654566319282835244787787799894310779783833699159288594555213714181128458251145584319223079897504395086859412457230891738946169368372321191373658977977723286698840356390251044443035457396733706583981055420456693824658413747607155981176573877626747665912387199931904006317334709003012790188175203447190250028061277777916798391090578584006464715943810511489154282775041174682194133952466682503431306181587829379004205392375072083366693241580002758391118854188641513168478436313080237596295773983001708984375e-308", 0x1.0000000000002p-1022);
verify("1.0000000000000006661338147750939242541790008544921875",1.0000000000000007);
verify("1090544144181609348835077142190",0x1.b8779f2474dfbp+99);
verify("2.2250738585072013e-308", 2.2250738585072013e-308);
verify("-92666518056446206563E3", -92666518056446206563E3);
verify("-92666518056446206563E3", -92666518056446206563E3);
verify("-42823146028335318693e-128",-42823146028335318693e-128);
verify("90054602635948575728E72",90054602635948575728E72);
verify("1.00000000000000188558920870223463870174566020691753515394643550663070558368373221972569761144603605635692374830246134201063722058e-309", 1.00000000000000188558920870223463870174566020691753515394643550663070558368373221972569761144603605635692374830246134201063722058e-309);
verify("0e9999999999999999999999999999", 0.0);
verify("-2402844368454405395.2", -2402844368454405395.2);
verify("2402844368454405395.2", 2402844368454405395.2);
verify("7.0420557077594588669468784357561207962098443483187940792729600000e+59", 7.0420557077594588669468784357561207962098443483187940792729600000e+59);
verify("7.0420557077594588669468784357561207962098443483187940792729600000e+59", 7.0420557077594588669468784357561207962098443483187940792729600000e+59);
verify("-1.7339253062092163730578609458683877051596800000000000000000000000e+42", -1.7339253062092163730578609458683877051596800000000000000000000000e+42);
verify("-2.0972622234386619214559824785284023792871122537545728000000000000e+52", -2.0972622234386619214559824785284023792871122537545728000000000000e+52);
verify("-1.0001803374372191849407179462120053338028379051879898808320000000e+57", -1.0001803374372191849407179462120053338028379051879898808320000000e+57);
verify("-1.8607245283054342363818436991534856973992070520151142825984000000e+58", -1.8607245283054342363818436991534856973992070520151142825984000000e+58);
verify("-1.9189205311132686907264385602245237137907390376574976000000000000e+52", -1.9189205311132686907264385602245237137907390376574976000000000000e+52);
verify("-2.8184483231688951563253238886553506793085187889855201280000000000e+54", -2.8184483231688951563253238886553506793085187889855201280000000000e+54);
verify("-1.7664960224650106892054063261344555646357024359107788800000000000e+53", -1.7664960224650106892054063261344555646357024359107788800000000000e+53);
verify("-2.1470977154320536489471030463761883783915110400000000000000000000e+45", -2.1470977154320536489471030463761883783915110400000000000000000000e+45);
verify("-4.4900312744003159009338275160799498340862630046359789166919680000e+61", -4.4900312744003159009338275160799498340862630046359789166919680000e+61);
verify("+1", 1.0);
verify("1.797693134862315700000000000000001e308", 1.7976931348623157e308);
verify("3e-324", 0x0.0000000000001p-1022);
verify("1.00000006e+09", 0x1.dcd651ep+29);
verify("4.9406564584124653e-324", 0x0.0000000000001p-1022);
verify("4.9406564584124654e-324", 0x0.0000000000001p-1022);
verify("2.2250738585072009e-308", 0x0.fffffffffffffp-1022);
verify("2.2250738585072014e-308", 0x1p-1022);
verify("1.7976931348623157e308", 0x1.fffffffffffffp+1023);
verify("1.7976931348623158e308", 0x1.fffffffffffffp+1023);
verify("4503599627370496.5", 4503599627370496.5);
verify("4503599627475352.5", 4503599627475352.5);
verify("4503599627475353.5", 4503599627475353.5);
verify("2251799813685248.25", 2251799813685248.25);
verify("1125899906842624.125", 1125899906842624.125);
verify("1125899906842901.875", 1125899906842901.875);
verify("2251799813685803.75", 2251799813685803.75);
verify("4503599627370497.5", 4503599627370497.5);
verify("45035996.273704995", 45035996.273704995);
verify("45035996.273704985", 45035996.273704985);
verify("0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044501477170144022721148195934182639518696390927032912960468522194496444440421538910330590478162701758282983178260792422137401728773891892910553144148156412434867599762821265346585071045737627442980259622449029037796981144446145705102663115100318287949527959668236039986479250965780342141637013812613333119898765515451440315261253813266652951306000184917766328660755595837392240989947807556594098101021612198814605258742579179000071675999344145086087205681577915435923018910334964869420614052182892431445797605163650903606514140377217442262561590244668525767372446430075513332450079650686719491377688478005309963967709758965844137894433796621993967316936280457084866613206797017728916080020698679408551343728867675409720757232455434770912461317493580281734466552734375", 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044501477170144022721148195934182639518696390927032912960468522194496444440421538910330590478162701758282983178260792422137401728773891892910553144148156412434867599762821265346585071045737627442980259622449029037796981144446145705102663115100318287949527959668236039986479250965780342141637013812613333119898765515451440315261253813266652951306000184917766328660755595837392240989947807556594098101021612198814605258742579179000071675999344145086087205681577915435923018910334964869420614052182892431445797605163650903606514140377217442262561590244668525767372446430075513332450079650686719491377688478005309963967709758965844137894433796621993967316936280457084866613206797017728916080020698679408551343728867675409720757232455434770912461317493580281734466552734375);
verify("0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022250738585072008890245868760858598876504231122409594654935248025624400092282356951787758888037591552642309780950434312085877387158357291821993020294379224223559819827501242041788969571311791082261043971979604000454897391938079198936081525613113376149842043271751033627391549782731594143828136275113838604094249464942286316695429105080201815926642134996606517803095075913058719846423906068637102005108723282784678843631944515866135041223479014792369585208321597621066375401613736583044193603714778355306682834535634005074073040135602968046375918583163124224521599262546494300836851861719422417646455137135420132217031370496583210154654068035397417906022589503023501937519773030945763173210852507299305089761582519159720757232455434770912461317493580281734466552734375", 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022250738585072008890245868760858598876504231122409594654935248025624400092282356951787758888037591552642309780950434312085877387158357291821993020294379224223559819827501242041788969571311791082261043971979604000454897391938079198936081525613113376149842043271751033627391549782731594143828136275113838604094249464942286316695429105080201815926642134996606517803095075913058719846423906068637102005108723282784678843631944515866135041223479014792369585208321597621066375401613736583044193603714778355306682834535634005074073040135602968046375918583163124224521599262546494300836851861719422417646455137135420132217031370496583210154654068035397417906022589503023501937519773030945763173210852507299305089761582519159720757232455434770912461317493580281734466552734375);
verify("1438456663141390273526118207642235581183227845246331231162636653790368152091394196930365828634687637948157940776599182791387527135353034738357134110310609455693900824193549772792016543182680519740580354365467985440183598701312257624545562331397018329928613196125590274187720073914818062530830316533158098624984118889298281371812288789537310599037529113415438738954894752124724983067241108764488346454376699018673078404751121414804937224240805993123816932326223683090770561597570457793932985826162604255884529134126396282202126526253389383421806727954588525596114379801269094096329805054803089299736996870951258573010877404407451953846698609198213926882692078557033228265259305481198526059813164469187586693257335779522020407645498684263339921905227556616698129967412891282231685504660671277927198290009824680186319750978665734576683784255802269708917361719466043175201158849097881370477111850171579869056016061666173029059588433776015644439705050377554277696143928278093453792803846252715966016733222646442382892123940052441346822429721593884378212558701004356924243030059517489346646577724622498919752597382095222500311124181823512251071356181769376577651390028297796156208815375089159128394945710515861334486267101797497111125909272505194792870889617179758703442608016143343262159998149700606597792535574457560429226974273443630323818747730771316763398572110874959981923732463076884528677392654150010269822239401993427482376513231389212353583573566376915572650916866553612366187378959554983566712767093372906030188976220169058025354973622211666504549316958271880975697143546564469806791358707318873075708383345004090151974068325838177531266954177406661392229801349994695941509935655355652985723782153570084089560139142231.738475042362596875449154552392299548947138162081694168675340677843807613129780449323363759027012972466987370921816813162658754726545121090545507240267000456594786540949605260722461937870630634874991729398208026467698131898691830012167897399682179601734569071423681e-733", std::numeric_limits<double>::infinity());
}
TEST_CASE("32bit.inf") {
verify("INF", std::numeric_limits<float>::infinity());
verify("-INF", -std::numeric_limits<float>::infinity());
verify("INFINITY", std::numeric_limits<float>::infinity());
verify("-INFINITY", -std::numeric_limits<float>::infinity());
verify("infinity", std::numeric_limits<float>::infinity());
verify("-infinity", -std::numeric_limits<float>::infinity());
verify("inf", std::numeric_limits<float>::infinity());
verify("-inf", -std::numeric_limits<float>::infinity());
verify("1234456789012345678901234567890e9999999999999999999999999999", std::numeric_limits<float>::infinity());
verify("2e3000", std::numeric_limits<float>::infinity());
verify("3.5028234666e38", std::numeric_limits<float>::infinity());
}
TEST_CASE("32bit.general") {
verify32(1.00000006e+09f);
verify32(1.4012984643e-45f);
verify32(1.1754942107e-38f);
verify32(1.1754943508e-45f);
verify("-0", -0.0f);
verify("1090544144181609348835077142190", 0x1.b877ap+99f);
verify("1.1754943508e-38", 1.1754943508e-38f);
verify("30219.0830078125", 30219.0830078125f);
verify("16252921.5", 16252921.5f);
verify("5322519.25", 5322519.25f);
verify("3900245.875", 3900245.875f);
verify("1510988.3125", 1510988.3125f);
verify("782262.28125", 782262.28125f);
verify("328381.484375", 328381.484375f);
verify("156782.0703125", 156782.0703125f);
verify("85003.24609375", 85003.24609375f);
verify("43827.048828125", 43827.048828125f);
verify("17419.6494140625", 17419.6494140625f);
verify("15498.36376953125", 15498.36376953125f);
verify("6318.580322265625", 6318.580322265625f);
verify("2525.2840576171875", 2525.2840576171875f);
verify("1370.9265747070312", 1370.9265747070312f);
verify("936.3702087402344", 936.3702087402344f);
verify("411.88682556152344", 411.88682556152344f);
verify("206.50310516357422", 206.50310516357422f);
verify("124.16878890991211", 124.16878890991211f);
verify("50.811574935913086", 50.811574935913086f);
verify("17.486443519592285", 17.486443519592285f);
verify("13.91745138168335", 13.91745138168335f);
verify("7.5464513301849365", 0x1.e2f90ep+2f);
verify("2.687217116355896", 2.687217116355896f);
verify("1.1877630352973938", 0x1.30113ep+0f);
verify("0.7622503340244293", 0.7622503340244293f);
verify("0.30531780421733856", 0x1.38a53ap-2f);
verify("0.21791061013936996", 0x1.be47eap-3f);
verify("0.09289376810193062", 0x1.7c7e2ep-4f);
verify("0.03706067614257336", 0.03706067614257336f);
verify("0.028068351559340954", 0.028068351559340954f);
verify("0.012114629615098238", 0x1.8cf8e2p-7f);
verify("0.004221370676532388", 0x1.14a6dap-8f);
verify("0.002153817447833717", 0.002153817447833717f);
verify("0.0015924838953651488", 0x1.a175cap-10f);
verify("0.0008602388261351734", 0.0008602388261351734f);
verify("0.00036393293703440577", 0x1.7d9c82p-12f);
verify("0.00013746770127909258", 0.00013746770127909258f);
verify("16407.9462890625", 16407.9462890625f);
verify("1.1754947011469036e-38", 0x1.000006p-126f);
verify("7.0064923216240854e-46", 0x1p-149f);
verify("8388614.5", 8388614.5f);
verify("0e9999999999999999999999999999", 0.f);
verify("4.7019774032891500318749461488889827112746622270883500860350068251e-38",4.7019774032891500318749461488889827112746622270883500860350068251e-38f);
verify("3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679", 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679f);
verify("2.3509887016445750159374730744444913556373311135441750430175034126e-38", 2.3509887016445750159374730744444913556373311135441750430175034126e-38f);
verify("+1", 1.f);
verify("7.0060e-46", 0.f);
verify("3.4028234664e38", 0x1.fffffep+127f);
verify("3.4028234665e38", 0x1.fffffep+127f);
verify("3.4028234666e38", 0x1.fffffep+127f);
verify("0.000000000000000000000000000000000000011754943508222875079687365372222456778186655567720875215087517062784172594547271728515625", 0.000000000000000000000000000000000000011754943508222875079687365372222456778186655567720875215087517062784172594547271728515625);
verify("0.00000000000000000000000000000000000000000000140129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125", 0.00000000000000000000000000000000000000000000140129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125f);
verify("0.00000000000000000000000000000000000002350988561514728583455765982071533026645717985517980855365926236850006129930346077117064851336181163787841796875", 0.00000000000000000000000000000000000002350988561514728583455765982071533026645717985517980855365926236850006129930346077117064851336181163787841796875f);
verify("0.00000000000000000000000000000000000001175494210692441075487029444849287348827052428745893333857174530571588870475618904265502351336181163787841796875", 0.00000000000000000000000000000000000001175494210692441075487029444849287348827052428745893333857174530571588870475618904265502351336181163787841796875f);
}

View File

@ -19,7 +19,7 @@ void allvalues() {
std::cout << ".";
std::cout.flush();
}
uint32_t word = w;
uint32_t word = uint32_t(w);
memcpy(&v, &word, sizeof(v));
{

View File

@ -11,6 +11,37 @@ template <typename T> char *to_string(T d, char *buffer) {
return buffer + written;
}
bool basic_test_64bit(std::string vals, double val) {
double result_value;
auto result = fast_float::from_chars(vals.data(), vals.data() + vals.size(),
result_value);
if (result.ec != std::errc()) {
std::cerr << " I could not parse " << vals << std::endl;
return false;
}
if(copysign(1,result_value) != copysign(1,val)) {
std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << val
<< std::endl;
return false;
} else if (std::isnan(val)) {
if (!std::isnan(result_value)) {
std::cerr << vals << std::endl;
std::cerr << "not nan" << result_value << std::endl;
return false;
}
} else if (result_value != val) {
std::cerr << vals << std::endl;
std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << val
<< std::endl;
std::cerr << std::dec;
std::cerr << "string: " << vals << std::endl;
return false;
}
return true;
}
void all_32bit_values() {
char buffer[64];
for (uint64_t w = 0; w <= 0xFFFFFFFF; w++) {
@ -25,28 +56,9 @@ void all_32bit_values() {
{
const char *string_end = to_string(v, buffer);
double result_value;
auto result = fast_float::from_chars(buffer, string_end, result_value);
if (result.ec != std::errc()) {
std::cerr << "parsing error ? " << buffer << std::endl;
abort();
}
if(copysign(1,result_value) != copysign(1,v)) {
std::cerr << buffer << std::endl;
std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << v
<< std::endl;
abort();
} else if (std::isnan(v)) {
if (!std::isnan(result_value)) {
std::cerr << "not nan" << buffer << std::endl;
abort();
}
} else if (result_value != v) {
std::cerr << "no match ? " << buffer << std::endl;
std::cout << "started with " << std::hexfloat << v << std::endl;
std::cout << "got back " << std::hexfloat << result_value << std::endl;
std::cout << std::dec;
abort();
std::string s(buffer, size_t(string_end-buffer));
if(!basic_test_64bit(s,v)) {
return;
}
}
}

View File

@ -31,7 +31,7 @@ template <typename T> char *to_string(T d, char *buffer) {
void strtod_from_string(const char * st, float& d) {
char *pr = (char *)st;
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__)
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
d = cygwin_strtod_l(st, &pr);
#elif defined(_WIN32)
static _locale_t c_locale = _create_locale(LC_ALL, "C");
@ -53,7 +53,7 @@ void allvalues() {
std::cout << ".";
std::cout.flush();
}
uint32_t word = w;
uint32_t word = uint32_t(w);
memcpy(&v, &word, sizeof(v));
if(std::isfinite(v)) {
float nextf = std::nextafterf(v, INFINITY);
@ -64,7 +64,7 @@ void allvalues() {
double v2{nextf};
assert(float(v2) == nextf);
double midv{v1 + (v2 - v1) / 2};
float expected_midv(midv);
float expected_midv = float(midv);
const char *string_end = to_string(midv, buffer);
float str_answer;
@ -112,8 +112,8 @@ void allvalues() {
}
int main() {
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__)
std::cout << "Warning: msys/cygwin detected. This particular test is likely to generate false failures due to our reliance on the underlying runtime library." << std::endl;
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
std::cout << "Warning: msys/cygwin or solaris detected. This particular test is likely to generate false failures due to our reliance on the underlying runtime library." << std::endl;
#endif
allvalues();
std::cout << std::endl;

View File

@ -90,7 +90,7 @@ void random_values(size_t N) {
int main() {
errors = 0;
size_t N = size_t(1) << 32;
size_t N = size_t(1) << (sizeof(size_t) * 4); // shift: 32 for 64bit, 16 for 32bit
random_values(N);
if (errors == 0) {
std::cout << std::endl;

View File

@ -0,0 +1,115 @@
#include "fast_float/fast_float.h"
#include <iostream>
#include <random>
#include <sstream>
#include <vector>
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
// Anything at all that is related to cygwin, msys and so forth will
// always use this fallback because we cannot rely on it behaving as normal
// gcc.
#include <locale>
#include <sstream>
// workaround for CYGWIN
double cygwin_strtod_l(const char* start, char** end) {
double d;
std::stringstream ss;
ss.imbue(std::locale::classic());
ss << start;
ss >> d;
size_t nread = ss.tellg();
*end = const_cast<char*>(start) + nread;
return d;
}
#endif
std::pair<double, bool> strtod_from_string(const char *st) {
double d;
char *pr;
#ifdef _WIN32
static _locale_t c_locale = _create_locale(LC_ALL, "C");
d = _strtod_l(st, &pr, c_locale);
#else
static locale_t c_locale = newlocale(LC_ALL_MASK, "C", NULL);
d = strtod_l(st, &pr, c_locale);
#endif
if (st == pr) {
std::cerr << "strtod_l could not parse '" << st << std::endl;
return std::make_pair(0, false);
}
return std::make_pair(d, true);
}
std::pair<float, bool> strtof_from_string(char *st) {
float d;
char *pr;
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
d = cygwin_strtod_l(st, &pr);
#elif defined(_WIN32)
static _locale_t c_locale = _create_locale(LC_ALL, "C");
d = _strtof_l(st, &pr, c_locale);
#else
static locale_t c_locale = newlocale(LC_ALL_MASK, "C", NULL);
d = strtof_l(st, &pr, c_locale);
#endif
if (st == pr) {
std::cerr << "strtof_l could not parse '" << st << std::endl;
return std::make_pair(0.0f, false);
}
return std::make_pair(d, true);
}
bool tester() {
std::random_device rd;
std::mt19937 gen(rd());
for (int q = 18; q <= 27; q++) {
std::cout << "q = " << -q << std::endl;
uint64_t power5 = 1;
for (int k = 0; k < q; k++) {
power5 *= 5;
}
uint64_t low_threshold = 0x20000000000000 / power5 + 1;
uint64_t threshold = 0xFFFFFFFFFFFFFFFF / power5;
std::uniform_int_distribution<uint64_t> dis(low_threshold, threshold);
for (size_t i = 0; i < 10000; i++) {
uint64_t mantissa = dis(gen) * power5;
std::stringstream ss;
ss << mantissa;
ss << "e";
ss << -q;
std::string to_be_parsed = ss.str();
std::pair<double, bool> expected_double =
strtod_from_string(to_be_parsed.c_str());
double result_value;
auto result =
fast_float::from_chars(to_be_parsed.data(), to_be_parsed.data() + to_be_parsed.size(), result_value);
if (result.ec != std::errc()) {
std::cout << to_be_parsed << std::endl;
std::cerr << " I could not parse " << std::endl;
return false;
}
if (result_value != expected_double.first) {
std::cout << to_be_parsed << std::endl;
std::cerr << std::hexfloat << result_value << std::endl;
std::cerr << std::hexfloat << expected_double.first << std::endl;
std::cerr << " Mismatch " << std::endl;
return false;
}
}
}
return true;
}
int main() {
if (tester()) {
std::cout << std::endl;
std::cout << "all ok" << std::endl;
return EXIT_SUCCESS;
}
std::cerr << std::endl;
std::cerr << "errors were encountered" << std::endl;
return EXIT_FAILURE;
}

View File

@ -92,7 +92,7 @@ void random_values(size_t N) {
int main() {
errors = 0;
size_t N = size_t(1) << 32;
size_t N = size_t(1) << (sizeof(size_t) * 4); // shift: 32 for 64bit, 16 for 32bit
random_values(N);
if (errors == 0) {
std::cout << std::endl;

View File

@ -2,7 +2,7 @@
#include <cstdint>
#include <random>
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__)
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
// Anything at all that is related to cygwin, msys and so forth will
// always use this fallback because we cannot rely on it behaving as normal
// gcc.
@ -24,7 +24,7 @@ double cygwin_strtod_l(const char* start, char** end) {
class RandomEngine {
public:
RandomEngine() = delete;
RandomEngine(int new_seed) { wyhash64_x_ = new_seed; };
RandomEngine(uint64_t new_seed) : wyhash64_x_(new_seed) {};
uint64_t next() {
// Adapted from https://github.com/wangyi-fudan/wyhash/blob/master/wyhash.h
// Inspired from
@ -47,7 +47,7 @@ public:
/* if (min == max) {
return min;
}*/
int s = max - min + 1;
uint64_t s = uint64_t(max - min + 1);
uint64_t x = next();
fast_float::value128 m = fast_float::full_multiplication(x, s);
uint64_t l = m.low;
@ -59,7 +59,7 @@ public:
l = m.low;
}
}
return (m.high) + min;
return int(m.high) + min;
}
int next_digit() { return next_ranged_int(0, 9); }
@ -78,8 +78,8 @@ size_t build_random_string(RandomEngine &rand, char *buffer) {
number_of_digits = rand.next_ranged_int(1, 2000);
}
int location_of_decimal_separator = rand.next_ranged_int(1, number_of_digits);
for (size_t i = 0; i < number_of_digits; i++) {
if (i == location_of_decimal_separator) {
for (size_t i = 0; i < size_t(number_of_digits); i++) {
if (i == size_t(location_of_decimal_separator)) {
buffer[pos++] = '.';
}
buffer[pos++] = char(rand.next_digit() + '0');
@ -98,7 +98,7 @@ size_t build_random_string(RandomEngine &rand, char *buffer) {
}
}
number_of_digits = rand.next_ranged_int(1, 3);
for (size_t i = 0; i < number_of_digits; i++) {
for (size_t i = 0; i < size_t(number_of_digits); i++) {
buffer[pos++] = char(rand.next_digit() + '0');
}
}
@ -126,7 +126,7 @@ std::pair<double, bool> strtod_from_string(char *st) {
std::pair<float, bool> strtof_from_string(char *st) {
float d;
char *pr;
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__)
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
d = cygwin_strtod_l(st, &pr);
#elif defined(_WIN32)
static _locale_t c_locale = _create_locale(LC_ALL, "C");
@ -146,7 +146,7 @@ std::pair<float, bool> strtof_from_string(char *st) {
* We generate random strings and we try to parse them with both strtod/strtof,
* and we verify that we get the same answer with with fast_float::from_chars.
*/
bool tester(int seed, size_t volume) {
bool tester(uint64_t seed, size_t volume) {
char buffer[4096]; // large buffer (can't overflow)
RandomEngine rand(seed);
for (size_t i = 0; i < volume; i++) {
@ -203,8 +203,8 @@ bool tester(int seed, size_t volume) {
}
int main() {
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__)
std::cout << "Warning: msys/cygwin detected. This particular test is likely to generate false failures due to our reliance on the underlying runtime library." << std::endl;
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
std::cout << "Warning: msys/cygwin or solaris detected. This particular test is likely to generate false failures due to our reliance on the underlying runtime library." << std::endl;
#endif
if (tester(1234344, 100000000)) {
std::cout << "All tests ok." << std::endl;

View File

@ -2,7 +2,7 @@
#include <cstdint>
#include <random>
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__)
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
// Anything at all that is related to cygwin, msys and so forth will
// always use this fallback because we cannot rely on it behaving as normal
// gcc.
@ -24,7 +24,7 @@ double cygwin_strtod_l(const char* start, char** end) {
class RandomEngine {
public:
RandomEngine() = delete;
RandomEngine(int new_seed) { wyhash64_x_ = new_seed; };
RandomEngine(uint64_t new_seed) : wyhash64_x_(new_seed) { };
uint64_t next() {
// Adapted from https://github.com/wangyi-fudan/wyhash/blob/master/wyhash.h
// Inspired from
@ -47,7 +47,7 @@ public:
/* if (min == max) {
return min;
}*/
int s = max - min + 1;
uint64_t s = uint64_t(max - min + 1);
uint64_t x = next();
fast_float::value128 m = fast_float::full_multiplication(x, s);
uint64_t l = m.low;
@ -59,7 +59,7 @@ public:
l = m.low;
}
}
return (m.high) + min;
return int(m.high) + min;
}
int next_digit() { return next_ranged_int(0, 9); }
@ -74,8 +74,8 @@ size_t build_random_string(RandomEngine &rand, char *buffer) {
}
int number_of_digits = rand.next_ranged_int(1, 19);
int location_of_decimal_separator = rand.next_ranged_int(1, number_of_digits);
for (size_t i = 0; i < number_of_digits; i++) {
if (i == location_of_decimal_separator) {
for (size_t i = 0; i < size_t(number_of_digits); i++) {
if (i == size_t(location_of_decimal_separator)) {
buffer[pos++] = '.';
}
buffer[pos++] = char(rand.next_digit() + '0');
@ -94,7 +94,7 @@ size_t build_random_string(RandomEngine &rand, char *buffer) {
}
}
number_of_digits = rand.next_ranged_int(1, 3);
for (size_t i = 0; i < number_of_digits; i++) {
for (size_t i = 0; i < size_t(number_of_digits); i++) {
buffer[pos++] = char(rand.next_digit() + '0');
}
}
@ -122,7 +122,7 @@ std::pair<double, bool> strtod_from_string(char *st) {
std::pair<float, bool> strtof_from_string(char *st) {
float d;
char *pr;
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__)
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
d = cygwin_strtod_l(st, &pr);
#elif defined(_WIN32)
static _locale_t c_locale = _create_locale(LC_ALL, "C");
@ -142,7 +142,7 @@ std::pair<float, bool> strtof_from_string(char *st) {
* We generate random strings and we try to parse them with both strtod/strtof,
* and we verify that we get the same answer with with fast_float::from_chars.
*/
bool tester(int seed, size_t volume) {
bool tester(uint64_t seed, size_t volume) {
char buffer[4096]; // large buffer (can't overflow)
RandomEngine rand(seed);
for (size_t i = 0; i < volume; i++) {
@ -199,7 +199,7 @@ bool tester(int seed, size_t volume) {
}
int main() {
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__)
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
std::cout << "Warning: msys/cygwin detected. This particular test is likely to generate false failures due to our reliance on the underlying runtime library." << std::endl;
#endif
if (tester(1234344, 100000000)) {

View File

@ -2,7 +2,7 @@
#include <vector>
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__)
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
// Anything at all that is related to cygwin, msys and so forth will
// always use this fallback because we cannot rely on it behaving as normal
// gcc.
@ -30,7 +30,7 @@ template <typename T> std::string to_string(T d) {
std::string s(64, '\0');
auto written = std::snprintf(&s[0], s.size(), "%.*e",
std::numeric_limits<T>::max_digits10 - 1, d);
s.resize(written);
s.resize(size_t(written));
return s;
}
@ -85,7 +85,7 @@ void strtod_from_string(const std::string &st, double& d) {
template <>
void strtod_from_string(const std::string &st, float& d) {
char *pr = (char *)st.c_str();
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__)
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
d = cygwin_strtod_l(st.c_str(), &pr);
#elif defined(_WIN32)
static _locale_t c_locale = _create_locale(LC_ALL, "C");
@ -236,7 +236,7 @@ bool partow_test() {
int main() {
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__)
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
std::cout << "Warning: msys/cygwin detected. This particular test is likely to generate false failures due to our reliance on the underlying runtime library." << std::endl;
#endif
std::cout << "32 bits checks" << std::endl;