koffi 2.3.6-beta.6 → 2.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/package.json +2 -2
- package/src/cnoke/cnoke.js +3 -7
- package/src/cnoke/src/builder.js +9 -6
- package/src/cnoke/src/index.js +2 -2
- package/src/koffi/build/2.3.7/koffi_darwin_arm64/koffi.node +0 -0
- package/src/koffi/build/2.3.7/koffi_darwin_x64/koffi.node +0 -0
- package/src/koffi/build/2.3.7/koffi_freebsd_arm64/koffi.node +0 -0
- package/src/koffi/build/2.3.7/koffi_freebsd_ia32/koffi.node +0 -0
- package/src/koffi/build/2.3.7/koffi_freebsd_x64/koffi.node +0 -0
- package/src/koffi/build/2.3.7/koffi_linux_arm32hf/koffi.node +0 -0
- package/src/koffi/build/2.3.7/koffi_linux_arm64/koffi.node +0 -0
- package/src/koffi/build/2.3.7/koffi_linux_ia32/koffi.node +0 -0
- package/src/koffi/build/2.3.7/koffi_linux_riscv64hf64/koffi.node +0 -0
- package/src/koffi/build/2.3.7/koffi_linux_x64/koffi.node +0 -0
- package/src/koffi/build/2.3.7/koffi_openbsd_ia32/koffi.node +0 -0
- package/src/koffi/build/2.3.7/koffi_openbsd_x64/koffi.node +0 -0
- package/src/koffi/build/2.3.7/koffi_win32_arm64/koffi.node +0 -0
- package/src/koffi/build/2.3.7/koffi_win32_ia32/koffi.node +0 -0
- package/src/koffi/build/2.3.7/koffi_win32_x64/koffi.node +0 -0
- package/src/koffi/src/ffi.cc +2 -2
- package/src/koffi/src/index.d.ts +2 -2
- package/src/koffi/src/index.js +1 -0
- package/src/koffi/build/2.3.6-beta.6/koffi_darwin_arm64/koffi.node +0 -0
- package/src/koffi/build/2.3.6-beta.6/koffi_darwin_x64/koffi.node +0 -0
- package/src/koffi/build/2.3.6-beta.6/koffi_freebsd_arm64/koffi.node +0 -0
- package/src/koffi/build/2.3.6-beta.6/koffi_freebsd_ia32/koffi.node +0 -0
- package/src/koffi/build/2.3.6-beta.6/koffi_freebsd_x64/koffi.node +0 -0
- package/src/koffi/build/2.3.6-beta.6/koffi_linux_arm32hf/koffi.node +0 -0
- package/src/koffi/build/2.3.6-beta.6/koffi_linux_arm64/koffi.node +0 -0
- package/src/koffi/build/2.3.6-beta.6/koffi_linux_ia32/koffi.node +0 -0
- package/src/koffi/build/2.3.6-beta.6/koffi_linux_riscv64hf64/koffi.node +0 -0
- package/src/koffi/build/2.3.6-beta.6/koffi_linux_x64/koffi.node +0 -0
- package/src/koffi/build/2.3.6-beta.6/koffi_openbsd_ia32/koffi.node +0 -0
- package/src/koffi/build/2.3.6-beta.6/koffi_openbsd_x64/koffi.node +0 -0
- package/src/koffi/build/2.3.6-beta.6/koffi_win32_arm64/koffi.node +0 -0
- package/src/koffi/build/2.3.6-beta.6/koffi_win32_arm64/koffi.pdb +0 -0
- package/src/koffi/build/2.3.6-beta.6/koffi_win32_ia32/koffi.node +0 -0
- package/src/koffi/build/2.3.6-beta.6/koffi_win32_ia32/koffi.pdb +0 -0
- package/src/koffi/build/2.3.6-beta.6/koffi_win32_x64/koffi.node +0 -0
- package/src/koffi/build/2.3.6-beta.6/koffi_win32_x64/koffi.pdb +0 -0
- package/vendor/brotli/BUILD +0 -144
- package/vendor/brotli/CMakeLists.txt +0 -421
- package/vendor/brotli/CONTRIBUTING.md +0 -27
- package/vendor/brotli/LICENSE +0 -19
- package/vendor/brotli/MANIFEST.in +0 -17
- package/vendor/brotli/Makefile +0 -55
- package/vendor/brotli/Makefile.am +0 -38
- package/vendor/brotli/README +0 -15
- package/vendor/brotli/README.md +0 -104
- package/vendor/brotli/WORKSPACE +0 -21
- package/vendor/brotli/bootstrap +0 -35
- package/vendor/brotli/c/common/constants.c +0 -15
- package/vendor/brotli/c/common/constants.h +0 -200
- package/vendor/brotli/c/common/context.c +0 -156
- package/vendor/brotli/c/common/context.h +0 -113
- package/vendor/brotli/c/common/dictionary.c +0 -5914
- package/vendor/brotli/c/common/dictionary.h +0 -64
- package/vendor/brotli/c/common/platform.c +0 -22
- package/vendor/brotli/c/common/platform.h +0 -596
- package/vendor/brotli/c/common/transform.c +0 -291
- package/vendor/brotli/c/common/transform.h +0 -85
- package/vendor/brotli/c/common/version.h +0 -26
- package/vendor/brotli/c/dec/bit_reader.c +0 -76
- package/vendor/brotli/c/dec/bit_reader.h +0 -351
- package/vendor/brotli/c/dec/decode.c +0 -2608
- package/vendor/brotli/c/dec/huffman.c +0 -339
- package/vendor/brotli/c/dec/huffman.h +0 -121
- package/vendor/brotli/c/dec/prefix.h +0 -732
- package/vendor/brotli/c/dec/state.c +0 -159
- package/vendor/brotli/c/dec/state.h +0 -365
- package/vendor/brotli/c/enc/backward_references.c +0 -145
- package/vendor/brotli/c/enc/backward_references.h +0 -39
- package/vendor/brotli/c/enc/backward_references_hq.c +0 -843
- package/vendor/brotli/c/enc/backward_references_hq.h +0 -95
- package/vendor/brotli/c/enc/backward_references_inc.h +0 -163
- package/vendor/brotli/c/enc/bit_cost.c +0 -35
- package/vendor/brotli/c/enc/bit_cost.h +0 -63
- package/vendor/brotli/c/enc/bit_cost_inc.h +0 -127
- package/vendor/brotli/c/enc/block_encoder_inc.h +0 -34
- package/vendor/brotli/c/enc/block_splitter.c +0 -194
- package/vendor/brotli/c/enc/block_splitter.h +0 -51
- package/vendor/brotli/c/enc/block_splitter_inc.h +0 -440
- package/vendor/brotli/c/enc/brotli_bit_stream.c +0 -1314
- package/vendor/brotli/c/enc/brotli_bit_stream.h +0 -84
- package/vendor/brotli/c/enc/cluster.c +0 -56
- package/vendor/brotli/c/enc/cluster.h +0 -48
- package/vendor/brotli/c/enc/cluster_inc.h +0 -320
- package/vendor/brotli/c/enc/command.c +0 -28
- package/vendor/brotli/c/enc/command.h +0 -190
- package/vendor/brotli/c/enc/compress_fragment.c +0 -790
- package/vendor/brotli/c/enc/compress_fragment.h +0 -61
- package/vendor/brotli/c/enc/compress_fragment_two_pass.c +0 -645
- package/vendor/brotli/c/enc/compress_fragment_two_pass.h +0 -54
- package/vendor/brotli/c/enc/dictionary_hash.c +0 -1846
- package/vendor/brotli/c/enc/dictionary_hash.h +0 -25
- package/vendor/brotli/c/enc/encode.c +0 -1927
- package/vendor/brotli/c/enc/encoder_dict.c +0 -33
- package/vendor/brotli/c/enc/encoder_dict.h +0 -43
- package/vendor/brotli/c/enc/entropy_encode.c +0 -503
- package/vendor/brotli/c/enc/entropy_encode.h +0 -122
- package/vendor/brotli/c/enc/entropy_encode_static.h +0 -539
- package/vendor/brotli/c/enc/fast_log.c +0 -105
- package/vendor/brotli/c/enc/fast_log.h +0 -66
- package/vendor/brotli/c/enc/find_match_length.h +0 -79
- package/vendor/brotli/c/enc/hash.h +0 -488
- package/vendor/brotli/c/enc/hash_composite_inc.h +0 -125
- package/vendor/brotli/c/enc/hash_forgetful_chain_inc.h +0 -293
- package/vendor/brotli/c/enc/hash_longest_match64_inc.h +0 -267
- package/vendor/brotli/c/enc/hash_longest_match_inc.h +0 -262
- package/vendor/brotli/c/enc/hash_longest_match_quickly_inc.h +0 -266
- package/vendor/brotli/c/enc/hash_rolling_inc.h +0 -212
- package/vendor/brotli/c/enc/hash_to_binary_tree_inc.h +0 -329
- package/vendor/brotli/c/enc/histogram.c +0 -100
- package/vendor/brotli/c/enc/histogram.h +0 -63
- package/vendor/brotli/c/enc/histogram_inc.h +0 -51
- package/vendor/brotli/c/enc/literal_cost.c +0 -175
- package/vendor/brotli/c/enc/literal_cost.h +0 -30
- package/vendor/brotli/c/enc/memory.c +0 -170
- package/vendor/brotli/c/enc/memory.h +0 -114
- package/vendor/brotli/c/enc/metablock.c +0 -663
- package/vendor/brotli/c/enc/metablock.h +0 -105
- package/vendor/brotli/c/enc/metablock_inc.h +0 -183
- package/vendor/brotli/c/enc/params.h +0 -46
- package/vendor/brotli/c/enc/prefix.h +0 -53
- package/vendor/brotli/c/enc/quality.h +0 -165
- package/vendor/brotli/c/enc/ringbuffer.h +0 -167
- package/vendor/brotli/c/enc/static_dict.c +0 -486
- package/vendor/brotli/c/enc/static_dict.h +0 -40
- package/vendor/brotli/c/enc/static_dict_lut.h +0 -5864
- package/vendor/brotli/c/enc/utf8_util.c +0 -85
- package/vendor/brotli/c/enc/utf8_util.h +0 -32
- package/vendor/brotli/c/enc/write_bits.h +0 -87
- package/vendor/brotli/c/include/brotli/decode.h +0 -344
- package/vendor/brotli/c/include/brotli/encode.h +0 -448
- package/vendor/brotli/c/include/brotli/port.h +0 -288
- package/vendor/brotli/c/include/brotli/types.h +0 -83
- package/vendor/brotli/c/tools/brotli.c +0 -1116
- package/vendor/brotli/c/tools/brotli.md +0 -107
- package/vendor/brotli/compiler_config_setting.bzl +0 -28
- package/vendor/brotli/configure +0 -8
- package/vendor/brotli/configure-cmake +0 -318
- package/vendor/brotli/configure.ac +0 -14
- package/vendor/brotli/docs/brotli.1 +0 -132
- package/vendor/brotli/docs/constants.h.3 +0 -47
- package/vendor/brotli/docs/decode.h.3 +0 -415
- package/vendor/brotli/docs/encode.h.3 +0 -586
- package/vendor/brotli/docs/types.h.3 +0 -117
- package/vendor/brotli/premake5.lua +0 -78
- package/vendor/brotli/python/Makefile +0 -57
- package/vendor/brotli/python/README.md +0 -54
- package/vendor/brotli/python/_brotli.cc +0 -753
- package/vendor/brotli/python/bro.py +0 -160
- package/vendor/brotli/python/brotli.py +0 -56
- package/vendor/brotli/python/tests/__init__.py +0 -0
- package/vendor/brotli/python/tests/_test_utils.py +0 -112
- package/vendor/brotli/python/tests/bro_test.py +0 -102
- package/vendor/brotli/python/tests/compress_test.py +0 -41
- package/vendor/brotli/python/tests/compressor_test.py +0 -94
- package/vendor/brotli/python/tests/decompress_test.py +0 -42
- package/vendor/brotli/python/tests/decompressor_test.py +0 -59
- package/vendor/brotli/scripts/libbrotlicommon.pc.in +0 -11
- package/vendor/brotli/scripts/libbrotlidec.pc.in +0 -12
- package/vendor/brotli/scripts/libbrotlienc.pc.in +0 -12
- package/vendor/brotli/scripts/sources.lst +0 -104
- package/vendor/brotli/setup.cfg +0 -5
- package/vendor/brotli/setup.py +0 -293
- package/vendor/brotli/tests/Makefile +0 -17
- package/vendor/brotli/tests/compatibility_test.sh +0 -25
- package/vendor/brotli/tests/roundtrip_test.sh +0 -36
- package/vendor/brotli/tests/run-compatibility-test.cmake +0 -31
- package/vendor/brotli/tests/run-roundtrip-test.cmake +0 -36
- package/vendor/brotli/tests/testdata/empty +0 -0
- package/vendor/brotli/tests/testdata/empty.compressed +0 -1
- package/vendor/brotli/tests/testdata/ukkonooa +0 -1
- package/vendor/brotli/tests/testdata/ukkonooa.compressed +0 -0
- package/vendor/dragonbox/CMakeLists.txt +0 -123
- package/vendor/dragonbox/LICENSE-Apache2-LLVM +0 -218
- package/vendor/dragonbox/LICENSE-Boost +0 -23
- package/vendor/dragonbox/README.md +0 -277
- package/vendor/dragonbox/cmake/dragonboxConfig.cmake +0 -1
- package/vendor/dragonbox/include/dragonbox/dragonbox.h +0 -2674
- package/vendor/dragonbox/include/dragonbox/dragonbox_to_chars.h +0 -108
- package/vendor/dragonbox/other_files/Dragonbox.pdf +0 -0
- package/vendor/dragonbox/other_files/Dragonbox_old.pdf +0 -0
- package/vendor/dragonbox/other_files/milo_benchmark.png +0 -0
- package/vendor/dragonbox/other_files/unknown_win64_vc2019.html +0 -540
- package/vendor/dragonbox/other_files/unknown_win64_vc2019_randomdigit_time.png +0 -0
- package/vendor/dragonbox/source/dragonbox_to_chars.cpp +0 -303
- package/vendor/dragonbox/subproject/3rdparty/grisu_exact/CMakeLists.txt +0 -24
- package/vendor/dragonbox/subproject/3rdparty/grisu_exact/fp_to_chars.cpp +0 -238
- package/vendor/dragonbox/subproject/3rdparty/grisu_exact/fp_to_chars.h +0 -95
- package/vendor/dragonbox/subproject/3rdparty/grisu_exact/grisu_exact.h +0 -2666
- package/vendor/dragonbox/subproject/3rdparty/ryu/CMakeLists.txt +0 -16
- package/vendor/dragonbox/subproject/3rdparty/ryu/ryu/common.h +0 -114
- package/vendor/dragonbox/subproject/3rdparty/ryu/ryu/d2s.c +0 -509
- package/vendor/dragonbox/subproject/3rdparty/ryu/ryu/d2s_full_table.h +0 -367
- package/vendor/dragonbox/subproject/3rdparty/ryu/ryu/d2s_intrinsics.h +0 -357
- package/vendor/dragonbox/subproject/3rdparty/ryu/ryu/digit_table.h +0 -35
- package/vendor/dragonbox/subproject/3rdparty/ryu/ryu/f2s.c +0 -345
- package/vendor/dragonbox/subproject/3rdparty/ryu/ryu/f2s_full_table.h +0 -55
- package/vendor/dragonbox/subproject/3rdparty/ryu/ryu/f2s_intrinsics.h +0 -128
- package/vendor/dragonbox/subproject/3rdparty/ryu/ryu/ryu.h +0 -46
- package/vendor/dragonbox/subproject/3rdparty/schubfach/CMakeLists.txt +0 -22
- package/vendor/dragonbox/subproject/3rdparty/schubfach/schubfach_32.cc +0 -699
- package/vendor/dragonbox/subproject/3rdparty/schubfach/schubfach_32.h +0 -31
- package/vendor/dragonbox/subproject/3rdparty/schubfach/schubfach_64.cc +0 -1354
- package/vendor/dragonbox/subproject/3rdparty/schubfach/schubfach_64.h +0 -31
- package/vendor/dragonbox/subproject/3rdparty/shaded_plots/example_shaded_plots.m +0 -68
- package/vendor/dragonbox/subproject/3rdparty/shaded_plots/license.txt +0 -25
- package/vendor/dragonbox/subproject/3rdparty/shaded_plots/plot_distribution.m +0 -92
- package/vendor/dragonbox/subproject/3rdparty/shaded_plots/plot_distribution_prctile.m +0 -121
- package/vendor/dragonbox/subproject/3rdparty/shaded_plots/plot_histogram_shaded.m +0 -99
- package/vendor/dragonbox/subproject/3rdparty/shaded_plots/plot_shaded.m +0 -93
- package/vendor/dragonbox/subproject/benchmark/CMakeLists.txt +0 -65
- package/vendor/dragonbox/subproject/benchmark/include/benchmark.h +0 -40
- package/vendor/dragonbox/subproject/benchmark/matlab/plot_benchmarks.m +0 -22
- package/vendor/dragonbox/subproject/benchmark/matlab/plot_digit_benchmark.m +0 -78
- package/vendor/dragonbox/subproject/benchmark/matlab/plot_uniform_benchmark.m +0 -95
- package/vendor/dragonbox/subproject/benchmark/results/digits_benchmark_binary32_clang.png +0 -0
- package/vendor/dragonbox/subproject/benchmark/results/digits_benchmark_binary32_msvc.png +0 -0
- package/vendor/dragonbox/subproject/benchmark/results/digits_benchmark_binary64_clang.png +0 -0
- package/vendor/dragonbox/subproject/benchmark/results/digits_benchmark_binary64_msvc.png +0 -0
- package/vendor/dragonbox/subproject/benchmark/results/uniform_benchmark_binary32_clang.png +0 -0
- package/vendor/dragonbox/subproject/benchmark/results/uniform_benchmark_binary32_msvc.png +0 -0
- package/vendor/dragonbox/subproject/benchmark/results/uniform_benchmark_binary64_clang.png +0 -0
- package/vendor/dragonbox/subproject/benchmark/results/uniform_benchmark_binary64_msvc.png +0 -0
- package/vendor/dragonbox/subproject/benchmark/source/benchmark.cpp +0 -238
- package/vendor/dragonbox/subproject/benchmark/source/dragonbox.cpp +0 -30
- package/vendor/dragonbox/subproject/benchmark/source/grisu_exact.cpp +0 -36
- package/vendor/dragonbox/subproject/benchmark/source/ryu.cpp +0 -27
- package/vendor/dragonbox/subproject/benchmark/source/schubfach.cpp +0 -31
- package/vendor/dragonbox/subproject/common/CMakeLists.txt +0 -42
- package/vendor/dragonbox/subproject/common/include/best_rational_approx.h +0 -97
- package/vendor/dragonbox/subproject/common/include/big_uint.h +0 -218
- package/vendor/dragonbox/subproject/common/include/continued_fractions.h +0 -174
- package/vendor/dragonbox/subproject/common/include/good_rational_approx.h +0 -267
- package/vendor/dragonbox/subproject/common/include/random_float.h +0 -182
- package/vendor/dragonbox/subproject/common/include/rational_continued_fractions.h +0 -57
- package/vendor/dragonbox/subproject/common/source/big_uint.cpp +0 -602
- package/vendor/dragonbox/subproject/meta/CMakeLists.txt +0 -41
- package/vendor/dragonbox/subproject/meta/results/binary32_generated_cache.txt +0 -82
- package/vendor/dragonbox/subproject/meta/results/binary64_compressed_cache_error_table.txt +0 -10
- package/vendor/dragonbox/subproject/meta/results/binary64_generated_cache.txt +0 -623
- package/vendor/dragonbox/subproject/meta/source/generate_cache.cpp +0 -126
- package/vendor/dragonbox/subproject/meta/source/live_test.cpp +0 -81
- package/vendor/dragonbox/subproject/meta/source/perf_test.cpp +0 -104
- package/vendor/dragonbox/subproject/meta/source/sandbox.cpp +0 -20
- package/vendor/dragonbox/subproject/test/CMakeLists.txt +0 -70
- package/vendor/dragonbox/subproject/test/results/binary32.csv +0 -255
- package/vendor/dragonbox/subproject/test/results/binary64.csv +0 -2047
- package/vendor/dragonbox/subproject/test/results/plot_required_bits.m +0 -18
- package/vendor/dragonbox/subproject/test/source/test_all_shorter_interval_cases.cpp +0 -88
- package/vendor/dragonbox/subproject/test/source/uniform_random_test.cpp +0 -95
- package/vendor/dragonbox/subproject/test/source/verify_cache_precision.cpp +0 -338
- package/vendor/dragonbox/subproject/test/source/verify_compressed_cache.cpp +0 -154
- package/vendor/dragonbox/subproject/test/source/verify_fast_multiplication.cpp +0 -168
- package/vendor/dragonbox/subproject/test/source/verify_log_computation.cpp +0 -251
- package/vendor/dragonbox/subproject/test/source/verify_magic_division.cpp +0 -113
- package/vendor/miniz/ChangeLog.md +0 -239
- package/vendor/miniz/LICENSE +0 -22
- package/vendor/miniz/examples/example1.c +0 -105
- package/vendor/miniz/examples/example2.c +0 -164
- package/vendor/miniz/examples/example3.c +0 -269
- package/vendor/miniz/examples/example4.c +0 -102
- package/vendor/miniz/examples/example5.c +0 -327
- package/vendor/miniz/examples/example6.c +0 -166
- package/vendor/miniz/miniz.c +0 -7835
- package/vendor/miniz/miniz.h +0 -1422
- package/vendor/miniz/readme.md +0 -46
- /package/src/koffi/build/{2.3.6-beta.6 → 2.3.7}/koffi_win32_arm64/koffi.exp +0 -0
- /package/src/koffi/build/{2.3.6-beta.6 → 2.3.7}/koffi_win32_arm64/koffi.lib +0 -0
- /package/src/koffi/build/{2.3.6-beta.6 → 2.3.7}/koffi_win32_ia32/koffi.exp +0 -0
- /package/src/koffi/build/{2.3.6-beta.6 → 2.3.7}/koffi_win32_ia32/koffi.lib +0 -0
- /package/src/koffi/build/{2.3.6-beta.6 → 2.3.7}/koffi_win32_x64/koffi.exp +0 -0
- /package/src/koffi/build/{2.3.6-beta.6 → 2.3.7}/koffi_win32_x64/koffi.lib +0 -0
|
@@ -1,2666 +0,0 @@
|
|
|
1
|
-
// Copyright 2020 Junekey Jeon
|
|
2
|
-
//
|
|
3
|
-
// The contents of this file may be used under the terms of
|
|
4
|
-
// the Apache License v2.0 with LLVM Exceptions.
|
|
5
|
-
//
|
|
6
|
-
// (See accompanying file LICENSE-Apache or copy at
|
|
7
|
-
// https://llvm.org/foundation/relicensing/LICENSE.txt)
|
|
8
|
-
//
|
|
9
|
-
// Alternatively, the contents of this file may be used under the terms of
|
|
10
|
-
// the Boost Software License, Version 1.0.
|
|
11
|
-
// (See accompanying file LICENSE-Boost or copy at
|
|
12
|
-
// https://www.boost.org/LICENSE_1_0.txt)
|
|
13
|
-
//
|
|
14
|
-
// Unless required by applicable law or agreed to in writing, this software
|
|
15
|
-
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
16
|
-
// KIND, either express or implied.
|
|
17
|
-
|
|
18
|
-
#ifndef JKJ_GRISU_EXACT
|
|
19
|
-
#define JKJ_GRISU_EXACT
|
|
20
|
-
|
|
21
|
-
//#include <bit> // We don't have C++20 <bit> yet
|
|
22
|
-
#include <bitset> // Payload of NaN's is of type std::bitset
|
|
23
|
-
#include <cassert>
|
|
24
|
-
#include <cstddef> // std::size_t, etc
|
|
25
|
-
#include <cstdint> // std::uint32_t, etc.
|
|
26
|
-
#include <cstring> // std::memcpy; not needed if C++20 std::bit_cast is used instead
|
|
27
|
-
#include <limits>
|
|
28
|
-
#include <type_traits> // std::remove_cv, etc
|
|
29
|
-
|
|
30
|
-
#if defined(_MSC_VER)
|
|
31
|
-
#include <intrin.h>
|
|
32
|
-
#include <immintrin.h>
|
|
33
|
-
|
|
34
|
-
// Suppress additional buffer overrun check
|
|
35
|
-
// I have no idea why MSVC thinks some functions here are vulnerable to the buffer overrun attacks
|
|
36
|
-
// No, they aren't.
|
|
37
|
-
#ifndef __clang__
|
|
38
|
-
#define JKJ_SAFEBUFFERS __declspec(safebuffers)
|
|
39
|
-
#else
|
|
40
|
-
#define JKJ_SAFEBUFFERS
|
|
41
|
-
#endif
|
|
42
|
-
#else
|
|
43
|
-
#define JKJ_SAFEBUFFERS
|
|
44
|
-
#endif
|
|
45
|
-
|
|
46
|
-
namespace jkj {
|
|
47
|
-
namespace grisu_exact_detail {
|
|
48
|
-
////////////////////////////////////////////////////////////////////////////////////////
|
|
49
|
-
// Utilities for 128-bit arithmetic
|
|
50
|
-
////////////////////////////////////////////////////////////////////////////////////////
|
|
51
|
-
|
|
52
|
-
// Get 128-bit result of multiplication of two 64-bit unsigned integers
|
|
53
|
-
struct uint128 {
|
|
54
|
-
uint128() = default;
|
|
55
|
-
|
|
56
|
-
#if (defined(__GNUC__) || defined(__clang__)) && defined(__SIZEOF_INT128__) && defined(__x86_64__)
|
|
57
|
-
unsigned __int128 internal_;
|
|
58
|
-
|
|
59
|
-
constexpr uint128(std::uint64_t high, std::uint64_t low) noexcept :
|
|
60
|
-
internal_{ ((unsigned __int128)low) | (((unsigned __int128)high) << 64) } {}
|
|
61
|
-
|
|
62
|
-
constexpr uint128(unsigned __int128 u) : internal_{ u } {}
|
|
63
|
-
|
|
64
|
-
constexpr std::uint64_t high() const noexcept {
|
|
65
|
-
return std::uint64_t(internal_ >> 64);
|
|
66
|
-
}
|
|
67
|
-
constexpr std::uint64_t low() const noexcept {
|
|
68
|
-
return std::uint64_t(internal_);
|
|
69
|
-
}
|
|
70
|
-
#else
|
|
71
|
-
std::uint64_t high_;
|
|
72
|
-
std::uint64_t low_;
|
|
73
|
-
|
|
74
|
-
constexpr uint128(std::uint64_t high, std::uint64_t low) noexcept :
|
|
75
|
-
high_{ high }, low_{ low } {}
|
|
76
|
-
|
|
77
|
-
constexpr std::uint64_t high() const noexcept {
|
|
78
|
-
return high_;
|
|
79
|
-
}
|
|
80
|
-
constexpr std::uint64_t low() const noexcept {
|
|
81
|
-
return low_;
|
|
82
|
-
}
|
|
83
|
-
#endif
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
JKJ_SAFEBUFFERS
|
|
87
|
-
inline uint128 umul128(std::uint64_t x, std::uint64_t y) noexcept {
|
|
88
|
-
#if (defined(__GNUC__) || defined(__clang__)) && defined(__SIZEOF_INT128__) && defined(__x86_64__)
|
|
89
|
-
return (unsigned __int128)(x) * (unsigned __int128)(y);
|
|
90
|
-
#elif defined(_MSC_VER) && defined(_M_X64)
|
|
91
|
-
uint128 result;
|
|
92
|
-
result.low_ = _umul128(x, y, &result.high_);
|
|
93
|
-
return result;
|
|
94
|
-
#else
|
|
95
|
-
constexpr auto mask = (std::uint64_t(1) << 32) - std::uint64_t(1);
|
|
96
|
-
|
|
97
|
-
auto a = x >> 32;
|
|
98
|
-
auto b = x & mask;
|
|
99
|
-
auto c = y >> 32;
|
|
100
|
-
auto d = y & mask;
|
|
101
|
-
|
|
102
|
-
auto ac = a * c;
|
|
103
|
-
auto bc = b * c;
|
|
104
|
-
auto ad = a * d;
|
|
105
|
-
auto bd = b * d;
|
|
106
|
-
|
|
107
|
-
auto intermediate = (bd >> 32) + (ad & mask) + (bc & mask);
|
|
108
|
-
|
|
109
|
-
return{ ac + (intermediate >> 32) + (ad >> 32) + (bc >> 32),
|
|
110
|
-
(intermediate << 32) + (bd & mask) };
|
|
111
|
-
#endif
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
JKJ_SAFEBUFFERS
|
|
115
|
-
inline std::uint64_t umul128_upper64(std::uint64_t x, std::uint64_t y) noexcept {
|
|
116
|
-
#if (defined(__GNUC__) || defined(__clang__)) && defined(__SIZEOF_INT128__) && defined(__x86_64__)
|
|
117
|
-
auto p = (unsigned __int128)(x) * (unsigned __int128)(y);
|
|
118
|
-
return std::uint64_t(p >> 64);
|
|
119
|
-
#elif defined(_MSC_VER) && defined(_M_X64)
|
|
120
|
-
return __umulh(x, y);
|
|
121
|
-
#else
|
|
122
|
-
constexpr auto mask = (std::uint64_t(1) << 32) - std::uint64_t(1);
|
|
123
|
-
|
|
124
|
-
auto a = x >> 32;
|
|
125
|
-
auto b = x & mask;
|
|
126
|
-
auto c = y >> 32;
|
|
127
|
-
auto d = y & mask;
|
|
128
|
-
|
|
129
|
-
auto ac = a * c;
|
|
130
|
-
auto bc = b * c;
|
|
131
|
-
auto ad = a * d;
|
|
132
|
-
auto bd = b * d;
|
|
133
|
-
|
|
134
|
-
auto intermediate = (bd >> 32) + (ad & mask) + (bc & mask);
|
|
135
|
-
|
|
136
|
-
return ac + (intermediate >> 32) + (ad >> 32) + (bc >> 32);
|
|
137
|
-
#endif
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Get upper 64-bits of multiplication of a 64-bit unsigned integer and a 128-bit unsigned integer
|
|
141
|
-
JKJ_SAFEBUFFERS
|
|
142
|
-
inline std::uint64_t umul192_upper64(std::uint64_t x, uint128 y) noexcept {
|
|
143
|
-
auto g0 = umul128(x, y.high());
|
|
144
|
-
auto g10 = umul128_upper64(x, y.low());
|
|
145
|
-
|
|
146
|
-
#if (defined(__GNUC__) || defined(__clang__)) && defined(__SIZEOF_INT128__) && defined(__x86_64__)
|
|
147
|
-
return uint128{ g0.internal_ + g10 }.high();
|
|
148
|
-
#elif defined(_MSC_VER) && defined(_M_X64)
|
|
149
|
-
std::uint64_t high, low;
|
|
150
|
-
auto carry = _addcarry_u64(0, g0.low(), g10, &low);
|
|
151
|
-
_addcarry_u64(carry, g0.high(), 0, &high);
|
|
152
|
-
return high;
|
|
153
|
-
#else
|
|
154
|
-
auto intermediate = g0.low() + g10;
|
|
155
|
-
return g0.high() + (intermediate < g10);
|
|
156
|
-
#endif
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Get upper 32-bits of multiplication of a 32-bit unsigned integer and a 64-bit unsigned integer
|
|
160
|
-
inline std::uint32_t umul96_upper32(std::uint32_t x, std::uint64_t y) noexcept {
|
|
161
|
-
return std::uint32_t(umul128_upper64(x, y));
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// Compute b^e in compile-time
|
|
165
|
-
template <class UInt>
|
|
166
|
-
constexpr UInt compute_power(UInt b, unsigned int e) noexcept {
|
|
167
|
-
UInt r = 1;
|
|
168
|
-
for (unsigned int i = 0; i < e; ++i) {
|
|
169
|
-
r *= b;
|
|
170
|
-
}
|
|
171
|
-
return r;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// Check if a number is a multiple of 2^exp
|
|
175
|
-
template <class UInt>
|
|
176
|
-
inline bool divisible_by_power_of_2(UInt x, int exp) noexcept {
|
|
177
|
-
static_assert(std::is_same_v<UInt, std::uint32_t> || std::is_same_v<UInt, std::uint64_t>);
|
|
178
|
-
assert(exp >= 1);
|
|
179
|
-
assert(x != 0);
|
|
180
|
-
#if (defined(__GNUC__) || defined(__clang__)) && defined(__x86_64__)
|
|
181
|
-
int index;
|
|
182
|
-
if constexpr (std::is_same_v<UInt, std::uint32_t>) {
|
|
183
|
-
if constexpr (sizeof(unsigned long) == 4) {
|
|
184
|
-
index = __builtin_ctzl((unsigned long)x);
|
|
185
|
-
}
|
|
186
|
-
else {
|
|
187
|
-
static_assert(sizeof(unsigned int) == 4,
|
|
188
|
-
"jkj::grisu_exact: at least one of unsigned int and unsigned long should be 4 bytes long");
|
|
189
|
-
index = __builtin_ctz((unsigned int)x);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
else {
|
|
193
|
-
static_assert(sizeof(unsigned long long) == 8,
|
|
194
|
-
"jkj::grisu_exact: unsigned long long should be 8 bytes long");
|
|
195
|
-
index = __builtin_ctzll((unsigned long long)x);
|
|
196
|
-
}
|
|
197
|
-
return index >= exp;
|
|
198
|
-
#elif defined(_MSC_VER) && defined(_M_X64)
|
|
199
|
-
unsigned long index;
|
|
200
|
-
if constexpr (std::is_same_v<UInt, std::uint32_t>) {
|
|
201
|
-
_BitScanForward(&index, x);
|
|
202
|
-
}
|
|
203
|
-
else {
|
|
204
|
-
_BitScanForward64(&index, x);
|
|
205
|
-
}
|
|
206
|
-
return int(index) >= exp;
|
|
207
|
-
#else
|
|
208
|
-
if (exp >= int(sizeof(UInt) * 8)) {
|
|
209
|
-
return false;
|
|
210
|
-
}
|
|
211
|
-
return x == ((x >> exp) << exp);
|
|
212
|
-
#endif
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
// Check if a number is a multiple of 5^exp
|
|
216
|
-
// Use the algorithm introduced in Section 9 of Granlund-Montgomery
|
|
217
|
-
template <class UInt>
|
|
218
|
-
constexpr UInt compute_modular_inverse_of_5() noexcept {
|
|
219
|
-
// Use Euler's theorem
|
|
220
|
-
// phi(p^k) = p^(k-1) * (p-1), so phi(2^n) = 2^(n-1).
|
|
221
|
-
// Hence, we need to compute 5^(2^(n-1) - 1), which is equal to
|
|
222
|
-
// 5^1 * 5^2 * 5^4 * 5^8 * ... * 5^(2^(n-2)),
|
|
223
|
-
// which can be computed as:
|
|
224
|
-
constexpr unsigned int n = std::numeric_limits<UInt>::digits;
|
|
225
|
-
UInt r = 5;
|
|
226
|
-
for (unsigned int e = 1; e <= n - 2; ++e) {
|
|
227
|
-
r = 5 * r * r;
|
|
228
|
-
}
|
|
229
|
-
return r;
|
|
230
|
-
}
|
|
231
|
-
template <class UInt>
|
|
232
|
-
struct divisibility_test_table_entry {
|
|
233
|
-
UInt max_quotient;
|
|
234
|
-
UInt mod_inv;
|
|
235
|
-
};
|
|
236
|
-
// std::array might be an overkill
|
|
237
|
-
template <class UInt, unsigned int N>
|
|
238
|
-
struct divisibility_test_table {
|
|
239
|
-
static constexpr auto size = N;
|
|
240
|
-
divisibility_test_table_entry<UInt> value[N];
|
|
241
|
-
};
|
|
242
|
-
template <class UInt, std::size_t size>
|
|
243
|
-
constexpr auto generate_divisibility_test_table() noexcept {
|
|
244
|
-
using return_type = divisibility_test_table<UInt, size>;
|
|
245
|
-
|
|
246
|
-
return_type table{};
|
|
247
|
-
for (unsigned int i = 0; i < size; ++i) {
|
|
248
|
-
table.value[i].max_quotient =
|
|
249
|
-
std::numeric_limits<UInt>::max() / compute_power(UInt(5), i);
|
|
250
|
-
table.value[i].mod_inv =
|
|
251
|
-
compute_power(compute_modular_inverse_of_5<UInt>(), i);
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
return table;
|
|
255
|
-
}
|
|
256
|
-
template <class UInt>
|
|
257
|
-
struct divisibility_test_table_holder {
|
|
258
|
-
static constexpr auto table = generate_divisibility_test_table<UInt,
|
|
259
|
-
std::is_same_v<UInt, std::uint32_t> ? 12 : 24>();
|
|
260
|
-
};
|
|
261
|
-
template <class UInt>
|
|
262
|
-
constexpr bool divisible_by_power_of_5(UInt x, unsigned int exp) noexcept {
|
|
263
|
-
assert(exp < divisibility_test_table_holder<UInt>::table.size);
|
|
264
|
-
auto const& entry = divisibility_test_table_holder<UInt>::table.value[exp];
|
|
265
|
-
return (x * entry.mod_inv) <= entry.max_quotient;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
////////////////////////////////////////////////////////////////////////////////////////
|
|
270
|
-
// Fast and accurate log floor calculation
|
|
271
|
-
////////////////////////////////////////////////////////////////////////////////////////
|
|
272
|
-
|
|
273
|
-
// This function is accurate if e is in the range [-1650,1650]
|
|
274
|
-
template <bool should_assert = true>
|
|
275
|
-
constexpr int floor_log10_pow2(int e) noexcept {
|
|
276
|
-
if constexpr (should_assert) {
|
|
277
|
-
assert(e >= -1650 && e <= 1650);
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
// The next 12 digits are 0xd27
|
|
281
|
-
constexpr std::int32_t log10_2_up_to_20 = 0x4d104;
|
|
282
|
-
|
|
283
|
-
return int(
|
|
284
|
-
// Calculate 0x0.4d104 * exp * 2^20
|
|
285
|
-
(std::int32_t(e) * log10_2_up_to_20)
|
|
286
|
-
// Perform arithmetic-shift
|
|
287
|
-
>> 20);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
// This function is accurate if e is in the range [-642,642]
|
|
291
|
-
template <bool should_assert = true>
|
|
292
|
-
constexpr int floor_log2_pow10(int e) noexcept {
|
|
293
|
-
if constexpr (should_assert) {
|
|
294
|
-
assert(e >= -642 && e <= 642);
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
// The next 12 digits are 0x12f
|
|
298
|
-
constexpr std::int32_t log2_5_over_4_up_to_20 = 0x35269e;
|
|
299
|
-
|
|
300
|
-
return int(
|
|
301
|
-
// Calculate 0x3.5269e * exp * 2^20
|
|
302
|
-
(std::int32_t(e) * log2_5_over_4_up_to_20)
|
|
303
|
-
// Perform arithmetic-shift
|
|
304
|
-
>> 20);
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
// This function is accurate if e is in the range [-65536,+65536]
|
|
309
|
-
// This function is only executed at compile-time,
|
|
310
|
-
// and never executed at runtime.
|
|
311
|
-
template <bool should_assert = true>
|
|
312
|
-
constexpr int floor_log5_pow2(int e) noexcept {
|
|
313
|
-
if constexpr (should_assert) {
|
|
314
|
-
assert(e >= -65536 && e <= 65536);
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
// The next 32 digits are 0x143dcb94
|
|
318
|
-
constexpr std::uint32_t log5_2_up_to_32 = 0x6e40d1a4;
|
|
319
|
-
|
|
320
|
-
return int(
|
|
321
|
-
// Calculate 0x0.6e40d1a4 * exp * 2^32
|
|
322
|
-
(std::int64_t(e) * log5_2_up_to_32)
|
|
323
|
-
// Perform arithmetic-shift
|
|
324
|
-
>> 32);
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
////////////////////////////////////////////////////////////////////////////////////////
|
|
329
|
-
// Collection of relevent information about IEEE-754 and precision settings
|
|
330
|
-
////////////////////////////////////////////////////////////////////////////////////////
|
|
331
|
-
|
|
332
|
-
template <class Float>
|
|
333
|
-
struct common_info {
|
|
334
|
-
using float_type = Float;
|
|
335
|
-
|
|
336
|
-
static_assert(std::numeric_limits<Float>::is_iec559 &&
|
|
337
|
-
std::numeric_limits<Float>::radix == 2 &&
|
|
338
|
-
(sizeof(Float) == 4 || sizeof(Float) == 8),
|
|
339
|
-
"Grisu-Exact algorithm only applies to IEEE-754 binary32 and binary64 formats!");
|
|
340
|
-
|
|
341
|
-
static constexpr std::size_t precision = std::numeric_limits<Float>::digits - 1;
|
|
342
|
-
|
|
343
|
-
using extended_significand_type = std::conditional_t<
|
|
344
|
-
sizeof(Float) == 4,
|
|
345
|
-
std::uint32_t,
|
|
346
|
-
std::uint64_t>;
|
|
347
|
-
|
|
348
|
-
static_assert(sizeof(extended_significand_type) == sizeof(Float));
|
|
349
|
-
|
|
350
|
-
static constexpr std::size_t extended_precision =
|
|
351
|
-
sizeof(extended_significand_type) * std::numeric_limits<unsigned char>::digits;
|
|
352
|
-
|
|
353
|
-
static constexpr auto sign_bit_mask =
|
|
354
|
-
(extended_significand_type(1) << (extended_precision - 1));
|
|
355
|
-
static constexpr std::size_t exponent_bits =
|
|
356
|
-
extended_precision - precision - 1;
|
|
357
|
-
static constexpr int exponent_bias = 1 - (1 << (exponent_bits - 1));
|
|
358
|
-
static constexpr auto exponent_bits_mask =
|
|
359
|
-
((extended_significand_type(1) << exponent_bits) - 1) << precision;
|
|
360
|
-
|
|
361
|
-
static constexpr auto boundary_bit =
|
|
362
|
-
(extended_significand_type(1) << (extended_precision - precision - 2));
|
|
363
|
-
static constexpr auto normal_interval_length = boundary_bit << 1;
|
|
364
|
-
static constexpr auto edge_case_boundary_bit = boundary_bit >> 1;
|
|
365
|
-
|
|
366
|
-
static constexpr int min_exponent =
|
|
367
|
-
std::numeric_limits<Float>::min_exponent - int(extended_precision);
|
|
368
|
-
static constexpr int max_exponent =
|
|
369
|
-
std::numeric_limits<Float>::max_exponent - int(extended_precision);
|
|
370
|
-
static_assert(min_exponent < 0 && max_exponent > 0 && -min_exponent >= max_exponent);
|
|
371
|
-
static_assert(min_exponent == 1 + exponent_bias - int(extended_precision) + 1);
|
|
372
|
-
|
|
373
|
-
static constexpr int alpha = sizeof(Float) == 4 ? -5 : -5;
|
|
374
|
-
static constexpr int gamma = alpha + 3;
|
|
375
|
-
static_assert(alpha >= -(int(extended_precision - precision) - 4) && gamma <= 0);
|
|
376
|
-
|
|
377
|
-
static constexpr int min_kappa =
|
|
378
|
-
-floor_log10_pow2(-(int(extended_precision - precision) - 3 + alpha)) - 1;
|
|
379
|
-
static constexpr int max_kappa =
|
|
380
|
-
-floor_log10_pow2(-(int(extended_precision) + gamma)) - 1;
|
|
381
|
-
static_assert(0 <= min_kappa && min_kappa <= max_kappa);
|
|
382
|
-
|
|
383
|
-
static constexpr int initial_kappa = sizeof(Float) == 4 ? 2 : 3;
|
|
384
|
-
static_assert(min_kappa <= initial_kappa && initial_kappa <= max_kappa);
|
|
385
|
-
|
|
386
|
-
// Ensure delta cannot overflow
|
|
387
|
-
// delta is upper bounded by 2^(q-p-1+gamma), and
|
|
388
|
-
// during the decreasing search, it would get multiplied by 10^(initial_kappa-min_kappa-1)
|
|
389
|
-
static_assert(floor_log2_pow10(initial_kappa - min_kappa - 1) <
|
|
390
|
-
32 - int(extended_precision - precision - 1) - gamma);
|
|
391
|
-
// Ensure 10^initial_kappa fits inside 32 bits
|
|
392
|
-
static_assert(initial_kappa < floor_log10_pow2(32));
|
|
393
|
-
|
|
394
|
-
static constexpr int min_k = -floor_log10_pow2(max_exponent + 1 - alpha);
|
|
395
|
-
static constexpr int max_k = -floor_log10_pow2(min_exponent + 1 - alpha);
|
|
396
|
-
|
|
397
|
-
static constexpr std::size_t cache_precision = extended_precision * 2;
|
|
398
|
-
|
|
399
|
-
using cache_entry_type = std::conditional_t<
|
|
400
|
-
sizeof(Float) == 4,
|
|
401
|
-
std::uint64_t,
|
|
402
|
-
uint128>;
|
|
403
|
-
|
|
404
|
-
static constexpr int integer_check_exponent_lower_bound_for_q_mp_m3 =
|
|
405
|
-
floor_log5_pow2(-(int(extended_precision - precision) - 3 + alpha)) -
|
|
406
|
-
(int(extended_precision - precision) - 3);
|
|
407
|
-
static constexpr int integer_check_exponent_lower_bound_for_q_mp_m2 =
|
|
408
|
-
floor_log5_pow2(-(int(extended_precision - precision) - 2 + alpha)) -
|
|
409
|
-
(int(extended_precision - precision) - 2);
|
|
410
|
-
static constexpr int integer_check_exponent_lower_bound_for_q_mp_m1 =
|
|
411
|
-
floor_log5_pow2(-(int(extended_precision - precision) - 1 + alpha)) -
|
|
412
|
-
(int(extended_precision - precision) - 1);
|
|
413
|
-
static constexpr int integer_check_exponent_lower_bound_for_q_mp =
|
|
414
|
-
floor_log5_pow2(-(int(extended_precision - precision) + alpha)) -
|
|
415
|
-
(int(extended_precision - precision));
|
|
416
|
-
static constexpr int max_exponent_for_k_geq_0 = alpha + 2;
|
|
417
|
-
static constexpr int max_exponent_for_k_geq_m1 = alpha + 5;
|
|
418
|
-
static constexpr int integer_check_exponent_upper_bound_for_p_p2 =
|
|
419
|
-
(alpha - 2) - floor_log2_pow10(-floor_log5_pow2(precision + 2) - 1);
|
|
420
|
-
static constexpr int integer_check_exponent_upper_bound_for_p_p1 =
|
|
421
|
-
(alpha - 2) - floor_log2_pow10(-floor_log5_pow2(precision + 1) - 1);
|
|
422
|
-
|
|
423
|
-
// Ensure that fractional parts cannot vanish when exponent is the minimum
|
|
424
|
-
static_assert(min_exponent < integer_check_exponent_lower_bound_for_q_mp_m3);
|
|
425
|
-
|
|
426
|
-
static constexpr int zero_fractional_part_min_exponent_normal =
|
|
427
|
-
floor_log5_pow2(-(int(extended_precision - precision) - 2 + alpha)) -
|
|
428
|
-
(int(extended_precision - precision) - 2);
|
|
429
|
-
static constexpr int zero_fractional_part_min_exponent_edge =
|
|
430
|
-
floor_log5_pow2(-(int(extended_precision - precision) - 3 + alpha)) -
|
|
431
|
-
(int(extended_precision - precision) - 3);
|
|
432
|
-
static constexpr int zero_fractional_part_max_exponent_normal =
|
|
433
|
-
alpha - 2 - floor_log2_pow10(-floor_log5_pow2(precision + 2) - 1);
|
|
434
|
-
static constexpr int max_exponent_for_nonnegative_k = alpha + 2;
|
|
435
|
-
static constexpr int zero_fractional_part_min_exponent_delta_normal =
|
|
436
|
-
floor_log5_pow2(-(int(extended_precision - precision) - 1 + alpha)) -
|
|
437
|
-
(int(extended_precision - precision) - 1);
|
|
438
|
-
};
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
////////////////////////////////////////////////////////////////////////////////////////
|
|
442
|
-
// Computed cache entries
|
|
443
|
-
// !! You SHOULD regenerate the cache if you modify alpha and gamma !!
|
|
444
|
-
////////////////////////////////////////////////////////////////////////////////////////
|
|
445
|
-
|
|
446
|
-
template <class Float>
|
|
447
|
-
struct cache_holder;
|
|
448
|
-
|
|
449
|
-
template <>
|
|
450
|
-
struct cache_holder<float> {
|
|
451
|
-
static constexpr std::uint64_t cache[] = {
|
|
452
|
-
0xa2425ff75e14fc32,
|
|
453
|
-
0xcad2f7f5359a3b3f,
|
|
454
|
-
0xfd87b5f28300ca0e,
|
|
455
|
-
0x9e74d1b791e07e49,
|
|
456
|
-
0xc612062576589ddb,
|
|
457
|
-
0xf79687aed3eec552,
|
|
458
|
-
0x9abe14cd44753b53,
|
|
459
|
-
0xc16d9a0095928a28,
|
|
460
|
-
0xf1c90080baf72cb2,
|
|
461
|
-
0x971da05074da7bef,
|
|
462
|
-
0xbce5086492111aeb,
|
|
463
|
-
0xec1e4a7db69561a6,
|
|
464
|
-
0x9392ee8e921d5d08,
|
|
465
|
-
0xb877aa3236a4b44a,
|
|
466
|
-
0xe69594bec44de15c,
|
|
467
|
-
0x901d7cf73ab0acda,
|
|
468
|
-
0xb424dc35095cd810,
|
|
469
|
-
0xe12e13424bb40e14,
|
|
470
|
-
0x8cbccc096f5088cc,
|
|
471
|
-
0xafebff0bcb24aaff,
|
|
472
|
-
0xdbe6fecebdedd5bf,
|
|
473
|
-
0x89705f4136b4a598,
|
|
474
|
-
0xabcc77118461cefd,
|
|
475
|
-
0xd6bf94d5e57a42bd,
|
|
476
|
-
0x8637bd05af6c69b6,
|
|
477
|
-
0xa7c5ac471b478424,
|
|
478
|
-
0xd1b71758e219652c,
|
|
479
|
-
0x83126e978d4fdf3c,
|
|
480
|
-
0xa3d70a3d70a3d70b,
|
|
481
|
-
0xcccccccccccccccd,
|
|
482
|
-
0x8000000000000000,
|
|
483
|
-
0xa000000000000000,
|
|
484
|
-
0xc800000000000000,
|
|
485
|
-
0xfa00000000000000,
|
|
486
|
-
0x9c40000000000000,
|
|
487
|
-
0xc350000000000000,
|
|
488
|
-
0xf424000000000000,
|
|
489
|
-
0x9896800000000000,
|
|
490
|
-
0xbebc200000000000,
|
|
491
|
-
0xee6b280000000000,
|
|
492
|
-
0x9502f90000000000,
|
|
493
|
-
0xba43b74000000000,
|
|
494
|
-
0xe8d4a51000000000,
|
|
495
|
-
0x9184e72a00000000,
|
|
496
|
-
0xb5e620f480000000,
|
|
497
|
-
0xe35fa931a0000000,
|
|
498
|
-
0x8e1bc9bf04000000,
|
|
499
|
-
0xb1a2bc2ec5000000,
|
|
500
|
-
0xde0b6b3a76400000,
|
|
501
|
-
0x8ac7230489e80000,
|
|
502
|
-
0xad78ebc5ac620000,
|
|
503
|
-
0xd8d726b7177a8000,
|
|
504
|
-
0x878678326eac9000,
|
|
505
|
-
0xa968163f0a57b400,
|
|
506
|
-
0xd3c21bcecceda100,
|
|
507
|
-
0x84595161401484a0,
|
|
508
|
-
0xa56fa5b99019a5c8,
|
|
509
|
-
0xcecb8f27f4200f3a,
|
|
510
|
-
0x813f3978f8940984,
|
|
511
|
-
0xa18f07d736b90be5,
|
|
512
|
-
0xc9f2c9cd04674ede,
|
|
513
|
-
0xfc6f7c4045812296,
|
|
514
|
-
0x9dc5ada82b70b59d,
|
|
515
|
-
0xc5371912364ce305,
|
|
516
|
-
0xf684df56c3e01bc6,
|
|
517
|
-
0x9a130b963a6c115c,
|
|
518
|
-
0xc097ce7bc90715b3,
|
|
519
|
-
0xf0bdc21abb48db20,
|
|
520
|
-
0x96769950b50d88f4,
|
|
521
|
-
0xbc143fa4e250eb31,
|
|
522
|
-
0xeb194f8e1ae525fd,
|
|
523
|
-
0x92efd1b8d0cf37be,
|
|
524
|
-
0xb7abc627050305ad,
|
|
525
|
-
0xe596b7b0c643c719,
|
|
526
|
-
0x8f7e32ce7bea5c6f,
|
|
527
|
-
0xb35dbf821ae4f38b,
|
|
528
|
-
0xe0352f62a19e306e
|
|
529
|
-
};
|
|
530
|
-
};
|
|
531
|
-
|
|
532
|
-
template <>
|
|
533
|
-
struct cache_holder<double> {
|
|
534
|
-
static constexpr uint128 cache[] = {
|
|
535
|
-
{ 0xc795830d75038c1d, 0xd59df5b9ef6a2418 },
|
|
536
|
-
{ 0xf97ae3d0d2446f25, 0x4b0573286b44ad1e },
|
|
537
|
-
{ 0x9becce62836ac577, 0x4ee367f9430aec33 },
|
|
538
|
-
{ 0xc2e801fb244576d5, 0x229c41f793cda740 },
|
|
539
|
-
{ 0xf3a20279ed56d48a, 0x6b43527578c11110 },
|
|
540
|
-
{ 0x9845418c345644d6, 0x830a13896b78aaaa },
|
|
541
|
-
{ 0xbe5691ef416bd60c, 0x23cc986bc656d554 },
|
|
542
|
-
{ 0xedec366b11c6cb8f, 0x2cbfbe86b7ec8aa9 },
|
|
543
|
-
{ 0x94b3a202eb1c3f39, 0x7bf7d71432f3d6aa },
|
|
544
|
-
{ 0xb9e08a83a5e34f07, 0xdaf5ccd93fb0cc54 },
|
|
545
|
-
{ 0xe858ad248f5c22c9, 0xd1b3400f8f9cff69 },
|
|
546
|
-
{ 0x91376c36d99995be, 0x23100809b9c21fa2 },
|
|
547
|
-
{ 0xb58547448ffffb2d, 0xabd40a0c2832a78b },
|
|
548
|
-
{ 0xe2e69915b3fff9f9, 0x16c90c8f323f516d },
|
|
549
|
-
{ 0x8dd01fad907ffc3b, 0xae3da7d97f6792e4 },
|
|
550
|
-
{ 0xb1442798f49ffb4a, 0x99cd11cfdf41779d },
|
|
551
|
-
{ 0xdd95317f31c7fa1d, 0x40405643d711d584 },
|
|
552
|
-
{ 0x8a7d3eef7f1cfc52, 0x482835ea666b2573 },
|
|
553
|
-
{ 0xad1c8eab5ee43b66, 0xda3243650005eed0 },
|
|
554
|
-
{ 0xd863b256369d4a40, 0x90bed43e40076a83 },
|
|
555
|
-
{ 0x873e4f75e2224e68, 0x5a7744a6e804a292 },
|
|
556
|
-
{ 0xa90de3535aaae202, 0x711515d0a205cb37 },
|
|
557
|
-
{ 0xd3515c2831559a83, 0x0d5a5b44ca873e04 },
|
|
558
|
-
{ 0x8412d9991ed58091, 0xe858790afe9486c3 },
|
|
559
|
-
{ 0xa5178fff668ae0b6, 0x626e974dbe39a873 },
|
|
560
|
-
{ 0xce5d73ff402d98e3, 0xfb0a3d212dc81290 },
|
|
561
|
-
{ 0x80fa687f881c7f8e, 0x7ce66634bc9d0b9a },
|
|
562
|
-
{ 0xa139029f6a239f72, 0x1c1fffc1ebc44e81 },
|
|
563
|
-
{ 0xc987434744ac874e, 0xa327ffb266b56221 },
|
|
564
|
-
{ 0xfbe9141915d7a922, 0x4bf1ff9f0062baa9 },
|
|
565
|
-
{ 0x9d71ac8fada6c9b5, 0x6f773fc3603db4aa },
|
|
566
|
-
{ 0xc4ce17b399107c22, 0xcb550fb4384d21d4 },
|
|
567
|
-
{ 0xf6019da07f549b2b, 0x7e2a53a146606a49 },
|
|
568
|
-
{ 0x99c102844f94e0fb, 0x2eda7444cbfc426e },
|
|
569
|
-
{ 0xc0314325637a1939, 0xfa911155fefb5309 },
|
|
570
|
-
{ 0xf03d93eebc589f88, 0x793555ab7eba27cb },
|
|
571
|
-
{ 0x96267c7535b763b5, 0x4bc1558b2f3458df },
|
|
572
|
-
{ 0xbbb01b9283253ca2, 0x9eb1aaedfb016f17 },
|
|
573
|
-
{ 0xea9c227723ee8bcb, 0x465e15a979c1cadd },
|
|
574
|
-
{ 0x92a1958a7675175f, 0x0bfacd89ec191eca },
|
|
575
|
-
{ 0xb749faed14125d36, 0xcef980ec671f667c },
|
|
576
|
-
{ 0xe51c79a85916f484, 0x82b7e12780e7401b },
|
|
577
|
-
{ 0x8f31cc0937ae58d2, 0xd1b2ecb8b0908811 },
|
|
578
|
-
{ 0xb2fe3f0b8599ef07, 0x861fa7e6dcb4aa16 },
|
|
579
|
-
{ 0xdfbdcece67006ac9, 0x67a791e093e1d49b },
|
|
580
|
-
{ 0x8bd6a141006042bd, 0xe0c8bb2c5c6d24e1 },
|
|
581
|
-
{ 0xaecc49914078536d, 0x58fae9f773886e19 },
|
|
582
|
-
{ 0xda7f5bf590966848, 0xaf39a475506a899f },
|
|
583
|
-
{ 0x888f99797a5e012d, 0x6d8406c952429604 },
|
|
584
|
-
{ 0xaab37fd7d8f58178, 0xc8e5087ba6d33b84 },
|
|
585
|
-
{ 0xd5605fcdcf32e1d6, 0xfb1e4a9a90880a65 },
|
|
586
|
-
{ 0x855c3be0a17fcd26, 0x5cf2eea09a550680 },
|
|
587
|
-
{ 0xa6b34ad8c9dfc06f, 0xf42faa48c0ea481f },
|
|
588
|
-
{ 0xd0601d8efc57b08b, 0xf13b94daf124da27 },
|
|
589
|
-
{ 0x823c12795db6ce57, 0x76c53d08d6b70859 },
|
|
590
|
-
{ 0xa2cb1717b52481ed, 0x54768c4b0c64ca6f },
|
|
591
|
-
{ 0xcb7ddcdda26da268, 0xa9942f5dcf7dfd0a },
|
|
592
|
-
{ 0xfe5d54150b090b02, 0xd3f93b35435d7c4d },
|
|
593
|
-
{ 0x9efa548d26e5a6e1, 0xc47bc5014a1a6db0 },
|
|
594
|
-
{ 0xc6b8e9b0709f109a, 0x359ab6419ca1091c },
|
|
595
|
-
{ 0xf867241c8cc6d4c0, 0xc30163d203c94b63 },
|
|
596
|
-
{ 0x9b407691d7fc44f8, 0x79e0de63425dcf1e },
|
|
597
|
-
{ 0xc21094364dfb5636, 0x985915fc12f542e5 },
|
|
598
|
-
{ 0xf294b943e17a2bc4, 0x3e6f5b7b17b2939e },
|
|
599
|
-
{ 0x979cf3ca6cec5b5a, 0xa705992ceecf9c43 },
|
|
600
|
-
{ 0xbd8430bd08277231, 0x50c6ff782a838354 },
|
|
601
|
-
{ 0xece53cec4a314ebd, 0xa4f8bf5635246429 },
|
|
602
|
-
{ 0x940f4613ae5ed136, 0x871b7795e136be9a },
|
|
603
|
-
{ 0xb913179899f68584, 0x28e2557b59846e40 },
|
|
604
|
-
{ 0xe757dd7ec07426e5, 0x331aeada2fe589d0 },
|
|
605
|
-
{ 0x9096ea6f3848984f, 0x3ff0d2c85def7622 },
|
|
606
|
-
{ 0xb4bca50b065abe63, 0x0fed077a756b53aa },
|
|
607
|
-
{ 0xe1ebce4dc7f16dfb, 0xd3e8495912c62895 },
|
|
608
|
-
{ 0x8d3360f09cf6e4bd, 0x64712dd7abbbd95d },
|
|
609
|
-
{ 0xb080392cc4349dec, 0xbd8d794d96aacfb4 },
|
|
610
|
-
{ 0xdca04777f541c567, 0xecf0d7a0fc5583a1 },
|
|
611
|
-
{ 0x89e42caaf9491b60, 0xf41686c49db57245 },
|
|
612
|
-
{ 0xac5d37d5b79b6239, 0x311c2875c522ced6 },
|
|
613
|
-
{ 0xd77485cb25823ac7, 0x7d633293366b828c },
|
|
614
|
-
{ 0x86a8d39ef77164bc, 0xae5dff9c02033198 },
|
|
615
|
-
{ 0xa8530886b54dbdeb, 0xd9f57f830283fdfd },
|
|
616
|
-
{ 0xd267caa862a12d66, 0xd072df63c324fd7c },
|
|
617
|
-
{ 0x8380dea93da4bc60, 0x4247cb9e59f71e6e },
|
|
618
|
-
{ 0xa46116538d0deb78, 0x52d9be85f074e609 },
|
|
619
|
-
{ 0xcd795be870516656, 0x67902e276c921f8c },
|
|
620
|
-
{ 0x806bd9714632dff6, 0x00ba1cd8a3db53b7 },
|
|
621
|
-
{ 0xa086cfcd97bf97f3, 0x80e8a40eccd228a5 },
|
|
622
|
-
{ 0xc8a883c0fdaf7df0, 0x6122cd128006b2ce },
|
|
623
|
-
{ 0xfad2a4b13d1b5d6c, 0x796b805720085f82 },
|
|
624
|
-
{ 0x9cc3a6eec6311a63, 0xcbe3303674053bb1 },
|
|
625
|
-
{ 0xc3f490aa77bd60fc, 0xbedbfc4411068a9d },
|
|
626
|
-
{ 0xf4f1b4d515acb93b, 0xee92fb5515482d45 },
|
|
627
|
-
{ 0x991711052d8bf3c5, 0x751bdd152d4d1c4b },
|
|
628
|
-
{ 0xbf5cd54678eef0b6, 0xd262d45a78a0635e },
|
|
629
|
-
{ 0xef340a98172aace4, 0x86fb897116c87c35 },
|
|
630
|
-
{ 0x9580869f0e7aac0e, 0xd45d35e6ae3d4da1 },
|
|
631
|
-
{ 0xbae0a846d2195712, 0x8974836059cca10a },
|
|
632
|
-
{ 0xe998d258869facd7, 0x2bd1a438703fc94c },
|
|
633
|
-
{ 0x91ff83775423cc06, 0x7b6306a34627ddd0 },
|
|
634
|
-
{ 0xb67f6455292cbf08, 0x1a3bc84c17b1d543 },
|
|
635
|
-
{ 0xe41f3d6a7377eeca, 0x20caba5f1d9e4a94 },
|
|
636
|
-
{ 0x8e938662882af53e, 0x547eb47b7282ee9d },
|
|
637
|
-
{ 0xb23867fb2a35b28d, 0xe99e619a4f23aa44 },
|
|
638
|
-
{ 0xdec681f9f4c31f31, 0x6405fa00e2ec94d5 },
|
|
639
|
-
{ 0x8b3c113c38f9f37e, 0xde83bc408dd3dd05 },
|
|
640
|
-
{ 0xae0b158b4738705e, 0x9624ab50b148d446 },
|
|
641
|
-
{ 0xd98ddaee19068c76, 0x3badd624dd9b0958 },
|
|
642
|
-
{ 0x87f8a8d4cfa417c9, 0xe54ca5d70a80e5d7 },
|
|
643
|
-
{ 0xa9f6d30a038d1dbc, 0x5e9fcf4ccd211f4d },
|
|
644
|
-
{ 0xd47487cc8470652b, 0x7647c32000696720 },
|
|
645
|
-
{ 0x84c8d4dfd2c63f3b, 0x29ecd9f40041e074 },
|
|
646
|
-
{ 0xa5fb0a17c777cf09, 0xf468107100525891 },
|
|
647
|
-
{ 0xcf79cc9db955c2cc, 0x7182148d4066eeb5 },
|
|
648
|
-
{ 0x81ac1fe293d599bf, 0xc6f14cd848405531 },
|
|
649
|
-
{ 0xa21727db38cb002f, 0xb8ada00e5a506a7d },
|
|
650
|
-
{ 0xca9cf1d206fdc03b, 0xa6d90811f0e4851d },
|
|
651
|
-
{ 0xfd442e4688bd304a, 0x908f4a166d1da664 },
|
|
652
|
-
{ 0x9e4a9cec15763e2e, 0x9a598e4e043287ff },
|
|
653
|
-
{ 0xc5dd44271ad3cdba, 0x40eff1e1853f29fe },
|
|
654
|
-
{ 0xf7549530e188c128, 0xd12bee59e68ef47d },
|
|
655
|
-
{ 0x9a94dd3e8cf578b9, 0x82bb74f8301958cf },
|
|
656
|
-
{ 0xc13a148e3032d6e7, 0xe36a52363c1faf02 },
|
|
657
|
-
{ 0xf18899b1bc3f8ca1, 0xdc44e6c3cb279ac2 },
|
|
658
|
-
{ 0x96f5600f15a7b7e5, 0x29ab103a5ef8c0ba },
|
|
659
|
-
{ 0xbcb2b812db11a5de, 0x7415d448f6b6f0e8 },
|
|
660
|
-
{ 0xebdf661791d60f56, 0x111b495b3464ad22 },
|
|
661
|
-
{ 0x936b9fcebb25c995, 0xcab10dd900beec35 },
|
|
662
|
-
{ 0xb84687c269ef3bfb, 0x3d5d514f40eea743 },
|
|
663
|
-
{ 0xe65829b3046b0afa, 0x0cb4a5a3112a5113 },
|
|
664
|
-
{ 0x8ff71a0fe2c2e6dc, 0x47f0e785eaba72ac },
|
|
665
|
-
{ 0xb3f4e093db73a093, 0x59ed216765690f57 },
|
|
666
|
-
{ 0xe0f218b8d25088b8, 0x306869c13ec3532d },
|
|
667
|
-
{ 0x8c974f7383725573, 0x1e414218c73a13fc },
|
|
668
|
-
{ 0xafbd2350644eeacf, 0xe5d1929ef90898fb },
|
|
669
|
-
{ 0xdbac6c247d62a583, 0xdf45f746b74abf3a },
|
|
670
|
-
{ 0x894bc396ce5da772, 0x6b8bba8c328eb784 },
|
|
671
|
-
{ 0xab9eb47c81f5114f, 0x066ea92f3f326565 },
|
|
672
|
-
{ 0xd686619ba27255a2, 0xc80a537b0efefebe },
|
|
673
|
-
{ 0x8613fd0145877585, 0xbd06742ce95f5f37 },
|
|
674
|
-
{ 0xa798fc4196e952e7, 0x2c48113823b73705 },
|
|
675
|
-
{ 0xd17f3b51fca3a7a0, 0xf75a15862ca504c6 },
|
|
676
|
-
{ 0x82ef85133de648c4, 0x9a984d73dbe722fc },
|
|
677
|
-
{ 0xa3ab66580d5fdaf5, 0xc13e60d0d2e0ebbb },
|
|
678
|
-
{ 0xcc963fee10b7d1b3, 0x318df905079926a9 },
|
|
679
|
-
{ 0xffbbcfe994e5c61f, 0xfdf17746497f7053 },
|
|
680
|
-
{ 0x9fd561f1fd0f9bd3, 0xfeb6ea8bedefa634 },
|
|
681
|
-
{ 0xc7caba6e7c5382c8, 0xfe64a52ee96b8fc1 },
|
|
682
|
-
{ 0xf9bd690a1b68637b, 0x3dfdce7aa3c673b1 },
|
|
683
|
-
{ 0x9c1661a651213e2d, 0x06bea10ca65c084f },
|
|
684
|
-
{ 0xc31bfa0fe5698db8, 0x486e494fcff30a63 },
|
|
685
|
-
{ 0xf3e2f893dec3f126, 0x5a89dba3c3efccfb },
|
|
686
|
-
{ 0x986ddb5c6b3a76b7, 0xf89629465a75e01d },
|
|
687
|
-
{ 0xbe89523386091465, 0xf6bbb397f1135824 },
|
|
688
|
-
{ 0xee2ba6c0678b597f, 0x746aa07ded582e2d },
|
|
689
|
-
{ 0x94db483840b717ef, 0xa8c2a44eb4571cdd },
|
|
690
|
-
{ 0xba121a4650e4ddeb, 0x92f34d62616ce414 },
|
|
691
|
-
{ 0xe896a0d7e51e1566, 0x77b020baf9c81d18 },
|
|
692
|
-
{ 0x915e2486ef32cd60, 0x0ace1474dc1d122f },
|
|
693
|
-
{ 0xb5b5ada8aaff80b8, 0x0d819992132456bb },
|
|
694
|
-
{ 0xe3231912d5bf60e6, 0x10e1fff697ed6c6a },
|
|
695
|
-
{ 0x8df5efabc5979c8f, 0xca8d3ffa1ef463c2 },
|
|
696
|
-
{ 0xb1736b96b6fd83b3, 0xbd308ff8a6b17cb3 },
|
|
697
|
-
{ 0xddd0467c64bce4a0, 0xac7cb3f6d05ddbdf },
|
|
698
|
-
{ 0x8aa22c0dbef60ee4, 0x6bcdf07a423aa96c },
|
|
699
|
-
{ 0xad4ab7112eb3929d, 0x86c16c98d2c953c7 },
|
|
700
|
-
{ 0xd89d64d57a607744, 0xe871c7bf077ba8b8 },
|
|
701
|
-
{ 0x87625f056c7c4a8b, 0x11471cd764ad4973 },
|
|
702
|
-
{ 0xa93af6c6c79b5d2d, 0xd598e40d3dd89bd0 },
|
|
703
|
-
{ 0xd389b47879823479, 0x4aff1d108d4ec2c4 },
|
|
704
|
-
{ 0x843610cb4bf160cb, 0xcedf722a585139bb },
|
|
705
|
-
{ 0xa54394fe1eedb8fe, 0xc2974eb4ee658829 },
|
|
706
|
-
{ 0xce947a3da6a9273e, 0x733d226229feea33 },
|
|
707
|
-
{ 0x811ccc668829b887, 0x0806357d5a3f5260 },
|
|
708
|
-
{ 0xa163ff802a3426a8, 0xca07c2dcb0cf26f8 },
|
|
709
|
-
{ 0xc9bcff6034c13052, 0xfc89b393dd02f0b6 },
|
|
710
|
-
{ 0xfc2c3f3841f17c67, 0xbbac2078d443ace3 },
|
|
711
|
-
{ 0x9d9ba7832936edc0, 0xd54b944b84aa4c0e },
|
|
712
|
-
{ 0xc5029163f384a931, 0x0a9e795e65d4df12 },
|
|
713
|
-
{ 0xf64335bcf065d37d, 0x4d4617b5ff4a16d6 },
|
|
714
|
-
{ 0x99ea0196163fa42e, 0x504bced1bf8e4e46 },
|
|
715
|
-
{ 0xc06481fb9bcf8d39, 0xe45ec2862f71e1d7 },
|
|
716
|
-
{ 0xf07da27a82c37088, 0x5d767327bb4e5a4d },
|
|
717
|
-
{ 0x964e858c91ba2655, 0x3a6a07f8d510f870 },
|
|
718
|
-
{ 0xbbe226efb628afea, 0x890489f70a55368c },
|
|
719
|
-
{ 0xeadab0aba3b2dbe5, 0x2b45ac74ccea842f },
|
|
720
|
-
{ 0x92c8ae6b464fc96f, 0x3b0b8bc90012929e },
|
|
721
|
-
{ 0xb77ada0617e3bbcb, 0x09ce6ebb40173745 },
|
|
722
|
-
{ 0xe55990879ddcaabd, 0xcc420a6a101d0516 },
|
|
723
|
-
{ 0x8f57fa54c2a9eab6, 0x9fa946824a12232e },
|
|
724
|
-
{ 0xb32df8e9f3546564, 0x47939822dc96abfa },
|
|
725
|
-
{ 0xdff9772470297ebd, 0x59787e2b93bc56f8 },
|
|
726
|
-
{ 0x8bfbea76c619ef36, 0x57eb4edb3c55b65b },
|
|
727
|
-
{ 0xaefae51477a06b03, 0xede622920b6b23f2 },
|
|
728
|
-
{ 0xdab99e59958885c4, 0xe95fab368e45ecee },
|
|
729
|
-
{ 0x88b402f7fd75539b, 0x11dbcb0218ebb415 },
|
|
730
|
-
{ 0xaae103b5fcd2a881, 0xd652bdc29f26a11a },
|
|
731
|
-
{ 0xd59944a37c0752a2, 0x4be76d3346f04960 },
|
|
732
|
-
{ 0x857fcae62d8493a5, 0x6f70a4400c562ddc },
|
|
733
|
-
{ 0xa6dfbd9fb8e5b88e, 0xcb4ccd500f6bb953 },
|
|
734
|
-
{ 0xd097ad07a71f26b2, 0x7e2000a41346a7a8 },
|
|
735
|
-
{ 0x825ecc24c873782f, 0x8ed400668c0c28c9 },
|
|
736
|
-
{ 0xa2f67f2dfa90563b, 0x728900802f0f32fb },
|
|
737
|
-
{ 0xcbb41ef979346bca, 0x4f2b40a03ad2ffba },
|
|
738
|
-
{ 0xfea126b7d78186bc, 0xe2f610c84987bfa9 },
|
|
739
|
-
{ 0x9f24b832e6b0f436, 0x0dd9ca7d2df4d7ca },
|
|
740
|
-
{ 0xc6ede63fa05d3143, 0x91503d1c79720dbc },
|
|
741
|
-
{ 0xf8a95fcf88747d94, 0x75a44c6397ce912b },
|
|
742
|
-
{ 0x9b69dbe1b548ce7c, 0xc986afbe3ee11abb },
|
|
743
|
-
{ 0xc24452da229b021b, 0xfbe85badce996169 },
|
|
744
|
-
{ 0xf2d56790ab41c2a2, 0xfae27299423fb9c4 },
|
|
745
|
-
{ 0x97c560ba6b0919a5, 0xdccd879fc967d41b },
|
|
746
|
-
{ 0xbdb6b8e905cb600f, 0x5400e987bbc1c921 },
|
|
747
|
-
{ 0xed246723473e3813, 0x290123e9aab23b69 },
|
|
748
|
-
{ 0x9436c0760c86e30b, 0xf9a0b6720aaf6522 },
|
|
749
|
-
{ 0xb94470938fa89bce, 0xf808e40e8d5b3e6a },
|
|
750
|
-
{ 0xe7958cb87392c2c2, 0xb60b1d1230b20e05 },
|
|
751
|
-
{ 0x90bd77f3483bb9b9, 0xb1c6f22b5e6f48c3 },
|
|
752
|
-
{ 0xb4ecd5f01a4aa828, 0x1e38aeb6360b1af4 },
|
|
753
|
-
{ 0xe2280b6c20dd5232, 0x25c6da63c38de1b1 },
|
|
754
|
-
{ 0x8d590723948a535f, 0x579c487e5a38ad0f },
|
|
755
|
-
{ 0xb0af48ec79ace837, 0x2d835a9df0c6d852 },
|
|
756
|
-
{ 0xdcdb1b2798182244, 0xf8e431456cf88e66 },
|
|
757
|
-
{ 0x8a08f0f8bf0f156b, 0x1b8e9ecb641b5900 },
|
|
758
|
-
{ 0xac8b2d36eed2dac5, 0xe272467e3d222f40 },
|
|
759
|
-
{ 0xd7adf884aa879177, 0x5b0ed81dcc6abb10 },
|
|
760
|
-
{ 0x86ccbb52ea94baea, 0x98e947129fc2b4ea },
|
|
761
|
-
{ 0xa87fea27a539e9a5, 0x3f2398d747b36225 },
|
|
762
|
-
{ 0xd29fe4b18e88640e, 0x8eec7f0d19a03aae },
|
|
763
|
-
{ 0x83a3eeeef9153e89, 0x1953cf68300424ad },
|
|
764
|
-
{ 0xa48ceaaab75a8e2b, 0x5fa8c3423c052dd8 },
|
|
765
|
-
{ 0xcdb02555653131b6, 0x3792f412cb06794e },
|
|
766
|
-
{ 0x808e17555f3ebf11, 0xe2bbd88bbee40bd1 },
|
|
767
|
-
{ 0xa0b19d2ab70e6ed6, 0x5b6aceaeae9d0ec5 },
|
|
768
|
-
{ 0xc8de047564d20a8b, 0xf245825a5a445276 },
|
|
769
|
-
{ 0xfb158592be068d2e, 0xeed6e2f0f0d56713 },
|
|
770
|
-
{ 0x9ced737bb6c4183d, 0x55464dd69685606c },
|
|
771
|
-
{ 0xc428d05aa4751e4c, 0xaa97e14c3c26b887 },
|
|
772
|
-
{ 0xf53304714d9265df, 0xd53dd99f4b3066a9 },
|
|
773
|
-
{ 0x993fe2c6d07b7fab, 0xe546a8038efe402a },
|
|
774
|
-
{ 0xbf8fdb78849a5f96, 0xde98520472bdd034 },
|
|
775
|
-
{ 0xef73d256a5c0f77c, 0x963e66858f6d4441 },
|
|
776
|
-
{ 0x95a8637627989aad, 0xdde7001379a44aa9 },
|
|
777
|
-
{ 0xbb127c53b17ec159, 0x5560c018580d5d53 },
|
|
778
|
-
{ 0xe9d71b689dde71af, 0xaab8f01e6e10b4a7 },
|
|
779
|
-
{ 0x9226712162ab070d, 0xcab3961304ca70e9 },
|
|
780
|
-
{ 0xb6b00d69bb55c8d1, 0x3d607b97c5fd0d23 },
|
|
781
|
-
{ 0xe45c10c42a2b3b05, 0x8cb89a7db77c506b },
|
|
782
|
-
{ 0x8eb98a7a9a5b04e3, 0x77f3608e92adb243 },
|
|
783
|
-
{ 0xb267ed1940f1c61c, 0x55f038b237591ed4 },
|
|
784
|
-
{ 0xdf01e85f912e37a3, 0x6b6c46dec52f6689 },
|
|
785
|
-
{ 0x8b61313bbabce2c6, 0x2323ac4b3b3da016 },
|
|
786
|
-
{ 0xae397d8aa96c1b77, 0xabec975e0a0d081b },
|
|
787
|
-
{ 0xd9c7dced53c72255, 0x96e7bd358c904a22 },
|
|
788
|
-
{ 0x881cea14545c7575, 0x7e50d64177da2e55 },
|
|
789
|
-
{ 0xaa242499697392d2, 0xdde50bd1d5d0b9ea },
|
|
790
|
-
{ 0xd4ad2dbfc3d07787, 0x955e4ec64b44e865 },
|
|
791
|
-
{ 0x84ec3c97da624ab4, 0xbd5af13bef0b113f },
|
|
792
|
-
{ 0xa6274bbdd0fadd61, 0xecb1ad8aeacdd58f },
|
|
793
|
-
{ 0xcfb11ead453994ba, 0x67de18eda5814af3 },
|
|
794
|
-
{ 0x81ceb32c4b43fcf4, 0x80eacf948770ced8 },
|
|
795
|
-
{ 0xa2425ff75e14fc31, 0xa1258379a94d028e },
|
|
796
|
-
{ 0xcad2f7f5359a3b3e, 0x096ee45813a04331 },
|
|
797
|
-
{ 0xfd87b5f28300ca0d, 0x8bca9d6e188853fd },
|
|
798
|
-
{ 0x9e74d1b791e07e48, 0x775ea264cf55347e },
|
|
799
|
-
{ 0xc612062576589dda, 0x95364afe032a819e },
|
|
800
|
-
{ 0xf79687aed3eec551, 0x3a83ddbd83f52205 },
|
|
801
|
-
{ 0x9abe14cd44753b52, 0xc4926a9672793543 },
|
|
802
|
-
{ 0xc16d9a0095928a27, 0x75b7053c0f178294 },
|
|
803
|
-
{ 0xf1c90080baf72cb1, 0x5324c68b12dd6339 },
|
|
804
|
-
{ 0x971da05074da7bee, 0xd3f6fc16ebca5e04 },
|
|
805
|
-
{ 0xbce5086492111aea, 0x88f4bb1ca6bcf585 },
|
|
806
|
-
{ 0xec1e4a7db69561a5, 0x2b31e9e3d06c32e6 },
|
|
807
|
-
{ 0x9392ee8e921d5d07, 0x3aff322e62439fd0 },
|
|
808
|
-
{ 0xb877aa3236a4b449, 0x09befeb9fad487c3 },
|
|
809
|
-
{ 0xe69594bec44de15b, 0x4c2ebe687989a9b4 },
|
|
810
|
-
{ 0x901d7cf73ab0acd9, 0x0f9d37014bf60a11 },
|
|
811
|
-
{ 0xb424dc35095cd80f, 0x538484c19ef38c95 },
|
|
812
|
-
{ 0xe12e13424bb40e13, 0x2865a5f206b06fba },
|
|
813
|
-
{ 0x8cbccc096f5088cb, 0xf93f87b7442e45d4 },
|
|
814
|
-
{ 0xafebff0bcb24aafe, 0xf78f69a51539d749 },
|
|
815
|
-
{ 0xdbe6fecebdedd5be, 0xb573440e5a884d1c },
|
|
816
|
-
{ 0x89705f4136b4a597, 0x31680a88f8953031 },
|
|
817
|
-
{ 0xabcc77118461cefc, 0xfdc20d2b36ba7c3e },
|
|
818
|
-
{ 0xd6bf94d5e57a42bc, 0x3d32907604691b4d },
|
|
819
|
-
{ 0x8637bd05af6c69b5, 0xa63f9a49c2c1b110 },
|
|
820
|
-
{ 0xa7c5ac471b478423, 0x0fcf80dc33721d54 },
|
|
821
|
-
{ 0xd1b71758e219652b, 0xd3c36113404ea4a9 },
|
|
822
|
-
{ 0x83126e978d4fdf3b, 0x645a1cac083126ea },
|
|
823
|
-
{ 0xa3d70a3d70a3d70a, 0x3d70a3d70a3d70a4 },
|
|
824
|
-
{ 0xcccccccccccccccc, 0xcccccccccccccccd },
|
|
825
|
-
{ 0x8000000000000000, 0x0000000000000000 },
|
|
826
|
-
{ 0xa000000000000000, 0x0000000000000000 },
|
|
827
|
-
{ 0xc800000000000000, 0x0000000000000000 },
|
|
828
|
-
{ 0xfa00000000000000, 0x0000000000000000 },
|
|
829
|
-
{ 0x9c40000000000000, 0x0000000000000000 },
|
|
830
|
-
{ 0xc350000000000000, 0x0000000000000000 },
|
|
831
|
-
{ 0xf424000000000000, 0x0000000000000000 },
|
|
832
|
-
{ 0x9896800000000000, 0x0000000000000000 },
|
|
833
|
-
{ 0xbebc200000000000, 0x0000000000000000 },
|
|
834
|
-
{ 0xee6b280000000000, 0x0000000000000000 },
|
|
835
|
-
{ 0x9502f90000000000, 0x0000000000000000 },
|
|
836
|
-
{ 0xba43b74000000000, 0x0000000000000000 },
|
|
837
|
-
{ 0xe8d4a51000000000, 0x0000000000000000 },
|
|
838
|
-
{ 0x9184e72a00000000, 0x0000000000000000 },
|
|
839
|
-
{ 0xb5e620f480000000, 0x0000000000000000 },
|
|
840
|
-
{ 0xe35fa931a0000000, 0x0000000000000000 },
|
|
841
|
-
{ 0x8e1bc9bf04000000, 0x0000000000000000 },
|
|
842
|
-
{ 0xb1a2bc2ec5000000, 0x0000000000000000 },
|
|
843
|
-
{ 0xde0b6b3a76400000, 0x0000000000000000 },
|
|
844
|
-
{ 0x8ac7230489e80000, 0x0000000000000000 },
|
|
845
|
-
{ 0xad78ebc5ac620000, 0x0000000000000000 },
|
|
846
|
-
{ 0xd8d726b7177a8000, 0x0000000000000000 },
|
|
847
|
-
{ 0x878678326eac9000, 0x0000000000000000 },
|
|
848
|
-
{ 0xa968163f0a57b400, 0x0000000000000000 },
|
|
849
|
-
{ 0xd3c21bcecceda100, 0x0000000000000000 },
|
|
850
|
-
{ 0x84595161401484a0, 0x0000000000000000 },
|
|
851
|
-
{ 0xa56fa5b99019a5c8, 0x0000000000000000 },
|
|
852
|
-
{ 0xcecb8f27f4200f3a, 0x0000000000000000 },
|
|
853
|
-
{ 0x813f3978f8940984, 0x4000000000000000 },
|
|
854
|
-
{ 0xa18f07d736b90be5, 0x5000000000000000 },
|
|
855
|
-
{ 0xc9f2c9cd04674ede, 0xa400000000000000 },
|
|
856
|
-
{ 0xfc6f7c4045812296, 0x4d00000000000000 },
|
|
857
|
-
{ 0x9dc5ada82b70b59d, 0xf020000000000000 },
|
|
858
|
-
{ 0xc5371912364ce305, 0x6c28000000000000 },
|
|
859
|
-
{ 0xf684df56c3e01bc6, 0xc732000000000000 },
|
|
860
|
-
{ 0x9a130b963a6c115c, 0x3c7f400000000000 },
|
|
861
|
-
{ 0xc097ce7bc90715b3, 0x4b9f100000000000 },
|
|
862
|
-
{ 0xf0bdc21abb48db20, 0x1e86d40000000000 },
|
|
863
|
-
{ 0x96769950b50d88f4, 0x1314448000000000 },
|
|
864
|
-
{ 0xbc143fa4e250eb31, 0x17d955a000000000 },
|
|
865
|
-
{ 0xeb194f8e1ae525fd, 0x5dcfab0800000000 },
|
|
866
|
-
{ 0x92efd1b8d0cf37be, 0x5aa1cae500000000 },
|
|
867
|
-
{ 0xb7abc627050305ad, 0xf14a3d9e40000000 },
|
|
868
|
-
{ 0xe596b7b0c643c719, 0x6d9ccd05d0000000 },
|
|
869
|
-
{ 0x8f7e32ce7bea5c6f, 0xe4820023a2000000 },
|
|
870
|
-
{ 0xb35dbf821ae4f38b, 0xdda2802c8a800000 },
|
|
871
|
-
{ 0xe0352f62a19e306e, 0xd50b2037ad200000 },
|
|
872
|
-
{ 0x8c213d9da502de45, 0x4526f422cc340000 },
|
|
873
|
-
{ 0xaf298d050e4395d6, 0x9670b12b7f410000 },
|
|
874
|
-
{ 0xdaf3f04651d47b4c, 0x3c0cdd765f114000 },
|
|
875
|
-
{ 0x88d8762bf324cd0f, 0xa5880a69fb6ac800 },
|
|
876
|
-
{ 0xab0e93b6efee0053, 0x8eea0d047a457a00 },
|
|
877
|
-
{ 0xd5d238a4abe98068, 0x72a4904598d6d880 },
|
|
878
|
-
{ 0x85a36366eb71f041, 0x47a6da2b7f864750 },
|
|
879
|
-
{ 0xa70c3c40a64e6c51, 0x999090b65f67d924 },
|
|
880
|
-
{ 0xd0cf4b50cfe20765, 0xfff4b4e3f741cf6d },
|
|
881
|
-
{ 0x82818f1281ed449f, 0xbff8f10e7a8921a4 },
|
|
882
|
-
{ 0xa321f2d7226895c7, 0xaff72d52192b6a0d },
|
|
883
|
-
{ 0xcbea6f8ceb02bb39, 0x9bf4f8a69f764490 },
|
|
884
|
-
{ 0xfee50b7025c36a08, 0x02f236d04753d5b4 },
|
|
885
|
-
{ 0x9f4f2726179a2245, 0x01d762422c946590 },
|
|
886
|
-
{ 0xc722f0ef9d80aad6, 0x424d3ad2b7b97ef5 },
|
|
887
|
-
{ 0xf8ebad2b84e0d58b, 0xd2e0898765a7deb2 },
|
|
888
|
-
{ 0x9b934c3b330c8577, 0x63cc55f49f88eb2f },
|
|
889
|
-
{ 0xc2781f49ffcfa6d5, 0x3cbf6b71c76b25fb },
|
|
890
|
-
{ 0xf316271c7fc3908a, 0x8bef464e3945ef7a },
|
|
891
|
-
{ 0x97edd871cfda3a56, 0x97758bf0e3cbb5ac },
|
|
892
|
-
{ 0xbde94e8e43d0c8ec, 0x3d52eeed1cbea317 },
|
|
893
|
-
{ 0xed63a231d4c4fb27, 0x4ca7aaa863ee4bdd },
|
|
894
|
-
{ 0x945e455f24fb1cf8, 0x8fe8caa93e74ef6a },
|
|
895
|
-
{ 0xb975d6b6ee39e436, 0xb3e2fd538e122b44 },
|
|
896
|
-
{ 0xe7d34c64a9c85d44, 0x60dbbca87196b616 },
|
|
897
|
-
{ 0x90e40fbeea1d3a4a, 0xbc8955e946fe31cd },
|
|
898
|
-
{ 0xb51d13aea4a488dd, 0x6babab6398bdbe41 },
|
|
899
|
-
{ 0xe264589a4dcdab14, 0xc696963c7eed2dd1 },
|
|
900
|
-
{ 0x8d7eb76070a08aec, 0xfc1e1de5cf543ca2 },
|
|
901
|
-
{ 0xb0de65388cc8ada8, 0x3b25a55f43294bcb },
|
|
902
|
-
{ 0xdd15fe86affad912, 0x49ef0eb713f39ebe },
|
|
903
|
-
{ 0x8a2dbf142dfcc7ab, 0x6e3569326c784337 },
|
|
904
|
-
{ 0xacb92ed9397bf996, 0x49c2c37f07965404 },
|
|
905
|
-
{ 0xd7e77a8f87daf7fb, 0xdc33745ec97be906 },
|
|
906
|
-
{ 0x86f0ac99b4e8dafd, 0x69a028bb3ded71a3 },
|
|
907
|
-
{ 0xa8acd7c0222311bc, 0xc40832ea0d68ce0c },
|
|
908
|
-
{ 0xd2d80db02aabd62b, 0xf50a3fa490c30190 },
|
|
909
|
-
{ 0x83c7088e1aab65db, 0x792667c6da79e0fa },
|
|
910
|
-
{ 0xa4b8cab1a1563f52, 0x577001b891185938 },
|
|
911
|
-
{ 0xcde6fd5e09abcf26, 0xed4c0226b55e6f86 },
|
|
912
|
-
{ 0x80b05e5ac60b6178, 0x544f8158315b05b4 },
|
|
913
|
-
{ 0xa0dc75f1778e39d6, 0x696361ae3db1c721 },
|
|
914
|
-
{ 0xc913936dd571c84c, 0x03bc3a19cd1e38e9 },
|
|
915
|
-
{ 0xfb5878494ace3a5f, 0x04ab48a04065c723 },
|
|
916
|
-
{ 0x9d174b2dcec0e47b, 0x62eb0d64283f9c76 },
|
|
917
|
-
{ 0xc45d1df942711d9a, 0x3ba5d0bd324f8394 },
|
|
918
|
-
{ 0xf5746577930d6500, 0xca8f44ec7ee36479 },
|
|
919
|
-
{ 0x9968bf6abbe85f20, 0x7e998b13cf4e1ecb },
|
|
920
|
-
{ 0xbfc2ef456ae276e8, 0x9e3fedd8c321a67e },
|
|
921
|
-
{ 0xefb3ab16c59b14a2, 0xc5cfe94ef3ea101e },
|
|
922
|
-
{ 0x95d04aee3b80ece5, 0xbba1f1d158724a12 },
|
|
923
|
-
{ 0xbb445da9ca61281f, 0x2a8a6e45ae8edc97 },
|
|
924
|
-
{ 0xea1575143cf97226, 0xf52d09d71a3293bd },
|
|
925
|
-
{ 0x924d692ca61be758, 0x593c2626705f9c56 },
|
|
926
|
-
{ 0xb6e0c377cfa2e12e, 0x6f8b2fb00c77836c },
|
|
927
|
-
{ 0xe498f455c38b997a, 0x0b6dfb9c0f956447 },
|
|
928
|
-
{ 0x8edf98b59a373fec, 0x4724bd4189bd5eac },
|
|
929
|
-
{ 0xb2977ee300c50fe7, 0x58edec91ec2cb657 },
|
|
930
|
-
{ 0xdf3d5e9bc0f653e1, 0x2f2967b66737e3ed },
|
|
931
|
-
{ 0x8b865b215899f46c, 0xbd79e0d20082ee74 },
|
|
932
|
-
{ 0xae67f1e9aec07187, 0xecd8590680a3aa11 },
|
|
933
|
-
{ 0xda01ee641a708de9, 0xe80e6f4820cc9495 },
|
|
934
|
-
{ 0x884134fe908658b2, 0x3109058d147fdcdd },
|
|
935
|
-
{ 0xaa51823e34a7eede, 0xbd4b46f0599fd415 },
|
|
936
|
-
{ 0xd4e5e2cdc1d1ea96, 0x6c9e18ac7007c91a },
|
|
937
|
-
{ 0x850fadc09923329e, 0x03e2cf6bc604ddb0 },
|
|
938
|
-
{ 0xa6539930bf6bff45, 0x84db8346b786151c },
|
|
939
|
-
{ 0xcfe87f7cef46ff16, 0xe612641865679a63 },
|
|
940
|
-
{ 0x81f14fae158c5f6e, 0x4fcb7e8f3f60c07e },
|
|
941
|
-
{ 0xa26da3999aef7749, 0xe3be5e330f38f09d },
|
|
942
|
-
{ 0xcb090c8001ab551c, 0x5cadf5bfd3072cc5 },
|
|
943
|
-
{ 0xfdcb4fa002162a63, 0x73d9732fc7c8f7f6 },
|
|
944
|
-
{ 0x9e9f11c4014dda7e, 0x2867e7fddcdd9afa },
|
|
945
|
-
{ 0xc646d63501a1511d, 0xb281e1fd541501b8 },
|
|
946
|
-
{ 0xf7d88bc24209a565, 0x1f225a7ca91a4226 },
|
|
947
|
-
{ 0x9ae757596946075f, 0x3375788de9b06958 },
|
|
948
|
-
{ 0xc1a12d2fc3978937, 0x0052d6b1641c83ae },
|
|
949
|
-
{ 0xf209787bb47d6b84, 0xc0678c5dbd23a49a },
|
|
950
|
-
{ 0x9745eb4d50ce6332, 0xf840b7ba963646e0 },
|
|
951
|
-
{ 0xbd176620a501fbff, 0xb650e5a93bc3d898 },
|
|
952
|
-
{ 0xec5d3fa8ce427aff, 0xa3e51f138ab4cebe },
|
|
953
|
-
{ 0x93ba47c980e98cdf, 0xc66f336c36b10137 },
|
|
954
|
-
{ 0xb8a8d9bbe123f017, 0xb80b0047445d4184 },
|
|
955
|
-
{ 0xe6d3102ad96cec1d, 0xa60dc059157491e5 },
|
|
956
|
-
{ 0x9043ea1ac7e41392, 0x87c89837ad68db2f },
|
|
957
|
-
{ 0xb454e4a179dd1877, 0x29babe4598c311fb },
|
|
958
|
-
{ 0xe16a1dc9d8545e94, 0xf4296dd6fef3d67a },
|
|
959
|
-
{ 0x8ce2529e2734bb1d, 0x1899e4a65f58660c },
|
|
960
|
-
{ 0xb01ae745b101e9e4, 0x5ec05dcff72e7f8f },
|
|
961
|
-
{ 0xdc21a1171d42645d, 0x76707543f4fa1f73 },
|
|
962
|
-
{ 0x899504ae72497eba, 0x6a06494a791c53a8 },
|
|
963
|
-
{ 0xabfa45da0edbde69, 0x0487db9d17636892 },
|
|
964
|
-
{ 0xd6f8d7509292d603, 0x45a9d2845d3c42b6 },
|
|
965
|
-
{ 0x865b86925b9bc5c2, 0x0b8a2392ba45a9b2 },
|
|
966
|
-
{ 0xa7f26836f282b732, 0x8e6cac7768d7141e },
|
|
967
|
-
{ 0xd1ef0244af2364ff, 0x3207d795430cd926 },
|
|
968
|
-
{ 0x8335616aed761f1f, 0x7f44e6bd49e807b8 },
|
|
969
|
-
{ 0xa402b9c5a8d3a6e7, 0x5f16206c9c6209a6 },
|
|
970
|
-
{ 0xcd036837130890a1, 0x36dba887c37a8c0f },
|
|
971
|
-
{ 0x802221226be55a64, 0xc2494954da2c9789 },
|
|
972
|
-
{ 0xa02aa96b06deb0fd, 0xf2db9baa10b7bd6c },
|
|
973
|
-
{ 0xc83553c5c8965d3d, 0x6f92829494e5acc7 },
|
|
974
|
-
{ 0xfa42a8b73abbf48c, 0xcb772339ba1f17f9 },
|
|
975
|
-
{ 0x9c69a97284b578d7, 0xff2a760414536efb },
|
|
976
|
-
{ 0xc38413cf25e2d70d, 0xfef5138519684aba },
|
|
977
|
-
{ 0xf46518c2ef5b8cd1, 0x7eb258665fc25d69 },
|
|
978
|
-
{ 0x98bf2f79d5993802, 0xef2f773ffbd97a61 },
|
|
979
|
-
{ 0xbeeefb584aff8603, 0xaafb550ffacfd8fa },
|
|
980
|
-
{ 0xeeaaba2e5dbf6784, 0x95ba2a53f983cf38 },
|
|
981
|
-
{ 0x952ab45cfa97a0b2, 0xdd945a747bf26183 },
|
|
982
|
-
{ 0xba756174393d88df, 0x94f971119aeef9e4 },
|
|
983
|
-
{ 0xe912b9d1478ceb17, 0x7a37cd5601aab85d },
|
|
984
|
-
{ 0x91abb422ccb812ee, 0xac62e055c10ab33a },
|
|
985
|
-
{ 0xb616a12b7fe617aa, 0x577b986b314d6009 },
|
|
986
|
-
{ 0xe39c49765fdf9d94, 0xed5a7e85fda0b80b },
|
|
987
|
-
{ 0x8e41ade9fbebc27d, 0x14588f13be847307 },
|
|
988
|
-
{ 0xb1d219647ae6b31c, 0x596eb2d8ae258fc8 },
|
|
989
|
-
{ 0xde469fbd99a05fe3, 0x6fca5f8ed9aef3bb },
|
|
990
|
-
{ 0x8aec23d680043bee, 0x25de7bb9480d5854 },
|
|
991
|
-
{ 0xada72ccc20054ae9, 0xaf561aa79a10ae6a },
|
|
992
|
-
{ 0xd910f7ff28069da4, 0x1b2ba1518094da04 },
|
|
993
|
-
{ 0x87aa9aff79042286, 0x90fb44d2f05d0842 },
|
|
994
|
-
{ 0xa99541bf57452b28, 0x353a1607ac744a53 },
|
|
995
|
-
{ 0xd3fa922f2d1675f2, 0x42889b8997915ce8 },
|
|
996
|
-
{ 0x847c9b5d7c2e09b7, 0x69956135febada11 },
|
|
997
|
-
{ 0xa59bc234db398c25, 0x43fab9837e699095 },
|
|
998
|
-
{ 0xcf02b2c21207ef2e, 0x94f967e45e03f4bb },
|
|
999
|
-
{ 0x8161afb94b44f57d, 0x1d1be0eebac278f5 },
|
|
1000
|
-
{ 0xa1ba1ba79e1632dc, 0x6462d92a69731732 },
|
|
1001
|
-
{ 0xca28a291859bbf93, 0x7d7b8f7503cfdcfe },
|
|
1002
|
-
{ 0xfcb2cb35e702af78, 0x5cda735244c3d43e },
|
|
1003
|
-
{ 0x9defbf01b061adab, 0x3a0888136afa64a7 },
|
|
1004
|
-
{ 0xc56baec21c7a1916, 0x088aaa1845b8fdd0 },
|
|
1005
|
-
{ 0xf6c69a72a3989f5b, 0x8aad549e57273d45 },
|
|
1006
|
-
{ 0x9a3c2087a63f6399, 0x36ac54e2f678864b },
|
|
1007
|
-
{ 0xc0cb28a98fcf3c7f, 0x84576a1bb416a7dd },
|
|
1008
|
-
{ 0xf0fdf2d3f3c30b9f, 0x656d44a2a11c51d5 },
|
|
1009
|
-
{ 0x969eb7c47859e743, 0x9f644ae5a4b1b325 },
|
|
1010
|
-
{ 0xbc4665b596706114, 0x873d5d9f0dde1fee },
|
|
1011
|
-
{ 0xeb57ff22fc0c7959, 0xa90cb506d155a7ea },
|
|
1012
|
-
{ 0x9316ff75dd87cbd8, 0x09a7f12442d588f2 },
|
|
1013
|
-
{ 0xb7dcbf5354e9bece, 0x0c11ed6d538aeb2f },
|
|
1014
|
-
{ 0xe5d3ef282a242e81, 0x8f1668c8a86da5fa },
|
|
1015
|
-
{ 0x8fa475791a569d10, 0xf96e017d694487bc },
|
|
1016
|
-
{ 0xb38d92d760ec4455, 0x37c981dcc395a9ac },
|
|
1017
|
-
{ 0xe070f78d3927556a, 0x85bbe253f47b1417 },
|
|
1018
|
-
{ 0x8c469ab843b89562, 0x93956d7478ccec8e },
|
|
1019
|
-
{ 0xaf58416654a6babb, 0x387ac8d1970027b2 },
|
|
1020
|
-
{ 0xdb2e51bfe9d0696a, 0x06997b05fcc0319e },
|
|
1021
|
-
{ 0x88fcf317f22241e2, 0x441fece3bdf81f03 },
|
|
1022
|
-
{ 0xab3c2fddeeaad25a, 0xd527e81cad7626c3 },
|
|
1023
|
-
{ 0xd60b3bd56a5586f1, 0x8a71e223d8d3b074 },
|
|
1024
|
-
{ 0x85c7056562757456, 0xf6872d5667844e49 },
|
|
1025
|
-
{ 0xa738c6bebb12d16c, 0xb428f8ac016561db },
|
|
1026
|
-
{ 0xd106f86e69d785c7, 0xe13336d701beba52 },
|
|
1027
|
-
{ 0x82a45b450226b39c, 0xecc0024661173473 },
|
|
1028
|
-
{ 0xa34d721642b06084, 0x27f002d7f95d0190 },
|
|
1029
|
-
{ 0xcc20ce9bd35c78a5, 0x31ec038df7b441f4 },
|
|
1030
|
-
{ 0xff290242c83396ce, 0x7e67047175a15271 },
|
|
1031
|
-
{ 0x9f79a169bd203e41, 0x0f0062c6e984d386 },
|
|
1032
|
-
{ 0xc75809c42c684dd1, 0x52c07b78a3e60868 },
|
|
1033
|
-
{ 0xf92e0c3537826145, 0xa7709a56ccdf8a82 },
|
|
1034
|
-
{ 0x9bbcc7a142b17ccb, 0x88a66076400bb691 },
|
|
1035
|
-
{ 0xc2abf989935ddbfe, 0x6acff893d00ea435 },
|
|
1036
|
-
{ 0xf356f7ebf83552fe, 0x0583f6b8c4124d43 },
|
|
1037
|
-
{ 0x98165af37b2153de, 0xc3727a337a8b704a },
|
|
1038
|
-
{ 0xbe1bf1b059e9a8d6, 0x744f18c0592e4c5c },
|
|
1039
|
-
{ 0xeda2ee1c7064130c, 0x1162def06f79df73 },
|
|
1040
|
-
{ 0x9485d4d1c63e8be7, 0x8addcb5645ac2ba8 },
|
|
1041
|
-
{ 0xb9a74a0637ce2ee1, 0x6d953e2bd7173692 },
|
|
1042
|
-
{ 0xe8111c87c5c1ba99, 0xc8fa8db6ccdd0437 },
|
|
1043
|
-
{ 0x910ab1d4db9914a0, 0x1d9c9892400a22a2 },
|
|
1044
|
-
{ 0xb54d5e4a127f59c8, 0x2503beb6d00cab4b },
|
|
1045
|
-
{ 0xe2a0b5dc971f303a, 0x2e44ae64840fd61d },
|
|
1046
|
-
{ 0x8da471a9de737e24, 0x5ceaecfed289e5d2 },
|
|
1047
|
-
{ 0xb10d8e1456105dad, 0x7425a83e872c5f47 },
|
|
1048
|
-
{ 0xdd50f1996b947518, 0xd12f124e28f77719 },
|
|
1049
|
-
{ 0x8a5296ffe33cc92f, 0x82bd6b70d99aaa6f },
|
|
1050
|
-
{ 0xace73cbfdc0bfb7b, 0x636cc64d1001550b },
|
|
1051
|
-
{ 0xd8210befd30efa5a, 0x3c47f7e05401aa4e },
|
|
1052
|
-
{ 0x8714a775e3e95c78, 0x65acfaec34810a71 },
|
|
1053
|
-
{ 0xa8d9d1535ce3b396, 0x7f1839a741a14d0d },
|
|
1054
|
-
{ 0xd31045a8341ca07c, 0x1ede48111209a050 },
|
|
1055
|
-
{ 0x83ea2b892091e44d, 0x934aed0aab460432 },
|
|
1056
|
-
{ 0xa4e4b66b68b65d60, 0xf81da84d5617853f },
|
|
1057
|
-
{ 0xce1de40642e3f4b9, 0x36251260ab9d668e },
|
|
1058
|
-
{ 0x80d2ae83e9ce78f3, 0xc1d72b7c6b426019 },
|
|
1059
|
-
{ 0xa1075a24e4421730, 0xb24cf65b8612f81f },
|
|
1060
|
-
{ 0xc94930ae1d529cfc, 0xdee033f26797b627 },
|
|
1061
|
-
{ 0xfb9b7cd9a4a7443c, 0x169840ef017da3b1 },
|
|
1062
|
-
{ 0x9d412e0806e88aa5, 0x8e1f289560ee864e },
|
|
1063
|
-
{ 0xc491798a08a2ad4e, 0xf1a6f2bab92a27e2 },
|
|
1064
|
-
{ 0xf5b5d7ec8acb58a2, 0xae10af696774b1db },
|
|
1065
|
-
{ 0x9991a6f3d6bf1765, 0xacca6da1e0a8ef29 },
|
|
1066
|
-
{ 0xbff610b0cc6edd3f, 0x17fd090a58d32af3 },
|
|
1067
|
-
{ 0xeff394dcff8a948e, 0xddfc4b4cef07f5b0 },
|
|
1068
|
-
{ 0x95f83d0a1fb69cd9, 0x4abdaf101564f98e },
|
|
1069
|
-
{ 0xbb764c4ca7a4440f, 0x9d6d1ad41abe37f1 },
|
|
1070
|
-
{ 0xea53df5fd18d5513, 0x84c86189216dc5ed },
|
|
1071
|
-
{ 0x92746b9be2f8552c, 0x32fd3cf5b4e49bb4 },
|
|
1072
|
-
{ 0xb7118682dbb66a77, 0x3fbc8c33221dc2a1 },
|
|
1073
|
-
{ 0xe4d5e82392a40515, 0x0fabaf3feaa5334a },
|
|
1074
|
-
{ 0x8f05b1163ba6832d, 0x29cb4d87f2a7400e },
|
|
1075
|
-
{ 0xb2c71d5bca9023f8, 0x743e20e9ef511012 },
|
|
1076
|
-
{ 0xdf78e4b2bd342cf6, 0x914da9246b255416 },
|
|
1077
|
-
{ 0x8bab8eefb6409c1a, 0x1ad089b6c2f7548e },
|
|
1078
|
-
{ 0xae9672aba3d0c320, 0xa184ac2473b529b1 },
|
|
1079
|
-
{ 0xda3c0f568cc4f3e8, 0xc9e5d72d90a2741e },
|
|
1080
|
-
{ 0x8865899617fb1871, 0x7e2fa67c7a658892 },
|
|
1081
|
-
{ 0xaa7eebfb9df9de8d, 0xddbb901b98feeab7 },
|
|
1082
|
-
{ 0xd51ea6fa85785631, 0x552a74227f3ea565 },
|
|
1083
|
-
{ 0x8533285c936b35de, 0xd53a88958f87275f },
|
|
1084
|
-
{ 0xa67ff273b8460356, 0x8a892abaf368f137 },
|
|
1085
|
-
{ 0xd01fef10a657842c, 0x2d2b7569b0432d85 },
|
|
1086
|
-
{ 0x8213f56a67f6b29b, 0x9c3b29620e29fc73 },
|
|
1087
|
-
{ 0xa298f2c501f45f42, 0x8349f3ba91b47b8f },
|
|
1088
|
-
{ 0xcb3f2f7642717713, 0x241c70a936219a73 },
|
|
1089
|
-
{ 0xfe0efb53d30dd4d7, 0xed238cd383aa0110 },
|
|
1090
|
-
{ 0x9ec95d1463e8a506, 0xf4363804324a40aa },
|
|
1091
|
-
{ 0xc67bb4597ce2ce48, 0xb143c6053edcd0d5 },
|
|
1092
|
-
{ 0xf81aa16fdc1b81da, 0xdd94b7868e94050a },
|
|
1093
|
-
{ 0x9b10a4e5e9913128, 0xca7cf2b4191c8326 },
|
|
1094
|
-
{ 0xc1d4ce1f63f57d72, 0xfd1c2f611f63a3f0 },
|
|
1095
|
-
{ 0xf24a01a73cf2dccf, 0xbc633b39673c8cec },
|
|
1096
|
-
{ 0x976e41088617ca01, 0xd5be0503e085d813 },
|
|
1097
|
-
{ 0xbd49d14aa79dbc82, 0x4b2d8644d8a74e18 },
|
|
1098
|
-
{ 0xec9c459d51852ba2, 0xddf8e7d60ed1219e },
|
|
1099
|
-
{ 0x93e1ab8252f33b45, 0xcabb90e5c942b503 },
|
|
1100
|
-
{ 0xb8da1662e7b00a17, 0x3d6a751f3b936243 },
|
|
1101
|
-
{ 0xe7109bfba19c0c9d, 0x0cc512670a783ad4 },
|
|
1102
|
-
{ 0x906a617d450187e2, 0x27fb2b80668b24c5 },
|
|
1103
|
-
{ 0xb484f9dc9641e9da, 0xb1f9f660802dedf6 },
|
|
1104
|
-
{ 0xe1a63853bbd26451, 0x5e7873f8a0396973 },
|
|
1105
|
-
{ 0x8d07e33455637eb2, 0xdb0b487b6423e1e8 },
|
|
1106
|
-
{ 0xb049dc016abc5e5f, 0x91ce1a9a3d2cda62 },
|
|
1107
|
-
{ 0xdc5c5301c56b75f7, 0x7641a140cc7810fb },
|
|
1108
|
-
{ 0x89b9b3e11b6329ba, 0xa9e904c87fcb0a9d },
|
|
1109
|
-
{ 0xac2820d9623bf429, 0x546345fa9fbdcd44 },
|
|
1110
|
-
{ 0xd732290fbacaf133, 0xa97c177947ad4095 },
|
|
1111
|
-
{ 0x867f59a9d4bed6c0, 0x49ed8eabcccc485d },
|
|
1112
|
-
{ 0xa81f301449ee8c70, 0x5c68f256bfff5a74 },
|
|
1113
|
-
{ 0xd226fc195c6a2f8c, 0x73832eec6fff3111 },
|
|
1114
|
-
{ 0x83585d8fd9c25db7, 0xc831fd53c5ff7eab },
|
|
1115
|
-
{ 0xa42e74f3d032f525, 0xba3e7ca8b77f5e55 },
|
|
1116
|
-
{ 0xcd3a1230c43fb26f, 0x28ce1bd2e55f35eb },
|
|
1117
|
-
{ 0x80444b5e7aa7cf85, 0x7980d163cf5b81b3 },
|
|
1118
|
-
{ 0xa0555e361951c366, 0xd7e105bcc332621f },
|
|
1119
|
-
{ 0xc86ab5c39fa63440, 0x8dd9472bf3fefaa7 },
|
|
1120
|
-
{ 0xfa856334878fc150, 0xb14f98f6f0feb951 },
|
|
1121
|
-
{ 0x9c935e00d4b9d8d2, 0x6ed1bf9a569f33d3 },
|
|
1122
|
-
{ 0xc3b8358109e84f07, 0x0a862f80ec4700c8 },
|
|
1123
|
-
{ 0xf4a642e14c6262c8, 0xcd27bb612758c0fa },
|
|
1124
|
-
{ 0x98e7e9cccfbd7dbd, 0x8038d51cb897789c },
|
|
1125
|
-
{ 0xbf21e44003acdd2c, 0xe0470a63e6bd56c3 },
|
|
1126
|
-
{ 0xeeea5d5004981478, 0x1858ccfce06cac74 },
|
|
1127
|
-
{ 0x95527a5202df0ccb, 0x0f37801e0c43ebc8 },
|
|
1128
|
-
{ 0xbaa718e68396cffd, 0xd30560258f54e6ba },
|
|
1129
|
-
{ 0xe950df20247c83fd, 0x47c6b82ef32a2069 },
|
|
1130
|
-
{ 0x91d28b7416cdd27e, 0x4cdc331d57fa5441 },
|
|
1131
|
-
{ 0xb6472e511c81471d, 0xe0133fe4adf8e952 },
|
|
1132
|
-
{ 0xe3d8f9e563a198e5, 0x58180fddd97723a6 },
|
|
1133
|
-
{ 0x8e679c2f5e44ff8f, 0x570f09eaa7ea7648 },
|
|
1134
|
-
{ 0xb201833b35d63f73, 0x2cd2cc6551e513da },
|
|
1135
|
-
{ 0xde81e40a034bcf4f, 0xf8077f7ea65e58d1 },
|
|
1136
|
-
{ 0x8b112e86420f6191, 0xfb04afaf27faf782 },
|
|
1137
|
-
{ 0xadd57a27d29339f6, 0x79c5db9af1f9b563 },
|
|
1138
|
-
{ 0xd94ad8b1c7380874, 0x18375281ae7822bc },
|
|
1139
|
-
{ 0x87cec76f1c830548, 0x8f2293910d0b15b5 },
|
|
1140
|
-
{ 0xa9c2794ae3a3c69a, 0xb2eb3875504ddb22 },
|
|
1141
|
-
{ 0xd433179d9c8cb841, 0x5fa60692a46151eb },
|
|
1142
|
-
{ 0x849feec281d7f328, 0xdbc7c41ba6bcd333 },
|
|
1143
|
-
{ 0xa5c7ea73224deff3, 0x12b9b522906c0800 },
|
|
1144
|
-
{ 0xcf39e50feae16bef, 0xd768226b34870a00 },
|
|
1145
|
-
{ 0x81842f29f2cce375, 0xe6a1158300d46640 },
|
|
1146
|
-
{ 0xa1e53af46f801c53, 0x60495ae3c1097fd0 },
|
|
1147
|
-
{ 0xca5e89b18b602368, 0x385bb19cb14bdfc4 },
|
|
1148
|
-
{ 0xfcf62c1dee382c42, 0x46729e03dd9ed7b5 },
|
|
1149
|
-
{ 0x9e19db92b4e31ba9, 0x6c07a2c26a8346d1 },
|
|
1150
|
-
{ 0xc5a05277621be293, 0xc7098b7305241885 }
|
|
1151
|
-
};
|
|
1152
|
-
};
|
|
1153
|
-
|
|
1154
|
-
template <class Float>
|
|
1155
|
-
constexpr typename common_info<Float>::cache_entry_type const& get_cache(int k) noexcept {
|
|
1156
|
-
assert(k >= common_info<Float>::min_k && k <= common_info<Float>::max_k);
|
|
1157
|
-
return cache_holder<Float>::cache[std::size_t(k - common_info<Float>::min_k)];
|
|
1158
|
-
}
|
|
1159
|
-
|
|
1160
|
-
// Forward declaration of the main class
|
|
1161
|
-
template <class Float>
|
|
1162
|
-
struct grisu_exact_impl;
|
|
1163
|
-
}
|
|
1164
|
-
|
|
1165
|
-
////////////////////////////////////////////////////////////////////////////////////////
|
|
1166
|
-
// DIY floating-point data type
|
|
1167
|
-
////////////////////////////////////////////////////////////////////////////////////////
|
|
1168
|
-
|
|
1169
|
-
template <class Float, bool is_signed>
|
|
1170
|
-
struct fp_t;
|
|
1171
|
-
|
|
1172
|
-
template <class Float>
|
|
1173
|
-
struct fp_t<Float, false> {
|
|
1174
|
-
using extended_significand_type =
|
|
1175
|
-
typename grisu_exact_detail::common_info<Float>::extended_significand_type;
|
|
1176
|
-
|
|
1177
|
-
extended_significand_type significand;
|
|
1178
|
-
int exponent;
|
|
1179
|
-
};
|
|
1180
|
-
|
|
1181
|
-
template <class Float>
|
|
1182
|
-
struct fp_t<Float, true> {
|
|
1183
|
-
using extended_significand_type =
|
|
1184
|
-
typename grisu_exact_detail::common_info<Float>::extended_significand_type;
|
|
1185
|
-
|
|
1186
|
-
extended_significand_type significand;
|
|
1187
|
-
int exponent;
|
|
1188
|
-
bool is_negative;
|
|
1189
|
-
};
|
|
1190
|
-
|
|
1191
|
-
template <class Float>
|
|
1192
|
-
using unsigned_fp_t = fp_t<Float, false>;
|
|
1193
|
-
|
|
1194
|
-
template <class Float>
|
|
1195
|
-
using signed_fp_t = fp_t<Float, true>;
|
|
1196
|
-
|
|
1197
|
-
// In order to reduce the argument passing overhead,
|
|
1198
|
-
// this class should be as simple as possible.
|
|
1199
|
-
// (e.g., no inheritance, no private non-static data member, etc.;
|
|
1200
|
-
// this is an unfortunate fact about x64 calling convention.)
|
|
1201
|
-
template <class Float>
|
|
1202
|
-
struct bit_representation_t
|
|
1203
|
-
{
|
|
1204
|
-
private:
|
|
1205
|
-
using common_info = grisu_exact_detail::common_info<Float>;
|
|
1206
|
-
|
|
1207
|
-
static constexpr auto precision = common_info::precision;
|
|
1208
|
-
static constexpr auto extended_precision = common_info::extended_precision;
|
|
1209
|
-
static constexpr auto sign_bit_mask = common_info::sign_bit_mask;
|
|
1210
|
-
static constexpr auto exponent_bits = common_info::exponent_bits;
|
|
1211
|
-
static constexpr auto exponent_bias = common_info::exponent_bias;
|
|
1212
|
-
static constexpr auto exponent_bits_mask = common_info::exponent_bits_mask;
|
|
1213
|
-
|
|
1214
|
-
public:
|
|
1215
|
-
using extended_significand_type =
|
|
1216
|
-
typename common_info::extended_significand_type;
|
|
1217
|
-
extended_significand_type f;
|
|
1218
|
-
|
|
1219
|
-
//// Inspector methods
|
|
1220
|
-
|
|
1221
|
-
Float as_ieee754() const noexcept {
|
|
1222
|
-
Float x;
|
|
1223
|
-
std::memcpy(&x, &f, sizeof(Float));
|
|
1224
|
-
return x;
|
|
1225
|
-
}
|
|
1226
|
-
|
|
1227
|
-
constexpr extended_significand_type extract_significand_bits() const noexcept {
|
|
1228
|
-
constexpr auto significand_bits_mask =
|
|
1229
|
-
(extended_significand_type(1) << precision) - 1;
|
|
1230
|
-
return f & significand_bits_mask;
|
|
1231
|
-
}
|
|
1232
|
-
|
|
1233
|
-
constexpr std::uint32_t extract_exponent_bits() const noexcept {
|
|
1234
|
-
constexpr auto exponent_bits_mask =
|
|
1235
|
-
(std::uint32_t(1) << exponent_bits) - 1;
|
|
1236
|
-
return std::uint32_t(f >> precision) & exponent_bits_mask;
|
|
1237
|
-
}
|
|
1238
|
-
|
|
1239
|
-
constexpr bool is_finite() const noexcept {
|
|
1240
|
-
return (f & exponent_bits_mask) != exponent_bits_mask;
|
|
1241
|
-
}
|
|
1242
|
-
|
|
1243
|
-
constexpr bool is_nonzero() const noexcept {
|
|
1244
|
-
// vs (f & ~sign_bit_mask) != 0;
|
|
1245
|
-
// It seems that there is no AND instruction for 64-bit immediate value in x86,
|
|
1246
|
-
// thus (f & ~sign_bit_mask) != 0 generates 3 instructions (load, and, compare),
|
|
1247
|
-
// while this generates only two (shift, compare).
|
|
1248
|
-
return (f << 1) != 0;
|
|
1249
|
-
}
|
|
1250
|
-
|
|
1251
|
-
// Allows positive and negative zeros
|
|
1252
|
-
constexpr bool is_subnormal() const noexcept {
|
|
1253
|
-
return (f & exponent_bits_mask) == 0;
|
|
1254
|
-
}
|
|
1255
|
-
|
|
1256
|
-
// Allows negative zero and negative NaN's, but not allow positive zero
|
|
1257
|
-
constexpr bool is_negative() const noexcept {
|
|
1258
|
-
// vs (f & sign_bit_mask) != 0;
|
|
1259
|
-
// It seems that there is no AND instruction for 64-bit immediate value in x86,
|
|
1260
|
-
// thus (f & sign_bit_mask) != 0 generates 3 instructions (load, and, compare),
|
|
1261
|
-
// while this generates only two (shift, compare).
|
|
1262
|
-
return (f >> (extended_precision - 1)) != 0;
|
|
1263
|
-
}
|
|
1264
|
-
|
|
1265
|
-
// Allows positive zero and positive NaN's, but not allow negative zero
|
|
1266
|
-
constexpr bool is_positive() const noexcept {
|
|
1267
|
-
// vs (f & sign_bit_mask) == 0;
|
|
1268
|
-
// Ditto
|
|
1269
|
-
return (f >> (extended_precision - 1)) == 0;
|
|
1270
|
-
}
|
|
1271
|
-
|
|
1272
|
-
constexpr bool is_positive_infinity() const noexcept {
|
|
1273
|
-
constexpr auto positive_infinity = exponent_bits_mask;
|
|
1274
|
-
return f == positive_infinity;
|
|
1275
|
-
}
|
|
1276
|
-
|
|
1277
|
-
constexpr bool is_negative_infinity() const noexcept {
|
|
1278
|
-
constexpr auto negative_infinity = exponent_bits_mask | sign_bit_mask;
|
|
1279
|
-
return f == negative_infinity;
|
|
1280
|
-
}
|
|
1281
|
-
|
|
1282
|
-
// Allows both plus and minus infinities
|
|
1283
|
-
constexpr bool is_infinity() const noexcept {
|
|
1284
|
-
return is_positive_infinity() || is_negative_infinity();
|
|
1285
|
-
}
|
|
1286
|
-
|
|
1287
|
-
constexpr bool is_nan() const noexcept {
|
|
1288
|
-
return !is_finite() && (extract_significand_bits() != 0);
|
|
1289
|
-
}
|
|
1290
|
-
|
|
1291
|
-
bool is_quiet_nan() const noexcept {
|
|
1292
|
-
if (!is_nan()) {
|
|
1293
|
-
return false;
|
|
1294
|
-
}
|
|
1295
|
-
|
|
1296
|
-
auto quiet_or_signal_indicator = extended_significand_type(1) << (precision - 1);
|
|
1297
|
-
auto quiet_or_signal = f & quiet_or_signal_indicator;
|
|
1298
|
-
|
|
1299
|
-
constexpr auto a_quiet_nan = std::numeric_limits<Float>::quiet_NaN();
|
|
1300
|
-
extended_significand_type a_quiet_nan_bit_representation;
|
|
1301
|
-
std::memcpy(&a_quiet_nan_bit_representation, &a_quiet_nan, sizeof(Float));
|
|
1302
|
-
|
|
1303
|
-
return (a_quiet_nan_bit_representation & quiet_or_signal_indicator)
|
|
1304
|
-
== quiet_or_signal;
|
|
1305
|
-
}
|
|
1306
|
-
|
|
1307
|
-
bool is_signaling_nan() const noexcept {
|
|
1308
|
-
return is_nan() && !is_quiet_nan();
|
|
1309
|
-
}
|
|
1310
|
-
|
|
1311
|
-
static constexpr std::size_t nan_payload_length = precision - 1;
|
|
1312
|
-
std::bitset<nan_payload_length> get_nan_payload() const noexcept {
|
|
1313
|
-
constexpr auto payload_mask =
|
|
1314
|
-
(extended_significand_type(1) << (precision - 1)) - 1;
|
|
1315
|
-
return{ f & payload_mask };
|
|
1316
|
-
}
|
|
1317
|
-
};
|
|
1318
|
-
|
|
1319
|
-
template <class Float>
|
|
1320
|
-
bit_representation_t<Float> get_bit_representation(Float x) noexcept {
|
|
1321
|
-
bit_representation_t<Float> br;
|
|
1322
|
-
std::memcpy(&br.f, &x, sizeof(Float));
|
|
1323
|
-
return br;
|
|
1324
|
-
}
|
|
1325
|
-
|
|
1326
|
-
// Determine what to do about the correct rounding guarantee
|
|
1327
|
-
namespace grisu_exact_correct_rounding {
|
|
1328
|
-
enum tag_t {
|
|
1329
|
-
do_not_care_tag,
|
|
1330
|
-
tie_to_even_tag,
|
|
1331
|
-
tie_to_odd_tag,
|
|
1332
|
-
tie_to_up_tag,
|
|
1333
|
-
tie_to_down_tag
|
|
1334
|
-
};
|
|
1335
|
-
|
|
1336
|
-
// Do not perform correct rounding search
|
|
1337
|
-
struct do_not_care {
|
|
1338
|
-
static constexpr tag_t tag = do_not_care_tag;
|
|
1339
|
-
template <bool return_sign, class Float, class IntervalTypeProvider>
|
|
1340
|
-
fp_t<Float, return_sign> delegate(bit_representation_t<Float> br,
|
|
1341
|
-
IntervalTypeProvider&&) const
|
|
1342
|
-
{
|
|
1343
|
-
return grisu_exact_detail::grisu_exact_impl<Float>::template compute<return_sign,
|
|
1344
|
-
std::remove_cv_t<std::remove_reference_t<IntervalTypeProvider>>, do_not_care>(br);
|
|
1345
|
-
}
|
|
1346
|
-
};
|
|
1347
|
-
|
|
1348
|
-
// Perform correct rounding search; tie-to-even
|
|
1349
|
-
struct tie_to_even {
|
|
1350
|
-
static constexpr tag_t tag = tie_to_even_tag;
|
|
1351
|
-
template <bool return_sign, class Float, class IntervalTypeProvider>
|
|
1352
|
-
fp_t<Float, return_sign> delegate(bit_representation_t<Float> br,
|
|
1353
|
-
IntervalTypeProvider&&) const
|
|
1354
|
-
{
|
|
1355
|
-
return grisu_exact_detail::grisu_exact_impl<Float>::template compute<return_sign,
|
|
1356
|
-
std::remove_cv_t<std::remove_reference_t<IntervalTypeProvider>>, tie_to_even>(br);
|
|
1357
|
-
}
|
|
1358
|
-
};
|
|
1359
|
-
|
|
1360
|
-
// Perform correct rounding search; tie-to-odd
|
|
1361
|
-
struct tie_to_odd {
|
|
1362
|
-
static constexpr tag_t tag = tie_to_odd_tag;
|
|
1363
|
-
template <bool return_sign, class Float, class IntervalTypeProvider>
|
|
1364
|
-
fp_t<Float, return_sign> delegate(bit_representation_t<Float> br,
|
|
1365
|
-
IntervalTypeProvider&&) const
|
|
1366
|
-
{
|
|
1367
|
-
return grisu_exact_detail::grisu_exact_impl<Float>::template compute<return_sign,
|
|
1368
|
-
std::remove_cv_t<std::remove_reference_t<IntervalTypeProvider>>, tie_to_odd>(br);
|
|
1369
|
-
}
|
|
1370
|
-
};
|
|
1371
|
-
|
|
1372
|
-
// Perform correct rounding search; tie-to-up
|
|
1373
|
-
struct tie_to_up {
|
|
1374
|
-
static constexpr tag_t tag = tie_to_up_tag;
|
|
1375
|
-
template <bool return_sign, class Float, class IntervalTypeProvider>
|
|
1376
|
-
fp_t<Float, return_sign> delegate(bit_representation_t<Float> br,
|
|
1377
|
-
IntervalTypeProvider&&) const
|
|
1378
|
-
{
|
|
1379
|
-
return grisu_exact_detail::grisu_exact_impl<Float>::template compute<return_sign,
|
|
1380
|
-
std::remove_cv_t<std::remove_reference_t<IntervalTypeProvider>>, tie_to_up>(br);
|
|
1381
|
-
}
|
|
1382
|
-
};
|
|
1383
|
-
|
|
1384
|
-
// Perform correct rounding search; tie-to-down
|
|
1385
|
-
struct tie_to_down {
|
|
1386
|
-
static constexpr tag_t tag = tie_to_down_tag;
|
|
1387
|
-
template <bool return_sign, class Float, class IntervalTypeProvider>
|
|
1388
|
-
fp_t<Float, return_sign> delegate(bit_representation_t<Float> br,
|
|
1389
|
-
IntervalTypeProvider&&) const
|
|
1390
|
-
{
|
|
1391
|
-
return grisu_exact_detail::grisu_exact_impl<Float>::template compute<return_sign,
|
|
1392
|
-
std::remove_cv_t<std::remove_reference_t<IntervalTypeProvider>>, tie_to_down>(br);
|
|
1393
|
-
}
|
|
1394
|
-
};
|
|
1395
|
-
}
|
|
1396
|
-
|
|
1397
|
-
// Dispatch to the appropriate operator() overloading of grisu_exact_impl<Float>
|
|
1398
|
-
namespace grisu_exact_rounding_modes {
|
|
1399
|
-
enum tag_t {
|
|
1400
|
-
to_nearest_tag,
|
|
1401
|
-
left_closed_directed_tag,
|
|
1402
|
-
right_closed_directed_tag
|
|
1403
|
-
};
|
|
1404
|
-
namespace interval_type {
|
|
1405
|
-
struct symmetric_boundary {
|
|
1406
|
-
static constexpr bool is_symmetric = true;
|
|
1407
|
-
bool is_closed;
|
|
1408
|
-
|
|
1409
|
-
constexpr bool include_left_endpoint() const noexcept {
|
|
1410
|
-
return is_closed;
|
|
1411
|
-
}
|
|
1412
|
-
constexpr bool include_right_endpoint() const noexcept {
|
|
1413
|
-
return is_closed;
|
|
1414
|
-
}
|
|
1415
|
-
};
|
|
1416
|
-
struct asymmetric_boundary {
|
|
1417
|
-
static constexpr bool is_symmetric = false;
|
|
1418
|
-
bool is_left_closed;
|
|
1419
|
-
constexpr bool include_left_endpoint() const noexcept {
|
|
1420
|
-
return is_left_closed;
|
|
1421
|
-
}
|
|
1422
|
-
constexpr bool include_right_endpoint() const noexcept {
|
|
1423
|
-
return !is_left_closed;
|
|
1424
|
-
}
|
|
1425
|
-
};
|
|
1426
|
-
struct closed {
|
|
1427
|
-
static constexpr bool is_symmetric = true;
|
|
1428
|
-
static constexpr bool include_left_endpoint() noexcept {
|
|
1429
|
-
return true;
|
|
1430
|
-
}
|
|
1431
|
-
static constexpr bool include_right_endpoint() noexcept {
|
|
1432
|
-
return true;
|
|
1433
|
-
}
|
|
1434
|
-
};
|
|
1435
|
-
struct open {
|
|
1436
|
-
static constexpr bool is_symmetric = true;
|
|
1437
|
-
static constexpr bool include_left_endpoint() noexcept {
|
|
1438
|
-
return false;
|
|
1439
|
-
}
|
|
1440
|
-
static constexpr bool include_right_endpoint() noexcept {
|
|
1441
|
-
return false;
|
|
1442
|
-
}
|
|
1443
|
-
};
|
|
1444
|
-
struct left_closed_right_open {
|
|
1445
|
-
static constexpr bool is_symmetric = false;
|
|
1446
|
-
static constexpr bool include_left_endpoint() noexcept {
|
|
1447
|
-
return true;
|
|
1448
|
-
}
|
|
1449
|
-
static constexpr bool include_right_endpoint() noexcept {
|
|
1450
|
-
return false;
|
|
1451
|
-
}
|
|
1452
|
-
};
|
|
1453
|
-
struct right_closed_left_open {
|
|
1454
|
-
static constexpr bool is_symmetric = false;
|
|
1455
|
-
static constexpr bool include_left_endpoint() noexcept {
|
|
1456
|
-
return false;
|
|
1457
|
-
}
|
|
1458
|
-
static constexpr bool include_right_endpoint() noexcept {
|
|
1459
|
-
return true;
|
|
1460
|
-
}
|
|
1461
|
-
};
|
|
1462
|
-
}
|
|
1463
|
-
|
|
1464
|
-
struct nearest_to_even {
|
|
1465
|
-
static constexpr tag_t tag = to_nearest_tag;
|
|
1466
|
-
|
|
1467
|
-
template <bool return_sign, class Float, class CorrectRoundingSearch>
|
|
1468
|
-
fp_t<Float, return_sign> delegate(bit_representation_t<Float> br,
|
|
1469
|
-
CorrectRoundingSearch&& crs) const
|
|
1470
|
-
{
|
|
1471
|
-
return std::forward<CorrectRoundingSearch>(crs).template delegate<return_sign>(
|
|
1472
|
-
br, *this);
|
|
1473
|
-
}
|
|
1474
|
-
template <class Float>
|
|
1475
|
-
constexpr interval_type::symmetric_boundary operator()(bit_representation_t<Float> br) const noexcept {
|
|
1476
|
-
return{ br.f % 2 == 0 };
|
|
1477
|
-
}
|
|
1478
|
-
};
|
|
1479
|
-
struct nearest_to_odd {
|
|
1480
|
-
static constexpr tag_t tag = to_nearest_tag;
|
|
1481
|
-
|
|
1482
|
-
template <bool return_sign, class Float, class CorrectRoundingSearch>
|
|
1483
|
-
fp_t<Float, return_sign> delegate(bit_representation_t<Float> br,
|
|
1484
|
-
CorrectRoundingSearch&& crs) const
|
|
1485
|
-
{
|
|
1486
|
-
return std::forward<CorrectRoundingSearch>(crs).template delegate<return_sign>(
|
|
1487
|
-
br, *this);
|
|
1488
|
-
}
|
|
1489
|
-
template <class Float>
|
|
1490
|
-
constexpr interval_type::symmetric_boundary operator()(bit_representation_t<Float> br) const noexcept {
|
|
1491
|
-
return{ br.f % 2 != 0 };
|
|
1492
|
-
}
|
|
1493
|
-
};
|
|
1494
|
-
struct nearest_toward_plus_infinity {
|
|
1495
|
-
static constexpr tag_t tag = to_nearest_tag;
|
|
1496
|
-
|
|
1497
|
-
template <bool return_sign, class Float, class CorrectRoundingSearch>
|
|
1498
|
-
fp_t<Float, return_sign> delegate(bit_representation_t<Float> br,
|
|
1499
|
-
CorrectRoundingSearch&& crs) const
|
|
1500
|
-
{
|
|
1501
|
-
return std::forward<CorrectRoundingSearch>(crs).template delegate<return_sign>(
|
|
1502
|
-
br, *this);
|
|
1503
|
-
}
|
|
1504
|
-
template <class Float>
|
|
1505
|
-
constexpr interval_type::asymmetric_boundary operator()(bit_representation_t<Float> br) const noexcept {
|
|
1506
|
-
return{ !br.is_negative() };
|
|
1507
|
-
}
|
|
1508
|
-
};
|
|
1509
|
-
struct nearest_toward_minus_infinity {
|
|
1510
|
-
static constexpr tag_t tag = to_nearest_tag;
|
|
1511
|
-
|
|
1512
|
-
template <bool return_sign, class Float, class CorrectRoundingSearch>
|
|
1513
|
-
fp_t<Float, return_sign> delegate(bit_representation_t<Float> br,
|
|
1514
|
-
CorrectRoundingSearch&& crs) const
|
|
1515
|
-
{
|
|
1516
|
-
return std::forward<CorrectRoundingSearch>(crs).template delegate<return_sign>(
|
|
1517
|
-
br, *this);
|
|
1518
|
-
}
|
|
1519
|
-
template <class Float>
|
|
1520
|
-
constexpr interval_type::asymmetric_boundary operator()(bit_representation_t<Float> br) const noexcept {
|
|
1521
|
-
return{ br.is_negative() };
|
|
1522
|
-
}
|
|
1523
|
-
};
|
|
1524
|
-
// This may generate the fastest code among nearest rounding modes
|
|
1525
|
-
struct nearest_toward_zero {
|
|
1526
|
-
static constexpr tag_t tag = to_nearest_tag;
|
|
1527
|
-
|
|
1528
|
-
template <bool return_sign, class Float, class CorrectRoundingSearch>
|
|
1529
|
-
fp_t<Float, return_sign> delegate(bit_representation_t<Float> br,
|
|
1530
|
-
CorrectRoundingSearch&& crs) const
|
|
1531
|
-
{
|
|
1532
|
-
return std::forward<CorrectRoundingSearch>(crs).template delegate<return_sign>(
|
|
1533
|
-
br, *this);
|
|
1534
|
-
}
|
|
1535
|
-
template <class Float>
|
|
1536
|
-
constexpr interval_type::right_closed_left_open operator()(bit_representation_t<Float>) const noexcept {
|
|
1537
|
-
return{};
|
|
1538
|
-
}
|
|
1539
|
-
};
|
|
1540
|
-
struct nearest_away_from_zero {
|
|
1541
|
-
static constexpr tag_t tag = to_nearest_tag;
|
|
1542
|
-
|
|
1543
|
-
template <bool return_sign, class Float, class CorrectRoundingSearch>
|
|
1544
|
-
fp_t<Float, return_sign> delegate(bit_representation_t<Float> br,
|
|
1545
|
-
CorrectRoundingSearch&& crs) const
|
|
1546
|
-
{
|
|
1547
|
-
return std::forward<CorrectRoundingSearch>(crs).template delegate<return_sign>(
|
|
1548
|
-
br, *this);
|
|
1549
|
-
}
|
|
1550
|
-
template <class Float>
|
|
1551
|
-
constexpr interval_type::left_closed_right_open operator()(bit_representation_t<Float>) const noexcept {
|
|
1552
|
-
return{};
|
|
1553
|
-
}
|
|
1554
|
-
};
|
|
1555
|
-
|
|
1556
|
-
namespace detail {
|
|
1557
|
-
struct nearest_always_closed {
|
|
1558
|
-
static constexpr tag_t tag = to_nearest_tag;
|
|
1559
|
-
|
|
1560
|
-
template <class Float>
|
|
1561
|
-
constexpr interval_type::closed operator()(bit_representation_t<Float>) const noexcept {
|
|
1562
|
-
return{};
|
|
1563
|
-
}
|
|
1564
|
-
};
|
|
1565
|
-
struct nearest_always_open {
|
|
1566
|
-
static constexpr tag_t tag = to_nearest_tag;
|
|
1567
|
-
|
|
1568
|
-
template <class Float>
|
|
1569
|
-
constexpr interval_type::open operator()(bit_representation_t<Float>) const noexcept {
|
|
1570
|
-
return{};
|
|
1571
|
-
}
|
|
1572
|
-
};
|
|
1573
|
-
}
|
|
1574
|
-
|
|
1575
|
-
// Same as nearest_to_even, but generate separate codes for
|
|
1576
|
-
// different boundary conditions; may produce faster (or slower) code, but bigger binary
|
|
1577
|
-
struct nearest_to_even_static_boundary {
|
|
1578
|
-
template <bool return_sign, class Float, class CorrectRoundingSearch>
|
|
1579
|
-
fp_t<Float, return_sign> delegate(bit_representation_t<Float> br,
|
|
1580
|
-
CorrectRoundingSearch&& crs) const
|
|
1581
|
-
{
|
|
1582
|
-
if (br.f % 2 == 0) {
|
|
1583
|
-
return std::forward<CorrectRoundingSearch>(crs).template delegate<return_sign>(
|
|
1584
|
-
br, detail::nearest_always_closed{});
|
|
1585
|
-
}
|
|
1586
|
-
else {
|
|
1587
|
-
return std::forward<CorrectRoundingSearch>(crs).template delegate<return_sign>(
|
|
1588
|
-
br, detail::nearest_always_open{});
|
|
1589
|
-
}
|
|
1590
|
-
}
|
|
1591
|
-
};
|
|
1592
|
-
// Same as nearest_to_odd, but generate separate codes for
|
|
1593
|
-
// different boundary conditions; may produce faster (or slower) code, but bigger binary
|
|
1594
|
-
struct nearest_to_odd_static_boundary {
|
|
1595
|
-
template <bool return_sign, class Float, class CorrectRoundingSearch>
|
|
1596
|
-
fp_t<Float, return_sign> delegate(bit_representation_t<Float> br,
|
|
1597
|
-
CorrectRoundingSearch&& crs) const
|
|
1598
|
-
{
|
|
1599
|
-
if (br.f % 2 == 0) {
|
|
1600
|
-
return std::forward<CorrectRoundingSearch>(crs).template delegate<return_sign>(
|
|
1601
|
-
br, detail::nearest_always_open{});
|
|
1602
|
-
}
|
|
1603
|
-
else {
|
|
1604
|
-
return std::forward<CorrectRoundingSearch>(crs).template delegate<return_sign>(
|
|
1605
|
-
br, detail::nearest_always_closed{});
|
|
1606
|
-
}
|
|
1607
|
-
}
|
|
1608
|
-
};
|
|
1609
|
-
// Same as nearest_toward_plus_infinity, but generate separate codes for
|
|
1610
|
-
// different boundary conditions; may produce faster (or slower) code, but bigger binary
|
|
1611
|
-
struct nearest_toward_plus_infinity_static_boundary {
|
|
1612
|
-
template <bool return_sign, class Float, class CorrectRoundingSearch>
|
|
1613
|
-
fp_t<Float, return_sign> delegate(bit_representation_t<Float> br,
|
|
1614
|
-
CorrectRoundingSearch&& crs) const
|
|
1615
|
-
{
|
|
1616
|
-
if (br.is_negative()) {
|
|
1617
|
-
return std::forward<CorrectRoundingSearch>(crs).template delegate<return_sign>(
|
|
1618
|
-
br, nearest_toward_zero{});
|
|
1619
|
-
}
|
|
1620
|
-
else {
|
|
1621
|
-
return std::forward<CorrectRoundingSearch>(crs).template delegate<return_sign>(
|
|
1622
|
-
br, nearest_away_from_zero{});
|
|
1623
|
-
}
|
|
1624
|
-
}
|
|
1625
|
-
};
|
|
1626
|
-
// Same as nearest_toward_minus_infinity, but generate separate codes for
|
|
1627
|
-
// different boundary conditions; may produce faster (or slower) code, but bigger binary
|
|
1628
|
-
struct nearest_toward_minus_infinity_static_boundary {
|
|
1629
|
-
template <bool return_sign, class Float, class CorrectRoundingSearch>
|
|
1630
|
-
fp_t<Float, return_sign> delegate(bit_representation_t<Float> br,
|
|
1631
|
-
CorrectRoundingSearch&& crs) const
|
|
1632
|
-
{
|
|
1633
|
-
if (br.is_negative()) {
|
|
1634
|
-
return std::forward<CorrectRoundingSearch>(crs).template delegate<return_sign>(
|
|
1635
|
-
br, nearest_away_from_zero{});
|
|
1636
|
-
}
|
|
1637
|
-
else {
|
|
1638
|
-
return std::forward<CorrectRoundingSearch>(crs).template delegate<return_sign>(
|
|
1639
|
-
br, nearest_toward_zero{});
|
|
1640
|
-
}
|
|
1641
|
-
}
|
|
1642
|
-
};
|
|
1643
|
-
|
|
1644
|
-
namespace detail {
|
|
1645
|
-
struct left_closed_directed {
|
|
1646
|
-
static constexpr tag_t tag = left_closed_directed_tag;
|
|
1647
|
-
|
|
1648
|
-
template <class Float>
|
|
1649
|
-
constexpr interval_type::left_closed_right_open operator()(bit_representation_t<Float>) const noexcept {
|
|
1650
|
-
return{};
|
|
1651
|
-
}
|
|
1652
|
-
};
|
|
1653
|
-
struct right_closed_directed {
|
|
1654
|
-
static constexpr tag_t tag = right_closed_directed_tag;
|
|
1655
|
-
|
|
1656
|
-
template <class Float>
|
|
1657
|
-
constexpr interval_type::right_closed_left_open operator()(bit_representation_t<Float>) const noexcept {
|
|
1658
|
-
return{};
|
|
1659
|
-
}
|
|
1660
|
-
};
|
|
1661
|
-
}
|
|
1662
|
-
|
|
1663
|
-
struct toward_plus_infinity {
|
|
1664
|
-
template <bool return_sign, class Float, class CorrectRoundingSearch>
|
|
1665
|
-
fp_t<Float, return_sign> delegate(bit_representation_t<Float> br,
|
|
1666
|
-
CorrectRoundingSearch&& crs) const
|
|
1667
|
-
{
|
|
1668
|
-
if (br.is_negative()) {
|
|
1669
|
-
return std::forward<CorrectRoundingSearch>(crs).template delegate<return_sign>(
|
|
1670
|
-
br, detail::left_closed_directed{});
|
|
1671
|
-
|
|
1672
|
-
}
|
|
1673
|
-
else {
|
|
1674
|
-
return std::forward<CorrectRoundingSearch>(crs).template delegate<return_sign>(
|
|
1675
|
-
br, detail::right_closed_directed{});
|
|
1676
|
-
}
|
|
1677
|
-
}
|
|
1678
|
-
};
|
|
1679
|
-
struct toward_minus_infinity {
|
|
1680
|
-
template <bool return_sign, class Float, class CorrectRoundingSearch>
|
|
1681
|
-
fp_t<Float, return_sign> delegate(bit_representation_t<Float> br,
|
|
1682
|
-
CorrectRoundingSearch&& crs) const
|
|
1683
|
-
{
|
|
1684
|
-
if (br.is_negative()) {
|
|
1685
|
-
return std::forward<CorrectRoundingSearch>(crs).template delegate<return_sign>(
|
|
1686
|
-
br, detail::right_closed_directed{});
|
|
1687
|
-
}
|
|
1688
|
-
else {
|
|
1689
|
-
return std::forward<CorrectRoundingSearch>(crs).template delegate<return_sign>(
|
|
1690
|
-
br, detail::left_closed_directed{});
|
|
1691
|
-
}
|
|
1692
|
-
}
|
|
1693
|
-
};
|
|
1694
|
-
struct toward_zero {
|
|
1695
|
-
template <bool return_sign, class Float, class CorrectRoundingSearch>
|
|
1696
|
-
fp_t<Float, return_sign> delegate(bit_representation_t<Float> br,
|
|
1697
|
-
CorrectRoundingSearch&& crs) const
|
|
1698
|
-
{
|
|
1699
|
-
return std::forward<CorrectRoundingSearch>(crs).template delegate<return_sign>(
|
|
1700
|
-
br, detail::left_closed_directed{});
|
|
1701
|
-
}
|
|
1702
|
-
};
|
|
1703
|
-
struct away_from_zero {
|
|
1704
|
-
template <bool return_sign, class Float, class CorrectRoundingSearch>
|
|
1705
|
-
fp_t<Float, return_sign> delegate(bit_representation_t<Float> br,
|
|
1706
|
-
CorrectRoundingSearch&& crs) const
|
|
1707
|
-
{
|
|
1708
|
-
return std::forward<CorrectRoundingSearch>(crs).template delegate<return_sign>(
|
|
1709
|
-
br, detail::right_closed_directed{});
|
|
1710
|
-
}
|
|
1711
|
-
};
|
|
1712
|
-
}
|
|
1713
|
-
|
|
1714
|
-
namespace grisu_exact_detail {
|
|
1715
|
-
////////////////////////////////////////////////////////////////////////////////////////
|
|
1716
|
-
// The main algorithm
|
|
1717
|
-
////////////////////////////////////////////////////////////////////////////////////////
|
|
1718
|
-
|
|
1719
|
-
// Get sign/decimal significand/decimal exponent from
|
|
1720
|
-
// the bit representation of a floating-point number
|
|
1721
|
-
template <class Float>
|
|
1722
|
-
struct grisu_exact_impl : private common_info<Float>
|
|
1723
|
-
{
|
|
1724
|
-
using extended_significand_type =
|
|
1725
|
-
typename common_info<Float>::extended_significand_type;
|
|
1726
|
-
using cache_entry_type =
|
|
1727
|
-
typename common_info<Float>::cache_entry_type;
|
|
1728
|
-
|
|
1729
|
-
using common_info<Float>::precision;
|
|
1730
|
-
using common_info<Float>::extended_precision;
|
|
1731
|
-
using common_info<Float>::cache_precision;
|
|
1732
|
-
using common_info<Float>::sign_bit_mask;
|
|
1733
|
-
using common_info<Float>::exponent_bits;
|
|
1734
|
-
using common_info<Float>::exponent_bias;
|
|
1735
|
-
using common_info<Float>::exponent_bits_mask;
|
|
1736
|
-
using common_info<Float>::min_exponent;
|
|
1737
|
-
using common_info<Float>::boundary_bit;
|
|
1738
|
-
using common_info<Float>::normal_interval_length;
|
|
1739
|
-
using common_info<Float>::edge_case_boundary_bit;
|
|
1740
|
-
using common_info<Float>::alpha;
|
|
1741
|
-
using common_info<Float>::gamma;
|
|
1742
|
-
using common_info<Float>::min_kappa;
|
|
1743
|
-
using common_info<Float>::max_kappa;
|
|
1744
|
-
using common_info<Float>::initial_kappa;
|
|
1745
|
-
using common_info<Float>::integer_check_exponent_lower_bound_for_q_mp_m3;
|
|
1746
|
-
using common_info<Float>::integer_check_exponent_lower_bound_for_q_mp_m2;
|
|
1747
|
-
using common_info<Float>::integer_check_exponent_lower_bound_for_q_mp_m1;
|
|
1748
|
-
using common_info<Float>::integer_check_exponent_lower_bound_for_q_mp;
|
|
1749
|
-
using common_info<Float>::max_exponent_for_k_geq_0;
|
|
1750
|
-
using common_info<Float>::max_exponent_for_k_geq_m1;
|
|
1751
|
-
using common_info<Float>::integer_check_exponent_upper_bound_for_p_p2;
|
|
1752
|
-
using common_info<Float>::integer_check_exponent_upper_bound_for_p_p1;
|
|
1753
|
-
|
|
1754
|
-
template <unsigned int e>
|
|
1755
|
-
static constexpr extended_significand_type power_of_10 = compute_power(extended_significand_type(10), e);
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
//// The main algorithm assumes the input is a normal/subnormal finite number
|
|
1759
|
-
|
|
1760
|
-
template <bool return_sign, class IntervalTypeProvider, class CorrectRoundingSearch>
|
|
1761
|
-
JKJ_SAFEBUFFERS
|
|
1762
|
-
static fp_t<Float, return_sign> compute(bit_representation_t<Float> br) noexcept
|
|
1763
|
-
{
|
|
1764
|
-
//////////////////////////////////////////////////////////////////////
|
|
1765
|
-
// Step 1: integer promotion & Grisu multiplier calculation
|
|
1766
|
-
//////////////////////////////////////////////////////////////////////
|
|
1767
|
-
|
|
1768
|
-
fp_t<Float, return_sign> ret_value;
|
|
1769
|
-
|
|
1770
|
-
auto interval_type = IntervalTypeProvider{}(br);
|
|
1771
|
-
|
|
1772
|
-
if constexpr (return_sign) {
|
|
1773
|
-
ret_value.is_negative = br.is_negative();
|
|
1774
|
-
}
|
|
1775
|
-
auto significand = br.f << exponent_bits;
|
|
1776
|
-
|
|
1777
|
-
auto exponent = int((br.f >> precision) & (exponent_bits_mask >> precision));
|
|
1778
|
-
// Deal with normal/subnormal dichotomy
|
|
1779
|
-
if (exponent != 0) {
|
|
1780
|
-
significand |= sign_bit_mask;
|
|
1781
|
-
exponent = exponent + exponent_bias - int(extended_precision) + 1;
|
|
1782
|
-
}
|
|
1783
|
-
else {
|
|
1784
|
-
exponent = min_exponent;
|
|
1785
|
-
}
|
|
1786
|
-
|
|
1787
|
-
// Compute the endpoints
|
|
1788
|
-
extended_significand_type fr;
|
|
1789
|
-
// For nearest rounding
|
|
1790
|
-
if constexpr (IntervalTypeProvider::tag ==
|
|
1791
|
-
grisu_exact_rounding_modes::to_nearest_tag)
|
|
1792
|
-
{
|
|
1793
|
-
fr = significand | boundary_bit;
|
|
1794
|
-
}
|
|
1795
|
-
// For left-closed directed rounding
|
|
1796
|
-
else if constexpr (IntervalTypeProvider::tag ==
|
|
1797
|
-
grisu_exact_rounding_modes::left_closed_directed_tag)
|
|
1798
|
-
{
|
|
1799
|
-
fr = significand + normal_interval_length;
|
|
1800
|
-
}
|
|
1801
|
-
// For right-closed directed rounding
|
|
1802
|
-
else {
|
|
1803
|
-
fr = significand;
|
|
1804
|
-
}
|
|
1805
|
-
|
|
1806
|
-
// Compute k and beta
|
|
1807
|
-
int const minus_k = floor_log10_pow2(exponent + 1 - alpha);
|
|
1808
|
-
int const minus_beta = -(exponent + floor_log2_pow10(-minus_k) + 1);
|
|
1809
|
-
assert(-minus_beta >= alpha && -minus_beta <= gamma);
|
|
1810
|
-
|
|
1811
|
-
// Compute zi and deltai
|
|
1812
|
-
auto const cache = jkj::grisu_exact_detail::get_cache<Float>(-minus_k);
|
|
1813
|
-
|
|
1814
|
-
extended_significand_type zi;
|
|
1815
|
-
if constexpr (IntervalTypeProvider::tag ==
|
|
1816
|
-
grisu_exact_rounding_modes::left_closed_directed_tag)
|
|
1817
|
-
{
|
|
1818
|
-
// Take care of the case when overflow occurs
|
|
1819
|
-
if (fr == 0) {
|
|
1820
|
-
if constexpr (sizeof(Float) == 4) {
|
|
1821
|
-
zi = extended_significand_type(cache >>
|
|
1822
|
-
extended_precision >> minus_beta);
|
|
1823
|
-
}
|
|
1824
|
-
else {
|
|
1825
|
-
zi = cache.high() >> minus_beta;
|
|
1826
|
-
}
|
|
1827
|
-
}
|
|
1828
|
-
else {
|
|
1829
|
-
zi = compute_mul(fr, cache, minus_beta);
|
|
1830
|
-
}
|
|
1831
|
-
}
|
|
1832
|
-
else {
|
|
1833
|
-
zi = compute_mul(fr, cache, minus_beta);
|
|
1834
|
-
}
|
|
1835
|
-
|
|
1836
|
-
auto deltai = compute_delta<IntervalTypeProvider::tag>(
|
|
1837
|
-
significand == sign_bit_mask && exponent != min_exponent, cache, minus_beta);
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
//////////////////////////////////////////////////////////////////////
|
|
1841
|
-
// Step 2: Search for kappa
|
|
1842
|
-
//////////////////////////////////////////////////////////////////////
|
|
1843
|
-
|
|
1844
|
-
// Comparison of fractional parts is delayed
|
|
1845
|
-
auto zf_vs_deltaf = zf_vs_deltaf_t::not_compared_yet;
|
|
1846
|
-
|
|
1847
|
-
// Compute s and r for initial kappa
|
|
1848
|
-
extended_significand_type divisor;
|
|
1849
|
-
ret_value.significand = zi / power_of_10<initial_kappa>;
|
|
1850
|
-
auto r = zi % power_of_10<initial_kappa>;
|
|
1851
|
-
|
|
1852
|
-
ret_value.exponent = initial_kappa + minus_k;
|
|
1853
|
-
|
|
1854
|
-
// We've got too much? or too less?
|
|
1855
|
-
if (r < deltai) {
|
|
1856
|
-
goto increasing_search_label;
|
|
1857
|
-
}
|
|
1858
|
-
else if (r == deltai) {
|
|
1859
|
-
if (is_zf_smaller_than_deltaf<IntervalTypeProvider::tag>(significand,
|
|
1860
|
-
minus_beta, cache, interval_type, exponent, minus_k))
|
|
1861
|
-
{
|
|
1862
|
-
zf_vs_deltaf = zf_vs_deltaf_t::zf_smaller;
|
|
1863
|
-
goto increasing_search_label;
|
|
1864
|
-
}
|
|
1865
|
-
zf_vs_deltaf = zf_vs_deltaf_t::zf_larger;
|
|
1866
|
-
}
|
|
1867
|
-
|
|
1868
|
-
// Perform decreasing search
|
|
1869
|
-
// In the paper, we calculate 10^(kappa0 - kappa) * r_(kappa - lambda) instead of
|
|
1870
|
-
// r_(kappa-lambda), and 10^(kappa0 - kappa) * deltai instead of deltai, and
|
|
1871
|
-
// 10^kappa0 instead of 10^kappa, so that the search procedure can be iterated.
|
|
1872
|
-
// However, in this implementation we will not iterate decreasing search and
|
|
1873
|
-
// the search will be performed only once. Hence, we do not need to do that.
|
|
1874
|
-
{
|
|
1875
|
-
// This procedure strictly depends on our specific choice of these parameters:
|
|
1876
|
-
static_assert(initial_kappa - min_kappa <= 2);
|
|
1877
|
-
|
|
1878
|
-
constexpr unsigned int lambda = 1;
|
|
1879
|
-
// We already know r < 10^initial_kappa < 2^32
|
|
1880
|
-
auto const quotient = std::uint32_t(r) / std::uint32_t(power_of_10<initial_kappa - lambda>);
|
|
1881
|
-
auto const new_r = std::uint32_t(r) % std::uint32_t(power_of_10<initial_kappa - lambda>);
|
|
1882
|
-
|
|
1883
|
-
// Check if the remainder is still greater than or equal to the delta
|
|
1884
|
-
// remainder should be strictly greater if the left boundary is contained
|
|
1885
|
-
|
|
1886
|
-
if (new_r < deltai) {
|
|
1887
|
-
goto decrease_kappa_by_1_label;
|
|
1888
|
-
}
|
|
1889
|
-
else if (new_r == deltai) {
|
|
1890
|
-
// zf_vs_deltaf cannot be zf_smaller here
|
|
1891
|
-
if (zf_vs_deltaf == zf_vs_deltaf_t::not_compared_yet) {
|
|
1892
|
-
if (is_zf_smaller_than_deltaf<IntervalTypeProvider::tag>(significand,
|
|
1893
|
-
minus_beta, cache, interval_type, exponent, minus_k))
|
|
1894
|
-
{
|
|
1895
|
-
zf_vs_deltaf = zf_vs_deltaf_t::zf_smaller;
|
|
1896
|
-
goto decrease_kappa_by_1_label;
|
|
1897
|
-
}
|
|
1898
|
-
zf_vs_deltaf = zf_vs_deltaf_t::zf_larger;
|
|
1899
|
-
}
|
|
1900
|
-
}
|
|
1901
|
-
|
|
1902
|
-
// Decrease kappa by 1 + lambda (lambda = 1)
|
|
1903
|
-
if constexpr (initial_kappa == 2) {
|
|
1904
|
-
// kappa = 0
|
|
1905
|
-
ret_value.significand = zi;
|
|
1906
|
-
r = 0;
|
|
1907
|
-
}
|
|
1908
|
-
else {
|
|
1909
|
-
static_assert(initial_kappa == 3);
|
|
1910
|
-
// kappa = 1
|
|
1911
|
-
ret_value.significand *= 100;
|
|
1912
|
-
ret_value.significand += 10 * quotient + (std::uint32_t(new_r) / 10);
|
|
1913
|
-
r = std::uint32_t(new_r) % 10;
|
|
1914
|
-
}
|
|
1915
|
-
ret_value.exponent -= 2;
|
|
1916
|
-
divisor = power_of_10<initial_kappa - 2>;
|
|
1917
|
-
|
|
1918
|
-
// Since kappa is already the smallest possible value,
|
|
1919
|
-
// we do not need to search for kappa'
|
|
1920
|
-
// (But still need to get away from the boundary for certain cases)
|
|
1921
|
-
if constexpr (CorrectRoundingSearch::tag !=
|
|
1922
|
-
grisu_exact_correct_rounding::do_not_care_tag &&
|
|
1923
|
-
IntervalTypeProvider::tag ==
|
|
1924
|
-
grisu_exact_rounding_modes::to_nearest_tag)
|
|
1925
|
-
{
|
|
1926
|
-
// For binary32 case, kappa == 0 case requires a separate correct rounding search
|
|
1927
|
-
if constexpr (min_kappa == 0)
|
|
1928
|
-
{
|
|
1929
|
-
goto correct_rounding_search_when_kappa_is_0_label;
|
|
1930
|
-
}
|
|
1931
|
-
else
|
|
1932
|
-
{
|
|
1933
|
-
goto correct_rounding_search_label;
|
|
1934
|
-
}
|
|
1935
|
-
}
|
|
1936
|
-
else
|
|
1937
|
-
{
|
|
1938
|
-
goto boundary_adjustment_label;
|
|
1939
|
-
}
|
|
1940
|
-
|
|
1941
|
-
decrease_kappa_by_1_label:
|
|
1942
|
-
// Decrease kappa by 1
|
|
1943
|
-
ret_value.significand *= 10;
|
|
1944
|
-
ret_value.significand += quotient;
|
|
1945
|
-
r = new_r;
|
|
1946
|
-
--ret_value.exponent;
|
|
1947
|
-
|
|
1948
|
-
divisor = power_of_10<initial_kappa - 1>;
|
|
1949
|
-
goto boundary_adjustment_label;
|
|
1950
|
-
}
|
|
1951
|
-
|
|
1952
|
-
increasing_search_label:
|
|
1953
|
-
// Perform binary search
|
|
1954
|
-
divisor = power_of_10<initial_kappa>;
|
|
1955
|
-
|
|
1956
|
-
if constexpr (sizeof(Float) == 4) {
|
|
1957
|
-
// This procedure strictly depends on our specific choice of these parameters:
|
|
1958
|
-
static_assert(max_kappa - initial_kappa < 8);
|
|
1959
|
-
|
|
1960
|
-
increasing_search<4, IntervalTypeProvider::tag, true>(ret_value, interval_type,
|
|
1961
|
-
zf_vs_deltaf, exponent, minus_k, minus_beta, significand, r, divisor, deltai, cache);
|
|
1962
|
-
increasing_search<2, IntervalTypeProvider::tag, false>(ret_value, interval_type,
|
|
1963
|
-
zf_vs_deltaf, exponent, minus_k, minus_beta, significand, r, divisor, deltai, cache);
|
|
1964
|
-
increasing_search<1, IntervalTypeProvider::tag, false>(ret_value, interval_type,
|
|
1965
|
-
zf_vs_deltaf, exponent, minus_k, minus_beta, significand, r, divisor, deltai, cache);
|
|
1966
|
-
}
|
|
1967
|
-
else {
|
|
1968
|
-
// This procedure strictly depends on our specific choice of these parameters:
|
|
1969
|
-
static_assert(max_kappa - initial_kappa < 16);
|
|
1970
|
-
|
|
1971
|
-
increasing_search<8, IntervalTypeProvider::tag, true>(ret_value, interval_type,
|
|
1972
|
-
zf_vs_deltaf, exponent, minus_k, minus_beta, significand, r, divisor, deltai, cache);
|
|
1973
|
-
increasing_search<4, IntervalTypeProvider::tag, false>(ret_value, interval_type,
|
|
1974
|
-
zf_vs_deltaf, exponent, minus_k, minus_beta, significand, r, divisor, deltai, cache);
|
|
1975
|
-
increasing_search<2, IntervalTypeProvider::tag, false>(ret_value, interval_type,
|
|
1976
|
-
zf_vs_deltaf, exponent, minus_k, minus_beta, significand, r, divisor, deltai, cache);
|
|
1977
|
-
increasing_search<1, IntervalTypeProvider::tag, false>(ret_value, interval_type,
|
|
1978
|
-
zf_vs_deltaf, exponent, minus_k, minus_beta, significand, r, divisor, deltai, cache);
|
|
1979
|
-
}
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
//////////////////////////////////////////////////////////////////////
|
|
1983
|
-
// Step 3: Dealing with the right endpoint (search for kappa')
|
|
1984
|
-
//////////////////////////////////////////////////////////////////////
|
|
1985
|
-
|
|
1986
|
-
boundary_adjustment_label:
|
|
1987
|
-
// If right endpoint is not included, we should check if z mod 10^kappa = 0
|
|
1988
|
-
if (!interval_type.include_right_endpoint() && r == 0) {
|
|
1989
|
-
constexpr integer_check_case_id case_id =
|
|
1990
|
-
IntervalTypeProvider::tag == grisu_exact_rounding_modes::to_nearest_tag ?
|
|
1991
|
-
integer_check_case_id::fc_pm_2_to_the_q_mp_m2_generic :
|
|
1992
|
-
integer_check_case_id::other;
|
|
1993
|
-
|
|
1994
|
-
if (is_product_integer<case_id>(fr, exponent, minus_k)) {
|
|
1995
|
-
// Decrease kappa until 10^kappa becomes smaller than delta
|
|
1996
|
-
// If left boundary is included, 10^kappa can also be equal to delta
|
|
1997
|
-
while (true) {
|
|
1998
|
-
if (divisor < deltai) {
|
|
1999
|
-
break;
|
|
2000
|
-
}
|
|
2001
|
-
else if (divisor == deltai) {
|
|
2002
|
-
// For nearest rounding only
|
|
2003
|
-
if constexpr (IntervalTypeProvider::tag ==
|
|
2004
|
-
grisu_exact_rounding_modes::to_nearest_tag)
|
|
2005
|
-
{
|
|
2006
|
-
// We need to decrease kappa if
|
|
2007
|
-
// (1) The left boundary is not included, and
|
|
2008
|
-
// (2) delta is exactly equal to 10^kappa.
|
|
2009
|
-
// For symmetric boundary conditions, the first condition is
|
|
2010
|
-
// always true because we already have checked it,
|
|
2011
|
-
// and otherwise it is always false.
|
|
2012
|
-
// The second condition is true if and only if e = -(q-p-1).
|
|
2013
|
-
if constexpr (decltype(interval_type)::is_symmetric)
|
|
2014
|
-
{
|
|
2015
|
-
if (exponent == -int(extended_precision - precision - 1))
|
|
2016
|
-
{
|
|
2017
|
-
ret_value.significand *= 10;
|
|
2018
|
-
divisor /= 10;
|
|
2019
|
-
--ret_value.exponent;
|
|
2020
|
-
}
|
|
2021
|
-
}
|
|
2022
|
-
}
|
|
2023
|
-
break;
|
|
2024
|
-
}
|
|
2025
|
-
|
|
2026
|
-
ret_value.significand *= 10;
|
|
2027
|
-
divisor /= 10;
|
|
2028
|
-
--ret_value.exponent;
|
|
2029
|
-
}
|
|
2030
|
-
|
|
2031
|
-
if constexpr (CorrectRoundingSearch::tag ==
|
|
2032
|
-
grisu_exact_correct_rounding::do_not_care_tag ||
|
|
2033
|
-
IntervalTypeProvider::tag !=
|
|
2034
|
-
grisu_exact_rounding_modes::to_nearest_tag)
|
|
2035
|
-
{
|
|
2036
|
-
--ret_value.significand;
|
|
2037
|
-
}
|
|
2038
|
-
|
|
2039
|
-
if constexpr (CorrectRoundingSearch::tag !=
|
|
2040
|
-
grisu_exact_correct_rounding::do_not_care_tag &&
|
|
2041
|
-
IntervalTypeProvider::tag ==
|
|
2042
|
-
grisu_exact_rounding_modes::left_closed_directed_tag)
|
|
2043
|
-
{
|
|
2044
|
-
r = divisor;
|
|
2045
|
-
}
|
|
2046
|
-
|
|
2047
|
-
// For binary32 case, kappa == 0 case requires a separate correct rounding search
|
|
2048
|
-
if constexpr (CorrectRoundingSearch::tag !=
|
|
2049
|
-
grisu_exact_correct_rounding::do_not_care_tag &&
|
|
2050
|
-
IntervalTypeProvider::tag ==
|
|
2051
|
-
grisu_exact_rounding_modes::to_nearest_tag &&
|
|
2052
|
-
min_kappa == 0)
|
|
2053
|
-
{
|
|
2054
|
-
if (ret_value.exponent == minus_k) {
|
|
2055
|
-
goto correct_rounding_search_when_kappa_is_0_label;
|
|
2056
|
-
}
|
|
2057
|
-
}
|
|
2058
|
-
}
|
|
2059
|
-
}
|
|
2060
|
-
|
|
2061
|
-
//////////////////////////////////////////////////////////////////////
|
|
2062
|
-
// Step 4: Correct rounding search
|
|
2063
|
-
//////////////////////////////////////////////////////////////////////
|
|
2064
|
-
|
|
2065
|
-
// Just to silence "unused label" warnings
|
|
2066
|
-
goto correct_rounding_search_label;
|
|
2067
|
-
correct_rounding_search_label:
|
|
2068
|
-
if constexpr (CorrectRoundingSearch::tag !=
|
|
2069
|
-
grisu_exact_correct_rounding::do_not_care_tag &&
|
|
2070
|
-
IntervalTypeProvider::tag ==
|
|
2071
|
-
grisu_exact_rounding_modes::left_closed_directed_tag)
|
|
2072
|
-
{
|
|
2073
|
-
// We already know r is at most deltai
|
|
2074
|
-
deltai -= std::uint32_t(r);
|
|
2075
|
-
auto const approx_x = zi - deltai;
|
|
2076
|
-
|
|
2077
|
-
auto const current_digit = ret_value.significand % 10;
|
|
2078
|
-
|
|
2079
|
-
// Perform binary search to find the minimum
|
|
2080
|
-
auto steps = current_digit / 2;
|
|
2081
|
-
while (steps != 0) {
|
|
2082
|
-
auto const displacement = steps * divisor;
|
|
2083
|
-
if (displacement > deltai) {
|
|
2084
|
-
steps /= 2;
|
|
2085
|
-
}
|
|
2086
|
-
else if (displacement == deltai) {
|
|
2087
|
-
// Compare fractional parts
|
|
2088
|
-
// If zf <= deltaf, we can move to the left
|
|
2089
|
-
// Otherwise, we should back off by 1
|
|
2090
|
-
// The function is_zf_smaller_than_deltaf relies on
|
|
2091
|
-
// several assumptions that are not true here.
|
|
2092
|
-
// Hence, we need to do the comparison more carefully,
|
|
2093
|
-
// by comparing the parity of approx_x and xi.
|
|
2094
|
-
// x = (zi - deltai) + (zf - deltaf)
|
|
2095
|
-
switch (zf_vs_deltaf) {
|
|
2096
|
-
case zf_vs_deltaf_t::not_compared_yet:
|
|
2097
|
-
// zf >= deltaf ?
|
|
2098
|
-
if ((compute_mul(significand, cache, minus_beta) & 1) == (approx_x & 1))
|
|
2099
|
-
{
|
|
2100
|
-
// zf > deltaf ?
|
|
2101
|
-
if (!equal_fractional_parts<IntervalTypeProvider::tag>(
|
|
2102
|
-
significand, exponent, minus_k))
|
|
2103
|
-
{
|
|
2104
|
-
--steps;
|
|
2105
|
-
}
|
|
2106
|
-
}
|
|
2107
|
-
break;
|
|
2108
|
-
|
|
2109
|
-
case zf_vs_deltaf_t::zf_larger:
|
|
2110
|
-
--steps;
|
|
2111
|
-
break;
|
|
2112
|
-
|
|
2113
|
-
case zf_vs_deltaf_t::zf_smaller:
|
|
2114
|
-
break;
|
|
2115
|
-
}
|
|
2116
|
-
goto return_label;
|
|
2117
|
-
}
|
|
2118
|
-
else {
|
|
2119
|
-
ret_value.significand -= steps;
|
|
2120
|
-
deltai -= std::uint32_t(displacement);
|
|
2121
|
-
}
|
|
2122
|
-
}
|
|
2123
|
-
}
|
|
2124
|
-
else if constexpr (CorrectRoundingSearch::tag !=
|
|
2125
|
-
grisu_exact_correct_rounding::do_not_care_tag &&
|
|
2126
|
-
IntervalTypeProvider::tag ==
|
|
2127
|
-
grisu_exact_rounding_modes::to_nearest_tag)
|
|
2128
|
-
{
|
|
2129
|
-
// Should treat the case kappa == 0 separately
|
|
2130
|
-
assert(ret_value.exponent != minus_k);
|
|
2131
|
-
|
|
2132
|
-
// Distribution of n' with uniformly random data:
|
|
2133
|
-
// [binary32]
|
|
2134
|
-
// -1: 48.0% 0: 32.9% 1: 5.7% 2: 8.7%
|
|
2135
|
-
// 3: 3.9% 4: 0.9%
|
|
2136
|
-
// [binary64]
|
|
2137
|
-
// -1: 51.9% 0: 31.9% 1: 10.2% 2: 4.5%
|
|
2138
|
-
// 3: 1.4% 4: 0.1% 5: 0.0%
|
|
2139
|
-
auto const displacement = (divisor / 2) + r;
|
|
2140
|
-
auto epsiloni = compute_delta<grisu_exact_rounding_modes::left_closed_directed_tag>(
|
|
2141
|
-
false, cache, minus_beta + 1);
|
|
2142
|
-
|
|
2143
|
-
// n' + 1 >= 1?
|
|
2144
|
-
if (displacement <= epsiloni) {
|
|
2145
|
-
auto const approx_y = zi - epsiloni;
|
|
2146
|
-
|
|
2147
|
-
std::uint8_t steps;
|
|
2148
|
-
epsiloni -= std::uint32_t(displacement);
|
|
2149
|
-
|
|
2150
|
-
// At this point, we can be sure that divisor should be
|
|
2151
|
-
// at most 1'000'000'000, because
|
|
2152
|
-
// epsiloni < 4'294'967'296 < 5'000'000'000 = (10'000'000'000 / 2)
|
|
2153
|
-
// and epsiloni >= divisor / 2.
|
|
2154
|
-
// Hence, 2 * divisor can fit inside std::uint32_t.
|
|
2155
|
-
auto const divisor32 = std::uint32_t(divisor);
|
|
2156
|
-
|
|
2157
|
-
// n' + 1 >= 2?
|
|
2158
|
-
if (divisor32 <= epsiloni) {
|
|
2159
|
-
epsiloni -= divisor32;
|
|
2160
|
-
|
|
2161
|
-
// n' + 1 >= 4?
|
|
2162
|
-
if (2 * divisor32 <= epsiloni) {
|
|
2163
|
-
epsiloni -= 2 * divisor32;
|
|
2164
|
-
|
|
2165
|
-
// n' + 1 >= 5?
|
|
2166
|
-
if (divisor32 <= epsiloni) {
|
|
2167
|
-
epsiloni -= divisor32;
|
|
2168
|
-
|
|
2169
|
-
// For binary32, this implies that n' should be 4
|
|
2170
|
-
if constexpr (sizeof(Float) == 4) {
|
|
2171
|
-
steps = 5;
|
|
2172
|
-
}
|
|
2173
|
-
// For binary64, there are inputs such that
|
|
2174
|
-
// n' = 5, though extremely rare
|
|
2175
|
-
else {
|
|
2176
|
-
// n' + 1 = 6?
|
|
2177
|
-
if (divisor32 <= epsiloni) {
|
|
2178
|
-
epsiloni -= divisor32;
|
|
2179
|
-
steps = 6;
|
|
2180
|
-
}
|
|
2181
|
-
// n' + 1 = 5
|
|
2182
|
-
else {
|
|
2183
|
-
steps = 5;
|
|
2184
|
-
}
|
|
2185
|
-
}
|
|
2186
|
-
}
|
|
2187
|
-
// n' + 1 = 4
|
|
2188
|
-
else {
|
|
2189
|
-
steps = 4;
|
|
2190
|
-
}
|
|
2191
|
-
}
|
|
2192
|
-
// n' + 1 = 2 or 3
|
|
2193
|
-
else {
|
|
2194
|
-
// n' + 1 = 3?
|
|
2195
|
-
if (divisor32 <= epsiloni) {
|
|
2196
|
-
epsiloni -= divisor32;
|
|
2197
|
-
steps = 3;
|
|
2198
|
-
}
|
|
2199
|
-
// n' + 1 = 2
|
|
2200
|
-
else {
|
|
2201
|
-
steps = 2;
|
|
2202
|
-
}
|
|
2203
|
-
}
|
|
2204
|
-
}
|
|
2205
|
-
// n' + 1 = 1
|
|
2206
|
-
else {
|
|
2207
|
-
steps = 1;
|
|
2208
|
-
}
|
|
2209
|
-
|
|
2210
|
-
// Check fractional if necessary
|
|
2211
|
-
if (epsiloni == 0) {
|
|
2212
|
-
auto const yi = compute_mul(significand, cache, minus_beta);
|
|
2213
|
-
// We have either yi == approx_y or yi == approx_y - 1
|
|
2214
|
-
if (yi == approx_y) {
|
|
2215
|
-
if constexpr (CorrectRoundingSearch::tag ==
|
|
2216
|
-
grisu_exact_correct_rounding::tie_to_even_tag ||
|
|
2217
|
-
CorrectRoundingSearch::tag ==
|
|
2218
|
-
grisu_exact_correct_rounding::tie_to_odd_tag)
|
|
2219
|
-
{
|
|
2220
|
-
// Compare round-up vs round-down
|
|
2221
|
-
// round-up : steps - 1
|
|
2222
|
-
// round-down: steps - 1 if !is_product_integer, steps otherwise
|
|
2223
|
-
// If they differ, that is, if is_product_integer,
|
|
2224
|
-
// then prefer even/odd
|
|
2225
|
-
if (is_product_integer<integer_check_case_id::other>(significand, exponent, minus_k))
|
|
2226
|
-
{
|
|
2227
|
-
// steps vs steps - 1
|
|
2228
|
-
if constexpr (CorrectRoundingSearch::tag ==
|
|
2229
|
-
grisu_exact_correct_rounding::tie_to_even_tag)
|
|
2230
|
-
{
|
|
2231
|
-
steps = (ret_value.significand & 1) != extended_significand_type(steps & 1)
|
|
2232
|
-
? steps - 1 : steps;
|
|
2233
|
-
}
|
|
2234
|
-
else
|
|
2235
|
-
{
|
|
2236
|
-
steps = (ret_value.significand & 1) == extended_significand_type(steps & 1)
|
|
2237
|
-
? steps - 1 : steps;
|
|
2238
|
-
}
|
|
2239
|
-
}
|
|
2240
|
-
else {
|
|
2241
|
-
--steps;
|
|
2242
|
-
}
|
|
2243
|
-
}
|
|
2244
|
-
else if constexpr (CorrectRoundingSearch::tag ==
|
|
2245
|
-
grisu_exact_correct_rounding::tie_to_up_tag)
|
|
2246
|
-
{
|
|
2247
|
-
--steps;
|
|
2248
|
-
}
|
|
2249
|
-
else {
|
|
2250
|
-
if (!is_product_integer<integer_check_case_id::other>(significand, exponent, minus_k)) {
|
|
2251
|
-
--steps;
|
|
2252
|
-
}
|
|
2253
|
-
}
|
|
2254
|
-
}
|
|
2255
|
-
}
|
|
2256
|
-
|
|
2257
|
-
// The calculated steps might be too much if the left endpoint is closer than usual
|
|
2258
|
-
if (steps == 1 && significand == sign_bit_mask) {
|
|
2259
|
-
// We know already r is at most deltai
|
|
2260
|
-
deltai -= std::uint32_t(r);
|
|
2261
|
-
if (divisor > deltai) {
|
|
2262
|
-
goto return_label;
|
|
2263
|
-
}
|
|
2264
|
-
else if (divisor == deltai) {
|
|
2265
|
-
// See the test result of verify_incorrect_rounding_removal.cpp
|
|
2266
|
-
if constexpr (sizeof(Float) == 4) {
|
|
2267
|
-
if (exponent == 59) {
|
|
2268
|
-
goto return_label;
|
|
2269
|
-
}
|
|
2270
|
-
}
|
|
2271
|
-
else {
|
|
2272
|
-
if (exponent == -203) {
|
|
2273
|
-
goto return_label;
|
|
2274
|
-
}
|
|
2275
|
-
}
|
|
2276
|
-
}
|
|
2277
|
-
}
|
|
2278
|
-
|
|
2279
|
-
ret_value.significand -= steps;
|
|
2280
|
-
}
|
|
2281
|
-
}
|
|
2282
|
-
|
|
2283
|
-
goto return_label;
|
|
2284
|
-
|
|
2285
|
-
// Just to silence "unused label" warnings
|
|
2286
|
-
goto correct_rounding_search_when_kappa_is_0_label;
|
|
2287
|
-
correct_rounding_search_when_kappa_is_0_label:
|
|
2288
|
-
if constexpr (CorrectRoundingSearch::tag !=
|
|
2289
|
-
grisu_exact_correct_rounding::do_not_care_tag &&
|
|
2290
|
-
IntervalTypeProvider::tag ==
|
|
2291
|
-
grisu_exact_rounding_modes::to_nearest_tag &&
|
|
2292
|
-
min_kappa == 0)
|
|
2293
|
-
{
|
|
2294
|
-
// (floor(2y) + 1) / 2 for tie-to-up, ceil(2y) / 2 for tie-to-down
|
|
2295
|
-
// First, compute floor(2y)
|
|
2296
|
-
auto two_yi = compute_mul(significand, cache, minus_beta - 1);
|
|
2297
|
-
|
|
2298
|
-
if constexpr (CorrectRoundingSearch::tag ==
|
|
2299
|
-
grisu_exact_correct_rounding::tie_to_even_tag ||
|
|
2300
|
-
CorrectRoundingSearch::tag ==
|
|
2301
|
-
grisu_exact_correct_rounding::tie_to_odd_tag)
|
|
2302
|
-
{
|
|
2303
|
-
// Compare round-up vs round-down
|
|
2304
|
-
// round-up : (two_yi + 1) / 2
|
|
2305
|
-
// round-down: (two_yi + 1) / 2 if !is_prodict_integer, two_yi / 2 otherwise
|
|
2306
|
-
// If they can differ, that is, if is_product_integer,
|
|
2307
|
-
// then prefer even/odd
|
|
2308
|
-
if (is_product_integer<integer_check_case_id::two_times_fc>(
|
|
2309
|
-
significand, exponent, minus_k))
|
|
2310
|
-
{
|
|
2311
|
-
if constexpr (CorrectRoundingSearch::tag ==
|
|
2312
|
-
grisu_exact_correct_rounding::tie_to_even_tag)
|
|
2313
|
-
{
|
|
2314
|
-
ret_value.significand = (two_yi / 2) % 2 == 1 ?
|
|
2315
|
-
(two_yi + 1) / 2 : two_yi / 2;
|
|
2316
|
-
}
|
|
2317
|
-
else
|
|
2318
|
-
{
|
|
2319
|
-
ret_value.significand = (two_yi / 2) % 2 == 0 ?
|
|
2320
|
-
(two_yi + 1) / 2 : two_yi / 2;
|
|
2321
|
-
}
|
|
2322
|
-
}
|
|
2323
|
-
else {
|
|
2324
|
-
ret_value.significand = (two_yi + 1) / 2;
|
|
2325
|
-
}
|
|
2326
|
-
}
|
|
2327
|
-
else if constexpr (CorrectRoundingSearch::tag ==
|
|
2328
|
-
grisu_exact_correct_rounding::tie_to_up_tag)
|
|
2329
|
-
{
|
|
2330
|
-
ret_value.significand = (two_yi + 1) / 2;
|
|
2331
|
-
}
|
|
2332
|
-
else {
|
|
2333
|
-
if (!is_product_integer<integer_check_case_id::two_times_fc>(
|
|
2334
|
-
significand, exponent, minus_k))
|
|
2335
|
-
{
|
|
2336
|
-
++two_yi;
|
|
2337
|
-
}
|
|
2338
|
-
|
|
2339
|
-
ret_value.significand = two_yi / 2;
|
|
2340
|
-
}
|
|
2341
|
-
}
|
|
2342
|
-
|
|
2343
|
-
return_label:
|
|
2344
|
-
return ret_value;
|
|
2345
|
-
}
|
|
2346
|
-
|
|
2347
|
-
static extended_significand_type compute_mul(
|
|
2348
|
-
extended_significand_type f, cache_entry_type const& cache, int minus_beta) noexcept
|
|
2349
|
-
{
|
|
2350
|
-
if constexpr (sizeof(Float) == 4) {
|
|
2351
|
-
return umul96_upper32(f, cache) >> minus_beta;
|
|
2352
|
-
}
|
|
2353
|
-
else {
|
|
2354
|
-
return umul192_upper64(f, cache) >> minus_beta;
|
|
2355
|
-
}
|
|
2356
|
-
}
|
|
2357
|
-
|
|
2358
|
-
template <grisu_exact_rounding_modes::tag_t tag>
|
|
2359
|
-
static std::uint32_t compute_delta([[maybe_unused]] bool is_edge_case,
|
|
2360
|
-
cache_entry_type const& cache, int minus_beta) noexcept
|
|
2361
|
-
{
|
|
2362
|
-
constexpr auto q_mp_m1 = extended_precision - precision - 1;
|
|
2363
|
-
constexpr auto intermediate_precision =
|
|
2364
|
-
sizeof(Float) == 4 ? cache_precision : extended_precision;
|
|
2365
|
-
using intermediate_type = std::conditional_t<sizeof(Float) == 4,
|
|
2366
|
-
cache_entry_type, extended_significand_type>;
|
|
2367
|
-
|
|
2368
|
-
intermediate_type r;
|
|
2369
|
-
if constexpr (sizeof(Float) == 4) {
|
|
2370
|
-
r = cache;
|
|
2371
|
-
}
|
|
2372
|
-
else {
|
|
2373
|
-
r = cache.high();
|
|
2374
|
-
}
|
|
2375
|
-
|
|
2376
|
-
// For nearest rounding
|
|
2377
|
-
if constexpr (tag == grisu_exact_rounding_modes::to_nearest_tag)
|
|
2378
|
-
{
|
|
2379
|
-
if (is_edge_case) {
|
|
2380
|
-
r = (r >> 1) + (r >> 2);
|
|
2381
|
-
}
|
|
2382
|
-
|
|
2383
|
-
return std::uint32_t(r >> (intermediate_precision - q_mp_m1 + minus_beta));
|
|
2384
|
-
}
|
|
2385
|
-
// For left-directed rounding
|
|
2386
|
-
else if constexpr (tag == grisu_exact_rounding_modes::left_closed_directed_tag)
|
|
2387
|
-
{
|
|
2388
|
-
return std::uint32_t(r >> (intermediate_precision - q_mp_m1 + minus_beta));
|
|
2389
|
-
}
|
|
2390
|
-
// For right-directed rounding
|
|
2391
|
-
else {
|
|
2392
|
-
if (is_edge_case) {
|
|
2393
|
-
return std::uint32_t(r >> (intermediate_precision - (q_mp_m1 - 1) + minus_beta));
|
|
2394
|
-
}
|
|
2395
|
-
else {
|
|
2396
|
-
return std::uint32_t(r >> (intermediate_precision - q_mp_m1 + minus_beta));
|
|
2397
|
-
}
|
|
2398
|
-
}
|
|
2399
|
-
}
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
static bool is_zf_strictly_smaller_than_deltaf(
|
|
2403
|
-
extended_significand_type fl,
|
|
2404
|
-
int minus_beta, cache_entry_type const& cache) noexcept
|
|
2405
|
-
{
|
|
2406
|
-
auto mul = compute_mul(fl, cache, minus_beta);
|
|
2407
|
-
return (mul & 1) != 0;
|
|
2408
|
-
}
|
|
2409
|
-
|
|
2410
|
-
enum class integer_check_case_id {
|
|
2411
|
-
fc_minus_2_to_the_q_mp_m3_edge,
|
|
2412
|
-
fc_pm_2_to_the_q_mp_m2_generic,
|
|
2413
|
-
fc_pm_2_to_the_q_mp_m2_edge,
|
|
2414
|
-
two_times_fc,
|
|
2415
|
-
other
|
|
2416
|
-
};
|
|
2417
|
-
template <integer_check_case_id case_id>
|
|
2418
|
-
static bool is_product_integer([[maybe_unused]] extended_significand_type f,
|
|
2419
|
-
int exponent, [[maybe_unused]] int minus_k) noexcept
|
|
2420
|
-
{
|
|
2421
|
-
// Case I: f = fc - 2^(q-p-3), Fw = 1 and Ew != Emin
|
|
2422
|
-
if constexpr (case_id == integer_check_case_id::fc_minus_2_to_the_q_mp_m3_edge) {
|
|
2423
|
-
return exponent >= integer_check_exponent_lower_bound_for_q_mp_m3 &&
|
|
2424
|
-
exponent <= max_exponent_for_k_geq_0;
|
|
2425
|
-
}
|
|
2426
|
-
// Case II: f = fc +- 2^(q-p-2), generic case
|
|
2427
|
-
else if constexpr (case_id == integer_check_case_id::fc_pm_2_to_the_q_mp_m2_generic) {
|
|
2428
|
-
if (exponent < integer_check_exponent_lower_bound_for_q_mp_m2) {
|
|
2429
|
-
return false;
|
|
2430
|
-
}
|
|
2431
|
-
// For k >= 0
|
|
2432
|
-
else if (exponent <= max_exponent_for_k_geq_0) {
|
|
2433
|
-
return true;
|
|
2434
|
-
}
|
|
2435
|
-
// For k < 0
|
|
2436
|
-
else if (exponent <= integer_check_exponent_upper_bound_for_p_p2)
|
|
2437
|
-
{
|
|
2438
|
-
assert((sizeof(Float) == 4 && 1 <= minus_k && minus_k <= 10) ||
|
|
2439
|
-
(sizeof(Float) == 8 && 1 <= minus_k && minus_k <= 23));
|
|
2440
|
-
return divisible_by_power_of_5(f, minus_k);
|
|
2441
|
-
}
|
|
2442
|
-
else {
|
|
2443
|
-
return false;
|
|
2444
|
-
}
|
|
2445
|
-
}
|
|
2446
|
-
// Case III: f = fc - 2^(q-p-2), Fw = 1 and Ew != Emin
|
|
2447
|
-
else if constexpr (case_id == integer_check_case_id::fc_pm_2_to_the_q_mp_m2_edge) {
|
|
2448
|
-
// For IEEE-754 binary32
|
|
2449
|
-
if constexpr (sizeof(Float) == 4) {
|
|
2450
|
-
return exponent >= integer_check_exponent_lower_bound_for_q_mp_m2 &&
|
|
2451
|
-
exponent <= max_exponent_for_k_geq_m1;
|
|
2452
|
-
}
|
|
2453
|
-
// For IEEE-754 binary64
|
|
2454
|
-
else {
|
|
2455
|
-
return exponent >= integer_check_exponent_lower_bound_for_q_mp_m2 &&
|
|
2456
|
-
exponent <= max_exponent_for_k_geq_0;
|
|
2457
|
-
}
|
|
2458
|
-
}
|
|
2459
|
-
// Case IV or V or VI: f = fc or fc +- 2^(q-p-1)
|
|
2460
|
-
else {
|
|
2461
|
-
constexpr auto exp_2_upper_bound =
|
|
2462
|
-
case_id == integer_check_case_id::two_times_fc ?
|
|
2463
|
-
integer_check_exponent_lower_bound_for_q_mp :
|
|
2464
|
-
integer_check_exponent_lower_bound_for_q_mp_m1;
|
|
2465
|
-
|
|
2466
|
-
// Exponent for 2 is negative
|
|
2467
|
-
if (exponent < exp_2_upper_bound) {
|
|
2468
|
-
auto exp_2 = minus_k - exponent;
|
|
2469
|
-
if constexpr (case_id == integer_check_case_id::two_times_fc) {
|
|
2470
|
-
--exp_2;
|
|
2471
|
-
}
|
|
2472
|
-
return divisible_by_power_of_2(f, exp_2);
|
|
2473
|
-
}
|
|
2474
|
-
// Both exponents for 2 and 5 are nonnegative
|
|
2475
|
-
else if (exponent <= max_exponent_for_k_geq_0) {
|
|
2476
|
-
return true;
|
|
2477
|
-
}
|
|
2478
|
-
// Exponent for 5 is negative
|
|
2479
|
-
else if (exponent <= integer_check_exponent_upper_bound_for_p_p1) {
|
|
2480
|
-
assert((sizeof(Float) == 4 && 1 <= minus_k && minus_k <= 10) ||
|
|
2481
|
-
(sizeof(Float) == 8 && 1 <= minus_k && minus_k <= 22));
|
|
2482
|
-
return divisible_by_power_of_5(f, minus_k);
|
|
2483
|
-
}
|
|
2484
|
-
else {
|
|
2485
|
-
return false;
|
|
2486
|
-
}
|
|
2487
|
-
}
|
|
2488
|
-
}
|
|
2489
|
-
|
|
2490
|
-
enum class zf_vs_deltaf_t : std::uint8_t {
|
|
2491
|
-
not_compared_yet = 0,
|
|
2492
|
-
zf_larger = 1,
|
|
2493
|
-
zf_smaller = 2
|
|
2494
|
-
};
|
|
2495
|
-
|
|
2496
|
-
template <grisu_exact_rounding_modes::tag_t tag>
|
|
2497
|
-
static bool equal_fractional_parts([[maybe_unused]] extended_significand_type fl,
|
|
2498
|
-
[[maybe_unused]] int exponent, [[maybe_unused]] int minus_k) noexcept
|
|
2499
|
-
{
|
|
2500
|
-
if constexpr (tag == grisu_exact_rounding_modes::to_nearest_tag)
|
|
2501
|
-
{
|
|
2502
|
-
// Generic case
|
|
2503
|
-
if (fl != (sign_bit_mask - edge_case_boundary_bit))
|
|
2504
|
-
{
|
|
2505
|
-
return is_product_integer<integer_check_case_id::fc_pm_2_to_the_q_mp_m2_generic>(
|
|
2506
|
-
fl, exponent, minus_k);
|
|
2507
|
-
}
|
|
2508
|
-
// Edge case
|
|
2509
|
-
else {
|
|
2510
|
-
return is_product_integer<integer_check_case_id::fc_minus_2_to_the_q_mp_m3_edge>(
|
|
2511
|
-
fl, exponent, minus_k);
|
|
2512
|
-
}
|
|
2513
|
-
}
|
|
2514
|
-
// For left-closed directed rounding
|
|
2515
|
-
else if constexpr (tag == grisu_exact_rounding_modes::left_closed_directed_tag)
|
|
2516
|
-
{
|
|
2517
|
-
// Returns zf_smaller if zf = deltaf
|
|
2518
|
-
return is_product_integer<integer_check_case_id::other>(
|
|
2519
|
-
fl, exponent, minus_k);
|
|
2520
|
-
}
|
|
2521
|
-
// For right-closed directed rounding
|
|
2522
|
-
else {
|
|
2523
|
-
// Since left endpoint is always not included,
|
|
2524
|
-
// we do not actually have to call this function at all
|
|
2525
|
-
return false;
|
|
2526
|
-
}
|
|
2527
|
-
}
|
|
2528
|
-
|
|
2529
|
-
template <grisu_exact_rounding_modes::tag_t tag, class IntervalType>
|
|
2530
|
-
static bool is_zf_smaller_than_deltaf(extended_significand_type fc,
|
|
2531
|
-
int minus_beta, cache_entry_type const& cache,
|
|
2532
|
-
IntervalType& interval_type, int exponent, int minus_k) noexcept
|
|
2533
|
-
{
|
|
2534
|
-
// Compute fl
|
|
2535
|
-
extended_significand_type fl;
|
|
2536
|
-
if constexpr (tag == grisu_exact_rounding_modes::to_nearest_tag)
|
|
2537
|
-
{
|
|
2538
|
-
fl = (fc == sign_bit_mask && exponent != min_exponent) ?
|
|
2539
|
-
sign_bit_mask - edge_case_boundary_bit :
|
|
2540
|
-
fc - boundary_bit;
|
|
2541
|
-
}
|
|
2542
|
-
// For left-closed directed rounding
|
|
2543
|
-
else if constexpr (tag == grisu_exact_rounding_modes::left_closed_directed_tag)
|
|
2544
|
-
{
|
|
2545
|
-
fl = fc;
|
|
2546
|
-
}
|
|
2547
|
-
// For right-closed directed rounding
|
|
2548
|
-
else {
|
|
2549
|
-
fl = (fc == sign_bit_mask && exponent != min_exponent) ?
|
|
2550
|
-
sign_bit_mask - boundary_bit :
|
|
2551
|
-
fc - normal_interval_length;
|
|
2552
|
-
}
|
|
2553
|
-
|
|
2554
|
-
return is_zf_strictly_smaller_than_deltaf(fl, minus_beta, cache) ||
|
|
2555
|
-
(interval_type.include_left_endpoint() &&
|
|
2556
|
-
equal_fractional_parts<tag>(fl, exponent, minus_k));
|
|
2557
|
-
}
|
|
2558
|
-
|
|
2559
|
-
// Perform binary search to find kappa upward
|
|
2560
|
-
// Returns true if kappa + lambda is a possible candidate
|
|
2561
|
-
template <extended_significand_type lambda,
|
|
2562
|
-
grisu_exact_rounding_modes::tag_t tag,
|
|
2563
|
-
bool is_initial_search, bool is_signed, class IntervalType
|
|
2564
|
-
>
|
|
2565
|
-
static bool increasing_search(
|
|
2566
|
-
fp_t<Float, is_signed>& ret_value,
|
|
2567
|
-
IntervalType& interval_type,
|
|
2568
|
-
zf_vs_deltaf_t& zf_vs_deltaf,
|
|
2569
|
-
int exponent, int minus_k, int minus_beta,
|
|
2570
|
-
extended_significand_type fc,
|
|
2571
|
-
extended_significand_type& r,
|
|
2572
|
-
extended_significand_type& divisor,
|
|
2573
|
-
std::uint32_t deltai,
|
|
2574
|
-
cache_entry_type const& cache) noexcept
|
|
2575
|
-
{
|
|
2576
|
-
auto const quotient = ret_value.significand / power_of_10<lambda>;
|
|
2577
|
-
auto const new_r = r + divisor * (ret_value.significand % power_of_10<lambda>);
|
|
2578
|
-
|
|
2579
|
-
// Check if delta is still greater than or equal to the remainder
|
|
2580
|
-
// delta should be strictly greater if the left boundary is not contained
|
|
2581
|
-
if (new_r > deltai) {
|
|
2582
|
-
return false;
|
|
2583
|
-
}
|
|
2584
|
-
else if (new_r == deltai) {
|
|
2585
|
-
if constexpr (is_initial_search) {
|
|
2586
|
-
// zf_vs_deltaf cannot be zf_larger here
|
|
2587
|
-
if (zf_vs_deltaf == zf_vs_deltaf_t::not_compared_yet) {
|
|
2588
|
-
if (!is_zf_smaller_than_deltaf<tag>(fc,
|
|
2589
|
-
minus_beta, cache, interval_type, exponent, minus_k))
|
|
2590
|
-
{
|
|
2591
|
-
zf_vs_deltaf = zf_vs_deltaf_t::zf_larger;
|
|
2592
|
-
return false;
|
|
2593
|
-
}
|
|
2594
|
-
zf_vs_deltaf = zf_vs_deltaf_t::zf_smaller;
|
|
2595
|
-
}
|
|
2596
|
-
}
|
|
2597
|
-
else {
|
|
2598
|
-
switch (zf_vs_deltaf) {
|
|
2599
|
-
case zf_vs_deltaf_t::not_compared_yet:
|
|
2600
|
-
if (!is_zf_smaller_than_deltaf<tag>(fc,
|
|
2601
|
-
minus_beta, cache, interval_type, exponent, minus_k))
|
|
2602
|
-
{
|
|
2603
|
-
zf_vs_deltaf = zf_vs_deltaf_t::zf_larger;
|
|
2604
|
-
return false;
|
|
2605
|
-
}
|
|
2606
|
-
zf_vs_deltaf = zf_vs_deltaf_t::zf_smaller;
|
|
2607
|
-
break;
|
|
2608
|
-
|
|
2609
|
-
case zf_vs_deltaf_t::zf_larger:
|
|
2610
|
-
return false;
|
|
2611
|
-
|
|
2612
|
-
case zf_vs_deltaf_t::zf_smaller:
|
|
2613
|
-
// Do nothing; just to silence the warning
|
|
2614
|
-
break;
|
|
2615
|
-
}
|
|
2616
|
-
}
|
|
2617
|
-
}
|
|
2618
|
-
|
|
2619
|
-
// Update kappa
|
|
2620
|
-
ret_value.significand = quotient;
|
|
2621
|
-
ret_value.exponent += lambda;
|
|
2622
|
-
r = new_r;
|
|
2623
|
-
divisor *= power_of_10<lambda>;
|
|
2624
|
-
return true;
|
|
2625
|
-
}
|
|
2626
|
-
};
|
|
2627
|
-
}
|
|
2628
|
-
|
|
2629
|
-
// What to do with non-finite inputs?
|
|
2630
|
-
namespace grisu_exact_case_handlers {
|
|
2631
|
-
struct assert_finite {
|
|
2632
|
-
template <class Float>
|
|
2633
|
-
void operator()([[maybe_unused]] bit_representation_t<Float> br) const
|
|
2634
|
-
{
|
|
2635
|
-
assert(br.is_finite());
|
|
2636
|
-
}
|
|
2637
|
-
};
|
|
2638
|
-
|
|
2639
|
-
// This policy is mainly for debugging purpose
|
|
2640
|
-
struct ignore_special_cases {
|
|
2641
|
-
template <class Float>
|
|
2642
|
-
void operator()(bit_representation_t<Float>) const
|
|
2643
|
-
{
|
|
2644
|
-
}
|
|
2645
|
-
};
|
|
2646
|
-
}
|
|
2647
|
-
|
|
2648
|
-
template <bool return_sign = true, class Float,
|
|
2649
|
-
class RoundingMode = grisu_exact_rounding_modes::nearest_to_even,
|
|
2650
|
-
class CorrectRoundingSearch = grisu_exact_correct_rounding::tie_to_even,
|
|
2651
|
-
class CaseHandler = grisu_exact_case_handlers::assert_finite
|
|
2652
|
-
>
|
|
2653
|
-
fp_t<Float, return_sign> grisu_exact(Float x,
|
|
2654
|
-
RoundingMode&& rounding_mode = {},
|
|
2655
|
-
CorrectRoundingSearch&& crs = {},
|
|
2656
|
-
CaseHandler&& case_handler = {})
|
|
2657
|
-
{
|
|
2658
|
-
auto br = get_bit_representation(x);
|
|
2659
|
-
case_handler(br);
|
|
2660
|
-
return std::forward<RoundingMode>(rounding_mode).template delegate<return_sign>(
|
|
2661
|
-
br, std::forward<CorrectRoundingSearch>(crs));
|
|
2662
|
-
}
|
|
2663
|
-
}
|
|
2664
|
-
|
|
2665
|
-
#undef JKJ_SAFEBUFFERS
|
|
2666
|
-
#endif
|