diff --git a/.github/workflows/ubuntu18.yml b/.github/workflows/ubuntu18.yml index 23850cc..bf1f2d0 100644 --- a/.github/workflows/ubuntu18.yml +++ b/.github/workflows/ubuntu18.yml @@ -9,9 +9,10 @@ jobs: fail-fast: false matrix: include: - - {cxx: -DCMAKE_CXX_COMPILER=g++-5} - - {cxx: -DCMAKE_CXX_COMPILER=g++-6} - - {cxx: } # default compiler 7 + - {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 - name: Setup cmake @@ -20,12 +21,13 @@ jobs: cmake-version: '3.9.x' - name: Install older compilers run: | + sudo -E dpkg --add-architecture i386 sudo -E apt-get update - sudo -E apt-get install -y --force-yes g++-5 g++-6 + 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}} -DFASTFLOAT_TEST=ON .. + run: cd build && cmake ${{matrix.cxx}} ${{matrix.arch}} -DFASTFLOAT_TEST=ON .. - name: Build run: cmake --build build - name: Run basic tests diff --git a/.github/workflows/ubuntu20.yml b/.github/workflows/ubuntu20.yml index 68aa1ee..451c9b4 100644 --- a/.github/workflows/ubuntu20.yml +++ b/.github/workflows/ubuntu20.yml @@ -9,8 +9,9 @@ jobs: fail-fast: false matrix: include: - - {cxx: -DCMAKE_CXX_COMPILER=g++-8} - - {cxx: } # default compiler 9 + - {cxx: -DCMAKE_CXX_COMPILER=g++-8, arch: } + - {cxx: , arch: } # default=gcc9 + - {cxx: , arch: -DCMAKE_CXX_FLAGS="-m32"} # default=gcc9 steps: - uses: actions/checkout@v2 - name: Setup cmake @@ -19,12 +20,13 @@ jobs: cmake-version: '3.9.x' - name: install older compilers run: | + sudo -E dpkg --add-architecture i386 sudo -E apt-get update - sudo -E apt-get install -y --force-yes g++-8 g++-7 - - name: Prepare build dir + 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}} -DFASTFLOAT_TEST=ON .. + run: cd build && cmake ${{matrix.cxx}} ${{matrix.arch}} -DFASTFLOAT_TEST=ON .. - name: Build run: cmake --build build - name: Run basic tests diff --git a/.github/workflows/vs16-ci.yml b/.github/workflows/vs16-ci.yml index 5a7071a..4f237fd 100644 --- a/.github/workflows/vs16-ci.yml +++ b/.github/workflows/vs16-ci.yml @@ -6,6 +6,12 @@ jobs: ci: name: windows-vs16 runs-on: windows-latest + strategy: + fail-fast: false + matrix: + include: + - vs: VS16Win64 + - vs: VS16Win32 steps: - uses: actions/checkout@v2 - name: 'Run CMake with VS16' @@ -16,9 +22,9 @@ jobs: buildDirectory: "${{ github.workspace }}/../../_temp/windows" cmakeBuildType: Release buildWithCMake: true - cmakeGenerator: VS16Win64 + cmakeGenerator: ${{matrix.vs}} cmakeAppendedArgs: -DFASTFLOAT_TEST=ON - buildWithCMakeArgs: --config Release + buildWithCMakeArgs: --config Release - name: 'Run CTest' run: ctest -C Release --output-on-failure -R basictest diff --git a/.github/workflows/vs16-clang-ci.yml b/.github/workflows/vs16-clang-ci.yml index 08afa25..2bf8e2b 100644 --- a/.github/workflows/vs16-clang-ci.yml +++ b/.github/workflows/vs16-clang-ci.yml @@ -6,6 +6,12 @@ jobs: ci: name: windows-vs16 runs-on: windows-latest + strategy: + fail-fast: false + matrix: + include: + - vs: VS16Win64 + - vs: VS16Win32 steps: - uses: actions/checkout@v2 - name: 'Run CMake with VS16' @@ -16,7 +22,7 @@ jobs: buildDirectory: "${{ github.workspace }}/../../_temp/windows" cmakeBuildType: Release buildWithCMake: true - cmakeGenerator: VS16Win64 + cmakeGenerator: ${{matrix.vs}} cmakeAppendedArgs: -T ClangCL -DFASTFLOAT_TEST=ON buildWithCMakeArgs: --config Release diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a5a3ead --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build/* +Testing/* \ No newline at end of file diff --git a/include/fast_float/float_common.h b/include/fast_float/float_common.h index 60e5f6e..a98a54b 100644 --- a/include/fast_float/float_common.h +++ b/include/fast_float/float_common.h @@ -139,15 +139,31 @@ fastfloat_really_inline value128 full_multiplication(uint64_t value1, return answer; } -#else +#else // gcc // compute value1 * value2 -fastfloat_really_inline value128 full_multiplication(uint64_t value1, - uint64_t value2) { +fastfloat_really_inline value128 full_multiplication(uint64_t a, + uint64_t b) { value128 answer; - __uint128_t r = ((__uint128_t)value1) * value2; +#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__arm__) + static constexpr const uint64_t lo32 = 0xffffffffu; + // https://stackoverflow.com/questions/28868367/getting-the-high-part-of-64-bit-integer-multiplication + uint64_t a_lo = a & lo32; + uint64_t a_hi = a >> 32; + uint64_t b_lo = b & lo32; + uint64_t b_hi = b >> 32; + uint64_t ab_hi = a_hi * b_hi; + uint64_t ab_mid = a_hi * b_lo; + uint64_t ba_mid = b_hi * a_lo; + uint64_t ab_lo = a_lo * b_lo; + uint64_t carry_bit = ((ab_mid & lo32) + (ba_mid & lo32) + (ab_lo >> 32)) >> 32; + answer.high = ab_hi + (ab_mid >> 32) + (ba_mid >> 32) + carry_bit; + answer.low = ab_lo + (ab_mid & lo32) + (ba_mid & lo32); +#else // if defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64) || defined(__aarch64__) || defined(_M_ARM64) + __uint128_t r = ((__uint128_t)a) * b; answer.low = uint64_t(r); answer.high = uint64_t(r >> 64); +#endif return answer; } diff --git a/tests/long_random64.cpp b/tests/long_random64.cpp index b8a6b05..47c4d0c 100644 --- a/tests/long_random64.cpp +++ b/tests/long_random64.cpp @@ -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; diff --git a/tests/random64.cpp b/tests/random64.cpp index 3f37975..d169fbb 100644 --- a/tests/random64.cpp +++ b/tests/random64.cpp @@ -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;