summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorthegeorg <[email protected]>2025-05-07 11:09:12 +0300
committerthegeorg <[email protected]>2025-05-07 11:25:22 +0300
commit4c98f14a2491da2bc1a9d40fed1d1682c7ec5dd6 (patch)
tree8142081775c27c8780fa0282a0273ee268e13b98
parent40b86c68b431bb65d67bba51ef9159066a833b68 (diff)
Update contrib/restricted/boost/locale to 1.88.0
commit_hash:87b595328ea79c6ba38cb973580804486ca4a3ff
-rw-r--r--contrib/restricted/boost/charconv/.yandex_meta/__init__.py20
-rw-r--r--contrib/restricted/boost/charconv/.yandex_meta/default.nix13
-rw-r--r--contrib/restricted/boost/charconv/.yandex_meta/devtools.copyrights.report196
-rw-r--r--contrib/restricted/boost/charconv/.yandex_meta/devtools.licenses.report216
-rw-r--r--contrib/restricted/boost/charconv/.yandex_meta/licenses.list.txt102
-rw-r--r--contrib/restricted/boost/charconv/LICENSE23
-rw-r--r--contrib/restricted/boost/charconv/README.md148
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv.hpp12
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/chars_format.hpp22
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/config.hpp39
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/apply_sign.hpp50
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/bit_layouts.hpp160
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/buffer_sizing.hpp72
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/compute_float32.hpp55
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/compute_float64.hpp201
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/compute_float80.hpp114
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/config.hpp191
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/dragonbox/dragonbox.hpp2752
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/dragonbox/dragonbox_common.hpp829
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/dragonbox/floff.hpp4044
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/emulated128.hpp1005
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/fallback_routines.hpp245
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/ascii_number.hpp288
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/bigint.hpp623
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/constexpr_feature_detect.hpp47
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/decimal_to_binary.hpp196
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/digit_comparison.hpp442
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/fast_float.hpp48
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/fast_table.hpp708
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/float_common.hpp628
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/parse_number.hpp247
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/from_chars_integer_impl.hpp333
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/from_chars_result.hpp41
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/integer_search_trees.hpp274
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/issignaling.hpp85
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/memcpy.hpp78
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/parser.hpp471
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/ryu/generic_128.hpp558
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/ryu/ryu_generic_128.hpp767
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/significand_tables.hpp691
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/to_chars_integer_impl.hpp459
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/to_chars_result.hpp34
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/detail/type_traits.hpp67
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/from_chars.hpp255
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/limits.hpp96
-rw-r--r--contrib/restricted/boost/charconv/include/boost/charconv/to_chars.hpp147
-rw-r--r--contrib/restricted/boost/charconv/ya.make31
-rw-r--r--contrib/restricted/boost/locale/.yandex_meta/__init__.py4
-rw-r--r--contrib/restricted/boost/locale/.yandex_meta/default.nix4
-rw-r--r--contrib/restricted/boost/locale/.yandex_meta/devtools.copyrights.report300
-rw-r--r--contrib/restricted/boost/locale/.yandex_meta/devtools.licenses.report243
-rw-r--r--contrib/restricted/boost/locale/.yandex_meta/licenses.list.txt31
-rw-r--r--contrib/restricted/boost/locale/README.md4
-rw-r--r--contrib/restricted/boost/locale/include/boost/locale/boundary/boundary_point.hpp2
-rw-r--r--contrib/restricted/boost/locale/include/boost/locale/boundary/index.hpp4
-rw-r--r--contrib/restricted/boost/locale/include/boost/locale/boundary/segment.hpp2
-rw-r--r--contrib/restricted/boost/locale/include/boost/locale/config.hpp5
-rw-r--r--contrib/restricted/boost/locale/include/boost/locale/detail/any_string.hpp8
-rw-r--r--contrib/restricted/boost/locale/include/boost/locale/detail/encoding.hpp6
-rw-r--r--contrib/restricted/boost/locale/include/boost/locale/encoding.hpp11
-rw-r--r--contrib/restricted/boost/locale/include/boost/locale/format.hpp4
-rw-r--r--contrib/restricted/boost/locale/include/boost/locale/formatting.hpp2
-rw-r--r--contrib/restricted/boost/locale/include/boost/locale/generator.hpp3
-rw-r--r--contrib/restricted/boost/locale/include/boost/locale/gnu_gettext.hpp5
-rw-r--r--contrib/restricted/boost/locale/include/boost/locale/message.hpp2
-rw-r--r--contrib/restricted/boost/locale/include/boost/locale/util/locale_data.hpp11
-rw-r--r--contrib/restricted/boost/locale/src/boost/locale/icu/time_zone.cpp212
-rw-r--r--contrib/restricted/boost/locale/src/encoding/codepage.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/encoding/codepage.cpp)12
-rw-r--r--contrib/restricted/boost/locale/src/encoding/iconv_converter.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/encoding/iconv_converter.hpp)4
-rw-r--r--contrib/restricted/boost/locale/src/encoding/uconv_converter.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/encoding/uconv_converter.hpp)4
-rw-r--r--contrib/restricted/boost/locale/src/encoding/wconv_converter.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/encoding/wconv_converter.hpp)2
-rw-r--r--contrib/restricted/boost/locale/src/icu/all_generator.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/icu/all_generator.hpp)0
-rw-r--r--contrib/restricted/boost/locale/src/icu/boundary.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/icu/boundary.cpp)12
-rw-r--r--contrib/restricted/boost/locale/src/icu/cdata.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/icu/cdata.hpp)0
-rw-r--r--contrib/restricted/boost/locale/src/icu/codecvt.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/icu/codecvt.cpp)14
-rw-r--r--contrib/restricted/boost/locale/src/icu/codecvt.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/icu/codecvt.hpp)0
-rw-r--r--contrib/restricted/boost/locale/src/icu/collator.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/icu/collator.cpp)25
-rw-r--r--contrib/restricted/boost/locale/src/icu/conversion.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/icu/conversion.cpp)29
-rw-r--r--contrib/restricted/boost/locale/src/icu/date_time.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/icu/date_time.cpp)31
-rw-r--r--contrib/restricted/boost/locale/src/icu/formatter.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/icu/formatter.cpp)85
-rw-r--r--contrib/restricted/boost/locale/src/icu/formatter.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/icu/formatter.hpp)6
-rw-r--r--contrib/restricted/boost/locale/src/icu/formatters_cache.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/icu/formatters_cache.cpp)16
-rw-r--r--contrib/restricted/boost/locale/src/icu/formatters_cache.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/icu/formatters_cache.hpp)2
-rw-r--r--contrib/restricted/boost/locale/src/icu/icu_backend.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/icu/icu_backend.cpp)10
-rw-r--r--contrib/restricted/boost/locale/src/icu/icu_backend.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/icu/icu_backend.hpp)0
-rw-r--r--contrib/restricted/boost/locale/src/icu/icu_util.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/icu/icu_util.hpp)0
-rw-r--r--contrib/restricted/boost/locale/src/icu/numeric.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/icu/numeric.cpp)64
-rw-r--r--contrib/restricted/boost/locale/src/icu/time_zone.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/icu/time_zone.hpp)14
-rw-r--r--contrib/restricted/boost/locale/src/icu/uconv.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/icu/uconv.hpp)2
-rw-r--r--contrib/restricted/boost/locale/src/posix/all_generator.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/posix/all_generator.hpp)0
-rw-r--r--contrib/restricted/boost/locale/src/posix/codecvt.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/posix/codecvt.cpp)6
-rw-r--r--contrib/restricted/boost/locale/src/posix/collate.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/posix/collate.cpp)5
-rw-r--r--contrib/restricted/boost/locale/src/posix/converter.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/posix/converter.cpp)6
-rw-r--r--contrib/restricted/boost/locale/src/posix/numeric.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/posix/numeric.cpp)4
-rw-r--r--contrib/restricted/boost/locale/src/posix/posix_backend.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/posix/posix_backend.cpp)10
-rw-r--r--contrib/restricted/boost/locale/src/posix/posix_backend.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/posix/posix_backend.hpp)0
-rw-r--r--contrib/restricted/boost/locale/src/shared/date_time.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/shared/date_time.cpp)0
-rw-r--r--contrib/restricted/boost/locale/src/shared/format.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/shared/format.cpp)10
-rw-r--r--contrib/restricted/boost/locale/src/shared/formatting.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/shared/formatting.cpp)4
-rw-r--r--contrib/restricted/boost/locale/src/shared/generator.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/shared/generator.cpp)9
-rw-r--r--contrib/restricted/boost/locale/src/shared/iconv_codecvt.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/shared/iconv_codecvt.cpp)6
-rw-r--r--contrib/restricted/boost/locale/src/shared/iconv_codecvt.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/shared/iconv_codecvt.hpp)0
-rw-r--r--contrib/restricted/boost/locale/src/shared/ids.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/shared/ids.cpp)2
-rw-r--r--contrib/restricted/boost/locale/src/shared/ios_prop.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/shared/ios_prop.hpp)0
-rw-r--r--contrib/restricted/boost/locale/src/shared/localization_backend.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/shared/localization_backend.cpp)8
-rw-r--r--contrib/restricted/boost/locale/src/shared/message.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/shared/message.cpp)36
-rw-r--r--contrib/restricted/boost/locale/src/shared/message.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/shared/message.hpp)0
-rw-r--r--contrib/restricted/boost/locale/src/shared/mo_hash.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/shared/mo_hash.hpp)0
-rw-r--r--contrib/restricted/boost/locale/src/shared/mo_lambda.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/shared/mo_lambda.cpp)2
-rw-r--r--contrib/restricted/boost/locale/src/shared/mo_lambda.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/shared/mo_lambda.hpp)0
-rw-r--r--contrib/restricted/boost/locale/src/shared/std_collate_adapter.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/shared/std_collate_adapter.hpp)0
-rw-r--r--contrib/restricted/boost/locale/src/std/all_generator.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/std/all_generator.hpp)0
-rw-r--r--contrib/restricted/boost/locale/src/std/codecvt.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/std/codecvt.cpp)2
-rw-r--r--contrib/restricted/boost/locale/src/std/collate.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/std/collate.cpp)2
-rw-r--r--contrib/restricted/boost/locale/src/std/converter.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/std/converter.cpp)4
-rw-r--r--contrib/restricted/boost/locale/src/std/numeric.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/std/numeric.cpp)4
-rw-r--r--contrib/restricted/boost/locale/src/std/std_backend.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/std/std_backend.cpp)16
-rw-r--r--contrib/restricted/boost/locale/src/std/std_backend.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/std/std_backend.hpp)0
-rw-r--r--contrib/restricted/boost/locale/src/util/codecvt_converter.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/util/codecvt_converter.cpp)4
-rw-r--r--contrib/restricted/boost/locale/src/util/default_locale.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/util/default_locale.cpp)0
-rw-r--r--contrib/restricted/boost/locale/src/util/encoding.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/util/encoding.cpp)12
-rw-r--r--contrib/restricted/boost/locale/src/util/encoding.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/util/encoding.hpp)10
-rw-r--r--contrib/restricted/boost/locale/src/util/foreach_char.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/util/foreach_char.hpp)2
-rw-r--r--contrib/restricted/boost/locale/src/util/gregorian.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/util/gregorian.cpp)4
-rw-r--r--contrib/restricted/boost/locale/src/util/gregorian.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/util/gregorian.hpp)0
-rw-r--r--contrib/restricted/boost/locale/src/util/iconv.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/util/iconv.hpp)0
-rw-r--r--contrib/restricted/boost/locale/src/util/info.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/util/info.cpp)0
-rw-r--r--contrib/restricted/boost/locale/src/util/locale_data.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/util/locale_data.cpp)79
-rw-r--r--contrib/restricted/boost/locale/src/util/make_std_unique.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/util/make_std_unique.hpp)0
-rw-r--r--contrib/restricted/boost/locale/src/util/numeric.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/util/numeric.hpp)34
-rw-r--r--contrib/restricted/boost/locale/src/util/numeric_conversion.hpp147
-rw-r--r--contrib/restricted/boost/locale/src/util/timezone.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/util/timezone.hpp)0
-rw-r--r--contrib/restricted/boost/locale/src/util/win_codepages.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/util/win_codepages.hpp)0
-rw-r--r--contrib/restricted/boost/locale/src/win32/all_generator.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/win32/all_generator.hpp)0
-rw-r--r--contrib/restricted/boost/locale/src/win32/api.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/win32/api.hpp)2
-rw-r--r--contrib/restricted/boost/locale/src/win32/collate.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/win32/collate.cpp)6
-rw-r--r--contrib/restricted/boost/locale/src/win32/converter.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/win32/converter.cpp)6
-rw-r--r--contrib/restricted/boost/locale/src/win32/lcid.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/win32/lcid.cpp)2
-rw-r--r--contrib/restricted/boost/locale/src/win32/lcid.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/win32/lcid.hpp)0
-rw-r--r--contrib/restricted/boost/locale/src/win32/numeric.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/win32/numeric.cpp)6
-rw-r--r--contrib/restricted/boost/locale/src/win32/win_backend.cpp (renamed from contrib/restricted/boost/locale/src/boost/locale/win32/win_backend.cpp)12
-rw-r--r--contrib/restricted/boost/locale/src/win32/win_backend.hpp (renamed from contrib/restricted/boost/locale/src/boost/locale/win32/win_backend.hpp)0
-rw-r--r--contrib/restricted/boost/locale/ya.make87
143 files changed, 19028 insertions, 839 deletions
diff --git a/contrib/restricted/boost/charconv/.yandex_meta/__init__.py b/contrib/restricted/boost/charconv/.yandex_meta/__init__.py
new file mode 100644
index 00000000000..9cd73a5e8d1
--- /dev/null
+++ b/contrib/restricted/boost/charconv/.yandex_meta/__init__.py
@@ -0,0 +1,20 @@
+from devtools.yamaker import boost
+from devtools.yamaker.project import NixSourceProject
+
+
+def post_install(self):
+ self.yamakes["."] = boost.make_library(self)
+
+
+boost_charconv = NixSourceProject(
+ nixattr="boost_charconv",
+ arcdir=boost.make_arcdir("charconv"),
+ owners=["g:cpp-contrib", "g:taxi-common"],
+ copy_sources=[
+ "include/boost/",
+ ],
+ disable_includes=[
+ "stdfloat",
+ ],
+ post_install=post_install,
+)
diff --git a/contrib/restricted/boost/charconv/.yandex_meta/default.nix b/contrib/restricted/boost/charconv/.yandex_meta/default.nix
new file mode 100644
index 00000000000..84c6fec242e
--- /dev/null
+++ b/contrib/restricted/boost/charconv/.yandex_meta/default.nix
@@ -0,0 +1,13 @@
+self: super: with self; {
+ boost_charconv = stdenv.mkDerivation rec {
+ pname = "boost_charconv";
+ version = "1.88.0";
+
+ src = fetchFromGitHub {
+ owner = "boostorg";
+ repo = "charconv";
+ rev = "boost-${version}";
+ hash = "sha256-/BT/McmmdetjDtaqwOKvmid6MthUqfzwfv1V/FXjqP8=";
+ };
+ };
+}
diff --git a/contrib/restricted/boost/charconv/.yandex_meta/devtools.copyrights.report b/contrib/restricted/boost/charconv/.yandex_meta/devtools.copyrights.report
new file mode 100644
index 00000000000..902429a44dc
--- /dev/null
+++ b/contrib/restricted/boost/charconv/.yandex_meta/devtools.copyrights.report
@@ -0,0 +1,196 @@
+# File format ($ symbol means the beginning of a line):
+#
+# $ # this message
+# $ # =======================
+# $ # comments (all commentaries should starts with some number of spaces and # symbol)
+# $ IGNORE_FILES {file1.ext1} {file2.ext2} - (optional) ignore listed files when generating license macro and credits
+# $ RENAME {original license id} TO {new license id} # user comments - (optional) use {new license id} instead {original license id} in ya.make files
+# $ # user comments
+# $
+# ${action} {license id} {license text hash}
+# $BELONGS ./ya/make/file/relative/path/1/ya.make ./ya/make/2/ya.make
+# ${all_file_action} filename
+# $ # user commentaries (many lines)
+# $ generated description - files with this license, license text... (some number of lines that starts with some number of spaces, do not modify)
+# ${action} {license spdx} {license text hash}
+# $BELONGS ./ya/make/file/relative/path/3/ya.make
+# ${all_file_action} filename
+# $ # user commentaries
+# $ generated description
+# $ ...
+#
+# You can modify action, all_file_action and add commentaries
+# Available actions:
+# keep - keep license in contrib and use in credits
+# skip - skip license
+# remove - remove all files with this license
+# rename - save license text/links into licenses texts file, but not store SPDX into LINCENSE macro. You should store correct license id into devtools.license.spdx.txt file
+#
+# {all file action} records will be generated when license text contains filename that exists on filesystem (in contrib directory)
+# We suppose that that files can contain some license info
+# Available all file actions:
+# FILE_IGNORE - ignore file (do nothing)
+# FILE_INCLUDE - include all file data into licenses text file
+# =======================
+
+KEEP COPYRIGHT_SERVICE_LABEL 0e29c20336773b79c29d48a3387695cf
+BELONGS ya.make
+ License text:
+ // Copyright 2022 Peter Dimov
+ // Copyright 2023 Matt Borland
+ // Copyright 2023 Junekey Jeon
+ // Distributed under the Boost Software License, Version 1.0.
+ // https://www.boost.org/LICENSE_1_0.txt
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ include/boost/charconv/to_chars.hpp [1:5]
+
+KEEP COPYRIGHT_SERVICE_LABEL 175f8970b1267cb559b66251e237f95e
+BELONGS ya.make
+ License text:
+ // Copyright 2020-2023 Junekey Jeon
+ // Copyright 2022 Peter Dimov
+ // Copyright 2023 Matt Borland
+ // Distributed under the Boost Software License, Version 1.0.
+ // https://www.boost.org/LICENSE_1_0.txt
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ include/boost/charconv/detail/to_chars_integer_impl.hpp [1:5]
+
+KEEP COPYRIGHT_SERVICE_LABEL 5bea22e8da8464acc8d9ab38156e45ce
+BELONGS ya.make
+ License text:
+ // Copyright 2024 Matt Borland
+ // Distributed under the Boost Software License, Version 1.0.
+ // https://www.boost.org/LICENSE_1_0.txt
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ include/boost/charconv/detail/buffer_sizing.hpp [1:3]
+ include/boost/charconv/detail/fallback_routines.hpp [1:3]
+
+KEEP COPYRIGHT_SERVICE_LABEL 6629d20784d6175b2277b7f2294eb136
+BELONGS ya.make
+ License text:
+ // Copyright 2020-2023 Daniel Lemire
+ // Copyright 2023 Matt Borland
+ // Distributed under the Boost Software License, Version 1.0.
+ // https://www.boost.org/LICENSE_1_0.txt
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ include/boost/charconv/detail/compute_float64.hpp [1:4]
+ include/boost/charconv/detail/emulated128.hpp [1:4]
+ include/boost/charconv/detail/fast_float/ascii_number.hpp [1:4]
+ include/boost/charconv/detail/fast_float/bigint.hpp [1:4]
+ include/boost/charconv/detail/fast_float/constexpr_feature_detect.hpp [1:4]
+ include/boost/charconv/detail/fast_float/decimal_to_binary.hpp [1:4]
+ include/boost/charconv/detail/fast_float/digit_comparison.hpp [1:4]
+ include/boost/charconv/detail/fast_float/fast_float.hpp [1:4]
+ include/boost/charconv/detail/fast_float/fast_table.hpp [1:4]
+ include/boost/charconv/detail/fast_float/float_common.hpp [1:4]
+ include/boost/charconv/detail/fast_float/parse_number.hpp [1:4]
+ include/boost/charconv/detail/significand_tables.hpp [1:4]
+
+KEEP COPYRIGHT_SERVICE_LABEL 9ffe57ee27b8ed11f13a2ad92594afe9
+BELONGS ya.make
+ License text:
+ // Copyright 2018 - 2023 Ulf Adams
+ // Copyright 2023 Matt Borland
+ // Distributed under the Boost Software License, Version 1.0.
+ // https://www.boost.org/LICENSE_1_0.txt
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ include/boost/charconv/detail/ryu/generic_128.hpp [1:4]
+ include/boost/charconv/detail/ryu/ryu_generic_128.hpp [1:4]
+
+KEEP COPYRIGHT_SERVICE_LABEL df56a08a51f11ebc1571263ab013bc25
+BELONGS ya.make
+ License text:
+ // Copyright 2022 Peter Dimov
+ // Distributed under the Boost Software License, Version 1.0.
+ // https://www.boost.org/LICENSE_1_0.txt
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ include/boost/charconv.hpp [4:6]
+ include/boost/charconv/config.hpp [4:7]
+ include/boost/charconv/detail/to_chars_integer_impl.hpp [1:5]
+ include/boost/charconv/from_chars.hpp [1:4]
+ include/boost/charconv/to_chars.hpp [1:5]
+
+KEEP COPYRIGHT_SERVICE_LABEL ed2a55914865861705ece89451296d32
+BELONGS ya.make
+ License text:
+ // Copyright 2020-2022 Junekey Jeon
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ include/boost/charconv/detail/dragonbox/dragonbox.hpp [1:1]
+ include/boost/charconv/detail/dragonbox/dragonbox_common.hpp [1:1]
+ include/boost/charconv/detail/dragonbox/floff.hpp [1:1]
+
+KEEP COPYRIGHT_SERVICE_LABEL fdba0502771598acb9f3611d2cd4bb09
+BELONGS ya.make
+ License text:
+ // Copyright 2023 Matt Borland
+ // Distributed under the Boost Software License, Version 1.0.
+ // https://www.boost.org/LICENSE_1_0.txt
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ include/boost/charconv/chars_format.hpp [1:3]
+ include/boost/charconv/config.hpp [4:7]
+ include/boost/charconv/detail/apply_sign.hpp [1:3]
+ include/boost/charconv/detail/bit_layouts.hpp [1:3]
+ include/boost/charconv/detail/compute_float32.hpp [1:3]
+ include/boost/charconv/detail/compute_float64.hpp [1:4]
+ include/boost/charconv/detail/compute_float80.hpp [1:3]
+ include/boost/charconv/detail/config.hpp [1:3]
+ include/boost/charconv/detail/dragonbox/dragonbox.hpp [18:20]
+ include/boost/charconv/detail/dragonbox/dragonbox_common.hpp [20:22]
+ include/boost/charconv/detail/dragonbox/floff.hpp [20:22]
+ include/boost/charconv/detail/emulated128.hpp [1:4]
+ include/boost/charconv/detail/fast_float/ascii_number.hpp [1:4]
+ include/boost/charconv/detail/fast_float/bigint.hpp [1:4]
+ include/boost/charconv/detail/fast_float/constexpr_feature_detect.hpp [1:4]
+ include/boost/charconv/detail/fast_float/decimal_to_binary.hpp [1:4]
+ include/boost/charconv/detail/fast_float/digit_comparison.hpp [1:4]
+ include/boost/charconv/detail/fast_float/fast_float.hpp [1:4]
+ include/boost/charconv/detail/fast_float/fast_table.hpp [1:4]
+ include/boost/charconv/detail/fast_float/float_common.hpp [1:4]
+ include/boost/charconv/detail/fast_float/parse_number.hpp [1:4]
+ include/boost/charconv/detail/from_chars_integer_impl.hpp [1:3]
+ include/boost/charconv/detail/from_chars_result.hpp [1:3]
+ include/boost/charconv/detail/integer_search_trees.hpp [1:3]
+ include/boost/charconv/detail/issignaling.hpp [1:3]
+ include/boost/charconv/detail/memcpy.hpp [1:3]
+ include/boost/charconv/detail/parser.hpp [1:3]
+ include/boost/charconv/detail/ryu/generic_128.hpp [1:4]
+ include/boost/charconv/detail/ryu/ryu_generic_128.hpp [1:4]
+ include/boost/charconv/detail/significand_tables.hpp [1:4]
+ include/boost/charconv/detail/to_chars_integer_impl.hpp [1:5]
+ include/boost/charconv/detail/to_chars_result.hpp [1:3]
+ include/boost/charconv/detail/type_traits.hpp [1:3]
+ include/boost/charconv/from_chars.hpp [1:4]
+ include/boost/charconv/limits.hpp [1:3]
+ include/boost/charconv/to_chars.hpp [1:5]
diff --git a/contrib/restricted/boost/charconv/.yandex_meta/devtools.licenses.report b/contrib/restricted/boost/charconv/.yandex_meta/devtools.licenses.report
new file mode 100644
index 00000000000..3430b38ab29
--- /dev/null
+++ b/contrib/restricted/boost/charconv/.yandex_meta/devtools.licenses.report
@@ -0,0 +1,216 @@
+# File format ($ symbol means the beginning of a line):
+#
+# $ # this message
+# $ # =======================
+# $ # comments (all commentaries should starts with some number of spaces and # symbol)
+# $ IGNORE_FILES {file1.ext1} {file2.ext2} - (optional) ignore listed files when generating license macro and credits
+# $ RENAME {original license id} TO {new license id} # user comments - (optional) use {new license id} instead {original license id} in ya.make files
+# $ # user comments
+# $
+# ${action} {license id} {license text hash}
+# $BELONGS ./ya/make/file/relative/path/1/ya.make ./ya/make/2/ya.make
+# ${all_file_action} filename
+# $ # user commentaries (many lines)
+# $ generated description - files with this license, license text... (some number of lines that starts with some number of spaces, do not modify)
+# ${action} {license spdx} {license text hash}
+# $BELONGS ./ya/make/file/relative/path/3/ya.make
+# ${all_file_action} filename
+# $ # user commentaries
+# $ generated description
+# $ ...
+#
+# You can modify action, all_file_action and add commentaries
+# Available actions:
+# keep - keep license in contrib and use in credits
+# skip - skip license
+# remove - remove all files with this license
+# rename - save license text/links into licenses texts file, but not store SPDX into LINCENSE macro. You should store correct license id into devtools.license.spdx.txt file
+#
+# {all file action} records will be generated when license text contains filename that exists on filesystem (in contrib directory)
+# We suppose that that files can contain some license info
+# Available all file actions:
+# FILE_IGNORE - ignore file (do nothing)
+# FILE_INCLUDE - include all file data into licenses text file
+# =======================
+
+KEEP Apache-2.0 2c3bc3726a0ef68dea2a008702f96131
+BELONGS ya.make
+ License text:
+ // (See accompanying file LICENSE-Apache or copy at
+ Scancode info:
+ Original SPDX id: Apache-2.0
+ Score : 90.00
+ Match type : TAG
+ Links : http://www.apache.org/licenses/, http://www.apache.org/licenses/LICENSE-2.0, https://spdx.org/licenses/Apache-2.0
+ Files with this license:
+ include/boost/charconv/detail/dragonbox/dragonbox.hpp [6:6]
+ include/boost/charconv/detail/dragonbox/dragonbox_common.hpp [6:6]
+ include/boost/charconv/detail/dragonbox/floff.hpp [6:6]
+
+KEEP BSL-1.0 2c7a3fa82e66676005cd4ee2608fd7d2
+BELONGS ya.make
+ Note: matched license text is too long. Read it in the source files.
+ Scancode info:
+ Original SPDX id: BSL-1.0
+ Score : 100.00
+ Match type : TEXT
+ Links : http://www.boost.org/LICENSE_1_0.txt, http://www.boost.org/users/license.html, https://spdx.org/licenses/BSL-1.0
+ Files with this license:
+ LICENSE [1:23]
+
+KEEP BSL-1.0 67d785c23d7b32d9a77d1123e74d8da2
+BELONGS ya.make
+ License text:
+ // the Boost Software License, Version 1.0.
+ // (See accompanying file LICENSE-Boost or copy at
+ // https://www.boost.org/LICENSE_1_0.txt)
+ Scancode info:
+ Original SPDX id: BSL-1.0
+ Score : 72.00
+ Match type : NOTICE
+ Links : http://www.boost.org/LICENSE_1_0.txt, http://www.boost.org/users/license.html, https://spdx.org/licenses/BSL-1.0
+ Files with this license:
+ include/boost/charconv/detail/dragonbox/dragonbox.hpp [10:12]
+ include/boost/charconv/detail/dragonbox/dragonbox_common.hpp [10:12]
+ include/boost/charconv/detail/dragonbox/floff.hpp [10:12]
+
+SKIP LicenseRef-scancode-warranty-disclaimer 92f6bc64e50f9371e66428f437beef7d
+BELONGS ya.make
+ # Not a license, but a warranty disclaimer
+ Note: matched license text is too long. Read it in the source files.
+ Scancode info:
+ Original SPDX id: LicenseRef-scancode-warranty-disclaimer
+ Score : 61.70
+ Match type : TEXT
+ Links : https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/warranty-disclaimer.LICENSE
+ Files with this license:
+ include/boost/charconv/detail/dragonbox/dragonbox.hpp [14:20]
+
+KEEP Apache-2.0 WITH LLVM-exception c6d514740e772226c6397fc13f9c7395
+BELONGS ya.make
+ License text:
+ // the Apache License v2.0 with LLVM Exceptions.
+ Scancode info:
+ Original SPDX id: Apache-2.0
+ Score : 100.00
+ Match type : NOTICE
+ Links : http://www.apache.org/licenses/, http://www.apache.org/licenses/LICENSE-2.0, https://spdx.org/licenses/Apache-2.0
+ Files with this license:
+ include/boost/charconv/detail/dragonbox/dragonbox.hpp [4:4]
+ include/boost/charconv/detail/dragonbox/dragonbox_common.hpp [4:4]
+ include/boost/charconv/detail/dragonbox/floff.hpp [4:4]
+ Scancode info:
+ Original SPDX id: LLVM-exception
+ Score : 100.00
+ Match type : NOTICE
+ Links : http://llvm.org/foundation/relicensing/LICENSE.txt, https://spdx.org/licenses/LLVM-exception
+ Files with this license:
+ include/boost/charconv/detail/dragonbox/dragonbox.hpp [4:4]
+ include/boost/charconv/detail/dragonbox/dragonbox_common.hpp [4:4]
+ include/boost/charconv/detail/dragonbox/floff.hpp [4:4]
+
+KEEP BSL-1.0 c9e6118e07afed16d6f26c06b5f29fe8
+BELONGS ya.make
+ License text:
+ // https://www.boost.org/LICENSE_1_0.txt
+ Scancode info:
+ Original SPDX id: BSL-1.0
+ Score : 100.00
+ Match type : REFERENCE
+ Links : http://www.boost.org/LICENSE_1_0.txt, http://www.boost.org/users/license.html, https://spdx.org/licenses/BSL-1.0
+ Files with this license:
+ include/boost/charconv/detail/apply_sign.hpp [3:3]
+ include/boost/charconv/detail/bit_layouts.hpp [3:3]
+ include/boost/charconv/detail/compute_float64.hpp [4:4]
+ include/boost/charconv/detail/config.hpp [3:3]
+ include/boost/charconv/detail/dragonbox/dragonbox.hpp [20:20]
+ include/boost/charconv/detail/dragonbox/dragonbox_common.hpp [22:22]
+ include/boost/charconv/detail/dragonbox/floff.hpp [22:22]
+ include/boost/charconv/detail/fallback_routines.hpp [3:3]
+ include/boost/charconv/detail/from_chars_result.hpp [3:3]
+ include/boost/charconv/detail/ryu/generic_128.hpp [4:4]
+ include/boost/charconv/detail/ryu/ryu_generic_128.hpp [4:4]
+ include/boost/charconv/detail/to_chars_result.hpp [3:3]
+ include/boost/charconv/from_chars.hpp [4:4]
+ include/boost/charconv/to_chars.hpp [5:5]
+
+SKIP LicenseRef-scancode-warranty-disclaimer d89f6d713ddca845d1eef6a38b0cf573
+BELONGS ya.make
+ # Not a license, but a warranty disclaimer
+ Note: matched license text is too long. Read it in the source files.
+ Scancode info:
+ Original SPDX id: LicenseRef-scancode-warranty-disclaimer
+ Score : 61.70
+ Match type : TEXT
+ Links : https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/warranty-disclaimer.LICENSE
+ Files with this license:
+ include/boost/charconv/detail/dragonbox/dragonbox_common.hpp [14:22]
+ include/boost/charconv/detail/dragonbox/floff.hpp [14:22]
+
+KEEP BSL-1.0 e03c043ca7052925e34194f3fe2631e4
+BELONGS ya.make
+ License text:
+ // Distributed under the Boost Software License, Version 1.0.
+ Scancode info:
+ Original SPDX id: BSL-1.0
+ Score : 100.00
+ Match type : NOTICE
+ Links : http://www.boost.org/LICENSE_1_0.txt, http://www.boost.org/users/license.html, https://spdx.org/licenses/BSL-1.0
+ Files with this license:
+ include/boost/charconv/detail/apply_sign.hpp [2:2]
+ include/boost/charconv/detail/bit_layouts.hpp [2:2]
+ include/boost/charconv/detail/compute_float64.hpp [3:3]
+ include/boost/charconv/detail/config.hpp [2:2]
+ include/boost/charconv/detail/dragonbox/dragonbox.hpp [19:19]
+ include/boost/charconv/detail/dragonbox/dragonbox_common.hpp [21:21]
+ include/boost/charconv/detail/dragonbox/floff.hpp [21:21]
+ include/boost/charconv/detail/fallback_routines.hpp [2:2]
+ include/boost/charconv/detail/from_chars_result.hpp [2:2]
+ include/boost/charconv/detail/ryu/generic_128.hpp [3:3]
+ include/boost/charconv/detail/ryu/ryu_generic_128.hpp [3:3]
+ include/boost/charconv/detail/to_chars_result.hpp [2:2]
+ include/boost/charconv/from_chars.hpp [3:3]
+ include/boost/charconv/to_chars.hpp [4:4]
+
+KEEP BSL-1.0 AND BSL-1.0 e9df2954141aa96551bf39192c39d2fe
+BELONGS ya.make
+ License text:
+ // Distributed under the Boost Software License, Version 1.0.
+ // https://www.boost.org/LICENSE_1_0.txt
+ Scancode info:
+ Original SPDX id: BSL-1.0
+ Score : 94.44
+ Match type : NOTICE
+ Links : http://www.boost.org/LICENSE_1_0.txt, http://www.boost.org/users/license.html, https://spdx.org/licenses/BSL-1.0
+ Files with this license:
+ include/boost/charconv.hpp [5:6]
+ include/boost/charconv/chars_format.hpp [2:3]
+ include/boost/charconv/detail/buffer_sizing.hpp [2:3]
+ include/boost/charconv/detail/compute_float32.hpp [2:3]
+ include/boost/charconv/detail/compute_float80.hpp [2:3]
+ include/boost/charconv/detail/emulated128.hpp [3:4]
+ include/boost/charconv/detail/fast_float/ascii_number.hpp [3:4]
+ include/boost/charconv/detail/fast_float/bigint.hpp [3:4]
+ include/boost/charconv/detail/fast_float/constexpr_feature_detect.hpp [3:4]
+ include/boost/charconv/detail/fast_float/decimal_to_binary.hpp [3:4]
+ include/boost/charconv/detail/fast_float/digit_comparison.hpp [3:4]
+ include/boost/charconv/detail/fast_float/fast_float.hpp [3:4]
+ include/boost/charconv/detail/fast_float/fast_table.hpp [3:4]
+ include/boost/charconv/detail/fast_float/float_common.hpp [3:4]
+ include/boost/charconv/detail/fast_float/parse_number.hpp [3:4]
+ include/boost/charconv/detail/from_chars_integer_impl.hpp [2:3]
+ include/boost/charconv/detail/integer_search_trees.hpp [2:3]
+ include/boost/charconv/detail/issignaling.hpp [2:3]
+ include/boost/charconv/detail/memcpy.hpp [2:3]
+ include/boost/charconv/detail/parser.hpp [2:3]
+ include/boost/charconv/detail/significand_tables.hpp [3:4]
+ include/boost/charconv/detail/to_chars_integer_impl.hpp [4:5]
+ include/boost/charconv/detail/type_traits.hpp [2:3]
+ include/boost/charconv/limits.hpp [2:3]
+ Scancode info:
+ Original SPDX id: BSL-1.0
+ Score : 88.89
+ Match type : NOTICE
+ Links : http://www.boost.org/LICENSE_1_0.txt, http://www.boost.org/users/license.html, https://spdx.org/licenses/BSL-1.0
+ Files with this license:
+ include/boost/charconv/config.hpp [6:7]
diff --git a/contrib/restricted/boost/charconv/.yandex_meta/licenses.list.txt b/contrib/restricted/boost/charconv/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..57dd425c46e
--- /dev/null
+++ b/contrib/restricted/boost/charconv/.yandex_meta/licenses.list.txt
@@ -0,0 +1,102 @@
+====================Apache-2.0====================
+// (See accompanying file LICENSE-Apache or copy at
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// the Apache License v2.0 with LLVM Exceptions.
+
+
+====================BSL-1.0====================
+// Distributed under the Boost Software License, Version 1.0.
+
+
+====================BSL-1.0====================
+// https://www.boost.org/LICENSE_1_0.txt
+
+
+====================BSL-1.0====================
+// the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE-Boost or copy at
+// https://www.boost.org/LICENSE_1_0.txt)
+
+
+====================BSL-1.0====================
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+====================BSL-1.0 AND BSL-1.0====================
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+
+====================COPYRIGHT====================
+// Copyright 2018 - 2023 Ulf Adams
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+
+====================COPYRIGHT====================
+// Copyright 2020-2022 Junekey Jeon
+
+
+====================COPYRIGHT====================
+// Copyright 2020-2023 Daniel Lemire
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+
+====================COPYRIGHT====================
+// Copyright 2020-2023 Junekey Jeon
+// Copyright 2022 Peter Dimov
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+
+====================COPYRIGHT====================
+// Copyright 2022 Peter Dimov
+// Copyright 2023 Matt Borland
+// Copyright 2023 Junekey Jeon
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+
+====================COPYRIGHT====================
+// Copyright 2022 Peter Dimov
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+
+====================COPYRIGHT====================
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+
+====================COPYRIGHT====================
+// Copyright 2024 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
diff --git a/contrib/restricted/boost/charconv/LICENSE b/contrib/restricted/boost/charconv/LICENSE
new file mode 100644
index 00000000000..36b7cd93cdf
--- /dev/null
+++ b/contrib/restricted/boost/charconv/LICENSE
@@ -0,0 +1,23 @@
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/contrib/restricted/boost/charconv/README.md b/contrib/restricted/boost/charconv/README.md
new file mode 100644
index 00000000000..ce70657a205
--- /dev/null
+++ b/contrib/restricted/boost/charconv/README.md
@@ -0,0 +1,148 @@
+# CharConv
+This library is a C++11 compatible implementation of `<charconv>`. The full documentation can be found here: https://www.boost.org/doc/libs/master/libs/charconv/doc/html/charconv.html
+
+# Build Status
+
+| | Master | Develop |
+|---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| Github Actions | [![CI](https://github.com/boostorg/charconv/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/boostorg/charconv/actions/workflows/ci.yml) | [![Build Status](https://github.com/boostorg/charconv/workflows/CI/badge.svg?branch=develop)](https://github.com/boostorg/charconv/actions/workflows/ci.yml) |
+| Drone | [![Build Status](https://drone.cpp.al/api/badges/boostorg/charconv/status.svg?ref=refs/heads/master)](https://drone.cpp.al/boostorg/charconv) | [![Build Status](https://drone.cpp.al/api/badges/boostorg/charconv/status.svg?ref=refs/heads/develop)](https://drone.cpp.al/boostorg/charconv) |
+| Codecov | [![codecov](https://codecov.io/gh/boostorg/charconv/branch/master/graph/badge.svg)](https://codecov.io/gh/boostorg/charconv/branch/master) | [![codecov](https://codecov.io/gh/boostorg/charconv/branch/develop/graph/badge.svg)](https://codecov.io/gh/boostorg/charconv/branch/develop) |
+| Fuzzing | [![Fuzz](https://github.com/boostorg/charconv/actions/workflows/fuzz.yml/badge.svg?branch=master)](https://github.com/boostorg/charconv/actions/workflows/fuzz.yml) | [![Fuzz](https://github.com/boostorg/charconv/actions/workflows/fuzz.yml/badge.svg)](https://github.com/boostorg/charconv/actions/workflows/fuzz.yml)|
+
+# How to build the library
+
+## B2
+
+````
+git clone https://github.com/boostorg/boost
+cd boost
+git submodule update --init
+cd ..
+./bootstrap
+./b2 cxxstd=11
+````
+
+This sets up a complete boost development and allows the tests to be run. To install the development environment run:
+
+````
+sudo ./b2 install cxxstd=11
+````
+
+# Synopsis
+
+Charconv is a collection of parsing functions that are locale-independent, non-allocating, and non-throwing.
+
+````
+namespace boost { namespace charconv {
+
+enum class chars_format : unsigned
+{
+ scientific = 1 << 0,
+ fixed = 1 << 1,
+ hex = 1 << 2,
+ general = fixed | scientific
+};
+
+struct from_chars_result
+{
+ const char* ptr;
+ std::errc ec;
+
+ friend constexpr bool operator==(const from_chars_result& lhs, const from_chars_result& rhs) noexcept
+ friend constexpr bool operator!=(const from_chars_result& lhs, const from_chars_result& rhs) noexcept
+ constexpr explicit operator bool() const noexcept
+}
+
+template <typename Integral>
+BOOST_CXX14_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, Integral& value, int base = 10) noexcept;
+
+BOOST_CXX14_CONSTEXPR from_chars_result from_chars<bool>(const char* first, const char* last, bool& value, int base) = delete;
+
+template <typename Real>
+from_chars_result from_chars(const char* first, const char* last, Real& value, chars_format fmt = chars_format::general) noexcept;
+
+template <typename Real>
+from_chars_result from_chars_erange(const char* first, const char* last, Real& value, chars_format fmt = chars_format::general) noexcept;
+
+struct to_chars_result
+{
+ char* ptr;
+ std::errc ec;
+
+ friend constexpr bool operator==(const to_chars_result& lhs, const to_chars_result& rhs) noexcept;
+ friend constexpr bool operator!=(const to_chars_result& lhs, const to_chars_result& rhs) noexcept;
+ constexpr explicit operator bool() const noexcept
+};
+
+template <typename Integral>
+BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, Integral value, int base = 10) noexcept;
+
+template <typename Integral>
+BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars<bool>(char* first, char* last, Integral value, int base) noexcept = delete;
+
+template <typename Real>
+to_chars_result to_chars(char* first, char* last, Real value, chars_format fmt = chars_format::general, int precision) noexcept;
+
+}} // Namespace boost::charconv
+````
+
+## Notes
+- `BOOST_CXX14_CONSTEXPR` is defined as `constexpr` when compiling with C++14 or newer.
+
+- `BOOST_CHARCONV_CONSTEXPR` is defined as `constexpr` when compiling with C++14 or newer, and the compiler has `__builtin_is_constant_evaluated`
+
+- For explanation of `from_chars_erange` see docs under heading: _Usage notes for from_chars for floating point types_
+
+# Examples
+
+## `from_chars`
+
+````
+const char* buffer = "42";
+int v = 0;
+from_chars_result r = boost::charconv::from_chars(buffer, buffer + std::strlen(buffer), v);
+assert(r.ec == std::errc());
+assert(r); // Equivalent to the above
+assert(v == 42);
+
+const char* buffer = "1.2345"
+double v = 0;
+auto r = boost::charconv::from_chars(buffer, buffer + std::strlen(buffer), v);
+assert(r.ec == std::errc());
+assert(v == 1.2345);
+
+const char* buffer = "2a";
+unsigned v = 0;
+auto r = boost::charconv::from_chars(buffer, buffer + std::strlen(buffer), v, 16);
+assert(r); // from_chars_result has operator bool()
+assert(v == 42);
+
+const char* buffer = "1.3a2bp-10";
+double v = 0;
+auto r = boost::charconv::from_chars(buffer, buffer + std::strlen(buffer), v, boost::charconv::chars_format::hex);
+assert(r);
+assert(v == 8.0427e-18);
+````
+## `to_chars`
+
+````
+char buffer[64] {};
+int v = 42;
+to_chars_result r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer), v);
+assert(r.ec == std::errc());
+assert(!strcmp(buffer, "42")); // strcmp returns 0 on match
+
+char buffer[64] {};
+double v = 1e300;
+to_chars_result r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer), v);
+assert(r.ec == std::errc());
+assert(!strcmp(buffer, "1e+300"));
+
+char buffer[64] {};
+int v = 42;
+to_chars_result r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer), v, 16);
+assert(r); // to_chars_result has operator bool()
+assert(!strcmp(buffer, "2a")); // strcmp returns 0 on match
+
+````
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv.hpp b/contrib/restricted/boost/charconv/include/boost/charconv.hpp
new file mode 100644
index 00000000000..975390bea45
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv.hpp
@@ -0,0 +1,12 @@
+#ifndef BOOST_CHARCONV_HPP_INCLUDED
+#define BOOST_CHARCONV_HPP_INCLUDED
+
+// Copyright 2022 Peter Dimov
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/charconv/from_chars.hpp>
+#include <boost/charconv/to_chars.hpp>
+#include <boost/charconv/limits.hpp>
+
+#endif // #ifndef BOOST_CHARCONV_HPP_INCLUDED
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/chars_format.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/chars_format.hpp
new file mode 100644
index 00000000000..0542372bffd
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/chars_format.hpp
@@ -0,0 +1,22 @@
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_CHARCONV_CHARS_FORMAT_HPP
+#define BOOST_CHARCONV_CHARS_FORMAT_HPP
+
+namespace boost { namespace charconv {
+
+// Floating-point format for primitive numerical conversion
+// chars_format is a bitmask type (16.3.3.3.3)
+enum class chars_format : unsigned
+{
+ scientific = 1 << 0,
+ fixed = 1 << 1,
+ hex = 1 << 2,
+ general = fixed | scientific
+};
+
+}} // Namespaces
+
+#endif // BOOST_CHARCONV_CHARS_FORMAT_HPP
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/config.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/config.hpp
new file mode 100644
index 00000000000..0d94ccd4a70
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/config.hpp
@@ -0,0 +1,39 @@
+#ifndef BOOST_CHARCONV_CONFIG_HPP_INCLUDED
+#define BOOST_CHARCONV_CONFIG_HPP_INCLUDED
+
+// Copyright 2022 Peter Dimov
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/config.hpp>
+#include <climits>
+
+// This header implements separate compilation features as described in
+// http://www.boost.org/more/separate_compilation.html
+
+#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_CHARCONV_DYN_LINK)
+# if defined(BOOST_CHARCONV_SOURCE)
+# define BOOST_CHARCONV_DECL BOOST_SYMBOL_EXPORT
+# else
+# define BOOST_CHARCONV_DECL BOOST_SYMBOL_IMPORT
+# endif
+#else
+# define BOOST_CHARCONV_DECL
+#endif
+
+// Autolink
+
+#if !defined(BOOST_CHARCONV_SOURCE) && !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_CHARCONV_NO_LIB)
+
+#define BOOST_LIB_NAME boost_charconv
+
+#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_CHARCONV_DYN_LINK)
+# define BOOST_DYN_LINK
+#endif
+
+#include <boost/config/auto_link.hpp>
+
+#endif
+
+#endif // BOOST_CHARCONV_CONFIG_HPP_INCLUDED
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/apply_sign.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/apply_sign.hpp
new file mode 100644
index 00000000000..ef6db714376
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/apply_sign.hpp
@@ -0,0 +1,50 @@
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_CHARCONV_DETAIL_APPLY_SIGN_HPP
+#define BOOST_CHARCONV_DETAIL_APPLY_SIGN_HPP
+
+#include <boost/config.hpp>
+#include <boost/charconv/detail/emulated128.hpp>
+#include <boost/charconv/detail/type_traits.hpp>
+#include <type_traits>
+
+// We are purposefully converting values here
+#ifdef BOOST_MSVC
+# pragma warning(push)
+# pragma warning(disable: 4146)
+#elif defined(__GNUC__) && __GNUC__ >= 5
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wconversion"
+#elif defined(__clang__)
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wconversion"
+#endif
+
+namespace boost { namespace charconv { namespace detail {
+
+template <typename Integer, typename Unsigned_Integer = detail::make_unsigned_t<Integer>,
+ typename std::enable_if<detail::is_signed<Integer>::value, bool>::type = true>
+constexpr Unsigned_Integer apply_sign(Integer val) noexcept
+{
+ return -(static_cast<Unsigned_Integer>(val));
+}
+
+template <typename Unsigned_Integer, typename std::enable_if<!detail::is_signed<Unsigned_Integer>::value, bool>::type = true>
+constexpr Unsigned_Integer apply_sign(Unsigned_Integer val) noexcept
+{
+ return val;
+}
+
+}}} // Namespaces
+
+#ifdef BOOST_MSVC
+# pragma warning(pop)
+#elif defined(__GNUC__) && __GNUC__ >= 5
+# pragma GCC diagnostic pop
+#elif defined(__clang__)
+# pragma clang diagnostic pop
+#endif
+
+#endif // BOOST_CHARCONV_DETAIL_APPLY_SIGN_HPP
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/bit_layouts.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/bit_layouts.hpp
new file mode 100644
index 00000000000..c163ce06ad2
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/bit_layouts.hpp
@@ -0,0 +1,160 @@
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_CHARCONV_DETAIL_BIT_LAYOUTS_HPP
+#define BOOST_CHARCONV_DETAIL_BIT_LAYOUTS_HPP
+
+#include <boost/charconv/detail/config.hpp>
+#include <boost/charconv/detail/emulated128.hpp>
+#include <cstdint>
+#include <cfloat>
+
+// Layouts of floating point types as specified by IEEE 754
+// See page 23 of IEEE 754-2008
+
+namespace boost { namespace charconv { namespace detail {
+
+struct ieee754_binary16
+{
+ static constexpr int significand_bits = 10;
+ static constexpr int exponent_bits = 5;
+ static constexpr int min_exponent = -14;
+ static constexpr int max_exponent = 15;
+ static constexpr int exponent_bias = -15;
+ static constexpr int decimal_digits = 5;
+};
+
+struct brainfloat16
+{
+ static constexpr int significand_bits = 7;
+ static constexpr int exponent_bits = 8;
+ static constexpr int min_exponent = -126;
+ static constexpr int max_exponent = 127;
+ static constexpr int exponent_bias = -127;
+ static constexpr int decimal_digits = 4;
+};
+
+struct ieee754_binary32
+{
+ static constexpr int significand_bits = 23;
+ static constexpr int exponent_bits = 8;
+ static constexpr int min_exponent = -126;
+ static constexpr int max_exponent = 127;
+ static constexpr int exponent_bias = -127;
+ static constexpr int decimal_digits = 9;
+};
+
+struct ieee754_binary64
+{
+ static constexpr int significand_bits = 52;
+ static constexpr int exponent_bits = 11;
+ static constexpr int min_exponent = -1022;
+ static constexpr int max_exponent = 1023;
+ static constexpr int exponent_bias = -1023;
+ static constexpr int decimal_digits = 17;
+};
+
+// 80 bit long double (e.g. x86-64)
+#if LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384
+
+struct IEEEl2bits
+{
+#if BOOST_CHARCONV_ENDIAN_LITTLE_BYTE
+ std::uint64_t mantissa_l : 64;
+ std::uint32_t exponent : 15;
+ std::uint32_t sign : 1;
+ std::uint64_t pad : 48;
+#else // Big endian
+ std::uint64_t pad : 48;
+ std::uint32_t sign : 1;
+ std::uint32_t exponent : 15;
+ std::uint64_t mantissa_h : 64;
+#endif
+};
+
+struct ieee754_binary80
+{
+ static constexpr int significand_bits = 64; // Fraction is 63 and 1 integer bit
+ static constexpr int exponent_bits = 15;
+ static constexpr int min_exponent = -16382;
+ static constexpr int max_exponent = 16383;
+ static constexpr int exponent_bias = -16383;
+ static constexpr int decimal_digits = 18;
+};
+
+#define BOOST_CHARCONV_LDBL_BITS 80
+
+// 128 bit long double (e.g. s390x, ppcle64)
+#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384
+
+struct IEEEl2bits
+{
+#if BOOST_CHARCONV_ENDIAN_LITTLE_BYTE
+ std::uint64_t mantissa_l : 64;
+ std::uint64_t mantissa_h : 48;
+ std::uint32_t exponent : 15;
+ std::uint32_t sign : 1;
+#else // Big endian
+ std::uint32_t sign : 1;
+ std::uint32_t exponent : 15;
+ std::uint64_t mantissa_h : 48;
+ std::uint64_t mantissa_l : 64;
+#endif
+};
+
+#define BOOST_CHARCONV_LDBL_BITS 128
+
+// 64 bit long double (double == long double on ARM)
+#elif LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
+
+struct IEEEl2bits
+{
+#if BOOST_CHARCONV_ENDIAN_LITTLE_BYTE
+ std::uint32_t mantissa_l : 32;
+ std::uint32_t mantissa_h : 20;
+ std::uint32_t exponent : 11;
+ std::uint32_t sign : 1;
+#else // Big endian
+ std::uint32_t sign : 1;
+ std::uint32_t exponent : 11;
+ std::uint32_t mantissa_h : 20;
+ std::uint32_t mantissa_l : 32;
+#endif
+};
+
+#define BOOST_CHARCONV_LDBL_BITS 64
+
+#else // Unsupported long double representation
+# define BOOST_CHARCONV_UNSUPPORTED_LONG_DOUBLE
+# define BOOST_CHARCONV_LDBL_BITS -1
+#endif
+
+struct IEEEbinary128
+{
+#if BOOST_CHARCONV_ENDIAN_LITTLE_BYTE
+ std::uint64_t mantissa_l : 64;
+ std::uint64_t mantissa_h : 48;
+ std::uint32_t exponent : 15;
+ std::uint32_t sign : 1;
+#else // Big endian
+ std::uint32_t sign : 1;
+ std::uint32_t exponent : 15;
+ std::uint64_t mantissa_h : 48;
+ std::uint64_t mantissa_l : 64;
+#endif
+};
+
+struct ieee754_binary128
+{
+ static constexpr int significand_bits = 112;
+ static constexpr int exponent_bits = 15;
+ static constexpr int min_exponent = -16382;
+ static constexpr int max_exponent = 16383;
+ static constexpr int exponent_bias = 16383;
+ static constexpr int decimal_digits = 33;
+};
+
+}}} // Namespaces
+
+#endif // BOOST_CHARCONV_DETAIL_BIT_LAYOUTS_HPP
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/buffer_sizing.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/buffer_sizing.hpp
new file mode 100644
index 00000000000..3115ee39e5f
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/buffer_sizing.hpp
@@ -0,0 +1,72 @@
+// Copyright 2024 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_CHARCONV_DETAIL_BUFFER_SIZING_HPP
+#define BOOST_CHARCONV_DETAIL_BUFFER_SIZING_HPP
+
+#include <boost/charconv/detail/config.hpp>
+#include <boost/charconv/detail/integer_search_trees.hpp>
+#include <type_traits>
+
+namespace boost {
+namespace charconv {
+namespace detail {
+
+#ifdef BOOST_MSVC
+# pragma warning(push)
+# pragma warning(disable: 4127) // Conditional expression for BOOST_IF_CONSTEXPR will be constant in not C++17
+#endif
+
+template <typename Real>
+inline int get_real_precision(int precision = -1) noexcept
+{
+ // If the user did not specify a precision than we use the maximum representable amount
+ // and remove trailing zeros at the end
+
+ int real_precision;
+ BOOST_IF_CONSTEXPR (!std::is_same<Real, long double>::value
+ #ifdef BOOST_CHARCONV_HAS_QUADMATH
+ && !std::is_same<Real, __float128>::value
+ #endif
+ )
+ {
+ real_precision = precision == -1 ? std::numeric_limits<Real>::max_digits10 : precision;
+ }
+ else
+ {
+ #ifdef BOOST_CHARCONV_HAS_QUADMATH
+ BOOST_CHARCONV_IF_CONSTEXPR (std::is_same<Real, __float128>::value)
+ {
+ real_precision = 33;
+ }
+ else
+ #endif
+ {
+ #if BOOST_CHARCONV_LDBL_BITS == 128
+ real_precision = 33;
+ #else
+ real_precision = 18;
+ #endif
+ }
+ }
+
+ return real_precision;
+}
+
+template <typename Int>
+inline int total_buffer_length(int real_precision, Int exp, bool signed_value)
+{
+ // Sign + integer part + '.' + precision of fraction part + e+/e- or p+/p- + exponent digits
+ return static_cast<int>(signed_value) + 1 + real_precision + 2 + num_digits(exp);
+}
+
+#ifdef BOOST_MSVC
+# pragma warning(pop)
+#endif
+
+} //namespace detail
+} //namespace charconv
+} //namespace boost
+
+#endif //BOOST_CHARCONV_DETAIL_BUFFER_SIZING_HPP
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/compute_float32.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/compute_float32.hpp
new file mode 100644
index 00000000000..85ece7f8c3a
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/compute_float32.hpp
@@ -0,0 +1,55 @@
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_CHARCONV_DETAIL_COMPUTE_FLOAT32_HPP
+#define BOOST_CHARCONV_DETAIL_COMPUTE_FLOAT32_HPP
+
+#include <boost/charconv/detail/compute_float64.hpp>
+#include <limits>
+#include <cstdint>
+#include <cmath>
+
+namespace boost { namespace charconv { namespace detail {
+
+inline float compute_float32(std::int64_t power, std::uint64_t i, bool negative, bool& success) noexcept
+{
+ const double d = compute_float64(power, i, negative, success);
+ float return_val;
+
+ if (success)
+ {
+ // Some compilers (e.g. Intel) will optimize std::isinf to always false depending on compiler flags
+ //
+ // From Intel(R) oneAPI DPC++/C++ Compiler 2023.0.0 (2023.0.0.20221201)
+ // warning: comparison with infinity always evaluates to false in fast floating point modes [-Wtautological-constant-compare]
+ // if (std::isinf(return_val))
+ if (d > static_cast<double>((std::numeric_limits<float>::max)()) ||
+ d < static_cast<double>((std::numeric_limits<float>::lowest)()))
+ {
+ return_val = negative ? -HUGE_VALF : HUGE_VALF;
+ success = false;
+ }
+ else
+ {
+ return_val = static_cast<float>(d);
+ }
+ }
+ else
+ {
+ if (power > 38)
+ {
+ return_val = negative ? -HUGE_VALF : HUGE_VALF;
+ }
+ else
+ {
+ return_val = negative ? -0.0F : 0.0F;
+ }
+ }
+
+ return return_val;
+}
+
+}}} // Namespaces
+
+#endif // BOOST_CHARCONV_DETAIL_COMPUTE_FLOAT32_HPP
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/compute_float64.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/compute_float64.hpp
new file mode 100644
index 00000000000..3cb83537fa9
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/compute_float64.hpp
@@ -0,0 +1,201 @@
+// Copyright 2020-2023 Daniel Lemire
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_CHARCONV_DETAIL_COMPUTE_FLOAT64_HPP
+#define BOOST_CHARCONV_DETAIL_COMPUTE_FLOAT64_HPP
+
+#include <boost/charconv/detail/config.hpp>
+#include <boost/charconv/detail/significand_tables.hpp>
+#include <boost/charconv/detail/emulated128.hpp>
+#include <boost/core/bit.hpp>
+#include <cstdint>
+#include <cfloat>
+#include <cstring>
+#include <cmath>
+
+namespace boost { namespace charconv { namespace detail {
+
+static constexpr double powers_of_ten[] = {
+ 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11,
+ 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22
+};
+
+// Attempts to compute i * 10^(power) exactly; and if "negative" is true, negate the result.
+//
+// This function will only work in some cases, when it does not work, success is
+// set to false. This should work *most of the time* (like 99% of the time).
+// We assume that power is in the [-325, 308] interval.
+inline double compute_float64(std::int64_t power, std::uint64_t i, bool negative, bool& success) noexcept
+{
+ static constexpr auto smallest_power = -325;
+ static constexpr auto largest_power = 308;
+
+ // We start with a fast path
+ // It was described in Clinger WD.
+ // How to read floating point numbers accurately.
+ // ACM SIGPLAN Notices. 1990
+#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)
+ if (0 <= power && power <= 22 && i <= UINT64_C(9007199254740991))
+#else
+ if (-22 <= power && power <= 22 && i <= UINT64_C(9007199254740991))
+#endif
+ {
+ // The general idea is as follows.
+ // If 0 <= s < 2^53 and if 10^0 <= p <= 10^22 then
+ // 1) Both s and p can be represented exactly as 64-bit floating-point
+ // values
+ // (binary64).
+ // 2) Because s and p can be represented exactly as floating-point values,
+ // then s * p
+ // and s / p will produce correctly rounded values.
+
+ auto d = static_cast<double>(i);
+
+ if (power < 0)
+ {
+ d = d / powers_of_ten[-power];
+ }
+ else
+ {
+ d = d * powers_of_ten[power];
+ }
+
+ if (negative)
+ {
+ d = -d;
+ }
+
+ success = true;
+ return d;
+ }
+
+ // When 22 < power && power < 22 + 16, we could
+ // hope for another, secondary fast path. It was
+ // described by David M. Gay in "Correctly rounded
+ // binary-decimal and decimal-binary conversions." (1990)
+ // If you need to compute i * 10^(22 + x) for x < 16,
+ // first compute i * 10^x, if you know that result is exact
+ // (e.g., when i * 10^x < 2^53),
+ // then you can still proceed and do (i * 10^x) * 10^22.
+ // Is this worth your time?
+ // You need 22 < power *and* power < 22 + 16 *and* (i * 10^(x-22) < 2^53)
+ // for this second fast path to work.
+ // If you have 22 < power *and* power < 22 + 16, and then you
+ // optimistically compute "i * 10^(x-22)", there is still a chance that you
+ // have wasted your time if i * 10^(x-22) >= 2^53. It makes the use cases of
+ // this optimization maybe less common than we would like. Source:
+ // http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
+ // also used in RapidJSON: https://rapidjson.org/strtod_8h_source.html
+
+ if (i == 0 || power < smallest_power)
+ {
+ return negative ? -0.0 : 0.0;
+ }
+ else if (power > largest_power)
+ {
+ return negative ? -HUGE_VAL : HUGE_VAL;
+ }
+
+ const std::uint64_t factor_significand = significands_table::significand_64[power - smallest_power];
+ const std::int64_t exponent = (((152170 + 65536) * power) >> 16) + 1024 + 63;
+ int leading_zeros = boost::core::countl_zero(i);
+ i <<= static_cast<std::uint64_t>(leading_zeros);
+
+ uint128 product = umul128(i, factor_significand);
+ std::uint64_t low = product.low;
+ std::uint64_t high = product.high;
+
+ // We know that upper has at most one leading zero because
+ // both i and factor_mantissa have a leading one. This means
+ // that the result is at least as large as ((1<<63)*(1<<63))/(1<<64).
+ //
+ // As long as the first 9 bits of "upper" are not "1", then we
+ // know that we have an exact computed value for the leading
+ // 55 bits because any imprecision would play out as a +1, in the worst case.
+ // Having 55 bits is necessary because we need 53 bits for the mantissa,
+ // but we have to have one rounding bit and, we can waste a bit if the most
+ // significant bit of the product is zero.
+ //
+ // We expect this next branch to be rarely taken (say 1% of the time).
+ // When (upper & 0x1FF) == 0x1FF, it can be common for
+ // lower + i < lower to be true (proba. much higher than 1%).
+ if (BOOST_UNLIKELY((high & 0x1FF) == 0x1FF) && (low + i < low))
+ {
+ const std::uint64_t factor_significand_low = significands_table::significand_128[power - smallest_power];
+ product = umul128(i, factor_significand_low);
+ //const std::uint64_t product_low = product.low;
+ const std::uint64_t product_middle2 = product.high;
+ const std::uint64_t product_middle1 = low;
+ std::uint64_t product_high = high;
+ const std::uint64_t product_middle = product_middle1 + product_middle2;
+
+ if (product_middle < product_middle1)
+ {
+ product_high++;
+ }
+
+ // Commented out because possibly unneeded
+ // See: https://arxiv.org/pdf/2212.06644.pdf
+ /*
+ // we want to check whether mantissa *i + i would affect our result
+ // This does happen, e.g. with 7.3177701707893310e+15
+ if (((product_middle + 1 == 0) && ((product_high & 0x1FF) == 0x1FF) && (product_low + i < product_low)))
+ {
+ success = false;
+ return 0;
+ }
+ */
+
+ low = product_middle;
+ high = product_high;
+ }
+
+ // The final significand should be 53 bits with a leading 1
+ // We shift it so that it occupies 54 bits with a leading 1
+ const std::uint64_t upper_bit = high >> 63;
+ std::uint64_t significand = high >> (upper_bit + 9);
+ leading_zeros += static_cast<int>(1 ^ upper_bit);
+
+ // If we have lots of trailing zeros we may fall between two values
+ if (BOOST_UNLIKELY((low == 0) && ((high & 0x1FF) == 0) && ((significand & 3) == 1)))
+ {
+ // if significand & 1 == 1 we might need to round up
+ success = false;
+ return 0;
+ }
+
+ significand += significand & 1;
+ significand >>= 1;
+
+ // Here the significand < (1<<53), unless there is an overflow
+ if (significand >= (UINT64_C(1) << 53))
+ {
+ significand = (UINT64_C(1) << 52);
+ leading_zeros--;
+ }
+
+ significand &= ~(UINT64_C(1) << 52);
+ const auto real_exponent = static_cast<std::uint64_t>(exponent - leading_zeros);
+
+ // We have to check that real_exponent is in range, otherwise fail
+ if (BOOST_UNLIKELY((real_exponent < 1) || (real_exponent > 2046)))
+ {
+ success = false;
+ return 0;
+ }
+
+ significand |= real_exponent << 52;
+ significand |= ((static_cast<std::uint64_t>(negative) << 63));
+
+ double d;
+ std::memcpy(&d, &significand, sizeof(d));
+
+ success = true;
+ return d;
+}
+
+}}} // Namespaces
+
+#endif // BOOST_CHARCONV_DETAIL_COMPUTE_FLOAT64_HPP
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/compute_float80.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/compute_float80.hpp
new file mode 100644
index 00000000000..ad1e51486ab
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/compute_float80.hpp
@@ -0,0 +1,114 @@
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_CHARCONV_DETAIL_COMPUTE_FLOAT80_HPP
+#define BOOST_CHARCONV_DETAIL_COMPUTE_FLOAT80_HPP
+
+#include <boost/charconv/detail/config.hpp>
+#include <boost/charconv/detail/emulated128.hpp>
+#include <boost/charconv/detail/bit_layouts.hpp>
+#include <system_error>
+#include <type_traits>
+#include <limits>
+#include <cstdint>
+#include <cmath>
+#include <climits>
+#include <cfloat>
+
+#ifdef BOOST_CHARCONV_DEBUG_FLOAT128
+#include <iostream>
+#include <iomanip>
+#include <boost/charconv/detail/to_chars_integer_impl.hpp>
+#endif
+
+namespace boost { namespace charconv { namespace detail {
+
+#if BOOST_CHARCONV_LDBL_BITS > 64
+
+static constexpr long double powers_of_ten_ld[] = {
+ 1e0L, 1e1L, 1e2L, 1e3L, 1e4L, 1e5L, 1e6L,
+ 1e7L, 1e8L, 1e9L, 1e10L, 1e11L, 1e12L, 1e13L,
+ 1e14L, 1e15L, 1e16L, 1e17L, 1e18L, 1e19L, 1e20L,
+ 1e21L, 1e22L, 1e23L, 1e24L, 1e25L, 1e26L, 1e27L,
+ 1e28L, 1e29L, 1e30L, 1e31L, 1e32L, 1e33L, 1e34L,
+ 1e35L, 1e36L, 1e37L, 1e38L, 1e39L, 1e40L, 1e41L,
+ 1e42L, 1e43L, 1e44L, 1e45L, 1e46L, 1e47L, 1e48L,
+ 1e49L, 1e50L, 1e51L, 1e52L, 1e53L, 1e54L, 1e55L
+};
+
+template <typename ResultType, typename Unsigned_Integer, typename ArrayPtr>
+inline ResultType fast_path(std::int64_t q, Unsigned_Integer w, bool negative, ArrayPtr table) noexcept
+{
+ // The general idea is as follows.
+ // if 0 <= s <= 2^64 and if 10^0 <= p <= 10^27
+ // Both s and p can be represented exactly
+ // because of this s*p and s/p will produce
+ // correctly rounded values
+
+ auto ld = static_cast<ResultType>(w);
+
+ if (q < 0)
+ {
+ ld /= table[-q];
+ }
+ else
+ {
+ ld *= table[q];
+ }
+
+ if (negative)
+ {
+ ld = -ld;
+ }
+
+ return ld;
+}
+
+template <typename ResultType, typename Unsigned_Integer>
+inline ResultType compute_float80(std::int64_t q, Unsigned_Integer w, bool negative, std::errc& success) noexcept
+{
+ // GLIBC uses 2^-16444 but MPFR uses 2^-16445 as the smallest subnormal value for 80 bit
+ // 39 is the max number of digits in an uint128_t
+ static constexpr auto smallest_power = -4951 - 39;
+ static constexpr auto largest_power = 4932;
+
+ // We start with a fast path
+ // It is an extension of what was described in Clinger WD.
+ // How to read floating point numbers accurately.
+ // ACM SIGPLAN Notices. 1990
+ // https://dl.acm.org/doi/pdf/10.1145/93542.93557
+ static constexpr auto clinger_max_exp = BOOST_CHARCONV_LDBL_BITS == 80 ? 27 : 48; // NOLINT : Only changes by platform
+ static constexpr auto clinger_min_exp = BOOST_CHARCONV_LDBL_BITS == 80 ? -34 : -55; // NOLINT
+
+ if (clinger_min_exp <= q && q <= clinger_max_exp && w <= static_cast<Unsigned_Integer>(1) << 113)
+ {
+ success = std::errc();
+ return fast_path<ResultType>(q, w, negative, powers_of_ten_ld);
+ }
+
+ if (w == 0)
+ {
+ success = std::errc();
+ return negative ? -0.0L : 0.0L;
+ }
+ else if (q > largest_power)
+ {
+ success = std::errc::result_out_of_range;
+ return negative ? -HUGE_VALL : HUGE_VALL;
+ }
+ else if (q < smallest_power)
+ {
+ success = std::errc::result_out_of_range;
+ return negative ? -0.0L : 0.0L;
+ }
+
+ success = std::errc::not_supported;
+ return 0;
+}
+
+#endif // BOOST_CHARCONV_LDBL_BITS > 64
+
+}}} // Namespaces
+
+#endif // BOOST_CHARCONV_DETAIL_COMPUTE_FLOAT80_HPP
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/config.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/config.hpp
new file mode 100644
index 00000000000..602f8c75d61
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/config.hpp
@@ -0,0 +1,191 @@
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_CHARCONV_DETAIL_CONFIG_HPP
+#define BOOST_CHARCONV_DETAIL_CONFIG_HPP
+
+#include <boost/config.hpp>
+#include <type_traits>
+#include <cfloat>
+
+#include <boost/assert.hpp>
+#define BOOST_CHARCONV_ASSERT(expr) BOOST_ASSERT(expr)
+#define BOOST_CHARCONV_ASSERT_MSG(expr, msg) BOOST_ASSERT_MSG(expr, msg)
+
+#ifdef BOOST_CHARCONV_DEBUG
+# define BOOST_CHARCONV_DEBUG_ASSERT(expr) BOOST_CHARCONV_ASSERT(expr)
+#else
+# define BOOST_CHARCONV_DEBUG_ASSERT(expr)
+#endif
+
+// Use 128-bit integers and suppress warnings for using extensions
+#if defined(BOOST_HAS_INT128)
+# define BOOST_CHARCONV_HAS_INT128
+# define BOOST_CHARCONV_INT128_MAX static_cast<boost::int128_type>((static_cast<boost::uint128_type>(1) << 127) - 1)
+# define BOOST_CHARCONV_INT128_MIN (-BOOST_CHARCONV_INT128_MAX - 1)
+# define BOOST_CHARCONV_UINT128_MAX (2 * static_cast<boost::uint128_type>(BOOST_CHARCONV_INT128_MAX) + 1)
+#endif
+
+#ifndef BOOST_NO_CXX14_CONSTEXPR
+# define BOOST_CHARCONV_CXX14_CONSTEXPR BOOST_CXX14_CONSTEXPR
+# define BOOST_CHARCONV_CXX14_CONSTEXPR_NO_INLINE BOOST_CXX14_CONSTEXPR
+#else
+# define BOOST_CHARCONV_CXX14_CONSTEXPR inline
+# define BOOST_CHARCONV_CXX14_CONSTEXPR_NO_INLINE
+#endif
+
+#if defined(__GNUC__) && __GNUC__ == 5
+# define BOOST_CHARCONV_GCC5_CONSTEXPR inline
+#else
+# define BOOST_CHARCONV_GCC5_CONSTEXPR BOOST_CHARCONV_CXX14_CONSTEXPR
+#endif
+
+// C++17 allowed for constexpr lambdas
+#if defined(__cpp_constexpr) && __cpp_constexpr >= 201603L
+# define BOOST_CHARCONV_CXX17_CONSTEXPR constexpr
+#else
+# define BOOST_CHARCONV_CXX17_CONSTEXPR inline
+#endif
+
+// Determine endianness
+#if defined(_WIN32)
+
+#define BOOST_CHARCONV_ENDIAN_BIG_BYTE 0
+#define BOOST_CHARCONV_ENDIAN_LITTLE_BYTE 1
+
+#elif defined(__BYTE_ORDER__)
+
+#define BOOST_CHARCONV_ENDIAN_BIG_BYTE (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+#define BOOST_CHARCONV_ENDIAN_LITTLE_BYTE (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+
+#else
+
+#error Could not determine endian type. Please file an issue at https://github.com/cppalliance/charconv with your architecture
+
+#endif // Determine endianness
+
+// Inclue intrinsics if available
+#if defined(BOOST_MSVC)
+# include <intrin.h>
+# if defined(_WIN64)
+# define BOOST_CHARCONV_HAS_MSVC_64BIT_INTRINSICS
+# else
+# define BOOST_CHARCONV_HAS_MSVC_32BIT_INTRINSICS
+# endif
+#endif
+
+static_assert((BOOST_CHARCONV_ENDIAN_BIG_BYTE || BOOST_CHARCONV_ENDIAN_LITTLE_BYTE) &&
+ !(BOOST_CHARCONV_ENDIAN_BIG_BYTE && BOOST_CHARCONV_ENDIAN_LITTLE_BYTE),
+"Inconsistent endianness detected. Please file an issue at https://github.com/cppalliance/charconv with your architecture");
+
+// Suppress additional buffer overrun check.
+// I have no idea why MSVC thinks some functions here are vulnerable to the buffer overrun
+// attacks. No, they aren't.
+#if defined(__GNUC__) || defined(__clang__)
+ #define BOOST_CHARCONV_SAFEBUFFERS
+#elif defined(_MSC_VER)
+ #define BOOST_CHARCONV_SAFEBUFFERS __declspec(safebuffers)
+#else
+ #define BOOST_CHARCONV_SAFEBUFFERS
+#endif
+
+#if defined(__has_builtin)
+ #define BOOST_CHARCONV_HAS_BUILTIN(x) __has_builtin(x)
+#else
+ #define BOOST_CHARCONV_HAS_BUILTIN(x) false
+#endif
+
+// Workaround for errors in MSVC 14.3 with gotos in if constexpr blocks
+#if defined(BOOST_MSVC) && (BOOST_MSVC == 1933 || BOOST_MSVC == 1934)
+# define BOOST_CHARCONV_IF_CONSTEXPR if
+#else
+# define BOOST_CHARCONV_IF_CONSTEXPR BOOST_IF_CONSTEXPR
+#endif
+
+// Clang < 4 return type deduction does not work with the policy implementation
+#ifndef BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION
+# if (defined(__clang__) && __clang_major__ < 4) || (defined(_MSC_VER) && _MSC_VER == 1900)
+# define BOOST_CHARCONV_NO_CXX14_RETURN_TYPE_DEDUCTION
+# endif
+#elif defined(BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION)
+# define BOOST_CHARCONV_NO_CXX14_RETURN_TYPE_DEDUCTION
+#endif
+
+// Is constant evaluated detection
+#ifdef __cpp_lib_is_constant_evaluated
+# define BOOST_CHARCONV_HAS_IS_CONSTANT_EVALUATED
+#endif
+
+#ifdef __has_builtin
+# if __has_builtin(__builtin_is_constant_evaluated) && !defined(BOOST_NO_CXX14_CONSTEXPR)
+# define BOOST_CHARCONV_HAS_BUILTIN_IS_CONSTANT_EVALUATED
+# endif
+#endif
+
+//
+// MSVC also supports __builtin_is_constant_evaluated if it's recent enough:
+//
+#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 192528326)
+# define BOOST_CHARCONV_HAS_BUILTIN_IS_CONSTANT_EVALUATED
+#endif
+
+//
+// As does GCC-9:
+//
+#if !defined(BOOST_NO_CXX14_CONSTEXPR) && defined(__GNUC__) && (__GNUC__ >= 9) && !defined(BOOST_CHARCONV_HAS_BUILTIN_IS_CONSTANT_EVALUATED)
+# define BOOST_CHARCONV_HAS_BUILTIN_IS_CONSTANT_EVALUATED
+#endif
+
+#if defined(BOOST_CHARCONV_HAS_IS_CONSTANT_EVALUATED) && !defined(BOOST_NO_CXX14_CONSTEXPR)
+# define BOOST_CHARCONV_IS_CONSTANT_EVALUATED(x) std::is_constant_evaluated()
+#elif defined(BOOST_CHARCONV_HAS_BUILTIN_IS_CONSTANT_EVALUATED)
+# define BOOST_CHARCONV_IS_CONSTANT_EVALUATED(x) __builtin_is_constant_evaluated()
+#elif !defined(BOOST_NO_CXX14_CONSTEXPR) && defined(__GNUC__) && (__GNUC__ >= 6)
+# define BOOST_CHARCONV_IS_CONSTANT_EVALUATED(x) __builtin_constant_p(x)
+# define BOOST_CHARCONV_USING_BUILTIN_CONSTANT_P
+#else
+# define BOOST_CHARCONV_IS_CONSTANT_EVALUATED(x) false
+# define BOOST_CHARCONV_NO_CONSTEXPR_DETECTION
+#endif
+
+#ifdef BOOST_MSVC
+# define BOOST_CHARCONV_ASSUME(expr) __assume(expr)
+#elif defined(__clang__)
+# define BOOST_CHARCONV_ASSUME(expr) __builtin_assume(expr)
+#elif defined(__GNUC__)
+# define BOOST_CHARCONV_ASSUME(expr) if (expr) {} else { __builtin_unreachable(); }
+#elif defined(__has_cpp_attribute)
+# if __has_cpp_attribute(assume)
+# define BOOST_CHARCONV_ASSUME(expr) [[assume(expr)]]
+# else
+# define BOOST_CHARCONV_ASSUME(expr)
+# endif
+#else
+# define BOOST_CHARCONV_ASSUME(expr)
+#endif
+
+// Detection for C++23 fixed width floating point types
+// All of these types are optional so check for each of them individually
+#if (defined(_MSVC_LANG) && _MSVC_LANG > 202002L) || __cplusplus > 202002L
+# if __has_include(<stdfloat>)
+# error #include <stdfloat>
+# endif
+#endif
+#ifdef __STDCPP_FLOAT16_T__
+# define BOOST_CHARCONV_HAS_FLOAT16
+#endif
+#ifdef __STDCPP_FLOAT32_T__
+# define BOOST_CHARCONV_HAS_FLOAT32
+#endif
+#ifdef __STDCPP_FLOAT64_T__
+# define BOOST_CHARCONV_HAS_FLOAT64
+#endif
+#ifdef __STDCPP_FLOAT128_T__
+# define BOOST_CHARCONV_HAS_STDFLOAT128
+#endif
+#ifdef __STDCPP_BFLOAT16_T__
+# define BOOST_CHARCONV_HAS_BRAINFLOAT16
+#endif
+
+#endif // BOOST_CHARCONV_DETAIL_CONFIG_HPP
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/dragonbox/dragonbox.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/dragonbox/dragonbox.hpp
new file mode 100644
index 00000000000..f2d3449acdf
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/dragonbox/dragonbox.hpp
@@ -0,0 +1,2752 @@
+// Copyright 2020-2022 Junekey Jeon
+//
+// The contents of this file may be used under the terms of
+// the Apache License v2.0 with LLVM Exceptions.
+//
+// (See accompanying file LICENSE-Apache or copy at
+// https://llvm.org/foundation/relicensing/LICENSE.txt)
+//
+// Alternatively, the contents of this file may be used under the terms of
+// the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE-Boost or copy at
+// https://www.boost.org/LICENSE_1_0.txt)
+//
+// Unless required by applicable law or agreed to in writing, this software
+// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.
+//
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_CHARCONV_DETAIL_DRAGONBOX_HPP
+#define BOOST_CHARCONV_DETAIL_DRAGONBOX_HPP
+
+#include <boost/charconv/detail/config.hpp>
+#include <boost/charconv/detail/dragonbox/dragonbox_common.hpp>
+#include <boost/charconv/detail/bit_layouts.hpp>
+#include <boost/charconv/detail/emulated128.hpp>
+#include <boost/charconv/detail/buffer_sizing.hpp>
+#include <boost/charconv/detail/to_chars_result.hpp>
+#include <boost/charconv/chars_format.hpp>
+#include <boost/core/bit.hpp>
+#include <type_traits>
+#include <limits>
+#include <cstdint>
+#include <cstring>
+
+#ifdef BOOST_MSVC
+# pragma warning(push)
+# pragma warning(disable: 4127) // Conditional expression is constant (e.g. BOOST_IF_CONSTEXPR statements)
+# pragma warning(disable: 4307) // Integral constant overflow (Only MSVC-14.1 issued this warning)
+#endif
+
+namespace boost { namespace charconv { namespace detail {
+
+// A floating-point traits class defines ways to interpret a bit pattern of given size as an
+// encoding of floating-point number. This is a default implementation of such a traits class,
+// supporting ways to interpret 32-bits into a binary32-encoded floating-point number and to
+// interpret 64-bits into a binary64-encoded floating-point number. Users might specialize this
+// class to change the default behavior for certain types.
+
+template <typename T>
+struct dragonbox_float_traits
+{
+ // I don't know if there is a truly reliable way of detecting
+ // IEEE-754 binary32/binary64 formats; I just did my best here.
+ static_assert(std::numeric_limits<T>::is_iec559 && std::numeric_limits<T>::radix == 2 &&
+ (physical_bits<T>::value == 32 || physical_bits<T>::value == 64),
+ "default_ieee754_traits only works for 32-bits or 64-bits types "
+ "supporting binary32 or binary64 formats!");
+
+ // The type that is being viewed.
+ using type = T;
+
+ // Refers to the format specification class.
+ using format = typename std::conditional<physical_bits<T>::value == 32, ieee754_binary32, ieee754_binary64>::type;
+
+ // Defines an unsigned integer type that is large enough to carry a variable of type T.
+ // Most of the operations will be done on this integer type.
+ using carrier_uint =
+ typename std::conditional<physical_bits<T>::value == 32, std::uint32_t, std::uint64_t>::type;
+
+ static_assert(sizeof(carrier_uint) == sizeof(T), "Type T must have a unsigned type with the same number of bits");
+
+ // Number of bits in the above unsigned integer type.
+ static constexpr int carrier_bits = static_cast<int>(physical_bits<carrier_uint>::value);
+
+ // Convert from carrier_uint into the original type.
+ // Depending on the floating-point encoding format, this operation might not be possible for
+ // some specific bit patterns. However, the contract is that u always denotes a
+ // valid bit pattern, so this function must be assumed to be noexcept.
+ static T carrier_to_float(carrier_uint u) noexcept
+ {
+ T x;
+ std::memcpy(&x, &u, sizeof(carrier_uint));
+ return x;
+ }
+
+ // Same as above.
+ static carrier_uint float_to_carrier(T x) noexcept
+ {
+ carrier_uint u;
+ std::memcpy(&u, &x, sizeof(carrier_uint));
+ return u;
+ }
+
+ // Extract exponent bits from a bit pattern.
+ // The result must be aligned to the LSB so that there is no additional zero paddings
+ // on the right. This function does not do bias adjustment.
+ static constexpr unsigned extract_exponent_bits(carrier_uint u) noexcept
+ {
+ return static_cast<unsigned>(u >> format::significand_bits) & ((static_cast<unsigned int>(1) << format::exponent_bits) - 1);
+ }
+
+ // Extract significand bits from a bit pattern.
+ // The result must be aligned to the LSB so that there is no additional zero paddings
+ // on the right. The result does not contain the implicit bit.
+ static constexpr carrier_uint extract_significand_bits(carrier_uint u) noexcept
+ {
+ return carrier_uint(u & carrier_uint((carrier_uint(1) << format::significand_bits) - 1));
+ }
+
+ // Remove the exponent bits and extract significand bits together with the sign bit.
+ static constexpr carrier_uint remove_exponent_bits(carrier_uint u, unsigned int exponent_bits) noexcept
+ {
+ return u ^ (carrier_uint(exponent_bits) << format::significand_bits);
+ }
+
+ // Shift the obtained signed significand bits to the left by 1 to remove the sign bit.
+ static constexpr carrier_uint remove_sign_bit_and_shift(carrier_uint u) noexcept {
+ return carrier_uint(carrier_uint(u) << 1);
+ }
+
+ // The actual value of exponent is obtained by adding this value to the extracted exponent
+ // bits.
+ static constexpr int exponent_bias = 1 - (1 << (carrier_bits - format::significand_bits - 2));
+
+ // Obtain the actual value of the binary exponent from the extracted exponent bits.
+ static constexpr int binary_exponent(unsigned exponent_bits) noexcept
+ {
+ return static_cast<int>(exponent_bits == 0 ? format::min_exponent : int(exponent_bits) + format::exponent_bias);
+ }
+
+ // Obtain the actual value of the binary exponent from the extracted significand bits and
+ // exponent bits.
+ static constexpr carrier_uint binary_significand(carrier_uint significand_bits, unsigned exponent_bits) noexcept
+ {
+ return exponent_bits == 0 ? significand_bits : significand_bits | (carrier_uint(1) << format::significand_bits);
+ }
+
+ /* Various boolean observer functions */
+
+ static constexpr bool is_nonzero(carrier_uint u) noexcept
+ {
+ return (u << 1) != 0;
+ }
+
+ static constexpr bool is_positive(carrier_uint u) noexcept
+ {
+ return u < (carrier_uint(1) << (format::significand_bits + format::exponent_bits));
+ }
+
+ static constexpr bool is_negative(carrier_uint u) noexcept
+ {
+ return !is_positive(u);
+ }
+
+ static constexpr bool is_finite(unsigned exponent_bits) noexcept
+ {
+ return exponent_bits != ((1u << format::exponent_bits) - 1);
+ }
+
+ static constexpr bool has_all_zero_significand_bits(carrier_uint u) noexcept
+ {
+ return (u << 1) == 0;
+ }
+
+ static constexpr bool has_even_significand_bits(carrier_uint u) noexcept
+ {
+ return u % 2 == 0;
+ }
+};
+
+// Convenient wrappers for floating-point traits classes.
+// In order to reduce the argument passing overhead, these classes should be as simple as
+// possible (e.g., no inheritance, no private non-static data member, etc.; this is an
+// unfortunate fact about common ABI convention).
+
+template <typename T, typename Traits = dragonbox_float_traits<T>>
+struct dragonbox_float_bits;
+
+template <typename T, typename Traits = dragonbox_float_traits<T>>
+struct dragonbox_signed_significand_bits;
+
+template <typename T, typename Traits>
+struct dragonbox_float_bits
+{
+ using type = T;
+ using traits_type = Traits;
+ using carrier_uint = typename traits_type::carrier_uint;
+
+ carrier_uint u;
+
+ dragonbox_float_bits() = default;
+ constexpr explicit dragonbox_float_bits(carrier_uint bit_pattern) noexcept : u{bit_pattern} {}
+ constexpr explicit dragonbox_float_bits(T float_value) noexcept
+ : u{traits_type::float_to_carrier(float_value)} {}
+
+ T to_float() const noexcept
+ {
+ return traits_type::carrier_to_float(u);
+ }
+
+ // Extract exponent bits from a bit pattern.
+ // The result must be aligned to the LSB so that there is no additional zero paddings
+ // on the right. This function does not do bias adjustment.
+ constexpr unsigned int extract_exponent_bits() const noexcept
+ {
+ return traits_type::extract_exponent_bits(u);
+ }
+
+ // Extract significand bits from a bit pattern.
+ // The result must be aligned to the LSB so that there is no additional zero paddings
+ // on the right. The result does not contain the implicit bit.
+ constexpr carrier_uint extract_significand_bits() const noexcept
+ {
+ return traits_type::extract_significand_bits(u);
+ }
+
+ // Remove the exponent bits and extract significand bits together with the sign bit.
+ constexpr auto remove_exponent_bits(unsigned int exponent_bits) const noexcept -> dragonbox_signed_significand_bits<type, traits_type>
+ {
+ return dragonbox_signed_significand_bits<type, traits_type>(traits_type::remove_exponent_bits(u, exponent_bits));
+ }
+
+ // Obtain the actual value of the binary exponent from the extracted exponent bits.
+ static constexpr int binary_exponent(unsigned exponent_bits) noexcept
+ {
+ return traits_type::binary_exponent(exponent_bits);
+ }
+
+ constexpr int binary_exponent() const noexcept
+ {
+ return binary_exponent(extract_exponent_bits());
+ }
+
+ // Obtain the actual value of the binary exponent from the extracted significand bits and
+ // exponent bits.
+ static constexpr carrier_uint binary_significand(carrier_uint significand_bits, unsigned exponent_bits) noexcept
+ {
+ return traits_type::binary_significand(significand_bits, exponent_bits);
+ }
+
+ constexpr carrier_uint binary_significand() const noexcept
+ {
+ return binary_significand(extract_significand_bits(), extract_exponent_bits());
+ }
+
+ constexpr bool is_nonzero() const noexcept
+ {
+ return traits_type::is_nonzero(u);
+ }
+
+ constexpr bool is_positive() const noexcept
+ {
+ return traits_type::is_positive(u);
+ }
+
+ constexpr bool is_negative() const noexcept
+ {
+ return traits_type::is_negative(u);
+ }
+
+ constexpr bool is_finite(unsigned exponent_bits) const noexcept
+ {
+ return traits_type::is_finite(exponent_bits);
+ }
+
+ constexpr bool is_finite() const noexcept
+ {
+ return traits_type::is_finite(extract_exponent_bits());
+ }
+
+ constexpr bool has_even_significand_bits() const noexcept
+ {
+ return traits_type::has_even_significand_bits(u);
+ }
+};
+
+template <typename T, typename Traits>
+struct dragonbox_signed_significand_bits
+{
+ using type = T;
+ using traits_type = Traits;
+ using carrier_uint = typename traits_type::carrier_uint;
+
+ carrier_uint u;
+
+ dragonbox_signed_significand_bits() = default;
+ constexpr explicit dragonbox_signed_significand_bits(carrier_uint bit_pattern) noexcept
+ : u{bit_pattern} {}
+
+ // Shift the obtained signed significand bits to the left by 1 to remove the sign bit.
+ constexpr carrier_uint remove_sign_bit_and_shift() const noexcept
+ {
+ return traits_type::remove_sign_bit_and_shift(u);
+ }
+
+ constexpr bool is_positive() const noexcept
+ {
+ return traits_type::is_positive(u);
+ }
+
+ constexpr bool is_negative() const noexcept
+ {
+ return traits_type::is_negative(u);
+ }
+
+ constexpr bool has_all_zero_significand_bits() const noexcept
+ {
+ return traits_type::has_all_zero_significand_bits(u);
+ }
+
+ constexpr bool has_even_significand_bits() const noexcept
+ {
+ return traits_type::has_even_significand_bits(u);
+ }
+};
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+ // Utilities for fast divisibility tests.
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ namespace div {
+ // Replace n by floor(n / 10^N).
+ // Returns true if and only if n is divisible by 10^N.
+ // Precondition: n <= 10^(N+1)
+ // !!It takes an in-out parameter!!
+ template <int N>
+ struct divide_by_pow10_info;
+
+ template <>
+ struct divide_by_pow10_info<1>
+ {
+ static constexpr std::uint32_t magic_number = 6554;
+ static constexpr int shift_amount = 16;
+ };
+
+ template <>
+ struct divide_by_pow10_info<2>
+ {
+ static constexpr std::uint32_t magic_number = 656;
+ static constexpr int shift_amount = 16;
+ };
+
+ template <int N>
+ BOOST_CXX14_CONSTEXPR bool check_divisibility_and_divide_by_pow10(std::uint32_t& n) noexcept
+ {
+ // Make sure the computation for max_n does not overflow.
+ // static_assert(N + 1 <= log::floor_log10_pow2(31));
+ BOOST_CHARCONV_ASSERT(n <= compute_power(UINT32_C(10), N + 1));
+
+ using info = divide_by_pow10_info<N>;
+ n *= info::magic_number;
+
+ constexpr auto mask = std::uint32_t(std::uint32_t(1) << info::shift_amount) - 1;
+ bool result = ((n & mask) < info::magic_number);
+
+ n >>= info::shift_amount;
+ return result;
+ }
+
+ // Compute floor(n / 10^N) for small n and N.
+ // Precondition: n <= 10^(N+1)
+ template <int N>
+ BOOST_CXX14_CONSTEXPR std::uint32_t small_division_by_pow10(std::uint32_t n) noexcept
+ {
+ // Make sure the computation for max_n does not overflow.
+ // static_assert(N + 1 <= log::floor_log10_pow2(31));
+ BOOST_CHARCONV_ASSERT(n <= compute_power(UINT32_C(10), N + 1));
+
+ return (n * divide_by_pow10_info<N>::magic_number) >> divide_by_pow10_info<N>::shift_amount;
+ }
+
+ // Compute floor(n / 10^N) for small N.
+ // Precondition: n <= n_max
+ template <unsigned N, typename UInt, UInt n_max>
+ BOOST_CXX14_CONSTEXPR UInt divide_by_pow10(UInt n) noexcept
+ {
+
+ // Specialize for 32-bit division by 100.
+ // Compiler is supposed to generate the identical code for just writing
+ // "n / 100", but for some reason MSVC generates an inefficient code
+ // (mul + mov for no apparent reason, instead of single imul),
+ // so we does this manually.
+ BOOST_IF_CONSTEXPR (std::is_same<UInt, std::uint32_t>::value && N == 2)
+ {
+ return static_cast<UInt>(umul64(static_cast<std::uint32_t>(n), UINT32_C(1374389535)) >> 37);
+ }
+ // Specialize for 64-bit division by 1000.
+ // Ensure that the correctness condition is met.
+ else BOOST_IF_CONSTEXPR (std::is_same<UInt, std::uint64_t>::value && N == 3 && n_max <= UINT64_C(15534100272597517998))
+ {
+ return static_cast<UInt>(umul128_upper64(n, UINT64_C(2361183241434822607)) >> 7);
+ }
+ else
+ {
+ BOOST_CXX14_CONSTEXPR auto divisor = compute_power(static_cast<UInt>(10), N);
+ return n / divisor;
+ }
+ }
+
+ #ifdef BOOST_MSVC
+ # pragma warning(push)
+ # pragma warning(disable: 4100) // MSVC 14.0 does not have BOOST_ATTRIBUTE_UNUSED so we disable the warning
+ #endif
+
+ template <typename UInt>
+ BOOST_CXX14_CONSTEXPR UInt divide_by_pow10(unsigned N, BOOST_ATTRIBUTE_UNUSED UInt n_max, UInt n) noexcept
+ {
+ BOOST_IF_CONSTEXPR (std::is_same<UInt, std::uint32_t>::value && N == 2)
+ {
+ return static_cast<UInt>(umul64(static_cast<std::uint32_t>(n), static_cast<std::uint32_t>(1374389535)) >> UINT32_C(37));
+ }
+ // Specialize for 64-bit division by 1000.
+ // Ensure that the correctness condition is met.
+ else BOOST_IF_CONSTEXPR (std::is_same<UInt, std::uint64_t>::value && N == 3 && n_max <= UINT64_C(15534100272597517998))
+ {
+ return static_cast<UInt>(umul128_upper64(n, UINT64_C(2361183241434822607)) >> 7);
+ }
+ else
+ {
+ auto divisor = compute_power(static_cast<UInt>(10), N);
+ return n / divisor;
+ }
+ }
+
+ #ifdef BOOST_MSVC
+ # pragma warning(pop)
+ #endif
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////
+// Return types for the main interface function.
+////////////////////////////////////////////////////////////////////////////////////////
+
+template <typename UInt, bool is_signed, bool trailing_zero_flag>
+struct decimal_fp;
+
+template <typename UInt>
+struct decimal_fp<UInt, false, false>
+{
+ using carrier_uint = UInt;
+
+ carrier_uint significand;
+ int exponent;
+};
+
+template <typename UInt>
+struct decimal_fp<UInt, true, false>
+{
+ using carrier_uint = UInt;
+
+ carrier_uint significand;
+ int exponent;
+ bool is_negative;
+};
+
+template <typename UInt>
+struct decimal_fp<UInt, false, true>
+{
+ using carrier_uint = UInt;
+
+ carrier_uint significand;
+ int exponent;
+ bool may_have_trailing_zeros;
+};
+
+template <typename UInt>
+struct decimal_fp<UInt, true, true>
+{
+ using carrier_uint = UInt;
+
+ carrier_uint significand;
+ int exponent;
+ bool is_negative;
+ bool may_have_trailing_zeros;
+};
+
+template <typename UInt>
+using unsigned_decimal_fp = decimal_fp<UInt, false, false>;
+
+template <typename UInt>
+using signed_decimal_fp = decimal_fp<UInt, true, false>;
+
+////////////////////////////////////////////////////////////////////////////////////////
+// Computed cache entries.
+////////////////////////////////////////////////////////////////////////////////////////
+
+#if (!defined(BOOST_MSVC) || BOOST_MSVC != 1900)
+template <bool b>
+struct cache_holder_ieee754_binary32_impl
+#else
+struct cache_holder_ieee754_binary32
+#endif
+{
+ using cache_entry_type = std::uint64_t;
+ static constexpr int cache_bits = 64;
+ static constexpr int min_k = -31;
+ static constexpr int max_k = 46;
+ static constexpr cache_entry_type cache[] = {
+ 0x81ceb32c4b43fcf5, 0xa2425ff75e14fc32, 0xcad2f7f5359a3b3f, 0xfd87b5f28300ca0e,
+ 0x9e74d1b791e07e49, 0xc612062576589ddb, 0xf79687aed3eec552, 0x9abe14cd44753b53,
+ 0xc16d9a0095928a28, 0xf1c90080baf72cb2, 0x971da05074da7bef, 0xbce5086492111aeb,
+ 0xec1e4a7db69561a6, 0x9392ee8e921d5d08, 0xb877aa3236a4b44a, 0xe69594bec44de15c,
+ 0x901d7cf73ab0acda, 0xb424dc35095cd810, 0xe12e13424bb40e14, 0x8cbccc096f5088cc,
+ 0xafebff0bcb24aaff, 0xdbe6fecebdedd5bf, 0x89705f4136b4a598, 0xabcc77118461cefd,
+ 0xd6bf94d5e57a42bd, 0x8637bd05af6c69b6, 0xa7c5ac471b478424, 0xd1b71758e219652c,
+ 0x83126e978d4fdf3c, 0xa3d70a3d70a3d70b, 0xcccccccccccccccd, 0x8000000000000000,
+ 0xa000000000000000, 0xc800000000000000, 0xfa00000000000000, 0x9c40000000000000,
+ 0xc350000000000000, 0xf424000000000000, 0x9896800000000000, 0xbebc200000000000,
+ 0xee6b280000000000, 0x9502f90000000000, 0xba43b74000000000, 0xe8d4a51000000000,
+ 0x9184e72a00000000, 0xb5e620f480000000, 0xe35fa931a0000000, 0x8e1bc9bf04000000,
+ 0xb1a2bc2ec5000000, 0xde0b6b3a76400000, 0x8ac7230489e80000, 0xad78ebc5ac620000,
+ 0xd8d726b7177a8000, 0x878678326eac9000, 0xa968163f0a57b400, 0xd3c21bcecceda100,
+ 0x84595161401484a0, 0xa56fa5b99019a5c8, 0xcecb8f27f4200f3a, 0x813f3978f8940985,
+ 0xa18f07d736b90be6, 0xc9f2c9cd04674edf, 0xfc6f7c4045812297, 0x9dc5ada82b70b59e,
+ 0xc5371912364ce306, 0xf684df56c3e01bc7, 0x9a130b963a6c115d, 0xc097ce7bc90715b4,
+ 0xf0bdc21abb48db21, 0x96769950b50d88f5, 0xbc143fa4e250eb32, 0xeb194f8e1ae525fe,
+ 0x92efd1b8d0cf37bf, 0xb7abc627050305ae, 0xe596b7b0c643c71a, 0x8f7e32ce7bea5c70,
+ 0xb35dbf821ae4f38c, 0xe0352f62a19e306f};
+};
+
+#if defined(BOOST_NO_CXX17_INLINE_VARIABLES) && (!defined(BOOST_MSVC) || BOOST_MSVC != 1900)
+
+template <bool b> constexpr int cache_holder_ieee754_binary32_impl<b>::cache_bits;
+template <bool b> constexpr int cache_holder_ieee754_binary32_impl<b>::min_k;
+template <bool b> constexpr int cache_holder_ieee754_binary32_impl<b>::max_k;
+template <bool b> constexpr typename cache_holder_ieee754_binary32_impl<b>::cache_entry_type cache_holder_ieee754_binary32_impl<b>::cache[];
+
+#endif
+
+#if (!defined(BOOST_MSVC) || BOOST_MSVC != 1900)
+using cache_holder_ieee754_binary32 = cache_holder_ieee754_binary32_impl<true>;
+#endif
+
+#if (!defined(BOOST_MSVC) || BOOST_MSVC != 1900)
+template <bool b>
+struct cache_holder_ieee754_binary64_impl
+#else
+struct cache_holder_ieee754_binary64
+#endif
+{
+ using cache_entry_type = uint128;
+ static constexpr int cache_bits = 128;
+ static constexpr int min_k = -292;
+ static constexpr int max_k = 326;
+ static constexpr cache_entry_type cache[] = {
+ {0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7b}, {0x9faacf3df73609b1, 0x77b191618c54e9ad},
+ {0xc795830d75038c1d, 0xd59df5b9ef6a2418}, {0xf97ae3d0d2446f25, 0x4b0573286b44ad1e},
+ {0x9becce62836ac577, 0x4ee367f9430aec33}, {0xc2e801fb244576d5, 0x229c41f793cda740},
+ {0xf3a20279ed56d48a, 0x6b43527578c11110}, {0x9845418c345644d6, 0x830a13896b78aaaa},
+ {0xbe5691ef416bd60c, 0x23cc986bc656d554}, {0xedec366b11c6cb8f, 0x2cbfbe86b7ec8aa9},
+ {0x94b3a202eb1c3f39, 0x7bf7d71432f3d6aa}, {0xb9e08a83a5e34f07, 0xdaf5ccd93fb0cc54},
+ {0xe858ad248f5c22c9, 0xd1b3400f8f9cff69}, {0x91376c36d99995be, 0x23100809b9c21fa2},
+ {0xb58547448ffffb2d, 0xabd40a0c2832a78b}, {0xe2e69915b3fff9f9, 0x16c90c8f323f516d},
+ {0x8dd01fad907ffc3b, 0xae3da7d97f6792e4}, {0xb1442798f49ffb4a, 0x99cd11cfdf41779d},
+ {0xdd95317f31c7fa1d, 0x40405643d711d584}, {0x8a7d3eef7f1cfc52, 0x482835ea666b2573},
+ {0xad1c8eab5ee43b66, 0xda3243650005eed0}, {0xd863b256369d4a40, 0x90bed43e40076a83},
+ {0x873e4f75e2224e68, 0x5a7744a6e804a292}, {0xa90de3535aaae202, 0x711515d0a205cb37},
+ {0xd3515c2831559a83, 0x0d5a5b44ca873e04}, {0x8412d9991ed58091, 0xe858790afe9486c3},
+ {0xa5178fff668ae0b6, 0x626e974dbe39a873}, {0xce5d73ff402d98e3, 0xfb0a3d212dc81290},
+ {0x80fa687f881c7f8e, 0x7ce66634bc9d0b9a}, {0xa139029f6a239f72, 0x1c1fffc1ebc44e81},
+ {0xc987434744ac874e, 0xa327ffb266b56221}, {0xfbe9141915d7a922, 0x4bf1ff9f0062baa9},
+ {0x9d71ac8fada6c9b5, 0x6f773fc3603db4aa}, {0xc4ce17b399107c22, 0xcb550fb4384d21d4},
+ {0xf6019da07f549b2b, 0x7e2a53a146606a49}, {0x99c102844f94e0fb, 0x2eda7444cbfc426e},
+ {0xc0314325637a1939, 0xfa911155fefb5309}, {0xf03d93eebc589f88, 0x793555ab7eba27cb},
+ {0x96267c7535b763b5, 0x4bc1558b2f3458df}, {0xbbb01b9283253ca2, 0x9eb1aaedfb016f17},
+ {0xea9c227723ee8bcb, 0x465e15a979c1cadd}, {0x92a1958a7675175f, 0x0bfacd89ec191eca},
+ {0xb749faed14125d36, 0xcef980ec671f667c}, {0xe51c79a85916f484, 0x82b7e12780e7401b},
+ {0x8f31cc0937ae58d2, 0xd1b2ecb8b0908811}, {0xb2fe3f0b8599ef07, 0x861fa7e6dcb4aa16},
+ {0xdfbdcece67006ac9, 0x67a791e093e1d49b}, {0x8bd6a141006042bd, 0xe0c8bb2c5c6d24e1},
+ {0xaecc49914078536d, 0x58fae9f773886e19}, {0xda7f5bf590966848, 0xaf39a475506a899f},
+ {0x888f99797a5e012d, 0x6d8406c952429604}, {0xaab37fd7d8f58178, 0xc8e5087ba6d33b84},
+ {0xd5605fcdcf32e1d6, 0xfb1e4a9a90880a65}, {0x855c3be0a17fcd26, 0x5cf2eea09a550680},
+ {0xa6b34ad8c9dfc06f, 0xf42faa48c0ea481f}, {0xd0601d8efc57b08b, 0xf13b94daf124da27},
+ {0x823c12795db6ce57, 0x76c53d08d6b70859}, {0xa2cb1717b52481ed, 0x54768c4b0c64ca6f},
+ {0xcb7ddcdda26da268, 0xa9942f5dcf7dfd0a}, {0xfe5d54150b090b02, 0xd3f93b35435d7c4d},
+ {0x9efa548d26e5a6e1, 0xc47bc5014a1a6db0}, {0xc6b8e9b0709f109a, 0x359ab6419ca1091c},
+ {0xf867241c8cc6d4c0, 0xc30163d203c94b63}, {0x9b407691d7fc44f8, 0x79e0de63425dcf1e},
+ {0xc21094364dfb5636, 0x985915fc12f542e5}, {0xf294b943e17a2bc4, 0x3e6f5b7b17b2939e},
+ {0x979cf3ca6cec5b5a, 0xa705992ceecf9c43}, {0xbd8430bd08277231, 0x50c6ff782a838354},
+ {0xece53cec4a314ebd, 0xa4f8bf5635246429}, {0x940f4613ae5ed136, 0x871b7795e136be9a},
+ {0xb913179899f68584, 0x28e2557b59846e40}, {0xe757dd7ec07426e5, 0x331aeada2fe589d0},
+ {0x9096ea6f3848984f, 0x3ff0d2c85def7622}, {0xb4bca50b065abe63, 0x0fed077a756b53aa},
+ {0xe1ebce4dc7f16dfb, 0xd3e8495912c62895}, {0x8d3360f09cf6e4bd, 0x64712dd7abbbd95d},
+ {0xb080392cc4349dec, 0xbd8d794d96aacfb4}, {0xdca04777f541c567, 0xecf0d7a0fc5583a1},
+ {0x89e42caaf9491b60, 0xf41686c49db57245}, {0xac5d37d5b79b6239, 0x311c2875c522ced6},
+ {0xd77485cb25823ac7, 0x7d633293366b828c}, {0x86a8d39ef77164bc, 0xae5dff9c02033198},
+ {0xa8530886b54dbdeb, 0xd9f57f830283fdfd}, {0xd267caa862a12d66, 0xd072df63c324fd7c},
+ {0x8380dea93da4bc60, 0x4247cb9e59f71e6e}, {0xa46116538d0deb78, 0x52d9be85f074e609},
+ {0xcd795be870516656, 0x67902e276c921f8c}, {0x806bd9714632dff6, 0x00ba1cd8a3db53b7},
+ {0xa086cfcd97bf97f3, 0x80e8a40eccd228a5}, {0xc8a883c0fdaf7df0, 0x6122cd128006b2ce},
+ {0xfad2a4b13d1b5d6c, 0x796b805720085f82}, {0x9cc3a6eec6311a63, 0xcbe3303674053bb1},
+ {0xc3f490aa77bd60fc, 0xbedbfc4411068a9d}, {0xf4f1b4d515acb93b, 0xee92fb5515482d45},
+ {0x991711052d8bf3c5, 0x751bdd152d4d1c4b}, {0xbf5cd54678eef0b6, 0xd262d45a78a0635e},
+ {0xef340a98172aace4, 0x86fb897116c87c35}, {0x9580869f0e7aac0e, 0xd45d35e6ae3d4da1},
+ {0xbae0a846d2195712, 0x8974836059cca10a}, {0xe998d258869facd7, 0x2bd1a438703fc94c},
+ {0x91ff83775423cc06, 0x7b6306a34627ddd0}, {0xb67f6455292cbf08, 0x1a3bc84c17b1d543},
+ {0xe41f3d6a7377eeca, 0x20caba5f1d9e4a94}, {0x8e938662882af53e, 0x547eb47b7282ee9d},
+ {0xb23867fb2a35b28d, 0xe99e619a4f23aa44}, {0xdec681f9f4c31f31, 0x6405fa00e2ec94d5},
+ {0x8b3c113c38f9f37e, 0xde83bc408dd3dd05}, {0xae0b158b4738705e, 0x9624ab50b148d446},
+ {0xd98ddaee19068c76, 0x3badd624dd9b0958}, {0x87f8a8d4cfa417c9, 0xe54ca5d70a80e5d7},
+ {0xa9f6d30a038d1dbc, 0x5e9fcf4ccd211f4d}, {0xd47487cc8470652b, 0x7647c32000696720},
+ {0x84c8d4dfd2c63f3b, 0x29ecd9f40041e074}, {0xa5fb0a17c777cf09, 0xf468107100525891},
+ {0xcf79cc9db955c2cc, 0x7182148d4066eeb5}, {0x81ac1fe293d599bf, 0xc6f14cd848405531},
+ {0xa21727db38cb002f, 0xb8ada00e5a506a7d}, {0xca9cf1d206fdc03b, 0xa6d90811f0e4851d},
+ {0xfd442e4688bd304a, 0x908f4a166d1da664}, {0x9e4a9cec15763e2e, 0x9a598e4e043287ff},
+ {0xc5dd44271ad3cdba, 0x40eff1e1853f29fe}, {0xf7549530e188c128, 0xd12bee59e68ef47d},
+ {0x9a94dd3e8cf578b9, 0x82bb74f8301958cf}, {0xc13a148e3032d6e7, 0xe36a52363c1faf02},
+ {0xf18899b1bc3f8ca1, 0xdc44e6c3cb279ac2}, {0x96f5600f15a7b7e5, 0x29ab103a5ef8c0ba},
+ {0xbcb2b812db11a5de, 0x7415d448f6b6f0e8}, {0xebdf661791d60f56, 0x111b495b3464ad22},
+ {0x936b9fcebb25c995, 0xcab10dd900beec35}, {0xb84687c269ef3bfb, 0x3d5d514f40eea743},
+ {0xe65829b3046b0afa, 0x0cb4a5a3112a5113}, {0x8ff71a0fe2c2e6dc, 0x47f0e785eaba72ac},
+ {0xb3f4e093db73a093, 0x59ed216765690f57}, {0xe0f218b8d25088b8, 0x306869c13ec3532d},
+ {0x8c974f7383725573, 0x1e414218c73a13fc}, {0xafbd2350644eeacf, 0xe5d1929ef90898fb},
+ {0xdbac6c247d62a583, 0xdf45f746b74abf3a}, {0x894bc396ce5da772, 0x6b8bba8c328eb784},
+ {0xab9eb47c81f5114f, 0x066ea92f3f326565}, {0xd686619ba27255a2, 0xc80a537b0efefebe},
+ {0x8613fd0145877585, 0xbd06742ce95f5f37}, {0xa798fc4196e952e7, 0x2c48113823b73705},
+ {0xd17f3b51fca3a7a0, 0xf75a15862ca504c6}, {0x82ef85133de648c4, 0x9a984d73dbe722fc},
+ {0xa3ab66580d5fdaf5, 0xc13e60d0d2e0ebbb}, {0xcc963fee10b7d1b3, 0x318df905079926a9},
+ {0xffbbcfe994e5c61f, 0xfdf17746497f7053}, {0x9fd561f1fd0f9bd3, 0xfeb6ea8bedefa634},
+ {0xc7caba6e7c5382c8, 0xfe64a52ee96b8fc1}, {0xf9bd690a1b68637b, 0x3dfdce7aa3c673b1},
+ {0x9c1661a651213e2d, 0x06bea10ca65c084f}, {0xc31bfa0fe5698db8, 0x486e494fcff30a63},
+ {0xf3e2f893dec3f126, 0x5a89dba3c3efccfb}, {0x986ddb5c6b3a76b7, 0xf89629465a75e01d},
+ {0xbe89523386091465, 0xf6bbb397f1135824}, {0xee2ba6c0678b597f, 0x746aa07ded582e2d},
+ {0x94db483840b717ef, 0xa8c2a44eb4571cdd}, {0xba121a4650e4ddeb, 0x92f34d62616ce414},
+ {0xe896a0d7e51e1566, 0x77b020baf9c81d18}, {0x915e2486ef32cd60, 0x0ace1474dc1d122f},
+ {0xb5b5ada8aaff80b8, 0x0d819992132456bb}, {0xe3231912d5bf60e6, 0x10e1fff697ed6c6a},
+ {0x8df5efabc5979c8f, 0xca8d3ffa1ef463c2}, {0xb1736b96b6fd83b3, 0xbd308ff8a6b17cb3},
+ {0xddd0467c64bce4a0, 0xac7cb3f6d05ddbdf}, {0x8aa22c0dbef60ee4, 0x6bcdf07a423aa96c},
+ {0xad4ab7112eb3929d, 0x86c16c98d2c953c7}, {0xd89d64d57a607744, 0xe871c7bf077ba8b8},
+ {0x87625f056c7c4a8b, 0x11471cd764ad4973}, {0xa93af6c6c79b5d2d, 0xd598e40d3dd89bd0},
+ {0xd389b47879823479, 0x4aff1d108d4ec2c4}, {0x843610cb4bf160cb, 0xcedf722a585139bb},
+ {0xa54394fe1eedb8fe, 0xc2974eb4ee658829}, {0xce947a3da6a9273e, 0x733d226229feea33},
+ {0x811ccc668829b887, 0x0806357d5a3f5260}, {0xa163ff802a3426a8, 0xca07c2dcb0cf26f8},
+ {0xc9bcff6034c13052, 0xfc89b393dd02f0b6}, {0xfc2c3f3841f17c67, 0xbbac2078d443ace3},
+ {0x9d9ba7832936edc0, 0xd54b944b84aa4c0e}, {0xc5029163f384a931, 0x0a9e795e65d4df12},
+ {0xf64335bcf065d37d, 0x4d4617b5ff4a16d6}, {0x99ea0196163fa42e, 0x504bced1bf8e4e46},
+ {0xc06481fb9bcf8d39, 0xe45ec2862f71e1d7}, {0xf07da27a82c37088, 0x5d767327bb4e5a4d},
+ {0x964e858c91ba2655, 0x3a6a07f8d510f870}, {0xbbe226efb628afea, 0x890489f70a55368c},
+ {0xeadab0aba3b2dbe5, 0x2b45ac74ccea842f}, {0x92c8ae6b464fc96f, 0x3b0b8bc90012929e},
+ {0xb77ada0617e3bbcb, 0x09ce6ebb40173745}, {0xe55990879ddcaabd, 0xcc420a6a101d0516},
+ {0x8f57fa54c2a9eab6, 0x9fa946824a12232e}, {0xb32df8e9f3546564, 0x47939822dc96abfa},
+ {0xdff9772470297ebd, 0x59787e2b93bc56f8}, {0x8bfbea76c619ef36, 0x57eb4edb3c55b65b},
+ {0xaefae51477a06b03, 0xede622920b6b23f2}, {0xdab99e59958885c4, 0xe95fab368e45ecee},
+ {0x88b402f7fd75539b, 0x11dbcb0218ebb415}, {0xaae103b5fcd2a881, 0xd652bdc29f26a11a},
+ {0xd59944a37c0752a2, 0x4be76d3346f04960}, {0x857fcae62d8493a5, 0x6f70a4400c562ddc},
+ {0xa6dfbd9fb8e5b88e, 0xcb4ccd500f6bb953}, {0xd097ad07a71f26b2, 0x7e2000a41346a7a8},
+ {0x825ecc24c873782f, 0x8ed400668c0c28c9}, {0xa2f67f2dfa90563b, 0x728900802f0f32fb},
+ {0xcbb41ef979346bca, 0x4f2b40a03ad2ffba}, {0xfea126b7d78186bc, 0xe2f610c84987bfa9},
+ {0x9f24b832e6b0f436, 0x0dd9ca7d2df4d7ca}, {0xc6ede63fa05d3143, 0x91503d1c79720dbc},
+ {0xf8a95fcf88747d94, 0x75a44c6397ce912b}, {0x9b69dbe1b548ce7c, 0xc986afbe3ee11abb},
+ {0xc24452da229b021b, 0xfbe85badce996169}, {0xf2d56790ab41c2a2, 0xfae27299423fb9c4},
+ {0x97c560ba6b0919a5, 0xdccd879fc967d41b}, {0xbdb6b8e905cb600f, 0x5400e987bbc1c921},
+ {0xed246723473e3813, 0x290123e9aab23b69}, {0x9436c0760c86e30b, 0xf9a0b6720aaf6522},
+ {0xb94470938fa89bce, 0xf808e40e8d5b3e6a}, {0xe7958cb87392c2c2, 0xb60b1d1230b20e05},
+ {0x90bd77f3483bb9b9, 0xb1c6f22b5e6f48c3}, {0xb4ecd5f01a4aa828, 0x1e38aeb6360b1af4},
+ {0xe2280b6c20dd5232, 0x25c6da63c38de1b1}, {0x8d590723948a535f, 0x579c487e5a38ad0f},
+ {0xb0af48ec79ace837, 0x2d835a9df0c6d852}, {0xdcdb1b2798182244, 0xf8e431456cf88e66},
+ {0x8a08f0f8bf0f156b, 0x1b8e9ecb641b5900}, {0xac8b2d36eed2dac5, 0xe272467e3d222f40},
+ {0xd7adf884aa879177, 0x5b0ed81dcc6abb10}, {0x86ccbb52ea94baea, 0x98e947129fc2b4ea},
+ {0xa87fea27a539e9a5, 0x3f2398d747b36225}, {0xd29fe4b18e88640e, 0x8eec7f0d19a03aae},
+ {0x83a3eeeef9153e89, 0x1953cf68300424ad}, {0xa48ceaaab75a8e2b, 0x5fa8c3423c052dd8},
+ {0xcdb02555653131b6, 0x3792f412cb06794e}, {0x808e17555f3ebf11, 0xe2bbd88bbee40bd1},
+ {0xa0b19d2ab70e6ed6, 0x5b6aceaeae9d0ec5}, {0xc8de047564d20a8b, 0xf245825a5a445276},
+ {0xfb158592be068d2e, 0xeed6e2f0f0d56713}, {0x9ced737bb6c4183d, 0x55464dd69685606c},
+ {0xc428d05aa4751e4c, 0xaa97e14c3c26b887}, {0xf53304714d9265df, 0xd53dd99f4b3066a9},
+ {0x993fe2c6d07b7fab, 0xe546a8038efe402a}, {0xbf8fdb78849a5f96, 0xde98520472bdd034},
+ {0xef73d256a5c0f77c, 0x963e66858f6d4441}, {0x95a8637627989aad, 0xdde7001379a44aa9},
+ {0xbb127c53b17ec159, 0x5560c018580d5d53}, {0xe9d71b689dde71af, 0xaab8f01e6e10b4a7},
+ {0x9226712162ab070d, 0xcab3961304ca70e9}, {0xb6b00d69bb55c8d1, 0x3d607b97c5fd0d23},
+ {0xe45c10c42a2b3b05, 0x8cb89a7db77c506b}, {0x8eb98a7a9a5b04e3, 0x77f3608e92adb243},
+ {0xb267ed1940f1c61c, 0x55f038b237591ed4}, {0xdf01e85f912e37a3, 0x6b6c46dec52f6689},
+ {0x8b61313bbabce2c6, 0x2323ac4b3b3da016}, {0xae397d8aa96c1b77, 0xabec975e0a0d081b},
+ {0xd9c7dced53c72255, 0x96e7bd358c904a22}, {0x881cea14545c7575, 0x7e50d64177da2e55},
+ {0xaa242499697392d2, 0xdde50bd1d5d0b9ea}, {0xd4ad2dbfc3d07787, 0x955e4ec64b44e865},
+ {0x84ec3c97da624ab4, 0xbd5af13bef0b113f}, {0xa6274bbdd0fadd61, 0xecb1ad8aeacdd58f},
+ {0xcfb11ead453994ba, 0x67de18eda5814af3}, {0x81ceb32c4b43fcf4, 0x80eacf948770ced8},
+ {0xa2425ff75e14fc31, 0xa1258379a94d028e}, {0xcad2f7f5359a3b3e, 0x096ee45813a04331},
+ {0xfd87b5f28300ca0d, 0x8bca9d6e188853fd}, {0x9e74d1b791e07e48, 0x775ea264cf55347e},
+ {0xc612062576589dda, 0x95364afe032a819e}, {0xf79687aed3eec551, 0x3a83ddbd83f52205},
+ {0x9abe14cd44753b52, 0xc4926a9672793543}, {0xc16d9a0095928a27, 0x75b7053c0f178294},
+ {0xf1c90080baf72cb1, 0x5324c68b12dd6339}, {0x971da05074da7bee, 0xd3f6fc16ebca5e04},
+ {0xbce5086492111aea, 0x88f4bb1ca6bcf585}, {0xec1e4a7db69561a5, 0x2b31e9e3d06c32e6},
+ {0x9392ee8e921d5d07, 0x3aff322e62439fd0}, {0xb877aa3236a4b449, 0x09befeb9fad487c3},
+ {0xe69594bec44de15b, 0x4c2ebe687989a9b4}, {0x901d7cf73ab0acd9, 0x0f9d37014bf60a11},
+ {0xb424dc35095cd80f, 0x538484c19ef38c95}, {0xe12e13424bb40e13, 0x2865a5f206b06fba},
+ {0x8cbccc096f5088cb, 0xf93f87b7442e45d4}, {0xafebff0bcb24aafe, 0xf78f69a51539d749},
+ {0xdbe6fecebdedd5be, 0xb573440e5a884d1c}, {0x89705f4136b4a597, 0x31680a88f8953031},
+ {0xabcc77118461cefc, 0xfdc20d2b36ba7c3e}, {0xd6bf94d5e57a42bc, 0x3d32907604691b4d},
+ {0x8637bd05af6c69b5, 0xa63f9a49c2c1b110}, {0xa7c5ac471b478423, 0x0fcf80dc33721d54},
+ {0xd1b71758e219652b, 0xd3c36113404ea4a9}, {0x83126e978d4fdf3b, 0x645a1cac083126ea},
+ {0xa3d70a3d70a3d70a, 0x3d70a3d70a3d70a4}, {0xcccccccccccccccc, 0xcccccccccccccccd},
+ {0x8000000000000000, 0x0000000000000000}, {0xa000000000000000, 0x0000000000000000},
+ {0xc800000000000000, 0x0000000000000000}, {0xfa00000000000000, 0x0000000000000000},
+ {0x9c40000000000000, 0x0000000000000000}, {0xc350000000000000, 0x0000000000000000},
+ {0xf424000000000000, 0x0000000000000000}, {0x9896800000000000, 0x0000000000000000},
+ {0xbebc200000000000, 0x0000000000000000}, {0xee6b280000000000, 0x0000000000000000},
+ {0x9502f90000000000, 0x0000000000000000}, {0xba43b74000000000, 0x0000000000000000},
+ {0xe8d4a51000000000, 0x0000000000000000}, {0x9184e72a00000000, 0x0000000000000000},
+ {0xb5e620f480000000, 0x0000000000000000}, {0xe35fa931a0000000, 0x0000000000000000},
+ {0x8e1bc9bf04000000, 0x0000000000000000}, {0xb1a2bc2ec5000000, 0x0000000000000000},
+ {0xde0b6b3a76400000, 0x0000000000000000}, {0x8ac7230489e80000, 0x0000000000000000},
+ {0xad78ebc5ac620000, 0x0000000000000000}, {0xd8d726b7177a8000, 0x0000000000000000},
+ {0x878678326eac9000, 0x0000000000000000}, {0xa968163f0a57b400, 0x0000000000000000},
+ {0xd3c21bcecceda100, 0x0000000000000000}, {0x84595161401484a0, 0x0000000000000000},
+ {0xa56fa5b99019a5c8, 0x0000000000000000}, {0xcecb8f27f4200f3a, 0x0000000000000000},
+ {0x813f3978f8940984, 0x4000000000000000}, {0xa18f07d736b90be5, 0x5000000000000000},
+ {0xc9f2c9cd04674ede, 0xa400000000000000}, {0xfc6f7c4045812296, 0x4d00000000000000},
+ {0x9dc5ada82b70b59d, 0xf020000000000000}, {0xc5371912364ce305, 0x6c28000000000000},
+ {0xf684df56c3e01bc6, 0xc732000000000000}, {0x9a130b963a6c115c, 0x3c7f400000000000},
+ {0xc097ce7bc90715b3, 0x4b9f100000000000}, {0xf0bdc21abb48db20, 0x1e86d40000000000},
+ {0x96769950b50d88f4, 0x1314448000000000}, {0xbc143fa4e250eb31, 0x17d955a000000000},
+ {0xeb194f8e1ae525fd, 0x5dcfab0800000000}, {0x92efd1b8d0cf37be, 0x5aa1cae500000000},
+ {0xb7abc627050305ad, 0xf14a3d9e40000000}, {0xe596b7b0c643c719, 0x6d9ccd05d0000000},
+ {0x8f7e32ce7bea5c6f, 0xe4820023a2000000}, {0xb35dbf821ae4f38b, 0xdda2802c8a800000},
+ {0xe0352f62a19e306e, 0xd50b2037ad200000}, {0x8c213d9da502de45, 0x4526f422cc340000},
+ {0xaf298d050e4395d6, 0x9670b12b7f410000}, {0xdaf3f04651d47b4c, 0x3c0cdd765f114000},
+ {0x88d8762bf324cd0f, 0xa5880a69fb6ac800}, {0xab0e93b6efee0053, 0x8eea0d047a457a00},
+ {0xd5d238a4abe98068, 0x72a4904598d6d880}, {0x85a36366eb71f041, 0x47a6da2b7f864750},
+ {0xa70c3c40a64e6c51, 0x999090b65f67d924}, {0xd0cf4b50cfe20765, 0xfff4b4e3f741cf6d},
+ {0x82818f1281ed449f, 0xbff8f10e7a8921a5}, {0xa321f2d7226895c7, 0xaff72d52192b6a0e},
+ {0xcbea6f8ceb02bb39, 0x9bf4f8a69f764491}, {0xfee50b7025c36a08, 0x02f236d04753d5b5},
+ {0x9f4f2726179a2245, 0x01d762422c946591}, {0xc722f0ef9d80aad6, 0x424d3ad2b7b97ef6},
+ {0xf8ebad2b84e0d58b, 0xd2e0898765a7deb3}, {0x9b934c3b330c8577, 0x63cc55f49f88eb30},
+ {0xc2781f49ffcfa6d5, 0x3cbf6b71c76b25fc}, {0xf316271c7fc3908a, 0x8bef464e3945ef7b},
+ {0x97edd871cfda3a56, 0x97758bf0e3cbb5ad}, {0xbde94e8e43d0c8ec, 0x3d52eeed1cbea318},
+ {0xed63a231d4c4fb27, 0x4ca7aaa863ee4bde}, {0x945e455f24fb1cf8, 0x8fe8caa93e74ef6b},
+ {0xb975d6b6ee39e436, 0xb3e2fd538e122b45}, {0xe7d34c64a9c85d44, 0x60dbbca87196b617},
+ {0x90e40fbeea1d3a4a, 0xbc8955e946fe31ce}, {0xb51d13aea4a488dd, 0x6babab6398bdbe42},
+ {0xe264589a4dcdab14, 0xc696963c7eed2dd2}, {0x8d7eb76070a08aec, 0xfc1e1de5cf543ca3},
+ {0xb0de65388cc8ada8, 0x3b25a55f43294bcc}, {0xdd15fe86affad912, 0x49ef0eb713f39ebf},
+ {0x8a2dbf142dfcc7ab, 0x6e3569326c784338}, {0xacb92ed9397bf996, 0x49c2c37f07965405},
+ {0xd7e77a8f87daf7fb, 0xdc33745ec97be907}, {0x86f0ac99b4e8dafd, 0x69a028bb3ded71a4},
+ {0xa8acd7c0222311bc, 0xc40832ea0d68ce0d}, {0xd2d80db02aabd62b, 0xf50a3fa490c30191},
+ {0x83c7088e1aab65db, 0x792667c6da79e0fb}, {0xa4b8cab1a1563f52, 0x577001b891185939},
+ {0xcde6fd5e09abcf26, 0xed4c0226b55e6f87}, {0x80b05e5ac60b6178, 0x544f8158315b05b5},
+ {0xa0dc75f1778e39d6, 0x696361ae3db1c722}, {0xc913936dd571c84c, 0x03bc3a19cd1e38ea},
+ {0xfb5878494ace3a5f, 0x04ab48a04065c724}, {0x9d174b2dcec0e47b, 0x62eb0d64283f9c77},
+ {0xc45d1df942711d9a, 0x3ba5d0bd324f8395}, {0xf5746577930d6500, 0xca8f44ec7ee3647a},
+ {0x9968bf6abbe85f20, 0x7e998b13cf4e1ecc}, {0xbfc2ef456ae276e8, 0x9e3fedd8c321a67f},
+ {0xefb3ab16c59b14a2, 0xc5cfe94ef3ea101f}, {0x95d04aee3b80ece5, 0xbba1f1d158724a13},
+ {0xbb445da9ca61281f, 0x2a8a6e45ae8edc98}, {0xea1575143cf97226, 0xf52d09d71a3293be},
+ {0x924d692ca61be758, 0x593c2626705f9c57}, {0xb6e0c377cfa2e12e, 0x6f8b2fb00c77836d},
+ {0xe498f455c38b997a, 0x0b6dfb9c0f956448}, {0x8edf98b59a373fec, 0x4724bd4189bd5ead},
+ {0xb2977ee300c50fe7, 0x58edec91ec2cb658}, {0xdf3d5e9bc0f653e1, 0x2f2967b66737e3ee},
+ {0x8b865b215899f46c, 0xbd79e0d20082ee75}, {0xae67f1e9aec07187, 0xecd8590680a3aa12},
+ {0xda01ee641a708de9, 0xe80e6f4820cc9496}, {0x884134fe908658b2, 0x3109058d147fdcde},
+ {0xaa51823e34a7eede, 0xbd4b46f0599fd416}, {0xd4e5e2cdc1d1ea96, 0x6c9e18ac7007c91b},
+ {0x850fadc09923329e, 0x03e2cf6bc604ddb1}, {0xa6539930bf6bff45, 0x84db8346b786151d},
+ {0xcfe87f7cef46ff16, 0xe612641865679a64}, {0x81f14fae158c5f6e, 0x4fcb7e8f3f60c07f},
+ {0xa26da3999aef7749, 0xe3be5e330f38f09e}, {0xcb090c8001ab551c, 0x5cadf5bfd3072cc6},
+ {0xfdcb4fa002162a63, 0x73d9732fc7c8f7f7}, {0x9e9f11c4014dda7e, 0x2867e7fddcdd9afb},
+ {0xc646d63501a1511d, 0xb281e1fd541501b9}, {0xf7d88bc24209a565, 0x1f225a7ca91a4227},
+ {0x9ae757596946075f, 0x3375788de9b06959}, {0xc1a12d2fc3978937, 0x0052d6b1641c83af},
+ {0xf209787bb47d6b84, 0xc0678c5dbd23a49b}, {0x9745eb4d50ce6332, 0xf840b7ba963646e1},
+ {0xbd176620a501fbff, 0xb650e5a93bc3d899}, {0xec5d3fa8ce427aff, 0xa3e51f138ab4cebf},
+ {0x93ba47c980e98cdf, 0xc66f336c36b10138}, {0xb8a8d9bbe123f017, 0xb80b0047445d4185},
+ {0xe6d3102ad96cec1d, 0xa60dc059157491e6}, {0x9043ea1ac7e41392, 0x87c89837ad68db30},
+ {0xb454e4a179dd1877, 0x29babe4598c311fc}, {0xe16a1dc9d8545e94, 0xf4296dd6fef3d67b},
+ {0x8ce2529e2734bb1d, 0x1899e4a65f58660d}, {0xb01ae745b101e9e4, 0x5ec05dcff72e7f90},
+ {0xdc21a1171d42645d, 0x76707543f4fa1f74}, {0x899504ae72497eba, 0x6a06494a791c53a9},
+ {0xabfa45da0edbde69, 0x0487db9d17636893}, {0xd6f8d7509292d603, 0x45a9d2845d3c42b7},
+ {0x865b86925b9bc5c2, 0x0b8a2392ba45a9b3}, {0xa7f26836f282b732, 0x8e6cac7768d7141f},
+ {0xd1ef0244af2364ff, 0x3207d795430cd927}, {0x8335616aed761f1f, 0x7f44e6bd49e807b9},
+ {0xa402b9c5a8d3a6e7, 0x5f16206c9c6209a7}, {0xcd036837130890a1, 0x36dba887c37a8c10},
+ {0x802221226be55a64, 0xc2494954da2c978a}, {0xa02aa96b06deb0fd, 0xf2db9baa10b7bd6d},
+ {0xc83553c5c8965d3d, 0x6f92829494e5acc8}, {0xfa42a8b73abbf48c, 0xcb772339ba1f17fa},
+ {0x9c69a97284b578d7, 0xff2a760414536efc}, {0xc38413cf25e2d70d, 0xfef5138519684abb},
+ {0xf46518c2ef5b8cd1, 0x7eb258665fc25d6a}, {0x98bf2f79d5993802, 0xef2f773ffbd97a62},
+ {0xbeeefb584aff8603, 0xaafb550ffacfd8fb}, {0xeeaaba2e5dbf6784, 0x95ba2a53f983cf39},
+ {0x952ab45cfa97a0b2, 0xdd945a747bf26184}, {0xba756174393d88df, 0x94f971119aeef9e5},
+ {0xe912b9d1478ceb17, 0x7a37cd5601aab85e}, {0x91abb422ccb812ee, 0xac62e055c10ab33b},
+ {0xb616a12b7fe617aa, 0x577b986b314d600a}, {0xe39c49765fdf9d94, 0xed5a7e85fda0b80c},
+ {0x8e41ade9fbebc27d, 0x14588f13be847308}, {0xb1d219647ae6b31c, 0x596eb2d8ae258fc9},
+ {0xde469fbd99a05fe3, 0x6fca5f8ed9aef3bc}, {0x8aec23d680043bee, 0x25de7bb9480d5855},
+ {0xada72ccc20054ae9, 0xaf561aa79a10ae6b}, {0xd910f7ff28069da4, 0x1b2ba1518094da05},
+ {0x87aa9aff79042286, 0x90fb44d2f05d0843}, {0xa99541bf57452b28, 0x353a1607ac744a54},
+ {0xd3fa922f2d1675f2, 0x42889b8997915ce9}, {0x847c9b5d7c2e09b7, 0x69956135febada12},
+ {0xa59bc234db398c25, 0x43fab9837e699096}, {0xcf02b2c21207ef2e, 0x94f967e45e03f4bc},
+ {0x8161afb94b44f57d, 0x1d1be0eebac278f6}, {0xa1ba1ba79e1632dc, 0x6462d92a69731733},
+ {0xca28a291859bbf93, 0x7d7b8f7503cfdcff}, {0xfcb2cb35e702af78, 0x5cda735244c3d43f},
+ {0x9defbf01b061adab, 0x3a0888136afa64a8}, {0xc56baec21c7a1916, 0x088aaa1845b8fdd1},
+ {0xf6c69a72a3989f5b, 0x8aad549e57273d46}, {0x9a3c2087a63f6399, 0x36ac54e2f678864c},
+ {0xc0cb28a98fcf3c7f, 0x84576a1bb416a7de}, {0xf0fdf2d3f3c30b9f, 0x656d44a2a11c51d6},
+ {0x969eb7c47859e743, 0x9f644ae5a4b1b326}, {0xbc4665b596706114, 0x873d5d9f0dde1fef},
+ {0xeb57ff22fc0c7959, 0xa90cb506d155a7eb}, {0x9316ff75dd87cbd8, 0x09a7f12442d588f3},
+ {0xb7dcbf5354e9bece, 0x0c11ed6d538aeb30}, {0xe5d3ef282a242e81, 0x8f1668c8a86da5fb},
+ {0x8fa475791a569d10, 0xf96e017d694487bd}, {0xb38d92d760ec4455, 0x37c981dcc395a9ad},
+ {0xe070f78d3927556a, 0x85bbe253f47b1418}, {0x8c469ab843b89562, 0x93956d7478ccec8f},
+ {0xaf58416654a6babb, 0x387ac8d1970027b3}, {0xdb2e51bfe9d0696a, 0x06997b05fcc0319f},
+ {0x88fcf317f22241e2, 0x441fece3bdf81f04}, {0xab3c2fddeeaad25a, 0xd527e81cad7626c4},
+ {0xd60b3bd56a5586f1, 0x8a71e223d8d3b075}, {0x85c7056562757456, 0xf6872d5667844e4a},
+ {0xa738c6bebb12d16c, 0xb428f8ac016561dc}, {0xd106f86e69d785c7, 0xe13336d701beba53},
+ {0x82a45b450226b39c, 0xecc0024661173474}, {0xa34d721642b06084, 0x27f002d7f95d0191},
+ {0xcc20ce9bd35c78a5, 0x31ec038df7b441f5}, {0xff290242c83396ce, 0x7e67047175a15272},
+ {0x9f79a169bd203e41, 0x0f0062c6e984d387}, {0xc75809c42c684dd1, 0x52c07b78a3e60869},
+ {0xf92e0c3537826145, 0xa7709a56ccdf8a83}, {0x9bbcc7a142b17ccb, 0x88a66076400bb692},
+ {0xc2abf989935ddbfe, 0x6acff893d00ea436}, {0xf356f7ebf83552fe, 0x0583f6b8c4124d44},
+ {0x98165af37b2153de, 0xc3727a337a8b704b}, {0xbe1bf1b059e9a8d6, 0x744f18c0592e4c5d},
+ {0xeda2ee1c7064130c, 0x1162def06f79df74}, {0x9485d4d1c63e8be7, 0x8addcb5645ac2ba9},
+ {0xb9a74a0637ce2ee1, 0x6d953e2bd7173693}, {0xe8111c87c5c1ba99, 0xc8fa8db6ccdd0438},
+ {0x910ab1d4db9914a0, 0x1d9c9892400a22a3}, {0xb54d5e4a127f59c8, 0x2503beb6d00cab4c},
+ {0xe2a0b5dc971f303a, 0x2e44ae64840fd61e}, {0x8da471a9de737e24, 0x5ceaecfed289e5d3},
+ {0xb10d8e1456105dad, 0x7425a83e872c5f48}, {0xdd50f1996b947518, 0xd12f124e28f7771a},
+ {0x8a5296ffe33cc92f, 0x82bd6b70d99aaa70}, {0xace73cbfdc0bfb7b, 0x636cc64d1001550c},
+ {0xd8210befd30efa5a, 0x3c47f7e05401aa4f}, {0x8714a775e3e95c78, 0x65acfaec34810a72},
+ {0xa8d9d1535ce3b396, 0x7f1839a741a14d0e}, {0xd31045a8341ca07c, 0x1ede48111209a051},
+ {0x83ea2b892091e44d, 0x934aed0aab460433}, {0xa4e4b66b68b65d60, 0xf81da84d56178540},
+ {0xce1de40642e3f4b9, 0x36251260ab9d668f}, {0x80d2ae83e9ce78f3, 0xc1d72b7c6b42601a},
+ {0xa1075a24e4421730, 0xb24cf65b8612f820}, {0xc94930ae1d529cfc, 0xdee033f26797b628},
+ {0xfb9b7cd9a4a7443c, 0x169840ef017da3b2}, {0x9d412e0806e88aa5, 0x8e1f289560ee864f},
+ {0xc491798a08a2ad4e, 0xf1a6f2bab92a27e3}, {0xf5b5d7ec8acb58a2, 0xae10af696774b1dc},
+ {0x9991a6f3d6bf1765, 0xacca6da1e0a8ef2a}, {0xbff610b0cc6edd3f, 0x17fd090a58d32af4},
+ {0xeff394dcff8a948e, 0xddfc4b4cef07f5b1}, {0x95f83d0a1fb69cd9, 0x4abdaf101564f98f},
+ {0xbb764c4ca7a4440f, 0x9d6d1ad41abe37f2}, {0xea53df5fd18d5513, 0x84c86189216dc5ee},
+ {0x92746b9be2f8552c, 0x32fd3cf5b4e49bb5}, {0xb7118682dbb66a77, 0x3fbc8c33221dc2a2},
+ {0xe4d5e82392a40515, 0x0fabaf3feaa5334b}, {0x8f05b1163ba6832d, 0x29cb4d87f2a7400f},
+ {0xb2c71d5bca9023f8, 0x743e20e9ef511013}, {0xdf78e4b2bd342cf6, 0x914da9246b255417},
+ {0x8bab8eefb6409c1a, 0x1ad089b6c2f7548f}, {0xae9672aba3d0c320, 0xa184ac2473b529b2},
+ {0xda3c0f568cc4f3e8, 0xc9e5d72d90a2741f}, {0x8865899617fb1871, 0x7e2fa67c7a658893},
+ {0xaa7eebfb9df9de8d, 0xddbb901b98feeab8}, {0xd51ea6fa85785631, 0x552a74227f3ea566},
+ {0x8533285c936b35de, 0xd53a88958f872760}, {0xa67ff273b8460356, 0x8a892abaf368f138},
+ {0xd01fef10a657842c, 0x2d2b7569b0432d86}, {0x8213f56a67f6b29b, 0x9c3b29620e29fc74},
+ {0xa298f2c501f45f42, 0x8349f3ba91b47b90}, {0xcb3f2f7642717713, 0x241c70a936219a74},
+ {0xfe0efb53d30dd4d7, 0xed238cd383aa0111}, {0x9ec95d1463e8a506, 0xf4363804324a40ab},
+ {0xc67bb4597ce2ce48, 0xb143c6053edcd0d6}, {0xf81aa16fdc1b81da, 0xdd94b7868e94050b},
+ {0x9b10a4e5e9913128, 0xca7cf2b4191c8327}, {0xc1d4ce1f63f57d72, 0xfd1c2f611f63a3f1},
+ {0xf24a01a73cf2dccf, 0xbc633b39673c8ced}, {0x976e41088617ca01, 0xd5be0503e085d814},
+ {0xbd49d14aa79dbc82, 0x4b2d8644d8a74e19}, {0xec9c459d51852ba2, 0xddf8e7d60ed1219f},
+ {0x93e1ab8252f33b45, 0xcabb90e5c942b504}, {0xb8da1662e7b00a17, 0x3d6a751f3b936244},
+ {0xe7109bfba19c0c9d, 0x0cc512670a783ad5}, {0x906a617d450187e2, 0x27fb2b80668b24c6},
+ {0xb484f9dc9641e9da, 0xb1f9f660802dedf7}, {0xe1a63853bbd26451, 0x5e7873f8a0396974},
+ {0x8d07e33455637eb2, 0xdb0b487b6423e1e9}, {0xb049dc016abc5e5f, 0x91ce1a9a3d2cda63},
+ {0xdc5c5301c56b75f7, 0x7641a140cc7810fc}, {0x89b9b3e11b6329ba, 0xa9e904c87fcb0a9e},
+ {0xac2820d9623bf429, 0x546345fa9fbdcd45}, {0xd732290fbacaf133, 0xa97c177947ad4096},
+ {0x867f59a9d4bed6c0, 0x49ed8eabcccc485e}, {0xa81f301449ee8c70, 0x5c68f256bfff5a75},
+ {0xd226fc195c6a2f8c, 0x73832eec6fff3112}, {0x83585d8fd9c25db7, 0xc831fd53c5ff7eac},
+ {0xa42e74f3d032f525, 0xba3e7ca8b77f5e56}, {0xcd3a1230c43fb26f, 0x28ce1bd2e55f35ec},
+ {0x80444b5e7aa7cf85, 0x7980d163cf5b81b4}, {0xa0555e361951c366, 0xd7e105bcc3326220},
+ {0xc86ab5c39fa63440, 0x8dd9472bf3fefaa8}, {0xfa856334878fc150, 0xb14f98f6f0feb952},
+ {0x9c935e00d4b9d8d2, 0x6ed1bf9a569f33d4}, {0xc3b8358109e84f07, 0x0a862f80ec4700c9},
+ {0xf4a642e14c6262c8, 0xcd27bb612758c0fb}, {0x98e7e9cccfbd7dbd, 0x8038d51cb897789d},
+ {0xbf21e44003acdd2c, 0xe0470a63e6bd56c4}, {0xeeea5d5004981478, 0x1858ccfce06cac75},
+ {0x95527a5202df0ccb, 0x0f37801e0c43ebc9}, {0xbaa718e68396cffd, 0xd30560258f54e6bb},
+ {0xe950df20247c83fd, 0x47c6b82ef32a206a}, {0x91d28b7416cdd27e, 0x4cdc331d57fa5442},
+ {0xb6472e511c81471d, 0xe0133fe4adf8e953}, {0xe3d8f9e563a198e5, 0x58180fddd97723a7},
+ {0x8e679c2f5e44ff8f, 0x570f09eaa7ea7649}, {0xb201833b35d63f73, 0x2cd2cc6551e513db},
+ {0xde81e40a034bcf4f, 0xf8077f7ea65e58d2}, {0x8b112e86420f6191, 0xfb04afaf27faf783},
+ {0xadd57a27d29339f6, 0x79c5db9af1f9b564}, {0xd94ad8b1c7380874, 0x18375281ae7822bd},
+ {0x87cec76f1c830548, 0x8f2293910d0b15b6}, {0xa9c2794ae3a3c69a, 0xb2eb3875504ddb23},
+ {0xd433179d9c8cb841, 0x5fa60692a46151ec}, {0x849feec281d7f328, 0xdbc7c41ba6bcd334},
+ {0xa5c7ea73224deff3, 0x12b9b522906c0801}, {0xcf39e50feae16bef, 0xd768226b34870a01},
+ {0x81842f29f2cce375, 0xe6a1158300d46641}, {0xa1e53af46f801c53, 0x60495ae3c1097fd1},
+ {0xca5e89b18b602368, 0x385bb19cb14bdfc5}, {0xfcf62c1dee382c42, 0x46729e03dd9ed7b6},
+ {0x9e19db92b4e31ba9, 0x6c07a2c26a8346d2}, {0xc5a05277621be293, 0xc7098b7305241886},
+ {0xf70867153aa2db38, 0xb8cbee4fc66d1ea8}};
+};
+
+#if defined(BOOST_NO_CXX17_INLINE_VARIABLES) && (!defined(BOOST_MSVC) || BOOST_MSVC != 1900)
+
+template <bool b> constexpr int cache_holder_ieee754_binary64_impl<b>::cache_bits;
+template <bool b> constexpr int cache_holder_ieee754_binary64_impl<b>::min_k;
+template <bool b> constexpr int cache_holder_ieee754_binary64_impl<b>::max_k;
+template <bool b> constexpr typename cache_holder_ieee754_binary64_impl<b>::cache_entry_type cache_holder_ieee754_binary64_impl<b>::cache[];
+
+#endif
+
+#if (!defined(BOOST_MSVC) || BOOST_MSVC != 1900)
+using cache_holder_ieee754_binary64 = cache_holder_ieee754_binary64_impl<true>;
+#endif
+
+////////////////////////////////////////////////////////////////////////////////////////
+// Policies.
+////////////////////////////////////////////////////////////////////////////////////////
+
+// Forward declare the implementation class.
+template <typename Float, typename FloatTraits = dragonbox_float_traits<Float>>
+struct impl;
+
+namespace policy_impl {
+// Sign policies.
+namespace sign {
+ struct base {};
+
+ struct ignore : base
+ {
+ using sign_policy = ignore;
+ static constexpr bool return_has_sign = false;
+
+ template <typename SignedSignificandBits, typename ReturnType>
+ static BOOST_CXX14_CONSTEXPR void handle_sign(SignedSignificandBits, ReturnType&) noexcept {}
+ };
+
+ struct return_sign : base
+ {
+ using sign_policy = return_sign;
+ static constexpr bool return_has_sign = true;
+
+ template <typename SignedSignificandBits, typename ReturnType>
+ static BOOST_CXX14_CONSTEXPR void handle_sign(SignedSignificandBits s, ReturnType& r) noexcept
+ {
+ r.is_negative = s.is_negative();
+ }
+ };
+}
+
+// Trailing zero policies.
+namespace trailing_zero {
+ struct base {};
+
+ struct ignore : base
+ {
+ using trailing_zero_policy = ignore;
+ static constexpr bool report_trailing_zeros = false;
+
+ template <typename Impl, typename ReturnType>
+ static BOOST_CXX14_CONSTEXPR void on_trailing_zeros(ReturnType&) noexcept {}
+
+ template <typename Impl, typename ReturnType>
+ static BOOST_CXX14_CONSTEXPR void no_trailing_zeros(ReturnType&) noexcept {}
+ };
+
+ struct remove : base
+ {
+ using trailing_zero_policy = remove;
+ static constexpr bool report_trailing_zeros = false;
+
+ template <typename Impl, typename ReturnType>
+ BOOST_FORCEINLINE static void on_trailing_zeros(ReturnType& r) noexcept
+ {
+ r.exponent += Impl::remove_trailing_zeros(r.significand);
+ }
+
+ template <typename Impl, typename ReturnType>
+ static BOOST_CXX14_CONSTEXPR void no_trailing_zeros(ReturnType&) noexcept {}
+ };
+
+ struct report : base
+ {
+ using trailing_zero_policy = report;
+ static constexpr bool report_trailing_zeros = true;
+
+ template <typename Impl, typename ReturnType>
+ static BOOST_CXX14_CONSTEXPR void on_trailing_zeros(ReturnType& r) noexcept
+ {
+ r.may_have_trailing_zeros = true;
+ }
+
+ template <typename Impl, typename ReturnType>
+ static BOOST_CXX14_CONSTEXPR void no_trailing_zeros(ReturnType& r) noexcept
+ {
+ r.may_have_trailing_zeros = false;
+ }
+ };
+}
+
+// Decimal-to-binary rounding mode policies.
+namespace decimal_to_binary_rounding {
+ struct base {};
+
+ enum class tag_t
+ {
+ to_nearest,
+ left_closed_directed,
+ right_closed_directed
+ };
+
+ namespace interval_type {
+ struct symmetric_boundary
+ {
+ static constexpr bool is_symmetric = true;
+ bool is_closed;
+ constexpr bool include_left_endpoint() const noexcept { return is_closed; }
+ constexpr bool include_right_endpoint() const noexcept { return is_closed; }
+ };
+
+ struct asymmetric_boundary
+ {
+ static constexpr bool is_symmetric = false;
+ bool is_left_closed;
+ constexpr bool include_left_endpoint() const noexcept { return is_left_closed; }
+ constexpr bool include_right_endpoint() const noexcept { return !is_left_closed; }
+ };
+
+ struct closed
+ {
+ static constexpr bool is_symmetric = true;
+ static constexpr bool include_left_endpoint() noexcept { return true; }
+ static constexpr bool include_right_endpoint() noexcept { return true; }
+ };
+
+ struct open
+ {
+ static constexpr bool is_symmetric = true;
+ static constexpr bool include_left_endpoint() noexcept { return false; }
+ static constexpr bool include_right_endpoint() noexcept { return false; }
+ };
+
+ struct left_closed_right_open
+ {
+ static constexpr bool is_symmetric = false;
+ static constexpr bool include_left_endpoint() noexcept { return true; }
+ static constexpr bool include_right_endpoint() noexcept { return false; }
+ };
+
+ struct right_closed_left_open
+ {
+ static constexpr bool is_symmetric = false;
+ static constexpr bool include_left_endpoint() noexcept { return false; }
+ static constexpr bool include_right_endpoint() noexcept { return true; }
+ };
+ }
+
+ template <typename T>
+ struct return_type : return_type<decltype(&T::operator())>
+ {};
+
+ struct nearest_to_even : base
+ {
+ using decimal_to_binary_rounding_policy = nearest_to_even;
+ static constexpr auto tag = tag_t::to_nearest;
+ using normal_interval_type = interval_type::symmetric_boundary;
+ using shorter_interval_type = interval_type::closed;
+
+ template <typename ReturnType, typename SignedSignificandBits, typename Func>
+ BOOST_FORCEINLINE static ReturnType delegate(SignedSignificandBits, Func f) noexcept
+ {
+ return f(nearest_to_even{});
+ }
+
+ template <typename ReturnType, typename SignedSignificandBits, typename Func>
+ BOOST_FORCEINLINE static constexpr ReturnType
+ invoke_normal_interval_case(SignedSignificandBits s, Func&& f) noexcept
+ {
+ return f(s.has_even_significand_bits());
+ }
+
+ template <typename ReturnType, typename SignedSignificandBits, typename Func>
+ BOOST_FORCEINLINE static constexpr ReturnType
+ invoke_shorter_interval_case(SignedSignificandBits, Func&& f) noexcept
+ {
+ return f();
+ }
+ };
+
+ struct nearest_to_odd : base
+ {
+ using decimal_to_binary_rounding_policy = nearest_to_odd;
+ static constexpr auto tag = tag_t::to_nearest;
+ using normal_interval_type = interval_type::symmetric_boundary;
+ using shorter_interval_type = interval_type::open;
+
+ template <typename ReturnType, typename SignedSignificandBits, typename Func>
+ BOOST_FORCEINLINE static ReturnType delegate(SignedSignificandBits, Func&& f) noexcept
+ {
+ return f(nearest_to_odd{});
+ }
+
+ template <typename ReturnType, typename SignedSignificandBits, typename Func>
+ BOOST_FORCEINLINE static constexpr ReturnType
+ invoke_normal_interval_case(SignedSignificandBits s, Func&& f) noexcept
+ {
+ return f(!s.has_even_significand_bits());
+ }
+
+ template <typename ReturnType, typename SignedSignificandBits, typename Func>
+ BOOST_FORCEINLINE static constexpr ReturnType
+ invoke_shorter_interval_case(SignedSignificandBits, Func&& f) noexcept
+ {
+ return f();
+ }
+ };
+
+ struct nearest_toward_plus_infinity : base
+ {
+ using decimal_to_binary_rounding_policy = nearest_toward_plus_infinity;
+ static constexpr auto tag = tag_t::to_nearest;
+ using normal_interval_type = interval_type::asymmetric_boundary;
+ using shorter_interval_type = interval_type::asymmetric_boundary;
+
+ template <typename ReturnType, typename SignedSignificandBits, typename Func>
+ BOOST_FORCEINLINE static ReturnType delegate(SignedSignificandBits, Func&& f) noexcept
+ {
+ return f(nearest_toward_plus_infinity{});
+ }
+
+ template <typename ReturnType, typename SignedSignificandBits, typename Func>
+ BOOST_FORCEINLINE static constexpr ReturnType
+ invoke_normal_interval_case(SignedSignificandBits s, Func&& f) noexcept
+ {
+ return f(!s.is_negative());
+ }
+
+ template <typename ReturnType, typename SignedSignificandBits, typename Func>
+ BOOST_FORCEINLINE static constexpr ReturnType
+ invoke_shorter_interval_case(SignedSignificandBits s, Func&& f) noexcept
+ {
+ return f(!s.is_negative());
+ }
+ };
+
+ struct nearest_toward_minus_infinity : base
+ {
+ using decimal_to_binary_rounding_policy = nearest_toward_minus_infinity;
+ static constexpr auto tag = tag_t::to_nearest;
+ using normal_interval_type = interval_type::asymmetric_boundary;
+ using shorter_interval_type = interval_type::asymmetric_boundary;
+
+ template <typename ReturnType, typename SignedSignificandBits, typename Func>
+ BOOST_FORCEINLINE static ReturnType delegate(SignedSignificandBits, Func&& f) noexcept
+ {
+ return f(nearest_toward_minus_infinity{});
+ }
+
+ template <typename ReturnType, typename SignedSignificandBits, typename Func>
+ BOOST_FORCEINLINE static constexpr ReturnType
+ invoke_normal_interval_case(SignedSignificandBits s, Func&& f) noexcept
+ {
+ return f(s.is_negative());
+ }
+
+ template <typename ReturnType, typename SignedSignificandBits, typename Func>
+ BOOST_FORCEINLINE static constexpr ReturnType
+ invoke_shorter_interval_case(SignedSignificandBits s, Func&& f) noexcept
+ {
+ return f(s.is_negative());
+ }
+ };
+
+ struct nearest_toward_zero : base
+ {
+ using decimal_to_binary_rounding_policy = nearest_toward_zero;
+ static constexpr auto tag = tag_t::to_nearest;
+ using normal_interval_type = interval_type::right_closed_left_open;
+ using shorter_interval_type = interval_type::right_closed_left_open;
+
+ template <typename ReturnType, typename SignedSignificandBits, typename Func>
+ BOOST_FORCEINLINE static ReturnType delegate(SignedSignificandBits, Func&& f) noexcept
+ {
+ return f(nearest_toward_zero{});
+ }
+
+ template <typename ReturnType, typename SignedSignificandBits, typename Func>
+ BOOST_FORCEINLINE static constexpr ReturnType
+ invoke_normal_interval_case(SignedSignificandBits, Func&& f) noexcept
+ {
+ return f();
+ }
+
+ template <typename ReturnType, typename SignedSignificandBits, typename Func>
+ BOOST_FORCEINLINE static constexpr ReturnType
+ invoke_shorter_interval_case(SignedSignificandBits, Func&& f) noexcept
+ {
+ return f();
+ }
+ };
+
+ struct nearest_away_from_zero : base
+ {
+ using decimal_to_binary_rounding_policy = nearest_away_from_zero;
+ static constexpr auto tag = tag_t::to_nearest;
+ using normal_interval_type = interval_type::left_closed_right_open;
+ using shorter_interval_type = interval_type::left_closed_right_open;
+
+ template <typename ReturnType, typename SignedSignificandBits, typename Func>
+ BOOST_FORCEINLINE static ReturnType delegate(SignedSignificandBits, Func&& f) noexcept
+ {
+ return f(nearest_away_from_zero{});
+ }
+
+ template <typename ReturnType, typename SignedSignificandBits, typename Func>
+ BOOST_FORCEINLINE static constexpr ReturnType
+ invoke_normal_interval_case(SignedSignificandBits, Func&& f) noexcept
+ {
+ return f();
+ }
+
+ template <typename ReturnType, typename SignedSignificandBits, typename Func>
+ BOOST_FORCEINLINE static constexpr ReturnType
+ invoke_shorter_interval_case(SignedSignificandBits, Func&& f) noexcept
+ {
+ return f();
+ }
+ };
+
+ struct nearest_always_closed
+ {
+ static constexpr auto tag = tag_t::to_nearest;
+ using normal_interval_type = interval_type::closed;
+ using shorter_interval_type = interval_type::closed;
+
+ template <typename ReturnType, typename SignedSignificandBits, typename Func>
+ BOOST_FORCEINLINE static constexpr ReturnType
+ invoke_normal_interval_case(SignedSignificandBits, Func&& f) noexcept
+ {
+ return f();
+ }
+
+ template <typename ReturnType, typename SignedSignificandBits, typename Func>
+ BOOST_FORCEINLINE static constexpr ReturnType
+ invoke_shorter_interval_case(SignedSignificandBits, Func&& f) noexcept
+ {
+ return f();
+ }
+ };
+
+ struct nearest_always_open
+ {
+ static constexpr auto tag = tag_t::to_nearest;
+ using normal_interval_type = interval_type::open;
+ using shorter_interval_type = interval_type::open;
+
+ template <typename ReturnType, typename SignedSignificandBits, typename Func>
+ BOOST_FORCEINLINE static constexpr ReturnType
+ invoke_normal_interval_case(SignedSignificandBits, Func&& f) noexcept
+ {
+ return f();
+ }
+
+ template <typename ReturnType, typename SignedSignificandBits, typename Func>
+ BOOST_FORCEINLINE static constexpr ReturnType
+ invoke_shorter_interval_case(SignedSignificandBits, Func&& f) noexcept
+ {
+ return f();
+ }
+ };
+
+ struct nearest_to_even_static_boundary : base
+ {
+ using decimal_to_binary_rounding_policy = nearest_to_even_static_boundary;
+
+ template <typename ReturnType, typename SignedSignificandBits, typename Func>
+ BOOST_FORCEINLINE static ReturnType delegate(SignedSignificandBits s, Func&& f) noexcept
+ {
+ if (s.has_even_significand_bits())
+ {
+ return f(nearest_always_closed{});
+ }
+ else
+ {
+ return f(nearest_always_open{});
+ }
+ }
+ };
+
+ struct nearest_to_odd_static_boundary : base
+ {
+ using decimal_to_binary_rounding_policy = nearest_to_odd_static_boundary;
+
+ template <typename ReturnType, typename SignedSignificandBits, typename Func>
+ BOOST_FORCEINLINE static ReturnType delegate(SignedSignificandBits s, Func&& f) noexcept
+ {
+ if (s.has_even_significand_bits())
+ {
+ return f(nearest_always_open{});
+ }
+ else
+ {
+ return f(nearest_always_closed{});
+ }
+ }
+ };
+ struct nearest_toward_plus_infinity_static_boundary : base
+ {
+ using decimal_to_binary_rounding_policy = nearest_toward_plus_infinity_static_boundary;
+
+ template <typename ReturnType, typename SignedSignificandBits, typename Func>
+ BOOST_FORCEINLINE static ReturnType delegate(SignedSignificandBits s, Func&& f) noexcept
+ {
+ if (s.is_negative())
+ {
+ return f(nearest_toward_zero{});
+ }
+ else
+ {
+ return f(nearest_away_from_zero{});
+ }
+ }
+ };
+
+ struct nearest_toward_minus_infinity_static_boundary : base
+ {
+ using decimal_to_binary_rounding_policy = nearest_toward_minus_infinity_static_boundary;
+
+ template <typename ReturnType, typename SignedSignificandBits, typename Func>
+ BOOST_FORCEINLINE static ReturnType delegate(SignedSignificandBits s, Func&& f) noexcept
+ {
+ if (s.is_negative())
+ {
+ return f(nearest_away_from_zero{});
+ }
+ else
+ {
+ return f(nearest_toward_zero{});
+ }
+ }
+ };
+
+ struct left_closed_directed
+ {
+ static constexpr auto tag = tag_t::left_closed_directed;
+ };
+ struct right_closed_directed
+ {
+ static constexpr auto tag = tag_t::right_closed_directed;
+ };
+
+ struct toward_plus_infinity : base
+ {
+ using decimal_to_binary_rounding_policy = toward_plus_infinity;
+
+ template <typename ReturnType, typename SignedSignificandBits, typename Func>
+ BOOST_FORCEINLINE static ReturnType delegate(SignedSignificandBits s, Func&& f) noexcept
+ {
+ if (s.is_negative())
+ {
+ return f(left_closed_directed{});
+ }
+ else
+ {
+ return f(right_closed_directed{});
+ }
+ }
+ };
+
+ struct toward_minus_infinity : base
+ {
+ using decimal_to_binary_rounding_policy = toward_minus_infinity;
+
+ template <typename ReturnType, typename SignedSignificandBits, typename Func>
+ BOOST_FORCEINLINE static ReturnType delegate(SignedSignificandBits s, Func&& f) noexcept
+ {
+ if (s.is_negative())
+ {
+ return f(right_closed_directed{});
+ }
+ else
+ {
+ return f(left_closed_directed{});
+ }
+ }
+ };
+
+ struct toward_zero : base
+ {
+ using decimal_to_binary_rounding_policy = toward_zero;
+
+ template <typename ReturnType, typename SignedSignificandBits, typename Func>
+ BOOST_FORCEINLINE static ReturnType delegate(SignedSignificandBits, Func&& f) noexcept
+ {
+ return f(left_closed_directed{});
+ }
+ };
+
+ struct away_from_zero : base
+ {
+ using decimal_to_binary_rounding_policy = away_from_zero;
+
+ template <typename ReturnType, typename SignedSignificandBits, typename Func>
+ BOOST_FORCEINLINE static ReturnType delegate(SignedSignificandBits, Func&& f) noexcept
+ {
+ return f(right_closed_directed{});
+ }
+ };
+}
+
+// Binary-to-decimal rounding policies.
+// (Always assumes nearest rounding modes.)
+namespace binary_to_decimal_rounding {
+ struct base {};
+
+ enum class tag_t
+ {
+ do_not_care,
+ to_even,
+ to_odd,
+ away_from_zero,
+ toward_zero
+ };
+
+ struct do_not_care : base
+ {
+ using binary_to_decimal_rounding_policy = do_not_care;
+ static constexpr auto tag = tag_t::do_not_care;
+
+ template <typename ReturnType>
+ static constexpr bool prefer_round_down(ReturnType const&) noexcept
+ {
+ return false;
+ }
+ };
+
+ struct to_even : base
+ {
+ using binary_to_decimal_rounding_policy = to_even;
+ static constexpr auto tag = tag_t::to_even;
+
+ template <typename ReturnType>
+ static constexpr bool prefer_round_down(ReturnType const& r) noexcept
+ {
+ return r.significand % 2 != 0;
+ }
+ };
+
+ struct to_odd : base
+ {
+ using binary_to_decimal_rounding_policy = to_odd;
+ static constexpr auto tag = tag_t::to_odd;
+
+ template <typename ReturnType>
+ static constexpr bool prefer_round_down(ReturnType const& r) noexcept
+ {
+ return r.significand % 2 == 0;
+ }
+ };
+
+ struct away_from_zero : base
+ {
+ using binary_to_decimal_rounding_policy = away_from_zero;
+ static constexpr auto tag = tag_t::away_from_zero;
+
+ template <typename ReturnType>
+ static constexpr bool prefer_round_down(ReturnType const&) noexcept
+ {
+ return false;
+ }
+ };
+
+ struct toward_zero : base
+ {
+ using binary_to_decimal_rounding_policy = toward_zero;
+ static constexpr auto tag = tag_t::toward_zero;
+
+ template <typename ReturnType>
+ static constexpr bool prefer_round_down(ReturnType const&) noexcept
+ {
+ return true;
+ }
+ };
+}
+
+// Cache policies.
+namespace cache {
+ struct base {};
+
+ struct full : base
+ {
+ using cache_policy = full;
+
+ template <typename FloatFormat, typename cache_format = typename std::conditional<std::is_same<FloatFormat, ieee754_binary32>::value,
+ cache_holder_ieee754_binary32,
+ cache_holder_ieee754_binary64>::type>
+ static constexpr typename cache_format::cache_entry_type get_cache(int k) noexcept
+ {
+ return cache_format::cache[std::size_t(k - cache_format::min_k)];
+ }
+ };
+}
+}
+
+namespace policy {
+namespace sign {
+ BOOST_INLINE_VARIABLE constexpr auto ignore = detail::policy_impl::sign::ignore{};
+ BOOST_INLINE_VARIABLE constexpr auto return_sign = detail::policy_impl::sign::return_sign{};
+}
+
+namespace trailing_zero {
+ BOOST_INLINE_VARIABLE constexpr auto ignore = detail::policy_impl::trailing_zero::ignore{};
+ BOOST_INLINE_VARIABLE constexpr auto remove = detail::policy_impl::trailing_zero::remove{};
+ BOOST_INLINE_VARIABLE constexpr auto report = detail::policy_impl::trailing_zero::report{};
+}
+
+namespace decimal_to_binary_rounding {
+ BOOST_INLINE_VARIABLE constexpr auto nearest_to_even =
+ detail::policy_impl::decimal_to_binary_rounding::nearest_to_even{};
+ BOOST_INLINE_VARIABLE constexpr auto nearest_to_odd =
+ detail::policy_impl::decimal_to_binary_rounding::nearest_to_odd{};
+ BOOST_INLINE_VARIABLE constexpr auto nearest_toward_plus_infinity =
+ detail::policy_impl::decimal_to_binary_rounding::nearest_toward_plus_infinity{};
+ BOOST_INLINE_VARIABLE constexpr auto nearest_toward_minus_infinity =
+ detail::policy_impl::decimal_to_binary_rounding::nearest_toward_minus_infinity{};
+ BOOST_INLINE_VARIABLE constexpr auto nearest_toward_zero =
+ detail::policy_impl::decimal_to_binary_rounding::nearest_toward_zero{};
+ BOOST_INLINE_VARIABLE constexpr auto nearest_away_from_zero =
+ detail::policy_impl::decimal_to_binary_rounding::nearest_away_from_zero{};
+
+ BOOST_INLINE_VARIABLE constexpr auto nearest_to_even_static_boundary =
+ detail::policy_impl::decimal_to_binary_rounding::nearest_to_even_static_boundary{};
+ BOOST_INLINE_VARIABLE constexpr auto nearest_to_odd_static_boundary =
+ detail::policy_impl::decimal_to_binary_rounding::nearest_to_odd_static_boundary{};
+ BOOST_INLINE_VARIABLE constexpr auto nearest_toward_plus_infinity_static_boundary =
+ detail::policy_impl::decimal_to_binary_rounding::
+ nearest_toward_plus_infinity_static_boundary{};
+ BOOST_INLINE_VARIABLE constexpr auto nearest_toward_minus_infinity_static_boundary =
+ detail::policy_impl::decimal_to_binary_rounding::
+ nearest_toward_minus_infinity_static_boundary{};
+
+ BOOST_INLINE_VARIABLE constexpr auto toward_plus_infinity =
+ detail::policy_impl::decimal_to_binary_rounding::toward_plus_infinity{};
+ BOOST_INLINE_VARIABLE constexpr auto toward_minus_infinity =
+ detail::policy_impl::decimal_to_binary_rounding::toward_minus_infinity{};
+ BOOST_INLINE_VARIABLE constexpr auto toward_zero =
+ detail::policy_impl::decimal_to_binary_rounding::toward_zero{};
+ BOOST_INLINE_VARIABLE constexpr auto away_from_zero =
+ detail::policy_impl::decimal_to_binary_rounding::away_from_zero{};
+}
+
+namespace binary_to_decimal_rounding {
+ BOOST_INLINE_VARIABLE constexpr auto do_not_care =
+ detail::policy_impl::binary_to_decimal_rounding::do_not_care{};
+ BOOST_INLINE_VARIABLE constexpr auto to_even =
+ detail::policy_impl::binary_to_decimal_rounding::to_even{};
+ BOOST_INLINE_VARIABLE constexpr auto to_odd =
+ detail::policy_impl::binary_to_decimal_rounding::to_odd{};
+ BOOST_INLINE_VARIABLE constexpr auto away_from_zero =
+ detail::policy_impl::binary_to_decimal_rounding::away_from_zero{};
+ BOOST_INLINE_VARIABLE constexpr auto toward_zero =
+ detail::policy_impl::binary_to_decimal_rounding::toward_zero{};
+}
+
+namespace cache {
+ BOOST_INLINE_VARIABLE constexpr auto full = detail::policy_impl::cache::full{};
+}
+} // Namespace Policy
+
+////////////////////////////////////////////////////////////////////////////////////////
+// The main algorithm.
+////////////////////////////////////////////////////////////////////////////////////////
+
+template <typename Float, typename FloatTraits>
+struct impl : private FloatTraits, private FloatTraits::format
+{
+ using format = typename FloatTraits::format;
+ using carrier_uint = typename FloatTraits::carrier_uint;
+
+ using FloatTraits::carrier_bits;
+ using format::significand_bits;
+ using format::min_exponent;
+ using format::max_exponent;
+ using format::exponent_bias;
+ using format::decimal_digits;
+
+ static constexpr int kappa = std::is_same<format, ieee754_binary32>::value ? 1 : 2;
+ static_assert(kappa >= 1, "Kappa must be >= 1");
+ // static_assert(carrier_bits >= significand_bits + 2 + log::floor_log2_pow10(kappa + 1));
+
+ static constexpr int min_k_a = -log::floor_log10_pow2_minus_log10_4_over_3(int(max_exponent - significand_bits));
+ static constexpr int min_k_b = -log::floor_log10_pow2(int(max_exponent - significand_bits)) + kappa;
+ static constexpr int min_k = min_k_a < min_k_b ? min_k_a : min_k_b;
+ // static_assert(min_k >= cache_holder<format>::min_k, "Min k is not in the cache");
+
+ static constexpr int max_k_a = -log::floor_log10_pow2_minus_log10_4_over_3(int(min_exponent - significand_bits /*+ 1*/));
+ static constexpr int max_k_b = -log::floor_log10_pow2(int(min_exponent - significand_bits)) + kappa;
+ static constexpr int max_k = max_k_a > max_k_b ? max_k_a : max_k_b;
+
+ using cache_format = typename std::conditional<std::is_same<format, ieee754_binary32>::value,
+ cache_holder_ieee754_binary32,
+ cache_holder_ieee754_binary64>::type;
+ using cache_entry_type = typename cache_format::cache_entry_type;
+ static constexpr auto cache_bits = cache_format::cache_bits;
+
+ static constexpr int case_shorter_interval_left_endpoint_lower_threshold = 2;
+ static BOOST_CXX14_CONSTEXPR const int case_shorter_interval_left_endpoint_upper_threshold = 3;
+ //2 + log::floor_log2(compute_power(10, count_factors<5>((carrier_uint(1) << (significand_bits + 2)) - 1) + 1) / 3);
+
+ static constexpr int case_shorter_interval_right_endpoint_lower_threshold = 0;
+ static BOOST_CXX14_CONSTEXPR const int case_shorter_interval_right_endpoint_upper_threshold = 3;
+ //2 + log::floor_log2(compute_power(10, count_factors<5>((carrier_uint(1) << (significand_bits + 1)) + 1) + 1) / 3);
+
+ static constexpr int shorter_interval_tie_lower_threshold =
+ -log::floor_log5_pow2_minus_log5_3(significand_bits + 4) - 2 - significand_bits;
+ static constexpr int shorter_interval_tie_upper_threshold =
+ -log::floor_log5_pow2(significand_bits + 2) - 2 - significand_bits;
+
+ struct compute_mul_result
+ {
+ carrier_uint result;
+ bool is_integer;
+ };
+
+ struct compute_mul_parity_result
+ {
+ bool parity;
+ bool is_integer;
+ };
+
+ //// The main algorithm assumes the input is a normal/subnormal finite number
+
+ #if defined(__GNUC__) && (__GNUC__ < 5) && !defined(__clang__)
+ # pragma GCC diagnostic push
+ # pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+ #endif
+
+ template <typename ReturnType, typename IntervalType, typename TrailingZeroPolicy,
+ typename BinaryToDecimalRoundingPolicy, typename CachePolicy, typename... AdditionalArgs>
+ BOOST_CHARCONV_SAFEBUFFERS static ReturnType compute_nearest_normal(carrier_uint const two_fc, const int exponent,
+ AdditionalArgs... additional_args) noexcept
+ {
+ //////////////////////////////////////////////////////////////////////
+ // Step 1: Schubfach multiplier calculation
+ //////////////////////////////////////////////////////////////////////
+
+ ReturnType ret_value = {};
+ IntervalType interval_type{additional_args...};
+
+ // Compute k and beta.
+ const int minus_k = log::floor_log10_pow2(exponent) - kappa;
+ const auto cache = CachePolicy::template get_cache<format>(-minus_k);
+ const int beta = exponent + log::floor_log2_pow10(-minus_k);
+
+ // Compute zi and deltai.
+ // 10^kappa <= deltai < 10^(kappa + 1)
+ const auto deltai = compute_delta(cache, beta);
+ // For the case of binary32, the result of integer check is not correct for
+ // 29711844 * 2^-82
+ // = 6.1442653300000000008655037797566933477355632930994033813476... * 10^-18
+ // and 29711844 * 2^-81
+ // = 1.2288530660000000001731007559513386695471126586198806762695... * 10^-17,
+ // and they are the unique counterexamples. However, since 29711844 is even,
+ // this does not cause any problem for the endpoints calculations; it can only
+ // cause a problem when we need to perform integer check for the center.
+ // Fortunately, with these inputs, that branch is never executed, so we are fine.
+ //const auto [zi, is_z_integer] = compute_mul((two_fc | 1) << beta, cache);
+ const auto z_res = compute_mul((two_fc | 1) << beta, cache);
+ const auto zi = z_res.result;
+ const auto is_z_integer = z_res.is_integer;
+
+ //////////////////////////////////////////////////////////////////////
+ // Step 2: Try larger divisor; remove trailing zeros if necessary
+ //////////////////////////////////////////////////////////////////////
+
+ BOOST_CXX14_CONSTEXPR auto big_divisor = compute_power(std::uint32_t(10), kappa + 1);
+ BOOST_CXX14_CONSTEXPR auto small_divisor = compute_power(std::uint32_t(10), kappa);
+
+ // Using an upper bound on zi, we might be able to optimize the division
+ // better than the compiler; we are computing zi / big_divisor here.
+ #ifdef BOOST_NO_CXX14_CONSTEXPR
+ ret_value.significand = div::divide_by_pow10<carrier_uint>(kappa + 1, (carrier_uint(1) << (significand_bits + 1)) * big_divisor - 1, zi);
+ #else
+ ret_value.significand = div::divide_by_pow10<kappa + 1, carrier_uint, (carrier_uint(1) << (significand_bits + 1)) * big_divisor - 1>(zi);
+ #endif
+
+ auto r = std::uint32_t(zi - big_divisor * ret_value.significand);
+
+ if (r < deltai)
+ {
+ // Exclude the right endpoint if necessary.
+ if (r == 0 && (is_z_integer & !interval_type.include_right_endpoint()))
+ {
+ BOOST_IF_CONSTEXPR (BinaryToDecimalRoundingPolicy::tag == policy_impl::binary_to_decimal_rounding::tag_t::do_not_care)
+ {
+ ret_value.significand *= 10;
+ ret_value.exponent = minus_k + kappa;
+ --ret_value.significand;
+ TrailingZeroPolicy::template no_trailing_zeros<impl>(ret_value);
+
+ return ret_value;
+ }
+ else
+ {
+ --ret_value.significand;
+ r = big_divisor;
+
+ goto small_divisor_case_label;
+ }
+ }
+ }
+ else if (r > deltai)
+ {
+ goto small_divisor_case_label;
+ }
+ else
+ {
+ // r == deltai; compare fractional parts.
+ // const auto [xi_parity, x_is_integer] =
+ // compute_mul_parity(two_fc - 1, cache, beta);
+ const auto x_res = compute_mul_parity(two_fc - 1, cache, beta);
+ const auto xi_parity = x_res.parity;
+ const auto x_is_integer = x_res.is_integer;
+
+ if (!(xi_parity | (x_is_integer & interval_type.include_left_endpoint())))
+ {
+ goto small_divisor_case_label;
+ }
+ }
+ ret_value.exponent = minus_k + kappa + 1;
+
+ // We may need to remove trailing zeros.
+ TrailingZeroPolicy::template on_trailing_zeros<impl>(ret_value);
+ return ret_value;
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Step 3: Find the significand with the smaller divisor
+ //////////////////////////////////////////////////////////////////////
+
+ small_divisor_case_label:
+ TrailingZeroPolicy::template no_trailing_zeros<impl>(ret_value);
+ ret_value.significand *= 10;
+ ret_value.exponent = minus_k + kappa;
+
+ BOOST_IF_CONSTEXPR (BinaryToDecimalRoundingPolicy::tag == policy_impl::binary_to_decimal_rounding::tag_t::do_not_care)
+ {
+ // Normally, we want to compute
+ // ret_value.significand += r / small_divisor
+ // and return, but we need to take care of the case that the resulting
+ // value is exactly the right endpoint, while that is not included in the
+ // interval.
+ if (!interval_type.include_right_endpoint())
+ {
+ // Is r divisible by 10^kappa?
+ if (is_z_integer && div::check_divisibility_and_divide_by_pow10<kappa>(r))
+ {
+ // This should be in the interval.
+ ret_value.significand += r - 1;
+ }
+ else
+ {
+ ret_value.significand += r;
+ }
+ }
+ else
+ {
+ ret_value.significand += div::small_division_by_pow10<kappa>(r);
+ }
+ }
+ else
+ {
+ auto dist = r - (deltai / 2) + (small_divisor / 2);
+ const bool approx_y_parity = ((dist ^ (small_divisor / 2)) & 1) != 0;
+
+ // Is dist divisible by 10^kappa?
+ const bool divisible_by_small_divisor = div::check_divisibility_and_divide_by_pow10<kappa>(dist);
+
+ // Add dist / 10^kappa to the significand.
+ ret_value.significand += dist;
+
+ if (divisible_by_small_divisor)
+ {
+ // Check z^(f) >= epsilon^(f).
+ // We have either yi == zi - epsiloni or yi == (zi - epsiloni) - 1,
+ // where yi == zi - epsiloni if and only if z^(f) >= epsilon^(f).
+ // Since there are only 2 possibilities, we only need to care about the
+ // parity. Also, zi and r should have the same parity since the divisor is
+ // an even number.
+ //const auto [yi_parity, is_y_integer] =
+ // compute_mul_parity(two_fc, cache, beta);
+ const auto y_res = compute_mul_parity(two_fc, cache, beta);
+ const auto yi_parity = y_res.parity;
+ const auto is_y_integer = y_res.is_integer;
+
+ if (yi_parity != approx_y_parity)
+ {
+ --ret_value.significand;
+ }
+ else
+ {
+ // If z^(f) >= epsilon^(f), we might have a tie
+ // when z^(f) == epsilon^(f), or equivalently, when y is an integer.
+ // For tie-to-up case, we can just choose the upper one.
+ if (BinaryToDecimalRoundingPolicy::prefer_round_down(ret_value) & is_y_integer)
+ {
+ --ret_value.significand;
+ }
+ }
+ }
+ }
+
+ return ret_value;
+ }
+
+ template <typename ReturnType, typename IntervalType, typename TrailingZeroPolicy,
+ typename BinaryToDecimalRoundingPolicy, typename CachePolicy, typename... AdditionalArgs>
+ BOOST_CHARCONV_SAFEBUFFERS static ReturnType compute_nearest_shorter(const int exponent, AdditionalArgs... additional_args) noexcept
+ {
+ ReturnType ret_value = {};
+ IntervalType interval_type{additional_args...};
+
+ // Compute k and beta.
+ const int minus_k = log::floor_log10_pow2_minus_log10_4_over_3(exponent);
+ const int beta = exponent + log::floor_log2_pow10(-minus_k);
+
+ // Compute xi and zi.
+ const auto cache = CachePolicy::template get_cache<format>(-minus_k);
+
+ auto xi = compute_left_endpoint_for_shorter_interval_case(cache, beta);
+ auto zi = compute_right_endpoint_for_shorter_interval_case(cache, beta);
+
+ // If we don't accept the right endpoint and
+ // if the right endpoint is an integer, decrease it.
+ if (!interval_type.include_right_endpoint() && is_right_endpoint_integer_shorter_interval(exponent))
+ {
+ --zi;
+ }
+ // If we don't accept the left endpoint or
+ // if the left endpoint is not an integer, increase it.
+ if (!interval_type.include_left_endpoint() || !is_left_endpoint_integer_shorter_interval(exponent))
+ {
+ ++xi;
+ }
+
+ // Try bigger divisor.
+ ret_value.significand = zi / 10;
+
+ // If succeed, remove trailing zeros if necessary and return.
+ if (ret_value.significand * 10 >= xi)
+ {
+ ret_value.exponent = minus_k + 1;
+ TrailingZeroPolicy::template on_trailing_zeros<impl>(ret_value);
+ return ret_value;
+ }
+
+ // Otherwise, compute the round-up of y.
+ TrailingZeroPolicy::template no_trailing_zeros<impl>(ret_value);
+ ret_value.significand = compute_round_up_for_shorter_interval_case(cache, beta);
+ ret_value.exponent = minus_k;
+
+ // When tie occurs, choose one of them according to the rule.
+ if (BinaryToDecimalRoundingPolicy::prefer_round_down(ret_value) &&
+ exponent >= shorter_interval_tie_lower_threshold &&
+ exponent <= shorter_interval_tie_upper_threshold)
+ {
+ --ret_value.significand;
+ }
+ else if (ret_value.significand < xi)
+ {
+ ++ret_value.significand;
+ }
+
+ return ret_value;
+ }
+
+ #if defined(__GNUC__) && (__GNUC__ < 5) && !defined(__clang__)
+ # pragma GCC diagnostic pop
+ #endif
+
+ template <class ReturnType, class TrailingZeroPolicy, class CachePolicy>
+ BOOST_CHARCONV_SAFEBUFFERS static ReturnType compute_left_closed_directed(carrier_uint const two_fc, int exponent) noexcept
+ {
+ //////////////////////////////////////////////////////////////////////
+ // Step 1: Schubfach multiplier calculation
+ //////////////////////////////////////////////////////////////////////
+
+ ReturnType ret_value;
+
+ // Compute k and beta.
+ const int minus_k = log::floor_log10_pow2(exponent) - kappa;
+ const auto cache = CachePolicy::template get_cache<format>(-minus_k);
+ const int beta = exponent + log::floor_log2_pow10(-minus_k);
+
+ // Compute xi and deltai.
+ // 10^kappa <= deltai < 10^(kappa + 1)
+ const auto deltai = compute_delta(cache, beta);
+ //auto [xi, is_x_integer] = compute_mul(two_fc << beta, cache);
+ const auto x_res = compute_mul(two_fc << beta, cache);
+ auto xi = x_res.result;
+ auto is_x_integer = x_res.is_integer;
+
+ // Deal with the unique exceptional cases
+ // 29711844 * 2^-82
+ // = 6.1442653300000000008655037797566933477355632930994033813476... * 10^-18
+ // and 29711844 * 2^-81
+ // = 1.2288530660000000001731007559513386695471126586198806762695... * 10^-17
+ // for binary32.
+ BOOST_IF_CONSTEXPR (std::is_same<format, ieee754_binary32>::value)
+ {
+ if (exponent <= -80)
+ {
+ is_x_integer = false;
+ }
+ }
+
+ if (!is_x_integer)
+ {
+ ++xi;
+ }
+
+ //////////////////////////////////////////////////////////////////////
+ // Step 2: Try larger divisor; remove trailing zeros if necessary
+ //////////////////////////////////////////////////////////////////////
+
+ BOOST_CXX14_CONSTEXPR auto big_divisor = compute_power(std::uint32_t(10), kappa + 1);
+
+ // Using an upper bound on xi, we might be able to optimize the division
+ // better than the compiler; we are computing xi / big_divisor here.
+
+ #ifdef BOOST_NO_CXX14_CONSTEXPR
+ ret_value.significand = div::divide_by_pow10<carrier_uint>(kappa + 1, (carrier_uint(1) << (significand_bits + 1)) * big_divisor - 1, xi);
+ #else
+ ret_value.significand = div::divide_by_pow10<kappa + 1, carrier_uint, (carrier_uint(1) << (significand_bits + 1)) * big_divisor - 1>(xi);
+ #endif
+
+ auto r = std::uint32_t(xi - big_divisor * ret_value.significand);
+
+ if (r != 0)
+ {
+ ++ret_value.significand;
+ r = big_divisor - r;
+ }
+
+ if (r > deltai)
+ {
+ goto small_divisor_case_label;
+ }
+ else if (r == deltai)
+ {
+ // Compare the fractional parts.
+ // This branch is never taken for the exceptional cases
+ // 2f_c = 29711482, e = -81
+ // (6.1442649164096937243516663440523473127541365101933479309082... * 10^-18)
+ // and 2f_c = 29711482, e = -80
+ // (1.2288529832819387448703332688104694625508273020386695861816... * 10^-17).
+ //const auto [zi_parity, is_z_integer] =
+ // compute_mul_parity(two_fc + 2, cache, beta);
+ const auto z_res = compute_mul_parity(two_fc + 2, cache, beta);
+ if (z_res.parity || z_res.is_integer)
+ {
+ goto small_divisor_case_label;
+ }
+ }
+
+ // The ceiling is inside, so we are done.
+ ret_value.exponent = minus_k + kappa + 1;
+ TrailingZeroPolicy::template on_trailing_zeros<impl>(ret_value);
+ return ret_value;
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Step 3: Find the significand with the smaller divisor
+ //////////////////////////////////////////////////////////////////////
+
+ small_divisor_case_label:
+ ret_value.significand *= 10;
+ ret_value.significand -= div::small_division_by_pow10<kappa>(r);
+ ret_value.exponent = minus_k + kappa;
+ TrailingZeroPolicy::template no_trailing_zeros<impl>(ret_value);
+ return ret_value;
+ }
+
+ template <typename ReturnType, typename TrailingZeroPolicy, typename CachePolicy>
+ BOOST_CHARCONV_SAFEBUFFERS static ReturnType compute_right_closed_directed(carrier_uint const two_fc, const int exponent, bool shorter_interval) noexcept
+ {
+ //////////////////////////////////////////////////////////////////////
+ // Step 1: Schubfach multiplier calculation
+ //////////////////////////////////////////////////////////////////////
+
+ ReturnType ret_value;
+
+ // Compute k and beta.
+ const int minus_k = log::floor_log10_pow2(exponent - (shorter_interval ? 1 : 0)) - kappa;
+ const auto cache = CachePolicy::template get_cache<format>(-minus_k);
+ const int beta = exponent + log::floor_log2_pow10(-minus_k);
+
+ // Compute zi and deltai.
+ // 10^kappa <= deltai < 10^(kappa + 1)
+ const auto deltai = shorter_interval ? compute_delta(cache, beta - 1) : compute_delta(cache, beta);
+ carrier_uint const zi = compute_mul(two_fc << beta, cache).result;
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Step 2: Try larger divisor; remove trailing zeros if necessary
+ //////////////////////////////////////////////////////////////////////
+
+ BOOST_CXX14_CONSTEXPR auto big_divisor = compute_power(std::uint32_t(10), kappa + 1);
+
+ // Using an upper bound on zi, we might be able to optimize the division better than
+ // the compiler; we are computing zi / big_divisor here.
+ #ifdef BOOST_NO_CXX14_CONSTEXPR
+ ret_value.significand = div::divide_by_pow10<carrier_uint>(kappa + 1, (carrier_uint(1) << (significand_bits + 1)) * big_divisor - 1, zi);
+ #else
+ ret_value.significand = div::divide_by_pow10<kappa + 1, carrier_uint, (carrier_uint(1) << (significand_bits + 1)) * big_divisor - 1>(zi);
+ #endif
+
+ const auto r = std::uint32_t(zi - big_divisor * ret_value.significand);
+
+ if (r > deltai)
+ {
+ goto small_divisor_case_label;
+ }
+ else if (r == deltai)
+ {
+ // Compare the fractional parts.
+ if (!compute_mul_parity(two_fc - (shorter_interval ? 1 : 2), cache, beta).parity)
+ {
+ goto small_divisor_case_label;
+ }
+ }
+
+ // The floor is inside, so we are done.
+ ret_value.exponent = minus_k + kappa + 1;
+ TrailingZeroPolicy::template on_trailing_zeros<impl>(ret_value);
+ return ret_value;
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Step 3: Find the significand with the small divisor
+ //////////////////////////////////////////////////////////////////////
+
+ small_divisor_case_label:
+ ret_value.significand *= 10;
+ ret_value.significand += div::small_division_by_pow10<kappa>(r);
+ ret_value.exponent = minus_k + kappa;
+ TrailingZeroPolicy::template no_trailing_zeros<impl>(ret_value);
+
+ return ret_value;
+ }
+
+ // Remove trailing zeros from n and return the number of zeros removed.
+ BOOST_FORCEINLINE static int remove_trailing_zeros(carrier_uint& n) noexcept
+ {
+ if (n == 0)
+ {
+ return 0;
+ }
+
+ BOOST_IF_CONSTEXPR (std::is_same<format, ieee754_binary32>::value)
+ {
+ constexpr auto mod_inv_5 = UINT32_C(0xcccccccd);
+ constexpr auto mod_inv_25 = mod_inv_5 * mod_inv_5;
+
+ int s = 0;
+ while (true)
+ {
+ auto q = boost::core::rotr(n * mod_inv_25, 2);
+ if (q <= (std::numeric_limits<std::uint32_t>::max)() / 100)
+ {
+ n = q;
+ s += 2;
+ }
+ else
+ {
+ break;
+ }
+ }
+ auto q = boost::core::rotr(n * mod_inv_5, 1);
+ if (q <= (std::numeric_limits<std::uint32_t>::max)() / 10)
+ {
+ n = q;
+ s |= 1;
+ }
+
+ return s;
+ }
+ else
+ {
+ // Static assertion does not work unless if constexpr is supported
+ // static_assert(std::is_same<format, ieee754_binary64>::value, "Must be a double type");
+
+ // Divide by 10^8 and reduce to 32-bits if divisible.
+ // Since ret_value.significand <= (2^53 * 1000 - 1) / 1000 < 10^16,
+ // n is at most of 16 digits.
+
+ // This magic number is ceil(2^90 / 10^8).
+ constexpr auto magic_number = UINT64_C(12379400392853802749);
+ auto nm = umul128(n, magic_number);
+
+ // Is n is divisible by 10^8?
+ if ((nm.high & ((std::uint64_t(1) << (90 - 64)) - 1)) == 0 &&
+ nm.low < magic_number) {
+ // If yes, work with the quotient.
+ auto n32 = static_cast<std::uint32_t>(nm.high >> (90 - 64));
+
+ constexpr auto mod_inv_5 = UINT32_C(0xcccccccd);
+ constexpr auto mod_inv_25 = mod_inv_5 * mod_inv_5;
+
+ int s = 8;
+ while (true)
+ {
+ auto q = boost::core::rotr(n32 * mod_inv_25, 2);
+ if (q <= (std::numeric_limits<std::uint32_t>::max)() / 100)
+ {
+ n32 = q;
+ s += 2;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ auto q = boost::core::rotr(n32 * mod_inv_5, 1);
+ if (q <= (std::numeric_limits<std::uint32_t>::max)() / 10)
+ {
+ n32 = q;
+ s |= 1;
+ }
+
+ n = n32;
+ return s;
+ }
+
+ // If n is not divisible by 10^8, work with n itself.
+ constexpr auto mod_inv_5 = UINT64_C(0xcccccccccccccccd);
+ constexpr auto mod_inv_25 = mod_inv_5 * mod_inv_5;
+
+ int s = 0;
+ while (true)
+ {
+ auto q = static_cast<carrier_uint>(boost::core::rotr(n * mod_inv_25, 2));
+ if (q <= (std::numeric_limits<std::uint64_t>::max)() / 100)
+ {
+ n = q;
+ s += 2;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ auto q = static_cast<carrier_uint>(boost::core::rotr(n * mod_inv_5, 1));
+ if (q <= (std::numeric_limits<std::uint64_t>::max)() / 10)
+ {
+ n = q;
+ s |= 1;
+ }
+
+ return s;
+ }
+ }
+
+ template <typename local_format = format, typename std::enable_if<std::is_same<local_format, ieee754_binary32>::value, bool>::type = true>
+ static compute_mul_result compute_mul(carrier_uint u, cache_entry_type const& cache) noexcept
+ {
+ auto r = umul96_upper64(u, cache);
+ return {carrier_uint(r >> 32), carrier_uint(r) == 0};
+ }
+
+ template <typename local_format = format, typename std::enable_if<std::is_same<local_format, ieee754_binary64>::value, bool>::type = true>
+ static compute_mul_result compute_mul(carrier_uint u, cache_entry_type const& cache) noexcept
+ {
+ auto r = umul192_upper128(u, cache);
+ return {r.high, r.low == 0};
+ }
+
+ template <typename local_format = format, typename std::enable_if<std::is_same<local_format, ieee754_binary32>::value, bool>::type = true>
+ static constexpr std::uint32_t compute_delta(cache_entry_type const& cache,
+ int beta) noexcept
+ {
+ return std::uint32_t(cache >> (cache_bits - 1 - beta));
+ }
+
+ template <typename local_format = format, typename std::enable_if<std::is_same<local_format, ieee754_binary64>::value, bool>::type = true>
+ static constexpr std::uint32_t compute_delta(cache_entry_type const& cache,
+ int beta) noexcept
+ {
+ return std::uint32_t(cache.high >> (carrier_bits - 1 - beta));
+ }
+
+ template <typename local_format = format, typename std::enable_if<std::is_same<local_format, ieee754_binary32>::value, bool>::type = true>
+ static compute_mul_parity_result compute_mul_parity(carrier_uint two_f,
+ cache_entry_type const& cache,
+ int beta) noexcept
+ {
+ auto r = umul96_lower64(two_f, cache);
+ return {((r >> (64 - beta)) & 1) != 0, std::uint32_t(r >> (32 - beta)) == 0};
+ }
+
+ template <typename local_format = format, typename std::enable_if<std::is_same<local_format, ieee754_binary64>::value, bool>::type = true>
+ static compute_mul_parity_result compute_mul_parity(carrier_uint two_f,
+ cache_entry_type const& cache,
+ int beta) noexcept
+ {
+ auto r = umul192_lower128(two_f, cache);
+ return {((r.high >> (64 - beta)) & 1) != 0, ((r.high << beta) | (r.low >> (64 - beta))) == 0};
+ }
+
+ template <typename local_format = format, typename std::enable_if<std::is_same<local_format, ieee754_binary32>::value, bool>::type = true>
+ static constexpr carrier_uint compute_left_endpoint_for_shorter_interval_case(cache_entry_type const& cache, int beta) noexcept
+ {
+ return carrier_uint((cache - (cache >> (significand_bits + 2))) >> (cache_bits - significand_bits - 1 - beta));
+ }
+
+ template <typename local_format = format, typename std::enable_if<std::is_same<local_format, ieee754_binary64>::value, bool>::type = true>
+ static constexpr carrier_uint compute_left_endpoint_for_shorter_interval_case(cache_entry_type const& cache, int beta) noexcept
+ {
+ return (cache.high - (cache.high >> (significand_bits + 2))) >> (carrier_bits - significand_bits - 1 - beta);
+ }
+
+ template <typename local_format = format, typename std::enable_if<std::is_same<local_format, ieee754_binary32>::value, bool>::type = true>
+ static constexpr carrier_uint compute_right_endpoint_for_shorter_interval_case(cache_entry_type const& cache, int beta) noexcept
+ {
+ return carrier_uint((cache + (cache >> (significand_bits + 1))) >> (cache_bits - significand_bits - 1 - beta));
+ }
+
+ template <typename local_format = format, typename std::enable_if<std::is_same<local_format, ieee754_binary64>::value, bool>::type = true>
+ static constexpr carrier_uint compute_right_endpoint_for_shorter_interval_case(cache_entry_type const& cache, int beta) noexcept
+ {
+ return (cache.high + (cache.high >> (significand_bits + 1))) >> (carrier_bits - significand_bits - 1 - beta);
+ }
+
+ template <typename local_format = format, typename std::enable_if<std::is_same<local_format, ieee754_binary32>::value, bool>::type = true>
+ static constexpr carrier_uint compute_round_up_for_shorter_interval_case(cache_entry_type const& cache, int beta) noexcept
+ {
+ return (carrier_uint(cache >> (cache_bits - significand_bits - 2 - beta)) + 1) / 2;
+ }
+
+ template <typename local_format = format, typename std::enable_if<std::is_same<local_format, ieee754_binary64>::value, bool>::type = true>
+ static constexpr carrier_uint compute_round_up_for_shorter_interval_case(cache_entry_type const& cache, int beta) noexcept
+ {
+ return ((cache.high >> (carrier_bits - significand_bits - 2 - beta)) + 1) / 2;
+ }
+
+ static constexpr bool is_right_endpoint_integer_shorter_interval(int exponent) noexcept
+ {
+ return exponent >= case_shorter_interval_right_endpoint_lower_threshold &&
+ exponent <= case_shorter_interval_right_endpoint_upper_threshold;
+ }
+
+ static constexpr bool is_left_endpoint_integer_shorter_interval(int exponent) noexcept
+ {
+ return exponent >= case_shorter_interval_left_endpoint_lower_threshold &&
+ exponent <= case_shorter_interval_left_endpoint_upper_threshold;
+ }
+};
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// Policy holder.
+////////////////////////////////////////////////////////////////////////////////////////
+
+namespace policy_impl {
+ // The library will specify a list of accepted kinds of policies and their defaults, and
+ // the user will pass a list of policies. The aim of helper classes/functions here is to
+ // do the following:
+ // 1. Check if the policy parameters given by the user are all valid; that means,
+ // each of them should be of the kinds specified by the library.
+ // If that's not the case, then the compilation fails.
+ // 2. Check if multiple policy parameters for the same kind is specified by the user.
+ // If that's the case, then the compilation fails.
+ // 3. Build a class deriving from all policies the user have given, and also from
+ // the default policies if the user did not specify one for some kinds.
+ // A policy belongs to a certain kind if it is deriving from a base class.
+
+ // For a given kind, find a policy belonging to that kind.
+ // Check if there are more than one such policies.
+ enum class policy_found_info
+ {
+ not_found,
+ unique,
+ repeated
+ };
+
+ template <typename Policy, policy_found_info info>
+ struct found_policy_pair
+ {
+ using policy = Policy;
+ static constexpr auto found_info = info;
+ };
+
+ template <typename Base, typename DefaultPolicy>
+ struct base_default_pair
+ {
+ using base = Base;
+
+ template <class FoundPolicyInfo>
+ static constexpr FoundPolicyInfo get_policy_impl(FoundPolicyInfo)
+ {
+ return {};
+ }
+
+ template <typename FoundPolicyInfo, typename FirstPolicy, typename... RemainingPolicies,
+ typename std::enable_if<std::is_base_of<Base, FirstPolicy>::value && (FoundPolicyInfo::found_info == policy_found_info::not_found), bool>::type = true>
+ static constexpr auto get_policy_impl(FoundPolicyInfo, FirstPolicy, RemainingPolicies... remainings) noexcept -> found_policy_pair<FirstPolicy, policy_found_info::unique>
+ {
+ return get_policy_impl(found_policy_pair<FirstPolicy, policy_found_info::unique>{}, remainings...);
+ }
+
+ template <typename FoundPolicyInfo, typename FirstPolicy, typename... RemainingPolicies,
+ typename std::enable_if<std::is_base_of<Base, FirstPolicy>::value && !(FoundPolicyInfo::found_info == policy_found_info::not_found), bool>::type = true>
+ static constexpr auto get_policy_impl(FoundPolicyInfo, FirstPolicy, RemainingPolicies... remainings) noexcept -> found_policy_pair<FirstPolicy, policy_found_info::repeated>
+ {
+ return get_policy_impl(found_policy_pair<FirstPolicy, policy_found_info::repeated>{}, remainings...);
+ }
+
+ template <typename FoundPolicyInfo, typename FirstPolicy, typename... RemainingPolicies,
+ typename std::enable_if<!std::is_base_of<Base, FirstPolicy>::value, bool>::type = true>
+ static constexpr auto get_policy_impl(FoundPolicyInfo, FirstPolicy, RemainingPolicies... remainings) noexcept -> found_policy_pair<FirstPolicy, FoundPolicyInfo::found_info>
+ {
+ return get_policy_impl(FoundPolicyInfo{}, remainings...);
+ }
+
+ template <typename... Policies>
+ static constexpr auto get_policy(Policies... policies) -> found_policy_pair<DefaultPolicy, policy_found_info::not_found>
+ {
+ return get_policy_impl(found_policy_pair<DefaultPolicy, policy_found_info::not_found>{}, policies...);
+ }
+ };
+
+ template <typename... BaseDefaultPairs>
+ struct base_default_pair_list {};
+
+ // Check if a given policy belongs to one of the kinds specified by the library.
+ template <typename Policy>
+ constexpr bool check_policy_validity(Policy, base_default_pair_list<>)
+ {
+ return false;
+ }
+
+ template <typename Policy, typename FirstBaseDefaultPair, typename... RemainingBaseDefaultPairs>
+ constexpr bool check_policy_validity(Policy, base_default_pair_list<FirstBaseDefaultPair, RemainingBaseDefaultPairs...>)
+ {
+ return std::is_base_of<typename FirstBaseDefaultPair::base, Policy>::value ||
+ check_policy_validity(Policy{}, base_default_pair_list<RemainingBaseDefaultPairs...>{});
+ }
+
+ template <typename BaseDefaultPairList>
+ constexpr bool check_policy_list_validity(BaseDefaultPairList)
+ {
+ return true;
+ }
+
+ template <typename BaseDefaultPairList, typename FirstPolicy, typename... RemainingPolicies>
+ constexpr bool check_policy_list_validity(BaseDefaultPairList, FirstPolicy, RemainingPolicies... remaining_policies)
+ {
+ return check_policy_validity(FirstPolicy{}, BaseDefaultPairList{}) &&
+ check_policy_list_validity(BaseDefaultPairList{}, remaining_policies...);
+ }
+
+ // Build policy_holder.
+ template <bool repeated_, typename... FoundPolicyPairs>
+ struct found_policy_pair_list
+ {
+ static constexpr bool repeated = repeated_;
+ };
+
+ template <typename... Policies>
+ struct policy_holder : Policies... {};
+
+ #ifndef BOOST_CHARCONV_NO_CXX14_RETURN_TYPE_DEDUCTION
+
+ template <bool repeated, typename... FoundPolicyPairs, typename... Policies>
+ constexpr auto make_policy_holder_impl(base_default_pair_list<>, found_policy_pair_list<repeated, FoundPolicyPairs...>, Policies...)
+ -> found_policy_pair_list<repeated, FoundPolicyPairs...>
+ {
+ return found_policy_pair_list<repeated, FoundPolicyPairs...>{};
+ }
+
+ template <typename FirstBaseDefaultPair, typename... RemainingBaseDefaultPairs, bool repeated,
+ typename... FoundPolicyPairs, typename... Policies>
+ constexpr auto make_policy_holder_impl(base_default_pair_list<FirstBaseDefaultPair, RemainingBaseDefaultPairs...>,
+ found_policy_pair_list<repeated, FoundPolicyPairs...>, Policies... policies)
+ {
+ using new_found_policy_pair = decltype(FirstBaseDefaultPair::get_policy(policies...));
+
+ return make_policy_holder_impl(base_default_pair_list<RemainingBaseDefaultPairs...>{},
+ found_policy_pair_list < repeated || new_found_policy_pair::found_info == policy_found_info::repeated,
+ new_found_policy_pair, FoundPolicyPairs... > {}, policies...);
+ }
+
+ template <bool repeated, typename... RawPolicies>
+ constexpr auto convert_to_policy_holder(found_policy_pair_list<repeated>, RawPolicies...) -> policy_holder<RawPolicies...>
+ {
+ return policy_holder<RawPolicies...>{};
+ }
+
+ template <bool repeated, typename FirstFoundPolicyPair, typename... RemainingFoundPolicyPairs, typename... RawPolicies>
+ constexpr auto convert_to_policy_holder(found_policy_pair_list<repeated, FirstFoundPolicyPair, RemainingFoundPolicyPairs...>,
+ RawPolicies... policies)
+ {
+ return convert_to_policy_holder(found_policy_pair_list<repeated, RemainingFoundPolicyPairs...>{}, typename FirstFoundPolicyPair::policy{}, policies...);
+ }
+
+ template <typename BaseDefaultPairList, typename... Policies>
+ constexpr auto make_policy_holder(BaseDefaultPairList, Policies... policies)
+ {
+ static_assert(check_policy_list_validity(BaseDefaultPairList{}, Policies{}...),
+ "jkj::dragonbox: an invalid policy is specified");
+
+ using policy_pair_list = decltype(make_policy_holder_impl(
+ BaseDefaultPairList{}, found_policy_pair_list<false>{}, policies...));
+
+ static_assert(!policy_pair_list::repeated,
+ "jkj::dragonbox: each policy should be specified at most once");
+
+ return convert_to_policy_holder(policy_pair_list{});
+ }
+ #endif
+}
+////////////////////////////////////////////////////////////////////////////////////////
+// The interface function.
+////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef BOOST_MSVC
+# pragma warning(push)
+# pragma warning(disable: 4100) // Unreferenced formal parameter (interval_type_provider)
+# pragma warning(disable: 4189) // Local variable is initializaed but unused (tag)
+#endif
+
+template <typename Float, typename FloatTraits = dragonbox_float_traits<Float>, typename... Policies>
+BOOST_FORCEINLINE BOOST_CHARCONV_SAFEBUFFERS auto
+to_decimal(dragonbox_signed_significand_bits<Float, FloatTraits> dragonbox_signed_significand_bits,
+ unsigned int exponent_bits, BOOST_ATTRIBUTE_UNUSED Policies... policies) noexcept
+ #ifdef BOOST_CHARCONV_NO_CXX14_RETURN_TYPE_DEDUCTION
+ -> decimal_fp<typename FloatTraits::carrier_uint, true, false>
+ #endif
+{
+ // Build policy holder type.
+ using namespace policy_impl;
+
+ #ifdef BOOST_CHARCONV_NO_CXX14_RETURN_TYPE_DEDUCTION
+ // For C++11 we hardcode the policy holder
+ using policy_holder = policy_holder<decimal_to_binary_rounding::nearest_to_even, binary_to_decimal_rounding::to_even, cache::full, sign::return_sign, trailing_zero::remove>;
+
+ #else
+
+ using policy_holder = decltype(make_policy_holder(
+ base_default_pair_list<base_default_pair<sign::base, sign::return_sign>,
+ base_default_pair<trailing_zero::base, trailing_zero::remove>,
+ base_default_pair<decimal_to_binary_rounding::base,
+ decimal_to_binary_rounding::nearest_to_even>,
+ base_default_pair<binary_to_decimal_rounding::base,
+ binary_to_decimal_rounding::to_even>,
+ base_default_pair<cache::base, cache::full>>{},
+ policies...));
+
+ #endif
+
+ using return_type = decimal_fp<typename FloatTraits::carrier_uint, policy_holder::return_has_sign, policy_holder::report_trailing_zeros>;
+
+ return_type ret = policy_holder::template delegate<return_type>(dragonbox_signed_significand_bits,
+ [exponent_bits, dragonbox_signed_significand_bits](policy_impl::decimal_to_binary_rounding::nearest_to_even interval_type_provider) {
+ using format = typename FloatTraits::format;
+ constexpr auto tag = decltype(interval_type_provider)::tag;
+
+ auto two_fc = dragonbox_signed_significand_bits.remove_sign_bit_and_shift();
+ auto exponent = int(exponent_bits);
+
+ BOOST_IF_CONSTEXPR (tag == decimal_to_binary_rounding::tag_t::to_nearest) { // NOLINT: if constexpr not always false
+ // Is the input a normal number?
+ if (exponent != 0) {
+ exponent += format::exponent_bias - format::significand_bits;
+
+ // Shorter interval case; proceed like Schubfach.
+ // One might think this condition is wrong, since when exponent_bits == 1
+ // and two_fc == 0, the interval is actually regular. However, it turns out
+ // that this seemingly wrong condition is actually fine, because the end
+ // result is anyway the same.
+ //
+ // [binary32]
+ // (fc-1/2) * 2^e = 1.175'494'28... * 10^-38
+ // (fc-1/4) * 2^e = 1.175'494'31... * 10^-38
+ // fc * 2^e = 1.175'494'35... * 10^-38
+ // (fc+1/2) * 2^e = 1.175'494'42... * 10^-38
+ //
+ // Hence, shorter_interval_case will return 1.175'494'4 * 10^-38.
+ // 1.175'494'3 * 10^-38 is also a correct shortest representation that will
+ // be rejected if we assume shorter interval, but 1.175'494'4 * 10^-38 is
+ // closer to the true value so it doesn't matter.
+ //
+ // [binary64]
+ // (fc-1/2) * 2^e = 2.225'073'858'507'201'13... * 10^-308
+ // (fc-1/4) * 2^e = 2.225'073'858'507'201'25... * 10^-308
+ // fc * 2^e = 2.225'073'858'507'201'38... * 10^-308
+ // (fc+1/2) * 2^e = 2.225'073'858'507'201'63... * 10^-308
+ //
+ // Hence, shorter_interval_case will return 2.225'073'858'507'201'4 *
+ // 10^-308. This is indeed of the shortest length, and it is the unique one
+ // closest to the true value among valid representations of the same length.
+ static_assert(std::is_same<format, ieee754_binary32>::value ||
+ std::is_same<format, ieee754_binary64>::value, "Format must be IEEE754 binary 32 or 64");
+
+ if (two_fc == 0) {
+ return decltype(interval_type_provider)::template invoke_shorter_interval_case<return_type>(
+ dragonbox_signed_significand_bits, [exponent]() {
+ return detail::impl<Float, FloatTraits>::
+ template compute_nearest_shorter<
+ return_type,
+ typename decltype(interval_type_provider)::
+ shorter_interval_type,
+ typename policy_holder::trailing_zero_policy,
+ typename policy_holder::
+ binary_to_decimal_rounding_policy,
+ typename policy_holder::cache_policy>(
+ exponent);
+ });
+ }
+
+ two_fc |= (decltype(two_fc)(1) << (format::significand_bits + 1));
+ }
+ // Is the input a subnormal number?
+ else {
+ exponent = format::min_exponent - format::significand_bits;
+ }
+
+ return decltype(interval_type_provider)::template invoke_normal_interval_case<return_type>(
+ dragonbox_signed_significand_bits, [two_fc, exponent](bool additional_args) {
+ return detail::impl<Float, FloatTraits>::
+ template compute_nearest_normal<
+ return_type,
+ typename decltype(interval_type_provider)::normal_interval_type,
+ typename policy_holder::trailing_zero_policy,
+ typename policy_holder::binary_to_decimal_rounding_policy,
+ typename policy_holder::cache_policy>(two_fc, exponent, additional_args);
+ });
+ }
+ else BOOST_IF_CONSTEXPR (tag == decimal_to_binary_rounding::tag_t::left_closed_directed) // NOLINT: if constexpr not always false
+ {
+ // Is the input a normal number?
+ if (exponent != 0) {
+ exponent += format::exponent_bias - format::significand_bits;
+ two_fc |= (decltype(two_fc)(1) << (format::significand_bits + 1));
+ }
+ // Is the input a subnormal number?
+ else {
+ exponent = format::min_exponent - format::significand_bits;
+ }
+
+ return detail::impl<Float>::template compute_left_closed_directed<
+ return_type, typename policy_holder::trailing_zero_policy,
+ typename policy_holder::cache_policy>(two_fc, exponent);
+ }
+ else
+ {
+ // Assertion does not work unless if constexpr is defined
+ // static_assert(tag == decimal_to_binary_rounding::tag_t::right_closed_directed, "Tag should be right_closed_direction");
+
+ bool shorter_interval = false;
+
+ // Is the input a normal number?
+ if (exponent != 0) {
+ if (two_fc == 0 && exponent != 1) {
+ shorter_interval = true;
+ }
+ exponent += format::exponent_bias - format::significand_bits;
+ two_fc |= (decltype(two_fc)(1) << (format::significand_bits + 1));
+ }
+ // Is the input a subnormal number?
+ else {
+ exponent = format::min_exponent - format::significand_bits;
+ }
+
+ return detail::impl<Float>::template compute_right_closed_directed<
+ return_type, typename policy_holder::trailing_zero_policy,
+ typename policy_holder::cache_policy>(two_fc, exponent, shorter_interval);
+ }
+ });
+
+ policy_holder::handle_sign(dragonbox_signed_significand_bits, ret);
+ return ret;
+}
+
+#ifdef BOOST_MSVC
+# pragma warning(pop)
+#endif
+
+template <typename Float, typename FloatTraits = dragonbox_float_traits<Float>, typename... Policies>
+BOOST_FORCEINLINE BOOST_CHARCONV_SAFEBUFFERS auto to_decimal(Float x, Policies... policies) noexcept
+ #ifdef BOOST_CHARCONV_NO_CXX14_RETURN_TYPE_DEDUCTION
+ -> decimal_fp<typename FloatTraits::carrier_uint, true, false>
+ #endif
+{
+ const auto br = dragonbox_float_bits<Float, FloatTraits>(x);
+ const auto exponent_bits = br.extract_exponent_bits();
+ const auto s = br.remove_exponent_bits(exponent_bits);
+
+ return to_decimal<Float, FloatTraits>(s, exponent_bits, policies...);
+}
+
+namespace to_chars_detail {
+ template <class Float, class FloatTraits>
+ extern to_chars_result dragon_box_print_chars(typename FloatTraits::carrier_uint significand, int exponent, char* first, char* last, chars_format fmt) noexcept;
+
+ // Avoid needless ABI overhead incurred by tag dispatch.
+ template <class PolicyHolder, class Float, class FloatTraits>
+ to_chars_result to_chars_n_impl(dragonbox_float_bits<Float, FloatTraits> br, char* first, char* last, chars_format fmt) noexcept
+ {
+ const auto exponent_bits = br.extract_exponent_bits();
+ const auto s = br.remove_exponent_bits(exponent_bits);
+
+ auto buffer = first;
+ const auto buffer_size = last - first;
+
+ if (br.is_finite(exponent_bits))
+ {
+ if (s.is_negative())
+ {
+ *buffer = '-';
+ ++buffer;
+ }
+ if (br.is_nonzero())
+ {
+ auto result = to_decimal<Float, FloatTraits>(
+ s, exponent_bits, policy::sign::ignore, policy::trailing_zero::ignore,
+ typename PolicyHolder::decimal_to_binary_rounding_policy{},
+ typename PolicyHolder::binary_to_decimal_rounding_policy{},
+ typename PolicyHolder::cache_policy{});
+ return to_chars_detail::dragon_box_print_chars<Float, FloatTraits>(result.significand, result.exponent, buffer, last, fmt);
+ }
+ else
+ {
+ if (fmt != chars_format::scientific)
+ {
+ std::memcpy(buffer, "0", 1); // NOLINT: Specifically not null-terminated
+ return {buffer + 1, std::errc()};
+ }
+
+ if (buffer_size >= 5)
+ {
+ std::memcpy(buffer, "0e+00", 5); // NOLINT: Specifically not null-terminated
+ return {buffer + 5, std::errc()};
+ }
+ else
+ {
+ return {last, std::errc::value_too_large};
+ }
+ }
+ }
+ else
+ {
+ bool is_negative = false;
+ if (s.is_negative())
+ {
+ *buffer = '-';
+ ++buffer;
+ is_negative = true;
+ }
+
+ if (s.has_all_zero_significand_bits())
+ {
+ if (buffer_size >= 3 + static_cast<std::ptrdiff_t>(is_negative))
+ {
+ std::memcpy(buffer, "inf", 3); // NOLINT: Specifically not null-terminated
+ return {buffer + 3, std::errc()};
+ }
+ else
+ {
+ return {last, std::errc::value_too_large};
+ }
+ }
+ else
+ {
+ // Doubles:
+ // qNaN = 2251799813685248
+ // sNaN = 1125899906842624
+ //
+ // Floats:
+ // qNaN = 4194304
+ // sNaN = 2097152
+ //
+ // use 1 for qNaN and 0 for sNaN
+ int nan_type;
+ BOOST_IF_CONSTEXPR (std::is_same<typename FloatTraits::format, ieee754_binary32>::value)
+ {
+ if (br.extract_significand_bits() == UINT32_C(4194304))
+ {
+ nan_type = 1;
+ }
+ else
+ {
+ nan_type = 0;
+ }
+ }
+ else
+ {
+ if (br.extract_significand_bits() == UINT64_C(2251799813685248))
+ {
+ nan_type = 1;
+ }
+ else
+ {
+ nan_type = 0;
+ }
+ }
+
+ if (nan_type == 1)
+ {
+ if (!s.is_negative())
+ {
+ if (buffer_size >= 3 + static_cast<std::ptrdiff_t>(is_negative))
+ {
+ std::memcpy(buffer, "nan", 3); // NOLINT: Specifically not null-terminated
+ return {buffer + 3, std::errc()};
+ }
+ else
+ {
+ return {last, std::errc::value_too_large};
+ }
+ }
+ else
+ {
+ if (buffer_size >= 8 + static_cast<std::ptrdiff_t>(is_negative))
+ {
+ std::memcpy(buffer, "nan(ind)", 8); // NOLINT: Specifically not null-terminated
+ return {buffer + 8, std::errc()};
+ }
+ else
+ {
+ return {last, std::errc::value_too_large};
+ }
+ }
+ }
+ else
+ {
+ if (buffer_size >= 9 + static_cast<std::ptrdiff_t>(is_negative))
+ {
+ std::memcpy(buffer, "nan(snan)", 9); // NOLINT: Specifically not null-terminated
+ return {buffer + 9, std::errc()};
+ }
+ else
+ {
+ return {last, std::errc::value_too_large};
+ }
+ }
+ }
+ }
+ }
+}
+
+// Returns the next-to-end position
+template <typename Float, typename FloatTraits = dragonbox_float_traits<Float>, typename... Policies>
+to_chars_result to_chars_n(Float x, char* first, char* last, chars_format fmt, BOOST_ATTRIBUTE_UNUSED Policies... policies) noexcept
+{
+ using namespace policy_impl;
+
+ #ifdef BOOST_CHARCONV_NO_CXX14_RETURN_TYPE_DEDUCTION
+ // For C++11 we hardcode the policy holder
+ using policy_holder = policy_holder<decimal_to_binary_rounding::nearest_to_even, binary_to_decimal_rounding::to_even, cache::full, sign::return_sign, trailing_zero::remove>;
+
+ #else
+
+ using policy_holder = decltype(make_policy_holder(
+ base_default_pair_list<base_default_pair<sign::base, sign::return_sign>,
+ base_default_pair<trailing_zero::base, trailing_zero::remove>,
+ base_default_pair<decimal_to_binary_rounding::base,
+ decimal_to_binary_rounding::nearest_to_even>,
+ base_default_pair<binary_to_decimal_rounding::base,
+ binary_to_decimal_rounding::to_even>,
+ base_default_pair<cache::base, cache::full>>{},
+ policies...));
+
+ #endif
+
+ return to_chars_detail::to_chars_n_impl<policy_holder>(dragonbox_float_bits<Float, FloatTraits>(x), first, last, fmt);
+}
+
+// Null-terminate and bypass the return value of fp_to_chars_n
+template <typename Float, typename FloatTraits = dragonbox_float_traits<Float>, typename... Policies>
+to_chars_result dragonbox_to_chars(Float x, char* first, char* last, chars_format fmt, Policies... policies) noexcept
+{
+ return to_chars_n<Float, FloatTraits>(x, first, last, fmt, policies...);
+}
+
+}}} // Namespaces
+
+#ifdef BOOST_MSVC
+# pragma warning(pop)
+#endif
+
+#endif // BOOST_CHARCONV_DETAIL_DRAGONBOX_HPP
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/dragonbox/dragonbox_common.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/dragonbox/dragonbox_common.hpp
new file mode 100644
index 00000000000..0bee7d091fa
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/dragonbox/dragonbox_common.hpp
@@ -0,0 +1,829 @@
+// Copyright 2020-2022 Junekey Jeon
+//
+// The contents of this file may be used under the terms of
+// the Apache License v2.0 with LLVM Exceptions.
+//
+// (See accompanying file LICENSE-Apache or copy at
+// https://llvm.org/foundation/relicensing/LICENSE.txt)
+//
+// Alternatively, the contents of this file may be used under the terms of
+// the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE-Boost or copy at
+// https://www.boost.org/LICENSE_1_0.txt)
+//
+// Unless required by applicable law or agreed to in writing, this software
+// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.
+//
+// Some parts are copied from Dragonbox project.
+//
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_CHARCONV_DETAIL_DRAGONBOX_COMMON_HPP
+#define BOOST_CHARCONV_DETAIL_DRAGONBOX_COMMON_HPP
+
+#include <boost/charconv/detail/config.hpp>
+#include <boost/charconv/detail/bit_layouts.hpp>
+#include <boost/charconv/detail/emulated128.hpp>
+#include <boost/charconv/chars_format.hpp>
+#include <boost/core/bit.hpp>
+#include <type_traits>
+#include <limits>
+#include <cstdint>
+#include <cstring>
+#include <cstddef>
+#include <climits>
+
+namespace boost { namespace charconv { namespace detail {
+
+template <typename T>
+struct physical_bits
+{
+ static constexpr std::size_t value = sizeof(T) * CHAR_BIT;
+};
+
+template <typename T>
+struct value_bits
+{
+ static constexpr std::size_t value = std::numeric_limits<typename std::enable_if<std::is_unsigned<T>::value, T>::type>::digits;
+};
+
+#ifdef BOOST_NO_CXX17_INLINE_VARIABLES
+
+template <typename T> constexpr std::size_t physical_bits<T>::value;
+template <typename T> constexpr std::size_t value_bits<T>::value;
+
+#endif
+
+// A floating-point traits class defines ways to interpret a bit pattern of given size as an
+// encoding of floating-point number. This is a default implementation of such a traits class,
+// supporting ways to interpret 32-bits into a binary32-encoded floating-point number and to
+// interpret 64-bits into a binary64-encoded floating-point number. Users might specialize this
+// class to change the default behavior for certain types.
+template <typename T>
+struct default_float_traits
+{
+ // I don't know if there is a truly reliable way of detecting
+ // IEEE-754 binary32/binary64 formats; I just did my best here.
+ static_assert(std::numeric_limits<T>::is_iec559 && std::numeric_limits<T>::radix == 2 &&
+ (detail::physical_bits<T>::value == 32 || detail::physical_bits<T>::value == 64),
+ "default_ieee754_traits only works for 32-bits or 64-bits types "
+ "supporting binary32 or binary64 formats!");
+
+ // The type that is being viewed.
+ using type = T;
+
+ // Refers to the format specification class.
+ using format =
+ typename std::conditional<detail::physical_bits<T>::value == 32, detail::ieee754_binary32, detail::ieee754_binary64>::type;
+
+ // Defines an unsignedeger type that is large enough to carry a variable of type T.
+ // Most of the operations will be done on this integer type.
+ using carrier_uint = typename std::conditional<detail::physical_bits<T>::value == 32, std::uint32_t, std::uint64_t>::type;
+
+ static_assert(sizeof(carrier_uint) == sizeof(T), "carrier_uint must be T");
+
+ // Number of bits in the above unsignedeger type.
+ static constexpr int carrier_bits = static_cast<int>(detail::physical_bits<carrier_uint>::value);
+
+ // Convert from carrier_uint into the original type.
+ // Depending on the floating-point encoding format, this operation might not be possible for
+ // some specific bit patterns. However, the contract is that u always denotes a
+ // valid bit pattern, so this function must be assumed to be noexcept.
+ static T carrier_to_float(carrier_uint u) noexcept
+ {
+ T x;
+ std::memcpy(&x, &u, sizeof(carrier_uint));
+ return x;
+ }
+
+ // Same as above.
+ static carrier_uint float_to_carrier(T x) noexcept
+ {
+ carrier_uint u;
+ std::memcpy(&u, &x, sizeof(carrier_uint));
+ return u;
+ }
+
+ // Extract exponent bits from a bit pattern.
+ // The result must be aligned to the LSB so that there is no additional zero paddings
+ // on the right. This function does not do bias adjustment.
+ static constexpr unsigned extract_exponent_bits(carrier_uint u) noexcept
+ {
+ return static_cast<unsigned>(u >> format::exponent_bits) & static_cast<unsigned>((1U << format::exponent_bits) - 1);
+ }
+
+ // Extract significand bits from a bit pattern.
+ // The result must be aligned to the LSB so that there is no additional zero paddings
+ // on the right. The result does not contain the implicit bit.
+ static constexpr carrier_uint extract_significand_bits(carrier_uint u) noexcept
+ {
+ return static_cast<carrier_uint>(u & static_cast<carrier_uint>((static_cast<carrier_uint>(1) << format::significand_bits) - 1));
+ }
+
+ // Remove the exponent bits and extract significand bits together with the sign bit.
+ static constexpr carrier_uint remove_exponent_bits(carrier_uint u, unsigned exponent_bits) noexcept
+ {
+ return u ^ (static_cast<carrier_uint>(exponent_bits) << format::significand_bits);
+ }
+
+ // Shift the obtained signed significand bits to the left by 1 to remove the sign bit.
+ static constexpr carrier_uint remove_sign_bit_and_shift(carrier_uint u) noexcept
+ {
+ return static_cast<carrier_uint>(static_cast<carrier_uint>(u) << 1);
+ }
+
+ // The actual value of exponent is obtained by adding this value to the extracted exponent bits
+ static constexpr int exponent_bias = 1 - (1 << (carrier_bits - format::significand_bits - 2));
+
+ // Obtain the actual value of the binary exponent from the extracted exponent bits.
+ static constexpr int binary_exponent(unsigned exponent_bits) noexcept
+ {
+ return exponent_bits == 0 ? format::min_exponent : static_cast<int>(exponent_bits) + format::exponent_bias;
+ }
+
+ // Obtain the actual value of the binary exponent from the extracted significand bits and
+ // exponent bits.
+ static constexpr carrier_uint binary_significand(carrier_uint significand_bits, unsigned exponent_bits) noexcept
+ {
+ return exponent_bits == 0 ? significand_bits : (significand_bits | (static_cast<carrier_uint>(1) << format::significand_bits));
+ }
+
+
+ // Various boolean observer functions
+
+ static constexpr bool is_nonzero(carrier_uint u) noexcept { return (u << 1) != 0; }
+
+ static constexpr bool is_positive(carrier_uint u) noexcept
+ {
+ return u < static_cast<carrier_uint>(1) << (format::significand_bits + format::exponent_bits);
+ }
+
+ static constexpr bool is_negative(carrier_uint u) noexcept { return !is_positive(u); }
+
+ static constexpr bool is_finite(unsigned exponent_bits) noexcept
+ {
+ //constexpr unsigned exponent_bits_all_set = (1u << format::exponent_bits) - 1;
+ return exponent_bits != (1u << format::exponent_bits) - 1;
+ }
+
+ static constexpr bool has_all_zero_significand_bits(carrier_uint u) noexcept
+ {
+ return (u << 1) == 0;
+ }
+
+ static constexpr bool has_even_significand_bits(carrier_uint u) noexcept
+ {
+ return u % 2 == 0;
+ }
+};
+
+// Convenient wrappers for floating-point traits classes.
+// In order to reduce the argument passing overhead, these classes should be as simple as
+// possible (e.g., no inheritance, no private non-static data member, etc.; this is an
+// unfortunate fact about common ABI convention).
+
+template <typename T, typename Traits = default_float_traits<T>>
+struct float_bits;
+
+template <typename T, typename Traits = default_float_traits<T>>
+struct signed_significand_bits;
+
+template <typename T, typename Traits>
+struct float_bits
+{
+ using type = T;
+ using traits_type = Traits;
+ using carrier_uint = typename traits_type::carrier_uint;
+
+ carrier_uint u;
+
+ float_bits() = default;
+ constexpr explicit float_bits(carrier_uint bit_pattern) noexcept : u{bit_pattern} {}
+ constexpr explicit float_bits(T float_value) noexcept : u{traits_type::float_to_carrier(float_value)} {}
+
+ constexpr T to_float() const noexcept { return traits_type::carrier_to_float(u); }
+
+ // Extract exponent bits from a bit pattern.
+ // The result must be aligned to the LSB so that there is no additional zero paddings
+ // on the right. This function does not do bias adjustment.
+ constexpr unsigned extract_exponent_bits() const noexcept
+ {
+ return traits_type::extract_exponent_bits(u);
+ }
+
+ // Extract significand bits from a bit pattern.
+ // The result must be aligned to the LSB so that there is no additional zero paddings
+ // on the right. The result does not contain the implicit bit.
+ constexpr carrier_uint extract_significand_bits() const noexcept
+ {
+ return traits_type::extract_significand_bits(u);
+ }
+
+ // Remove the exponent bits and extract significand bits together with the sign bit.
+ constexpr signed_significand_bits<type, traits_type> remove_exponent_bits(unsigned exponent_bits) const noexcept
+ {
+ return signed_significand_bits<type, traits_type>(traits_type::remove_exponent_bits(u, exponent_bits));
+ }
+
+ // Obtain the actual value of the binary exponent from the extracted exponent bits.
+ static constexpr int binary_exponent(unsigned exponent_bits) noexcept
+ {
+ return traits_type::binary_exponent(exponent_bits);
+ }
+
+ constexpr int binary_exponent() const noexcept
+ {
+ return binary_exponent(extract_exponent_bits());
+ }
+
+ // Obtain the actual value of the binary exponent from the extracted significand bits and
+ // exponent bits.
+ static constexpr carrier_uint binary_significand(carrier_uint significand_bits, unsigned exponent_bits) noexcept
+ {
+ return traits_type::binary_significand(significand_bits, exponent_bits);
+ }
+
+ constexpr carrier_uint binary_significand() const noexcept
+ {
+ return binary_significand(extract_significand_bits(), extract_exponent_bits());
+ }
+
+ constexpr bool is_nonzero() const noexcept { return traits_type::is_nonzero(u); }
+
+ constexpr bool is_positive() const noexcept { return traits_type::is_positive(u); }
+
+ constexpr bool is_negative() const noexcept { return traits_type::is_negative(u); }
+
+ constexpr bool is_finite(unsigned exponent_bits) const noexcept { return traits_type::is_finite(exponent_bits); }
+
+ constexpr bool is_finite() const noexcept { return traits_type::is_finite(extract_exponent_bits()); }
+
+ constexpr bool has_even_significand_bits() const noexcept { return traits_type::has_even_significand_bits(u); }
+};
+
+template <typename T, typename Traits>
+struct signed_significand_bits
+{
+ using type = T;
+ using traits_type = Traits;
+ using carrier_uint = typename traits_type::carrier_uint;
+
+ carrier_uint u;
+
+ signed_significand_bits() = default;
+ constexpr explicit signed_significand_bits(carrier_uint bit_pattern) noexcept
+ : u{bit_pattern} {}
+
+ // Shift the obtained signed significand bits to the left by 1 to remove the sign bit.
+ constexpr carrier_uint remove_sign_bit_and_shift() const noexcept
+ {
+ return traits_type::remove_sign_bit_and_shift(u);
+ }
+
+ constexpr bool is_positive() const noexcept { return traits_type::is_positive(u); }
+
+ constexpr bool is_negative() const noexcept { return traits_type::is_negative(u); }
+
+ constexpr bool has_all_zero_significand_bits() const noexcept
+ {
+ return traits_type::has_all_zero_significand_bits(u);
+ }
+
+ constexpr bool has_even_significand_bits() const noexcept
+ {
+ return traits_type::has_even_significand_bits(u);
+ }
+};
+
+////////////////////////////////////////////////////////////////////////////////////////
+// Some simple utilities for constexpr computation.
+////////////////////////////////////////////////////////////////////////////////////////
+
+template <class Int, class Int2>
+BOOST_CHARCONV_CXX14_CONSTEXPR Int compute_power(Int a, Int2 exp) noexcept
+{
+ BOOST_CHARCONV_ASSERT(exp >= 0);
+
+ Int res = 1;
+ while (exp > 0)
+ {
+ if (exp % 2 != 0)
+ {
+ res *= a;
+ }
+
+ a *= a;
+ exp >>= 1;
+ }
+ return res;
+}
+
+static constexpr std::uint64_t power_of_10[] = {
+ UINT64_C(1), UINT64_C(10), UINT64_C(100), UINT64_C(1000), UINT64_C(10000),
+ UINT64_C(100000), UINT64_C(1000000), UINT64_C(10000000), UINT64_C(100000000),
+ UINT64_C(1000000000), UINT64_C(10000000000), UINT64_C(100000000000), UINT64_C(1000000000000),
+ UINT64_C(10000000000000), UINT64_C(100000000000000), UINT64_C(1000000000000000),
+ UINT64_C(10000000000000000), UINT64_C(100000000000000000), UINT64_C(1000000000000000000),
+ UINT64_C(10000000000000000000)
+};
+
+static_assert(sizeof(power_of_10) == 20 * sizeof(std::uint64_t), "There should be the first 20 powers of 10");
+
+
+template <unsigned a, typename UInt>
+BOOST_CHARCONV_CXX14_CONSTEXPR int count_factors(UInt n) noexcept
+{
+ int c = 0;
+
+ while (n % a == 0)
+ {
+ n /= a;
+ ++c;
+ }
+ return c;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+// Utilities for fast/constexpr log computation.
+////////////////////////////////////////////////////////////////////////////////////////
+
+namespace log {
+static_assert((-1 >> 1) == -1, "right-shift for signed integers must be arithmetic");
+
+// Compute floor(e * c - s).
+enum class multiply : std::uint32_t {};
+enum class subtract : std::uint32_t {};
+enum class shift : std::size_t {};
+enum class min_exponent : std::int32_t {};
+enum class max_exponent : std::int32_t {};
+
+template <multiply m, subtract f, shift k, min_exponent e_min, max_exponent e_max>
+constexpr int compute(int e) noexcept
+{
+ return static_cast<int>((std::int32_t(e) * std::int32_t(m) - std::int32_t(f)) >> std::size_t(k));
+}
+
+// For constexpr computation.
+// Returns -1 when n = 0.
+template <class UInt>
+BOOST_CHARCONV_CXX14_CONSTEXPR int floor_log2(UInt n) noexcept
+{
+ int count = -1;
+ while (n != 0)
+ {
+ ++count;
+ n >>= 1;
+ }
+
+ return count;
+}
+
+static constexpr int floor_log10_pow2_min_exponent = -2620;
+
+static constexpr int floor_log10_pow2_max_exponent = 2620;
+
+constexpr int floor_log10_pow2(int e) noexcept
+{
+ using namespace log;
+ return compute<multiply(315653), subtract(0), shift(20),
+ min_exponent(floor_log10_pow2_min_exponent),
+ max_exponent(floor_log10_pow2_max_exponent)>(e);
+}
+
+static constexpr int floor_log2_pow10_min_exponent = -1233;
+
+static constexpr int floor_log2_pow10_max_exponent = 1233;
+
+constexpr int floor_log2_pow10(int e) noexcept
+{
+ using namespace log;
+ return compute<multiply(1741647), subtract(0), shift(19),
+ min_exponent(floor_log2_pow10_min_exponent),
+ max_exponent(floor_log2_pow10_max_exponent)>(e);
+}
+
+static constexpr int floor_log10_pow2_minus_log10_4_over_3_min_exponent = -2985;
+
+static constexpr int floor_log10_pow2_minus_log10_4_over_3_max_exponent = 2936;
+
+constexpr int floor_log10_pow2_minus_log10_4_over_3(int e) noexcept
+{
+ using namespace log;
+ return compute<multiply(631305), subtract(261663), shift(21),
+ min_exponent(floor_log10_pow2_minus_log10_4_over_3_min_exponent),
+ max_exponent(floor_log10_pow2_minus_log10_4_over_3_max_exponent)>(e);
+}
+
+static constexpr int floor_log5_pow2_min_exponent = -1831;
+
+static constexpr int floor_log5_pow2_max_exponent = 1831;
+
+constexpr int floor_log5_pow2(int e) noexcept
+{
+ using namespace log;
+ return compute<multiply(225799), subtract(0), shift(19),
+ min_exponent(floor_log5_pow2_min_exponent),
+ max_exponent(floor_log5_pow2_max_exponent)>(e);
+}
+
+static constexpr int floor_log5_pow2_minus_log5_3_min_exponent = -3543;
+
+static constexpr int floor_log5_pow2_minus_log5_3_max_exponent = 2427;
+
+constexpr int floor_log5_pow2_minus_log5_3(int e) noexcept
+{
+ using namespace log;
+ return compute<multiply(451597), subtract(715764), shift(20),
+ min_exponent(floor_log5_pow2_minus_log5_3_min_exponent),
+ max_exponent(floor_log5_pow2_minus_log5_3_max_exponent)>(e);
+}
+} // Namespace log
+
+template <bool b>
+struct main_cache_holder_impl
+{
+ using cache_entry_type = boost::charconv::detail::uint128;
+ static constexpr int cache_bits = 128;
+ static constexpr int min_k = -292;
+ static constexpr int max_k = 326;
+ static constexpr cache_entry_type cache[] = {
+ {0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7b}, {0x9faacf3df73609b1, 0x77b191618c54e9ad},
+ {0xc795830d75038c1d, 0xd59df5b9ef6a2418}, {0xf97ae3d0d2446f25, 0x4b0573286b44ad1e},
+ {0x9becce62836ac577, 0x4ee367f9430aec33}, {0xc2e801fb244576d5, 0x229c41f793cda740},
+ {0xf3a20279ed56d48a, 0x6b43527578c11110}, {0x9845418c345644d6, 0x830a13896b78aaaa},
+ {0xbe5691ef416bd60c, 0x23cc986bc656d554}, {0xedec366b11c6cb8f, 0x2cbfbe86b7ec8aa9},
+ {0x94b3a202eb1c3f39, 0x7bf7d71432f3d6aa}, {0xb9e08a83a5e34f07, 0xdaf5ccd93fb0cc54},
+ {0xe858ad248f5c22c9, 0xd1b3400f8f9cff69}, {0x91376c36d99995be, 0x23100809b9c21fa2},
+ {0xb58547448ffffb2d, 0xabd40a0c2832a78b}, {0xe2e69915b3fff9f9, 0x16c90c8f323f516d},
+ {0x8dd01fad907ffc3b, 0xae3da7d97f6792e4}, {0xb1442798f49ffb4a, 0x99cd11cfdf41779d},
+ {0xdd95317f31c7fa1d, 0x40405643d711d584}, {0x8a7d3eef7f1cfc52, 0x482835ea666b2573},
+ {0xad1c8eab5ee43b66, 0xda3243650005eed0}, {0xd863b256369d4a40, 0x90bed43e40076a83},
+ {0x873e4f75e2224e68, 0x5a7744a6e804a292}, {0xa90de3535aaae202, 0x711515d0a205cb37},
+ {0xd3515c2831559a83, 0x0d5a5b44ca873e04}, {0x8412d9991ed58091, 0xe858790afe9486c3},
+ {0xa5178fff668ae0b6, 0x626e974dbe39a873}, {0xce5d73ff402d98e3, 0xfb0a3d212dc81290},
+ {0x80fa687f881c7f8e, 0x7ce66634bc9d0b9a}, {0xa139029f6a239f72, 0x1c1fffc1ebc44e81},
+ {0xc987434744ac874e, 0xa327ffb266b56221}, {0xfbe9141915d7a922, 0x4bf1ff9f0062baa9},
+ {0x9d71ac8fada6c9b5, 0x6f773fc3603db4aa}, {0xc4ce17b399107c22, 0xcb550fb4384d21d4},
+ {0xf6019da07f549b2b, 0x7e2a53a146606a49}, {0x99c102844f94e0fb, 0x2eda7444cbfc426e},
+ {0xc0314325637a1939, 0xfa911155fefb5309}, {0xf03d93eebc589f88, 0x793555ab7eba27cb},
+ {0x96267c7535b763b5, 0x4bc1558b2f3458df}, {0xbbb01b9283253ca2, 0x9eb1aaedfb016f17},
+ {0xea9c227723ee8bcb, 0x465e15a979c1cadd}, {0x92a1958a7675175f, 0x0bfacd89ec191eca},
+ {0xb749faed14125d36, 0xcef980ec671f667c}, {0xe51c79a85916f484, 0x82b7e12780e7401b},
+ {0x8f31cc0937ae58d2, 0xd1b2ecb8b0908811}, {0xb2fe3f0b8599ef07, 0x861fa7e6dcb4aa16},
+ {0xdfbdcece67006ac9, 0x67a791e093e1d49b}, {0x8bd6a141006042bd, 0xe0c8bb2c5c6d24e1},
+ {0xaecc49914078536d, 0x58fae9f773886e19}, {0xda7f5bf590966848, 0xaf39a475506a899f},
+ {0x888f99797a5e012d, 0x6d8406c952429604}, {0xaab37fd7d8f58178, 0xc8e5087ba6d33b84},
+ {0xd5605fcdcf32e1d6, 0xfb1e4a9a90880a65}, {0x855c3be0a17fcd26, 0x5cf2eea09a550680},
+ {0xa6b34ad8c9dfc06f, 0xf42faa48c0ea481f}, {0xd0601d8efc57b08b, 0xf13b94daf124da27},
+ {0x823c12795db6ce57, 0x76c53d08d6b70859}, {0xa2cb1717b52481ed, 0x54768c4b0c64ca6f},
+ {0xcb7ddcdda26da268, 0xa9942f5dcf7dfd0a}, {0xfe5d54150b090b02, 0xd3f93b35435d7c4d},
+ {0x9efa548d26e5a6e1, 0xc47bc5014a1a6db0}, {0xc6b8e9b0709f109a, 0x359ab6419ca1091c},
+ {0xf867241c8cc6d4c0, 0xc30163d203c94b63}, {0x9b407691d7fc44f8, 0x79e0de63425dcf1e},
+ {0xc21094364dfb5636, 0x985915fc12f542e5}, {0xf294b943e17a2bc4, 0x3e6f5b7b17b2939e},
+ {0x979cf3ca6cec5b5a, 0xa705992ceecf9c43}, {0xbd8430bd08277231, 0x50c6ff782a838354},
+ {0xece53cec4a314ebd, 0xa4f8bf5635246429}, {0x940f4613ae5ed136, 0x871b7795e136be9a},
+ {0xb913179899f68584, 0x28e2557b59846e40}, {0xe757dd7ec07426e5, 0x331aeada2fe589d0},
+ {0x9096ea6f3848984f, 0x3ff0d2c85def7622}, {0xb4bca50b065abe63, 0x0fed077a756b53aa},
+ {0xe1ebce4dc7f16dfb, 0xd3e8495912c62895}, {0x8d3360f09cf6e4bd, 0x64712dd7abbbd95d},
+ {0xb080392cc4349dec, 0xbd8d794d96aacfb4}, {0xdca04777f541c567, 0xecf0d7a0fc5583a1},
+ {0x89e42caaf9491b60, 0xf41686c49db57245}, {0xac5d37d5b79b6239, 0x311c2875c522ced6},
+ {0xd77485cb25823ac7, 0x7d633293366b828c}, {0x86a8d39ef77164bc, 0xae5dff9c02033198},
+ {0xa8530886b54dbdeb, 0xd9f57f830283fdfd}, {0xd267caa862a12d66, 0xd072df63c324fd7c},
+ {0x8380dea93da4bc60, 0x4247cb9e59f71e6e}, {0xa46116538d0deb78, 0x52d9be85f074e609},
+ {0xcd795be870516656, 0x67902e276c921f8c}, {0x806bd9714632dff6, 0x00ba1cd8a3db53b7},
+ {0xa086cfcd97bf97f3, 0x80e8a40eccd228a5}, {0xc8a883c0fdaf7df0, 0x6122cd128006b2ce},
+ {0xfad2a4b13d1b5d6c, 0x796b805720085f82}, {0x9cc3a6eec6311a63, 0xcbe3303674053bb1},
+ {0xc3f490aa77bd60fc, 0xbedbfc4411068a9d}, {0xf4f1b4d515acb93b, 0xee92fb5515482d45},
+ {0x991711052d8bf3c5, 0x751bdd152d4d1c4b}, {0xbf5cd54678eef0b6, 0xd262d45a78a0635e},
+ {0xef340a98172aace4, 0x86fb897116c87c35}, {0x9580869f0e7aac0e, 0xd45d35e6ae3d4da1},
+ {0xbae0a846d2195712, 0x8974836059cca10a}, {0xe998d258869facd7, 0x2bd1a438703fc94c},
+ {0x91ff83775423cc06, 0x7b6306a34627ddd0}, {0xb67f6455292cbf08, 0x1a3bc84c17b1d543},
+ {0xe41f3d6a7377eeca, 0x20caba5f1d9e4a94}, {0x8e938662882af53e, 0x547eb47b7282ee9d},
+ {0xb23867fb2a35b28d, 0xe99e619a4f23aa44}, {0xdec681f9f4c31f31, 0x6405fa00e2ec94d5},
+ {0x8b3c113c38f9f37e, 0xde83bc408dd3dd05}, {0xae0b158b4738705e, 0x9624ab50b148d446},
+ {0xd98ddaee19068c76, 0x3badd624dd9b0958}, {0x87f8a8d4cfa417c9, 0xe54ca5d70a80e5d7},
+ {0xa9f6d30a038d1dbc, 0x5e9fcf4ccd211f4d}, {0xd47487cc8470652b, 0x7647c32000696720},
+ {0x84c8d4dfd2c63f3b, 0x29ecd9f40041e074}, {0xa5fb0a17c777cf09, 0xf468107100525891},
+ {0xcf79cc9db955c2cc, 0x7182148d4066eeb5}, {0x81ac1fe293d599bf, 0xc6f14cd848405531},
+ {0xa21727db38cb002f, 0xb8ada00e5a506a7d}, {0xca9cf1d206fdc03b, 0xa6d90811f0e4851d},
+ {0xfd442e4688bd304a, 0x908f4a166d1da664}, {0x9e4a9cec15763e2e, 0x9a598e4e043287ff},
+ {0xc5dd44271ad3cdba, 0x40eff1e1853f29fe}, {0xf7549530e188c128, 0xd12bee59e68ef47d},
+ {0x9a94dd3e8cf578b9, 0x82bb74f8301958cf}, {0xc13a148e3032d6e7, 0xe36a52363c1faf02},
+ {0xf18899b1bc3f8ca1, 0xdc44e6c3cb279ac2}, {0x96f5600f15a7b7e5, 0x29ab103a5ef8c0ba},
+ {0xbcb2b812db11a5de, 0x7415d448f6b6f0e8}, {0xebdf661791d60f56, 0x111b495b3464ad22},
+ {0x936b9fcebb25c995, 0xcab10dd900beec35}, {0xb84687c269ef3bfb, 0x3d5d514f40eea743},
+ {0xe65829b3046b0afa, 0x0cb4a5a3112a5113}, {0x8ff71a0fe2c2e6dc, 0x47f0e785eaba72ac},
+ {0xb3f4e093db73a093, 0x59ed216765690f57}, {0xe0f218b8d25088b8, 0x306869c13ec3532d},
+ {0x8c974f7383725573, 0x1e414218c73a13fc}, {0xafbd2350644eeacf, 0xe5d1929ef90898fb},
+ {0xdbac6c247d62a583, 0xdf45f746b74abf3a}, {0x894bc396ce5da772, 0x6b8bba8c328eb784},
+ {0xab9eb47c81f5114f, 0x066ea92f3f326565}, {0xd686619ba27255a2, 0xc80a537b0efefebe},
+ {0x8613fd0145877585, 0xbd06742ce95f5f37}, {0xa798fc4196e952e7, 0x2c48113823b73705},
+ {0xd17f3b51fca3a7a0, 0xf75a15862ca504c6}, {0x82ef85133de648c4, 0x9a984d73dbe722fc},
+ {0xa3ab66580d5fdaf5, 0xc13e60d0d2e0ebbb}, {0xcc963fee10b7d1b3, 0x318df905079926a9},
+ {0xffbbcfe994e5c61f, 0xfdf17746497f7053}, {0x9fd561f1fd0f9bd3, 0xfeb6ea8bedefa634},
+ {0xc7caba6e7c5382c8, 0xfe64a52ee96b8fc1}, {0xf9bd690a1b68637b, 0x3dfdce7aa3c673b1},
+ {0x9c1661a651213e2d, 0x06bea10ca65c084f}, {0xc31bfa0fe5698db8, 0x486e494fcff30a63},
+ {0xf3e2f893dec3f126, 0x5a89dba3c3efccfb}, {0x986ddb5c6b3a76b7, 0xf89629465a75e01d},
+ {0xbe89523386091465, 0xf6bbb397f1135824}, {0xee2ba6c0678b597f, 0x746aa07ded582e2d},
+ {0x94db483840b717ef, 0xa8c2a44eb4571cdd}, {0xba121a4650e4ddeb, 0x92f34d62616ce414},
+ {0xe896a0d7e51e1566, 0x77b020baf9c81d18}, {0x915e2486ef32cd60, 0x0ace1474dc1d122f},
+ {0xb5b5ada8aaff80b8, 0x0d819992132456bb}, {0xe3231912d5bf60e6, 0x10e1fff697ed6c6a},
+ {0x8df5efabc5979c8f, 0xca8d3ffa1ef463c2}, {0xb1736b96b6fd83b3, 0xbd308ff8a6b17cb3},
+ {0xddd0467c64bce4a0, 0xac7cb3f6d05ddbdf}, {0x8aa22c0dbef60ee4, 0x6bcdf07a423aa96c},
+ {0xad4ab7112eb3929d, 0x86c16c98d2c953c7}, {0xd89d64d57a607744, 0xe871c7bf077ba8b8},
+ {0x87625f056c7c4a8b, 0x11471cd764ad4973}, {0xa93af6c6c79b5d2d, 0xd598e40d3dd89bd0},
+ {0xd389b47879823479, 0x4aff1d108d4ec2c4}, {0x843610cb4bf160cb, 0xcedf722a585139bb},
+ {0xa54394fe1eedb8fe, 0xc2974eb4ee658829}, {0xce947a3da6a9273e, 0x733d226229feea33},
+ {0x811ccc668829b887, 0x0806357d5a3f5260}, {0xa163ff802a3426a8, 0xca07c2dcb0cf26f8},
+ {0xc9bcff6034c13052, 0xfc89b393dd02f0b6}, {0xfc2c3f3841f17c67, 0xbbac2078d443ace3},
+ {0x9d9ba7832936edc0, 0xd54b944b84aa4c0e}, {0xc5029163f384a931, 0x0a9e795e65d4df12},
+ {0xf64335bcf065d37d, 0x4d4617b5ff4a16d6}, {0x99ea0196163fa42e, 0x504bced1bf8e4e46},
+ {0xc06481fb9bcf8d39, 0xe45ec2862f71e1d7}, {0xf07da27a82c37088, 0x5d767327bb4e5a4d},
+ {0x964e858c91ba2655, 0x3a6a07f8d510f870}, {0xbbe226efb628afea, 0x890489f70a55368c},
+ {0xeadab0aba3b2dbe5, 0x2b45ac74ccea842f}, {0x92c8ae6b464fc96f, 0x3b0b8bc90012929e},
+ {0xb77ada0617e3bbcb, 0x09ce6ebb40173745}, {0xe55990879ddcaabd, 0xcc420a6a101d0516},
+ {0x8f57fa54c2a9eab6, 0x9fa946824a12232e}, {0xb32df8e9f3546564, 0x47939822dc96abfa},
+ {0xdff9772470297ebd, 0x59787e2b93bc56f8}, {0x8bfbea76c619ef36, 0x57eb4edb3c55b65b},
+ {0xaefae51477a06b03, 0xede622920b6b23f2}, {0xdab99e59958885c4, 0xe95fab368e45ecee},
+ {0x88b402f7fd75539b, 0x11dbcb0218ebb415}, {0xaae103b5fcd2a881, 0xd652bdc29f26a11a},
+ {0xd59944a37c0752a2, 0x4be76d3346f04960}, {0x857fcae62d8493a5, 0x6f70a4400c562ddc},
+ {0xa6dfbd9fb8e5b88e, 0xcb4ccd500f6bb953}, {0xd097ad07a71f26b2, 0x7e2000a41346a7a8},
+ {0x825ecc24c873782f, 0x8ed400668c0c28c9}, {0xa2f67f2dfa90563b, 0x728900802f0f32fb},
+ {0xcbb41ef979346bca, 0x4f2b40a03ad2ffba}, {0xfea126b7d78186bc, 0xe2f610c84987bfa9},
+ {0x9f24b832e6b0f436, 0x0dd9ca7d2df4d7ca}, {0xc6ede63fa05d3143, 0x91503d1c79720dbc},
+ {0xf8a95fcf88747d94, 0x75a44c6397ce912b}, {0x9b69dbe1b548ce7c, 0xc986afbe3ee11abb},
+ {0xc24452da229b021b, 0xfbe85badce996169}, {0xf2d56790ab41c2a2, 0xfae27299423fb9c4},
+ {0x97c560ba6b0919a5, 0xdccd879fc967d41b}, {0xbdb6b8e905cb600f, 0x5400e987bbc1c921},
+ {0xed246723473e3813, 0x290123e9aab23b69}, {0x9436c0760c86e30b, 0xf9a0b6720aaf6522},
+ {0xb94470938fa89bce, 0xf808e40e8d5b3e6a}, {0xe7958cb87392c2c2, 0xb60b1d1230b20e05},
+ {0x90bd77f3483bb9b9, 0xb1c6f22b5e6f48c3}, {0xb4ecd5f01a4aa828, 0x1e38aeb6360b1af4},
+ {0xe2280b6c20dd5232, 0x25c6da63c38de1b1}, {0x8d590723948a535f, 0x579c487e5a38ad0f},
+ {0xb0af48ec79ace837, 0x2d835a9df0c6d852}, {0xdcdb1b2798182244, 0xf8e431456cf88e66},
+ {0x8a08f0f8bf0f156b, 0x1b8e9ecb641b5900}, {0xac8b2d36eed2dac5, 0xe272467e3d222f40},
+ {0xd7adf884aa879177, 0x5b0ed81dcc6abb10}, {0x86ccbb52ea94baea, 0x98e947129fc2b4ea},
+ {0xa87fea27a539e9a5, 0x3f2398d747b36225}, {0xd29fe4b18e88640e, 0x8eec7f0d19a03aae},
+ {0x83a3eeeef9153e89, 0x1953cf68300424ad}, {0xa48ceaaab75a8e2b, 0x5fa8c3423c052dd8},
+ {0xcdb02555653131b6, 0x3792f412cb06794e}, {0x808e17555f3ebf11, 0xe2bbd88bbee40bd1},
+ {0xa0b19d2ab70e6ed6, 0x5b6aceaeae9d0ec5}, {0xc8de047564d20a8b, 0xf245825a5a445276},
+ {0xfb158592be068d2e, 0xeed6e2f0f0d56713}, {0x9ced737bb6c4183d, 0x55464dd69685606c},
+ {0xc428d05aa4751e4c, 0xaa97e14c3c26b887}, {0xf53304714d9265df, 0xd53dd99f4b3066a9},
+ {0x993fe2c6d07b7fab, 0xe546a8038efe402a}, {0xbf8fdb78849a5f96, 0xde98520472bdd034},
+ {0xef73d256a5c0f77c, 0x963e66858f6d4441}, {0x95a8637627989aad, 0xdde7001379a44aa9},
+ {0xbb127c53b17ec159, 0x5560c018580d5d53}, {0xe9d71b689dde71af, 0xaab8f01e6e10b4a7},
+ {0x9226712162ab070d, 0xcab3961304ca70e9}, {0xb6b00d69bb55c8d1, 0x3d607b97c5fd0d23},
+ {0xe45c10c42a2b3b05, 0x8cb89a7db77c506b}, {0x8eb98a7a9a5b04e3, 0x77f3608e92adb243},
+ {0xb267ed1940f1c61c, 0x55f038b237591ed4}, {0xdf01e85f912e37a3, 0x6b6c46dec52f6689},
+ {0x8b61313bbabce2c6, 0x2323ac4b3b3da016}, {0xae397d8aa96c1b77, 0xabec975e0a0d081b},
+ {0xd9c7dced53c72255, 0x96e7bd358c904a22}, {0x881cea14545c7575, 0x7e50d64177da2e55},
+ {0xaa242499697392d2, 0xdde50bd1d5d0b9ea}, {0xd4ad2dbfc3d07787, 0x955e4ec64b44e865},
+ {0x84ec3c97da624ab4, 0xbd5af13bef0b113f}, {0xa6274bbdd0fadd61, 0xecb1ad8aeacdd58f},
+ {0xcfb11ead453994ba, 0x67de18eda5814af3}, {0x81ceb32c4b43fcf4, 0x80eacf948770ced8},
+ {0xa2425ff75e14fc31, 0xa1258379a94d028e}, {0xcad2f7f5359a3b3e, 0x096ee45813a04331},
+ {0xfd87b5f28300ca0d, 0x8bca9d6e188853fd}, {0x9e74d1b791e07e48, 0x775ea264cf55347e},
+ {0xc612062576589dda, 0x95364afe032a819e}, {0xf79687aed3eec551, 0x3a83ddbd83f52205},
+ {0x9abe14cd44753b52, 0xc4926a9672793543}, {0xc16d9a0095928a27, 0x75b7053c0f178294},
+ {0xf1c90080baf72cb1, 0x5324c68b12dd6339}, {0x971da05074da7bee, 0xd3f6fc16ebca5e04},
+ {0xbce5086492111aea, 0x88f4bb1ca6bcf585}, {0xec1e4a7db69561a5, 0x2b31e9e3d06c32e6},
+ {0x9392ee8e921d5d07, 0x3aff322e62439fd0}, {0xb877aa3236a4b449, 0x09befeb9fad487c3},
+ {0xe69594bec44de15b, 0x4c2ebe687989a9b4}, {0x901d7cf73ab0acd9, 0x0f9d37014bf60a11},
+ {0xb424dc35095cd80f, 0x538484c19ef38c95}, {0xe12e13424bb40e13, 0x2865a5f206b06fba},
+ {0x8cbccc096f5088cb, 0xf93f87b7442e45d4}, {0xafebff0bcb24aafe, 0xf78f69a51539d749},
+ {0xdbe6fecebdedd5be, 0xb573440e5a884d1c}, {0x89705f4136b4a597, 0x31680a88f8953031},
+ {0xabcc77118461cefc, 0xfdc20d2b36ba7c3e}, {0xd6bf94d5e57a42bc, 0x3d32907604691b4d},
+ {0x8637bd05af6c69b5, 0xa63f9a49c2c1b110}, {0xa7c5ac471b478423, 0x0fcf80dc33721d54},
+ {0xd1b71758e219652b, 0xd3c36113404ea4a9}, {0x83126e978d4fdf3b, 0x645a1cac083126ea},
+ {0xa3d70a3d70a3d70a, 0x3d70a3d70a3d70a4}, {0xcccccccccccccccc, 0xcccccccccccccccd},
+ {0x8000000000000000, 0x0000000000000000}, {0xa000000000000000, 0x0000000000000000},
+ {0xc800000000000000, 0x0000000000000000}, {0xfa00000000000000, 0x0000000000000000},
+ {0x9c40000000000000, 0x0000000000000000}, {0xc350000000000000, 0x0000000000000000},
+ {0xf424000000000000, 0x0000000000000000}, {0x9896800000000000, 0x0000000000000000},
+ {0xbebc200000000000, 0x0000000000000000}, {0xee6b280000000000, 0x0000000000000000},
+ {0x9502f90000000000, 0x0000000000000000}, {0xba43b74000000000, 0x0000000000000000},
+ {0xe8d4a51000000000, 0x0000000000000000}, {0x9184e72a00000000, 0x0000000000000000},
+ {0xb5e620f480000000, 0x0000000000000000}, {0xe35fa931a0000000, 0x0000000000000000},
+ {0x8e1bc9bf04000000, 0x0000000000000000}, {0xb1a2bc2ec5000000, 0x0000000000000000},
+ {0xde0b6b3a76400000, 0x0000000000000000}, {0x8ac7230489e80000, 0x0000000000000000},
+ {0xad78ebc5ac620000, 0x0000000000000000}, {0xd8d726b7177a8000, 0x0000000000000000},
+ {0x878678326eac9000, 0x0000000000000000}, {0xa968163f0a57b400, 0x0000000000000000},
+ {0xd3c21bcecceda100, 0x0000000000000000}, {0x84595161401484a0, 0x0000000000000000},
+ {0xa56fa5b99019a5c8, 0x0000000000000000}, {0xcecb8f27f4200f3a, 0x0000000000000000},
+ {0x813f3978f8940984, 0x4000000000000000}, {0xa18f07d736b90be5, 0x5000000000000000},
+ {0xc9f2c9cd04674ede, 0xa400000000000000}, {0xfc6f7c4045812296, 0x4d00000000000000},
+ {0x9dc5ada82b70b59d, 0xf020000000000000}, {0xc5371912364ce305, 0x6c28000000000000},
+ {0xf684df56c3e01bc6, 0xc732000000000000}, {0x9a130b963a6c115c, 0x3c7f400000000000},
+ {0xc097ce7bc90715b3, 0x4b9f100000000000}, {0xf0bdc21abb48db20, 0x1e86d40000000000},
+ {0x96769950b50d88f4, 0x1314448000000000}, {0xbc143fa4e250eb31, 0x17d955a000000000},
+ {0xeb194f8e1ae525fd, 0x5dcfab0800000000}, {0x92efd1b8d0cf37be, 0x5aa1cae500000000},
+ {0xb7abc627050305ad, 0xf14a3d9e40000000}, {0xe596b7b0c643c719, 0x6d9ccd05d0000000},
+ {0x8f7e32ce7bea5c6f, 0xe4820023a2000000}, {0xb35dbf821ae4f38b, 0xdda2802c8a800000},
+ {0xe0352f62a19e306e, 0xd50b2037ad200000}, {0x8c213d9da502de45, 0x4526f422cc340000},
+ {0xaf298d050e4395d6, 0x9670b12b7f410000}, {0xdaf3f04651d47b4c, 0x3c0cdd765f114000},
+ {0x88d8762bf324cd0f, 0xa5880a69fb6ac800}, {0xab0e93b6efee0053, 0x8eea0d047a457a00},
+ {0xd5d238a4abe98068, 0x72a4904598d6d880}, {0x85a36366eb71f041, 0x47a6da2b7f864750},
+ {0xa70c3c40a64e6c51, 0x999090b65f67d924}, {0xd0cf4b50cfe20765, 0xfff4b4e3f741cf6d},
+ {0x82818f1281ed449f, 0xbff8f10e7a8921a5}, {0xa321f2d7226895c7, 0xaff72d52192b6a0e},
+ {0xcbea6f8ceb02bb39, 0x9bf4f8a69f764491}, {0xfee50b7025c36a08, 0x02f236d04753d5b5},
+ {0x9f4f2726179a2245, 0x01d762422c946591}, {0xc722f0ef9d80aad6, 0x424d3ad2b7b97ef6},
+ {0xf8ebad2b84e0d58b, 0xd2e0898765a7deb3}, {0x9b934c3b330c8577, 0x63cc55f49f88eb30},
+ {0xc2781f49ffcfa6d5, 0x3cbf6b71c76b25fc}, {0xf316271c7fc3908a, 0x8bef464e3945ef7b},
+ {0x97edd871cfda3a56, 0x97758bf0e3cbb5ad}, {0xbde94e8e43d0c8ec, 0x3d52eeed1cbea318},
+ {0xed63a231d4c4fb27, 0x4ca7aaa863ee4bde}, {0x945e455f24fb1cf8, 0x8fe8caa93e74ef6b},
+ {0xb975d6b6ee39e436, 0xb3e2fd538e122b45}, {0xe7d34c64a9c85d44, 0x60dbbca87196b617},
+ {0x90e40fbeea1d3a4a, 0xbc8955e946fe31ce}, {0xb51d13aea4a488dd, 0x6babab6398bdbe42},
+ {0xe264589a4dcdab14, 0xc696963c7eed2dd2}, {0x8d7eb76070a08aec, 0xfc1e1de5cf543ca3},
+ {0xb0de65388cc8ada8, 0x3b25a55f43294bcc}, {0xdd15fe86affad912, 0x49ef0eb713f39ebf},
+ {0x8a2dbf142dfcc7ab, 0x6e3569326c784338}, {0xacb92ed9397bf996, 0x49c2c37f07965405},
+ {0xd7e77a8f87daf7fb, 0xdc33745ec97be907}, {0x86f0ac99b4e8dafd, 0x69a028bb3ded71a4},
+ {0xa8acd7c0222311bc, 0xc40832ea0d68ce0d}, {0xd2d80db02aabd62b, 0xf50a3fa490c30191},
+ {0x83c7088e1aab65db, 0x792667c6da79e0fb}, {0xa4b8cab1a1563f52, 0x577001b891185939},
+ {0xcde6fd5e09abcf26, 0xed4c0226b55e6f87}, {0x80b05e5ac60b6178, 0x544f8158315b05b5},
+ {0xa0dc75f1778e39d6, 0x696361ae3db1c722}, {0xc913936dd571c84c, 0x03bc3a19cd1e38ea},
+ {0xfb5878494ace3a5f, 0x04ab48a04065c724}, {0x9d174b2dcec0e47b, 0x62eb0d64283f9c77},
+ {0xc45d1df942711d9a, 0x3ba5d0bd324f8395}, {0xf5746577930d6500, 0xca8f44ec7ee3647a},
+ {0x9968bf6abbe85f20, 0x7e998b13cf4e1ecc}, {0xbfc2ef456ae276e8, 0x9e3fedd8c321a67f},
+ {0xefb3ab16c59b14a2, 0xc5cfe94ef3ea101f}, {0x95d04aee3b80ece5, 0xbba1f1d158724a13},
+ {0xbb445da9ca61281f, 0x2a8a6e45ae8edc98}, {0xea1575143cf97226, 0xf52d09d71a3293be},
+ {0x924d692ca61be758, 0x593c2626705f9c57}, {0xb6e0c377cfa2e12e, 0x6f8b2fb00c77836d},
+ {0xe498f455c38b997a, 0x0b6dfb9c0f956448}, {0x8edf98b59a373fec, 0x4724bd4189bd5ead},
+ {0xb2977ee300c50fe7, 0x58edec91ec2cb658}, {0xdf3d5e9bc0f653e1, 0x2f2967b66737e3ee},
+ {0x8b865b215899f46c, 0xbd79e0d20082ee75}, {0xae67f1e9aec07187, 0xecd8590680a3aa12},
+ {0xda01ee641a708de9, 0xe80e6f4820cc9496}, {0x884134fe908658b2, 0x3109058d147fdcde},
+ {0xaa51823e34a7eede, 0xbd4b46f0599fd416}, {0xd4e5e2cdc1d1ea96, 0x6c9e18ac7007c91b},
+ {0x850fadc09923329e, 0x03e2cf6bc604ddb1}, {0xa6539930bf6bff45, 0x84db8346b786151d},
+ {0xcfe87f7cef46ff16, 0xe612641865679a64}, {0x81f14fae158c5f6e, 0x4fcb7e8f3f60c07f},
+ {0xa26da3999aef7749, 0xe3be5e330f38f09e}, {0xcb090c8001ab551c, 0x5cadf5bfd3072cc6},
+ {0xfdcb4fa002162a63, 0x73d9732fc7c8f7f7}, {0x9e9f11c4014dda7e, 0x2867e7fddcdd9afb},
+ {0xc646d63501a1511d, 0xb281e1fd541501b9}, {0xf7d88bc24209a565, 0x1f225a7ca91a4227},
+ {0x9ae757596946075f, 0x3375788de9b06959}, {0xc1a12d2fc3978937, 0x0052d6b1641c83af},
+ {0xf209787bb47d6b84, 0xc0678c5dbd23a49b}, {0x9745eb4d50ce6332, 0xf840b7ba963646e1},
+ {0xbd176620a501fbff, 0xb650e5a93bc3d899}, {0xec5d3fa8ce427aff, 0xa3e51f138ab4cebf},
+ {0x93ba47c980e98cdf, 0xc66f336c36b10138}, {0xb8a8d9bbe123f017, 0xb80b0047445d4185},
+ {0xe6d3102ad96cec1d, 0xa60dc059157491e6}, {0x9043ea1ac7e41392, 0x87c89837ad68db30},
+ {0xb454e4a179dd1877, 0x29babe4598c311fc}, {0xe16a1dc9d8545e94, 0xf4296dd6fef3d67b},
+ {0x8ce2529e2734bb1d, 0x1899e4a65f58660d}, {0xb01ae745b101e9e4, 0x5ec05dcff72e7f90},
+ {0xdc21a1171d42645d, 0x76707543f4fa1f74}, {0x899504ae72497eba, 0x6a06494a791c53a9},
+ {0xabfa45da0edbde69, 0x0487db9d17636893}, {0xd6f8d7509292d603, 0x45a9d2845d3c42b7},
+ {0x865b86925b9bc5c2, 0x0b8a2392ba45a9b3}, {0xa7f26836f282b732, 0x8e6cac7768d7141f},
+ {0xd1ef0244af2364ff, 0x3207d795430cd927}, {0x8335616aed761f1f, 0x7f44e6bd49e807b9},
+ {0xa402b9c5a8d3a6e7, 0x5f16206c9c6209a7}, {0xcd036837130890a1, 0x36dba887c37a8c10},
+ {0x802221226be55a64, 0xc2494954da2c978a}, {0xa02aa96b06deb0fd, 0xf2db9baa10b7bd6d},
+ {0xc83553c5c8965d3d, 0x6f92829494e5acc8}, {0xfa42a8b73abbf48c, 0xcb772339ba1f17fa},
+ {0x9c69a97284b578d7, 0xff2a760414536efc}, {0xc38413cf25e2d70d, 0xfef5138519684abb},
+ {0xf46518c2ef5b8cd1, 0x7eb258665fc25d6a}, {0x98bf2f79d5993802, 0xef2f773ffbd97a62},
+ {0xbeeefb584aff8603, 0xaafb550ffacfd8fb}, {0xeeaaba2e5dbf6784, 0x95ba2a53f983cf39},
+ {0x952ab45cfa97a0b2, 0xdd945a747bf26184}, {0xba756174393d88df, 0x94f971119aeef9e5},
+ {0xe912b9d1478ceb17, 0x7a37cd5601aab85e}, {0x91abb422ccb812ee, 0xac62e055c10ab33b},
+ {0xb616a12b7fe617aa, 0x577b986b314d600a}, {0xe39c49765fdf9d94, 0xed5a7e85fda0b80c},
+ {0x8e41ade9fbebc27d, 0x14588f13be847308}, {0xb1d219647ae6b31c, 0x596eb2d8ae258fc9},
+ {0xde469fbd99a05fe3, 0x6fca5f8ed9aef3bc}, {0x8aec23d680043bee, 0x25de7bb9480d5855},
+ {0xada72ccc20054ae9, 0xaf561aa79a10ae6b}, {0xd910f7ff28069da4, 0x1b2ba1518094da05},
+ {0x87aa9aff79042286, 0x90fb44d2f05d0843}, {0xa99541bf57452b28, 0x353a1607ac744a54},
+ {0xd3fa922f2d1675f2, 0x42889b8997915ce9}, {0x847c9b5d7c2e09b7, 0x69956135febada12},
+ {0xa59bc234db398c25, 0x43fab9837e699096}, {0xcf02b2c21207ef2e, 0x94f967e45e03f4bc},
+ {0x8161afb94b44f57d, 0x1d1be0eebac278f6}, {0xa1ba1ba79e1632dc, 0x6462d92a69731733},
+ {0xca28a291859bbf93, 0x7d7b8f7503cfdcff}, {0xfcb2cb35e702af78, 0x5cda735244c3d43f},
+ {0x9defbf01b061adab, 0x3a0888136afa64a8}, {0xc56baec21c7a1916, 0x088aaa1845b8fdd1},
+ {0xf6c69a72a3989f5b, 0x8aad549e57273d46}, {0x9a3c2087a63f6399, 0x36ac54e2f678864c},
+ {0xc0cb28a98fcf3c7f, 0x84576a1bb416a7de}, {0xf0fdf2d3f3c30b9f, 0x656d44a2a11c51d6},
+ {0x969eb7c47859e743, 0x9f644ae5a4b1b326}, {0xbc4665b596706114, 0x873d5d9f0dde1fef},
+ {0xeb57ff22fc0c7959, 0xa90cb506d155a7eb}, {0x9316ff75dd87cbd8, 0x09a7f12442d588f3},
+ {0xb7dcbf5354e9bece, 0x0c11ed6d538aeb30}, {0xe5d3ef282a242e81, 0x8f1668c8a86da5fb},
+ {0x8fa475791a569d10, 0xf96e017d694487bd}, {0xb38d92d760ec4455, 0x37c981dcc395a9ad},
+ {0xe070f78d3927556a, 0x85bbe253f47b1418}, {0x8c469ab843b89562, 0x93956d7478ccec8f},
+ {0xaf58416654a6babb, 0x387ac8d1970027b3}, {0xdb2e51bfe9d0696a, 0x06997b05fcc0319f},
+ {0x88fcf317f22241e2, 0x441fece3bdf81f04}, {0xab3c2fddeeaad25a, 0xd527e81cad7626c4},
+ {0xd60b3bd56a5586f1, 0x8a71e223d8d3b075}, {0x85c7056562757456, 0xf6872d5667844e4a},
+ {0xa738c6bebb12d16c, 0xb428f8ac016561dc}, {0xd106f86e69d785c7, 0xe13336d701beba53},
+ {0x82a45b450226b39c, 0xecc0024661173474}, {0xa34d721642b06084, 0x27f002d7f95d0191},
+ {0xcc20ce9bd35c78a5, 0x31ec038df7b441f5}, {0xff290242c83396ce, 0x7e67047175a15272},
+ {0x9f79a169bd203e41, 0x0f0062c6e984d387}, {0xc75809c42c684dd1, 0x52c07b78a3e60869},
+ {0xf92e0c3537826145, 0xa7709a56ccdf8a83}, {0x9bbcc7a142b17ccb, 0x88a66076400bb692},
+ {0xc2abf989935ddbfe, 0x6acff893d00ea436}, {0xf356f7ebf83552fe, 0x0583f6b8c4124d44},
+ {0x98165af37b2153de, 0xc3727a337a8b704b}, {0xbe1bf1b059e9a8d6, 0x744f18c0592e4c5d},
+ {0xeda2ee1c7064130c, 0x1162def06f79df74}, {0x9485d4d1c63e8be7, 0x8addcb5645ac2ba9},
+ {0xb9a74a0637ce2ee1, 0x6d953e2bd7173693}, {0xe8111c87c5c1ba99, 0xc8fa8db6ccdd0438},
+ {0x910ab1d4db9914a0, 0x1d9c9892400a22a3}, {0xb54d5e4a127f59c8, 0x2503beb6d00cab4c},
+ {0xe2a0b5dc971f303a, 0x2e44ae64840fd61e}, {0x8da471a9de737e24, 0x5ceaecfed289e5d3},
+ {0xb10d8e1456105dad, 0x7425a83e872c5f48}, {0xdd50f1996b947518, 0xd12f124e28f7771a},
+ {0x8a5296ffe33cc92f, 0x82bd6b70d99aaa70}, {0xace73cbfdc0bfb7b, 0x636cc64d1001550c},
+ {0xd8210befd30efa5a, 0x3c47f7e05401aa4f}, {0x8714a775e3e95c78, 0x65acfaec34810a72},
+ {0xa8d9d1535ce3b396, 0x7f1839a741a14d0e}, {0xd31045a8341ca07c, 0x1ede48111209a051},
+ {0x83ea2b892091e44d, 0x934aed0aab460433}, {0xa4e4b66b68b65d60, 0xf81da84d56178540},
+ {0xce1de40642e3f4b9, 0x36251260ab9d668f}, {0x80d2ae83e9ce78f3, 0xc1d72b7c6b42601a},
+ {0xa1075a24e4421730, 0xb24cf65b8612f820}, {0xc94930ae1d529cfc, 0xdee033f26797b628},
+ {0xfb9b7cd9a4a7443c, 0x169840ef017da3b2}, {0x9d412e0806e88aa5, 0x8e1f289560ee864f},
+ {0xc491798a08a2ad4e, 0xf1a6f2bab92a27e3}, {0xf5b5d7ec8acb58a2, 0xae10af696774b1dc},
+ {0x9991a6f3d6bf1765, 0xacca6da1e0a8ef2a}, {0xbff610b0cc6edd3f, 0x17fd090a58d32af4},
+ {0xeff394dcff8a948e, 0xddfc4b4cef07f5b1}, {0x95f83d0a1fb69cd9, 0x4abdaf101564f98f},
+ {0xbb764c4ca7a4440f, 0x9d6d1ad41abe37f2}, {0xea53df5fd18d5513, 0x84c86189216dc5ee},
+ {0x92746b9be2f8552c, 0x32fd3cf5b4e49bb5}, {0xb7118682dbb66a77, 0x3fbc8c33221dc2a2},
+ {0xe4d5e82392a40515, 0x0fabaf3feaa5334b}, {0x8f05b1163ba6832d, 0x29cb4d87f2a7400f},
+ {0xb2c71d5bca9023f8, 0x743e20e9ef511013}, {0xdf78e4b2bd342cf6, 0x914da9246b255417},
+ {0x8bab8eefb6409c1a, 0x1ad089b6c2f7548f}, {0xae9672aba3d0c320, 0xa184ac2473b529b2},
+ {0xda3c0f568cc4f3e8, 0xc9e5d72d90a2741f}, {0x8865899617fb1871, 0x7e2fa67c7a658893},
+ {0xaa7eebfb9df9de8d, 0xddbb901b98feeab8}, {0xd51ea6fa85785631, 0x552a74227f3ea566},
+ {0x8533285c936b35de, 0xd53a88958f872760}, {0xa67ff273b8460356, 0x8a892abaf368f138},
+ {0xd01fef10a657842c, 0x2d2b7569b0432d86}, {0x8213f56a67f6b29b, 0x9c3b29620e29fc74},
+ {0xa298f2c501f45f42, 0x8349f3ba91b47b90}, {0xcb3f2f7642717713, 0x241c70a936219a74},
+ {0xfe0efb53d30dd4d7, 0xed238cd383aa0111}, {0x9ec95d1463e8a506, 0xf4363804324a40ab},
+ {0xc67bb4597ce2ce48, 0xb143c6053edcd0d6}, {0xf81aa16fdc1b81da, 0xdd94b7868e94050b},
+ {0x9b10a4e5e9913128, 0xca7cf2b4191c8327}, {0xc1d4ce1f63f57d72, 0xfd1c2f611f63a3f1},
+ {0xf24a01a73cf2dccf, 0xbc633b39673c8ced}, {0x976e41088617ca01, 0xd5be0503e085d814},
+ {0xbd49d14aa79dbc82, 0x4b2d8644d8a74e19}, {0xec9c459d51852ba2, 0xddf8e7d60ed1219f},
+ {0x93e1ab8252f33b45, 0xcabb90e5c942b504}, {0xb8da1662e7b00a17, 0x3d6a751f3b936244},
+ {0xe7109bfba19c0c9d, 0x0cc512670a783ad5}, {0x906a617d450187e2, 0x27fb2b80668b24c6},
+ {0xb484f9dc9641e9da, 0xb1f9f660802dedf7}, {0xe1a63853bbd26451, 0x5e7873f8a0396974},
+ {0x8d07e33455637eb2, 0xdb0b487b6423e1e9}, {0xb049dc016abc5e5f, 0x91ce1a9a3d2cda63},
+ {0xdc5c5301c56b75f7, 0x7641a140cc7810fc}, {0x89b9b3e11b6329ba, 0xa9e904c87fcb0a9e},
+ {0xac2820d9623bf429, 0x546345fa9fbdcd45}, {0xd732290fbacaf133, 0xa97c177947ad4096},
+ {0x867f59a9d4bed6c0, 0x49ed8eabcccc485e}, {0xa81f301449ee8c70, 0x5c68f256bfff5a75},
+ {0xd226fc195c6a2f8c, 0x73832eec6fff3112}, {0x83585d8fd9c25db7, 0xc831fd53c5ff7eac},
+ {0xa42e74f3d032f525, 0xba3e7ca8b77f5e56}, {0xcd3a1230c43fb26f, 0x28ce1bd2e55f35ec},
+ {0x80444b5e7aa7cf85, 0x7980d163cf5b81b4}, {0xa0555e361951c366, 0xd7e105bcc3326220},
+ {0xc86ab5c39fa63440, 0x8dd9472bf3fefaa8}, {0xfa856334878fc150, 0xb14f98f6f0feb952},
+ {0x9c935e00d4b9d8d2, 0x6ed1bf9a569f33d4}, {0xc3b8358109e84f07, 0x0a862f80ec4700c9},
+ {0xf4a642e14c6262c8, 0xcd27bb612758c0fb}, {0x98e7e9cccfbd7dbd, 0x8038d51cb897789d},
+ {0xbf21e44003acdd2c, 0xe0470a63e6bd56c4}, {0xeeea5d5004981478, 0x1858ccfce06cac75},
+ {0x95527a5202df0ccb, 0x0f37801e0c43ebc9}, {0xbaa718e68396cffd, 0xd30560258f54e6bb},
+ {0xe950df20247c83fd, 0x47c6b82ef32a206a}, {0x91d28b7416cdd27e, 0x4cdc331d57fa5442},
+ {0xb6472e511c81471d, 0xe0133fe4adf8e953}, {0xe3d8f9e563a198e5, 0x58180fddd97723a7},
+ {0x8e679c2f5e44ff8f, 0x570f09eaa7ea7649}, {0xb201833b35d63f73, 0x2cd2cc6551e513db},
+ {0xde81e40a034bcf4f, 0xf8077f7ea65e58d2}, {0x8b112e86420f6191, 0xfb04afaf27faf783},
+ {0xadd57a27d29339f6, 0x79c5db9af1f9b564}, {0xd94ad8b1c7380874, 0x18375281ae7822bd},
+ {0x87cec76f1c830548, 0x8f2293910d0b15b6}, {0xa9c2794ae3a3c69a, 0xb2eb3875504ddb23},
+ {0xd433179d9c8cb841, 0x5fa60692a46151ec}, {0x849feec281d7f328, 0xdbc7c41ba6bcd334},
+ {0xa5c7ea73224deff3, 0x12b9b522906c0801}, {0xcf39e50feae16bef, 0xd768226b34870a01},
+ {0x81842f29f2cce375, 0xe6a1158300d46641}, {0xa1e53af46f801c53, 0x60495ae3c1097fd1},
+ {0xca5e89b18b602368, 0x385bb19cb14bdfc5}, {0xfcf62c1dee382c42, 0x46729e03dd9ed7b6},
+ {0x9e19db92b4e31ba9, 0x6c07a2c26a8346d2}, {0xc5a05277621be293, 0xc7098b7305241886},
+ {0xf70867153aa2db38, 0xb8cbee4fc66d1ea8}};
+};
+
+#if (defined(BOOST_NO_CXX17_INLINE_VARIABLES) && (!defined(BOOST_MSVC) || BOOST_MSVC != 1900)) || \
+ (defined(__clang_major__) && __clang_major__ == 5)
+
+template <bool b> constexpr int main_cache_holder_impl<b>::cache_bits;
+template <bool b> constexpr int main_cache_holder_impl<b>::min_k;
+template <bool b> constexpr int main_cache_holder_impl<b>::max_k;
+template <bool b> constexpr typename main_cache_holder_impl<b>::cache_entry_type main_cache_holder_impl<b>::cache[];
+
+#endif
+
+using main_cache_holder = main_cache_holder_impl<true>;
+
+// Compressed cache for double
+struct compressed_cache_detail
+{
+ static constexpr int compression_ratio = 27;
+ static constexpr std::size_t compressed_table_size = (main_cache_holder::max_k - main_cache_holder::min_k + compression_ratio) /
+ compression_ratio;
+
+ struct cache_holder_t
+ {
+ static constexpr uint128 table[] = {
+ {0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7b},
+ {0xa5178fff668ae0b6, 0x626e974dbe39a873},
+ {0x855c3be0a17fcd26, 0x5cf2eea09a550680},
+ {0xd77485cb25823ac7, 0x7d633293366b828c},
+ {0xae0b158b4738705e, 0x9624ab50b148d446},
+ {0x8c974f7383725573, 0x1e414218c73a13fc},
+ {0xe3231912d5bf60e6, 0x10e1fff697ed6c6a},
+ {0xb77ada0617e3bbcb, 0x09ce6ebb40173745},
+ {0x9436c0760c86e30b, 0xf9a0b6720aaf6522},
+ {0xef73d256a5c0f77c, 0x963e66858f6d4441},
+ {0xc16d9a0095928a27, 0x75b7053c0f178294},
+ {0x9c40000000000000, 0x0000000000000000},
+ {0xfc6f7c4045812296, 0x4d00000000000000},
+ {0xcbea6f8ceb02bb39, 0x9bf4f8a69f764491},
+ {0xa4b8cab1a1563f52, 0x577001b891185939},
+ {0x850fadc09923329e, 0x03e2cf6bc604ddb1},
+ {0xd6f8d7509292d603, 0x45a9d2845d3c42b7},
+ {0xada72ccc20054ae9, 0xaf561aa79a10ae6b},
+ {0x8c469ab843b89562, 0x93956d7478ccec8f},
+ {0xe2a0b5dc971f303a, 0x2e44ae64840fd61e},
+ {0xb7118682dbb66a77, 0x3fbc8c33221dc2a2},
+ {0x93e1ab8252f33b45, 0xcabb90e5c942b504},
+ {0xeeea5d5004981478, 0x1858ccfce06cac75},
+ };
+
+ static_assert(sizeof(table) == compressed_table_size * sizeof(uint128), "Table should have 23 elements");
+ };
+
+ struct pow5_holder_t
+ {
+ static constexpr std::uint64_t table[] = {
+ 1, 5, 25, 125, 625, 3125, 15625, 78125, 390625, 1953125, 9765625, 48828125, 244140625, 1220703125,
+ 6103515625, 30517578125, 152587890625, 762939453125, 3814697265625, 19073486328125, 95367431640625,
+ 476837158203125, 2384185791015625, 11920928955078125, 59604644775390625, 298023223876953125, 1490116119384765625
+ };
+
+ static_assert(sizeof(table) == compression_ratio * sizeof(std::uint64_t), "Table should have 27 elements");
+ };
+};
+
+}}}
+
+#endif // BOOST_CHARCONV_DETAIL_DRAGONBOX_COMMON_HPP
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/dragonbox/floff.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/dragonbox/floff.hpp
new file mode 100644
index 00000000000..32d138b3739
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/dragonbox/floff.hpp
@@ -0,0 +1,4044 @@
+// Copyright 2020-2022 Junekey Jeon
+//
+// The contents of this file may be used under the terms of
+// the Apache License v2.0 with LLVM Exceptions.
+//
+// (See accompanying file LICENSE-Apache or copy at
+// https://llvm.org/foundation/relicensing/LICENSE.txt)
+//
+// Alternatively, the contents of this file may be used under the terms of
+// the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE-Boost or copy at
+// https://www.boost.org/LICENSE_1_0.txt)
+//
+// Unless required by applicable law or agreed to in writing, this software
+// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.
+//
+// Some parts are copied from Dragonbox project.
+//
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_CHARCONV_DETAIL_FLOFF
+#define BOOST_CHARCONV_DETAIL_FLOFF
+
+#include <boost/charconv/detail/config.hpp>
+#include <boost/charconv/detail/bit_layouts.hpp>
+#include <boost/charconv/detail/emulated128.hpp>
+#include <boost/charconv/detail/dragonbox/dragonbox_common.hpp>
+#include <boost/charconv/detail/to_chars_result.hpp>
+#include <boost/charconv/chars_format.hpp>
+#include <boost/core/bit.hpp>
+#include <type_traits>
+#include <limits>
+#include <cstdint>
+#include <cstring>
+#include <cstddef>
+#include <climits>
+
+#ifdef BOOST_MSVC
+# pragma warning(push)
+# pragma warning(disable: 4127) // Extensive use of BOOST_IF_CONSTEXPR emits warnings under C++11 and 14
+# pragma warning(disable: 4554) // parentheses are used be warning is still emitted
+#endif
+
+namespace boost { namespace charconv { namespace detail {
+
+#ifdef BOOST_MSVC
+# pragma warning(push)
+# pragma warning(disable: 4702) // use of BOOST_IF_CONSTEXPR can result in unreachable code if max_blocks is 3
+ // Other older compilers will emit warnings if the unreachable code is wrapped
+ // in an else block (e.g. no return statment)
+#endif
+
+template <std::size_t max_blocks>
+struct fixed_point_calculator
+{
+ static_assert(1 < max_blocks, "Max blocks must be greater than 1");
+
+ // Multiply multiplier to the fractional blocks and take the resulting integer part.
+ // The fractional blocks are updated.
+ template <typename MultiplierType>
+ BOOST_FORCEINLINE static MultiplierType generate(MultiplierType multiplier,
+ std::uint64_t* blocks_ptr,
+ std::size_t number_of_blocks) noexcept
+ {
+ BOOST_CHARCONV_ASSERT(0 < number_of_blocks && number_of_blocks <= max_blocks);
+
+ BOOST_IF_CONSTEXPR (max_blocks == 3)
+ {
+ uint128 mul_result;
+ std::uint64_t carry = 0;
+
+ switch (number_of_blocks)
+ {
+ case 3:
+ mul_result = umul128(blocks_ptr[2], multiplier);
+ blocks_ptr[2] = mul_result.low;
+ carry = mul_result.high;
+ BOOST_FALLTHROUGH;
+
+ case 2:
+ mul_result = umul128(blocks_ptr[1], multiplier);
+ mul_result += carry;
+ blocks_ptr[1] = mul_result.low;
+ carry = mul_result.high;
+ BOOST_FALLTHROUGH;
+
+ case 1:
+ mul_result = umul128(blocks_ptr[0], multiplier);
+ mul_result += carry;
+ blocks_ptr[0] = mul_result.low;
+ return mul_result.high;
+
+ default:
+ BOOST_UNREACHABLE_RETURN(carry); // NOLINT : Macro for unreachable can expand to be empty
+ }
+ }
+
+ auto mul_result = umul128(blocks_ptr[number_of_blocks - 1], multiplier);
+ blocks_ptr[number_of_blocks - 1] = mul_result.low;
+ auto carry = mul_result.high;
+ for (std::size_t i = 1; i < number_of_blocks; ++i)
+ {
+ mul_result = umul128(blocks_ptr[number_of_blocks - i - 1], multiplier);
+ mul_result += carry;
+ blocks_ptr[number_of_blocks - i - 1] = mul_result.low;
+ carry = mul_result.high;
+ }
+
+ return MultiplierType(carry);
+ }
+
+ // Multiply multiplier to the fractional blocks and discard the resulting integer part.
+ // The fractional blocks are updated.
+ template <typename MultiplierType>
+ BOOST_FORCEINLINE static void discard_upper(MultiplierType multiplier,
+ std::uint64_t* blocks_ptr,
+ std::size_t number_of_blocks) noexcept
+ {
+ BOOST_CHARCONV_ASSERT(0 < number_of_blocks && number_of_blocks <= max_blocks);
+
+ blocks_ptr[0] *= multiplier;
+ if (number_of_blocks > 1)
+ {
+ BOOST_IF_CONSTEXPR (max_blocks == 3)
+ {
+ uint128 mul_result;
+ std::uint64_t carry = 0;
+
+ if (number_of_blocks > 2)
+ {
+ mul_result = umul128(multiplier, blocks_ptr[2]);
+ blocks_ptr[2] = mul_result.low;
+ carry = mul_result.high;
+ }
+
+ mul_result = umul128(multiplier, blocks_ptr[1]);
+ mul_result += carry;
+ blocks_ptr[1] = mul_result.low;
+ blocks_ptr[0] += mul_result.high;
+ }
+ else
+ {
+ auto mul_result = umul128(multiplier, blocks_ptr[number_of_blocks - 1]);
+ blocks_ptr[number_of_blocks - 1] = mul_result.low;
+ auto carry = mul_result.high;
+
+ for (std::size_t i = 2; i < number_of_blocks; ++i)
+ {
+ mul_result = umul128(multiplier, blocks_ptr[number_of_blocks - i]);
+ mul_result += carry;
+ blocks_ptr[number_of_blocks - i] = mul_result.low;
+ carry = mul_result.high;
+ }
+
+ blocks_ptr[0] += carry;
+ }
+ }
+ }
+
+ // Multiply multiplier to the fractional blocks and take the resulting integer part.
+ // Don't care about what happens to the fractional blocks.
+ template <typename MultiplierType>
+ BOOST_FORCEINLINE static MultiplierType
+ generate_and_discard_lower(MultiplierType multiplier, std::uint64_t* blocks_ptr,
+ std::size_t number_of_blocks) noexcept
+ {
+ BOOST_CHARCONV_ASSERT(0 < number_of_blocks && number_of_blocks <= max_blocks);
+
+ BOOST_IF_CONSTEXPR (max_blocks == 3)
+ {
+ uint128 mul_result;
+ std::uint64_t carry = 0;
+
+ switch (number_of_blocks)
+ {
+ case 3:
+ mul_result = umul128(blocks_ptr[2], static_cast<std::uint64_t>(multiplier));
+ carry = mul_result.high;
+ BOOST_FALLTHROUGH;
+
+ case 2:
+ mul_result = umul128(blocks_ptr[1], static_cast<std::uint64_t>(multiplier));
+ mul_result += carry;
+ carry = mul_result.high;
+ BOOST_FALLTHROUGH;
+
+ case 1:
+ mul_result = umul128(blocks_ptr[0], static_cast<std::uint64_t>(multiplier));
+ mul_result += carry;
+ return static_cast<MultiplierType>(mul_result.high);
+
+ default:
+ BOOST_UNREACHABLE_RETURN(carry); // NOLINT
+ }
+ }
+
+ auto mul_result = umul128(blocks_ptr[number_of_blocks - 1], static_cast<std::uint64_t>(multiplier));
+ auto carry = mul_result.high;
+ for (std::size_t i = 1; i < number_of_blocks; ++i)
+ {
+ mul_result = umul128(blocks_ptr[number_of_blocks - i - 1], static_cast<std::uint64_t>(multiplier));
+ mul_result += carry;
+ carry = mul_result.high;
+ }
+
+ return static_cast<MultiplierType>(carry);
+ }
+};
+
+#ifdef BOOST_MSVC
+# pragma warning(pop)
+#endif
+
+template <bool b>
+struct additional_static_data_holder_impl
+{
+ static constexpr char radix_100_table[] = {
+ '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', //
+ '0', '5', '0', '6', '0', '7', '0', '8', '0', '9', //
+ '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', //
+ '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', //
+ '2', '0', '2', '1', '2', '2', '2', '3', '2', '4', //
+ '2', '5', '2', '6', '2', '7', '2', '8', '2', '9', //
+ '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', //
+ '3', '5', '3', '6', '3', '7', '3', '8', '3', '9', //
+ '4', '0', '4', '1', '4', '2', '4', '3', '4', '4', //
+ '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', //
+ '5', '0', '5', '1', '5', '2', '5', '3', '5', '4', //
+ '5', '5', '5', '6', '5', '7', '5', '8', '5', '9', //
+ '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', //
+ '6', '5', '6', '6', '6', '7', '6', '8', '6', '9', //
+ '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', //
+ '7', '5', '7', '6', '7', '7', '7', '8', '7', '9', //
+ '8', '0', '8', '1', '8', '2', '8', '3', '8', '4', //
+ '8', '5', '8', '6', '8', '7', '8', '8', '8', '9', //
+ '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', //
+ '9', '5', '9', '6', '9', '7', '9', '8', '9', '9' //
+ };
+
+ static constexpr std::uint32_t fractional_part_rounding_thresholds32[] = {
+ UINT32_C(2576980378), UINT32_C(2190433321), UINT32_C(2151778616), UINT32_C(2147913145),
+ UINT32_C(2147526598), UINT32_C(2147487943), UINT32_C(2147484078), UINT32_C(2147483691)
+ };
+
+ static constexpr std::uint64_t fractional_part_rounding_thresholds64[] = {
+ UINT64_C(11068046444225730970), UINT64_C(9407839477591871325), UINT64_C(9241818780928485360),
+ UINT64_C(9225216711262146764), UINT64_C(9223556504295512904), UINT64_C(9223390483598849518),
+ UINT64_C(9223373881529183179), UINT64_C(9223372221322216546), UINT64_C(9223372055301519882),
+ UINT64_C(9223372038699450216), UINT64_C(9223372037039243249), UINT64_C(9223372036873222553),
+ UINT64_C(9223372036856620483), UINT64_C(9223372036854960276), UINT64_C(9223372036854794255),
+ UINT64_C(9223372036854777653), UINT64_C(9223372036854775993), UINT64_C(9223372036854775827)
+ };
+};
+
+#if defined(BOOST_NO_CXX17_INLINE_VARIABLES) && (!defined(BOOST_MSVC) || BOOST_MSVC != 1900)
+
+template <bool b> constexpr char additional_static_data_holder_impl<b>::radix_100_table[];
+template <bool b> constexpr std::uint32_t additional_static_data_holder_impl<b>::fractional_part_rounding_thresholds32[];
+template <bool b> constexpr std::uint64_t additional_static_data_holder_impl<b>::fractional_part_rounding_thresholds64[];
+
+#endif
+
+using additional_static_data_holder = additional_static_data_holder_impl<true>;
+
+struct compute_mul_result
+{
+ std::uint64_t result;
+ bool is_integer;
+};
+
+// Load the necessary bits into blocks_ptr and then return the number of cache blocks
+// loaded. The most significant block is loaded into blocks_ptr[0].
+template <typename ExtendedCache, bool zero_out,
+ typename CacheBlockType = typename std::decay<decltype(ExtendedCache::cache[0])>::type,
+ typename std::enable_if<(ExtendedCache::constant_block_count), bool>::type = true>
+inline std::uint8_t cache_block_count_helper(CacheBlockType*, int, int, std::uint32_t) noexcept
+{
+ return static_cast<std::uint8_t>(ExtendedCache::max_cache_blocks);
+}
+
+template <typename ExtendedCache, bool zero_out,
+ typename CacheBlockType = typename std::decay<decltype(ExtendedCache::cache[0])>::type,
+ typename std::enable_if<!(ExtendedCache::constant_block_count), bool>::type = true>
+inline std::uint8_t cache_block_count_helper(CacheBlockType*, int e, int, std::uint32_t multiplier_index) noexcept
+{
+ const auto mul_info = ExtendedCache::multiplier_index_info_table[multiplier_index];
+
+ const auto cache_block_count_index =
+ mul_info.cache_block_count_index_offset +
+ static_cast<std::uint32_t>(e - ExtendedCache::e_min) / ExtendedCache::collapse_factor -
+ ExtendedCache::cache_block_count_offset_base;
+
+ BOOST_IF_CONSTEXPR (ExtendedCache::max_cache_blocks < 3)
+ {
+ // 1-bit packing.
+ return static_cast<std::uint8_t>(
+ (ExtendedCache::cache_block_counts[cache_block_count_index /
+ 8] >>
+ (cache_block_count_index % 8)) &
+ 0x1) +
+ 1;
+ }
+ else BOOST_IF_CONSTEXPR (ExtendedCache::max_cache_blocks < 4)
+ {
+ // 2-bit packing.
+ return static_cast<std::uint8_t>(
+ (ExtendedCache::cache_block_counts[cache_block_count_index / 4] >>
+ (2 * (cache_block_count_index % 4))) &
+ 0x3);
+ }
+ else
+ {
+ // 4-bit packing.
+ return std::uint8_t(
+ (ExtendedCache::cache_block_counts[cache_block_count_index / 2] >>
+ (4 * (cache_block_count_index % 2))) &
+ 0xf);
+ }
+}
+
+template <typename ExtendedCache, bool zero_out,
+ typename CacheBlockType = typename std::decay<decltype(ExtendedCache::cache[0])>::type>
+BOOST_FORCEINLINE std::uint8_t load_extended_cache(CacheBlockType* blocks_ptr, int e, int k,
+ std::uint32_t multiplier_index) noexcept
+{
+ BOOST_IF_CONSTEXPR (zero_out)
+ {
+ std::memset(blocks_ptr, 0, sizeof(CacheBlockType) * ExtendedCache::max_cache_blocks);
+ }
+
+ const auto mul_info = ExtendedCache::multiplier_index_info_table[multiplier_index];
+
+ std::uint32_t number_of_leading_zero_blocks;
+ std::uint32_t first_cache_block_index;
+ std::uint32_t bit_offset;
+ std::uint32_t excessive_bits_to_left;
+ std::uint32_t excessive_bits_to_right;
+ std::uint8_t cache_block_count = cache_block_count_helper<ExtendedCache, zero_out, CacheBlockType>(blocks_ptr, e, k, multiplier_index);
+
+ // The request window starting/ending positions.
+ auto start_bit_index = static_cast<int>(mul_info.cache_bit_index_offset) + e - ExtendedCache::cache_bit_index_offset_base;
+ auto end_bit_index = start_bit_index + cache_block_count * static_cast<int>(ExtendedCache::cache_bits_unit);
+
+ // The source window starting/ending positions.
+ const auto src_start_bit_index = static_cast<int>(mul_info.first_cache_bit_index);
+ const auto src_end_bit_index = static_cast<int>(ExtendedCache::multiplier_index_info_table[multiplier_index + 1].first_cache_bit_index);
+
+ // If the request window goes further than the left boundary of the source window,
+ if (start_bit_index < src_start_bit_index)
+ {
+ number_of_leading_zero_blocks =
+ static_cast<std::uint32_t>(src_start_bit_index - start_bit_index) /
+ static_cast<std::uint32_t>(ExtendedCache::cache_bits_unit);
+ excessive_bits_to_left = static_cast<std::uint32_t>(src_start_bit_index - start_bit_index) %
+ static_cast<std::uint32_t>(ExtendedCache::cache_bits_unit);
+
+ BOOST_IF_CONSTEXPR (!zero_out)
+ {
+ std::memset(blocks_ptr, 0, number_of_leading_zero_blocks * sizeof(CacheBlockType));
+ }
+
+ start_bit_index += static_cast<int>(number_of_leading_zero_blocks * ExtendedCache::cache_bits_unit);
+
+ const auto src_start_block_index =
+ static_cast<int>(static_cast<std::uint32_t>(src_start_bit_index) /
+ static_cast<std::uint32_t>(ExtendedCache::cache_bits_unit));
+
+ const auto src_start_block_bit_index =
+ src_start_block_index * static_cast<int>(ExtendedCache::cache_bits_unit);
+
+ first_cache_block_index = static_cast<std::uint32_t>(src_start_block_index);
+
+ if (start_bit_index < src_start_block_bit_index)
+ {
+ auto shift_amount = src_start_block_bit_index - start_bit_index;
+ BOOST_CHARCONV_ASSERT(shift_amount >= 0 && shift_amount < static_cast<int>(ExtendedCache::cache_bits_unit));
+
+ blocks_ptr[number_of_leading_zero_blocks] =
+ ((ExtendedCache::cache[src_start_block_index] >> shift_amount) &
+ (CacheBlockType(CacheBlockType(0) - CacheBlockType(1)) >>
+ excessive_bits_to_left));
+
+ ++number_of_leading_zero_blocks;
+ bit_offset = static_cast<std::uint32_t>(static_cast<int>(ExtendedCache::cache_bits_unit) - shift_amount);
+ excessive_bits_to_left = 0;
+ }
+ else
+ {
+ bit_offset = static_cast<std::uint32_t>(start_bit_index - src_start_block_bit_index);
+ }
+ }
+ else
+ {
+ number_of_leading_zero_blocks = 0;
+ first_cache_block_index =
+ static_cast<std::uint32_t>(start_bit_index) / static_cast<std::uint32_t>(ExtendedCache::cache_bits_unit);
+ bit_offset =
+ static_cast<std::uint32_t>(start_bit_index) % static_cast<std::uint32_t>(ExtendedCache::cache_bits_unit);
+ excessive_bits_to_left = 0;
+ }
+
+ // If the request window goes further than the right boundary of the source window,
+ if (end_bit_index > src_end_bit_index)
+ {
+ const std::uint8_t number_of_trailing_zero_blocks =
+ static_cast<std::uint8_t>(end_bit_index - src_end_bit_index) / ExtendedCache::cache_bits_unit;
+ excessive_bits_to_right = static_cast<std::uint32_t>(end_bit_index - src_end_bit_index) %
+ static_cast<std::uint32_t>(ExtendedCache::cache_bits_unit);
+
+ cache_block_count -= number_of_trailing_zero_blocks;
+ }
+ else
+ {
+ excessive_bits_to_right = 0;
+ }
+
+ // Load blocks.
+ const auto number_of_blocks_to_load = cache_block_count - number_of_leading_zero_blocks;
+ auto* const dst_ptr = blocks_ptr + number_of_leading_zero_blocks;
+ if (bit_offset == 0)
+ {
+ BOOST_IF_CONSTEXPR (ExtendedCache::max_cache_blocks == 3)
+ {
+ switch (number_of_blocks_to_load)
+ {
+ case 3:
+ std::memcpy(dst_ptr, ExtendedCache::cache + first_cache_block_index, 3 * sizeof(CacheBlockType));
+ break;
+ case 2:
+ std::memcpy(dst_ptr, ExtendedCache::cache + first_cache_block_index, 2 * sizeof(CacheBlockType));
+ break;
+ case 1:
+ std::memcpy(dst_ptr, ExtendedCache::cache + first_cache_block_index, 1 * sizeof(CacheBlockType));
+ break;
+ case 0:
+ break;
+ default:
+ BOOST_UNREACHABLE_RETURN(dst_ptr); // NOLINT
+ }
+ }
+ else
+ {
+ std::memcpy(dst_ptr, ExtendedCache::cache + first_cache_block_index, number_of_blocks_to_load * sizeof(CacheBlockType));
+ }
+ }
+ else
+ {
+ BOOST_IF_CONSTEXPR (ExtendedCache::max_cache_blocks == 3)
+ {
+ switch (number_of_blocks_to_load)
+ {
+ case 3:
+ *(dst_ptr + 2) =
+ (ExtendedCache::cache[first_cache_block_index + 2] << bit_offset) |
+ (ExtendedCache::cache[first_cache_block_index + 3] >>
+ (ExtendedCache::cache_bits_unit - bit_offset));
+ BOOST_FALLTHROUGH;
+ case 2:
+ *(dst_ptr + 1) =
+ (ExtendedCache::cache[first_cache_block_index + 1] << bit_offset) |
+ (ExtendedCache::cache[first_cache_block_index + 2] >>
+ (ExtendedCache::cache_bits_unit - bit_offset));
+ BOOST_FALLTHROUGH;
+ case 1:
+ *dst_ptr = (ExtendedCache::cache[first_cache_block_index] << bit_offset) |
+ (ExtendedCache::cache[first_cache_block_index + 1] >>
+ (ExtendedCache::cache_bits_unit - bit_offset));
+ case 0:
+ break;
+ default:
+ BOOST_UNREACHABLE_RETURN(dst_ptr); // NOLINT
+ }
+ }
+ else
+ {
+ for (std::uint8_t i = 0; i < number_of_blocks_to_load; ++i)
+ {
+ *(dst_ptr + i) =
+ (ExtendedCache::cache[first_cache_block_index + i] << bit_offset) |
+ (ExtendedCache::cache[first_cache_block_index + i + 1] >>
+ (ExtendedCache::cache_bits_unit - bit_offset));
+ }
+ }
+ }
+
+ // Remove possible flooding bits from adjacent entries.
+ *dst_ptr &= (CacheBlockType(CacheBlockType(0) - CacheBlockType(1)) >> excessive_bits_to_left);
+
+ blocks_ptr[cache_block_count - 1] &= (CacheBlockType(CacheBlockType(0) - CacheBlockType(1)) << excessive_bits_to_right);
+
+ // To compute ceil(2^Q * x / D), we need to check if
+ // 2^Q * x / D = 2^(Q + e + k - eta - 1) * 5^(k - eta) is an integer or not.
+ if (k < ExtendedCache::segment_length ||
+ e + k + static_cast<int>(cache_block_count * ExtendedCache::cache_bits_unit) -
+ static_cast<int>(excessive_bits_to_right) <
+ ExtendedCache::segment_length + 1) {
+ blocks_ptr[cache_block_count - 1] += (CacheBlockType(1) << excessive_bits_to_right);
+ BOOST_CHARCONV_ASSERT(blocks_ptr[cache_block_count - 1] != 0);
+ }
+
+ return cache_block_count;
+}
+
+template <bool constant_block_count, std::uint8_t max_cache_blocks>
+struct cache_block_count_t;
+
+template <std::uint8_t max_cache_blocks>
+struct cache_block_count_t<false, max_cache_blocks>
+{
+ std::uint8_t value;
+
+ operator std::uint8_t() const noexcept { return value; } // NOLINT : implicit conversions are ok for block count
+ cache_block_count_t& operator=(std::uint8_t new_value) noexcept
+ {
+ value = new_value;
+ return *this;
+ }
+};
+
+template <std::uint8_t max_cache_blocks>
+struct cache_block_count_t<true, max_cache_blocks>
+{
+ static constexpr std::uint8_t value = max_cache_blocks;
+ operator std::uint8_t() const noexcept { return value; } // NOLINT : implicit conversions are ok for block count
+ cache_block_count_t& operator=(std::uint8_t) noexcept
+ {
+ // Don't do anything.
+ return *this;
+ }
+};
+
+template <unsigned n>
+struct uconst
+{
+ constexpr uconst() {}; // NOLINT : Clang 3.x does not support = default
+ static constexpr unsigned value = n;
+};
+
+BOOST_INLINE_VARIABLE constexpr uconst<0> uconst0;
+BOOST_INLINE_VARIABLE constexpr uconst<1> uconst1;
+BOOST_INLINE_VARIABLE constexpr uconst<6> uconst6;
+BOOST_INLINE_VARIABLE constexpr uconst<9> uconst9;
+BOOST_INLINE_VARIABLE constexpr uconst<14> uconst14;
+BOOST_INLINE_VARIABLE constexpr uconst<16> uconst16;
+
+#ifdef __clang__
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wsign-conversion"
+#elif defined(__GNUC__)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wsign-conversion"
+#elif defined(BOOST_MSVC)
+# pragma warning(push)
+# pragma warning(disable: 4365 4267)
+#endif
+
+template <unsigned digits, bool dummy = (digits <= 9)>
+struct uint_with_known_number_of_digits;
+
+template <unsigned digits_>
+struct uint_with_known_number_of_digits<digits_, true>
+{
+ static constexpr auto digits = digits_;
+ std::uint32_t value;
+};
+
+template <unsigned digits_>
+struct uint_with_known_number_of_digits<digits_, false>
+{
+ static constexpr auto digits = digits_;
+ std::uint64_t value;
+};
+
+template <typename HasFurtherDigits, typename... Args, typename std::enable_if<std::is_same<HasFurtherDigits, bool>::value, bool>::type = true>
+static BOOST_FORCEINLINE bool check_rounding_condition_inside_subsegment(
+ std::uint32_t current_digits, std::uint32_t fractional_part,
+ int remaining_digits_in_the_current_subsegment, HasFurtherDigits has_further_digits,
+ Args...) noexcept
+{
+ if (fractional_part >= additional_static_data_holder::fractional_part_rounding_thresholds32[remaining_digits_in_the_current_subsegment - 1])
+ {
+ return true;
+ }
+
+ return ((fractional_part >> 31) & ((current_digits & 1) | has_further_digits)) != 0;
+}
+
+template <typename HasFurtherDigits, typename... Args,
+ typename std::enable_if<!std::is_same<HasFurtherDigits, bool>::value, bool>::type = true>
+static BOOST_FORCEINLINE bool check_rounding_condition_inside_subsegment(
+ std::uint32_t current_digits, std::uint32_t fractional_part,
+ int remaining_digits_in_the_current_subsegment, HasFurtherDigits has_further_digits,
+ Args... args) noexcept
+{
+ if (fractional_part >= additional_static_data_holder::fractional_part_rounding_thresholds32[remaining_digits_in_the_current_subsegment - 1])
+ {
+ return true;
+ }
+
+ return fractional_part >= 0x80000000 && ((current_digits & 1) != 0 || has_further_digits(args...));
+}
+
+template <typename HasFurtherDigits, typename... Args,
+ typename std::enable_if<std::is_same<HasFurtherDigits, bool>::value, bool>::type = true>
+static BOOST_FORCEINLINE bool check_rounding_condition_with_next_bit(std::uint32_t current_digits, bool next_bit,
+ HasFurtherDigits has_further_digits, Args...) noexcept
+{
+ if (!next_bit)
+ {
+ return false;
+ }
+
+ return ((current_digits & 1) | has_further_digits) != 0;
+}
+
+template <typename HasFurtherDigits, typename... Args,
+ typename std::enable_if<!std::is_same<HasFurtherDigits, bool>::value, bool>::type = true>
+static BOOST_FORCEINLINE bool check_rounding_condition_with_next_bit(std::uint32_t current_digits, bool next_bit,
+ HasFurtherDigits has_further_digits, Args... args) noexcept
+{
+ if (!next_bit)
+ {
+ return false;
+ }
+
+ return (current_digits & 1) != 0 || has_further_digits(args...);
+}
+
+template <typename UintWithKnownDigits, typename HasFurtherDigits, typename... Args,
+ typename std::enable_if<std::is_same<HasFurtherDigits, bool>::value, bool>::type = true>
+static BOOST_FORCEINLINE bool check_rounding_condition_subsegment_boundary_with_next_subsegment(
+ std::uint32_t current_digits, UintWithKnownDigits next_subsegment,
+ HasFurtherDigits has_further_digits, Args...) noexcept
+{
+ if (next_subsegment.value > power_of_10[decltype(next_subsegment)::digits] / 2)
+ {
+ return true;
+ }
+
+ return next_subsegment.value == power_of_10[decltype(next_subsegment)::digits] / 2 &&
+ ((current_digits & 1) | has_further_digits) != 0;
+}
+
+template <typename UintWithKnownDigits, typename HasFurtherDigits, typename... Args,
+ typename std::enable_if<!std::is_same<HasFurtherDigits, bool>::value, bool>::type = true>
+static BOOST_FORCEINLINE bool check_rounding_condition_subsegment_boundary_with_next_subsegment(
+ std::uint32_t current_digits, UintWithKnownDigits next_subsegment,
+ HasFurtherDigits has_further_digits, Args... args) noexcept
+{
+ if (next_subsegment.value > power_of_10[decltype(next_subsegment)::digits] / 2)
+ {
+ return true;
+ }
+
+ return next_subsegment.value == power_of_10[decltype(next_subsegment)::digits] / 2 &&
+ ((current_digits & 1) != 0 || has_further_digits(args...));
+}
+
+#ifdef __clang__
+# pragma clang diagnostic pop
+#elif defined(__GNUC__)
+# pragma GCC diagnostic pop
+#elif defined(BOOST_MSVC)
+# pragma warning(pop)
+#endif
+
+#ifdef BOOST_MSVC
+# pragma warning(push)
+# pragma warning(disable: 4307) // MSVC 14.1 emits warnings for uint64_t constants
+#endif
+
+namespace has_further_digits_impl {
+template <int k_right_threshold, int additional_neg_exp_of_2>
+bool no_neg_k_can_be_integer(int k, int exp2_base) noexcept
+{
+ return k < k_right_threshold || exp2_base + k < additional_neg_exp_of_2;
+}
+
+template <int k_left_threshold, int k_right_threshold, int additional_neg_exp_of_2, int min_neg_exp_of_5, typename SignificandType>
+bool only_one_neg_k_can_be_integer(int k, int exp2_base, SignificandType significand) noexcept
+{
+ // Supposed to be k - additional_neg_exp_of_5_v < -min_neg_exp_of_5 || ...
+ if (k < k_left_threshold || exp2_base + k < additional_neg_exp_of_2)
+ {
+ return true;
+ }
+ // Supposed to be k - additional_neg_exp_of_5_v >= 0.
+ if (k >= k_right_threshold)
+ {
+ return false;
+ }
+
+ BOOST_CXX14_CONSTEXPR std::uint64_t mod_inv = compute_power(UINT64_C(0xcccccccccccccccd), static_cast<unsigned>(min_neg_exp_of_5));
+ BOOST_CXX14_CONSTEXPR std::uint64_t max_quot = UINT64_C(0xffffffffffffffff) / compute_power(UINT64_C(5), static_cast<unsigned>(min_neg_exp_of_5));
+
+ return (significand * mod_inv) > max_quot;
+}
+
+template <int k_left_threshold, int k_middle_threshold, int k_right_threshold,
+ int additional_neg_exp_of_2, int min_neg_exp_of_5, int segment_length,
+ typename SignificandType>
+bool only_two_neg_k_can_be_integer(int k, int exp2_base,
+ SignificandType significand) noexcept {
+ // Supposed to be k - additional_neg_exp_of_5_v < -min_neg_exp_of_5 - segment_length
+ // || ...
+ if (k < k_left_threshold || exp2_base + k < additional_neg_exp_of_2) {
+ return true;
+ }
+ // Supposed to be k - additional_neg_exp_of_5_v >= 0.
+ if (k >= k_right_threshold) {
+ return false;
+ }
+
+ if (k >= k_middle_threshold) {
+ BOOST_CXX14_CONSTEXPR std::uint64_t mod_inv =
+ compute_power(UINT64_C(0xcccccccccccccccd), static_cast<unsigned>(min_neg_exp_of_5));
+ BOOST_CXX14_CONSTEXPR std::uint64_t max_quot =
+ UINT64_C(0xffffffffffffffff) /
+ compute_power(UINT64_C(5), static_cast<unsigned>(min_neg_exp_of_5));
+
+ return (significand * mod_inv) > max_quot;
+ }
+ else {
+ BOOST_CXX14_CONSTEXPR std::uint64_t mod_inv = compute_power(
+ UINT64_C(0xcccccccccccccccd), static_cast<unsigned>(min_neg_exp_of_5 + segment_length));
+ BOOST_CXX14_CONSTEXPR std::uint64_t max_quot =
+ UINT64_C(0xffffffffffffffff) /
+ compute_power(UINT64_C(5),
+ static_cast<unsigned>(min_neg_exp_of_5 + segment_length));
+
+ return (significand * mod_inv) > max_quot;
+ }
+}
+} // Namespace has_further_digits_impl
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+inline void print_1_digit(std::uint32_t n, char* buffer) noexcept
+{
+ *buffer = char('0' + n);
+}
+
+inline void print_2_digits(std::uint32_t n, char* buffer) noexcept
+{
+ std::memcpy(buffer, additional_static_data_holder::radix_100_table + n * 2, 2);
+}
+
+inline void print_6_digits(std::uint32_t n, char* buffer) noexcept
+{
+ // 429497 = ceil(2^32/10^4)
+ auto prod = (n * UINT64_C(429497)) + 1;
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+
+ for (int i = 0; i < 2; ++i)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer + 2 + i * 2);
+ }
+}
+
+inline void print_7_digits(std::uint32_t n, char* buffer) noexcept
+{
+ // 17592187 = ceil(2^(32+12)/10^6)
+ auto prod = ((n * UINT64_C(17592187)) >> 12) + 1;
+ print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
+
+ for (int i = 0; i < 3; ++i)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer + 1 + i * 2);
+ }
+}
+
+inline void print_8_digits(std::uint32_t n, char* buffer) noexcept
+{
+ // 140737489 = ceil(2^(32+15)/10^6)
+ auto prod = ((n * UINT64_C(140737489)) >> 15) + 1;
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+
+ for (int i = 0; i < 3; ++i)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer + 2 + i * 2);
+ }
+}
+
+inline void print_9_digits(std::uint32_t n, char* buffer) noexcept
+{
+ // 1441151881 = ceil(2^(32+25)/10^8)
+ auto prod = ((n * UINT64_C(1441151881)) >> 25) + 1;
+ print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
+
+ for (int i = 0; i < 4; ++i)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer + 1 + i * 2);
+ }
+}
+
+struct main_cache_full
+{
+ template <typename FloatFormat>
+ static constexpr typename main_cache_holder::cache_entry_type get_cache(int k) noexcept
+ {
+ return main_cache_holder::cache[std::size_t(k - main_cache_holder::min_k)];
+ }
+};
+
+struct main_cache_compressed
+{
+ template <typename FloatFormat>
+ static BOOST_CHARCONV_CXX14_CONSTEXPR typename main_cache_holder::cache_entry_type get_cache(int k) noexcept
+ {
+ BOOST_CHARCONV_ASSERT(k >= main_cache_holder::min_k && k <= main_cache_holder::max_k);
+
+ BOOST_IF_CONSTEXPR (std::is_same<FloatFormat, ieee754_binary64>::value)
+ {
+ // Compute the base index.
+ const auto cache_index =
+ static_cast<int>(static_cast<std::uint32_t>(k - main_cache_holder::min_k) /
+ compressed_cache_detail::compression_ratio);
+
+ const auto kb = cache_index * compressed_cache_detail::compression_ratio +
+ main_cache_holder::min_k;
+
+ const auto offset = k - kb;
+
+ // Get the base cache.
+ const auto base_cache = compressed_cache_detail::cache_holder_t::table[cache_index];
+
+ if (offset == 0)
+ {
+ return base_cache;
+ }
+ else
+ {
+
+ // Compute the required amount of bit-shift.
+ const auto alpha = log::floor_log2_pow10(kb + offset) - log::floor_log2_pow10(kb) - offset;
+ BOOST_CHARCONV_ASSERT(alpha > 0 && alpha < 64);
+
+ // Try to recover the real cache.
+ const auto pow5 = compressed_cache_detail::pow5_holder_t::table[offset];
+ auto recovered_cache = umul128(base_cache.high, pow5);
+ const auto middle_low = umul128(base_cache.low, pow5);
+
+ recovered_cache += middle_low.high;
+
+ const auto high_to_middle = recovered_cache.high << (64 - alpha);
+ const auto middle_to_low = recovered_cache.low << (64 - alpha);
+
+ recovered_cache = uint128{(recovered_cache.low >> alpha) | high_to_middle, ((middle_low.low >> alpha) | middle_to_low)};
+
+ BOOST_CHARCONV_ASSERT(recovered_cache.low + 1 != 0);
+ recovered_cache = uint128(recovered_cache.high, recovered_cache.low + 1);
+
+ return recovered_cache;
+ }
+ }
+ else
+ {
+ // Just use the full cache for anything other than binary64
+ return main_cache_holder::cache[std::size_t(k - main_cache_holder::min_k)];
+ }
+ }
+};
+
+template <bool b>
+struct extended_cache_long_impl
+{
+ static constexpr std::size_t max_cache_blocks = 3;
+ static constexpr std::size_t cache_bits_unit = 64;
+ static constexpr int segment_length = 22;
+ static constexpr bool constant_block_count = true;
+ static constexpr int e_min = -1074;
+ static constexpr int k_min = -272;
+ static constexpr int cache_bit_index_offset_base = 977;
+ static constexpr std::uint64_t cache[] = {
+ 0xa37fce126597973c, 0xe50ff107bab528a0, 0x8f1ba3f17395a391, 0xd56bdc876cdb4648,
+ 0x6ca000bdd9e33bd4, 0x23cf34bbf983f78b, 0x8737d87296e93f5d, 0xa2824ba6d9df301d,
+ 0x8ce3eccf7cfb42ab, 0xe5ecdc0b78109f00, 0xa620c9995c9c5c3a, 0xa0f79c97ac210943,
+ 0x64dfb5636985915f, 0xc12f542e4c7ea6ee, 0x34de81232784ea17, 0xd0cbde7fac4643f2,
+ 0x5d9400de8fef7552, 0x81214f68696d9af2, 0xb7d0e0a2ccaccf20, 0x5c4ed9243f16193d,
+ 0xf71838486e60b926, 0x48892047ec1a8bf4, 0x14ff2faa9c32befa, 0x666fbaa24ddbb8e9,
+ 0x436682c807652a58, 0xed98ddaee19068c7, 0x63badd624dd9b095, 0x72dbb637d5b77493,
+ 0xd01998fb8d9e8861, 0xacb39418dce017b9, 0x8db8f2f13eed81cf, 0xfd699fbb7d0a737a,
+ 0x011cd67160923d91, 0x9a66fd7732c14d98, 0x235857d065a52d18, 0x895288951dab0d8e,
+ 0x59041cb66e4f0e68, 0x5e7c68240249e750, 0x8881a2a6ab00987b, 0x5fc8c32c863aaeac,
+ 0x3bafbe662a7f81a8, 0xd47692705ae76b64, 0xeb1cc7d99143fb53, 0xcf8be24f7b0fc499,
+ 0x6a276e8f0fbf33eb, 0x63b2d61966fa7243, 0x0970327d2cc58011, 0x43ff09410ec24aae,
+ 0x0bdb6f345ea1851d, 0x409c37132c5836ff, 0xf3150f74a6190324, 0x5c358d6c07453d23,
+ 0x7207012ad7846ba7, 0x61ad5d0772604733, 0x19a20a6e21c2018d, 0x5f568fd497ef18b2,
+ 0xeda5815eed00749f, 0x029531461bc483d8, 0xb8789d7784875911, 0x6fc40572236f2ba5,
+ 0x9c2a50a76ace3168, 0xbf4815c2bea56741, 0xf84e8f2fe9b211f5, 0x689033182d2ea7ed,
+ 0x5bcb3a3230a68f47, 0xa848403d116805ef, 0xfaeaa73623b79604, 0x31d76828d2181b64,
+ 0x7c4eabddc7dd634b, 0xc2b13231eeff6fda, 0x8094743db32bf251, 0x2df07391bde052d2,
+ 0xffd9bdbf321ad8ae, 0x06b2c6d1cf6cf742, 0xf32a54ce1598fe8f, 0x1cc2e3082d28897e,
+ 0x0485f2e46b488584, 0xe3f6965b145a49cb, 0x406eaa1217aefe69, 0x0777373638de456b,
+ 0xcde91853b592212b, 0x3faf7b46d7f79c18, 0x558d83afb7127381, 0x5f490259c7957aeb,
+ 0x76e6540e246d73cc, 0x5098a935a866dc75, 0xc50d9c29002d9e73, 0xcc8f8252faac0b7f,
+ 0xb759afb688f8251d, 0x6a2934d3036c85d3, 0x570eb3ce4c86407f, 0x036f2b68794754af,
+ 0x57661a5d6993fe2c, 0x6d07b7fabe546a80, 0x38efe4029259743c, 0x548f417ebaa61c6c,
+ 0xb0c31fa64a3fcc9e, 0x7dab825964fb7100, 0xd0c92ae8207d6f22, 0xf1e38a8a9c541144,
+ 0x2139951c68d0385b, 0x9d9e22c42f139287, 0x4fea4d670876b800, 0x35f293a9a62252d4,
+ 0x4b606b26f1922c5c, 0x8e5660b37505cb11, 0x868138391855da81, 0x6e95f6c9b45c7aa2,
+ 0x425ff75e14fc31a1, 0x258379a94d028d18, 0xdf2ccd1fe00a03b6, 0x398471c1ff970f83,
+ 0x8c36b2214a3db8e7, 0x431dd42c3fe7f4fb, 0xb09bcf0fffb5b849, 0xc47dd13da60fb5a1,
+ 0x8fdad56516fe9d75, 0xc317e1025a7e1c63, 0x9ddcb98cbb384fda, 0x80adccda993bf70e,
+ 0x667f1622e4052ae4, 0xa41598d58f777363, 0x704b93d675808501, 0xaf046d3fd448aaf3,
+ 0x1dc4611873bf3f70, 0x834acdae9f0f4f53, 0x4f5d60585a5f1c1a, 0x3ced1b4be0d415c1,
+ 0x5d57f4de8ec12376, 0x51c0e7e72f799542, 0x46f7604940e6a510, 0x1a546a0f9345ed75,
+ 0x0df4097cab773ca2, 0x72b122774e4029e6, 0xae4a55b99aebd424, 0x04163a291bad2fa3,
+ 0x86ad58be322a49aa, 0x98f051614696e839, 0x64d08f241fc4ec58, 0xae41f23dca90dd5d,
+ 0x68bbd62f5af3107a, 0x7025f39ef241c56c, 0xd2e7c72fa9be33ac, 0x0aece66fd3e29a7d,
+ 0xd91241cebf3bd47c, 0x3ed7bfdee19ba2f6, 0x4bdf483194c7444e, 0xc99d83c931e8ab87,
+ 0x1732f416dbf7381f, 0x2ac88e244de13b96, 0x2cab688bd86c8bf8, 0x9f209787bb47d6b8,
+ 0x4c0678c5dbd23a49, 0xa0612c3c5ce15e55, 0x4dccc6ca29b3e9df, 0x0dc079c918022212,
+ 0x26be55a64c249495, 0x4da2c9789dd268b0, 0xe975528c76435158, 0xa6cb8a4d2356f9cf,
+ 0xdcafd2279c77d987, 0xaa9aff7904228690, 0xfb44d2f05d0842fb, 0x118fc9c217a1d2b2,
+ 0x04b3d9686f55b572, 0xbd9cb3625ef1cfc3, 0x2eba0e25e938e6c3, 0x1f48eaf234ad3a21,
+ 0xf2dc02fad2890f79, 0xace340325d4a7f9b, 0xe9e051f540b239dc, 0x221091f05abb8687,
+ 0x7e08deb014db8afe, 0x4711e1e9d9a094cc, 0x0b2d79bd90a9ef61, 0xb93d19bd45b82515,
+ 0x45e9e31d63c1afe1, 0x2c5f0a596005c216, 0xe687cc2331b14a12, 0x51963a2412b6f60c,
+ 0x91aeb77c8fe68eaa, 0xd6e18e8cc6841d68, 0x9391085cc2c933d9, 0x6e184be07e68df49,
+ 0x4fe4e52edb0dce60, 0x6cda31e8617f0ca2, 0xf8b9374fda7e7c95, 0x8032c603725e774d,
+ 0x222b6aa27e007612, 0xf7b7f47cf096afad, 0xe6a9fbafee77e77a, 0x3776ee406e63fbaa,
+ 0xde147932fcf78be6, 0x2ab9e031ffaa071e, 0x2169ad0e8a9b1256, 0xe33358135938b76a,
+ 0xcaec07e7a5373835, 0xef2863090a97c3ec, 0x6ccfb95f69c3adcc, 0x173e00da427cee4b,
+ 0x20f4ed58fcfb3040, 0x16f6fb326a60c32c, 0x2968fa04270ed545, 0x70673adfac0eabc4,
+ 0x6ff3c9364ff4e873, 0xde09ed35f13325d3, 0x2396e863b18c500f, 0xe22d253cc031e3ff,
+ 0x756d97a61247798d, 0xc9fc8d937e43c880, 0x0759ba59c08e14c7, 0xcd7aad86a4a45810,
+ 0x9f91c21c571dbe84, 0xd52d936f44abe8a3, 0xd5b48c100959d9d0, 0xb6cc856b3adc93b6,
+ 0x7aea8f8e067d2c8d, 0x04bc177f7b4287a6, 0xe3fcda36fa3b3342, 0xeaeb442e15d45095,
+ 0x2f4dd1ca5e89b18b, 0x602368385bb19cb1, 0x4bdfc434d3028181, 0x0b5a92cb80ac8150,
+ 0xb95953a97b1578ab, 0x46e6a18b01781b92, 0xdfd31585f38d7433, 0x0b1084b96009370b,
+ 0x9a81808e52462ba3, 0xff83368ace4af235, 0xb4e5d8a647e05e95, 0xf848cfc90df4b231,
+ 0x9919c68cf3576038, 0x1e89dad8a6790435, 0x7ac9361379139511, 0x7b5f9b6b937a7760,
+ 0x6e42e395fde0c1f7, 0x430cef1679799f8f, 0x0ad21cc1b4828074, 0x8982577d0ea42349,
+ 0xb1aca6185a7d0d0d, 0x4085c6db106c3d74, 0xba6f7a86e728a418, 0x0325a28758a974d2,
+ 0x57ea317f731817ed, 0xbd1e8e00b215a6eb, 0xb39f323742948e87, 0x9f9b0f873784cef4,
+ 0xa8c83d26585c5377, 0x837ba337bfcf893c, 0x0a7eeca62a23b805, 0xba4925a9e7f7346f,
+ 0xa574eebb90c8da6d, 0x5db7ff0e8d0b8d2d, 0x1562834c52c048d8, 0x0b2e577a853bcafc,
+ 0xdecef97a3524ff97, 0xeec053c8fd537066, 0xeaf2b1df83d600e4, 0x5be8b9ab7717eccf,
+ 0x05905b91ecbba038, 0xabacba5b373029ed, 0x22fb2283c0ee1267, 0x9c32b2ec3634c580,
+ 0x5186c586b6e5611c, 0x71eb0de5e91bb0a0, 0x89e969b42975ef08, 0x2ba0958bc44e322f,
+ 0x626d033cb828ba7d, 0xe5fbb65c7776509d, 0xb1403ae51ae9bc82, 0x5d773f0d9753a966,
+ 0x4a06feadd4ec8585, 0xda58a710fccd7b76, 0x6061ba4cd3d80d59, 0xf4824f5cfa2ba71c,
+ 0xfce622bba0ece756, 0x7d9c738486bc6842, 0x5f629d33c99db969, 0x855ff7c9b79362e6,
+ 0x892188a87c7de231, 0x85fea7caf30e2b5e, 0xbefeb221543782c5, 0x769ca33d280842f6,
+ 0x3974ebaf71353e52, 0xed0577283980f0cb, 0x7c37d689ab6b0662, 0x5037aeffcd3db52d,
+ 0x11bb0a5f64fbdcb5, 0xf5fd5aa5f2b7e974, 0xe1aa07ba7074367b, 0x4b5c14aa1c6a0d28,
+ 0xe9fc8c9c36f73953, 0x2609ad2cd0f99b76, 0x8d4f1d6bb589844f, 0xde09f066714fa909,
+ 0xe004c5d7adad3747, 0xd5ac81a94dfdefe3, 0xfd3e0083658a13c2, 0xf5512f25dd6e39a7,
+ 0xeb7204042ffa181d, 0x046d9254242d06e3, 0x91a5ca94f8706fab, 0xf5c58cc57af63c98,
+ 0x04e7ff1e23474908, 0xe4a9bec5c5818324, 0x1edfb105cc3084dd, 0x82431ec76e72a87a,
+ 0xe0b215be32c51083, 0x0d9942e3b5245098, 0xa49f1aad5723fd7e, 0xad45edba25a4bde8,
+ 0x241f0adc0cd56771, 0xf09bf2de59df3274, 0x090db856bbc020f2, 0x6aa4efb2d2ecb9bb,
+ 0xc6be4224ba04c233, 0x557a1760bde90850, 0x23090117938cb921, 0xcbec34da23f3e9c2,
+ 0xdfe2d55daad85c54, 0xa7932be700067f48, 0xfb7874535e2d76a4, 0x5161ba088056e74f,
+ 0xc275a8435be6cdb2, 0x05fcb771cab5aa15, 0x7f18a4382c9565a8, 0x4244c2cb833d6710,
+ 0x884e2b7a4a3db4d0, 0x08ded459d3edf2c2, 0x1616df531fee90cd, 0x9531c65800a97aaa,
+ 0x881ba77ab7e5d63a, 0x606d27428df4edd3, 0x294063ed78e305c7, 0x7de2b12f8a8cceb5,
+ 0xe6b01cc54a494437, 0x0cdecbe5ac90907c, 0xb88496c657d3e644, 0xf3eecf996f9c6b13,
+ 0x24aad7949edcde03, 0x304ca88ebfeaa534, 0x7b68a7bd3ef1916b, 0x3cc307a784d9060c,
+ 0x5dca03f19b213efd, 0xa380539c235f80c3, 0xf39756fc01d75bd7, 0x39ac6c7281739adb,
+ 0x4b606dc4aa036fda, 0x97126cd02a23b97c, 0x98c1e6906230aead, 0xe12d0f696a6bbc36,
+ 0x657a202bb6a89a33, 0x6421a07bda47e13d, 0x8d9d21b3c6b1dbee, 0x1f110f3744f13e0d,
+ 0x04d86fccb6e77ee8, 0x8c92852d9c9c14b3, 0x56be3cef19b19446, 0x57ceef0e2ebcbcf7,
+ 0x230a9328be0144bf, 0x3c1949b98a92aebc, 0x7ed2db80a62003f2, 0x84e609d13c7594f4,
+ 0xf8e81b9a9f35b4e8, 0xc2982fde1a087e4b, 0x84b0713cb3b18147, 0x3582530578d1ff08,
+ 0x0e5b6538cd61fce4, 0x46867abf4b6e72bc, 0x4fe9652832325e89, 0x7d141d065654745f,
+ 0x9bd5c0479188a53d, 0x4ccd47925108c00b, 0xfd3f6c8d961d47e3, 0x9c5c18a96093d2ad,
+ 0xa7d91bf008a358c3, 0x3ea3e5629f977d55, 0x80f0fed6a5f06003, 0x21f390e377ee4d68,
+ 0x73ed055ec082526b, 0x28482600c10f6ce2, 0x2bff1aaf94c11fe9, 0xde29cb7a943801b8,
+ 0x045b0493dd35af0e, 0xaeae25ff7a431c16, 0x78c9d3348f5364b7, 0xf973d1af84bc2476,
+ 0x4d2303e11baf18f3, 0xacebdb3fe5efbc7b, 0xd274a5cf5be50678, 0x2d60c40fdf53ac67,
+ 0x109592b606139855, 0x612f472a9c09925f, 0x701a035ccd4e7ab0, 0xac881f0db121a709,
+ 0xe1ed47438368366d, 0xde2faff8eeb2810a, 0x8eb2188044342ef9, 0x0e3c1aa7b6851548,
+ 0x7ce94a6ba4fd843f, 0x0da503676ee5ebb2, 0xf3bc7bb2cb8669e8, 0xd4b9e44de392fe64,
+ 0x81e470ebf207fdea, 0xdd53b09d49a0e5b5, 0xf78e23167a350d5a, 0x706470fc2d84423b,
+ 0x816ee82b19a29476, 0x35a9d218ba7cd4a1, 0xf590f12fb09b3fe3, 0x5e574140b302f8b7,
+ 0x6cb237a2021f77c3, 0x30a29037231a861e, 0xff4bb07af553a606, 0x831412ee2690d92c,
+ 0xf6d2d725ef14ff67, 0x2f79f810928a40ff, 0x2857d91ea9b04f71, 0xd063066f0ed78f3c,
+ 0xbf4b8dbc8a34017d, 0x6230f319f8b1f9c4, 0x061b0e25d8899834, 0x4071de32ef7ff0bf,
+ 0xbc546a0793fcfcd3, 0xd5881f5d968cf898, 0x0e21c0674cdda190, 0x0000000000000000};
+
+ struct multiplier_index_info
+ {
+ std::uint16_t first_cache_bit_index;
+ std::uint16_t cache_bit_index_offset;
+ };
+
+ static constexpr multiplier_index_info multiplier_index_info_table[] = {
+ {0, 0}, {171, 244}, {419, 565}, {740, 959}, {1135, 1427},
+ {1604, 1969}, {2141, 2579}, {2750, 3261}, {3434, 4019}, {4191, 4849},
+ {5019, 5750}, {5924, 6728}, {6904, 7781}, {7922, 8872}, {8993, 10016},
+ {9026, 10122}, {9110, 10279}, {9245, 10487}, {9431, 10746}, {9668, 11056},
+ {9956, 11418}, {10296, 11831}, {10687, 12295}, {11129, 12810}, {11622, 13376},
+ {12166, 13993}, {12761, 14661}, {13407, 15380}, {14104, 16150}, {14852, 16902},
+ {15582, 17627}, {16285, 18332}, {16968, 19019}, {17633, 19683}, {18275, 20326},
+ {18896, 20947}, {19495, 21546}, {20072, 22122}, {20626, 22669}, {21151, 23202},
+ {21662, 23713}, {22151, 24202}, {22618, 24669}, {23063, 25114}, {23486, 25535},
+ {23885, 25936}, {24264, 26313}, {24619, 26670}, {24954, 27004}, {25266, 27316},
+ {25556, 27603}, {25821, 27870}, {26066, 28117}, {26291, 28340}, {26492, 28543},
+ {26673, 28723}, {26831, 28881}, {26967, 29018}, {27082, 29133}, {27175, 29225},
+ {27245, 29296}, {27294, 29344}, {27320, 29370}, {27324, 0}};
+};
+
+#if defined(BOOST_NO_CXX17_INLINE_VARIABLES) && (!defined(BOOST_MSVC) || BOOST_MSVC != 1900)
+
+template <bool b> constexpr std::size_t extended_cache_long_impl<b>::max_cache_blocks;
+template <bool b> constexpr std::size_t extended_cache_long_impl<b>::cache_bits_unit;
+template <bool b> constexpr int extended_cache_long_impl<b>::segment_length;
+template <bool b> constexpr bool extended_cache_long_impl<b>::constant_block_count;
+template <bool b> constexpr int extended_cache_long_impl<b>::e_min;
+template <bool b> constexpr int extended_cache_long_impl<b>::k_min;
+template <bool b> constexpr int extended_cache_long_impl<b>::cache_bit_index_offset_base;
+template <bool b> constexpr std::uint64_t extended_cache_long_impl<b>::cache[];
+template <bool b> constexpr typename extended_cache_long_impl<b>::multiplier_index_info extended_cache_long_impl<b>::multiplier_index_info_table[];
+
+#endif
+
+using extended_cache_long = extended_cache_long_impl<true>;
+
+struct extended_cache_compact
+{
+ static constexpr std::size_t max_cache_blocks = 6;
+ static constexpr std::size_t cache_bits_unit = 64;
+ static constexpr int segment_length = 80;
+ static constexpr bool constant_block_count = false;
+ static constexpr int collapse_factor = 64;
+ static constexpr int e_min = -1074;
+ static constexpr int k_min = -211;
+ static constexpr int cache_bit_index_offset_base = 967;
+ static constexpr int cache_block_count_offset_base = 27;
+
+ static constexpr std::uint64_t cache[] = {
+ 0x9faacf3df73609b1, 0x77b191618c54e9ac, 0xcbc0fe19cae9528c, 0x8164d034592c3d4e,
+ 0x04c42d46c9d7a229, 0x7ee39007a5bc8cc3, 0x5469cf7bb8b25e57, 0x2effce010198cb81,
+ 0x642eb5bc0d8169e0, 0x91356aed1f5cd514, 0xe1c8f30156868b8c, 0xd1201a2b857f5cc5,
+ 0x15c07ee55715eff8, 0x8530360cd386f94f, 0xeb706c10ea02c329, 0x3cb22680f921f59e,
+ 0x3231912d5bf60e61, 0x0e1fff697ed6c695, 0xa8bed97c2f3b63fc, 0xda96e93c07538a6d,
+ 0xc1c4e34ccd6fdbc5, 0x85c09fd1d0f79834, 0x485f3a5d03622bba, 0xe640b09cca5b9d50,
+ 0x19a80913a40927a9, 0x4d82d751a5cf886d, 0x325c9cd793b9977b, 0x4896c18501fb9e0c,
+ 0xa9993bfdf3ea7275, 0xcb7d257a3ee7c9d8, 0xcbf8fdb78849a5f9, 0x6de98520472bdd03,
+ 0x36efd14b69b311de, 0x694fa387dcf3e78f, 0xdccfbfc61d1662ef, 0xbe3a4d4104fb75a2,
+ 0x289ccaebae5c6d2d, 0x436915952987fa63, 0x830446728505ab75, 0x3ad8772923e4e0c0,
+ 0xca946600436f3894, 0x0faae7895e3885f0, 0xadf6b773b1ebf8e0, 0x52473dd5e8218647,
+ 0x5e6b5121ca3b747c, 0x217399923cd80bc0, 0x0a56ced144bb2f9f, 0xb856e82eea863c1f,
+ 0x5cdae42f9562104d, 0x3fa421962c8c4241, 0x63451ff73769a3d2, 0xb0895649e11affd6,
+ 0xe5dd7be415e5d3ef, 0x282a242e818f1668, 0xc8a86da5faf0b5cc, 0xf5176ecc7cbb19db,
+ 0x2a9a282e49b4da0e, 0x59e22f9ed2cb3a4b, 0xc010afa26505a7e7, 0xee47b3ab83a99c3e,
+ 0xc7eafae5fa385ec2, 0x3ec747e06293a148, 0x4b8a8260baf424a7, 0x63079a1ac7709a4e,
+ 0x7fd0cd567aa4a0fa, 0x6909d0e0cfc6ce8d, 0xe0c965770d1491dd, 0xa6d4449e3a3e13ea,
+ 0x73e06d2253c6b584, 0x9f95a4b69679998d, 0x0cc8cc76a8234060, 0xd3da311bb4fc0aae,
+ 0x670614382f45f33c, 0x21f68425f4189fbf, 0x557ce28d58d9a8bd, 0x1f16d908907d0a0e,
+ 0x929415f993b9a2c2, 0x95e0878748988052, 0xc4a104701f794a31, 0xe7d2d2b0c3c31b19,
+ 0x1e6a68d5574b3d9d, 0x5727ec70c7681154, 0xe4b2adae8ac5259e, 0x1cefff5ed639205f,
+ 0xf9410ba5daeb3af5, 0x21b0ad30acb4b8d2, 0xd324604028bf6fac, 0x349a5d2dc4bdc6e0,
+ 0xc77223714aff22d9, 0x5b18ce4aabb5b369, 0xb8a6d609b15ecab7, 0x2111dbce86023643,
+ 0x2a5717a571b96b6c, 0x8039783af28427bf, 0x5bbadd6a1a3fb931, 0xe8564a7a3e3ff2dc,
+ 0xd0868939e541158e, 0xc57d0b8a8af06dde, 0xf1706d329def96c1, 0xbe74f435713bb7d5,
+ 0x8dcdaef5bfb0242c, 0x73b5a1c8c8ec33c7, 0x4ab726d9dac95550, 0x210cf3b3ddfa00ae,
+ 0x559d5e65eefbfa04, 0xe5d1f67c5f9de0ec, 0x6ad4699ea2d0efd6, 0x9590c0f05024f29a,
+ 0x917d5715e6e20913, 0xb13124a40bffe5ba, 0x5248ce22e40406e5, 0xb844b16596551ded,
+ 0xad4c4c5140496c58, 0x458562ae335689b6, 0x269441e13a195ad3, 0x7a5e32a8baf53ea8,
+ 0x6d1469edb474b5f6, 0xe87b554829f6ee5b, 0xbf824a42bae3bdef, 0xed12ec6937744feb,
+ 0x2ca544e624e048f9, 0x1bab8d5ee0c61285, 0x8863eaef018d32d9, 0x98f37ac46669f7ea,
+ 0xa9a0573cb5501b2b, 0xf25c3a8e08a5694d, 0x42355a8000000000, 0x0000000000000000};
+
+ struct multiplier_index_info
+ {
+ std::uint16_t first_cache_bit_index;
+ std::uint16_t cache_bit_index_offset;
+ std::uint16_t cache_block_count_index_offset;
+ };
+
+ static constexpr multiplier_index_info multiplier_index_info_table[] = {
+ {0, 0, 0}, {377, 643, 9}, {1020, 1551, 22}, {1924, 2721, 39},
+ {3046, 4109, 60}, {3114, 4443, 70}, {3368, 4962, 84}, {3807, 5667, 98},
+ {4432, 6473, 111}, {5158, 7199, 123}, {5804, 7845, 134}, {6370, 8411, 143},
+ {6856, 8896, 151}, {7261, 9302, 158}, {7587, 9628, 164}, {7833, 9874, 168},
+ {7999, 10039, 171}, {8084, 10124, 173}, {8089, 0, 0}};
+
+ static constexpr std::uint8_t cache_block_counts[] = {
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x56, 0x34, 0x12, 0x66,
+ 0x66, 0x45, 0x23, 0x61, 0x66, 0x66, 0x66, 0x45, 0x23, 0x61, 0x66, 0x66, 0x66,
+ 0x56, 0x34, 0x12, 0x66, 0x66, 0x66, 0x56, 0x34, 0x12, 0x66, 0x66, 0x66, 0x45,
+ 0x23, 0x61, 0x66, 0x56, 0x34, 0x12, 0x66, 0x56, 0x34, 0x12, 0x66, 0x45, 0x23,
+ 0x61, 0x45, 0x23, 0x41, 0x23, 0x31, 0x12, 0x12, 0x01};
+};
+
+#ifdef BOOST_CXX17_INLINE_VARIABLES
+
+constexpr std::size_t extended_cache_compact::max_cache_blocks;
+constexpr std::size_t extended_cache_compact::cache_bits_unit;
+constexpr int extended_cache_compact::segment_length;
+constexpr bool extended_cache_compact::constant_block_count;
+constexpr int extended_cache_compact::collapse_factor;
+constexpr int extended_cache_compact::e_min;
+constexpr int extended_cache_compact::k_min;
+constexpr int extended_cache_compact::cache_bit_index_offset_base;
+constexpr int extended_cache_compact::cache_block_count_offset_base;
+constexpr extended_cache_compact::multiplier_index_info extended_cache_compact::multiplier_index_info_table[];
+constexpr std::uint8_t extended_cache_compact::cache_block_counts[];
+
+#endif
+
+struct extended_cache_super_compact
+{
+ static constexpr std::size_t max_cache_blocks = 15;
+ static constexpr std::size_t cache_bits_unit = 64;
+ static constexpr int segment_length = 252;
+ static constexpr bool constant_block_count = false;
+ static constexpr int collapse_factor = 128;
+ static constexpr int e_min = -1074;
+ static constexpr int k_min = -65;
+ static constexpr int cache_bit_index_offset_base = 1054;
+ static constexpr int cache_block_count_offset_base = 10;
+
+ static constexpr std::uint64_t cache[] = {
+ 0xf712b443bbd52b7b, 0xa5e9ec7501d523e4, 0x6f99ee8b281c132a, 0x1c7262e905287f33,
+ 0xbf4f71a69f411989, 0xe95fb0bf35d5c518, 0x00d875ffe81c1457, 0x31f0fcb03c200323,
+ 0x6f64d6af592895a0, 0x45c073ee14c78fb0, 0x8744404cbdba226c, 0x8dbe2386885f0c74,
+ 0x279b6693e94ab813, 0x6df0a4a86ccbb52e, 0xa94baea98e947129, 0xfc2b4e9bb4cbe9a4,
+ 0x73bbc273e753c4ad, 0xc70c8ff8c19c1059, 0xb7da754b6db8b578, 0x5214cf7f2274988c,
+ 0x39b5c4db3b36b321, 0xda6f355441d9f234, 0x01ab018d850bd7e2, 0x36517c3f140b3bcf,
+ 0xd0e52375d8d125a7, 0xaf9709f49f3b8404, 0x022dd12dd219aa3f, 0x46e2ecebe43f459e,
+ 0xa428ebddeecd6636, 0x3a7d11bff7e2a722, 0xd35d40e9d3b97c7d, 0x60ef65c4478901f1,
+ 0x945301feb0da841a, 0x2028c054ab187f51, 0xbe94b1f686a8b684, 0x09c13fdc1c4868c9,
+ 0xf2325ac2bf88a4ce, 0x92980d8fa53b6888, 0x8f6e17c7572a3359, 0x2964c5bfdd7761f2,
+ 0xf60269fc4910b562, 0x3ca164c4a2183ab0, 0x13f4f9e5a06a95c9, 0xf75022e39380598a,
+ 0x0d3f3c870002ab76, 0x24a4beb4780b78ef, 0x17a59a8f5696d625, 0x0ad76de884cb489d,
+ 0x559d3d0681553d6a, 0x813dcf205788af76, 0xf42f9c3ad707bf72, 0x770d63ceb129026c,
+ 0xa604d413fc14c7c2, 0x3cfc19e01239c784, 0xec7ef19965cedd56, 0x7303dcb3b300b6fd,
+ 0x118059e1139c0f3c, 0x97097186308c91f7, 0x2ad91d77379dce42, 0xad396c61acbe15ec,
+ 0x728518461b5722b6, 0xb85c5bb1ed805ecd, 0x816abc04592a4974, 0x1866b17c7cfbd0d0,
+ 0x0000000000000000};
+
+ struct multiplier_index_info
+ {
+ std::uint16_t first_cache_bit_index;
+ std::uint16_t cache_bit_index_offset;
+ std::uint16_t cache_block_count_index_offset;
+ };
+
+ static constexpr multiplier_index_info multiplier_index_info_table[] = {
+ {0, 0, 0}, {860, 1698, 13}, {2506, 4181, 29}, {2941, 5069, 36},
+ {3577, 5705, 41}, {3961, 6088, 44}, {4092, 0, 0}};
+
+ static constexpr std::uint8_t cache_block_counts[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xee,
+ 0xee, 0xee, 0xee, 0xee, 0xac, 0x68,
+ 0x24, 0x8a, 0x46, 0x62, 0x24, 0x13};
+};
+
+#ifdef BOOST_CXX17_INLINE_VARIABLES
+
+constexpr std::size_t extended_cache_super_compact::max_cache_blocks;
+constexpr std::size_t extended_cache_super_compact::cache_bits_unit;
+constexpr int extended_cache_super_compact::segment_length;
+constexpr bool extended_cache_super_compact::constant_block_count;
+constexpr int extended_cache_super_compact::collapse_factor;
+constexpr int extended_cache_super_compact::e_min;
+constexpr int extended_cache_super_compact::k_min;
+constexpr int extended_cache_super_compact::cache_bit_index_offset_base;
+constexpr int extended_cache_super_compact::cache_block_count_offset_base;
+constexpr std::uint64_t extended_cache_super_compact::cache[];
+constexpr extended_cache_super_compact::multiplier_index_info extended_cache_super_compact::multiplier_index_info_table[];
+constexpr std::uint8_t extended_cache_super_compact::cache_block_counts[];
+
+#endif
+
+#ifdef BOOST_MSVC
+# pragma warning(push)
+# pragma warning(disable: 4100) // MSVC 14.0 warning of unused formal parameter is incorrect
+#endif
+
+template <unsigned v1, unsigned v2, typename ExtendedCache>
+bool has_further_digits(std::uint64_t significand, int exp2_base, int& k, boost::charconv::detail::uconst<v1> additional_neg_exp_of_2_c, boost::charconv::detail::uconst<v2> additional_neg_exp_of_10_c) noexcept
+{
+ constexpr auto additional_neg_exp_of_2_v = static_cast<int>(decltype(additional_neg_exp_of_2_c)::value +
+ decltype(additional_neg_exp_of_10_c)::value);
+
+ constexpr auto additional_neg_exp_of_5_v = static_cast<int>(decltype(additional_neg_exp_of_10_c)::value);
+
+ constexpr auto min_neg_exp_of_5 = (-ExtendedCache::k_min + additional_neg_exp_of_5_v) % ExtendedCache::segment_length;
+
+ // k >= k_right_threshold iff k - k1 >= 0.
+ static_assert(additional_neg_exp_of_5_v + ExtendedCache::segment_length >= 1 + ExtendedCache::k_min,
+ "additional_neg_exp_of_5_v + ExtendedCache::segment_length >= 1 + ExtendedCache::k_min");
+
+ constexpr auto k_right_threshold = ExtendedCache::k_min +
+ ((additional_neg_exp_of_5_v + ExtendedCache::segment_length - 1 -
+ ExtendedCache::k_min) /
+ ExtendedCache::segment_length) *
+ ExtendedCache::segment_length;
+
+ // When the smallest absolute value of negative exponent for 5 is too big,
+ // so whenever the exponent for 5 is negative, the result cannot be an
+ // integer.
+ BOOST_IF_CONSTEXPR (min_neg_exp_of_5 > 23)
+ {
+ return boost::charconv::detail::has_further_digits_impl::no_neg_k_can_be_integer<
+ k_right_threshold, additional_neg_exp_of_2_v>(k, exp2_base);
+ }
+ // When the smallest absolute value of negative exponent for 5 is big enough, so
+ // the only negative exponent for 5 that allows the result to be an integer is the
+ // smallest one.
+ else BOOST_IF_CONSTEXPR (min_neg_exp_of_5 + ExtendedCache::segment_length > 23)
+ {
+ // k < k_left_threshold iff k - k1 < -min_neg_exp_of_5.
+ static_assert(additional_neg_exp_of_5_v + ExtendedCache::segment_length >= min_neg_exp_of_5 + 1 + ExtendedCache::k_min,
+ "additional_neg_exp_of_5_v + ExtendedCache::segment_length >= min_neg_exp_of_5 + 1 + ExtendedCache::k_min");
+
+ constexpr auto k_left_threshold =
+ ExtendedCache::k_min +
+ ((additional_neg_exp_of_5_v - min_neg_exp_of_5 +
+ ExtendedCache::segment_length - 1 - ExtendedCache::k_min) /
+ ExtendedCache::segment_length) *
+ ExtendedCache::segment_length;
+
+ return boost::charconv::detail::has_further_digits_impl::only_one_neg_k_can_be_integer<
+ k_left_threshold, k_right_threshold, additional_neg_exp_of_2_v,
+ min_neg_exp_of_5>(k, exp2_base, significand);
+ }
+ // When the smallest absolute value of negative exponent for 5 is big enough, so
+ // the only negative exponents for 5 that allows the result to be an integer are the
+ // smallest one and the next smallest one.
+ else
+ {
+ static_assert(min_neg_exp_of_5 + 2 * ExtendedCache::segment_length > 23,
+ "min_neg_exp_of_5 + 2 * ExtendedCache::segment_length > 23");
+
+ constexpr auto k_left_threshold =
+ ExtendedCache::k_min +
+ ((additional_neg_exp_of_5_v - min_neg_exp_of_5 - 1 - ExtendedCache::k_min) /
+ ExtendedCache::segment_length) *
+ ExtendedCache::segment_length;
+
+ constexpr auto k_middle_threshold =
+ ExtendedCache::k_min +
+ ((additional_neg_exp_of_5_v - min_neg_exp_of_5 +
+ ExtendedCache::segment_length - 1 - ExtendedCache::k_min) /
+ ExtendedCache::segment_length) *
+ ExtendedCache::segment_length;
+
+ return boost::charconv::detail::has_further_digits_impl::only_two_neg_k_can_be_integer<
+ k_left_threshold, k_middle_threshold, k_right_threshold,
+ additional_neg_exp_of_2_v, min_neg_exp_of_5, ExtendedCache::segment_length>(
+ k, exp2_base, significand);
+ }
+}
+
+template <unsigned v1, unsigned v2, typename ExtendedCache>
+inline bool has_further_digits(std::uint64_t significand, int exp2_base, int& k)
+{
+ boost::charconv::detail::uconst<v1> additional_neg_exp_of_2_c;
+ boost::charconv::detail::uconst<v2> additional_neg_exp_of_10_c;
+
+ return has_further_digits<v1, v2, ExtendedCache>(significand, exp2_base, k, additional_neg_exp_of_2_c, additional_neg_exp_of_10_c);
+}
+
+template <unsigned additional_neg_exp_of_2, unsigned additional_neg_exp_of_10, typename ExtendedCache>
+bool compute_has_further_digits(unsigned remaining_subsegment_pairs, std::uint64_t significand, int exp2_base, int& k) noexcept
+{
+ #define BOOST_CHARCONV_252_HAS_FURTHER_DIGITS(n) \
+ case n: \
+ return has_further_digits<additional_neg_exp_of_2, additional_neg_exp_of_10 + (n - 1) * 18, ExtendedCache>(significand, exp2_base, k)
+ switch (remaining_subsegment_pairs) {
+ BOOST_CHARCONV_252_HAS_FURTHER_DIGITS(1);
+ BOOST_CHARCONV_252_HAS_FURTHER_DIGITS(2);
+ BOOST_CHARCONV_252_HAS_FURTHER_DIGITS(3);
+ BOOST_CHARCONV_252_HAS_FURTHER_DIGITS(4);
+ BOOST_CHARCONV_252_HAS_FURTHER_DIGITS(5);
+ BOOST_CHARCONV_252_HAS_FURTHER_DIGITS(6);
+ BOOST_CHARCONV_252_HAS_FURTHER_DIGITS(7);
+ BOOST_CHARCONV_252_HAS_FURTHER_DIGITS(8);
+ BOOST_CHARCONV_252_HAS_FURTHER_DIGITS(9);
+ BOOST_CHARCONV_252_HAS_FURTHER_DIGITS(10);
+ BOOST_CHARCONV_252_HAS_FURTHER_DIGITS(11);
+ BOOST_CHARCONV_252_HAS_FURTHER_DIGITS(12);
+ BOOST_CHARCONV_252_HAS_FURTHER_DIGITS(13);
+ BOOST_CHARCONV_252_HAS_FURTHER_DIGITS(14);
+
+ default:
+ BOOST_UNREACHABLE_RETURN(remaining_subsegment_pairs); // NOLINT
+ }
+ #undef BOOST_CHARCONV_252_HAS_FURTHER_DIGITS
+
+ BOOST_UNREACHABLE_RETURN(false); // NOLINT
+}
+
+#ifdef BOOST_MSVC
+# pragma warning(pop)
+#endif
+
+// Print 0.000...0 where precision is the number of 0's after the decimal dot.
+inline to_chars_result print_zero_fixed(char* buffer, std::size_t buffer_size, const int precision) noexcept
+{
+ // No trailing decimal dot.
+ if (precision == 0)
+ {
+ *buffer = '0';
+ return {buffer + 1, std::errc()};
+ }
+
+ if (buffer_size < static_cast<std::size_t>(precision) + 2U)
+ {
+ return {buffer + buffer_size, std::errc::value_too_large};
+ }
+
+ std::memcpy(buffer, "0.", 2); // NOLINT : Specifically not null-terminating
+ std::memset(buffer + 2, '0', static_cast<std::size_t>(precision)); // NOLINT : Specifically not null-terminating
+ return {buffer + 2 + precision, std::errc()};
+}
+
+// precision means the number of decimal significand digits minus 1.
+// Assumes round-to-nearest, tie-to-even rounding.
+template <typename MainCache = main_cache_full, typename ExtendedCache>
+BOOST_CHARCONV_SAFEBUFFERS to_chars_result floff(const double x, int precision, char* first, char* last,
+ boost::charconv::chars_format fmt) noexcept
+{
+ if (first >= last)
+ {
+ return {last, std::errc::value_too_large};
+ }
+
+ auto buffer_size = static_cast<std::size_t>(last - first);
+ auto buffer = first;
+
+ BOOST_CHARCONV_ASSERT(precision >= 0);
+ using namespace detail;
+
+ std::uint64_t br = default_float_traits<double>::float_to_carrier(x);
+ bool is_negative = ((br >> 63) != 0);
+ br <<= 1;
+ int e = static_cast<int>(br >> (ieee754_binary64::significand_bits + 1));
+ auto significand = (br & ((UINT64_C(1) << (ieee754_binary64::significand_bits + 1)) - 1)); // shifted by 1-bit.
+
+ if (is_negative)
+ {
+ *buffer = '-';
+ ++buffer;
+ --buffer_size;
+
+ if (buffer_size == 0)
+ {
+ return {buffer, std::errc::value_too_large};
+ }
+ }
+
+ // Infinities or NaN
+ if (e == ((UINT32_C(1) << ieee754_binary64::exponent_bits) - 1))
+ {
+ if (significand == 0)
+ {
+ constexpr std::size_t inf_chars = 3;
+
+ if (buffer_size < inf_chars)
+ {
+ return {last, std::errc::value_too_large};
+ }
+
+ std::memcpy(buffer, "inf", inf_chars); // NOLINT : Specifically not null-terminating
+ return {buffer + inf_chars, std::errc()};
+ }
+ else
+ {
+ // Significand values for NaN by type
+ // qNaN = 4503599627370496
+ // sNaN = 2251799813685248
+ //
+ if (significand == UINT64_C(4503599627370496))
+ {
+ if (!is_negative)
+ {
+ constexpr std::size_t nan_chars = 3;
+
+ if (buffer_size < nan_chars)
+ {
+ return {last, std::errc::value_too_large};
+ }
+
+ std::memcpy(buffer, "nan", nan_chars); // NOLINT : Specifically not null-terminating
+ return {buffer + nan_chars, std::errc()};
+ }
+ else
+ {
+ constexpr std::size_t neg_nan_chars = 8;
+
+ if (buffer_size < neg_nan_chars)
+ {
+ return {last, std::errc::value_too_large};
+ }
+
+ std::memcpy(buffer, "nan(ind)", neg_nan_chars); // NOLINT : Specifically not null-terminating
+ return {buffer + neg_nan_chars, std::errc()};
+ }
+ }
+ else
+ {
+ constexpr std::size_t snan_chars = 9;
+
+ if (buffer_size < snan_chars)
+ {
+ return {last, std::errc::value_too_large};
+ }
+
+ std::memcpy(buffer, "nan(snan)", snan_chars); // NOLINT : Specifically not null-terminating
+ return {buffer + snan_chars, std::errc()};
+ }
+ }
+ }
+ else
+ {
+ // Normal numbers.
+ if (e != 0)
+ {
+ significand |= (decltype(significand)(1) << (ieee754_binary64::significand_bits + 1));
+ e += (ieee754_binary64::exponent_bias - ieee754_binary64::significand_bits);
+ }
+ // Subnormal numbers.
+ else
+ {
+ // Zero
+ if (significand == 0)
+ {
+ if (fmt == boost::charconv::chars_format::general)
+ {
+ // For the case of chars_format::general, 0 is always printed as 0.
+ *buffer = '0';
+ return {buffer + 1, std::errc()};
+ }
+ else if (fmt == boost::charconv::chars_format::fixed)
+ {
+ return print_zero_fixed(buffer, buffer_size, precision);
+ }
+ // For the case of chars_format::scientific, print as many 0's as requested after the decimal dot, and then print e+00.
+ if (precision == 0)
+ {
+ constexpr std::size_t zero_chars = 5;
+
+ if (buffer_size < zero_chars)
+ {
+ return {last, std::errc::value_too_large};
+ }
+
+ std::memcpy(buffer, "0e+00", zero_chars);
+ return {buffer + zero_chars, std::errc()};
+ }
+ else
+ {
+ if (buffer_size < static_cast<std::size_t>(precision) + 6U)
+ {
+ return {last, std::errc::value_too_large};
+ }
+
+ std::memcpy(buffer, "0.", 2); // NOLINT : Specifically not null-terminating
+ std::memset(buffer + 2, '0', static_cast<std::size_t>(precision)); // NOLINT : Specifically not null-terminating
+ std::memcpy(buffer + 2 + precision, "e+00", 4); // NOLINT : Specifically not null-terminating
+ return {buffer + precision + 6, std::errc()};
+ }
+ }
+ // Nonzero
+ e = ieee754_binary64::min_exponent - ieee754_binary64::significand_bits;
+ }
+ }
+
+ constexpr int kappa = 2;
+ int k = kappa - log::floor_log10_pow2(e);
+ std::uint32_t current_digits {};
+ char* const buffer_starting_pos = buffer;
+ char* decimal_dot_pos = buffer; // decimal_dot_pos == buffer_starting_pos indicates that there should be no decimal dot.
+ int decimal_exponent_normalized {};
+
+ // Number of digits to be printed.
+ int remaining_digits {};
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////
+ /// Phase 1 - Print the first digit segment computed with the Dragonbox table.
+ /////////////////////////////////////////////////////////////////////////////////////////////////
+
+ {
+ // Compute the first digit segment.
+ const auto main_cache = MainCache::template get_cache<ieee754_binary64>(k);
+ const int beta = e + log::floor_log2_pow10(k);
+
+ // Integer check is okay for binary64.
+ //auto [first_segment, has_more_segments]
+ compute_mul_result segments = [&] {
+ const auto r = umul192_upper128(significand << beta, main_cache);
+ return compute_mul_result{r.high, r.low == 0};
+ }();
+
+ auto first_segment = segments.result;
+ auto has_more_segments = !segments.is_integer;
+
+ // The first segment can be up to 19 digits. It is in fact always of either 18 or 19
+ // digits except when the input is a subnormal number. For subnormal numbers, the
+ // smallest possible value of the first segment is 10^kappa, so it is of at least
+ // kappa+1 digits (i.e., 3 in this case).
+
+ int first_segment_length = 19;
+ auto first_segment_aligned = first_segment; // Aligned to have 19 digits.
+ while (first_segment_aligned < UINT64_C(10000000000000000))
+ {
+ first_segment_aligned *= 100;
+ first_segment_length -= 2;
+ }
+ if (first_segment_aligned < UINT64_C(1000000000000000000))
+ {
+ first_segment_aligned *= 10;
+ first_segment_length -= 1;
+ }
+ // The decimal exponent when written as X.XXXX.... x 10^XX.
+ decimal_exponent_normalized = first_segment_length - k - 1;
+
+ // Figure out the correct value of remaining_digits.
+ if (fmt == boost::charconv::chars_format::scientific)
+ {
+ remaining_digits = precision + 1;
+ int exponent_print_length =
+ decimal_exponent_normalized >= 100 ? 5 :
+ decimal_exponent_normalized <= -100 ? 6 :
+ decimal_exponent_normalized >= 0 ? 4 : 5;
+
+ // No trailing decimal dot.
+ auto minimum_required_buffer_size =
+ static_cast<std::size_t>(remaining_digits + exponent_print_length + (precision != 0 ? 1 : 0));
+ if (buffer_size < minimum_required_buffer_size)
+ {
+ return {last, std::errc::value_too_large};
+ }
+
+ if (precision != 0)
+ {
+ // Reserve a place for the decimal dot.
+ *buffer = '0';
+ ++buffer;
+ ++decimal_dot_pos;
+ }
+ }
+ else if (fmt == boost::charconv::chars_format::fixed)
+ {
+ if (decimal_exponent_normalized >= 0)
+ {
+ remaining_digits = precision + decimal_exponent_normalized + 1;
+
+ // No trailing decimal dot.
+ auto minimum_required_buffer_size =
+ static_cast<std::size_t>(remaining_digits + (precision != 0 ? 1 : 0));
+
+ // We need one more space if the rounding changes the exponent,
+ // but since we don't know at this point if that will actually happen, handle such a case later.
+
+ if (buffer_size < minimum_required_buffer_size)
+ {
+ return {last, std::errc::value_too_large};
+ }
+
+ if (precision != 0)
+ {
+ // Reserve a place for the decimal dot.
+ *buffer = '0';
+ ++buffer;
+ decimal_dot_pos += decimal_exponent_normalized + 1;
+ }
+ }
+ else
+ {
+ int number_of_leading_zeros = -decimal_exponent_normalized - 1;
+
+ // When there are more than precision number of leading zeros,
+ // all the digits we need to print are 0.
+ if (number_of_leading_zeros > precision)
+ {
+ return print_zero_fixed(buffer, buffer_size, precision);
+ }
+ // When the number of leading zeros is exactly precision,
+ // then we might need to print 1 at the last digit due to rounding.
+ if (number_of_leading_zeros == precision)
+ {
+ // Since the last digit before rounding is 0,
+ // according to the "round-to-nearest, tie-to-even" rule, we round-up
+ // if and only if the input is strictly larger than the midpoint.
+ bool round_up = (first_segment_aligned + (has_more_segments ? 1 : 0)) > UINT64_C(5000000000000000000);
+ if (!round_up)
+ {
+ return print_zero_fixed(buffer, buffer_size, precision);
+ }
+
+ // No trailing decimal dot.
+ if (precision == 0)
+ {
+ *buffer = '1';
+ return {buffer + 1, std::errc()};
+ }
+
+ if (buffer_size < static_cast<std::size_t>(precision) + 2U)
+ {
+ return {buffer + buffer_size, std::errc::value_too_large};
+ }
+
+ std::memcpy(buffer, "0.", 2); // NOLINT : Specifically not null-terminating
+ std::memset(buffer + 2, '0', static_cast<std::size_t>(precision - 1)); // NOLINT : Specifically not null-terminating
+ buffer[1 + precision] = '1';
+ return {buffer + 2 + precision, std::errc()};
+ }
+
+ remaining_digits = precision - number_of_leading_zeros;
+
+ // Always have decimal dot.
+ BOOST_CHARCONV_ASSERT(precision > 0);
+ auto minimum_required_buffer_size = static_cast<std::size_t>(precision + 2);
+ if (buffer_size < minimum_required_buffer_size)
+ {
+ return {last, std::errc::value_too_large};
+ }
+
+ // Print leading zeros.
+ std::memset(buffer, '0', static_cast<std::size_t>(number_of_leading_zeros + 2));
+ buffer += number_of_leading_zeros + 2;
+ ++decimal_dot_pos;
+ }
+ }
+ else
+ {
+ // fmt == boost::charconv::chars_format::general
+ if (precision == 0)
+ {
+ // For general format, precision = 0 is interpreted as precision = 1.
+ precision = 1;
+ }
+ remaining_digits = precision;
+
+ // Use scientific format if decimal_exponent_normalized <= -6 or decimal_exponent_normalized >= precision.
+ // Use fixed format if -4 <= decimal_exponent_normalized <= precision - 2.
+ // If decimal_exponent_normalized == -5, use fixed format if and only if the rounding increases the exponent.
+ // If decimal_exponent_normalized == precision - 1, use scientific format if and only if the rounding increases the exponent.
+ // Since we cannot reliably decide which format to use, necessary corrections will be made in the last phase.
+
+ // We may end up not printing the decimal dot if fixed format is chosen, but reserve a place anyway.
+ *buffer = '0';
+ ++buffer;
+ decimal_dot_pos += (0 < decimal_exponent_normalized && decimal_exponent_normalized < precision)
+ ? decimal_exponent_normalized + 1 : 1;
+ }
+
+ if (remaining_digits <= 2)
+ {
+ uint128 prod;
+ std::uint64_t fractional_part64;
+ std::uint64_t fractional_part_rounding_threshold64;
+
+ // Convert to fixed-point form with 64/32-bit boundary for the fractional part.
+
+ if (remaining_digits == 1)
+ {
+ prod = umul128(first_segment_aligned, UINT64_C(1329227995784915873));
+ // ceil(2^63 + 2^64/10^18)
+ fractional_part_rounding_threshold64 = additional_static_data_holder::fractional_part_rounding_thresholds64[17];
+ }
+ else
+ {
+ prod = umul128(first_segment_aligned, UINT64_C(13292279957849158730));
+ // ceil(2^63 + 2^64/10^17)
+ fractional_part_rounding_threshold64 = additional_static_data_holder::
+ fractional_part_rounding_thresholds64[16];
+ }
+ fractional_part64 = (prod.low >> 56) | (prod.high << 8);
+ current_digits = static_cast<std::uint32_t>(prod.high >> 56);
+
+ // Perform rounding, print the digit, and return.
+ if (remaining_digits == 1)
+ {
+ if (fractional_part64 >= fractional_part_rounding_threshold64 ||
+ ((fractional_part64 >> 63) & (has_more_segments | (current_digits & 1))) != 0)
+ {
+ goto round_up_one_digit;
+ }
+
+ print_1_digit(current_digits, buffer);
+ ++buffer;
+ }
+ else
+ {
+ if (fractional_part64 >= fractional_part_rounding_threshold64 ||
+ ((fractional_part64 >> 63) & (has_more_segments | (current_digits & 1))) != 0)
+ {
+ goto round_up_two_digits;
+ }
+
+ print_2_digits(current_digits, buffer);
+ buffer += 2;
+ }
+
+ goto insert_decimal_dot;
+ } // remaining_digits <= 2
+
+ // At this point, there are at least 3 digits to print.
+ // We split the segment into three chunks, each consisting of 9 digits, 8 digits,
+ // and 2 digits.
+
+ // MSVC doesn't know how to do Grandlund-Montgomery for large 64-bit integers.
+ // 7922816251426433760 = ceil(2^96/10^10) = floor(2^96*(10^9/(10^19 - 1)))
+ const auto first_subsegment =
+ static_cast<std::uint32_t>(umul128_upper64(first_segment, UINT64_C(7922816251426433760)) >> 32);
+
+ const auto second_third_subsegments =
+ first_segment - first_subsegment * UINT64_C(10000000000);
+
+ BOOST_CHARCONV_ASSERT(first_subsegment < UINT64_C(1000000000));
+ BOOST_CHARCONV_ASSERT(second_third_subsegments < UINT64_C(10000000000));
+
+ int remaining_digits_in_the_current_subsegment;
+ std::uint64_t prod; // holds intermediate values for digit generation.
+
+ // Print the first subsegment.
+ if (first_subsegment != 0)
+ {
+ // 9 digits (19 digits in total).
+ if (first_subsegment >= 100000000)
+ {
+ // 1441151882 = ceil(2^57 / 10^8) + 1
+ prod = first_subsegment * UINT64_C(1441151882);
+ prod >>= 25;
+ remaining_digits_in_the_current_subsegment = 8;
+ }
+ // 7 or 8 digits (17 or 18 digits in total).
+ else if (first_subsegment >= 1000000)
+ {
+ // 281474978 = ceil(2^48 / 10^6) + 1
+ prod = first_subsegment * UINT64_C(281474978);
+ prod >>= 16;
+ remaining_digits_in_the_current_subsegment = 6;
+ }
+ // 5 or 6 digits (15 or 16 digits in total).
+ else if (first_subsegment >= 10000)
+ {
+ // 429497 = ceil(2^32 / 10^4)
+ prod = first_subsegment * UINT64_C(429497);
+ remaining_digits_in_the_current_subsegment = 4;
+ }
+ // 3 or 4 digits (13 or 14 digits in total).
+ else if (first_subsegment >= 100)
+ {
+ // 42949673 = ceil(2^32 / 10^2)
+ prod = first_subsegment * UINT64_C(42949673);
+ remaining_digits_in_the_current_subsegment = 2;
+ }
+ // 1 or 2 digits (11 or 12 digits in total).
+ else
+ {
+ prod = std::uint64_t(first_subsegment) << 32;
+ remaining_digits_in_the_current_subsegment = 0;
+ }
+
+ const auto initial_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ buffer -= (initial_digits < 10 && buffer != first ? 1 : 0);
+ remaining_digits -= (2 - (initial_digits < 10 ? 1 : 0));
+
+ // Avoid the situation where we have a leading 0 that we don't need
+ // Typically used to account for inserting a decimal, but we know
+ // we won't need that in the 0 precision case
+ if (precision == 0 && initial_digits < 10)
+ {
+ print_1_digit(initial_digits, buffer);
+ ++buffer;
+ }
+ else
+ {
+ print_2_digits(initial_digits, buffer);
+ buffer += 2;
+ }
+
+ if (remaining_digits > remaining_digits_in_the_current_subsegment)
+ {
+ remaining_digits -= remaining_digits_in_the_current_subsegment;
+
+ for (; remaining_digits_in_the_current_subsegment > 0; remaining_digits_in_the_current_subsegment -= 2)
+ {
+ // Write next two digits.
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+ buffer += 2;
+ }
+ }
+ else
+ {
+ for (int i = 0; i < (remaining_digits - 1) / 2; ++i)
+ {
+ // Write next two digits.
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+ buffer += 2;
+ }
+
+ // Distinguish two cases of rounding.
+ if (remaining_digits_in_the_current_subsegment > remaining_digits)
+ {
+ if ((remaining_digits & 1) != 0)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
+ }
+ else
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ }
+
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (check_rounding_condition_inside_subsegment(
+ current_digits, static_cast<std::uint32_t>(prod),
+ remaining_digits_in_the_current_subsegment - remaining_digits,
+ second_third_subsegments != 0 || has_more_segments))
+ {
+ goto round_up;
+ }
+
+ goto print_last_digits;
+ }
+ else
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
+ current_digits,
+ uint_with_known_number_of_digits<10>{second_third_subsegments},
+ has_more_segments))
+ {
+ goto round_up_two_digits;
+ }
+
+ goto print_last_two_digits;
+ }
+ }
+ }
+
+ // Print the second subsegment.
+ // The second subsegment cannot be zero even for subnormal numbers.
+
+ if (remaining_digits <= 2)
+ {
+ // In this case the first subsegment must be nonzero.
+
+ if (remaining_digits == 1)
+ {
+ const auto prod128 = umul128(second_third_subsegments, UINT64_C(18446744074));
+
+ current_digits = static_cast<std::uint32_t>(prod128.high);
+ const auto fractional_part64 = prod128.low + 1;
+ // 18446744074 is even, so prod.low cannot be equal to 2^64 - 1.
+ BOOST_CHARCONV_ASSERT(fractional_part64 != 0);
+
+ if (fractional_part64 >= additional_static_data_holder::fractional_part_rounding_thresholds64[8] ||
+ ((fractional_part64 >> 63) & (has_more_segments | (current_digits & 1))) != 0)
+ {
+ goto round_up_one_digit;
+ }
+
+ goto print_last_one_digit;
+ } // remaining_digits == 1
+ else
+ {
+ const auto prod128 = umul128(second_third_subsegments, UINT64_C(184467440738));
+
+ current_digits = static_cast<std::uint32_t>(prod128.high);
+ const auto fractional_part64 = prod128.low + 1;
+ // 184467440738 is even, so prod.low cannot be equal to 2^64 - 1.
+ BOOST_CHARCONV_ASSERT(fractional_part64 != 0);
+
+ if (fractional_part64 >= additional_static_data_holder::fractional_part_rounding_thresholds64[7] ||
+ ((fractional_part64 >> 63) & (has_more_segments | (current_digits & 1))) != 0)
+ {
+ goto round_up_two_digits;
+ }
+
+ goto print_last_two_digits;
+ }
+ } // remaining_digits <= 2
+
+ // Compilers are not aware of how to leverage the maximum value of
+ // second_third_subsegments to find out a better magic number which allows us to
+ // eliminate an additional shift.
+ // 184467440737095517 = ceil(2^64/100) < floor(2^64*(10^8/(10^10 - 1))).
+ const auto second_subsegment = static_cast<std::uint32_t>(
+ umul128_upper64(second_third_subsegments, UINT64_C(184467440737095517)));
+
+ // Since the final result is of 2 digits, we can do the computation in 32-bits.
+ const auto third_subsegment =
+ static_cast<std::uint32_t>(second_third_subsegments) - second_subsegment * 100;
+
+ BOOST_CHARCONV_ASSERT(second_subsegment < 100000000);
+ BOOST_CHARCONV_ASSERT(third_subsegment < 100);
+
+ {
+ std::uint32_t initial_digits;
+ if (first_subsegment != 0)
+ {
+ prod = ((second_subsegment * UINT64_C(281474977)) >> 16) + 1;
+ remaining_digits_in_the_current_subsegment = 6;
+
+ initial_digits = static_cast<std::uint32_t>(prod >> 32);
+ remaining_digits -= 2;
+ }
+ else
+ {
+ // 7 or 8 digits (9 or 10 digits in total).
+ if (second_subsegment >= 1000000)
+ {
+ prod = (second_subsegment * UINT64_C(281474978)) >> 16;
+ remaining_digits_in_the_current_subsegment = 6;
+ }
+ // 5 or 6 digits (7 or 8 digits in total).
+ else if (second_subsegment >= 10000)
+ {
+ prod = second_subsegment * UINT64_C(429497);
+ remaining_digits_in_the_current_subsegment = 4;
+ }
+ // 3 or 4 digits (5 or 6 digits in total).
+ else if (second_subsegment >= 100)
+ {
+ prod = second_subsegment * UINT64_C(42949673);
+ remaining_digits_in_the_current_subsegment = 2;
+ }
+ // 1 or 2 digits (3 or 4 digits in total).
+ else
+ {
+ prod = std::uint64_t(second_subsegment) << 32;
+ remaining_digits_in_the_current_subsegment = 0;
+ }
+
+ initial_digits = static_cast<std::uint32_t>(prod >> 32);
+ buffer -= (initial_digits < 10 ? 1 : 0);
+ remaining_digits -= (2 - (initial_digits < 10 ? 1 : 0));
+ }
+
+ print_2_digits(initial_digits, buffer);
+ buffer += 2;
+
+ if (remaining_digits > remaining_digits_in_the_current_subsegment)
+ {
+ remaining_digits -= remaining_digits_in_the_current_subsegment;
+ for (; remaining_digits_in_the_current_subsegment > 0; remaining_digits_in_the_current_subsegment -= 2)
+ {
+ // Write next two digits.
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+ buffer += 2;
+ }
+ }
+ else
+ {
+ for (int i = 0; i < (remaining_digits - 1) / 2; ++i)
+ {
+ // Write next two digits.
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+ buffer += 2;
+ }
+
+ // Distinguish two cases of rounding.
+ if (remaining_digits_in_the_current_subsegment > remaining_digits)
+ {
+ if ((remaining_digits & 1) != 0)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
+ }
+ else
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ }
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (check_rounding_condition_inside_subsegment(
+ current_digits, static_cast<std::uint32_t>(prod),
+ remaining_digits_in_the_current_subsegment - remaining_digits,
+ third_subsegment != 0 || has_more_segments))
+ {
+ goto round_up;
+ }
+
+ goto print_last_digits;
+ }
+ else
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
+ current_digits,
+ uint_with_known_number_of_digits<2>{third_subsegment},
+ has_more_segments))
+ {
+ goto round_up_two_digits;
+ }
+
+ goto print_last_two_digits;
+ }
+ }
+ }
+
+ // Print the third subsegment.
+ {
+ if (remaining_digits > 2)
+ {
+ print_2_digits(third_subsegment, buffer);
+ buffer += 2;
+ remaining_digits -= 2;
+
+ // If there is no more segment, then fill remaining digits with 0's and return.
+ if (!has_more_segments)
+ {
+ goto fill_remaining_digits_with_0s;
+ }
+ }
+ else if (remaining_digits == 1)
+ {
+ prod = third_subsegment * UINT64_C(429496730);
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (check_rounding_condition_inside_subsegment(
+ current_digits, static_cast<std::uint32_t>(prod), 1, has_more_segments))
+ {
+ goto round_up_one_digit;
+ }
+
+ goto print_last_one_digit;
+ }
+ else
+ {
+ // remaining_digits == 2.
+ // If there is no more segment, then print the current two digits and return.
+ if (!has_more_segments)
+ {
+ print_2_digits(third_subsegment, buffer);
+ buffer += 2;
+ goto insert_decimal_dot;
+ }
+
+ // Otherwise, for performing the rounding, we have to wait until the next
+ // segment becomes available. This state can be detected afterward by
+ // inspecting if remaining_digits == 0.
+ remaining_digits = 0;
+ current_digits = third_subsegment;
+ }
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////
+ /// Phase 2 - Print further digit segments computed with the extended cache table.
+ /////////////////////////////////////////////////////////////////////////////////////////////////
+
+ {
+ auto multiplier_index =
+ static_cast<std::uint32_t>(k + ExtendedCache::segment_length - ExtendedCache::k_min) /
+ static_cast<std::uint32_t>(ExtendedCache::segment_length);
+
+ int digits_in_the_second_segment;
+ {
+ const auto new_k =
+ ExtendedCache::k_min + static_cast<int>(multiplier_index) * ExtendedCache::segment_length;
+ digits_in_the_second_segment = new_k - k;
+ k = new_k;
+ }
+
+ const auto exp2_base = e + boost::core::countr_zero(significand);
+
+ using cache_block_type = typename std::decay<decltype(ExtendedCache::cache[0])>::type;
+
+ cache_block_type blocks[ExtendedCache::max_cache_blocks];
+ cache_block_count_t<ExtendedCache::constant_block_count, ExtendedCache::max_cache_blocks> cache_block_count;
+
+ // Deal with the second segment. The second segment is special because it can have
+ // overlapping digits with the first segment. Note that we cannot just move the buffer
+ // pointer backward and print the whole segment from there, because it may contain
+ // leading zeros.
+ {
+ cache_block_count =
+ load_extended_cache<ExtendedCache, ExtendedCache::constant_block_count>(
+ blocks, e, k, multiplier_index);
+
+ // Compute nm mod 2^Q.
+ fixed_point_calculator<ExtendedCache::max_cache_blocks>::discard_upper(significand, blocks, cache_block_count);
+
+ BOOST_CHARCONV_IF_CONSTEXPR (ExtendedCache::segment_length == 22)
+ {
+ // No rounding, continue.
+ if (remaining_digits > digits_in_the_second_segment)
+ {
+ remaining_digits -= digits_in_the_second_segment;
+
+ if (digits_in_the_second_segment <= 2)
+ {
+ BOOST_CHARCONV_ASSERT(digits_in_the_second_segment != 0);
+
+ fixed_point_calculator<ExtendedCache::max_cache_blocks>::discard_upper(
+ power_of_10[19], blocks, cache_block_count);
+
+ auto subsegment =
+ fixed_point_calculator<ExtendedCache::max_cache_blocks>::
+ generate_and_discard_lower(power_of_10[3], blocks,
+ cache_block_count);
+
+ if (digits_in_the_second_segment == 1)
+ {
+ auto prod = subsegment * UINT64_C(429496730);
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
+ print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
+ ++buffer;
+ }
+ else
+ {
+ auto prod = subsegment * UINT64_C(42949673);
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+ buffer += 2;
+ }
+ } // digits_in_the_second_segment <= 2
+ else if (digits_in_the_second_segment <= 16)
+ {
+ BOOST_CHARCONV_ASSERT(22 - digits_in_the_second_segment <= 19);
+
+ fixed_point_calculator<ExtendedCache::max_cache_blocks>::discard_upper(
+ compute_power(UINT64_C(10), 22 - digits_in_the_second_segment),
+ blocks, cache_block_count);
+
+ // When there are at most 9 digits, we can store them in 32-bits.
+ if (digits_in_the_second_segment <= 9)
+ {
+ // The number of overlapping digits is in the range 13 ~ 19.
+ const auto subsegment =
+ fixed_point_calculator<ExtendedCache::max_cache_blocks>::
+ generate_and_discard_lower(power_of_10[9], blocks,
+ cache_block_count);
+
+ std::uint64_t prod;
+ if ((digits_in_the_second_segment & 1) != 0)
+ {
+ prod = ((subsegment * UINT64_C(720575941)) >> 24) + 1;
+ print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
+ ++buffer;
+ }
+ else
+ {
+ prod = ((subsegment * UINT64_C(450359963)) >> 20) + 1;
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+ buffer += 2;
+ }
+
+ for (; digits_in_the_second_segment > 2; digits_in_the_second_segment -= 2)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+ buffer += 2;
+ }
+ } // digits_in_the_second_segment <= 9
+ else
+ {
+ // The number of digits in the segment is in the range 10 ~ 16.
+ const auto first_second_subsegments =
+ fixed_point_calculator<ExtendedCache::max_cache_blocks>::
+ generate_and_discard_lower(power_of_10[16], blocks,
+ cache_block_count);
+
+ // The first segment is of 8 digits, and the second segment is of
+ // 2 ~ 8 digits.
+ // ceil(2^(64+14)/10^8) = 3022314549036573
+ // = floor(2^(64+14)*(10^8/(10^16 - 1)))
+ const auto first_subsegment =
+ static_cast<std::uint32_t>(umul128_upper64(first_second_subsegments,
+ UINT64_C(3022314549036573)) >>
+ 14);
+ const auto second_subsegment =
+ static_cast<std::uint32_t>(first_second_subsegments) -
+ UINT32_C(100000000) * first_subsegment;
+
+ // Print the first subsegment.
+ print_8_digits(first_subsegment, buffer);
+ buffer += 8;
+
+ // Print the second subsegment.
+ // There are at least 2 digits in the second subsegment.
+ auto prod = ((second_subsegment * UINT64_C(140737489)) >> 15) + 1;
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+ buffer += 2;
+ digits_in_the_second_segment -= 10;
+
+ for (; digits_in_the_second_segment > 1; digits_in_the_second_segment -= 2)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+ buffer += 2;
+ }
+
+ if (digits_in_the_second_segment != 0)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
+ print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
+ ++buffer;
+ }
+ }
+ } // digits_in_the_second_segment <= 16
+ else
+ {
+ // The number of digits in the segment is in the range 17 ~ 22.
+ const auto first_subsegment =
+ fixed_point_calculator<ExtendedCache::max_cache_blocks>::generate(
+ power_of_10[6], blocks, cache_block_count);
+
+ const auto second_third_subsegments =
+ fixed_point_calculator<ExtendedCache::max_cache_blocks>::
+ generate_and_discard_lower(power_of_10[16], blocks,
+ cache_block_count);
+
+ // ceil(2^(64+14)/10^8) = 3022314549036573
+ // = floor(2^(64+14)*(10^8/(10^16 - 1)))
+ const auto second_subsegment =
+ static_cast<std::uint32_t>(umul128_upper64(second_third_subsegments,
+ UINT64_C(3022314549036573)) >>
+ 14);
+ const auto third_subsegment = static_cast<std::uint32_t>(second_third_subsegments) -
+ UINT32_C(100000000) * second_subsegment;
+
+ // Print the first subsegment (1 ~ 6 digits).
+ std::uint64_t prod {};
+ auto remaining_digits_in_the_current_subsegment =
+ digits_in_the_second_segment - 16;
+
+ switch (remaining_digits_in_the_current_subsegment)
+ {
+ case 1:
+ prod = first_subsegment * UINT64_C(429496730);
+ goto second_segment22_more_than_16_digits_first_subsegment_no_rounding_odd_remaining;
+
+ case 2:
+ prod = first_subsegment * UINT64_C(42949673);
+ goto second_segment22_more_than_16_digits_first_subsegment_no_rounding_even_remaining;
+
+ case 3:
+ prod = first_subsegment * UINT64_C(4294968);
+ goto second_segment22_more_than_16_digits_first_subsegment_no_rounding_odd_remaining;
+
+ case 4:
+ prod = first_subsegment * UINT64_C(429497);
+ goto second_segment22_more_than_16_digits_first_subsegment_no_rounding_even_remaining;
+
+ case 5:
+ prod = ((first_subsegment * UINT64_C(687195)) >> 4) + 1;
+ goto second_segment22_more_than_16_digits_first_subsegment_no_rounding_odd_remaining;
+
+ case 6:
+ prod = first_subsegment * UINT64_C(429497);
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+ buffer += 2;
+ remaining_digits_in_the_current_subsegment = 4;
+ goto second_segment22_more_than_16_digits_first_subsegment_no_rounding_even_remaining;
+
+ default:
+ BOOST_UNREACHABLE_RETURN(prod); // NOLINT
+ }
+
+ second_segment22_more_than_16_digits_first_subsegment_no_rounding_odd_remaining
+ :
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
+ print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
+ ++buffer;
+
+ second_segment22_more_than_16_digits_first_subsegment_no_rounding_even_remaining
+ :
+ for (; remaining_digits_in_the_current_subsegment > 1;
+ remaining_digits_in_the_current_subsegment -= 2)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+ buffer += 2;
+ }
+
+ // Print the second and third subsegments (8 digits each).
+ print_8_digits(second_subsegment, buffer);
+ print_8_digits(third_subsegment, buffer + 8);
+ buffer += 16;
+ }
+ } // remaining_digits > digits_in_the_second_segment
+
+ // Perform rounding and return.
+ else
+ {
+ if (digits_in_the_second_segment <= 2)
+ {
+ fixed_point_calculator<ExtendedCache::max_cache_blocks>::discard_upper(
+ power_of_10[19], blocks, cache_block_count);
+
+ // Get one more bit for potential rounding on the segment boundary.
+ auto subsegment =
+ fixed_point_calculator<ExtendedCache::max_cache_blocks>::
+ generate_and_discard_lower(2000, blocks, cache_block_count);
+
+ bool segment_boundary_rounding_bit = ((subsegment & 1) != 0);
+ subsegment >>= 1;
+
+ if (digits_in_the_second_segment == 2)
+ {
+ // Convert subsegment into fixed-point fractional form where the
+ // integer part is of one digit. The integer part is ignored.
+ // 42949673 = ceil(2^32/10^2)
+ auto prod = static_cast<std::uint64_t>(subsegment) * UINT64_C(42949673);
+
+ if (remaining_digits == 1)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+ const bool has_further_digits_v = has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0);
+ if (check_rounding_condition_inside_subsegment(current_digits, static_cast<std::uint32_t>(prod), 1, has_further_digits_v))
+ {
+ goto round_up_one_digit;
+ }
+ goto print_last_one_digit;
+ }
+
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ const auto next_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (remaining_digits == 0)
+ {
+ if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
+ current_digits,
+ uint_with_known_number_of_digits<2>{next_digits},
+ has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0)))
+ {
+ goto round_up_two_digits;
+ }
+ goto print_last_two_digits;
+ }
+
+ current_digits = next_digits;
+ BOOST_CHARCONV_ASSERT(remaining_digits == 2);
+ }
+ else
+ {
+ BOOST_CHARCONV_ASSERT(digits_in_the_second_segment == 1);
+ // Convert subsegment into fixed-point fractional form where the
+ // integer part is of two digits. The integer part is ignored.
+ // 429496730 = ceil(2^32/10^1)
+ auto prod = static_cast<std::uint64_t>(subsegment) * UINT64_C(429496730);
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
+ const auto next_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (remaining_digits == 0)
+ {
+ if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
+ current_digits,
+ uint_with_known_number_of_digits<1>{next_digits},
+ has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0)))
+ {
+ goto round_up_two_digits;
+ }
+ goto print_last_two_digits;
+ }
+
+ current_digits = next_digits;
+ BOOST_CHARCONV_ASSERT(remaining_digits == 1);
+ }
+
+ if (check_rounding_condition_with_next_bit(
+ current_digits, segment_boundary_rounding_bit,
+ has_further_digits<0, 0, ExtendedCache>(significand, exp2_base, k, uconst0, uconst0)))
+ {
+ goto round_up;
+ }
+
+ goto print_last_digits;
+ } // digits_in_the_second_segment <= 2
+
+ // When there are at most 9 digits in the segment.
+ if (digits_in_the_second_segment <= 9)
+ {
+ // Throw away all overlapping digits.
+ BOOST_CHARCONV_ASSERT(22 - digits_in_the_second_segment <= 19);
+
+ fixed_point_calculator<ExtendedCache::max_cache_blocks>::discard_upper(
+ compute_power(UINT64_C(10), 22 - digits_in_the_second_segment),
+ blocks, cache_block_count);
+
+ // Get one more bit for potential rounding on the segment boundary.
+ auto segment = fixed_point_calculator<ExtendedCache::max_cache_blocks>::
+ generate_and_discard_lower(power_of_10[9] << 1, blocks,
+ cache_block_count);
+
+ std::uint64_t prod;
+ digits_in_the_second_segment -= remaining_digits;
+
+ if ((remaining_digits & 1) != 0)
+ {
+ prod = ((segment * UINT64_C(1441151881)) >> 26) + 1;
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (remaining_digits == 1)
+ {
+ goto second_segment22_at_most_9_digits_rounding;
+ }
+
+ print_1_digit(current_digits, buffer);
+ ++buffer;
+ }
+ else
+ {
+ prod = ((segment * UINT64_C(1801439851)) >> 23) + 1;
+ const auto next_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (remaining_digits == 0)
+ {
+ if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
+ current_digits,
+ uint_with_known_number_of_digits<2>{next_digits}, [&] {
+ return static_cast<std::uint32_t>(prod) >=
+ (additional_static_data_holder::
+ fractional_part_rounding_thresholds32[digits_in_the_second_segment - 3] & UINT32_C(0x7fffffff))
+ || has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0);
+ }))
+ {
+ goto round_up_two_digits;
+ }
+ goto print_last_two_digits;
+ }
+ else if (remaining_digits == 2)
+ {
+ current_digits = next_digits;
+ goto second_segment22_at_most_9_digits_rounding;
+ }
+
+ print_2_digits(next_digits, buffer);
+ buffer += 2;
+ }
+
+ BOOST_CHARCONV_ASSERT(remaining_digits >= 3);
+
+ for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+ buffer += 2;
+ }
+
+ if (digits_in_the_second_segment != 0)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+ remaining_digits = 0;
+
+ second_segment22_at_most_9_digits_rounding:
+ if (check_rounding_condition_inside_subsegment(
+ current_digits, static_cast<std::uint32_t>(prod),
+ digits_in_the_second_segment, has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1,
+ uconst0)))
+ {
+ goto round_up;
+ }
+
+ goto print_last_digits;
+ }
+ else
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(200);
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+ const auto segment_boundary_rounding_bit = (current_digits & 1) != 0;
+ current_digits >>= 1;
+
+ if (check_rounding_condition_with_next_bit(
+ current_digits, segment_boundary_rounding_bit,
+ has_further_digits<0, 1, ExtendedCache>(significand, exp2_base, k, uconst0, uconst1)))
+ {
+ goto round_up_two_digits;
+ }
+ goto print_last_two_digits;
+ }
+ } // digits_in_the_second_segment <= 9
+
+ // first_second_subsegments is of 1 ~ 13 digits, and third_subsegment is
+ // of 9 digits.
+ // Get one more bit for potential rounding condition check.
+ auto first_second_subsegments =
+ fixed_point_calculator<ExtendedCache::max_cache_blocks>::generate(
+ power_of_10[13] << 1, blocks, cache_block_count);
+
+ bool first_bit_of_third_subsegment = ((first_second_subsegments & 1) != 0);
+ first_second_subsegments >>= 1;
+
+ // Compilers are not aware of how to leverage the maximum value of
+ // first_second_subsegments to find out a better magic number which
+ // allows us to eliminate an additional shift.
+ // 1844674407371 = ceil(2^64/10^7) = floor(2^64*(10^6/(10^13 - 1))).
+ const auto first_subsegment =
+ static_cast<std::uint32_t>(boost::charconv::detail::umul128_upper64(
+ first_second_subsegments, 1844674407371));
+
+ const auto second_subsegment =
+ static_cast<std::uint32_t>(first_second_subsegments) - 10000000 * first_subsegment;
+
+ int digits_in_the_second_subsegment;
+
+ // Print the first subsegment (0 ~ 6 digits) if exists.
+ if (digits_in_the_second_segment > 16)
+ {
+ std::uint64_t prod;
+ int remaining_digits_in_the_current_subsegment = digits_in_the_second_segment - 16;
+
+ // No rounding, continue.
+ if (remaining_digits > remaining_digits_in_the_current_subsegment)
+ {
+ remaining_digits -= remaining_digits_in_the_current_subsegment;
+
+ // There is no overlap in the second subsegment.
+ digits_in_the_second_subsegment = 7;
+
+ // When there is no overlapping digit.
+ if (remaining_digits_in_the_current_subsegment == 6)
+ {
+ prod = (first_subsegment * UINT64_C(429497)) + 1;
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+ buffer += 2;
+ remaining_digits_in_the_current_subsegment -= 2;
+ }
+ // If there are overlapping digits, move all overlapping digits
+ // into the integer part.
+ else
+ {
+ prod = ((first_subsegment * UINT64_C(687195)) >> 4) + 1;
+ prod *= compute_power(UINT64_C(10), 5 - remaining_digits_in_the_current_subsegment);
+
+ if ((remaining_digits_in_the_current_subsegment & 1) != 0)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
+ print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
+ ++buffer;
+ }
+ }
+
+ for (; remaining_digits_in_the_current_subsegment > 1; remaining_digits_in_the_current_subsegment -= 2)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+ buffer += 2;
+ }
+ }
+ // The first subsegment is the last subsegment to print.
+ else
+ {
+ if ((remaining_digits & 1) != 0)
+ {
+ prod = ((first_subsegment * UINT64_C(687195)) >> 4) + 1;
+
+ // If there are overlapping digits, move all overlapping digits
+ // into the integer part and then get the next digit.
+ if (remaining_digits_in_the_current_subsegment < 6)
+ {
+ prod *= compute_power(UINT64_C(10), 5 - remaining_digits_in_the_current_subsegment);
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
+ }
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+ remaining_digits_in_the_current_subsegment -= remaining_digits;
+
+ if (remaining_digits == 1)
+ {
+ goto second_segment22_more_than_9_digits_first_subsegment_rounding;
+ }
+
+ print_1_digit(current_digits, buffer);
+ ++buffer;
+ }
+ else
+ {
+ // When there is no overlapping digit.
+ if (remaining_digits_in_the_current_subsegment == 6)
+ {
+ if (remaining_digits == 0)
+ {
+ if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
+ current_digits,
+ uint_with_known_number_of_digits<6>{
+ first_subsegment},
+ has_further_digits<1, 16, ExtendedCache>(significand, exp2_base, k, uconst1, uconst16)))
+ {
+ goto round_up_two_digits;
+ }
+ goto print_last_two_digits;
+ }
+
+ prod = (first_subsegment * UINT64_C(429497)) + 1;
+ }
+ // Otherwise, convert the subsegment into a fixed-point
+ // fraction form, move all overlapping digits into the
+ // integer part, and then extract the next two digits.
+ else
+ {
+ prod = ((first_subsegment * UINT64_C(687195)) >> 4) + 1;
+ prod *= compute_power(UINT64_C(10), 5 - remaining_digits_in_the_current_subsegment);
+
+ if (remaining_digits == 0)
+ {
+ goto second_segment22_more_than_9_digits_first_subsegment_rounding_inside_subsegment;
+ }
+
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ }
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+ remaining_digits_in_the_current_subsegment -= remaining_digits;
+
+ if (remaining_digits == 2)
+ {
+ goto second_segment22_more_than_9_digits_first_subsegment_rounding;
+ }
+
+ print_2_digits(current_digits, buffer);
+ buffer += 2;
+ }
+
+ BOOST_CHARCONV_ASSERT(remaining_digits >= 3);
+
+ if (remaining_digits > 4)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+ buffer += 2;
+ }
+
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+ remaining_digits = 0;
+
+ second_segment22_more_than_9_digits_first_subsegment_rounding:
+ if (remaining_digits_in_the_current_subsegment == 0)
+ {
+ if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
+ current_digits,
+ uint_with_known_number_of_digits<7>{second_subsegment},
+ has_further_digits<1, 9, ExtendedCache>(significand, exp2_base, k, uconst1, uconst9)))
+ {
+ goto round_up;
+ }
+ }
+ else
+ {
+ second_segment22_more_than_9_digits_first_subsegment_rounding_inside_subsegment
+ :
+ if (check_rounding_condition_inside_subsegment(
+ current_digits, static_cast<std::uint32_t>(prod),
+ remaining_digits_in_the_current_subsegment,
+ has_further_digits<1, 16, ExtendedCache>(significand, exp2_base, k, uconst1, uconst16)))
+ {
+ goto round_up;
+ }
+ }
+ goto print_last_digits;
+ }
+ }
+ else
+ {
+ digits_in_the_second_subsegment = digits_in_the_second_segment - 9;
+ }
+
+ // Print the second subsegment (1 ~ 7 digits).
+ {
+ // No rounding, continue.
+ if (remaining_digits > digits_in_the_second_subsegment)
+ {
+ auto prod = ((second_subsegment * UINT64_C(17592187)) >> 12) + 1;
+ remaining_digits -= digits_in_the_second_subsegment;
+
+ // When there is no overlapping digit.
+ if (digits_in_the_second_subsegment == 7)
+ {
+ print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
+ ++buffer;
+ }
+ // If there are overlapping digits, move all overlapping digits
+ // into the integer part.
+ else
+ {
+ prod *= compute_power(UINT64_C(10),
+ 6 - digits_in_the_second_subsegment);
+
+ if ((digits_in_the_second_subsegment & 1) != 0)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
+ print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
+ ++buffer;
+ }
+ }
+
+ for (; digits_in_the_second_subsegment > 1; digits_in_the_second_subsegment -= 2)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+ buffer += 2;
+ }
+ }
+ // The second subsegment is the last subsegment to print.
+ else
+ {
+ std::uint64_t prod;
+
+ if ((remaining_digits & 1) != 0)
+ {
+ prod = ((second_subsegment * UINT64_C(17592187)) >> 12) + 1;
+
+ // If there are overlapping digits, move all overlapping digits
+ // into the integer part and then get the next digit.
+ if (digits_in_the_second_subsegment < 7)
+ {
+ prod *= compute_power(UINT64_C(10), 6 - digits_in_the_second_subsegment);
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
+ }
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+ digits_in_the_second_subsegment -= remaining_digits;
+
+ if (remaining_digits == 1)
+ {
+ goto second_segment22_more_than_9_digits_second_subsegment_rounding;
+ }
+
+ print_1_digit(current_digits, buffer);
+ ++buffer;
+ }
+ else
+ {
+ // When there is no overlapping digit.
+ if (digits_in_the_second_subsegment == 7)
+ {
+ if (remaining_digits == 0)
+ {
+ if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
+ current_digits,
+ uint_with_known_number_of_digits<7>{
+ second_subsegment},
+ has_further_digits<1, 9, ExtendedCache>(significand, exp2_base, k, uconst1, uconst9)))
+ {
+ goto round_up_two_digits;
+ }
+ goto print_last_two_digits;
+ }
+
+ prod = ((second_subsegment * UINT64_C(10995117)) >> 8) + 1;
+ }
+ // Otherwise, convert the subsegment into a fixed-point
+ // fraction form, move all overlapping digits into the
+ // integer part, and then extract the next two digits.
+ else
+ {
+ prod = ((second_subsegment * UINT64_C(17592187)) >> 12) + 1;
+ prod *= compute_power(UINT64_C(10), 6 - digits_in_the_second_subsegment);
+
+ if (remaining_digits == 0)
+ {
+ goto second_segment22_more_than_9_digits_second_subsegment_rounding_inside_subsegment;
+ }
+
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ }
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+ digits_in_the_second_subsegment -= remaining_digits;
+
+ if (remaining_digits == 2)
+ {
+ goto second_segment22_more_than_9_digits_second_subsegment_rounding;
+ }
+
+ print_2_digits(current_digits, buffer);
+ buffer += 2;
+ }
+
+ BOOST_CHARCONV_ASSERT(remaining_digits >= 3);
+
+ if (remaining_digits > 4)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+ buffer += 2;
+ }
+
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+ remaining_digits = 0;
+
+ second_segment22_more_than_9_digits_second_subsegment_rounding:
+ if (digits_in_the_second_subsegment == 0)
+ {
+ if (check_rounding_condition_with_next_bit(
+ current_digits, first_bit_of_third_subsegment,
+ has_further_digits<0, 9, ExtendedCache>(significand, exp2_base, k, uconst0, uconst9)))
+ {
+ goto round_up;
+ }
+ }
+ else
+ {
+ second_segment22_more_than_9_digits_second_subsegment_rounding_inside_subsegment
+ :
+ if (check_rounding_condition_inside_subsegment(
+ current_digits, static_cast<std::uint32_t>(prod),
+ digits_in_the_second_subsegment, has_further_digits<1, 9, ExtendedCache>(significand, exp2_base, k,
+ uconst1, uconst9)))
+ {
+ goto round_up;
+ }
+ }
+ goto print_last_digits;
+ }
+ }
+
+ // Print the third subsegment (9 digits).
+ {
+ // Get one more bit if we need to check rounding conditions on
+ // the segment boundary. We already have shifted by 1-bit in the
+ // computation of first & second subsegments, so here we don't
+ // shift the multiplier.
+ auto third_subsegment =
+ fixed_point_calculator<ExtendedCache::max_cache_blocks>::
+ generate_and_discard_lower(power_of_10[9], blocks,
+ cache_block_count);
+
+ bool segment_boundary_rounding_bit = ((third_subsegment & 1) != 0);
+ third_subsegment >>= 1;
+ third_subsegment += (first_bit_of_third_subsegment ? 500000000 : 0);
+
+ std::uint64_t prod;
+ if ((remaining_digits & 1) != 0)
+ {
+ prod = ((third_subsegment * UINT64_C(720575941)) >> 24) + 1;
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (remaining_digits == 1)
+ {
+ if (check_rounding_condition_inside_subsegment(
+ current_digits, static_cast<std::uint32_t>(prod), 8,
+ has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0)))
+ {
+ goto round_up_one_digit;
+ }
+ goto print_last_one_digit;
+ }
+
+ print_1_digit(current_digits, buffer);
+ ++buffer;
+ }
+ else
+ {
+ prod = ((third_subsegment * UINT64_C(450359963)) >> 20) + 1;
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (remaining_digits == 2)
+ {
+ goto second_segment22_more_than_9_digits_third_subsegment_rounding;
+ }
+
+ print_2_digits(current_digits, buffer);
+ buffer += 2;
+ }
+
+ for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+ buffer += 2;
+ }
+
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (remaining_digits < 9)
+ {
+ second_segment22_more_than_9_digits_third_subsegment_rounding:
+ if (check_rounding_condition_inside_subsegment(
+ current_digits, static_cast<std::uint32_t>(prod), 9 - remaining_digits,
+ has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0)))
+ {
+ goto round_up_two_digits;
+ }
+ }
+ else
+ {
+ if (check_rounding_condition_with_next_bit(
+ current_digits, segment_boundary_rounding_bit,
+ has_further_digits<0, 0, ExtendedCache>(significand, exp2_base, k, uconst0, uconst0)))
+ {
+ goto round_up_two_digits;
+ }
+ }
+ goto print_last_two_digits;
+ }
+ }
+ } // ExtendedCache::segment_length == 22
+
+ else BOOST_CHARCONV_IF_CONSTEXPR (ExtendedCache::segment_length == 252)
+ {
+ int overlapping_digits = 252 - digits_in_the_second_segment;
+ int remaining_subsegment_pairs = 14;
+
+ while (overlapping_digits >= 18)
+ {
+ fixed_point_calculator<ExtendedCache::max_cache_blocks>::discard_upper(
+ power_of_10[18], blocks, cache_block_count);
+ --remaining_subsegment_pairs;
+ overlapping_digits -= 18;
+ }
+
+ auto subsegment_pair = fixed_point_calculator<ExtendedCache::max_cache_blocks>::generate(power_of_10[18] << 1, blocks, cache_block_count);
+ auto subsegment_boundary_rounding_bit = (subsegment_pair & 1) != 0;
+ subsegment_pair >>= 1;
+
+ // Deal with the first subsegment pair.
+ {
+ // Divide it into two 9-digits subsegments.
+ const auto first_part = static_cast<std::uint32_t>(subsegment_pair / power_of_10[9]);
+ const auto second_part = static_cast<std::uint32_t>(subsegment_pair - power_of_10[9] * first_part);
+
+ auto print_subsegment = [&](std::uint32_t subsegment, int digits_in_the_subsegment)
+ {
+ remaining_digits -= digits_in_the_subsegment;
+
+ // Move all overlapping digits into the integer part.
+ auto prod = ((subsegment * UINT64_C(720575941)) >> 24) + 1;
+ if (digits_in_the_subsegment < 9)
+ {
+ prod *= compute_power(UINT32_C(10), 8 - digits_in_the_subsegment);
+
+ if ((digits_in_the_subsegment & 1) != 0)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
+ print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
+ ++buffer;
+ }
+ }
+ else
+ {
+ print_1_digit(static_cast<std::uint32_t>(prod >> 32), buffer);
+ ++buffer;
+ }
+
+ for (; digits_in_the_subsegment > 1; digits_in_the_subsegment -= 2)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+ buffer += 2;
+ }
+ };
+
+ // When the first part is not completely overlapping with the first segment.
+ int digits_in_the_second_part;
+ if (overlapping_digits < 9)
+ {
+ int digits_in_the_first_part = 9 - overlapping_digits;
+
+ // No rounding, continue.
+ if (remaining_digits > digits_in_the_first_part)
+ {
+ digits_in_the_second_part = 9;
+ print_subsegment(first_part, digits_in_the_first_part);
+ }
+ // Perform rounding and return.
+ else
+ {
+ // When there is no overlapping digit.
+ std::uint64_t prod;
+ if (digits_in_the_first_part == 9)
+ {
+ if ((remaining_digits & 1) != 0)
+ {
+ prod = ((first_part * UINT64_C(720575941)) >> 24) + 1;
+ }
+ else
+ {
+ if (remaining_digits == 0)
+ {
+ if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
+ current_digits,
+ uint_with_known_number_of_digits<9>{first_part},
+ compute_has_further_digits<1, 9, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
+ {
+ goto round_up_two_digits;
+ }
+ goto print_last_two_digits;
+ }
+
+ prod = ((first_part * UINT64_C(450359963)) >> 20) + 1;
+ }
+ }
+ else
+ {
+ prod = ((first_part * UINT64_C(720575941)) >> 24) + 1;
+ prod *= compute_power(UINT32_C(10), 8 - digits_in_the_first_part);
+
+ if ((remaining_digits & 1) != 0)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
+ }
+ else
+ {
+ if (remaining_digits == 0)
+ {
+ goto second_segment252_first_subsegment_rounding_inside_subsegment;
+ }
+
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ }
+ }
+ digits_in_the_first_part -= remaining_digits;
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (remaining_digits > 2)
+ {
+ if ((remaining_digits & 1) != 0)
+ {
+ print_1_digit(current_digits, buffer);
+ ++buffer;
+ }
+ else
+ {
+ print_2_digits(current_digits, buffer);
+ buffer += 2;
+ }
+
+ for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+ buffer += 2;
+ }
+
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+ remaining_digits = 0;
+ }
+
+ if (digits_in_the_first_part != 0)
+ {
+ second_segment252_first_subsegment_rounding_inside_subsegment:
+ if (check_rounding_condition_inside_subsegment(
+ current_digits, static_cast<std::uint32_t>(prod),
+ digits_in_the_first_part, compute_has_further_digits<1, 9, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
+ {
+ goto round_up;
+ }
+ }
+ else
+ {
+ if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
+ current_digits,
+ uint_with_known_number_of_digits<9>{static_cast<std::uint32_t>(second_part)},
+ compute_has_further_digits<1, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
+ {
+ goto round_up;
+ }
+ }
+ goto print_last_digits;
+ }
+ }
+ else
+ {
+ digits_in_the_second_part = 18 - overlapping_digits;
+ }
+
+ // Print the second part.
+ // No rounding, continue.
+ if (remaining_digits > digits_in_the_second_part)
+ {
+ print_subsegment(second_part, digits_in_the_second_part);
+ }
+ // Perform rounding and return.
+ else
+ {
+ // When there is no overlapping digit.
+ std::uint64_t prod;
+ if (digits_in_the_second_part == 9)
+ {
+ if ((remaining_digits & 1) != 0)
+ {
+ prod = ((second_part * UINT64_C(720575941)) >> 24) + 1;
+ }
+ else
+ {
+ if (remaining_digits == 0)
+ {
+ if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
+ current_digits,
+ uint_with_known_number_of_digits<9>{static_cast<std::uint32_t>(second_part)},
+ compute_has_further_digits<1, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
+ {
+ goto round_up_two_digits;
+ }
+ goto print_last_two_digits;
+ }
+
+ prod = ((second_part * UINT64_C(450359963)) >> 20) + 1;
+ }
+ }
+ else
+ {
+ prod = ((second_part * UINT64_C(720575941)) >> 24) + 1;
+ prod *= compute_power(UINT32_C(10), 8 - digits_in_the_second_part);
+
+ if ((remaining_digits & 1) != 0)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(10);
+ }
+ else
+ {
+ if (remaining_digits == 0)
+ {
+ goto second_segment252_second_subsegment_rounding_inside_subsegment;
+ }
+
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ }
+ }
+ digits_in_the_second_part -= remaining_digits;
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (remaining_digits > 2)
+ {
+ if ((remaining_digits & 1) != 0)
+ {
+ print_1_digit(current_digits, buffer);
+ ++buffer;
+ }
+ else
+ {
+ print_2_digits(current_digits, buffer);
+ buffer += 2;
+ }
+
+ for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+ buffer += 2;
+ }
+
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+ remaining_digits = 0;
+ }
+
+ if (digits_in_the_second_part != 0)
+ {
+ second_segment252_second_subsegment_rounding_inside_subsegment:
+ if (check_rounding_condition_inside_subsegment(
+ current_digits, static_cast<std::uint32_t>(prod),
+ digits_in_the_second_part, compute_has_further_digits<1, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
+ {
+ goto round_up;
+ }
+ }
+ else
+ {
+ if (check_rounding_condition_with_next_bit(
+ current_digits, subsegment_boundary_rounding_bit,
+ compute_has_further_digits<0, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
+ {
+ goto round_up;
+ }
+ }
+ goto print_last_digits;
+ }
+ }
+
+ // Remaining subsegment pairs do not have overlapping digits.
+ --remaining_subsegment_pairs;
+ for (; remaining_subsegment_pairs > 0; --remaining_subsegment_pairs)
+ {
+ subsegment_pair = fixed_point_calculator<ExtendedCache::max_cache_blocks>::generate(power_of_10[18], blocks, cache_block_count);
+
+ subsegment_pair += (subsegment_boundary_rounding_bit ? power_of_10[18] : 0);
+ subsegment_boundary_rounding_bit = (subsegment_pair & 1) != 0;
+ subsegment_pair >>= 1;
+
+ const auto first_part = static_cast<std::uint32_t>(subsegment_pair / power_of_10[9]);
+ const auto second_part = static_cast<std::uint32_t>(subsegment_pair - power_of_10[9] * first_part);
+
+ // The first part can be printed without rounding.
+ if (remaining_digits > 9)
+ {
+ print_9_digits(first_part, buffer);
+
+ // The second part also can be printed without rounding.
+ if (remaining_digits > 18)
+ {
+ print_9_digits(second_part, buffer + 9);
+ }
+ // Otherwise, perform rounding and return.
+ else
+ {
+ buffer += 9;
+ remaining_digits -= 9;
+
+ std::uint64_t prod;
+ int remaining_digits_in_the_current_subsegment = 9 - remaining_digits;
+
+ if ((remaining_digits & 1) != 0)
+ {
+ prod = ((second_part * UINT64_C(720575941)) >> 24) + 1;
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (remaining_digits == 1)
+ {
+ goto second_segment252_loop_second_subsegment_rounding;
+ }
+
+ print_1_digit(current_digits, buffer);
+ ++buffer;
+ }
+ else
+ {
+ prod = ((second_part * UINT64_C(450359963)) >> 20) + 1;
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (remaining_digits == 2)
+ {
+ goto second_segment252_loop_second_subsegment_rounding;
+ }
+
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+ buffer += 2;
+ }
+
+ for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+ buffer += 2;
+ }
+
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+ remaining_digits = 0;
+
+ if (remaining_digits_in_the_current_subsegment != 0)
+ {
+ second_segment252_loop_second_subsegment_rounding:
+ if (check_rounding_condition_inside_subsegment(
+ current_digits, static_cast<std::uint32_t>(prod),
+ remaining_digits_in_the_current_subsegment,
+ compute_has_further_digits<1, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
+ {
+ goto round_up;
+ }
+ goto print_last_digits;
+ }
+ else
+ {
+ if (check_rounding_condition_with_next_bit(
+ current_digits, subsegment_boundary_rounding_bit,
+ compute_has_further_digits<0, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
+ {
+ goto round_up_two_digits;
+ }
+ goto print_last_two_digits;
+ }
+ }
+ }
+ // Otherwise, perform rounding and return.
+ else
+ {
+ std::uint64_t prod;
+ int remaining_digits_in_the_current_subsegment = 9 - remaining_digits;
+ if ((remaining_digits & 1) != 0)
+ {
+ prod = ((first_part * UINT64_C(720575941)) >> 24) + 1;
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (remaining_digits == 1)
+ {
+ goto second_segment252_loop_first_subsegment_rounding;
+ }
+
+ print_1_digit(current_digits, buffer);
+ ++buffer;
+ }
+ else
+ {
+ prod = ((first_part * UINT64_C(450359963)) >> 20) + 1;
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (remaining_digits == 2)
+ {
+ goto second_segment252_loop_first_subsegment_rounding;
+ }
+
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+ buffer += 2;
+ }
+
+ for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+ buffer += 2;
+ }
+
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+ remaining_digits = 0;
+
+ if (remaining_digits_in_the_current_subsegment != 0)
+ {
+ second_segment252_loop_first_subsegment_rounding:
+ if (check_rounding_condition_inside_subsegment(
+ current_digits, static_cast<std::uint32_t>(prod),
+ remaining_digits_in_the_current_subsegment,
+ compute_has_further_digits<1, 9, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
+ {
+ goto round_up;
+ }
+ goto print_last_digits;
+ }
+ else
+ {
+ if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
+ current_digits,
+ uint_with_known_number_of_digits<9>{static_cast<std::uint32_t>(second_part)},
+ compute_has_further_digits<1, 9, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
+ {
+ goto round_up_two_digits;
+ }
+ goto print_last_two_digits;
+ }
+ }
+
+ buffer += 18;
+ remaining_digits -= 18;
+ }
+ } // ExtendedCache::segment_length == 252
+ }
+
+ // Print all remaining segments.
+ while (has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0))
+ {
+ // Get new segment.
+ ++multiplier_index;
+ k += ExtendedCache::segment_length;
+
+ cache_block_count = load_extended_cache<ExtendedCache, ExtendedCache::constant_block_count>(blocks, e, k, multiplier_index);
+
+ // Compute nm mod 2^Q.
+ fixed_point_calculator<ExtendedCache::max_cache_blocks>::discard_upper(significand, blocks, cache_block_count);
+
+ BOOST_CHARCONV_IF_CONSTEXPR (ExtendedCache::segment_length == 22)
+ {
+ // When at least two subsegments left.
+ if (remaining_digits > 16)
+ {
+ std::uint64_t first_second_subsegments = fixed_point_calculator<ExtendedCache::max_cache_blocks>::generate(power_of_10[16], blocks, cache_block_count);
+
+ const auto first_subsegment =
+ static_cast<std::uint32_t>(boost::charconv::detail::umul128_upper64(first_second_subsegments, UINT64_C(3022314549036573)) >> 14);
+
+ const std::uint32_t second_subsegment = static_cast<std::uint32_t>(first_second_subsegments) - UINT32_C(100000000) * first_subsegment;
+
+ print_8_digits(first_subsegment, buffer);
+ print_8_digits(second_subsegment, buffer + 8);
+
+ // When more segments left.
+ if (remaining_digits > 22)
+ {
+ const auto third_subsegment = static_cast<std::uint32_t>(
+ fixed_point_calculator<ExtendedCache::max_cache_blocks>::generate_and_discard_lower(power_of_10[6], blocks,cache_block_count));
+
+ print_6_digits(third_subsegment, buffer + 16);
+ buffer += 22;
+ remaining_digits -= 22;
+ }
+ // When this is the last segment.
+ else
+ {
+ buffer += 16;
+ remaining_digits -= 16;
+
+ auto third_subsegment = fixed_point_calculator<ExtendedCache::max_cache_blocks>::
+ generate_and_discard_lower(power_of_10[6] << 1, blocks, cache_block_count);
+
+ bool segment_boundary_rounding_bit = ((third_subsegment & 1) != 0);
+ third_subsegment >>= 1;
+
+ std::uint64_t prod;
+ if ((remaining_digits & 1) != 0)
+ {
+ prod = ((third_subsegment * UINT64_C(687195)) >> 4) + 1;
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (remaining_digits == 1)
+ {
+ if (check_rounding_condition_inside_subsegment(
+ current_digits, static_cast<std::uint32_t>(prod), 5,
+ has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0)))
+ {
+ goto round_up_one_digit;
+ }
+ goto print_last_one_digit;
+ }
+
+ print_1_digit(current_digits, buffer);
+ ++buffer;
+ }
+ else
+ {
+ prod = (third_subsegment * UINT64_C(429497)) + 1;
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (remaining_digits == 2)
+ {
+ goto segment_loop22_more_than_16_digits_rounding;
+ }
+
+ print_2_digits(current_digits, buffer);
+ buffer += 2;
+ }
+
+ if (remaining_digits > 4)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+ buffer += 2;
+
+ if (remaining_digits == 6)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (check_rounding_condition_with_next_bit(
+ current_digits, segment_boundary_rounding_bit,
+ has_further_digits<0, 0, ExtendedCache>(significand, exp2_base, k, uconst0, uconst0)))
+ {
+ goto round_up_two_digits;
+ }
+ goto print_last_two_digits;
+ }
+ }
+
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ segment_loop22_more_than_16_digits_rounding:
+ if (check_rounding_condition_inside_subsegment(
+ current_digits, static_cast<std::uint32_t>(prod), 6 - remaining_digits,
+ has_further_digits<1, 0, ExtendedCache>(significand, exp2_base, k, uconst1, uconst0)))
+ {
+ goto round_up_two_digits;
+ }
+ goto print_last_two_digits;
+ }
+ }
+ // When two subsegments left.
+ else if (remaining_digits > 8)
+ {
+ // Get one more bit for potential rounding conditions check.
+ auto first_second_subsegments =
+ fixed_point_calculator<ExtendedCache::max_cache_blocks>::
+ generate_and_discard_lower(power_of_10[16] << 1, blocks, cache_block_count);
+
+ bool first_bit_of_third_subsegment = ((first_second_subsegments & 1) != 0);
+ first_second_subsegments >>= 1;
+
+ // 3022314549036573 = ceil(2^78/10^8) = floor(2^78*(10^8/(10^16 -
+ // 1))).
+ const auto first_subsegment =
+ static_cast<std::uint32_t>(boost::charconv::detail::umul128_upper64(first_second_subsegments, UINT64_C(3022314549036573)) >> 14);
+
+ const auto second_subsegment = static_cast<std::uint32_t>(first_second_subsegments) - UINT32_C(100000000) * first_subsegment;
+
+ print_8_digits(first_subsegment, buffer);
+ buffer += 8;
+ remaining_digits -= 8;
+
+ // Second subsegment (8 digits).
+ std::uint64_t prod;
+ if ((remaining_digits & 1) != 0)
+ {
+ prod = ((second_subsegment * UINT64_C(112589991)) >> 18) + 1;
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (remaining_digits == 1)
+ {
+ if (check_rounding_condition_inside_subsegment(
+ current_digits, static_cast<std::uint32_t>(prod), 7, has_further_digits<1, 6, ExtendedCache>(significand, exp2_base, k,
+ uconst1, uconst6)))
+ {
+ goto round_up_one_digit;
+ }
+ goto print_last_one_digit;
+ }
+
+ print_1_digit(current_digits, buffer);
+ ++buffer;
+ }
+ else
+ {
+ prod = ((second_subsegment * UINT64_C(140737489)) >> 15) + 1;
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (remaining_digits == 2)
+ {
+ goto segment_loop22_more_than_8_digits_rounding;
+ }
+
+ print_2_digits(current_digits, buffer);
+ buffer += 2;
+ }
+
+ for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+ buffer += 2;
+ }
+
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (remaining_digits < 8)
+ {
+ segment_loop22_more_than_8_digits_rounding:
+ if (check_rounding_condition_inside_subsegment(
+ current_digits, static_cast<std::uint32_t>(prod), 8 - remaining_digits,
+ has_further_digits<1, 6, ExtendedCache>(significand, exp2_base, k, uconst1, uconst6)))
+ {
+ goto round_up_two_digits;
+ }
+ }
+ else {
+ if (check_rounding_condition_with_next_bit(
+ current_digits, first_bit_of_third_subsegment,
+ has_further_digits<0, 6, ExtendedCache>(significand, exp2_base, k, uconst0, uconst6)))
+ {
+ goto round_up_two_digits;
+ }
+ }
+ goto print_last_two_digits;
+ }
+ // remaining_digits is at most 8.
+ else
+ {
+ // Get one more bit for potential rounding conditions check.
+ auto first_subsegment =
+ fixed_point_calculator<ExtendedCache::max_cache_blocks>::
+ generate_and_discard_lower(power_of_10[8] << 1, blocks, cache_block_count);
+
+ bool first_bit_of_second_subsegment = ((first_subsegment & 1) != 0);
+ first_subsegment >>= 1;
+
+ std::uint64_t prod;
+ if ((remaining_digits & 1) != 0)
+ {
+ prod = ((first_subsegment * UINT64_C(112589991)) >> 18) + 1;
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (remaining_digits == 1)
+ {
+ if (check_rounding_condition_inside_subsegment(
+ current_digits, static_cast<std::uint32_t>(prod), 7, has_further_digits<1, 14, ExtendedCache>(significand, exp2_base, k,
+ uconst1, uconst14)))
+ {
+ goto round_up_one_digit;
+ }
+ goto print_last_one_digit;
+ }
+
+ print_1_digit(current_digits, buffer);
+ ++buffer;
+ }
+ else
+ {
+ prod = ((first_subsegment * UINT64_C(140737489)) >> 15) + 1;
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (remaining_digits == 2)
+ {
+ goto segment_loop22_at_most_8_digits_rounding;
+ }
+
+ print_2_digits(current_digits, buffer);
+ buffer += 2;
+ }
+
+ for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+ buffer += 2;
+ }
+
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (remaining_digits < 8)
+ {
+ segment_loop22_at_most_8_digits_rounding:
+ if (check_rounding_condition_inside_subsegment(
+ current_digits, static_cast<std::uint32_t>(prod), 8 - remaining_digits,
+ has_further_digits<1, 14, ExtendedCache>(significand, exp2_base, k, uconst1, uconst14)))
+ {
+ goto round_up_two_digits;
+ }
+ }
+ else
+ {
+ if (check_rounding_condition_with_next_bit(
+ current_digits, first_bit_of_second_subsegment,
+ has_further_digits<0, 14, ExtendedCache>(significand, exp2_base, k, uconst0, uconst14)))
+ {
+ goto round_up_two_digits;
+ }
+ }
+ goto print_last_two_digits;
+ }
+ } // ExtendedCache::segment_length == 22
+ else if (ExtendedCache::segment_length == 252)
+ {
+ // Print as many 18-digits subsegment pairs as possible.
+ for (int remaining_subsegment_pairs = 14; remaining_subsegment_pairs > 0;
+ --remaining_subsegment_pairs)
+ {
+ // No rounding, continue.
+ if (remaining_digits > 18)
+ {
+ const auto subsegment_pair =
+ fixed_point_calculator<ExtendedCache::max_cache_blocks>::generate(power_of_10[18], blocks, cache_block_count);
+
+ const auto first_part = static_cast<std::uint32_t>(subsegment_pair / power_of_10[9]);
+ const auto second_part = static_cast<std::uint32_t>(subsegment_pair - power_of_10[9] * first_part);
+
+ print_9_digits(first_part, buffer);
+ print_9_digits(second_part, buffer + 9);
+ buffer += 18;
+ remaining_digits -= 18;
+ }
+ // Final subsegment pair.
+ else
+ {
+ auto last_subsegment_pair =
+ fixed_point_calculator<ExtendedCache::max_cache_blocks>::
+ generate_and_discard_lower(power_of_10[18] << 1, blocks, cache_block_count);
+
+ const bool subsegment_boundary_rounding_bit = ((last_subsegment_pair & 1) != 0);
+ last_subsegment_pair >>= 1;
+
+ const auto first_part = static_cast<std::uint32_t>(last_subsegment_pair / power_of_10[9]);
+ const auto second_part = static_cast<std::uint32_t>(last_subsegment_pair) - power_of_10[9] * first_part;
+
+ if (remaining_digits <= 9)
+ {
+ std::uint64_t prod;
+
+ if ((remaining_digits & 1) != 0)
+ {
+ prod = ((first_part * UINT64_C(1441151881)) >> 25) + 1;
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (remaining_digits == 1)
+ {
+ if (check_rounding_condition_inside_subsegment(
+ current_digits, static_cast<std::uint32_t>(prod), 8,
+ compute_has_further_digits<1, 9, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
+ {
+ goto round_up_one_digit;
+ }
+ goto print_last_one_digit;
+ }
+
+ print_1_digit(current_digits, buffer);
+ ++buffer;
+ }
+ else
+ {
+ prod = ((first_part * UINT64_C(450359963)) >> 20) + 1;
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (remaining_digits == 2)
+ {
+ goto segment_loop252_final18_first_part_rounding;
+ }
+
+ print_2_digits(current_digits, buffer);
+ buffer += 2;
+ }
+
+ for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+ buffer += 2;
+ }
+
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (remaining_digits < 9)
+ {
+ segment_loop252_final18_first_part_rounding:
+ if (check_rounding_condition_inside_subsegment(
+ current_digits, static_cast<std::uint32_t>(prod),
+ 9 - remaining_digits, compute_has_further_digits<1, 9, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
+ {
+ goto round_up_two_digits;
+ }
+ }
+ else
+ {
+ if (check_rounding_condition_subsegment_boundary_with_next_subsegment(
+ current_digits,
+ uint_with_known_number_of_digits<9>{static_cast<std::uint32_t>(second_part)},
+ compute_has_further_digits<1, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
+ {
+ goto round_up_two_digits;
+ }
+ }
+ goto print_last_two_digits;
+ } // remaining_digits <= 9
+
+ print_9_digits(first_part, buffer);
+ buffer += 9;
+ remaining_digits -= 9;
+
+ std::uint64_t prod;
+
+ if ((remaining_digits & 1) != 0)
+ {
+ prod = ((second_part * UINT64_C(1441151881)) >> 25) + 1;
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (remaining_digits == 1)
+ {
+ if (check_rounding_condition_inside_subsegment(
+ current_digits, static_cast<std::uint32_t>(prod), 8,
+ compute_has_further_digits<1, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
+ {
+ goto round_up_one_digit;
+ }
+ goto print_last_one_digit;
+ }
+
+ print_1_digit(current_digits, buffer);
+ ++buffer;
+ }
+ else
+ {
+ prod = ((second_part * UINT64_C(450359963)) >> 20) + 1;
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (remaining_digits == 2)
+ {
+ goto segment_loop252_final18_second_part_rounding;
+ }
+
+ print_2_digits(current_digits, buffer);
+ buffer += 2;
+ }
+
+ for (int i = 0; i < (remaining_digits - 3) / 2; ++i)
+ {
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ print_2_digits(static_cast<std::uint32_t>(prod >> 32), buffer);
+ buffer += 2;
+ }
+
+ prod = static_cast<std::uint32_t>(prod) * UINT64_C(100);
+ current_digits = static_cast<std::uint32_t>(prod >> 32);
+
+ if (remaining_digits < 9)
+ {
+ segment_loop252_final18_second_part_rounding:
+ if (check_rounding_condition_inside_subsegment(
+ current_digits, static_cast<std::uint32_t>(prod), 9 - remaining_digits,
+ compute_has_further_digits<1, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
+ {
+ goto round_up_two_digits;
+ }
+ }
+ else
+ {
+ if (check_rounding_condition_with_next_bit(
+ current_digits, subsegment_boundary_rounding_bit,
+ compute_has_further_digits<0, 0, ExtendedCache>, remaining_subsegment_pairs, significand, exp2_base, k))
+ {
+ goto round_up_two_digits;
+ }
+ }
+ goto print_last_two_digits;
+ }
+ }
+ } // if (ExtendedCache::segment_length == 252)
+ }
+ }
+
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////
+ /// Phase 3 - Fill remaining digits with 0's, insert decimal dot, print exponent, and
+ /// return.
+ /////////////////////////////////////////////////////////////////////////////////////////////////
+
+fill_remaining_digits_with_0s:
+ // This is probably not needed for the general format, but currently I am not 100% sure.
+ // (When fixed format is eventually chosen, we do not remove trailing zeros in the integer part.
+ // I am not sure if those trailing zeros are guaranteed to be already printed or not.)
+ std::memset(buffer, '0', static_cast<std::size_t>(remaining_digits));
+ buffer += remaining_digits;
+
+insert_decimal_dot:
+ if (fmt == chars_format::general)
+ {
+ // Decide between fixed vs scientific.
+ if (-4 <= decimal_exponent_normalized && decimal_exponent_normalized < precision)
+ {
+ // Fixed.
+ if (decimal_exponent_normalized >= 0)
+ {
+ // Insert decimal dot.
+ decimal_dot_pos = buffer_starting_pos + decimal_exponent_normalized + 1;
+ std::memmove(buffer_starting_pos, buffer_starting_pos + 1,
+ static_cast<std::size_t>(decimal_dot_pos - buffer_starting_pos));
+ *decimal_dot_pos = '.';
+ }
+ else
+ {
+ // Print leading zeros and insert decimal dot.
+ int number_of_leading_zeros = -decimal_exponent_normalized - 1;
+ std::memmove(buffer_starting_pos + number_of_leading_zeros + 2, buffer_starting_pos + 1,
+ static_cast<std::size_t>(buffer - buffer_starting_pos - 1));
+ std::memcpy(buffer_starting_pos, "0.", 2);
+ std::memset(buffer_starting_pos + 2, '0', static_cast<std::size_t>(number_of_leading_zeros));
+ buffer += number_of_leading_zeros + 1;
+ }
+ // Don't print exponent.
+ fmt = chars_format::fixed;
+ }
+ else
+ {
+ // Scientific.
+ // Insert decimal dot.
+ *buffer_starting_pos = *(buffer_starting_pos + 1);
+ *(buffer_starting_pos + 1) = '.';
+ }
+
+ // Remove trailing zeros.
+ while (true)
+ {
+ auto prev = buffer - 1;
+
+ // Remove decimal dot as well if there is no fractional digits.
+ if (*prev == '.')
+ {
+ buffer = prev;
+ break;
+ }
+ else if (*prev != '0')
+ {
+ break;
+ }
+ buffer = prev;
+ }
+ }
+ else if (decimal_dot_pos != buffer_starting_pos)
+ {
+ std::memmove(buffer_starting_pos, buffer_starting_pos + 1,
+ static_cast<std::size_t>(decimal_dot_pos - buffer_starting_pos));
+ *decimal_dot_pos = '.';
+ }
+
+ if (fmt != chars_format::fixed)
+ {
+ if (decimal_exponent_normalized >= 0)
+ {
+ std::memcpy(buffer, "e+", 2); // NOLINT : Specifically not null-terminating
+ }
+ else
+ {
+ std::memcpy(buffer, "e-", 2); // NOLINT : Specifically not null-terminating
+ decimal_exponent_normalized = -decimal_exponent_normalized;
+ }
+
+ buffer += 2;
+ if (decimal_exponent_normalized >= 100)
+ {
+ // d1 = decimal_exponent / 10; d2 = decimal_exponent % 10;
+ // 6554 = ceil(2^16 / 10)
+ auto prod = static_cast<std::uint32_t>(decimal_exponent_normalized) * UINT32_C(6554);
+ auto d1 = prod >> 16;
+ prod = static_cast<std::uint16_t>(prod) * UINT16_C(5); // * 10
+ auto d2 = prod >> 15; // >> 16
+ print_2_digits(d1, buffer);
+ print_1_digit(d2, buffer + 2);
+ buffer += 3;
+ }
+ else
+ {
+ print_2_digits(static_cast<std::uint32_t>(decimal_exponent_normalized), buffer);
+ buffer += 2;
+ }
+ }
+
+ return {buffer, std::errc()};
+
+round_up:
+ if ((remaining_digits & 1) != 0)
+ {
+ round_up_one_digit:
+ if (++current_digits == 10)
+ {
+ goto round_up_all_9s;
+ }
+
+ goto print_last_one_digit;
+ }
+ else
+ {
+ round_up_two_digits:
+ if (++current_digits == 100)
+ {
+ goto round_up_all_9s;
+ }
+
+ goto print_last_two_digits;
+ }
+
+print_last_digits:
+ if ((remaining_digits & 1) != 0)
+ {
+ print_last_one_digit:
+ print_1_digit(current_digits, buffer);
+ ++buffer;
+ }
+ else
+ {
+ print_last_two_digits:
+ print_2_digits(current_digits, buffer);
+ buffer += 2;
+ }
+
+ goto insert_decimal_dot;
+
+round_up_all_9s:
+ char* first_9_pos = buffer;
+ buffer += (2 - (remaining_digits & 1));
+
+ // Find the starting position of printed digits.
+ char* digit_starting_pos = [&] {
+ // For negative exponent & fixed format, we already printed leading zeros.
+ if (fmt == chars_format::fixed && decimal_exponent_normalized < 0)
+ {
+ return buffer_starting_pos - decimal_exponent_normalized + 1;
+ }
+ // We reserved one slot for decimal dot, so the starting position of printed digits
+ // is buffer_starting_pos + 1 if we need to print decimal dot.
+ return buffer_starting_pos == decimal_dot_pos ? buffer_starting_pos
+ : buffer_starting_pos + 1;
+ }();
+ // Find all preceding 9's.
+ if ((first_9_pos - digit_starting_pos) % 2 != 0)
+ {
+ if (*(first_9_pos - 1) != '9')
+ {
+ ++*(first_9_pos - 1);
+ if ((remaining_digits & 1) != 0)
+ {
+ *first_9_pos = '0';
+ }
+ else
+ {
+ std::memcpy(first_9_pos, "00", 2);
+ }
+ goto insert_decimal_dot;
+ }
+ --first_9_pos;
+ }
+ while (first_9_pos != digit_starting_pos)
+ {
+ if (std::memcmp(first_9_pos - 2, "99", 2) != 0)
+ {
+ if (*(first_9_pos - 1) != '9')
+ {
+ ++*(first_9_pos - 1);
+ }
+ else
+ {
+ ++*(first_9_pos - 2);
+ *(first_9_pos - 1) = '0';
+ }
+ std::memset(first_9_pos, '0', static_cast<std::size_t>(buffer - first_9_pos));
+ goto insert_decimal_dot;
+ }
+ first_9_pos -= 2;
+ }
+
+ // Every digit we wrote so far are all 9's. In this case, we have to shift the whole thing by 1.
+ ++decimal_exponent_normalized;
+
+ if (fmt == chars_format::fixed)
+ {
+ if (decimal_exponent_normalized > 0)
+ {
+ // We need to print one more character.
+ if (buffer == last)
+ {
+ return {last, std::errc::value_too_large};
+ }
+ ++buffer;
+ // If we were to print the decimal dot, we have to shift it to right
+ // since we now have one more digit in the integer part.
+ if (buffer_starting_pos != decimal_dot_pos)
+ {
+ ++decimal_dot_pos;
+ }
+ }
+ else if (decimal_exponent_normalized == 0)
+ {
+ // For the case 0.99...9 -> 1.00...0, the rounded digit is one before the first digit written.
+ // Note: decimal_exponent_normalized was negative before the increment (++decimal_exponent_normalized),
+ // so we already have printed "00" onto the buffer.
+ // Hence, --digit_starting_pos doesn't go more than the starting position of the buffer.
+ --digit_starting_pos;
+ }
+ }
+
+ // Nolint is applied to the following two calls since we know they are not supposed to be null terminated
+ *digit_starting_pos = '1';
+ std::memset(digit_starting_pos + 1, '0', static_cast<std::size_t>(buffer - digit_starting_pos - 1)); // NOLINT
+
+ goto insert_decimal_dot;
+}
+
+}}} // Namespaces
+
+#ifdef BOOST_MSVC
+# pragma warning(pop)
+#endif
+
+#endif // BOOST_CHARCONV_DETAIL_FLOFF
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/emulated128.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/emulated128.hpp
new file mode 100644
index 00000000000..281b031cb42
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/emulated128.hpp
@@ -0,0 +1,1005 @@
+// Copyright 2020-2023 Daniel Lemire
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+//
+// If the architecture (e.g. Apple ARM) does not have __int128 we need to emulate it
+
+#ifndef BOOST_CHARCONV_DETAIL_EMULATED128_HPP
+#define BOOST_CHARCONV_DETAIL_EMULATED128_HPP
+
+#include <boost/charconv/detail/config.hpp>
+#include <boost/charconv/config.hpp>
+#include <boost/core/bit.hpp>
+#include <type_traits>
+#include <limits>
+#include <cstdint>
+#include <cassert>
+#include <cmath>
+
+namespace boost { namespace charconv { namespace detail {
+
+// Compilers might support built-in 128-bit integer types. However, it seems that
+// emulating them with a pair of 64-bit integers actually produces a better code,
+// so we avoid using those built-ins. That said, they are still useful for
+// implementing 64-bit x 64-bit -> 128-bit multiplication.
+
+// Memcpy-able temp class for uint128
+struct trivial_uint128
+{
+ #if BOOST_CHARCONV_ENDIAN_LITTLE_BYTE
+ std::uint64_t low;
+ std::uint64_t high;
+ #else
+ std::uint64_t high;
+ std::uint64_t low;
+ #endif
+};
+
+// Macro replacement lists can not be enclosed in parentheses
+struct uint128
+{
+ std::uint64_t high;
+ std::uint64_t low;
+
+ // Constructors
+ constexpr uint128() noexcept : high {}, low {} {}
+
+ constexpr uint128(const uint128& v) noexcept = default;
+
+ constexpr uint128(uint128&& v) noexcept = default;
+
+ constexpr uint128(std::uint64_t high_, std::uint64_t low_) noexcept : high {high_}, low {low_} {}
+
+ constexpr uint128(const trivial_uint128& v) noexcept : high {v.high}, low {v.low} {} // NOLINT
+
+ constexpr uint128(trivial_uint128&& v) noexcept : high {v.high}, low {v.low} {} // NOLINT
+
+ #define SIGNED_CONSTRUCTOR(expr) constexpr uint128(expr v) noexcept : high {v < 0 ? UINT64_MAX : UINT64_C(0)}, low {static_cast<std::uint64_t>(v)} {} // NOLINT
+ #define UNSIGNED_CONSTRUCTOR(expr) constexpr uint128(expr v) noexcept : high {}, low {static_cast<std::uint64_t>(v)} {} // NOLINT
+
+ SIGNED_CONSTRUCTOR(char) // NOLINT
+ SIGNED_CONSTRUCTOR(signed char) // NOLINT
+ SIGNED_CONSTRUCTOR(short) // NOLINT
+ SIGNED_CONSTRUCTOR(int) // NOLINT
+ SIGNED_CONSTRUCTOR(long) // NOLINT
+ SIGNED_CONSTRUCTOR(long long) // NOLINT
+
+ UNSIGNED_CONSTRUCTOR(unsigned char) // NOLINT
+ UNSIGNED_CONSTRUCTOR(unsigned short) // NOLINT
+ UNSIGNED_CONSTRUCTOR(unsigned) // NOLINT
+ UNSIGNED_CONSTRUCTOR(unsigned long) // NOLINT
+ UNSIGNED_CONSTRUCTOR(unsigned long long) // NOLINT
+
+ #ifdef BOOST_CHARCONV_HAS_INT128
+ constexpr uint128(boost::int128_type v) noexcept : // NOLINT : Allow implicit conversions
+ high {static_cast<std::uint64_t>(v >> 64)},
+ low {static_cast<std::uint64_t>(static_cast<boost::uint128_type>(v) & ~UINT64_C(0))} {}
+
+ constexpr uint128(boost::uint128_type v) noexcept : // NOLINT : Allow implicit conversions
+ high {static_cast<std::uint64_t>(v >> 64)},
+ low {static_cast<std::uint64_t>(v & ~UINT64_C(0))} {}
+ #endif
+
+ #undef SIGNED_CONSTRUCTOR
+ #undef UNSIGNED_CONSTRUCTOR
+
+ // Assignment Operators
+ #define SIGNED_ASSIGNMENT_OPERATOR(expr) BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator=(const expr& v) noexcept { high = v < 0 ? UINT64_MAX : UINT64_C(0); low = static_cast<std::uint64_t>(v); return *this; } // NOLINT
+ #define UNSIGNED_ASSIGNMENT_OPERATOR(expr) BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator=(const expr& v) noexcept { high = 0U; low = static_cast<std::uint64_t>(v); return *this; } // NOLINT
+
+ SIGNED_ASSIGNMENT_OPERATOR(char) // NOLINT
+ SIGNED_ASSIGNMENT_OPERATOR(signed char) // NOLINT
+ SIGNED_ASSIGNMENT_OPERATOR(short) // NOLINT
+ SIGNED_ASSIGNMENT_OPERATOR(int) // NOLINT
+ SIGNED_ASSIGNMENT_OPERATOR(long) // NOLINT
+ SIGNED_ASSIGNMENT_OPERATOR(long long) // NOLINT
+
+ UNSIGNED_ASSIGNMENT_OPERATOR(unsigned char) // NOLINT
+ UNSIGNED_ASSIGNMENT_OPERATOR(unsigned short) // NOLINT
+ UNSIGNED_ASSIGNMENT_OPERATOR(unsigned) // NOLINT
+ UNSIGNED_ASSIGNMENT_OPERATOR(unsigned long) // NOLINT
+ UNSIGNED_ASSIGNMENT_OPERATOR(unsigned long long) // NOLINT
+
+ #ifdef BOOST_CHARCONV_HAS_INT128
+ BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator=(const boost::int128_type& v) noexcept { *this = uint128(v); return *this; }
+ BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator=(const boost::uint128_type& v) noexcept { *this = uint128(v); return *this; }
+ #endif
+
+ BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator=(const trivial_uint128& v) noexcept { this->low = v.low; this->high = v.high; return *this; }
+
+ BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator=(const uint128&) noexcept;
+
+ #undef SIGNED_ASSIGNMENT_OPERATOR
+ #undef UNSIGNED_ASSIGNMENT_OPERATOR
+
+ // Conversion Operators
+ #define INTEGER_CONVERSION_OPERATOR(expr) explicit constexpr operator expr() const noexcept { return static_cast<expr>(low); } // NOLINT
+ #define FLOAT_CONVERSION_OPERATOR(expr) explicit operator expr() const noexcept { return std::ldexp(static_cast<expr>(high), 64) + static_cast<expr>(low); } // NOLINT
+
+ INTEGER_CONVERSION_OPERATOR(char) // NOLINT
+ INTEGER_CONVERSION_OPERATOR(signed char) // NOLINT
+ INTEGER_CONVERSION_OPERATOR(short) // NOLINT
+ INTEGER_CONVERSION_OPERATOR(int) // NOLINT
+ INTEGER_CONVERSION_OPERATOR(long) // NOLINT
+ INTEGER_CONVERSION_OPERATOR(long long) // NOLINT
+ INTEGER_CONVERSION_OPERATOR(unsigned char) // NOLINT
+ INTEGER_CONVERSION_OPERATOR(unsigned short) // NOLINT
+ INTEGER_CONVERSION_OPERATOR(unsigned) // NOLINT
+ INTEGER_CONVERSION_OPERATOR(unsigned long) // NOLINT
+ INTEGER_CONVERSION_OPERATOR(unsigned long long) // NOLINT
+
+ explicit constexpr operator bool() const noexcept { return high || low; }
+
+ #ifdef BOOST_CHARCONV_HAS_INT128
+ explicit constexpr operator boost::int128_type() const noexcept { return (static_cast<boost::int128_type>(high) << 64) + low; }
+ explicit constexpr operator boost::uint128_type() const noexcept { return (static_cast<boost::uint128_type>(high) << 64) + low; }
+ #endif
+
+ FLOAT_CONVERSION_OPERATOR(float) // NOLINT
+ FLOAT_CONVERSION_OPERATOR(double) // NOLINT
+ FLOAT_CONVERSION_OPERATOR(long double) // NOLINT
+
+ #undef INTEGER_CONVERSION_OPERATOR
+ #undef FLOAT_CONVERSION_OPERATOR
+
+ // Unary Operators
+ constexpr friend uint128 operator-(uint128 val) noexcept;
+ constexpr friend uint128 operator+(uint128 val) noexcept;
+
+ // Comparison Operators
+
+ // Equality
+ #define INTEGER_OPERATOR_EQUAL(expr) constexpr friend bool operator==(uint128 lhs, expr rhs) noexcept { return lhs.high == 0 && rhs >= 0 && lhs.low == static_cast<std::uint64_t>(rhs); } // NOLINT
+ #define UNSIGNED_INTEGER_OPERATOR_EQUAL(expr) constexpr friend bool operator==(uint128 lhs, expr rhs) noexcept { return lhs.high == 0 && lhs.low == static_cast<std::uint64_t>(rhs); } // NOLINT
+
+ INTEGER_OPERATOR_EQUAL(char) // NOLINT
+ INTEGER_OPERATOR_EQUAL(signed char) // NOLINT
+ INTEGER_OPERATOR_EQUAL(short) // NOLINT
+ INTEGER_OPERATOR_EQUAL(int) // NOLINT
+ INTEGER_OPERATOR_EQUAL(long) // NOLINT
+ INTEGER_OPERATOR_EQUAL(long long) // NOLINT
+ UNSIGNED_INTEGER_OPERATOR_EQUAL(unsigned char) // NOLINT
+ UNSIGNED_INTEGER_OPERATOR_EQUAL(unsigned short) // NOLINT
+ UNSIGNED_INTEGER_OPERATOR_EQUAL(unsigned) // NOLINT
+ UNSIGNED_INTEGER_OPERATOR_EQUAL(unsigned long) // NOLINT
+ UNSIGNED_INTEGER_OPERATOR_EQUAL(unsigned long long) // NOLINT
+
+ #ifdef BOOST_CHARCONV_HAS_INT128
+ constexpr friend bool operator==(uint128 lhs, boost::int128_type rhs) noexcept { return lhs == uint128(rhs); }
+ constexpr friend bool operator==(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs == uint128(rhs); }
+ #endif
+
+ constexpr friend bool operator==(uint128 lhs, uint128 rhs) noexcept;
+
+ #undef INTEGER_OPERATOR_EQUAL
+ #undef UNSIGNED_INTEGER_OPERATOR_EQUAL
+
+ // Inequality
+ #define INTEGER_OPERATOR_NOTEQUAL(expr) constexpr friend bool operator!=(uint128 lhs, expr rhs) noexcept { return !(lhs == rhs); } // NOLINT
+
+ INTEGER_OPERATOR_NOTEQUAL(char) // NOLINT
+ INTEGER_OPERATOR_NOTEQUAL(signed char) // NOLINT
+ INTEGER_OPERATOR_NOTEQUAL(short) // NOLINT
+ INTEGER_OPERATOR_NOTEQUAL(int) // NOLINT
+ INTEGER_OPERATOR_NOTEQUAL(long) // NOLINT
+ INTEGER_OPERATOR_NOTEQUAL(long long) // NOLINT
+ INTEGER_OPERATOR_NOTEQUAL(unsigned char) // NOLINT
+ INTEGER_OPERATOR_NOTEQUAL(unsigned short) // NOLINT
+ INTEGER_OPERATOR_NOTEQUAL(unsigned) // NOLINT
+ INTEGER_OPERATOR_NOTEQUAL(unsigned long) // NOLINT
+ INTEGER_OPERATOR_NOTEQUAL(unsigned long long) // NOLINT
+
+ #ifdef BOOST_CHARCONV_HAS_INT128
+ constexpr friend bool operator!=(uint128 lhs, boost::int128_type rhs) noexcept { return !(lhs == rhs); }
+ constexpr friend bool operator!=(uint128 lhs, boost::uint128_type rhs) noexcept { return !(lhs == rhs); }
+ #endif
+
+ constexpr friend bool operator!=(uint128 lhs, uint128 rhs) noexcept;
+
+ #undef INTEGER_OPERATOR_NOTEQUAL
+
+ // Less than
+ #define INTEGER_OPERATOR_LESS_THAN(expr) constexpr friend bool operator<(uint128 lhs, expr rhs) noexcept { return lhs.high == 0U && rhs > 0 && lhs.low < static_cast<std::uint64_t>(rhs); } // NOLINT
+ #define UNSIGNED_INTEGER_OPERATOR_LESS_THAN(expr) constexpr friend bool operator<(uint128 lhs, expr rhs) noexcept { return lhs.high == 0U && lhs.low < static_cast<std::uint64_t>(rhs); } // NOLINT
+
+ INTEGER_OPERATOR_LESS_THAN(char) // NOLINT
+ INTEGER_OPERATOR_LESS_THAN(signed char) // NOLINT
+ INTEGER_OPERATOR_LESS_THAN(short) // NOLINT
+ INTEGER_OPERATOR_LESS_THAN(int) // NOLINT
+ INTEGER_OPERATOR_LESS_THAN(long) // NOLINT
+ INTEGER_OPERATOR_LESS_THAN(long long) // NOLINT
+ UNSIGNED_INTEGER_OPERATOR_LESS_THAN(unsigned char) // NOLINT
+ UNSIGNED_INTEGER_OPERATOR_LESS_THAN(unsigned short) // NOLINT
+ UNSIGNED_INTEGER_OPERATOR_LESS_THAN(unsigned) // NOLINT
+ UNSIGNED_INTEGER_OPERATOR_LESS_THAN(unsigned long) // NOLINT
+ UNSIGNED_INTEGER_OPERATOR_LESS_THAN(unsigned long long) // NOLINT
+
+ #ifdef BOOST_CHARCONV_HAS_INT128
+ BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator<(uint128 lhs, boost::int128_type rhs) noexcept { return lhs < uint128(rhs); }
+ BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator<(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs < uint128(rhs); }
+ #endif
+
+ BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator<(uint128 lhs, uint128 rhs) noexcept;
+
+ #undef INTEGER_OPERATOR_LESS_THAN
+ #undef UNSIGNED_INTEGER_OPERATOR_LESS_THAN
+
+ // Less than or equal to
+ #define INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(expr) constexpr friend bool operator<=(uint128 lhs, expr rhs) noexcept { return lhs.high == 0U && rhs >= 0 && lhs.low <= static_cast<std::uint64_t>(rhs); } // NOLINT
+ #define UNSIGNED_INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(expr) constexpr friend bool operator<=(uint128 lhs, expr rhs) noexcept { return lhs.high == 0U && lhs.low <= static_cast<std::uint64_t>(rhs); } // NOLINT
+
+ INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(char) // NOLINT
+ INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(signed char) // NOLINT
+ INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(short) // NOLINT
+ INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(int) // NOLINT
+ INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(long) // NOLINT
+ INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(long long) // NOLINT
+ UNSIGNED_INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(unsigned char) // NOLINT
+ UNSIGNED_INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(unsigned short) // NOLINT
+ UNSIGNED_INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(unsigned) // NOLINT
+ UNSIGNED_INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(unsigned long) // NOLINT
+ UNSIGNED_INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(unsigned long long) // NOLINT
+
+ #ifdef BOOST_CHARCONV_HAS_INT128
+ BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator<=(uint128 lhs, boost::int128_type rhs) noexcept { return lhs <= uint128(rhs); }
+ BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator<=(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs <= uint128(rhs); }
+ #endif
+
+ BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator<=(uint128 lhs, uint128 rhs) noexcept;
+
+ #undef INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO
+ #undef UNSIGNED_INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO
+
+ // Greater than
+ #define INTEGER_OPERATOR_GREATER_THAN(expr) constexpr friend bool operator>(uint128 lhs, expr rhs) noexcept { return lhs.high > 0U || rhs < 0 || lhs.low > static_cast<std::uint64_t>(rhs); } // NOLINT
+ #define UNSIGNED_INTEGER_OPERATOR_GREATER_THAN(expr) constexpr friend bool operator>(uint128 lhs, expr rhs) noexcept { return lhs.high > 0U || lhs.low > static_cast<std::uint64_t>(rhs); } // NOLINT
+
+ INTEGER_OPERATOR_GREATER_THAN(char) // NOLINT
+ INTEGER_OPERATOR_GREATER_THAN(signed char) // NOLINT
+ INTEGER_OPERATOR_GREATER_THAN(short) // NOLINT
+ INTEGER_OPERATOR_GREATER_THAN(int) // NOLINT
+ INTEGER_OPERATOR_GREATER_THAN(long) // NOLINT
+ INTEGER_OPERATOR_GREATER_THAN(long long) // NOLINT
+ UNSIGNED_INTEGER_OPERATOR_GREATER_THAN(unsigned char) // NOLINT
+ UNSIGNED_INTEGER_OPERATOR_GREATER_THAN(unsigned short) // NOLINT
+ UNSIGNED_INTEGER_OPERATOR_GREATER_THAN(unsigned) // NOLINT
+ UNSIGNED_INTEGER_OPERATOR_GREATER_THAN(unsigned long) // NOLINT
+ UNSIGNED_INTEGER_OPERATOR_GREATER_THAN(unsigned long long) // NOLINT
+
+ #ifdef BOOST_CHARCONV_HAS_INT128
+ BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator>(uint128 lhs, boost::int128_type rhs) noexcept { return lhs > uint128(rhs); }
+ BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator>(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs > uint128(rhs); }
+ #endif
+
+ BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator>(uint128 lhs, uint128 rhs) noexcept;
+
+ #undef INTEGER_OPERATOR_GREATER_THAN
+ #undef UNSIGNED_INTEGER_OPERATOR_GREATER_THAN
+
+ // Greater than or equal to
+ #define INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(expr) constexpr friend bool operator>=(uint128 lhs, expr rhs) noexcept { return lhs.high > 0U || rhs < 0 || lhs.low >= static_cast<std::uint64_t>(rhs); } // NOLINT
+ #define UNSIGNED_INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(expr) constexpr friend bool operator>=(uint128 lhs, expr rhs) noexcept { return lhs.high > 0U || lhs.low >= static_cast<std::uint64_t>(rhs); } // NOLINT
+
+ INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(char) // NOLINT
+ INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(signed char) // NOLINT
+ INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(short) // NOLINT
+ INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(int) // NOLINT
+ INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(long) // NOLINT
+ INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(long long) // NOLINT
+ UNSIGNED_INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(unsigned char) // NOLINT
+ UNSIGNED_INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(unsigned short) // NOLINT
+ UNSIGNED_INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(unsigned) // NOLINT
+ UNSIGNED_INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(unsigned long) // NOLINT
+ UNSIGNED_INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(unsigned long long) // NOLINT
+
+ #ifdef BOOST_CHARCONV_HAS_INT128
+ BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator>=(uint128 lhs, boost::int128_type rhs) noexcept { return lhs >= uint128(rhs); }
+ BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator>=(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs >= uint128(rhs); }
+ #endif
+
+ BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator>=(uint128 lhs, uint128 rhs) noexcept;
+
+ #undef INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO
+ #undef UNSIGNED_INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO
+
+ // Binary Operators
+
+ // Not
+ constexpr friend uint128 operator~(uint128 v) noexcept;
+
+ // Or
+ #define INTEGER_BINARY_OPERATOR_OR(expr) constexpr friend uint128 operator|(uint128 lhs, expr rhs) noexcept { return {lhs.high, lhs.low | static_cast<std::uint64_t>(rhs)}; } // NOLINT
+
+ INTEGER_BINARY_OPERATOR_OR(char) // NOLINT
+ INTEGER_BINARY_OPERATOR_OR(signed char) // NOLINT
+ INTEGER_BINARY_OPERATOR_OR(short) // NOLINT
+ INTEGER_BINARY_OPERATOR_OR(int) // NOLINT
+ INTEGER_BINARY_OPERATOR_OR(long) // NOLINT
+ INTEGER_BINARY_OPERATOR_OR(long long) // NOLINT
+ INTEGER_BINARY_OPERATOR_OR(unsigned char) // NOLINT
+ INTEGER_BINARY_OPERATOR_OR(unsigned short) // NOLINT
+ INTEGER_BINARY_OPERATOR_OR(unsigned) // NOLINT
+ INTEGER_BINARY_OPERATOR_OR(unsigned long) // NOLINT
+ INTEGER_BINARY_OPERATOR_OR(unsigned long long) // NOLINT
+
+ #ifdef BOOST_CHARCONV_HAS_INT128
+ constexpr friend uint128 operator|(uint128 lhs, boost::int128_type rhs) noexcept { return lhs | uint128(rhs); }
+ constexpr friend uint128 operator|(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs | uint128(rhs); }
+ #endif
+
+ constexpr friend uint128 operator|(uint128 lhs, uint128 rhs) noexcept;
+
+ BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator|=(uint128 v) noexcept;
+
+ #undef INTEGER_BINARY_OPERATOR_OR
+
+ // And
+ #define INTEGER_BINARY_OPERATOR_AND(expr) constexpr friend uint128 operator&(uint128 lhs, expr rhs) noexcept { return {lhs.high, lhs.low & static_cast<std::uint64_t>(rhs)}; } // NOLINT
+
+ INTEGER_BINARY_OPERATOR_AND(char) // NOLINT
+ INTEGER_BINARY_OPERATOR_AND(signed char) // NOLINT
+ INTEGER_BINARY_OPERATOR_AND(short) // NOLINT
+ INTEGER_BINARY_OPERATOR_AND(int) // NOLINT
+ INTEGER_BINARY_OPERATOR_AND(long) // NOLINT
+ INTEGER_BINARY_OPERATOR_AND(long long) // NOLINT
+ INTEGER_BINARY_OPERATOR_AND(unsigned char) // NOLINT
+ INTEGER_BINARY_OPERATOR_AND(unsigned short) // NOLINT
+ INTEGER_BINARY_OPERATOR_AND(unsigned) // NOLINT
+ INTEGER_BINARY_OPERATOR_AND(unsigned long) // NOLINT
+ INTEGER_BINARY_OPERATOR_AND(unsigned long long) // NOLINT
+
+ #ifdef BOOST_CHARCONV_HAS_INT128
+ constexpr friend uint128 operator&(uint128 lhs, boost::int128_type rhs) noexcept { return lhs & uint128(rhs); }
+ constexpr friend uint128 operator&(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs & uint128(rhs); }
+ #endif
+
+ constexpr friend uint128 operator&(uint128 lhs, uint128 rhs) noexcept;
+
+ BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator&=(uint128 v) noexcept;
+
+ #undef INTEGER_BINARY_OPERATOR_AND
+
+ // Xor
+ #define INTEGER_BINARY_OPERATOR_XOR(expr) constexpr friend uint128 operator^(uint128 lhs, expr rhs) noexcept { return {lhs.high, lhs.low ^ static_cast<std::uint64_t>(rhs)}; } // NOLINT
+
+ INTEGER_BINARY_OPERATOR_XOR(char) // NOLINT
+ INTEGER_BINARY_OPERATOR_XOR(signed char) // NOLINT
+ INTEGER_BINARY_OPERATOR_XOR(short) // NOLINT
+ INTEGER_BINARY_OPERATOR_XOR(int) // NOLINT
+ INTEGER_BINARY_OPERATOR_XOR(long) // NOLINT
+ INTEGER_BINARY_OPERATOR_XOR(long long) // NOLINT
+ INTEGER_BINARY_OPERATOR_XOR(unsigned char) // NOLINT
+ INTEGER_BINARY_OPERATOR_XOR(unsigned short) // NOLINT
+ INTEGER_BINARY_OPERATOR_XOR(unsigned) // NOLINT
+ INTEGER_BINARY_OPERATOR_XOR(unsigned long) // NOLINT
+ INTEGER_BINARY_OPERATOR_XOR(unsigned long long) // NOLINT
+
+ #ifdef BOOST_CHARCONV_HAS_INT128
+ constexpr friend uint128 operator^(uint128 lhs, boost::int128_type rhs) noexcept { return lhs ^ uint128(rhs); }
+ constexpr friend uint128 operator^(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs ^ uint128(rhs); }
+ #endif
+
+ constexpr friend uint128 operator^(uint128 lhs, uint128 rhs) noexcept;
+
+ BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator^=(uint128 v) noexcept;
+
+ #undef INTEGER_BINARY_OPERATOR_XOR
+
+ // Left shift
+ #define INTEGER_BINARY_OPERATOR_LEFT_SHIFT(expr) \
+ BOOST_CHARCONV_CXX14_CONSTEXPR friend uint128 operator<<(uint128 lhs, expr rhs) noexcept \
+ { \
+ if (rhs >= 64) \
+ { \
+ return {lhs.low << (rhs - 64), 0}; \
+ } \
+ else if (rhs == 0) \
+ { \
+ return lhs; \
+ } \
+ \
+ return {(lhs.high << rhs) | (lhs.low >> (64 - rhs)), lhs.low << rhs}; \
+ } // NOLINT
+
+ INTEGER_BINARY_OPERATOR_LEFT_SHIFT(char) // NOLINT
+ INTEGER_BINARY_OPERATOR_LEFT_SHIFT(signed char) // NOLINT
+ INTEGER_BINARY_OPERATOR_LEFT_SHIFT(short) // NOLINT
+ INTEGER_BINARY_OPERATOR_LEFT_SHIFT(int) // NOLINT
+ INTEGER_BINARY_OPERATOR_LEFT_SHIFT(long) // NOLINT
+ INTEGER_BINARY_OPERATOR_LEFT_SHIFT(long long) // NOLINT
+ INTEGER_BINARY_OPERATOR_LEFT_SHIFT(unsigned char) // NOLINT
+ INTEGER_BINARY_OPERATOR_LEFT_SHIFT(unsigned short) // NOLINT
+ INTEGER_BINARY_OPERATOR_LEFT_SHIFT(unsigned) // NOLINT
+ INTEGER_BINARY_OPERATOR_LEFT_SHIFT(unsigned long) // NOLINT
+ INTEGER_BINARY_OPERATOR_LEFT_SHIFT(unsigned long long) // NOLINT
+
+ #define INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(expr) \
+ BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator<<=(expr amount) noexcept \
+ { \
+ *this = *this << amount; \
+ return *this; \
+ } // NOLINT
+
+ INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(char) // NOLINT
+ INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(signed char) // NOLINT
+ INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(short) // NOLINT
+ INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(int) // NOLINT
+ INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(long) // NOLINT
+ INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(long long) // NOLINT
+ INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(unsigned char) // NOLINT
+ INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(unsigned short) // NOLINT
+ INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(unsigned) // NOLINT
+ INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(unsigned long) // NOLINT
+ INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(unsigned long long) // NOLINT
+
+ #undef INTEGER_BINARY_OPERATOR_LEFT_SHIFT
+ #undef INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT
+
+ // Right Shift
+ #define INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(expr) \
+ BOOST_CHARCONV_CXX14_CONSTEXPR friend uint128 operator>>(uint128 lhs, expr amount) noexcept \
+ { \
+ if (amount >= 64) \
+ { \
+ return {0, lhs.high >> (amount - 64)}; \
+ } \
+ else if (amount == 0) \
+ { \
+ return lhs; \
+ } \
+ \
+ return {lhs.high >> amount, (lhs.low >> amount) | (lhs.high << (64 - amount))}; \
+ } // NOLINT
+
+ INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(char) // NOLINT
+ INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(signed char) // NOLINT
+ INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(short) // NOLINT
+ INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(int) // NOLINT
+ INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(long) // NOLINT
+ INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(long long) // NOLINT
+ INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(unsigned char) // NOLINT
+ INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(unsigned short) // NOLINT
+ INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(unsigned) // NOLINT
+ INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(unsigned long) // NOLINT
+ INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(unsigned long long) // NOLINT
+
+ #define INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(expr) \
+ BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator>>=(expr amount) noexcept \
+ { \
+ *this = *this >> amount; \
+ return *this; \
+ } // NOLINT
+
+ INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(char) // NOLINT
+ INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(signed char) // NOLINT
+ INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(short) // NOLINT
+ INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(int) // NOLINT
+ INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(long) // NOLINT
+ INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(long long) // NOLINT
+ INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(unsigned char) // NOLINT
+ INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(unsigned short) // NOLINT
+ INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(unsigned) // NOLINT
+ INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(unsigned long) // NOLINT
+ INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(unsigned long long) // NOLINT
+
+ #undef INTEGER_BINARY_OPERATOR_RIGHT_SHIFT
+ #undef INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT
+
+ // Arithmetic operators (Add, sub, mul, div, mod)
+ inline uint128 &operator+=(std::uint64_t n) noexcept;
+
+ BOOST_CHARCONV_CXX14_CONSTEXPR friend uint128 operator+(uint128 lhs, uint128 rhs) noexcept;
+
+ BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator+=(uint128 v) noexcept;
+
+ BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator++() noexcept;
+
+ BOOST_CHARCONV_CXX14_CONSTEXPR const uint128 operator++(int) noexcept;
+
+ BOOST_CHARCONV_CXX14_CONSTEXPR friend uint128 operator-(uint128 lhs, uint128 rhs) noexcept;
+
+ BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator-=(uint128 v) noexcept;
+
+ BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator--() noexcept;
+
+ BOOST_CHARCONV_CXX14_CONSTEXPR const uint128 operator--(int) noexcept;
+
+ BOOST_CHARCONV_CXX14_CONSTEXPR friend uint128 operator*(uint128 lhs, uint128 rhs) noexcept;
+
+ BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator*=(uint128 v) noexcept;
+
+ BOOST_CHARCONV_CXX14_CONSTEXPR friend uint128 operator/(uint128 lhs, uint128 rhs) noexcept;
+
+ BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator/=(uint128 v) noexcept;
+
+ BOOST_CHARCONV_CXX14_CONSTEXPR friend uint128 operator%(uint128 lhs, uint128 rhs) noexcept;
+
+ BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator%=(uint128 v) noexcept;
+
+private:
+ BOOST_CHARCONV_CXX14_CONSTEXPR friend int high_bit(uint128 v) noexcept;
+
+ BOOST_CHARCONV_CXX14_CONSTEXPR friend void
+ div_impl(uint128 lhs, uint128 rhs, uint128 &quotient, uint128 &remainder) noexcept;
+};
+
+constexpr uint128 operator-(uint128 val) noexcept
+{
+ return {~val.high + static_cast<std::uint64_t>(val.low == 0), ~val.low + 1};
+}
+
+constexpr uint128 operator+(uint128 val) noexcept
+{
+ return val;
+}
+
+BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator=(const uint128& v) noexcept // NOLINT : User defined for older compilers
+{
+ low = v.low;
+ high = v.high;
+ return *this;
+}
+
+constexpr bool operator==(uint128 lhs, uint128 rhs) noexcept
+{
+ return lhs.high == rhs.high && lhs.low == rhs.low;
+}
+
+constexpr bool operator!=(uint128 lhs, uint128 rhs) noexcept
+{
+ return !(lhs == rhs);
+}
+
+BOOST_CHARCONV_CXX14_CONSTEXPR bool operator<(uint128 lhs, uint128 rhs) noexcept
+{
+ if (lhs.high == rhs.high)
+ {
+ return lhs.low < rhs.low;
+ }
+
+ return lhs.high < rhs.high;
+}
+
+BOOST_CHARCONV_CXX14_CONSTEXPR bool operator<=(uint128 lhs, uint128 rhs) noexcept
+{
+ return !(rhs < lhs);
+}
+
+BOOST_CHARCONV_CXX14_CONSTEXPR bool operator>(uint128 lhs, uint128 rhs) noexcept
+{
+ return rhs < lhs;
+}
+
+BOOST_CHARCONV_CXX14_CONSTEXPR bool operator>=(uint128 lhs, uint128 rhs) noexcept
+{
+ return !(lhs < rhs);
+}
+
+constexpr uint128 operator~(uint128 v) noexcept
+{
+ return {~v.high, ~v.low};
+}
+
+constexpr uint128 operator|(uint128 lhs, uint128 rhs) noexcept
+{
+ return {lhs.high | rhs.high, lhs.low | rhs.low};
+}
+
+BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator|=(uint128 v) noexcept
+{
+ *this = *this | v;
+ return *this;
+}
+
+constexpr uint128 operator&(uint128 lhs, uint128 rhs) noexcept
+{
+ return {lhs.high & rhs.high, lhs.low & rhs.low};
+}
+
+BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator&=(uint128 v) noexcept
+{
+ *this = *this & v;
+ return *this;
+}
+
+constexpr uint128 operator^(uint128 lhs, uint128 rhs) noexcept
+{
+ return {lhs.high ^ rhs.high, lhs.low ^ rhs.low};
+}
+
+BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator^=(uint128 v) noexcept
+{
+ *this = *this ^ v;
+ return *this;
+}
+
+inline uint128 &uint128::operator+=(std::uint64_t n) noexcept
+{
+ #if BOOST_CHARCONV_HAS_BUILTIN(__builtin_addcll)
+
+ unsigned long long carry {};
+ low = __builtin_addcll(low, n, 0, &carry);
+ high = __builtin_addcll(high, 0, carry, &carry);
+
+ #elif BOOST_CHARCONV_HAS_BUILTIN(__builtin_ia32_addcarryx_u64)
+
+ unsigned long long result {};
+ auto carry = __builtin_ia32_addcarryx_u64(0, low, n, &result);
+ low = result;
+ __builtin_ia32_addcarryx_u64(carry, high, 0, &result);
+ high = result;
+
+ #elif defined(BOOST_MSVC) && defined(_M_X64)
+
+ auto carry = _addcarry_u64(0, low, n, &low);
+ _addcarry_u64(carry, high, 0, &high);
+
+ #else
+
+ auto sum = low + n;
+ high += (sum < low ? 1 : 0);
+ low = sum;
+
+ #endif
+ return *this;
+}
+
+BOOST_CHARCONV_CXX14_CONSTEXPR uint128 operator+(uint128 lhs, uint128 rhs) noexcept
+{
+ const uint128 temp = {lhs.high + rhs.high, lhs.low + rhs.low};
+
+ // Need to carry a bit into rhs
+ if (temp.low < lhs.low)
+ {
+ return {temp.high + 1, temp.low};
+ }
+
+ return temp;
+}
+
+BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator+=(uint128 v) noexcept
+{
+ *this = *this + v;
+ return *this;
+}
+
+BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator++() noexcept
+{
+ if (this->low == UINT64_MAX)
+ {
+ this->low = 0;
+ ++this->high;
+ }
+ else
+ {
+ ++this->low;
+ }
+
+ return *this;
+}
+
+BOOST_CHARCONV_CXX14_CONSTEXPR const uint128 uint128::operator++(int) noexcept
+{
+ return ++(*this);
+}
+
+BOOST_CHARCONV_CXX14_CONSTEXPR uint128 operator-(uint128 lhs, uint128 rhs) noexcept
+{
+ const uint128 temp {lhs.high - rhs.high, lhs.low - rhs.low};
+
+ // Check for carry
+ if (lhs.low < rhs.low)
+ {
+ return {temp.high - 1, temp.low};
+ }
+
+ return temp;
+}
+
+BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator-=(uint128 v) noexcept
+{
+ *this = *this - v;
+ return *this;
+}
+
+BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator--() noexcept
+{
+ if (this->low == 0)
+ {
+ this->low = UINT64_MAX;
+ --this->high;
+ }
+ else // NOLINT
+ {
+ --this->low;
+ }
+
+ return *this;
+}
+
+BOOST_CHARCONV_CXX14_CONSTEXPR const uint128 uint128::operator--(int) noexcept
+{
+ return --(*this);
+}
+BOOST_CHARCONV_CXX14_CONSTEXPR uint128 operator*(uint128 lhs, uint128 rhs) noexcept
+{
+ const auto a = static_cast<std::uint64_t>(lhs.low >> 32);
+ const auto b = static_cast<std::uint64_t>(lhs.low & UINT32_MAX);
+ const auto c = static_cast<std::uint64_t>(rhs.low >> 32);
+ const auto d = static_cast<std::uint64_t>(rhs.low & UINT32_MAX);
+
+ uint128 result { lhs.high * rhs.low + lhs.low * rhs.high + a * c, b * d };
+ result += uint128(a * d) << 32;
+ result += uint128(b * c) << 32;
+ return result;
+}
+
+BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator*=(uint128 v) noexcept
+{
+ *this = *this * v;
+ return *this;
+}
+
+BOOST_CHARCONV_CXX14_CONSTEXPR int high_bit(uint128 v) noexcept
+{
+ if (v.high != 0)
+ {
+ return 127 - boost::core::countl_zero(v.high);
+ }
+ else if (v.low != 0)
+ {
+ return 63 - boost::core::countl_zero(v.low);
+ }
+
+ return 0;
+}
+
+// See: https://stackoverflow.com/questions/5386377/division-without-using
+BOOST_CHARCONV_CXX14_CONSTEXPR void div_impl(uint128 lhs, uint128 rhs, uint128& quotient, uint128& remainder) noexcept
+{
+ constexpr uint128 one {0, 1};
+
+ if (rhs > lhs)
+ {
+ quotient = 0U;
+ remainder = 0U;
+ }
+ else if (lhs == rhs)
+ {
+ quotient = 1U;
+ remainder = 0U;
+ }
+
+ uint128 denom = rhs;
+ quotient = 0U;
+
+ std::int32_t shift = high_bit(lhs) - high_bit(rhs);
+ if (shift < 0)
+ {
+ shift = 32 - shift;
+ }
+ denom <<= shift;
+
+ for (int i = 0; i <= shift; ++i)
+ {
+ quotient <<= 1;
+ if (lhs >= denom)
+ {
+ lhs -= denom;
+ quotient |= one;
+ }
+ denom >>= 1;
+ }
+
+ remainder = lhs;
+}
+
+BOOST_CHARCONV_CXX14_CONSTEXPR uint128 operator/(uint128 lhs, uint128 rhs) noexcept
+{
+ uint128 quotient {0, 0};
+ uint128 remainder {0, 0};
+ div_impl(lhs, rhs, quotient, remainder);
+
+ return quotient;
+}
+
+BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator/=(uint128 v) noexcept
+{
+ *this = *this / v;
+ return *this;
+}
+
+BOOST_CHARCONV_CXX14_CONSTEXPR uint128 operator%(uint128 lhs, uint128 rhs) noexcept
+{
+ uint128 quotient {0, 0};
+ uint128 remainder {0, 0};
+ div_impl(lhs, rhs, quotient, remainder);
+
+ return remainder;
+}
+
+BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator%=(uint128 v) noexcept
+{
+ *this = *this % v;
+ return *this;
+}
+
+static inline std::uint64_t umul64(std::uint32_t x, std::uint32_t y) noexcept
+{
+ // __emulu is not available on ARM https://learn.microsoft.com/en-us/cpp/intrinsics/emul-emulu?view=msvc-170
+ #if defined(BOOST_CHARCONV_HAS_MSVC_32BIT_INTRINSICS) && !defined(_M_ARM)
+
+ return __emulu(x, y);
+
+ #else
+
+ return x * static_cast<std::uint64_t>(y);
+
+ #endif
+}
+
+// Get 128-bit result of multiplication of two 64-bit unsigned integers.
+BOOST_CHARCONV_SAFEBUFFERS inline uint128 umul128(std::uint64_t x, std::uint64_t y) noexcept
+{
+ #if defined(BOOST_CHARCONV_HAS_INT128)
+
+ auto result = static_cast<boost::uint128_type>(x) * static_cast<boost::uint128_type>(y);
+ return {static_cast<std::uint64_t>(result >> 64), static_cast<std::uint64_t>(result)};
+
+ // _umul128 is x64 only https://learn.microsoft.com/en-us/cpp/intrinsics/umul128?view=msvc-170
+ #elif defined(BOOST_CHARCONV_HAS_MSVC_64BIT_INTRINSICS) && !defined(_M_ARM64)
+
+ unsigned long long high;
+ std::uint64_t low = _umul128(x, y, &high);
+ return {static_cast<std::uint64_t>(high), low};
+
+ // https://developer.arm.com/documentation/dui0802/a/A64-General-Instructions/UMULH
+ #elif defined(_M_ARM64) && !defined(__MINGW32__)
+
+ std::uint64_t high = __umulh(x, y);
+ std::uint64_t low = x * y;
+ return {high, low};
+
+ #else
+
+ auto a = static_cast<std::uint32_t>(x >> 32);
+ auto b = static_cast<std::uint32_t>(x);
+ auto c = static_cast<std::uint32_t>(y >> 32);
+ auto d = static_cast<std::uint32_t>(y);
+
+ auto ac = umul64(a, c);
+ auto bc = umul64(b, c);
+ auto ad = umul64(a, d);
+ auto bd = umul64(b, d);
+
+ auto intermediate = (bd >> 32) + static_cast<std::uint32_t>(ad) + static_cast<std::uint32_t>(bc);
+
+ return {ac + (intermediate >> 32) + (ad >> 32) + (bc >> 32),
+ (intermediate << 32) + static_cast<std::uint32_t>(bd)};
+
+ #endif
+}
+
+BOOST_CHARCONV_SAFEBUFFERS inline std::uint64_t umul128_upper64(std::uint64_t x, std::uint64_t y) noexcept
+{
+ #if defined(BOOST_CHARCONV_HAS_INT128)
+
+ auto result = static_cast<boost::uint128_type>(x) * static_cast<boost::uint128_type>(y);
+ return static_cast<std::uint64_t>(result >> 64);
+
+ #elif defined(BOOST_CHARCONV_HAS_MSVC_64BIT_INTRINSICS)
+
+ return __umulh(x, y);
+
+ #else
+
+ auto a = static_cast<std::uint32_t>(x >> 32);
+ auto b = static_cast<std::uint32_t>(x);
+ auto c = static_cast<std::uint32_t>(y >> 32);
+ auto d = static_cast<std::uint32_t>(y);
+
+ auto ac = umul64(a, c);
+ auto bc = umul64(b, c);
+ auto ad = umul64(a, d);
+ auto bd = umul64(b, d);
+
+ auto intermediate = (bd >> 32) + static_cast<std::uint32_t>(ad) + static_cast<std::uint32_t>(bc);
+
+ return ac + (intermediate >> 32) + (ad >> 32) + (bc >> 32);
+
+ #endif
+}
+
+// Get upper 128-bits of multiplication of a 64-bit unsigned integer and a 128-bit
+// unsigned integer.
+BOOST_CHARCONV_SAFEBUFFERS inline uint128 umul192_upper128(std::uint64_t x, uint128 y) noexcept
+{
+ auto r = umul128(x, y.high);
+ r += umul128_upper64(x, y.low);
+ return r;
+}
+
+// Get upper 64-bits of multiplication of a 32-bit unsigned integer and a 64-bit
+// unsigned integer.
+inline std::uint64_t umul96_upper64(std::uint32_t x, std::uint64_t y) noexcept
+{
+ #if defined(BOOST_CHARCONV_HAS_INT128) || defined(BOOST_CHARCONV_HAS_MSVC_64BIT_INTRINSICS)
+
+ return umul128_upper64(static_cast<std::uint64_t>(x) << 32, y);
+
+ #else
+
+ auto yh = static_cast<std::uint32_t>(y >> 32);
+ auto yl = static_cast<std::uint32_t>(y);
+
+ auto xyh = umul64(x, yh);
+ auto xyl = umul64(x, yl);
+
+ return xyh + (xyl >> 32);
+
+ #endif
+}
+
+// Get lower 128-bits of multiplication of a 64-bit unsigned integer and a 128-bit
+// unsigned integer.
+BOOST_CHARCONV_SAFEBUFFERS inline uint128 umul192_lower128(std::uint64_t x, uint128 y) noexcept
+{
+ auto high = x * y.high;
+ auto highlow = umul128(x, y.low);
+ return {high + highlow.high, highlow.low};
+}
+
+// Get lower 64-bits of multiplication of a 32-bit unsigned integer and a 64-bit
+// unsigned integer.
+inline std::uint64_t umul96_lower64(std::uint32_t x, std::uint64_t y) noexcept
+{
+ return x * y;
+}
+
+}}} // Namespaces
+
+// Non-standard libraries may add specializations for library-provided types
+namespace std {
+
+template <>
+struct numeric_limits<boost::charconv::detail::uint128>
+{
+ // Member constants
+ BOOST_ATTRIBUTE_UNUSED static constexpr bool is_specialized = true;
+ BOOST_ATTRIBUTE_UNUSED static constexpr bool is_signed = false;
+ BOOST_ATTRIBUTE_UNUSED static constexpr bool is_integer = true;
+ BOOST_ATTRIBUTE_UNUSED static constexpr bool is_exact = true;
+ BOOST_ATTRIBUTE_UNUSED static constexpr bool has_infinity = false;
+ BOOST_ATTRIBUTE_UNUSED static constexpr bool has_quiet_NaN = false;
+ BOOST_ATTRIBUTE_UNUSED static constexpr bool has_signaling_NaN = false;
+ BOOST_ATTRIBUTE_UNUSED static constexpr std::float_round_style round_style = std::round_toward_zero;
+ BOOST_ATTRIBUTE_UNUSED static constexpr bool is_iec559 = false;
+ BOOST_ATTRIBUTE_UNUSED static constexpr bool is_bounded = true;
+ BOOST_ATTRIBUTE_UNUSED static constexpr bool is_modulo = true;
+ BOOST_ATTRIBUTE_UNUSED static constexpr int digits = 128;
+ BOOST_ATTRIBUTE_UNUSED static constexpr int digits10 = 38;
+ BOOST_ATTRIBUTE_UNUSED static constexpr int max_digits10 = 0;
+ BOOST_ATTRIBUTE_UNUSED static constexpr int radix = 2;
+ BOOST_ATTRIBUTE_UNUSED static constexpr int min_exponent = 0;
+ BOOST_ATTRIBUTE_UNUSED static constexpr int min_exponent10 = 0;
+ BOOST_ATTRIBUTE_UNUSED static constexpr int max_exponent = 0;
+ BOOST_ATTRIBUTE_UNUSED static constexpr int max_exponent10 = 0;
+ BOOST_ATTRIBUTE_UNUSED static constexpr bool traps = std::numeric_limits<std::uint64_t>::traps;
+ BOOST_ATTRIBUTE_UNUSED static constexpr bool tinyness_before = false;
+
+ // Member functions
+ BOOST_ATTRIBUTE_UNUSED static constexpr boost::charconv::detail::uint128 (min)() { return 0; }
+ BOOST_ATTRIBUTE_UNUSED static constexpr boost::charconv::detail::uint128 lowest() { return 0; }
+ BOOST_ATTRIBUTE_UNUSED static constexpr boost::charconv::detail::uint128 (max)() { return {UINT64_MAX, UINT64_MAX}; }
+ BOOST_ATTRIBUTE_UNUSED static constexpr boost::charconv::detail::uint128 epsilon() { return 0; }
+ BOOST_ATTRIBUTE_UNUSED static constexpr boost::charconv::detail::uint128 round_error() { return 0; }
+ BOOST_ATTRIBUTE_UNUSED static constexpr boost::charconv::detail::uint128 infinity() { return 0; }
+ BOOST_ATTRIBUTE_UNUSED static constexpr boost::charconv::detail::uint128 quiet_NaN() { return 0; }
+ BOOST_ATTRIBUTE_UNUSED static constexpr boost::charconv::detail::uint128 signaling_NaN() { return 0; }
+ BOOST_ATTRIBUTE_UNUSED static constexpr boost::charconv::detail::uint128 (denorm_min)() { return 0; }
+};
+
+} // Namespace std
+
+#endif // BOOST_CHARCONV_DETAIL_EMULATED128_HPP
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/fallback_routines.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/fallback_routines.hpp
new file mode 100644
index 00000000000..94f87b82b9e
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/fallback_routines.hpp
@@ -0,0 +1,245 @@
+// Copyright 2024 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_FALLBACK_ROUTINES_HPP
+#define BOOST_FALLBACK_ROUTINES_HPP
+
+#include <boost/charconv/detail/to_chars_integer_impl.hpp>
+#include <boost/charconv/detail/dragonbox/floff.hpp>
+#include <boost/charconv/detail/config.hpp>
+#include <boost/charconv/detail/from_chars_result.hpp>
+#include <boost/charconv/chars_format.hpp>
+#include <system_error>
+#include <type_traits>
+#include <locale>
+#include <clocale>
+#include <cstring>
+#include <cstdio>
+
+namespace boost {
+namespace charconv {
+namespace detail {
+
+template <typename T>
+inline int print_val(char* first, std::size_t size, char* format, T value) noexcept
+{
+ return std::snprintf(first, size, format, value);
+}
+
+template <typename T>
+to_chars_result to_chars_printf_impl(char* first, char* last, T value, chars_format fmt, int precision)
+{
+ // v % + . + num_digits(INT_MAX) + specifier + null terminator
+ // 1 + 1 + 10 + 1 + 1
+ char format[14] {};
+ std::memcpy(format, "%", 1); // NOLINT : No null terminator is purposeful
+ std::size_t pos = 1;
+
+ // precision of -1 is unspecified
+ if (precision != -1 && fmt != chars_format::fixed)
+ {
+ format[pos] = '.';
+ ++pos;
+ const auto unsigned_precision = static_cast<std::uint32_t>(precision);
+ if (unsigned_precision < 10)
+ {
+ boost::charconv::detail::print_1_digit(unsigned_precision, format + pos);
+ ++pos;
+ }
+ else if (unsigned_precision < 100)
+ {
+ boost::charconv::detail::print_2_digits(unsigned_precision, format + pos);
+ pos += 2;
+ }
+ else
+ {
+ boost::charconv::detail::to_chars_int(format + pos, format + sizeof(format), precision);
+ pos = std::strlen(format);
+ }
+ }
+ else if (fmt == chars_format::fixed)
+ {
+ // Force 0 decimal places
+ std::memcpy(format + pos, ".0", 2); // NOLINT : No null terminator is purposeful
+ pos += 2;
+ }
+
+ // Add the type identifier
+ BOOST_CHARCONV_IF_CONSTEXPR (std::is_same<T, long double>::value)
+ {
+ format[pos] = 'L';
+ ++pos;
+ }
+
+ // Add the format character
+ switch (fmt)
+ {
+ case boost::charconv::chars_format::general:
+ format[pos] = 'g';
+ break;
+
+ case boost::charconv::chars_format::scientific:
+ format[pos] = 'e';
+ break;
+
+ case boost::charconv::chars_format::fixed:
+ format[pos] = 'f';
+ break;
+
+ case boost::charconv::chars_format::hex:
+ format[pos] = 'a';
+ break;
+ }
+
+ const auto rv = print_val(first, static_cast<std::size_t>(last - first), format, value);
+
+ if (rv <= 0)
+ {
+ return {last, static_cast<std::errc>(errno)};
+ }
+
+ return {first + rv, std::errc()};
+}
+
+#ifdef BOOST_MSVC
+# pragma warning(push)
+# pragma warning(disable: 4244) // Implict converion when BOOST_IF_CONSTEXPR expands to if
+#elif defined(__GNUC__) && __GNUC__ >= 5
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+# pragma GCC diagnostic ignored "-Wfloat-conversion"
+#elif defined(__clang__) && __clang_major__ > 7
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wimplicit-float-conversion"
+#elif defined(__clang__) && __clang_major__ <= 7
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wconversion"
+#endif
+
+// We know that the string is in the "C" locale because it would have previously passed through our parser.
+// Convert the string into the current locale so that the strto* family of functions
+// works correctly for the given locale.
+//
+// We are operating on our own copy of the buffer, so we are free to modify it.
+inline void convert_string_locale(char* buffer) noexcept
+{
+ const auto locale_decimal_point = *std::localeconv()->decimal_point;
+ if (locale_decimal_point != '.')
+ {
+ auto p = std::strchr(buffer, '.');
+ if (p != nullptr)
+ {
+ *p = locale_decimal_point;
+ }
+ }
+}
+
+template <typename T>
+from_chars_result from_chars_strtod_impl(const char* first, const char* last, T& value, char* buffer) noexcept
+{
+ // For strto(f/d)
+ // Floating point value corresponding to the contents of str on success.
+ // If the converted value falls out of range of corresponding return type, range error occurs and HUGE_VAL, HUGE_VALF or HUGE_VALL is returned.
+ // If no conversion can be performed, 0 is returned and *str_end is set to str.
+
+ std::memcpy(buffer, first, static_cast<std::size_t>(last - first));
+ buffer[last - first] = '\0';
+ convert_string_locale(buffer);
+
+ char* str_end;
+ T return_value {};
+ from_chars_result r {nullptr, std::errc()};
+
+ BOOST_IF_CONSTEXPR (std::is_same<T, float>::value)
+ {
+ return_value = std::strtof(buffer, &str_end);
+
+ #ifndef __INTEL_LLVM_COMPILER
+ if (return_value == HUGE_VALF)
+ #else
+ if (return_value >= (std::numeric_limits<T>::max)())
+ #endif
+ {
+ r = {last, std::errc::result_out_of_range};
+ }
+ }
+ else BOOST_IF_CONSTEXPR (std::is_same<T, double>::value)
+ {
+ return_value = std::strtod(buffer, &str_end);
+
+ #ifndef __INTEL_LLVM_COMPILER
+ if (return_value == HUGE_VAL)
+ #else
+ if (return_value >= (std::numeric_limits<T>::max)())
+ #endif
+ {
+ r = {last, std::errc::result_out_of_range};
+ }
+ }
+ else BOOST_IF_CONSTEXPR (std::is_same<T, long double>::value)
+ {
+ return_value = std::strtold(buffer, &str_end);
+
+ #ifndef __INTEL_LLVM_COMPILER
+ if (return_value == HUGE_VALL)
+ #else
+ if (return_value >= (std::numeric_limits<T>::max)())
+ #endif
+ {
+ r = {last, std::errc::result_out_of_range};
+ }
+ }
+
+ // Since this is a fallback routine we are safe to check for 0
+ if (return_value == 0 && str_end == last)
+ {
+ r = {first, std::errc::result_out_of_range};
+ }
+
+ if (r)
+ {
+ value = return_value;
+ r = {first + (str_end - buffer), std::errc()};
+ }
+
+ return r;
+}
+
+template <typename T>
+inline from_chars_result from_chars_strtod(const char* first, const char* last, T& value) noexcept
+{
+ if (last - first < 1024)
+ {
+ char buffer[1024];
+ return from_chars_strtod_impl(first, last, value, buffer);
+ }
+
+ // If the string to be parsed does not fit into the 1024 byte static buffer than we have to allocate a buffer.
+ // malloc is used here because it does not throw on allocation failure.
+
+ char* buffer = static_cast<char*>(std::malloc(static_cast<std::size_t>(last - first + 1)));
+ if (buffer == nullptr)
+ {
+ return {first, std::errc::not_enough_memory};
+ }
+
+ auto r = from_chars_strtod_impl(first, last, value, buffer);
+ std::free(buffer);
+
+ return r;
+}
+
+#ifdef BOOST_MSVC
+# pragma warning(pop)
+#elif defined(__GNUC__) && __GNUC__ >= 5
+# pragma GCC diagnostic pop
+#elif defined(__clang__)
+# pragma clang diagnostic pop
+#endif
+
+} //namespace detail
+} //namespace charconv
+} //namespace boost
+
+#endif //BOOST_FALLBACK_ROUTINES_HPP
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/ascii_number.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/ascii_number.hpp
new file mode 100644
index 00000000000..159a7661d02
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/ascii_number.hpp
@@ -0,0 +1,288 @@
+// Copyright 2020-2023 Daniel Lemire
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+//
+// Derivative of: https://github.com/fastfloat/fast_float
+
+#ifndef BOOST_CHARCONV_DETAIL_FASTFLOAT_ASCII_NUMBER_HPP
+#define BOOST_CHARCONV_DETAIL_FASTFLOAT_ASCII_NUMBER_HPP
+
+#include <boost/charconv/detail/fast_float/float_common.hpp>
+#include <cctype>
+#include <cstdint>
+#include <cstring>
+#include <iterator>
+
+namespace boost { namespace charconv { namespace detail { namespace fast_float {
+
+// Next function can be micro-optimized, but compilers are entirely
+// able to optimize it well.
+template <typename UC>
+BOOST_FORCEINLINE constexpr bool is_integer(UC c) noexcept {
+ return !(c > UC('9') || c < UC('0'));
+}
+
+BOOST_FORCEINLINE constexpr uint64_t byteswap(uint64_t val) {
+ return (val & 0xFF00000000000000) >> 56
+ | (val & 0x00FF000000000000) >> 40
+ | (val & 0x0000FF0000000000) >> 24
+ | (val & 0x000000FF00000000) >> 8
+ | (val & 0x00000000FF000000) << 8
+ | (val & 0x0000000000FF0000) << 24
+ | (val & 0x000000000000FF00) << 40
+ | (val & 0x00000000000000FF) << 56;
+}
+
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+uint64_t read_u64(const char *chars) {
+ if (cpp20_and_in_constexpr()) {
+ uint64_t val = 0;
+ for(int i = 0; i < 8; ++i) {
+ val |= uint64_t(*chars) << (i*8);
+ ++chars;
+ }
+ return val;
+ }
+ uint64_t val;
+ ::memcpy(&val, chars, sizeof(uint64_t));
+#if BOOST_CHARCONV_FASTFLOAT_IS_BIG_ENDIAN == 1
+ // Need to read as-if the number was in little-endian order.
+ val = byteswap(val);
+#endif
+ return val;
+}
+
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+void write_u64(uint8_t *chars, uint64_t val) {
+ if (cpp20_and_in_constexpr()) {
+ for(int i = 0; i < 8; ++i) {
+ *chars = uint8_t(val);
+ val >>= 8;
+ ++chars;
+ }
+ return;
+ }
+#if BOOST_CHARCONV_FASTFLOAT_IS_BIG_ENDIAN == 1
+ // Need to read as-if the number was in little-endian order.
+ val = byteswap(val);
+#endif
+ ::memcpy(chars, &val, sizeof(uint64_t));
+}
+
+// credit @aqrit
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR14
+uint32_t parse_eight_digits_unrolled(uint64_t val) {
+ constexpr uint64_t mask = 0x000000FF000000FF;
+ constexpr uint64_t mul1 = 0x000F424000000064; // 100 + (1000000ULL << 32)
+ constexpr uint64_t mul2 = 0x0000271000000001; // 1 + (10000ULL << 32)
+ val -= 0x3030303030303030;
+ val = (val * 10) + (val >> 8); // val = (val * 2561) >> 8;
+ val = (((val & mask) * mul1) + (((val >> 16) & mask) * mul2)) >> 32;
+ return uint32_t(val);
+}
+
+BOOST_FORCEINLINE constexpr
+uint32_t parse_eight_digits_unrolled(const char16_t *) noexcept {
+ return 0;
+}
+
+BOOST_FORCEINLINE constexpr
+uint32_t parse_eight_digits_unrolled(const char32_t *) noexcept {
+ return 0;
+}
+
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+uint32_t parse_eight_digits_unrolled(const char *chars) noexcept {
+ return parse_eight_digits_unrolled(read_u64(chars));
+}
+
+// credit @aqrit
+BOOST_FORCEINLINE constexpr bool is_made_of_eight_digits_fast(uint64_t val) noexcept {
+ return !((((val + 0x4646464646464646) | (val - 0x3030303030303030)) & 0x8080808080808080));
+}
+
+BOOST_FORCEINLINE constexpr
+bool is_made_of_eight_digits_fast(const char16_t *) noexcept {
+ return false;
+}
+
+BOOST_FORCEINLINE constexpr
+bool is_made_of_eight_digits_fast(const char32_t *) noexcept {
+ return false;
+}
+
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+bool is_made_of_eight_digits_fast(const char *chars) noexcept {
+ return is_made_of_eight_digits_fast(read_u64(chars));
+}
+
+template <typename UC>
+struct parsed_number_string_t {
+ int64_t exponent{0};
+ uint64_t mantissa{0};
+ UC const * lastmatch{nullptr};
+ bool negative{false};
+ bool valid{false};
+ bool too_many_digits{false};
+ // contains the range of the significant digits
+ span<const UC> integer{}; // non-nullable
+ span<const UC> fraction{}; // nullable
+};
+using byte_span = span<char>;
+using parsed_number_string = parsed_number_string_t<char>;
+// Assuming that you use no more than 19 digits, this will
+// parse an ASCII string.
+template <typename UC>
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+parsed_number_string_t<UC> parse_number_string(UC const *p, UC const * pend, parse_options_t<UC> options) noexcept {
+ chars_format const fmt = options.format;
+ UC const decimal_point = options.decimal_point;
+
+ parsed_number_string_t<UC> answer;
+ answer.valid = false;
+ answer.too_many_digits = false;
+ answer.negative = (*p == UC('-'));
+#ifdef BOOST_CHARCONV_FASTFLOAT_ALLOWS_LEADING_PLUS // disabled by default
+ if ((*p == UC('-')) || (*p == UC('+')))
+#else
+ if (*p == UC('-')) // C++17 20.19.3.(7.1) explicitly forbids '+' sign here
+#endif
+ {
+ ++p;
+ if (p == pend) {
+ return answer;
+ }
+ if (!is_integer(*p) && (*p != decimal_point)) { // a sign must be followed by an integer or the dot
+ return answer;
+ }
+ }
+ UC const * const start_digits = p;
+
+ uint64_t i = 0; // an unsigned int avoids signed overflows (which are bad)
+
+ while ((p != pend) && is_integer(*p)) {
+ // a multiplication by 10 is cheaper than an arbitrary integer
+ // multiplication
+ i = 10 * i +
+ uint64_t(*p - UC('0')); // might overflow, we will handle the overflow later
+ ++p;
+ }
+ UC const * const end_of_integer_part = p;
+ int64_t digit_count = int64_t(end_of_integer_part - start_digits);
+ answer.integer = span<const UC>(start_digits, size_t(digit_count));
+ int64_t exponent = 0;
+ if ((p != pend) && (*p == decimal_point)) {
+ ++p;
+ UC const * before = p;
+ // can occur at most twice without overflowing, but let it occur more, since
+ // for integers with many digits, digit parsing is the primary bottleneck.
+ if (std::is_same<UC,char>::value) {
+ while ((std::distance(p, pend) >= 8) && is_made_of_eight_digits_fast(p)) {
+ i = i * 100000000 + parse_eight_digits_unrolled(p); // in rare cases, this will overflow, but that's ok
+ p += 8;
+ }
+ }
+ while ((p != pend) && is_integer(*p)) {
+ uint8_t digit = uint8_t(*p - UC('0'));
+ ++p;
+ i = i * 10 + digit; // in rare cases, this will overflow, but that's ok
+ }
+ exponent = before - p;
+ answer.fraction = span<const UC>(before, size_t(p - before));
+ digit_count -= exponent;
+ }
+ // we must have encountered at least one integer!
+ if (digit_count == 0) {
+ return answer;
+ }
+ int64_t exp_number = 0; // explicit exponential part
+ if ((static_cast<unsigned>(fmt) & static_cast<unsigned>(chars_format::scientific)) && (p != pend) && ((UC('e') == *p) || (UC('E') == *p))) {
+ UC const * location_of_e = p;
+ ++p;
+ bool neg_exp = false;
+ if ((p != pend) && (UC('-') == *p)) {
+ neg_exp = true;
+ ++p;
+ } else if ((p != pend) && (UC('+') == *p)) { // '+' on exponent is allowed by C++17 20.19.3.(7.1)
+ ++p;
+ }
+ if ((p == pend) || !is_integer(*p)) {
+ if(!(static_cast<unsigned>(fmt) & static_cast<unsigned>(chars_format::fixed))) {
+ // We are in error.
+ return answer;
+ }
+ // Otherwise, we will be ignoring the 'e'.
+ p = location_of_e;
+ } else {
+ while ((p != pend) && is_integer(*p)) {
+ uint8_t digit = uint8_t(*p - UC('0'));
+ if (exp_number < 0x10000000) {
+ exp_number = 10 * exp_number + digit;
+ }
+ ++p;
+ }
+ if(neg_exp) { exp_number = - exp_number; }
+ exponent += exp_number;
+ }
+ } else {
+ // If it scientific and not fixed, we have to bail out.
+ if((static_cast<unsigned>(fmt) & static_cast<unsigned>(chars_format::scientific)) &&
+ !(static_cast<unsigned>(fmt) & static_cast<unsigned>(chars_format::fixed)))
+ {
+ return answer;
+ }
+ }
+ answer.lastmatch = p;
+ answer.valid = true;
+
+ // If we frequently had to deal with long strings of digits,
+ // we could extend our code by using a 128-bit integer instead
+ // of a 64-bit integer. However, this is uncommon.
+ //
+ // We can deal with up to 19 digits.
+ if (digit_count > 19) { // this is uncommon
+ // It is possible that the integer had an overflow.
+ // We have to handle the case where we have 0.0000somenumber.
+ // We need to be mindful of the case where we only have zeroes...
+ // E.g., 0.000000000...000.
+ UC const * start = start_digits;
+ while ((start != pend) && (*start == UC('0') || *start == decimal_point)) {
+ if(*start == UC('0')) { digit_count --; }
+ start++;
+ }
+ if (digit_count > 19) {
+ answer.too_many_digits = true;
+ // Let us start again, this time, avoiding overflows.
+ // We don't need to check if is_integer, since we use the
+ // pre-tokenized spans from above.
+ i = 0;
+ p = answer.integer.ptr;
+ UC const * int_end = p + answer.integer.len();
+ constexpr uint64_t minimal_nineteen_digit_integer{1000000000000000000};
+ while((i < minimal_nineteen_digit_integer) && (p != int_end)) {
+ i = i * 10 + uint64_t(*p - UC('0'));
+ ++p;
+ }
+ if (i >= minimal_nineteen_digit_integer) { // We have a big integers
+ exponent = end_of_integer_part - p + exp_number;
+ } else { // We have a value with a fractional component.
+ p = answer.fraction.ptr;
+ UC const * frac_end = p + answer.fraction.len();
+ while((i < minimal_nineteen_digit_integer) && (p != frac_end)) {
+ i = i * 10 + uint64_t(*p - UC('0'));
+ ++p;
+ }
+ exponent = answer.fraction.ptr - p + exp_number;
+ }
+ // We have now corrected both exponent and i, to a truncated value
+ }
+ }
+ answer.exponent = exponent;
+ answer.mantissa = i;
+ return answer;
+}
+
+}}}} // namespace s
+
+#endif
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/bigint.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/bigint.hpp
new file mode 100644
index 00000000000..fd98590cd79
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/bigint.hpp
@@ -0,0 +1,623 @@
+// Copyright 2020-2023 Daniel Lemire
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+//
+// Derivative of: https://github.com/fastfloat/fast_float
+
+#ifndef BOOST_CHARCONV_DETAIL_FASTFLOAT_BIGINT_HPP
+#define BOOST_CHARCONV_DETAIL_FASTFLOAT_BIGINT_HPP
+
+#include <boost/charconv/detail/fast_float/float_common.hpp>
+#include <algorithm>
+#include <cstdint>
+#include <climits>
+#include <cstring>
+
+namespace boost { namespace charconv { namespace detail { namespace fast_float {
+
+// the limb width: we want efficient multiplication of double the bits in
+// limb, or for 64-bit limbs, at least 64-bit multiplication where we can
+// extract the high and low parts efficiently. this is every 64-bit
+// architecture except for sparc, which emulates 128-bit multiplication.
+// we might have platforms where `CHAR_BIT` is not 8, so let's avoid
+// doing `8 * sizeof(limb)`.
+#if defined(BOOST_CHARCONV_FASTFLOAT_64BIT) && !defined(__sparc)
+#define BOOST_CHARCONV_FASTFLOAT_64BIT_LIMB 1
+typedef uint64_t limb;
+constexpr size_t limb_bits = 64;
+#else
+#define BOOST_CHARCONV_FASTFLOAT_32BIT_LIMB
+typedef uint32_t limb;
+constexpr size_t limb_bits = 32;
+#endif
+
+typedef span<limb> limb_span;
+
+// number of bits in a bigint. this needs to be at least the number
+// of bits required to store the largest bigint, which is
+// `log2(10**(digits + max_exp))`, or `log2(10**(767 + 342))`, or
+// ~3600 bits, so we round to 4000.
+constexpr size_t bigint_bits = 4000;
+constexpr size_t bigint_limbs = bigint_bits / limb_bits;
+
+// vector-like type that is allocated on the stack. the entire
+// buffer is pre-allocated, and only the length changes.
+template <uint16_t size>
+struct stackvec {
+ limb data[size];
+ // we never need more than 150 limbs
+ uint16_t length{0};
+
+ stackvec() = default;
+ stackvec(const stackvec &) = delete;
+ stackvec &operator=(const stackvec &) = delete;
+ stackvec(stackvec &&) = delete;
+ stackvec &operator=(stackvec &&other) = delete;
+
+ // create stack vector from existing limb span.
+ BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20 stackvec(limb_span s) {
+ BOOST_CHARCONV_FASTFLOAT_ASSERT(try_extend(s));
+ }
+
+ BOOST_CHARCONV_FASTFLOAT_CONSTEXPR14 limb& operator[](size_t index) noexcept {
+ BOOST_CHARCONV_FASTFLOAT_DEBUG_ASSERT(index < length);
+ return data[index];
+ }
+ BOOST_CHARCONV_FASTFLOAT_CONSTEXPR14 const limb& operator[](size_t index) const noexcept {
+ BOOST_CHARCONV_FASTFLOAT_DEBUG_ASSERT(index < length);
+ return data[index];
+ }
+ // index from the end of the container
+ BOOST_CHARCONV_FASTFLOAT_CONSTEXPR14 const limb& rindex(size_t index) const noexcept {
+ BOOST_CHARCONV_FASTFLOAT_DEBUG_ASSERT(index < length);
+ size_t rindex = length - index - 1;
+ return data[rindex];
+ }
+
+ // set the length, without bounds checking.
+ BOOST_CHARCONV_FASTFLOAT_CONSTEXPR14 void set_len(size_t len) noexcept {
+ length = uint16_t(len);
+ }
+ constexpr size_t len() const noexcept {
+ return length;
+ }
+ constexpr bool is_empty() const noexcept {
+ return length == 0;
+ }
+ constexpr size_t capacity() const noexcept {
+ return size;
+ }
+ // append item to vector, without bounds checking
+ BOOST_CHARCONV_FASTFLOAT_CONSTEXPR14 void push_unchecked(limb value) noexcept {
+ data[length] = value;
+ length++;
+ }
+ // append item to vector, returning if item was added
+ BOOST_CHARCONV_FASTFLOAT_CONSTEXPR14 bool try_push(limb value) noexcept {
+ if (len() < capacity()) {
+ push_unchecked(value);
+ return true;
+ } else {
+ return false;
+ }
+ }
+ // add items to the vector, from a span, without bounds checking
+ BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20 void extend_unchecked(limb_span s) noexcept {
+ limb* ptr = data + length;
+ std::copy_n(s.ptr, s.len(), ptr);
+ set_len(len() + s.len());
+ }
+ // try to add items to the vector, returning if items were added
+ BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20 bool try_extend(limb_span s) noexcept {
+ if (len() + s.len() <= capacity()) {
+ extend_unchecked(s);
+ return true;
+ } else {
+ return false;
+ }
+ }
+ // resize the vector, without bounds checking
+ // if the new size is longer than the vector, assign value to each
+ // appended item.
+ BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+ void resize_unchecked(size_t new_len, limb value) noexcept {
+ if (new_len > len()) {
+ size_t count = new_len - len();
+ limb* first = data + len();
+ limb* last = first + count;
+ ::std::fill(first, last, value);
+ set_len(new_len);
+ } else {
+ set_len(new_len);
+ }
+ }
+ // try to resize the vector, returning if the vector was resized.
+ BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20 bool try_resize(size_t new_len, limb value) noexcept {
+ if (new_len > capacity()) {
+ return false;
+ } else {
+ resize_unchecked(new_len, value);
+ return true;
+ }
+ }
+ // check if any limbs are non-zero after the given index.
+ // this needs to be done in reverse order, since the index
+ // is relative to the most significant limbs.
+ BOOST_CHARCONV_FASTFLOAT_CONSTEXPR14 bool nonzero(size_t index) const noexcept {
+ while (index < len()) {
+ if (rindex(index) != 0) {
+ return true;
+ }
+ index++;
+ }
+ return false;
+ }
+ // normalize the big integer, so most-significant zero limbs are removed.
+ BOOST_CHARCONV_FASTFLOAT_CONSTEXPR14 void normalize() noexcept {
+ while (len() > 0 && rindex(0) == 0) {
+ length--;
+ }
+ }
+};
+
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR14
+uint64_t empty_hi64(bool& truncated) noexcept {
+ truncated = false;
+ return 0;
+}
+
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+uint64_t uint64_hi64(uint64_t r0, bool& truncated) noexcept {
+ truncated = false;
+ int shl = leading_zeroes(r0);
+ return r0 << shl;
+}
+
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+uint64_t uint64_hi64(uint64_t r0, uint64_t r1, bool& truncated) noexcept {
+ int shl = leading_zeroes(r0);
+ if (shl == 0) {
+ truncated = r1 != 0;
+ return r0;
+ } else {
+ int shr = 64 - shl;
+ truncated = (r1 << shl) != 0;
+ return (r0 << shl) | (r1 >> shr);
+ }
+}
+
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+uint64_t uint32_hi64(uint32_t r0, bool& truncated) noexcept {
+ return uint64_hi64(r0, truncated);
+}
+
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+uint64_t uint32_hi64(uint32_t r0, uint32_t r1, bool& truncated) noexcept {
+ uint64_t x0 = r0;
+ uint64_t x1 = r1;
+ return uint64_hi64((x0 << 32) | x1, truncated);
+}
+
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+uint64_t uint32_hi64(uint32_t r0, uint32_t r1, uint32_t r2, bool& truncated) noexcept {
+ uint64_t x0 = r0;
+ uint64_t x1 = r1;
+ uint64_t x2 = r2;
+ return uint64_hi64(x0, (x1 << 32) | x2, truncated);
+}
+
+// add two small integers, checking for overflow.
+// we want an efficient operation. for msvc, where
+// we don't have built-in intrinsics, this is still
+// pretty fast.
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+limb scalar_add(limb x, limb y, bool& overflow) noexcept {
+ limb z;
+// gcc and clang
+#if defined(__has_builtin)
+ #if __has_builtin(__builtin_add_overflow)
+ if (!cpp20_and_in_constexpr()) {
+ overflow = __builtin_add_overflow(x, y, &z);
+ return z;
+ }
+ #endif
+#endif
+
+ // generic, this still optimizes correctly on MSVC.
+ z = x + y;
+ overflow = z < x;
+ return z;
+}
+
+// multiply two small integers, getting both the high and low bits.
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+limb scalar_mul(limb x, limb y, limb& carry) noexcept {
+#ifdef BOOST_CHARCONV_FASTFLOAT_64BIT_LIMB
+ #if defined(__SIZEOF_INT128__)
+ // GCC and clang both define it as an extension.
+ __uint128_t z = __uint128_t(x) * __uint128_t(y) + __uint128_t(carry);
+ carry = limb(z >> limb_bits);
+ return limb(z);
+ #else
+ // fallback, no native 128-bit integer multiplication with carry.
+ // on msvc, this optimizes identically, somehow.
+ value128 z = full_multiplication(x, y);
+ bool overflow;
+ z.low = scalar_add(z.low, carry, overflow);
+ z.high += uint64_t(overflow); // cannot overflow
+ carry = z.high;
+ return z.low;
+ #endif
+#else
+ uint64_t z = uint64_t(x) * uint64_t(y) + uint64_t(carry);
+ carry = limb(z >> limb_bits);
+ return limb(z);
+#endif
+}
+
+// add scalar value to bigint starting from offset.
+// used in grade school multiplication
+template <uint16_t size>
+inline BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+bool small_add_from(stackvec<size>& vec, limb y, size_t start) noexcept {
+ size_t index = start;
+ limb carry = y;
+ bool overflow;
+ while (carry != 0 && index < vec.len()) {
+ vec[index] = scalar_add(vec[index], carry, overflow);
+ carry = limb(overflow);
+ index += 1;
+ }
+ if (carry != 0) {
+ BOOST_CHARCONV_FASTFLOAT_TRY(vec.try_push(carry));
+ }
+ return true;
+}
+
+// add scalar value to bigint.
+template <uint16_t size>
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+bool small_add(stackvec<size>& vec, limb y) noexcept {
+ return small_add_from(vec, y, 0);
+}
+
+// multiply bigint by scalar value.
+template <uint16_t size>
+inline BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+bool small_mul(stackvec<size>& vec, limb y) noexcept {
+ limb carry = 0;
+ for (size_t index = 0; index < vec.len(); index++) {
+ vec[index] = scalar_mul(vec[index], y, carry);
+ }
+ if (carry != 0) {
+ BOOST_CHARCONV_FASTFLOAT_TRY(vec.try_push(carry));
+ }
+ return true;
+}
+
+// add bigint to bigint starting from index.
+// used in grade school multiplication
+template <uint16_t size>
+BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+bool large_add_from(stackvec<size>& x, limb_span y, size_t start) noexcept {
+ // the effective x buffer is from `xstart..x.len()`, so exit early
+ // if we can't get that current range.
+ if (x.len() < start || y.len() > x.len() - start) {
+ BOOST_CHARCONV_FASTFLOAT_TRY(x.try_resize(y.len() + start, 0));
+ }
+
+ bool carry = false;
+ for (size_t index = 0; index < y.len(); index++) {
+ limb xi = x[index + start];
+ limb yi = y[index];
+ bool c1 = false;
+ bool c2 = false;
+ xi = scalar_add(xi, yi, c1);
+ if (carry) {
+ xi = scalar_add(xi, 1, c2);
+ }
+ x[index + start] = xi;
+ carry = c1 | c2;
+ }
+
+ // handle overflow
+ if (carry) {
+ BOOST_CHARCONV_FASTFLOAT_TRY(small_add_from(x, 1, y.len() + start));
+ }
+ return true;
+}
+
+// add bigint to bigint.
+template <uint16_t size>
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+bool large_add_from(stackvec<size>& x, limb_span y) noexcept {
+ return large_add_from(x, y, 0);
+}
+
+// grade-school multiplication algorithm
+template <uint16_t size>
+BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+bool long_mul(stackvec<size>& x, limb_span y) noexcept {
+ limb_span xs = limb_span(x.data, x.len());
+ stackvec<size> z(xs);
+ limb_span zs = limb_span(z.data, z.len());
+
+ if (y.len() != 0) {
+ limb y0 = y[0];
+ BOOST_CHARCONV_FASTFLOAT_TRY(small_mul(x, y0));
+ for (size_t index = 1; index < y.len(); index++) {
+ limb yi = y[index];
+ stackvec<size> zi;
+ if (yi != 0) {
+ // re-use the same buffer throughout
+ zi.set_len(0);
+ BOOST_CHARCONV_FASTFLOAT_TRY(zi.try_extend(zs));
+ BOOST_CHARCONV_FASTFLOAT_TRY(small_mul(zi, yi));
+ limb_span zis = limb_span(zi.data, zi.len());
+ BOOST_CHARCONV_FASTFLOAT_TRY(large_add_from(x, zis, index));
+ }
+ }
+ }
+
+ x.normalize();
+ return true;
+}
+
+// grade-school multiplication algorithm
+template <uint16_t size>
+BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+bool large_mul(stackvec<size>& x, limb_span y) noexcept {
+ if (y.len() == 1) {
+ BOOST_CHARCONV_FASTFLOAT_TRY(small_mul(x, y[0]));
+ } else {
+ BOOST_CHARCONV_FASTFLOAT_TRY(long_mul(x, y));
+ }
+ return true;
+}
+
+template <typename = void>
+struct pow5_tables {
+ static constexpr uint32_t large_step = 135;
+ static constexpr uint64_t small_power_of_5[] = {
+ 1UL, 5UL, 25UL, 125UL, 625UL, 3125UL, 15625UL, 78125UL, 390625UL,
+ 1953125UL, 9765625UL, 48828125UL, 244140625UL, 1220703125UL,
+ 6103515625UL, 30517578125UL, 152587890625UL, 762939453125UL,
+ 3814697265625UL, 19073486328125UL, 95367431640625UL, 476837158203125UL,
+ 2384185791015625UL, 11920928955078125UL, 59604644775390625UL,
+ 298023223876953125UL, 1490116119384765625UL, 7450580596923828125UL,
+ };
+#ifdef BOOST_CHARCONV_FASTFLOAT_64BIT_LIMB
+ constexpr static limb large_power_of_5[] = {
+ 1414648277510068013UL, 9180637584431281687UL, 4539964771860779200UL,
+ 10482974169319127550UL, 198276706040285095UL};
+#else
+ constexpr static limb large_power_of_5[] = {
+ 4279965485U, 329373468U, 4020270615U, 2137533757U, 4287402176U,
+ 1057042919U, 1071430142U, 2440757623U, 381945767U, 46164893U};
+#endif
+};
+
+template <typename T>
+constexpr uint32_t pow5_tables<T>::large_step;
+
+template <typename T>
+constexpr uint64_t pow5_tables<T>::small_power_of_5[];
+
+template <typename T>
+constexpr limb pow5_tables<T>::large_power_of_5[];
+
+// big integer type. implements a small subset of big integer
+// arithmetic, using simple algorithms since asymptotically
+// faster algorithms are slower for a small number of limbs.
+// all operations assume the big-integer is normalized.
+struct bigint : pow5_tables<> {
+ // storage of the limbs, in little-endian order.
+ stackvec<bigint_limbs> vec;
+
+ BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20 bigint(): vec() {}
+ bigint(const bigint &) = delete;
+ bigint &operator=(const bigint &) = delete;
+ bigint(bigint &&) = delete;
+ bigint &operator=(bigint &&other) = delete;
+
+ BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20 bigint(uint64_t value): vec() {
+#ifdef BOOST_CHARCONV_FASTFLOAT_64BIT_LIMB
+ vec.push_unchecked(value);
+#else
+ vec.push_unchecked(uint32_t(value));
+ vec.push_unchecked(uint32_t(value >> 32));
+#endif
+ vec.normalize();
+ }
+
+ // get the high 64 bits from the vector, and if bits were truncated.
+ // this is to get the significant digits for the float.
+ BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20 uint64_t hi64(bool& truncated) const noexcept {
+#ifdef BOOST_CHARCONV_FASTFLOAT_64BIT_LIMB
+ if (vec.len() == 0) {
+ return empty_hi64(truncated);
+ } else if (vec.len() == 1) {
+ return uint64_hi64(vec.rindex(0), truncated);
+ } else {
+ uint64_t result = uint64_hi64(vec.rindex(0), vec.rindex(1), truncated);
+ truncated |= vec.nonzero(2);
+ return result;
+ }
+#else
+ if (vec.len() == 0) {
+ return empty_hi64(truncated);
+ } else if (vec.len() == 1) {
+ return uint32_hi64(vec.rindex(0), truncated);
+ } else if (vec.len() == 2) {
+ return uint32_hi64(vec.rindex(0), vec.rindex(1), truncated);
+ } else {
+ uint64_t result = uint32_hi64(vec.rindex(0), vec.rindex(1), vec.rindex(2), truncated);
+ truncated |= vec.nonzero(3);
+ return result;
+ }
+#endif
+ }
+
+ // compare two big integers, returning the large value.
+ // assumes both are normalized. if the return value is
+ // negative, other is larger, if the return value is
+ // positive, this is larger, otherwise they are equal.
+ // the limbs are stored in little-endian order, so we
+ // must compare the limbs in ever order.
+ BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20 int compare(const bigint& other) const noexcept {
+ if (vec.len() > other.vec.len()) {
+ return 1;
+ } else if (vec.len() < other.vec.len()) {
+ return -1;
+ } else {
+ for (size_t index = vec.len(); index > 0; index--) {
+ limb xi = vec[index - 1];
+ limb yi = other.vec[index - 1];
+ if (xi > yi) {
+ return 1;
+ } else if (xi < yi) {
+ return -1;
+ }
+ }
+ return 0;
+ }
+ }
+
+ // shift left each limb n bits, carrying over to the new limb
+ // returns true if we were able to shift all the digits.
+ BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20 bool shl_bits(size_t n) noexcept {
+ // Internally, for each item, we shift left by n, and add the previous
+ // right shifted limb-bits.
+ // For example, we transform (for u8) shifted left 2, to:
+ // b10100100 b01000010
+ // b10 b10010001 b00001000
+ BOOST_CHARCONV_FASTFLOAT_DEBUG_ASSERT(n != 0);
+ BOOST_CHARCONV_FASTFLOAT_DEBUG_ASSERT(n < sizeof(limb) * 8);
+
+ size_t shl = n;
+ size_t shr = limb_bits - shl;
+ limb prev = 0;
+ for (size_t index = 0; index < vec.len(); index++) {
+ limb xi = vec[index];
+ vec[index] = (xi << shl) | (prev >> shr);
+ prev = xi;
+ }
+
+ limb carry = prev >> shr;
+ if (carry != 0) {
+ return vec.try_push(carry);
+ }
+ return true;
+ }
+
+ // move the limbs left by `n` limbs.
+ BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20 bool shl_limbs(size_t n) noexcept {
+ BOOST_CHARCONV_FASTFLOAT_DEBUG_ASSERT(n != 0);
+ if (n + vec.len() > vec.capacity()) {
+ return false;
+ } else if (!vec.is_empty()) {
+ // move limbs
+ limb* dst = vec.data + n;
+ const limb* src = vec.data;
+ std::copy_backward(src, src + vec.len(), dst + vec.len());
+ // fill in empty limbs
+ limb* first = vec.data;
+ limb* last = first + n;
+ ::std::fill(first, last, 0);
+ vec.set_len(n + vec.len());
+ return true;
+ } else {
+ return true;
+ }
+ }
+
+ // move the limbs left by `n` bits.
+ BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20 bool shl(size_t n) noexcept {
+ size_t rem = n % limb_bits;
+ size_t div = n / limb_bits;
+ if (rem != 0) {
+ BOOST_CHARCONV_FASTFLOAT_TRY(shl_bits(rem));
+ }
+ if (div != 0) {
+ BOOST_CHARCONV_FASTFLOAT_TRY(shl_limbs(div));
+ }
+ return true;
+ }
+
+ // get the number of leading zeros in the bigint.
+ BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20 int ctlz() const noexcept {
+ if (vec.is_empty()) {
+ return 0;
+ } else {
+#ifdef BOOST_CHARCONV_FASTFLOAT_64BIT_LIMB
+ return leading_zeroes(vec.rindex(0));
+#else
+ // no use defining a specialized leading_zeroes for a 32-bit type.
+ uint64_t r0 = vec.rindex(0);
+ return leading_zeroes(r0 << 32);
+#endif
+ }
+ }
+
+ // get the number of bits in the bigint.
+ BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20 int bit_length() const noexcept {
+ int lz = ctlz();
+ return int(limb_bits * vec.len()) - lz;
+ }
+
+ BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20 bool mul(limb y) noexcept {
+ return small_mul(vec, y);
+ }
+
+ BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20 bool add(limb y) noexcept {
+ return small_add(vec, y);
+ }
+
+ // multiply as if by 2 raised to a power.
+ BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20 bool pow2(uint32_t exp) noexcept {
+ return shl(exp);
+ }
+
+ // multiply as if by 5 raised to a power.
+ BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20 bool pow5(uint32_t exp) noexcept {
+ // multiply by a power of 5
+ constexpr size_t large_length = sizeof(large_power_of_5) / sizeof(limb);
+ limb_span large = limb_span(large_power_of_5, large_length);
+ while (exp >= large_step) {
+ BOOST_CHARCONV_FASTFLOAT_TRY(large_mul(vec, large));
+ exp -= large_step;
+ }
+#ifdef BOOST_CHARCONV_FASTFLOAT_64BIT_LIMB
+ constexpr uint32_t small_step = 27;
+ constexpr limb max_native = 7450580596923828125UL;
+#else
+ constexpr uint32_t small_step = 13;
+ constexpr limb max_native = 1220703125U;
+#endif
+ while (exp >= small_step) {
+ BOOST_CHARCONV_FASTFLOAT_TRY(small_mul(vec, max_native));
+ exp -= small_step;
+ }
+ if (exp != 0) {
+ // Work around clang bug https://godbolt.org/z/zedh7rrhc
+ // This is similar to https://github.com/llvm/llvm-project/issues/47746,
+ // except the workaround described there don't work here
+ BOOST_CHARCONV_FASTFLOAT_TRY(
+ small_mul(vec, limb(((void)small_power_of_5[0], small_power_of_5[exp])))
+ );
+ }
+
+ return true;
+ }
+
+ // multiply as if by 10 raised to a power.
+ BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20 bool pow10(uint32_t exp) noexcept {
+ BOOST_CHARCONV_FASTFLOAT_TRY(pow5(exp));
+ return pow2(exp);
+ }
+};
+
+}}}} // namespace fast_float
+
+#endif
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/constexpr_feature_detect.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/constexpr_feature_detect.hpp
new file mode 100644
index 00000000000..1ac1e4aabf5
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/constexpr_feature_detect.hpp
@@ -0,0 +1,47 @@
+// Copyright 2020-2023 Daniel Lemire
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+//
+// Derivative of: https://github.com/fastfloat/fast_float
+
+#ifndef BOOST_CHARCONV_DETAIL_FASTFLOAT_CONSTEXPR_FEATURE_DETECT_HPP
+#define BOOST_CHARCONV_DETAIL_FASTFLOAT_CONSTEXPR_FEATURE_DETECT_HPP
+
+#ifdef __has_include
+#if __has_include(<version>)
+#include <version>
+#endif
+#endif
+
+// Testing for https://wg21.link/N3652, adopted in C++14
+#if __cpp_constexpr >= 201304
+#define BOOST_CHARCONV_FASTFLOAT_CONSTEXPR14 constexpr
+#else
+#define BOOST_CHARCONV_FASTFLOAT_CONSTEXPR14
+#endif
+
+#if defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L
+#define BOOST_CHARCONV_FASTFLOAT_HAS_BIT_CAST 1
+#else
+#define BOOST_CHARCONV_FASTFLOAT_HAS_BIT_CAST 0
+#endif
+
+#if defined(__cpp_lib_is_constant_evaluated) && __cpp_lib_is_constant_evaluated >= 201811L
+#define BOOST_CHARCONV_FASTFLOAT_HAS_IS_CONSTANT_EVALUATED 1
+#else
+#define BOOST_CHARCONV_FASTFLOAT_HAS_IS_CONSTANT_EVALUATED 0
+#endif
+
+// Testing for relevant C++20 constexpr library features
+#if BOOST_CHARCONV_FASTFLOAT_HAS_IS_CONSTANT_EVALUATED \
+ && BOOST_CHARCONV_FASTFLOAT_HAS_BIT_CAST \
+ && __cpp_lib_constexpr_algorithms >= 201806L /*For std::copy and std::fill*/
+#define BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20 constexpr
+#define BOOST_CHARCONV_FASTFLOAT_IS_CONSTEXPR 1
+#else
+#define BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+#define BOOST_CHARCONV_FASTFLOAT_IS_CONSTEXPR 0
+#endif
+
+#endif // BOOST_CHARCONV_FASTFLOAT_CONSTEXPR_FEATURE_DETECT_H
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/decimal_to_binary.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/decimal_to_binary.hpp
new file mode 100644
index 00000000000..4a76a6eeb69
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/decimal_to_binary.hpp
@@ -0,0 +1,196 @@
+// Copyright 2020-2023 Daniel Lemire
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+//
+// Derivative of: https://github.com/fastfloat/fast_float
+
+#ifndef BOOST_CHARCONV_DETAIL_FASTFLOAT_DECIMAL_TO_BINARY_HPP
+#define BOOST_CHARCONV_DETAIL_FASTFLOAT_DECIMAL_TO_BINARY_HPP
+
+#include <boost/charconv/detail/fast_float/float_common.hpp>
+#include <boost/charconv/detail/fast_float/fast_table.hpp>
+#include <cfloat>
+#include <cinttypes>
+#include <cmath>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+
+namespace boost { namespace charconv { namespace detail { namespace fast_float {
+
+// This will compute or rather approximate w * 5**q and return a pair of 64-bit words approximating
+// the result, with the "high" part corresponding to the most significant bits and the
+// low part corresponding to the least significant bits.
+//
+template <int bit_precision>
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+value128 compute_product_approximation(int64_t q, uint64_t w) {
+ const int index = 2 * int(q - powers::smallest_power_of_five);
+ // For small values of q, e.g., q in [0,27], the answer is always exact because
+ // The line value128 firstproduct = full_multiplication(w, power_of_five_128[index]);
+ // gives the exact answer.
+ value128 firstproduct = full_multiplication(w, powers::power_of_five_128[index]);
+ static_assert((bit_precision >= 0) && (bit_precision <= 64), " precision should be in (0,64]");
+ constexpr uint64_t precision_mask = (bit_precision < 64) ?
+ (uint64_t(0xFFFFFFFFFFFFFFFF) >> bit_precision)
+ : uint64_t(0xFFFFFFFFFFFFFFFF);
+ if((firstproduct.high & precision_mask) == precision_mask) { // could further guard with (lower + w < lower)
+ // regarding the second product, we only need secondproduct.high, but our expectation is that the compiler will optimize this extra work away if needed.
+ value128 secondproduct = full_multiplication(w, powers::power_of_five_128[index + 1]);
+ firstproduct.low += secondproduct.high;
+ if(secondproduct.high > firstproduct.low) {
+ firstproduct.high++;
+ }
+ }
+ return firstproduct;
+}
+
+namespace detail {
+/**
+ * For q in (0,350), we have that
+ * f = (((152170 + 65536) * q ) >> 16);
+ * is equal to
+ * floor(p) + q
+ * where
+ * p = log(5**q)/log(2) = q * log(5)/log(2)
+ *
+ * For negative values of q in (-400,0), we have that
+ * f = (((152170 + 65536) * q ) >> 16);
+ * is equal to
+ * -ceil(p) + q
+ * where
+ * p = log(5**-q)/log(2) = -q * log(5)/log(2)
+ */
+ constexpr BOOST_FORCEINLINE int32_t power(int32_t q) noexcept {
+ return (((152170 + 65536) * q) >> 16) + 63;
+ }
+} // namespace detail
+
+// create an adjusted mantissa, biased by the invalid power2
+// for significant digits already multiplied by 10 ** q.
+template <typename binary>
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR14
+adjusted_mantissa compute_error_scaled(int64_t q, uint64_t w, int lz) noexcept {
+ int hilz = int(w >> 63) ^ 1;
+ adjusted_mantissa answer;
+ answer.mantissa = w << hilz;
+ int bias = binary::mantissa_explicit_bits() - binary::minimum_exponent();
+ answer.power2 = int32_t(detail::power(int32_t(q)) + bias - hilz - lz - 62 + invalid_am_bias);
+ return answer;
+}
+
+// w * 10 ** q, without rounding the representation up.
+// the power2 in the exponent will be adjusted by invalid_am_bias.
+template <typename binary>
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+adjusted_mantissa compute_error(int64_t q, uint64_t w) noexcept {
+ int lz = leading_zeroes(w);
+ w <<= lz;
+ value128 product = compute_product_approximation<binary::mantissa_explicit_bits() + 3>(q, w);
+ return compute_error_scaled<binary>(q, product.high, lz);
+}
+
+// w * 10 ** q
+// The returned value should be a valid ieee64 number that simply need to be packed.
+// However, in some very rare cases, the computation will fail. In such cases, we
+// return an adjusted_mantissa with a negative power of 2: the caller should recompute
+// in such cases.
+template <typename binary>
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+adjusted_mantissa compute_float(int64_t q, uint64_t w) noexcept {
+ adjusted_mantissa answer;
+ if ((w == 0) || (q < binary::smallest_power_of_ten())) {
+ answer.power2 = 0;
+ answer.mantissa = 0;
+ // result should be zero
+ return answer;
+ }
+ if (q > binary::largest_power_of_ten()) {
+ // we want to get infinity:
+ answer.power2 = binary::infinite_power();
+ answer.mantissa = 0;
+ return answer;
+ }
+ // At this point in time q is in [powers::smallest_power_of_five, powers::largest_power_of_five].
+
+ // We want the most significant bit of i to be 1. Shift if needed.
+ int lz = leading_zeroes(w);
+ w <<= lz;
+
+ // The required precision is binary::mantissa_explicit_bits() + 3 because
+ // 1. We need the implicit bit
+ // 2. We need an extra bit for rounding purposes
+ // 3. We might lose a bit due to the "upperbit" routine (result too small, requiring a shift)
+
+ value128 product = compute_product_approximation<binary::mantissa_explicit_bits() + 3>(q, w);
+ // The computed 'product' is always sufficient.
+ // Mathematical proof:
+ // Noble Mushtak and Daniel Lemire, Fast Number Parsing Without Fallback (to appear)
+ // See script/mushtak_lemire.py
+
+ // The "compute_product_approximation" function can be slightly slower than a branchless approach:
+ // value128 product = compute_product(q, w);
+ // but in practice, we can win big with the compute_product_approximation if its additional branch
+ // is easily predicted. Which is best is data specific.
+ int upperbit = int(product.high >> 63);
+
+ answer.mantissa = product.high >> (upperbit + 64 - binary::mantissa_explicit_bits() - 3);
+
+ answer.power2 = int32_t(detail::power(int32_t(q)) + upperbit - lz - binary::minimum_exponent());
+ if (answer.power2 <= 0) { // we have a subnormal?
+ // Here have that answer.power2 <= 0 so -answer.power2 >= 0
+ if(-answer.power2 + 1 >= 64) { // if we have more than 64 bits below the minimum exponent, you have a zero for sure.
+ answer.power2 = 0;
+ answer.mantissa = 0;
+ // result should be zero
+ return answer;
+ }
+ // next line is safe because -answer.power2 + 1 < 64
+ answer.mantissa >>= -answer.power2 + 1;
+ // Thankfully, we can't have both "round-to-even" and subnormals because
+ // "round-to-even" only occurs for powers close to 0.
+ answer.mantissa += (answer.mantissa & 1); // round up
+ answer.mantissa >>= 1;
+ // There is a weird scenario where we don't have a subnormal but just.
+ // Suppose we start with 2.2250738585072013e-308, we end up
+ // with 0x3fffffffffffff x 2^-1023-53 which is technically subnormal
+ // whereas 0x40000000000000 x 2^-1023-53 is normal. Now, we need to round
+ // up 0x3fffffffffffff x 2^-1023-53 and once we do, we are no longer
+ // subnormal, but we can only know this after rounding.
+ // So we only declare a subnormal if we are smaller than the threshold.
+ answer.power2 = (answer.mantissa < (uint64_t(1) << binary::mantissa_explicit_bits())) ? 0 : 1;
+ return answer;
+ }
+
+ // usually, we round *up*, but if we fall right in between and and we have an
+ // even basis, we need to round down
+ // We are only concerned with the cases where 5**q fits in single 64-bit word.
+ if ((product.low <= 1) && (q >= binary::min_exponent_round_to_even()) && (q <= binary::max_exponent_round_to_even()) &&
+ ((answer.mantissa & 3) == 1) ) { // we may fall between two floats!
+ // To be in-between two floats we need that in doing
+ // answer.mantissa = product.high >> (upperbit + 64 - binary::mantissa_explicit_bits() - 3);
+ // ... we dropped out only zeroes. But if this happened, then we can go back!!!
+ if((answer.mantissa << (upperbit + 64 - binary::mantissa_explicit_bits() - 3)) == product.high) {
+ answer.mantissa &= ~uint64_t(1); // flip it so that we do not round up
+ }
+ }
+
+ answer.mantissa += (answer.mantissa & 1); // round up
+ answer.mantissa >>= 1;
+ if (answer.mantissa >= (uint64_t(2) << binary::mantissa_explicit_bits())) {
+ answer.mantissa = (uint64_t(1) << binary::mantissa_explicit_bits());
+ answer.power2++; // undo previous addition
+ }
+
+ answer.mantissa &= ~(uint64_t(1) << binary::mantissa_explicit_bits());
+ if (answer.power2 >= binary::infinite_power()) { // infinity
+ answer.power2 = binary::infinite_power();
+ answer.mantissa = 0;
+ }
+ return answer;
+}
+
+}}}} // namespace fast_float
+
+#endif
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/digit_comparison.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/digit_comparison.hpp
new file mode 100644
index 00000000000..231279410a2
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/digit_comparison.hpp
@@ -0,0 +1,442 @@
+// Copyright 2020-2023 Daniel Lemire
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+//
+// Derivative of: https://github.com/fastfloat/fast_float
+
+#ifndef BOOST_CHARCONV_DETAIL_FASTFLOAT_DIGIT_COMPARISON_HPP
+#define BOOST_CHARCONV_DETAIL_FASTFLOAT_DIGIT_COMPARISON_HPP
+
+#include <boost/charconv/detail/fast_float/float_common.hpp>
+#include <boost/charconv/detail/fast_float/bigint.hpp>
+#include <boost/charconv/detail/fast_float/ascii_number.hpp>
+#include <algorithm>
+#include <cstdint>
+#include <cstring>
+#include <iterator>
+
+namespace boost { namespace charconv { namespace detail { namespace fast_float {
+
+// 1e0 to 1e19
+constexpr static uint64_t powers_of_ten_uint64[] = {
+ 1UL, 10UL, 100UL, 1000UL, 10000UL, 100000UL, 1000000UL, 10000000UL, 100000000UL,
+ 1000000000UL, 10000000000UL, 100000000000UL, 1000000000000UL, 10000000000000UL,
+ 100000000000000UL, 1000000000000000UL, 10000000000000000UL, 100000000000000000UL,
+ 1000000000000000000UL, 10000000000000000000UL};
+
+// calculate the exponent, in scientific notation, of the number.
+// this algorithm is not even close to optimized, but it has no practical
+// effect on performance: in order to have a faster algorithm, we'd need
+// to slow down performance for faster algorithms, and this is still fast.
+template <typename UC>
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR14
+int32_t scientific_exponent(parsed_number_string_t<UC> & num) noexcept {
+ uint64_t mantissa = num.mantissa;
+ int32_t exponent = int32_t(num.exponent);
+ while (mantissa >= 10000) {
+ mantissa /= 10000;
+ exponent += 4;
+ }
+ while (mantissa >= 100) {
+ mantissa /= 100;
+ exponent += 2;
+ }
+ while (mantissa >= 10) {
+ mantissa /= 10;
+ exponent += 1;
+ }
+ return exponent;
+}
+
+// this converts a native floating-point number to an extended-precision float.
+template <typename T>
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+adjusted_mantissa to_extended(T value) noexcept {
+ using equiv_uint = typename binary_format<T>::equiv_uint;
+ constexpr equiv_uint exponent_mask = binary_format<T>::exponent_mask();
+ constexpr equiv_uint mantissa_mask = binary_format<T>::mantissa_mask();
+ constexpr equiv_uint hidden_bit_mask = binary_format<T>::hidden_bit_mask();
+
+ adjusted_mantissa am;
+ int32_t bias = binary_format<T>::mantissa_explicit_bits() - binary_format<T>::minimum_exponent();
+ equiv_uint bits;
+#if BOOST_CHARCONV_FASTFLOAT_HAS_BIT_CAST
+ bits = std::bit_cast<equiv_uint>(value);
+#else
+ ::memcpy(&bits, &value, sizeof(T));
+#endif
+ if ((bits & exponent_mask) == 0) {
+ // denormal
+ am.power2 = 1 - bias;
+ am.mantissa = bits & mantissa_mask;
+ } else {
+ // normal
+ am.power2 = int32_t((bits & exponent_mask) >> binary_format<T>::mantissa_explicit_bits());
+ am.power2 -= bias;
+ am.mantissa = (bits & mantissa_mask) | hidden_bit_mask;
+ }
+
+ return am;
+}
+
+// get the extended precision value of the halfway point between b and b+u.
+// we are given a native float that represents b, so we need to adjust it
+// halfway between b and b+u.
+template <typename T>
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+adjusted_mantissa to_extended_halfway(T value) noexcept {
+ adjusted_mantissa am = to_extended(value);
+ am.mantissa <<= 1;
+ am.mantissa += 1;
+ am.power2 -= 1;
+ return am;
+}
+
+// round an extended-precision float to the nearest machine float.
+template <typename T, typename callback>
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR14
+void round(adjusted_mantissa& am, callback cb) noexcept {
+ int32_t mantissa_shift = 64 - binary_format<T>::mantissa_explicit_bits() - 1;
+ if (-am.power2 >= mantissa_shift) {
+ // have a denormal float
+ int32_t shift = -am.power2 + 1;
+ cb(am, std::min<int32_t>(shift, 64));
+ // check for round-up: if rounding-nearest carried us to the hidden bit.
+ am.power2 = (am.mantissa < (uint64_t(1) << binary_format<T>::mantissa_explicit_bits())) ? 0 : 1;
+ return;
+ }
+
+ // have a normal float, use the default shift.
+ cb(am, mantissa_shift);
+
+ // check for carry
+ if (am.mantissa >= (uint64_t(2) << binary_format<T>::mantissa_explicit_bits())) {
+ am.mantissa = (uint64_t(1) << binary_format<T>::mantissa_explicit_bits());
+ am.power2++;
+ }
+
+ // check for infinite: we could have carried to an infinite power
+ am.mantissa &= ~(uint64_t(1) << binary_format<T>::mantissa_explicit_bits());
+ if (am.power2 >= binary_format<T>::infinite_power()) {
+ am.power2 = binary_format<T>::infinite_power();
+ am.mantissa = 0;
+ }
+}
+
+template <typename callback>
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR14
+void round_nearest_tie_even(adjusted_mantissa& am, int32_t shift, callback cb) noexcept {
+ const uint64_t mask
+ = (shift == 64)
+ ? UINT64_MAX
+ : (uint64_t(1) << shift) - 1;
+ const uint64_t halfway
+ = (shift == 0)
+ ? 0
+ : uint64_t(1) << (shift - 1);
+ uint64_t truncated_bits = am.mantissa & mask;
+ bool is_above = truncated_bits > halfway;
+ bool is_halfway = truncated_bits == halfway;
+
+ // shift digits into position
+ if (shift == 64) {
+ am.mantissa = 0;
+ } else {
+ am.mantissa >>= shift;
+ }
+ am.power2 += shift;
+
+ bool is_odd = (am.mantissa & 1) == 1;
+ am.mantissa += uint64_t(cb(is_odd, is_halfway, is_above));
+}
+
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR14
+void round_down(adjusted_mantissa& am, int32_t shift) noexcept {
+ if (shift == 64) {
+ am.mantissa = 0;
+ } else {
+ am.mantissa >>= shift;
+ }
+ am.power2 += shift;
+}
+template <typename UC>
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+void skip_zeros(UC const * & first, UC const * last) noexcept {
+ uint64_t val;
+ while (!cpp20_and_in_constexpr() && std::distance(first, last) >= int_cmp_len<UC>()) {
+ ::memcpy(&val, first, sizeof(uint64_t));
+ if (val != int_cmp_zeros<UC>()) {
+ break;
+ }
+ first += int_cmp_len<UC>();
+ }
+ while (first != last) {
+ if (*first != UC('0')) {
+ break;
+ }
+ first++;
+ }
+}
+
+// determine if any non-zero digits were truncated.
+// all characters must be valid digits.
+template <typename UC>
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+bool is_truncated(UC const * first, UC const * last) noexcept {
+ // do 8-bit optimizations, can just compare to 8 literal 0s.
+ uint64_t val;
+ while (!cpp20_and_in_constexpr() && std::distance(first, last) >= int_cmp_len<UC>()) {
+ ::memcpy(&val, first, sizeof(uint64_t));
+ if (val != int_cmp_zeros<UC>()) {
+ return true;
+ }
+ first += int_cmp_len<UC>();
+ }
+ while (first != last) {
+ if (*first != UC('0')) {
+ return true;
+ }
+ ++first;
+ }
+ return false;
+}
+template <typename UC>
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+bool is_truncated(span<const UC> s) noexcept {
+ return is_truncated(s.ptr, s.ptr + s.len());
+}
+
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+void parse_eight_digits(const char16_t*& , limb& , size_t& , size_t& ) noexcept {
+ // currently unused
+}
+
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+void parse_eight_digits(const char32_t*& , limb& , size_t& , size_t& ) noexcept {
+ // currently unused
+}
+
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+void parse_eight_digits(const char*& p, limb& value, size_t& counter, size_t& count) noexcept {
+ value = value * 100000000 + parse_eight_digits_unrolled(p);
+ p += 8;
+ counter += 8;
+ count += 8;
+}
+
+template <typename UC>
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR14
+void parse_one_digit(UC const *& p, limb& value, size_t& counter, size_t& count) noexcept {
+ value = value * 10 + limb(*p - UC('0'));
+ p++;
+ counter++;
+ count++;
+}
+
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+void add_native(bigint& big, limb power, limb value) noexcept {
+ big.mul(power);
+ big.add(value);
+}
+
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+void round_up_bigint(bigint& big, size_t& count) noexcept {
+ // need to round-up the digits, but need to avoid rounding
+ // ....9999 to ...10000, which could cause a false halfway point.
+ add_native(big, 10, 1);
+ count++;
+}
+
+// parse the significant digits into a big integer
+template <typename UC>
+inline BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+void parse_mantissa(bigint& result, parsed_number_string_t<UC>& num, size_t max_digits, size_t& digits) noexcept {
+ // try to minimize the number of big integer and scalar multiplication.
+ // therefore, try to parse 8 digits at a time, and multiply by the largest
+ // scalar value (9 or 19 digits) for each step.
+ size_t counter = 0;
+ digits = 0;
+ limb value = 0;
+#ifdef BOOST_CHARCONV_FASTFLOAT_64BIT_LIMB
+ constexpr size_t step = 19;
+#else
+ constexpr size_t step = 9;
+#endif
+
+ // process all integer digits.
+ UC const * p = num.integer.ptr;
+ UC const * pend = p + num.integer.len();
+ skip_zeros(p, pend);
+ // process all digits, in increments of step per loop
+ while (p != pend) {
+ if (std::is_same<UC,char>::value) {
+ while ((std::distance(p, pend) >= 8) && (step - counter >= 8) && (max_digits - digits >= 8)) {
+ parse_eight_digits(p, value, counter, digits);
+ }
+ }
+ while (counter < step && p != pend && digits < max_digits) {
+ parse_one_digit(p, value, counter, digits);
+ }
+ if (digits == max_digits) {
+ // add the temporary value, then check if we've truncated any digits
+ add_native(result, limb(powers_of_ten_uint64[counter]), value);
+ bool truncated = is_truncated(p, pend);
+ if (num.fraction.ptr != nullptr) {
+ truncated |= is_truncated(num.fraction);
+ }
+ if (truncated) {
+ round_up_bigint(result, digits);
+ }
+ return;
+ } else {
+ add_native(result, limb(powers_of_ten_uint64[counter]), value);
+ counter = 0;
+ value = 0;
+ }
+ }
+
+ // add our fraction digits, if they're available.
+ if (num.fraction.ptr != nullptr) {
+ p = num.fraction.ptr;
+ pend = p + num.fraction.len();
+ if (digits == 0) {
+ skip_zeros(p, pend);
+ }
+ // process all digits, in increments of step per loop
+ while (p != pend) {
+ if (std::is_same<UC,char>::value) {
+ while ((std::distance(p, pend) >= 8) && (step - counter >= 8) && (max_digits - digits >= 8)) {
+ parse_eight_digits(p, value, counter, digits);
+ }
+ }
+ while (counter < step && p != pend && digits < max_digits) {
+ parse_one_digit(p, value, counter, digits);
+ }
+ if (digits == max_digits) {
+ // add the temporary value, then check if we've truncated any digits
+ add_native(result, limb(powers_of_ten_uint64[counter]), value);
+ bool truncated = is_truncated(p, pend);
+ if (truncated) {
+ round_up_bigint(result, digits);
+ }
+ return;
+ } else {
+ add_native(result, limb(powers_of_ten_uint64[counter]), value);
+ counter = 0;
+ value = 0;
+ }
+ }
+ }
+
+ if (counter != 0) {
+ add_native(result, limb(powers_of_ten_uint64[counter]), value);
+ }
+}
+
+template <typename T>
+inline BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+adjusted_mantissa positive_digit_comp(bigint& bigmant, int32_t exponent) noexcept {
+ BOOST_CHARCONV_FASTFLOAT_ASSERT(bigmant.pow10(uint32_t(exponent)));
+ adjusted_mantissa answer;
+ bool truncated;
+ answer.mantissa = bigmant.hi64(truncated);
+ int bias = binary_format<T>::mantissa_explicit_bits() - binary_format<T>::minimum_exponent();
+ answer.power2 = bigmant.bit_length() - 64 + bias;
+
+ round<T>(answer, [truncated](adjusted_mantissa& a, int32_t shift) {
+ round_nearest_tie_even(a, shift, [truncated](bool is_odd, bool is_halfway, bool is_above) -> bool {
+ return is_above || (is_halfway && truncated) || (is_odd && is_halfway);
+ });
+ });
+
+ return answer;
+}
+
+// the scaling here is quite simple: we have, for the real digits `m * 10^e`,
+// and for the theoretical digits `n * 2^f`. Since `e` is always negative,
+// to scale them identically, we do `n * 2^f * 5^-f`, so we now have `m * 2^e`.
+// we then need to scale by `2^(f- e)`, and then the two significant digits
+// are of the same magnitude.
+template <typename T>
+inline BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+adjusted_mantissa negative_digit_comp(bigint& bigmant, adjusted_mantissa am, int32_t exponent) noexcept {
+ bigint& real_digits = bigmant;
+ int32_t real_exp = exponent;
+
+ // get the value of `b`, rounded down, and get a bigint representation of b+h
+ adjusted_mantissa am_b = am;
+ // gcc7 buf: use a lambda to remove the noexcept qualifier bug with -Wnoexcept-type.
+ round<T>(am_b, [](adjusted_mantissa&a, int32_t shift) { round_down(a, shift); });
+ T b;
+ to_float(false, am_b, b);
+ adjusted_mantissa theor = to_extended_halfway(b);
+ bigint theor_digits(theor.mantissa);
+ int32_t theor_exp = theor.power2;
+
+ // scale real digits and theor digits to be same power.
+ int32_t pow2_exp = theor_exp - real_exp;
+ uint32_t pow5_exp = uint32_t(-real_exp);
+ if (pow5_exp != 0) {
+ BOOST_CHARCONV_FASTFLOAT_ASSERT(theor_digits.pow5(pow5_exp));
+ }
+ if (pow2_exp > 0) {
+ BOOST_CHARCONV_FASTFLOAT_ASSERT(theor_digits.pow2(uint32_t(pow2_exp)));
+ } else if (pow2_exp < 0) {
+ BOOST_CHARCONV_FASTFLOAT_ASSERT(real_digits.pow2(uint32_t(-pow2_exp)));
+ }
+
+ // compare digits, and use it to director rounding
+ int ord = real_digits.compare(theor_digits);
+ adjusted_mantissa answer = am;
+ round<T>(answer, [ord](adjusted_mantissa& a, int32_t shift) {
+ round_nearest_tie_even(a, shift, [ord](bool is_odd, bool, bool) -> bool {
+ if (ord > 0) {
+ return true;
+ } else if (ord < 0) {
+ return false;
+ } else {
+ return is_odd;
+ }
+ });
+ });
+
+ return answer;
+}
+
+// parse the significant digits as a big integer to unambiguously round
+// the significant digits. here, we are trying to determine how to round
+// an extended float representation close to `b+h`, halfway between `b`
+// (the float rounded-down) and `b+u`, the next positive float. this
+// algorithm is always correct, and uses one of two approaches. when
+// the exponent is positive relative to the significant digits (such as
+// 1234), we create a big-integer representation, get the high 64-bits,
+// determine if any lower bits are truncated, and use that to direct
+// rounding. in case of a negative exponent relative to the significant
+// digits (such as 1.2345), we create a theoretical representation of
+// `b` as a big-integer type, scaled to the same binary exponent as
+// the actual digits. we then compare the big integer representations
+// of both, and use that to direct rounding.
+template <typename T, typename UC>
+inline BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+adjusted_mantissa digit_comp(parsed_number_string_t<UC>& num, adjusted_mantissa am) noexcept {
+ // remove the invalid exponent bias
+ am.power2 -= invalid_am_bias;
+
+ int32_t sci_exp = scientific_exponent(num);
+ size_t max_digits = binary_format<T>::max_digits();
+ size_t digits = 0;
+ bigint bigmant;
+ parse_mantissa(bigmant, num, max_digits, digits);
+ // can't underflow, since digits is at most max_digits.
+ int32_t exponent = sci_exp + 1 - int32_t(digits);
+ if (exponent >= 0) {
+ return positive_digit_comp<T>(bigmant, exponent);
+ } else {
+ return negative_digit_comp<T>(bigmant, am, exponent);
+ }
+}
+
+}}}} // namespace fast_float
+
+#endif
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/fast_float.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/fast_float.hpp
new file mode 100644
index 00000000000..00bb6c52331
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/fast_float.hpp
@@ -0,0 +1,48 @@
+// Copyright 2020-2023 Daniel Lemire
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+//
+// Derivative of: https://github.com/fastfloat/fast_float
+
+#ifndef BOOST_CHARCONV_DETAIL_FASTFLOAT_FAST_FLOAT_HPP
+#define BOOST_CHARCONV_DETAIL_FASTFLOAT_FAST_FLOAT_HPP
+
+#include <boost/charconv/detail/fast_float/float_common.hpp>
+
+namespace boost { namespace charconv { namespace detail { namespace fast_float {
+/**
+ * This function parses the character sequence [first,last) for a number. It parses floating-point numbers expecting
+ * a locale-independent format equivalent to what is used by std::strtod in the default ("C") locale.
+ * The resulting floating-point value is the closest floating-point values (using either float or double),
+ * using the "round to even" convention for values that would otherwise fall right in-between two values.
+ * That is, we provide exact parsing according to the IEEE standard.
+ *
+ * Given a successful parse, the pointer (`ptr`) in the returned value is set to point right after the
+ * parsed number, and the `value` referenced is set to the parsed value. In case of error, the returned
+ * `ec` contains a representative error, otherwise the default (`std::errc()`) value is stored.
+ *
+ * The implementation does not throw and does not allocate memory (e.g., with `new` or `malloc`).
+ *
+ * Like the C++17 standard, the `fast_float::from_chars` functions take an optional last argument of
+ * the type `fast_float::chars_format`. It is a bitset value: we check whether
+ * `fmt & fast_float::chars_format::fixed` and `fmt & fast_float::chars_format::scientific` are set
+ * to determine whether we allow the fixed point and scientific notation respectively.
+ * The default is `fast_float::chars_format::general` which allows both `fixed` and `scientific`.
+ */
+template<typename T, typename UC = char>
+BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+from_chars_result_t<UC> from_chars(UC const * first, UC const * last,
+ T &value, chars_format fmt = chars_format::general) noexcept;
+
+/**
+ * Like from_chars, but accepts an `options` argument to govern number parsing.
+ */
+template<typename T, typename UC = char>
+BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+from_chars_result_t<UC> from_chars_advanced(UC const * first, UC const * last,
+ T &value, parse_options_t<UC> options) noexcept;
+
+}}}} // namespace fast_float
+#include <boost/charconv/detail/fast_float/parse_number.hpp>
+#endif // BOOST_CHARCONV_FASTFLOAT_FAST_FLOAT_H
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/fast_table.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/fast_table.hpp
new file mode 100644
index 00000000000..e08eb314562
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/fast_table.hpp
@@ -0,0 +1,708 @@
+// Copyright 2020-2023 Daniel Lemire
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+//
+// Derivative of: https://github.com/fastfloat/fast_float
+
+#ifndef BOOST_CHARCONV_DETAIL_FASTFLOAT_FAST_TABLE_HPP
+#define BOOST_CHARCONV_DETAIL_FASTFLOAT_FAST_TABLE_HPP
+
+#include <boost/charconv/detail/fast_float/float_common.hpp>
+#include <cstdint>
+
+namespace boost { namespace charconv { namespace detail { namespace fast_float {
+
+/**
+ * When mapping numbers from decimal to binary,
+ * we go from w * 10^q to m * 2^p but we have
+ * 10^q = 5^q * 2^q, so effectively
+ * we are trying to match
+ * w * 2^q * 5^q to m * 2^p. Thus the powers of two
+ * are not a concern since they can be represented
+ * exactly using the binary notation, only the powers of five
+ * affect the binary significand.
+ */
+
+/**
+ * The smallest non-zero float (binary64) is 2^-1074.
+ * We take as input numbers of the form w x 10^q where w < 2^64.
+ * We have that w * 10^-343 < 2^(64-344) 5^-343 < 2^-1076.
+ * However, we have that
+ * (2^64-1) * 10^-342 = (2^64-1) * 2^-342 * 5^-342 > 2^-1074.
+ * Thus it is possible for a number of the form w * 10^-342 where
+ * w is a 64-bit value to be a non-zero floating-point number.
+ *********
+ * Any number of form w * 10^309 where w>= 1 is going to be
+ * infinite in binary64 so we never need to worry about powers
+ * of 5 greater than 308.
+ */
+template <class unused = void>
+struct powers_template {
+
+constexpr static int smallest_power_of_five = binary_format<double>::smallest_power_of_ten();
+constexpr static int largest_power_of_five = binary_format<double>::largest_power_of_ten();
+constexpr static int number_of_entries = 2 * (largest_power_of_five - smallest_power_of_five + 1);
+// Powers of five from 5^-342 all the way to 5^308 rounded toward one.
+constexpr static uint64_t power_of_five_128[number_of_entries] = {
+ 0xeef453d6923bd65a,0x113faa2906a13b3f,
+ 0x9558b4661b6565f8,0x4ac7ca59a424c507,
+ 0xbaaee17fa23ebf76,0x5d79bcf00d2df649,
+ 0xe95a99df8ace6f53,0xf4d82c2c107973dc,
+ 0x91d8a02bb6c10594,0x79071b9b8a4be869,
+ 0xb64ec836a47146f9,0x9748e2826cdee284,
+ 0xe3e27a444d8d98b7,0xfd1b1b2308169b25,
+ 0x8e6d8c6ab0787f72,0xfe30f0f5e50e20f7,
+ 0xb208ef855c969f4f,0xbdbd2d335e51a935,
+ 0xde8b2b66b3bc4723,0xad2c788035e61382,
+ 0x8b16fb203055ac76,0x4c3bcb5021afcc31,
+ 0xaddcb9e83c6b1793,0xdf4abe242a1bbf3d,
+ 0xd953e8624b85dd78,0xd71d6dad34a2af0d,
+ 0x87d4713d6f33aa6b,0x8672648c40e5ad68,
+ 0xa9c98d8ccb009506,0x680efdaf511f18c2,
+ 0xd43bf0effdc0ba48,0x212bd1b2566def2,
+ 0x84a57695fe98746d,0x14bb630f7604b57,
+ 0xa5ced43b7e3e9188,0x419ea3bd35385e2d,
+ 0xcf42894a5dce35ea,0x52064cac828675b9,
+ 0x818995ce7aa0e1b2,0x7343efebd1940993,
+ 0xa1ebfb4219491a1f,0x1014ebe6c5f90bf8,
+ 0xca66fa129f9b60a6,0xd41a26e077774ef6,
+ 0xfd00b897478238d0,0x8920b098955522b4,
+ 0x9e20735e8cb16382,0x55b46e5f5d5535b0,
+ 0xc5a890362fddbc62,0xeb2189f734aa831d,
+ 0xf712b443bbd52b7b,0xa5e9ec7501d523e4,
+ 0x9a6bb0aa55653b2d,0x47b233c92125366e,
+ 0xc1069cd4eabe89f8,0x999ec0bb696e840a,
+ 0xf148440a256e2c76,0xc00670ea43ca250d,
+ 0x96cd2a865764dbca,0x380406926a5e5728,
+ 0xbc807527ed3e12bc,0xc605083704f5ecf2,
+ 0xeba09271e88d976b,0xf7864a44c633682e,
+ 0x93445b8731587ea3,0x7ab3ee6afbe0211d,
+ 0xb8157268fdae9e4c,0x5960ea05bad82964,
+ 0xe61acf033d1a45df,0x6fb92487298e33bd,
+ 0x8fd0c16206306bab,0xa5d3b6d479f8e056,
+ 0xb3c4f1ba87bc8696,0x8f48a4899877186c,
+ 0xe0b62e2929aba83c,0x331acdabfe94de87,
+ 0x8c71dcd9ba0b4925,0x9ff0c08b7f1d0b14,
+ 0xaf8e5410288e1b6f,0x7ecf0ae5ee44dd9,
+ 0xdb71e91432b1a24a,0xc9e82cd9f69d6150,
+ 0x892731ac9faf056e,0xbe311c083a225cd2,
+ 0xab70fe17c79ac6ca,0x6dbd630a48aaf406,
+ 0xd64d3d9db981787d,0x92cbbccdad5b108,
+ 0x85f0468293f0eb4e,0x25bbf56008c58ea5,
+ 0xa76c582338ed2621,0xaf2af2b80af6f24e,
+ 0xd1476e2c07286faa,0x1af5af660db4aee1,
+ 0x82cca4db847945ca,0x50d98d9fc890ed4d,
+ 0xa37fce126597973c,0xe50ff107bab528a0,
+ 0xcc5fc196fefd7d0c,0x1e53ed49a96272c8,
+ 0xff77b1fcbebcdc4f,0x25e8e89c13bb0f7a,
+ 0x9faacf3df73609b1,0x77b191618c54e9ac,
+ 0xc795830d75038c1d,0xd59df5b9ef6a2417,
+ 0xf97ae3d0d2446f25,0x4b0573286b44ad1d,
+ 0x9becce62836ac577,0x4ee367f9430aec32,
+ 0xc2e801fb244576d5,0x229c41f793cda73f,
+ 0xf3a20279ed56d48a,0x6b43527578c1110f,
+ 0x9845418c345644d6,0x830a13896b78aaa9,
+ 0xbe5691ef416bd60c,0x23cc986bc656d553,
+ 0xedec366b11c6cb8f,0x2cbfbe86b7ec8aa8,
+ 0x94b3a202eb1c3f39,0x7bf7d71432f3d6a9,
+ 0xb9e08a83a5e34f07,0xdaf5ccd93fb0cc53,
+ 0xe858ad248f5c22c9,0xd1b3400f8f9cff68,
+ 0x91376c36d99995be,0x23100809b9c21fa1,
+ 0xb58547448ffffb2d,0xabd40a0c2832a78a,
+ 0xe2e69915b3fff9f9,0x16c90c8f323f516c,
+ 0x8dd01fad907ffc3b,0xae3da7d97f6792e3,
+ 0xb1442798f49ffb4a,0x99cd11cfdf41779c,
+ 0xdd95317f31c7fa1d,0x40405643d711d583,
+ 0x8a7d3eef7f1cfc52,0x482835ea666b2572,
+ 0xad1c8eab5ee43b66,0xda3243650005eecf,
+ 0xd863b256369d4a40,0x90bed43e40076a82,
+ 0x873e4f75e2224e68,0x5a7744a6e804a291,
+ 0xa90de3535aaae202,0x711515d0a205cb36,
+ 0xd3515c2831559a83,0xd5a5b44ca873e03,
+ 0x8412d9991ed58091,0xe858790afe9486c2,
+ 0xa5178fff668ae0b6,0x626e974dbe39a872,
+ 0xce5d73ff402d98e3,0xfb0a3d212dc8128f,
+ 0x80fa687f881c7f8e,0x7ce66634bc9d0b99,
+ 0xa139029f6a239f72,0x1c1fffc1ebc44e80,
+ 0xc987434744ac874e,0xa327ffb266b56220,
+ 0xfbe9141915d7a922,0x4bf1ff9f0062baa8,
+ 0x9d71ac8fada6c9b5,0x6f773fc3603db4a9,
+ 0xc4ce17b399107c22,0xcb550fb4384d21d3,
+ 0xf6019da07f549b2b,0x7e2a53a146606a48,
+ 0x99c102844f94e0fb,0x2eda7444cbfc426d,
+ 0xc0314325637a1939,0xfa911155fefb5308,
+ 0xf03d93eebc589f88,0x793555ab7eba27ca,
+ 0x96267c7535b763b5,0x4bc1558b2f3458de,
+ 0xbbb01b9283253ca2,0x9eb1aaedfb016f16,
+ 0xea9c227723ee8bcb,0x465e15a979c1cadc,
+ 0x92a1958a7675175f,0xbfacd89ec191ec9,
+ 0xb749faed14125d36,0xcef980ec671f667b,
+ 0xe51c79a85916f484,0x82b7e12780e7401a,
+ 0x8f31cc0937ae58d2,0xd1b2ecb8b0908810,
+ 0xb2fe3f0b8599ef07,0x861fa7e6dcb4aa15,
+ 0xdfbdcece67006ac9,0x67a791e093e1d49a,
+ 0x8bd6a141006042bd,0xe0c8bb2c5c6d24e0,
+ 0xaecc49914078536d,0x58fae9f773886e18,
+ 0xda7f5bf590966848,0xaf39a475506a899e,
+ 0x888f99797a5e012d,0x6d8406c952429603,
+ 0xaab37fd7d8f58178,0xc8e5087ba6d33b83,
+ 0xd5605fcdcf32e1d6,0xfb1e4a9a90880a64,
+ 0x855c3be0a17fcd26,0x5cf2eea09a55067f,
+ 0xa6b34ad8c9dfc06f,0xf42faa48c0ea481e,
+ 0xd0601d8efc57b08b,0xf13b94daf124da26,
+ 0x823c12795db6ce57,0x76c53d08d6b70858,
+ 0xa2cb1717b52481ed,0x54768c4b0c64ca6e,
+ 0xcb7ddcdda26da268,0xa9942f5dcf7dfd09,
+ 0xfe5d54150b090b02,0xd3f93b35435d7c4c,
+ 0x9efa548d26e5a6e1,0xc47bc5014a1a6daf,
+ 0xc6b8e9b0709f109a,0x359ab6419ca1091b,
+ 0xf867241c8cc6d4c0,0xc30163d203c94b62,
+ 0x9b407691d7fc44f8,0x79e0de63425dcf1d,
+ 0xc21094364dfb5636,0x985915fc12f542e4,
+ 0xf294b943e17a2bc4,0x3e6f5b7b17b2939d,
+ 0x979cf3ca6cec5b5a,0xa705992ceecf9c42,
+ 0xbd8430bd08277231,0x50c6ff782a838353,
+ 0xece53cec4a314ebd,0xa4f8bf5635246428,
+ 0x940f4613ae5ed136,0x871b7795e136be99,
+ 0xb913179899f68584,0x28e2557b59846e3f,
+ 0xe757dd7ec07426e5,0x331aeada2fe589cf,
+ 0x9096ea6f3848984f,0x3ff0d2c85def7621,
+ 0xb4bca50b065abe63,0xfed077a756b53a9,
+ 0xe1ebce4dc7f16dfb,0xd3e8495912c62894,
+ 0x8d3360f09cf6e4bd,0x64712dd7abbbd95c,
+ 0xb080392cc4349dec,0xbd8d794d96aacfb3,
+ 0xdca04777f541c567,0xecf0d7a0fc5583a0,
+ 0x89e42caaf9491b60,0xf41686c49db57244,
+ 0xac5d37d5b79b6239,0x311c2875c522ced5,
+ 0xd77485cb25823ac7,0x7d633293366b828b,
+ 0x86a8d39ef77164bc,0xae5dff9c02033197,
+ 0xa8530886b54dbdeb,0xd9f57f830283fdfc,
+ 0xd267caa862a12d66,0xd072df63c324fd7b,
+ 0x8380dea93da4bc60,0x4247cb9e59f71e6d,
+ 0xa46116538d0deb78,0x52d9be85f074e608,
+ 0xcd795be870516656,0x67902e276c921f8b,
+ 0x806bd9714632dff6,0xba1cd8a3db53b6,
+ 0xa086cfcd97bf97f3,0x80e8a40eccd228a4,
+ 0xc8a883c0fdaf7df0,0x6122cd128006b2cd,
+ 0xfad2a4b13d1b5d6c,0x796b805720085f81,
+ 0x9cc3a6eec6311a63,0xcbe3303674053bb0,
+ 0xc3f490aa77bd60fc,0xbedbfc4411068a9c,
+ 0xf4f1b4d515acb93b,0xee92fb5515482d44,
+ 0x991711052d8bf3c5,0x751bdd152d4d1c4a,
+ 0xbf5cd54678eef0b6,0xd262d45a78a0635d,
+ 0xef340a98172aace4,0x86fb897116c87c34,
+ 0x9580869f0e7aac0e,0xd45d35e6ae3d4da0,
+ 0xbae0a846d2195712,0x8974836059cca109,
+ 0xe998d258869facd7,0x2bd1a438703fc94b,
+ 0x91ff83775423cc06,0x7b6306a34627ddcf,
+ 0xb67f6455292cbf08,0x1a3bc84c17b1d542,
+ 0xe41f3d6a7377eeca,0x20caba5f1d9e4a93,
+ 0x8e938662882af53e,0x547eb47b7282ee9c,
+ 0xb23867fb2a35b28d,0xe99e619a4f23aa43,
+ 0xdec681f9f4c31f31,0x6405fa00e2ec94d4,
+ 0x8b3c113c38f9f37e,0xde83bc408dd3dd04,
+ 0xae0b158b4738705e,0x9624ab50b148d445,
+ 0xd98ddaee19068c76,0x3badd624dd9b0957,
+ 0x87f8a8d4cfa417c9,0xe54ca5d70a80e5d6,
+ 0xa9f6d30a038d1dbc,0x5e9fcf4ccd211f4c,
+ 0xd47487cc8470652b,0x7647c3200069671f,
+ 0x84c8d4dfd2c63f3b,0x29ecd9f40041e073,
+ 0xa5fb0a17c777cf09,0xf468107100525890,
+ 0xcf79cc9db955c2cc,0x7182148d4066eeb4,
+ 0x81ac1fe293d599bf,0xc6f14cd848405530,
+ 0xa21727db38cb002f,0xb8ada00e5a506a7c,
+ 0xca9cf1d206fdc03b,0xa6d90811f0e4851c,
+ 0xfd442e4688bd304a,0x908f4a166d1da663,
+ 0x9e4a9cec15763e2e,0x9a598e4e043287fe,
+ 0xc5dd44271ad3cdba,0x40eff1e1853f29fd,
+ 0xf7549530e188c128,0xd12bee59e68ef47c,
+ 0x9a94dd3e8cf578b9,0x82bb74f8301958ce,
+ 0xc13a148e3032d6e7,0xe36a52363c1faf01,
+ 0xf18899b1bc3f8ca1,0xdc44e6c3cb279ac1,
+ 0x96f5600f15a7b7e5,0x29ab103a5ef8c0b9,
+ 0xbcb2b812db11a5de,0x7415d448f6b6f0e7,
+ 0xebdf661791d60f56,0x111b495b3464ad21,
+ 0x936b9fcebb25c995,0xcab10dd900beec34,
+ 0xb84687c269ef3bfb,0x3d5d514f40eea742,
+ 0xe65829b3046b0afa,0xcb4a5a3112a5112,
+ 0x8ff71a0fe2c2e6dc,0x47f0e785eaba72ab,
+ 0xb3f4e093db73a093,0x59ed216765690f56,
+ 0xe0f218b8d25088b8,0x306869c13ec3532c,
+ 0x8c974f7383725573,0x1e414218c73a13fb,
+ 0xafbd2350644eeacf,0xe5d1929ef90898fa,
+ 0xdbac6c247d62a583,0xdf45f746b74abf39,
+ 0x894bc396ce5da772,0x6b8bba8c328eb783,
+ 0xab9eb47c81f5114f,0x66ea92f3f326564,
+ 0xd686619ba27255a2,0xc80a537b0efefebd,
+ 0x8613fd0145877585,0xbd06742ce95f5f36,
+ 0xa798fc4196e952e7,0x2c48113823b73704,
+ 0xd17f3b51fca3a7a0,0xf75a15862ca504c5,
+ 0x82ef85133de648c4,0x9a984d73dbe722fb,
+ 0xa3ab66580d5fdaf5,0xc13e60d0d2e0ebba,
+ 0xcc963fee10b7d1b3,0x318df905079926a8,
+ 0xffbbcfe994e5c61f,0xfdf17746497f7052,
+ 0x9fd561f1fd0f9bd3,0xfeb6ea8bedefa633,
+ 0xc7caba6e7c5382c8,0xfe64a52ee96b8fc0,
+ 0xf9bd690a1b68637b,0x3dfdce7aa3c673b0,
+ 0x9c1661a651213e2d,0x6bea10ca65c084e,
+ 0xc31bfa0fe5698db8,0x486e494fcff30a62,
+ 0xf3e2f893dec3f126,0x5a89dba3c3efccfa,
+ 0x986ddb5c6b3a76b7,0xf89629465a75e01c,
+ 0xbe89523386091465,0xf6bbb397f1135823,
+ 0xee2ba6c0678b597f,0x746aa07ded582e2c,
+ 0x94db483840b717ef,0xa8c2a44eb4571cdc,
+ 0xba121a4650e4ddeb,0x92f34d62616ce413,
+ 0xe896a0d7e51e1566,0x77b020baf9c81d17,
+ 0x915e2486ef32cd60,0xace1474dc1d122e,
+ 0xb5b5ada8aaff80b8,0xd819992132456ba,
+ 0xe3231912d5bf60e6,0x10e1fff697ed6c69,
+ 0x8df5efabc5979c8f,0xca8d3ffa1ef463c1,
+ 0xb1736b96b6fd83b3,0xbd308ff8a6b17cb2,
+ 0xddd0467c64bce4a0,0xac7cb3f6d05ddbde,
+ 0x8aa22c0dbef60ee4,0x6bcdf07a423aa96b,
+ 0xad4ab7112eb3929d,0x86c16c98d2c953c6,
+ 0xd89d64d57a607744,0xe871c7bf077ba8b7,
+ 0x87625f056c7c4a8b,0x11471cd764ad4972,
+ 0xa93af6c6c79b5d2d,0xd598e40d3dd89bcf,
+ 0xd389b47879823479,0x4aff1d108d4ec2c3,
+ 0x843610cb4bf160cb,0xcedf722a585139ba,
+ 0xa54394fe1eedb8fe,0xc2974eb4ee658828,
+ 0xce947a3da6a9273e,0x733d226229feea32,
+ 0x811ccc668829b887,0x806357d5a3f525f,
+ 0xa163ff802a3426a8,0xca07c2dcb0cf26f7,
+ 0xc9bcff6034c13052,0xfc89b393dd02f0b5,
+ 0xfc2c3f3841f17c67,0xbbac2078d443ace2,
+ 0x9d9ba7832936edc0,0xd54b944b84aa4c0d,
+ 0xc5029163f384a931,0xa9e795e65d4df11,
+ 0xf64335bcf065d37d,0x4d4617b5ff4a16d5,
+ 0x99ea0196163fa42e,0x504bced1bf8e4e45,
+ 0xc06481fb9bcf8d39,0xe45ec2862f71e1d6,
+ 0xf07da27a82c37088,0x5d767327bb4e5a4c,
+ 0x964e858c91ba2655,0x3a6a07f8d510f86f,
+ 0xbbe226efb628afea,0x890489f70a55368b,
+ 0xeadab0aba3b2dbe5,0x2b45ac74ccea842e,
+ 0x92c8ae6b464fc96f,0x3b0b8bc90012929d,
+ 0xb77ada0617e3bbcb,0x9ce6ebb40173744,
+ 0xe55990879ddcaabd,0xcc420a6a101d0515,
+ 0x8f57fa54c2a9eab6,0x9fa946824a12232d,
+ 0xb32df8e9f3546564,0x47939822dc96abf9,
+ 0xdff9772470297ebd,0x59787e2b93bc56f7,
+ 0x8bfbea76c619ef36,0x57eb4edb3c55b65a,
+ 0xaefae51477a06b03,0xede622920b6b23f1,
+ 0xdab99e59958885c4,0xe95fab368e45eced,
+ 0x88b402f7fd75539b,0x11dbcb0218ebb414,
+ 0xaae103b5fcd2a881,0xd652bdc29f26a119,
+ 0xd59944a37c0752a2,0x4be76d3346f0495f,
+ 0x857fcae62d8493a5,0x6f70a4400c562ddb,
+ 0xa6dfbd9fb8e5b88e,0xcb4ccd500f6bb952,
+ 0xd097ad07a71f26b2,0x7e2000a41346a7a7,
+ 0x825ecc24c873782f,0x8ed400668c0c28c8,
+ 0xa2f67f2dfa90563b,0x728900802f0f32fa,
+ 0xcbb41ef979346bca,0x4f2b40a03ad2ffb9,
+ 0xfea126b7d78186bc,0xe2f610c84987bfa8,
+ 0x9f24b832e6b0f436,0xdd9ca7d2df4d7c9,
+ 0xc6ede63fa05d3143,0x91503d1c79720dbb,
+ 0xf8a95fcf88747d94,0x75a44c6397ce912a,
+ 0x9b69dbe1b548ce7c,0xc986afbe3ee11aba,
+ 0xc24452da229b021b,0xfbe85badce996168,
+ 0xf2d56790ab41c2a2,0xfae27299423fb9c3,
+ 0x97c560ba6b0919a5,0xdccd879fc967d41a,
+ 0xbdb6b8e905cb600f,0x5400e987bbc1c920,
+ 0xed246723473e3813,0x290123e9aab23b68,
+ 0x9436c0760c86e30b,0xf9a0b6720aaf6521,
+ 0xb94470938fa89bce,0xf808e40e8d5b3e69,
+ 0xe7958cb87392c2c2,0xb60b1d1230b20e04,
+ 0x90bd77f3483bb9b9,0xb1c6f22b5e6f48c2,
+ 0xb4ecd5f01a4aa828,0x1e38aeb6360b1af3,
+ 0xe2280b6c20dd5232,0x25c6da63c38de1b0,
+ 0x8d590723948a535f,0x579c487e5a38ad0e,
+ 0xb0af48ec79ace837,0x2d835a9df0c6d851,
+ 0xdcdb1b2798182244,0xf8e431456cf88e65,
+ 0x8a08f0f8bf0f156b,0x1b8e9ecb641b58ff,
+ 0xac8b2d36eed2dac5,0xe272467e3d222f3f,
+ 0xd7adf884aa879177,0x5b0ed81dcc6abb0f,
+ 0x86ccbb52ea94baea,0x98e947129fc2b4e9,
+ 0xa87fea27a539e9a5,0x3f2398d747b36224,
+ 0xd29fe4b18e88640e,0x8eec7f0d19a03aad,
+ 0x83a3eeeef9153e89,0x1953cf68300424ac,
+ 0xa48ceaaab75a8e2b,0x5fa8c3423c052dd7,
+ 0xcdb02555653131b6,0x3792f412cb06794d,
+ 0x808e17555f3ebf11,0xe2bbd88bbee40bd0,
+ 0xa0b19d2ab70e6ed6,0x5b6aceaeae9d0ec4,
+ 0xc8de047564d20a8b,0xf245825a5a445275,
+ 0xfb158592be068d2e,0xeed6e2f0f0d56712,
+ 0x9ced737bb6c4183d,0x55464dd69685606b,
+ 0xc428d05aa4751e4c,0xaa97e14c3c26b886,
+ 0xf53304714d9265df,0xd53dd99f4b3066a8,
+ 0x993fe2c6d07b7fab,0xe546a8038efe4029,
+ 0xbf8fdb78849a5f96,0xde98520472bdd033,
+ 0xef73d256a5c0f77c,0x963e66858f6d4440,
+ 0x95a8637627989aad,0xdde7001379a44aa8,
+ 0xbb127c53b17ec159,0x5560c018580d5d52,
+ 0xe9d71b689dde71af,0xaab8f01e6e10b4a6,
+ 0x9226712162ab070d,0xcab3961304ca70e8,
+ 0xb6b00d69bb55c8d1,0x3d607b97c5fd0d22,
+ 0xe45c10c42a2b3b05,0x8cb89a7db77c506a,
+ 0x8eb98a7a9a5b04e3,0x77f3608e92adb242,
+ 0xb267ed1940f1c61c,0x55f038b237591ed3,
+ 0xdf01e85f912e37a3,0x6b6c46dec52f6688,
+ 0x8b61313bbabce2c6,0x2323ac4b3b3da015,
+ 0xae397d8aa96c1b77,0xabec975e0a0d081a,
+ 0xd9c7dced53c72255,0x96e7bd358c904a21,
+ 0x881cea14545c7575,0x7e50d64177da2e54,
+ 0xaa242499697392d2,0xdde50bd1d5d0b9e9,
+ 0xd4ad2dbfc3d07787,0x955e4ec64b44e864,
+ 0x84ec3c97da624ab4,0xbd5af13bef0b113e,
+ 0xa6274bbdd0fadd61,0xecb1ad8aeacdd58e,
+ 0xcfb11ead453994ba,0x67de18eda5814af2,
+ 0x81ceb32c4b43fcf4,0x80eacf948770ced7,
+ 0xa2425ff75e14fc31,0xa1258379a94d028d,
+ 0xcad2f7f5359a3b3e,0x96ee45813a04330,
+ 0xfd87b5f28300ca0d,0x8bca9d6e188853fc,
+ 0x9e74d1b791e07e48,0x775ea264cf55347e,
+ 0xc612062576589dda,0x95364afe032a819e,
+ 0xf79687aed3eec551,0x3a83ddbd83f52205,
+ 0x9abe14cd44753b52,0xc4926a9672793543,
+ 0xc16d9a0095928a27,0x75b7053c0f178294,
+ 0xf1c90080baf72cb1,0x5324c68b12dd6339,
+ 0x971da05074da7bee,0xd3f6fc16ebca5e04,
+ 0xbce5086492111aea,0x88f4bb1ca6bcf585,
+ 0xec1e4a7db69561a5,0x2b31e9e3d06c32e6,
+ 0x9392ee8e921d5d07,0x3aff322e62439fd0,
+ 0xb877aa3236a4b449,0x9befeb9fad487c3,
+ 0xe69594bec44de15b,0x4c2ebe687989a9b4,
+ 0x901d7cf73ab0acd9,0xf9d37014bf60a11,
+ 0xb424dc35095cd80f,0x538484c19ef38c95,
+ 0xe12e13424bb40e13,0x2865a5f206b06fba,
+ 0x8cbccc096f5088cb,0xf93f87b7442e45d4,
+ 0xafebff0bcb24aafe,0xf78f69a51539d749,
+ 0xdbe6fecebdedd5be,0xb573440e5a884d1c,
+ 0x89705f4136b4a597,0x31680a88f8953031,
+ 0xabcc77118461cefc,0xfdc20d2b36ba7c3e,
+ 0xd6bf94d5e57a42bc,0x3d32907604691b4d,
+ 0x8637bd05af6c69b5,0xa63f9a49c2c1b110,
+ 0xa7c5ac471b478423,0xfcf80dc33721d54,
+ 0xd1b71758e219652b,0xd3c36113404ea4a9,
+ 0x83126e978d4fdf3b,0x645a1cac083126ea,
+ 0xa3d70a3d70a3d70a,0x3d70a3d70a3d70a4,
+ 0xcccccccccccccccc,0xcccccccccccccccd,
+ 0x8000000000000000,0x0,
+ 0xa000000000000000,0x0,
+ 0xc800000000000000,0x0,
+ 0xfa00000000000000,0x0,
+ 0x9c40000000000000,0x0,
+ 0xc350000000000000,0x0,
+ 0xf424000000000000,0x0,
+ 0x9896800000000000,0x0,
+ 0xbebc200000000000,0x0,
+ 0xee6b280000000000,0x0,
+ 0x9502f90000000000,0x0,
+ 0xba43b74000000000,0x0,
+ 0xe8d4a51000000000,0x0,
+ 0x9184e72a00000000,0x0,
+ 0xb5e620f480000000,0x0,
+ 0xe35fa931a0000000,0x0,
+ 0x8e1bc9bf04000000,0x0,
+ 0xb1a2bc2ec5000000,0x0,
+ 0xde0b6b3a76400000,0x0,
+ 0x8ac7230489e80000,0x0,
+ 0xad78ebc5ac620000,0x0,
+ 0xd8d726b7177a8000,0x0,
+ 0x878678326eac9000,0x0,
+ 0xa968163f0a57b400,0x0,
+ 0xd3c21bcecceda100,0x0,
+ 0x84595161401484a0,0x0,
+ 0xa56fa5b99019a5c8,0x0,
+ 0xcecb8f27f4200f3a,0x0,
+ 0x813f3978f8940984,0x4000000000000000,
+ 0xa18f07d736b90be5,0x5000000000000000,
+ 0xc9f2c9cd04674ede,0xa400000000000000,
+ 0xfc6f7c4045812296,0x4d00000000000000,
+ 0x9dc5ada82b70b59d,0xf020000000000000,
+ 0xc5371912364ce305,0x6c28000000000000,
+ 0xf684df56c3e01bc6,0xc732000000000000,
+ 0x9a130b963a6c115c,0x3c7f400000000000,
+ 0xc097ce7bc90715b3,0x4b9f100000000000,
+ 0xf0bdc21abb48db20,0x1e86d40000000000,
+ 0x96769950b50d88f4,0x1314448000000000,
+ 0xbc143fa4e250eb31,0x17d955a000000000,
+ 0xeb194f8e1ae525fd,0x5dcfab0800000000,
+ 0x92efd1b8d0cf37be,0x5aa1cae500000000,
+ 0xb7abc627050305ad,0xf14a3d9e40000000,
+ 0xe596b7b0c643c719,0x6d9ccd05d0000000,
+ 0x8f7e32ce7bea5c6f,0xe4820023a2000000,
+ 0xb35dbf821ae4f38b,0xdda2802c8a800000,
+ 0xe0352f62a19e306e,0xd50b2037ad200000,
+ 0x8c213d9da502de45,0x4526f422cc340000,
+ 0xaf298d050e4395d6,0x9670b12b7f410000,
+ 0xdaf3f04651d47b4c,0x3c0cdd765f114000,
+ 0x88d8762bf324cd0f,0xa5880a69fb6ac800,
+ 0xab0e93b6efee0053,0x8eea0d047a457a00,
+ 0xd5d238a4abe98068,0x72a4904598d6d880,
+ 0x85a36366eb71f041,0x47a6da2b7f864750,
+ 0xa70c3c40a64e6c51,0x999090b65f67d924,
+ 0xd0cf4b50cfe20765,0xfff4b4e3f741cf6d,
+ 0x82818f1281ed449f,0xbff8f10e7a8921a4,
+ 0xa321f2d7226895c7,0xaff72d52192b6a0d,
+ 0xcbea6f8ceb02bb39,0x9bf4f8a69f764490,
+ 0xfee50b7025c36a08,0x2f236d04753d5b4,
+ 0x9f4f2726179a2245,0x1d762422c946590,
+ 0xc722f0ef9d80aad6,0x424d3ad2b7b97ef5,
+ 0xf8ebad2b84e0d58b,0xd2e0898765a7deb2,
+ 0x9b934c3b330c8577,0x63cc55f49f88eb2f,
+ 0xc2781f49ffcfa6d5,0x3cbf6b71c76b25fb,
+ 0xf316271c7fc3908a,0x8bef464e3945ef7a,
+ 0x97edd871cfda3a56,0x97758bf0e3cbb5ac,
+ 0xbde94e8e43d0c8ec,0x3d52eeed1cbea317,
+ 0xed63a231d4c4fb27,0x4ca7aaa863ee4bdd,
+ 0x945e455f24fb1cf8,0x8fe8caa93e74ef6a,
+ 0xb975d6b6ee39e436,0xb3e2fd538e122b44,
+ 0xe7d34c64a9c85d44,0x60dbbca87196b616,
+ 0x90e40fbeea1d3a4a,0xbc8955e946fe31cd,
+ 0xb51d13aea4a488dd,0x6babab6398bdbe41,
+ 0xe264589a4dcdab14,0xc696963c7eed2dd1,
+ 0x8d7eb76070a08aec,0xfc1e1de5cf543ca2,
+ 0xb0de65388cc8ada8,0x3b25a55f43294bcb,
+ 0xdd15fe86affad912,0x49ef0eb713f39ebe,
+ 0x8a2dbf142dfcc7ab,0x6e3569326c784337,
+ 0xacb92ed9397bf996,0x49c2c37f07965404,
+ 0xd7e77a8f87daf7fb,0xdc33745ec97be906,
+ 0x86f0ac99b4e8dafd,0x69a028bb3ded71a3,
+ 0xa8acd7c0222311bc,0xc40832ea0d68ce0c,
+ 0xd2d80db02aabd62b,0xf50a3fa490c30190,
+ 0x83c7088e1aab65db,0x792667c6da79e0fa,
+ 0xa4b8cab1a1563f52,0x577001b891185938,
+ 0xcde6fd5e09abcf26,0xed4c0226b55e6f86,
+ 0x80b05e5ac60b6178,0x544f8158315b05b4,
+ 0xa0dc75f1778e39d6,0x696361ae3db1c721,
+ 0xc913936dd571c84c,0x3bc3a19cd1e38e9,
+ 0xfb5878494ace3a5f,0x4ab48a04065c723,
+ 0x9d174b2dcec0e47b,0x62eb0d64283f9c76,
+ 0xc45d1df942711d9a,0x3ba5d0bd324f8394,
+ 0xf5746577930d6500,0xca8f44ec7ee36479,
+ 0x9968bf6abbe85f20,0x7e998b13cf4e1ecb,
+ 0xbfc2ef456ae276e8,0x9e3fedd8c321a67e,
+ 0xefb3ab16c59b14a2,0xc5cfe94ef3ea101e,
+ 0x95d04aee3b80ece5,0xbba1f1d158724a12,
+ 0xbb445da9ca61281f,0x2a8a6e45ae8edc97,
+ 0xea1575143cf97226,0xf52d09d71a3293bd,
+ 0x924d692ca61be758,0x593c2626705f9c56,
+ 0xb6e0c377cfa2e12e,0x6f8b2fb00c77836c,
+ 0xe498f455c38b997a,0xb6dfb9c0f956447,
+ 0x8edf98b59a373fec,0x4724bd4189bd5eac,
+ 0xb2977ee300c50fe7,0x58edec91ec2cb657,
+ 0xdf3d5e9bc0f653e1,0x2f2967b66737e3ed,
+ 0x8b865b215899f46c,0xbd79e0d20082ee74,
+ 0xae67f1e9aec07187,0xecd8590680a3aa11,
+ 0xda01ee641a708de9,0xe80e6f4820cc9495,
+ 0x884134fe908658b2,0x3109058d147fdcdd,
+ 0xaa51823e34a7eede,0xbd4b46f0599fd415,
+ 0xd4e5e2cdc1d1ea96,0x6c9e18ac7007c91a,
+ 0x850fadc09923329e,0x3e2cf6bc604ddb0,
+ 0xa6539930bf6bff45,0x84db8346b786151c,
+ 0xcfe87f7cef46ff16,0xe612641865679a63,
+ 0x81f14fae158c5f6e,0x4fcb7e8f3f60c07e,
+ 0xa26da3999aef7749,0xe3be5e330f38f09d,
+ 0xcb090c8001ab551c,0x5cadf5bfd3072cc5,
+ 0xfdcb4fa002162a63,0x73d9732fc7c8f7f6,
+ 0x9e9f11c4014dda7e,0x2867e7fddcdd9afa,
+ 0xc646d63501a1511d,0xb281e1fd541501b8,
+ 0xf7d88bc24209a565,0x1f225a7ca91a4226,
+ 0x9ae757596946075f,0x3375788de9b06958,
+ 0xc1a12d2fc3978937,0x52d6b1641c83ae,
+ 0xf209787bb47d6b84,0xc0678c5dbd23a49a,
+ 0x9745eb4d50ce6332,0xf840b7ba963646e0,
+ 0xbd176620a501fbff,0xb650e5a93bc3d898,
+ 0xec5d3fa8ce427aff,0xa3e51f138ab4cebe,
+ 0x93ba47c980e98cdf,0xc66f336c36b10137,
+ 0xb8a8d9bbe123f017,0xb80b0047445d4184,
+ 0xe6d3102ad96cec1d,0xa60dc059157491e5,
+ 0x9043ea1ac7e41392,0x87c89837ad68db2f,
+ 0xb454e4a179dd1877,0x29babe4598c311fb,
+ 0xe16a1dc9d8545e94,0xf4296dd6fef3d67a,
+ 0x8ce2529e2734bb1d,0x1899e4a65f58660c,
+ 0xb01ae745b101e9e4,0x5ec05dcff72e7f8f,
+ 0xdc21a1171d42645d,0x76707543f4fa1f73,
+ 0x899504ae72497eba,0x6a06494a791c53a8,
+ 0xabfa45da0edbde69,0x487db9d17636892,
+ 0xd6f8d7509292d603,0x45a9d2845d3c42b6,
+ 0x865b86925b9bc5c2,0xb8a2392ba45a9b2,
+ 0xa7f26836f282b732,0x8e6cac7768d7141e,
+ 0xd1ef0244af2364ff,0x3207d795430cd926,
+ 0x8335616aed761f1f,0x7f44e6bd49e807b8,
+ 0xa402b9c5a8d3a6e7,0x5f16206c9c6209a6,
+ 0xcd036837130890a1,0x36dba887c37a8c0f,
+ 0x802221226be55a64,0xc2494954da2c9789,
+ 0xa02aa96b06deb0fd,0xf2db9baa10b7bd6c,
+ 0xc83553c5c8965d3d,0x6f92829494e5acc7,
+ 0xfa42a8b73abbf48c,0xcb772339ba1f17f9,
+ 0x9c69a97284b578d7,0xff2a760414536efb,
+ 0xc38413cf25e2d70d,0xfef5138519684aba,
+ 0xf46518c2ef5b8cd1,0x7eb258665fc25d69,
+ 0x98bf2f79d5993802,0xef2f773ffbd97a61,
+ 0xbeeefb584aff8603,0xaafb550ffacfd8fa,
+ 0xeeaaba2e5dbf6784,0x95ba2a53f983cf38,
+ 0x952ab45cfa97a0b2,0xdd945a747bf26183,
+ 0xba756174393d88df,0x94f971119aeef9e4,
+ 0xe912b9d1478ceb17,0x7a37cd5601aab85d,
+ 0x91abb422ccb812ee,0xac62e055c10ab33a,
+ 0xb616a12b7fe617aa,0x577b986b314d6009,
+ 0xe39c49765fdf9d94,0xed5a7e85fda0b80b,
+ 0x8e41ade9fbebc27d,0x14588f13be847307,
+ 0xb1d219647ae6b31c,0x596eb2d8ae258fc8,
+ 0xde469fbd99a05fe3,0x6fca5f8ed9aef3bb,
+ 0x8aec23d680043bee,0x25de7bb9480d5854,
+ 0xada72ccc20054ae9,0xaf561aa79a10ae6a,
+ 0xd910f7ff28069da4,0x1b2ba1518094da04,
+ 0x87aa9aff79042286,0x90fb44d2f05d0842,
+ 0xa99541bf57452b28,0x353a1607ac744a53,
+ 0xd3fa922f2d1675f2,0x42889b8997915ce8,
+ 0x847c9b5d7c2e09b7,0x69956135febada11,
+ 0xa59bc234db398c25,0x43fab9837e699095,
+ 0xcf02b2c21207ef2e,0x94f967e45e03f4bb,
+ 0x8161afb94b44f57d,0x1d1be0eebac278f5,
+ 0xa1ba1ba79e1632dc,0x6462d92a69731732,
+ 0xca28a291859bbf93,0x7d7b8f7503cfdcfe,
+ 0xfcb2cb35e702af78,0x5cda735244c3d43e,
+ 0x9defbf01b061adab,0x3a0888136afa64a7,
+ 0xc56baec21c7a1916,0x88aaa1845b8fdd0,
+ 0xf6c69a72a3989f5b,0x8aad549e57273d45,
+ 0x9a3c2087a63f6399,0x36ac54e2f678864b,
+ 0xc0cb28a98fcf3c7f,0x84576a1bb416a7dd,
+ 0xf0fdf2d3f3c30b9f,0x656d44a2a11c51d5,
+ 0x969eb7c47859e743,0x9f644ae5a4b1b325,
+ 0xbc4665b596706114,0x873d5d9f0dde1fee,
+ 0xeb57ff22fc0c7959,0xa90cb506d155a7ea,
+ 0x9316ff75dd87cbd8,0x9a7f12442d588f2,
+ 0xb7dcbf5354e9bece,0xc11ed6d538aeb2f,
+ 0xe5d3ef282a242e81,0x8f1668c8a86da5fa,
+ 0x8fa475791a569d10,0xf96e017d694487bc,
+ 0xb38d92d760ec4455,0x37c981dcc395a9ac,
+ 0xe070f78d3927556a,0x85bbe253f47b1417,
+ 0x8c469ab843b89562,0x93956d7478ccec8e,
+ 0xaf58416654a6babb,0x387ac8d1970027b2,
+ 0xdb2e51bfe9d0696a,0x6997b05fcc0319e,
+ 0x88fcf317f22241e2,0x441fece3bdf81f03,
+ 0xab3c2fddeeaad25a,0xd527e81cad7626c3,
+ 0xd60b3bd56a5586f1,0x8a71e223d8d3b074,
+ 0x85c7056562757456,0xf6872d5667844e49,
+ 0xa738c6bebb12d16c,0xb428f8ac016561db,
+ 0xd106f86e69d785c7,0xe13336d701beba52,
+ 0x82a45b450226b39c,0xecc0024661173473,
+ 0xa34d721642b06084,0x27f002d7f95d0190,
+ 0xcc20ce9bd35c78a5,0x31ec038df7b441f4,
+ 0xff290242c83396ce,0x7e67047175a15271,
+ 0x9f79a169bd203e41,0xf0062c6e984d386,
+ 0xc75809c42c684dd1,0x52c07b78a3e60868,
+ 0xf92e0c3537826145,0xa7709a56ccdf8a82,
+ 0x9bbcc7a142b17ccb,0x88a66076400bb691,
+ 0xc2abf989935ddbfe,0x6acff893d00ea435,
+ 0xf356f7ebf83552fe,0x583f6b8c4124d43,
+ 0x98165af37b2153de,0xc3727a337a8b704a,
+ 0xbe1bf1b059e9a8d6,0x744f18c0592e4c5c,
+ 0xeda2ee1c7064130c,0x1162def06f79df73,
+ 0x9485d4d1c63e8be7,0x8addcb5645ac2ba8,
+ 0xb9a74a0637ce2ee1,0x6d953e2bd7173692,
+ 0xe8111c87c5c1ba99,0xc8fa8db6ccdd0437,
+ 0x910ab1d4db9914a0,0x1d9c9892400a22a2,
+ 0xb54d5e4a127f59c8,0x2503beb6d00cab4b,
+ 0xe2a0b5dc971f303a,0x2e44ae64840fd61d,
+ 0x8da471a9de737e24,0x5ceaecfed289e5d2,
+ 0xb10d8e1456105dad,0x7425a83e872c5f47,
+ 0xdd50f1996b947518,0xd12f124e28f77719,
+ 0x8a5296ffe33cc92f,0x82bd6b70d99aaa6f,
+ 0xace73cbfdc0bfb7b,0x636cc64d1001550b,
+ 0xd8210befd30efa5a,0x3c47f7e05401aa4e,
+ 0x8714a775e3e95c78,0x65acfaec34810a71,
+ 0xa8d9d1535ce3b396,0x7f1839a741a14d0d,
+ 0xd31045a8341ca07c,0x1ede48111209a050,
+ 0x83ea2b892091e44d,0x934aed0aab460432,
+ 0xa4e4b66b68b65d60,0xf81da84d5617853f,
+ 0xce1de40642e3f4b9,0x36251260ab9d668e,
+ 0x80d2ae83e9ce78f3,0xc1d72b7c6b426019,
+ 0xa1075a24e4421730,0xb24cf65b8612f81f,
+ 0xc94930ae1d529cfc,0xdee033f26797b627,
+ 0xfb9b7cd9a4a7443c,0x169840ef017da3b1,
+ 0x9d412e0806e88aa5,0x8e1f289560ee864e,
+ 0xc491798a08a2ad4e,0xf1a6f2bab92a27e2,
+ 0xf5b5d7ec8acb58a2,0xae10af696774b1db,
+ 0x9991a6f3d6bf1765,0xacca6da1e0a8ef29,
+ 0xbff610b0cc6edd3f,0x17fd090a58d32af3,
+ 0xeff394dcff8a948e,0xddfc4b4cef07f5b0,
+ 0x95f83d0a1fb69cd9,0x4abdaf101564f98e,
+ 0xbb764c4ca7a4440f,0x9d6d1ad41abe37f1,
+ 0xea53df5fd18d5513,0x84c86189216dc5ed,
+ 0x92746b9be2f8552c,0x32fd3cf5b4e49bb4,
+ 0xb7118682dbb66a77,0x3fbc8c33221dc2a1,
+ 0xe4d5e82392a40515,0xfabaf3feaa5334a,
+ 0x8f05b1163ba6832d,0x29cb4d87f2a7400e,
+ 0xb2c71d5bca9023f8,0x743e20e9ef511012,
+ 0xdf78e4b2bd342cf6,0x914da9246b255416,
+ 0x8bab8eefb6409c1a,0x1ad089b6c2f7548e,
+ 0xae9672aba3d0c320,0xa184ac2473b529b1,
+ 0xda3c0f568cc4f3e8,0xc9e5d72d90a2741e,
+ 0x8865899617fb1871,0x7e2fa67c7a658892,
+ 0xaa7eebfb9df9de8d,0xddbb901b98feeab7,
+ 0xd51ea6fa85785631,0x552a74227f3ea565,
+ 0x8533285c936b35de,0xd53a88958f87275f,
+ 0xa67ff273b8460356,0x8a892abaf368f137,
+ 0xd01fef10a657842c,0x2d2b7569b0432d85,
+ 0x8213f56a67f6b29b,0x9c3b29620e29fc73,
+ 0xa298f2c501f45f42,0x8349f3ba91b47b8f,
+ 0xcb3f2f7642717713,0x241c70a936219a73,
+ 0xfe0efb53d30dd4d7,0xed238cd383aa0110,
+ 0x9ec95d1463e8a506,0xf4363804324a40aa,
+ 0xc67bb4597ce2ce48,0xb143c6053edcd0d5,
+ 0xf81aa16fdc1b81da,0xdd94b7868e94050a,
+ 0x9b10a4e5e9913128,0xca7cf2b4191c8326,
+ 0xc1d4ce1f63f57d72,0xfd1c2f611f63a3f0,
+ 0xf24a01a73cf2dccf,0xbc633b39673c8cec,
+ 0x976e41088617ca01,0xd5be0503e085d813,
+ 0xbd49d14aa79dbc82,0x4b2d8644d8a74e18,
+ 0xec9c459d51852ba2,0xddf8e7d60ed1219e,
+ 0x93e1ab8252f33b45,0xcabb90e5c942b503,
+ 0xb8da1662e7b00a17,0x3d6a751f3b936243,
+ 0xe7109bfba19c0c9d,0xcc512670a783ad4,
+ 0x906a617d450187e2,0x27fb2b80668b24c5,
+ 0xb484f9dc9641e9da,0xb1f9f660802dedf6,
+ 0xe1a63853bbd26451,0x5e7873f8a0396973,
+ 0x8d07e33455637eb2,0xdb0b487b6423e1e8,
+ 0xb049dc016abc5e5f,0x91ce1a9a3d2cda62,
+ 0xdc5c5301c56b75f7,0x7641a140cc7810fb,
+ 0x89b9b3e11b6329ba,0xa9e904c87fcb0a9d,
+ 0xac2820d9623bf429,0x546345fa9fbdcd44,
+ 0xd732290fbacaf133,0xa97c177947ad4095,
+ 0x867f59a9d4bed6c0,0x49ed8eabcccc485d,
+ 0xa81f301449ee8c70,0x5c68f256bfff5a74,
+ 0xd226fc195c6a2f8c,0x73832eec6fff3111,
+ 0x83585d8fd9c25db7,0xc831fd53c5ff7eab,
+ 0xa42e74f3d032f525,0xba3e7ca8b77f5e55,
+ 0xcd3a1230c43fb26f,0x28ce1bd2e55f35eb,
+ 0x80444b5e7aa7cf85,0x7980d163cf5b81b3,
+ 0xa0555e361951c366,0xd7e105bcc332621f,
+ 0xc86ab5c39fa63440,0x8dd9472bf3fefaa7,
+ 0xfa856334878fc150,0xb14f98f6f0feb951,
+ 0x9c935e00d4b9d8d2,0x6ed1bf9a569f33d3,
+ 0xc3b8358109e84f07,0xa862f80ec4700c8,
+ 0xf4a642e14c6262c8,0xcd27bb612758c0fa,
+ 0x98e7e9cccfbd7dbd,0x8038d51cb897789c,
+ 0xbf21e44003acdd2c,0xe0470a63e6bd56c3,
+ 0xeeea5d5004981478,0x1858ccfce06cac74,
+ 0x95527a5202df0ccb,0xf37801e0c43ebc8,
+ 0xbaa718e68396cffd,0xd30560258f54e6ba,
+ 0xe950df20247c83fd,0x47c6b82ef32a2069,
+ 0x91d28b7416cdd27e,0x4cdc331d57fa5441,
+ 0xb6472e511c81471d,0xe0133fe4adf8e952,
+ 0xe3d8f9e563a198e5,0x58180fddd97723a6,
+ 0x8e679c2f5e44ff8f,0x570f09eaa7ea7648,};
+};
+
+template <class unused>
+constexpr uint64_t powers_template<unused>::power_of_five_128[number_of_entries];
+
+using powers = powers_template<>;
+
+}}}} // namespace fast_float
+
+#endif
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/float_common.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/float_common.hpp
new file mode 100644
index 00000000000..0b9d3aee584
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/float_common.hpp
@@ -0,0 +1,628 @@
+// Copyright 2020-2023 Daniel Lemire
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+//
+// Derivative of: https://github.com/fastfloat/fast_float
+
+#ifndef BOOST_CHARCONV_DETAIL_FASTFLOAT_FLOAT_COMMON_HPP
+#define BOOST_CHARCONV_DETAIL_FASTFLOAT_FLOAT_COMMON_HPP
+
+#include <boost/charconv/detail/fast_float/constexpr_feature_detect.hpp>
+#include <boost/charconv/detail/from_chars_result.hpp>
+#include <boost/charconv/detail/config.hpp>
+#include <boost/charconv/chars_format.hpp>
+#include <cfloat>
+#include <cstdint>
+#include <cassert>
+#include <cstring>
+#include <type_traits>
+#include <system_error>
+
+namespace boost { namespace charconv { namespace detail { namespace fast_float {
+
+
+template <typename UC>
+struct parse_options_t {
+ constexpr explicit parse_options_t(chars_format fmt = chars_format::general,
+ UC dot = UC('.'))
+ : format(fmt), decimal_point(dot) {}
+
+ /** Which number formats are accepted */
+ chars_format format;
+ /** The character used as decimal point */
+ UC decimal_point;
+};
+using parse_options = parse_options_t<char>;
+
+}}}}
+
+#if BOOST_CHARCONV_FASTFLOAT_HAS_BIT_CAST
+#include <bit>
+#endif
+
+#if (defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) \
+ || defined(__amd64) || defined(__aarch64__) || defined(_M_ARM64) \
+ || defined(__MINGW64__) \
+ || defined(__s390x__) \
+ || (defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || defined(__PPC64LE__)) )
+#define BOOST_CHARCONV_FASTFLOAT_64BIT 1
+#elif (defined(__i386) || defined(__i386__) || defined(_M_IX86) \
+ || defined(__arm__) || defined(_M_ARM) || defined(__ppc__) \
+ || defined(__MINGW32__) || defined(__EMSCRIPTEN__))
+#define BOOST_CHARCONV_FASTFLOAT_32BIT 1
+#else
+ // Need to check incrementally, since SIZE_MAX is a size_t, avoid overflow.
+ // We can never tell the register width, but the SIZE_MAX is a good approximation.
+ // UINTPTR_MAX and INTPTR_MAX are optional, so avoid them for max portability.
+ #if SIZE_MAX == 0xffff
+ #error Unknown platform (16-bit, unsupported)
+ #elif SIZE_MAX == 0xffffffff
+ #define BOOST_CHARCONV_FASTFLOAT_32BIT 1
+ #elif SIZE_MAX == 0xffffffffffffffff
+ #define BOOST_CHARCONV_FASTFLOAT_64BIT 1
+ #else
+ #error Unknown platform (not 32-bit, not 64-bit?)
+ #endif
+#endif
+
+#if ((defined(_WIN32) || defined(_WIN64)) && !defined(__clang__))
+#include <intrin.h>
+#endif
+
+#if defined(_MSC_VER) && !defined(__clang__)
+#define BOOST_CHARCONV_FASTFLOAT_VISUAL_STUDIO 1
+#endif
+
+#if defined __BYTE_ORDER__ && defined __ORDER_BIG_ENDIAN__
+#define BOOST_CHARCONV_FASTFLOAT_IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+#elif defined _WIN32
+#define BOOST_CHARCONV_FASTFLOAT_IS_BIG_ENDIAN 0
+#else
+#if defined(__APPLE__) || defined(__FreeBSD__)
+#include <machine/endian.h>
+#elif defined(sun) || defined(__sun)
+#include <sys/byteorder.h>
+#else
+#ifdef __has_include
+#if __has_include(<endian.h>)
+#include <endian.h>
+#endif //__has_include(<endian.h>)
+#endif //__has_include
+#endif
+#
+#ifndef __BYTE_ORDER__
+// safe choice
+#define BOOST_CHARCONV_FASTFLOAT_IS_BIG_ENDIAN 0
+#endif
+#
+#ifndef __ORDER_LITTLE_ENDIAN__
+// safe choice
+#define BOOST_CHARCONV_FASTFLOAT_IS_BIG_ENDIAN 0
+#endif
+#
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#define BOOST_CHARCONV_FASTFLOAT_IS_BIG_ENDIAN 0
+#else
+#define BOOST_CHARCONV_FASTFLOAT_IS_BIG_ENDIAN 1
+#endif
+#endif
+
+#ifndef BOOST_CHARCONV_FASTFLOAT_ASSERT
+#define BOOST_CHARCONV_FASTFLOAT_ASSERT(x) { ((void)(x)); }
+#endif
+
+#ifndef BOOST_CHARCONV_FASTFLOAT_DEBUG_ASSERT
+#define BOOST_CHARCONV_FASTFLOAT_DEBUG_ASSERT(x) { ((void)(x)); }
+#endif
+
+// rust style `try!()` macro, or `?` operator
+#define BOOST_CHARCONV_FASTFLOAT_TRY(x) { if (!(x)) return false; }
+
+namespace boost { namespace charconv { namespace detail { namespace fast_float {
+
+BOOST_FORCEINLINE constexpr bool cpp20_and_in_constexpr() {
+#if BOOST_CHARCONV_FASTFLOAT_HAS_IS_CONSTANT_EVALUATED
+ return std::is_constant_evaluated();
+#else
+ return false;
+#endif
+}
+
+// Compares two ASCII strings in a case insensitive manner.
+template <typename UC>
+inline BOOST_CHARCONV_FASTFLOAT_CONSTEXPR14 bool
+fastfloat_strncasecmp(UC const * input1, UC const * input2, size_t length) {
+ char running_diff{0};
+ for (size_t i = 0; i < length; ++i) {
+ running_diff |= (char(input1[i]) ^ char(input2[i]));
+ }
+ return (running_diff == 0) || (running_diff == 32);
+}
+
+#ifndef FLT_EVAL_METHOD
+#error "FLT_EVAL_METHOD should be defined, please include cfloat."
+#endif
+
+// a pointer and a length to a contiguous block of memory
+template <typename T>
+struct span {
+ const T* ptr;
+ size_t length;
+ constexpr span(const T* _ptr, size_t _length) : ptr(_ptr), length(_length) {}
+ constexpr span() : ptr(nullptr), length(0) {}
+
+ constexpr size_t len() const noexcept {
+ return length;
+ }
+
+ BOOST_CHARCONV_FASTFLOAT_CONSTEXPR14 const T& operator[](size_t index) const noexcept {
+ BOOST_CHARCONV_FASTFLOAT_DEBUG_ASSERT(index < length);
+ return ptr[index];
+ }
+};
+
+struct value128 {
+ uint64_t low;
+ uint64_t high;
+ constexpr value128(uint64_t _low, uint64_t _high) : low(_low), high(_high) {}
+ constexpr value128() : low(0), high(0) {}
+};
+
+/* Helper C++11 constexpr generic implementation of leading_zeroes */
+BOOST_FORCEINLINE constexpr
+int leading_zeroes_generic(uint64_t input_num, int last_bit = 0) {
+ return (
+ ((input_num & uint64_t(0xffffffff00000000)) && (input_num >>= 32, last_bit |= 32)),
+ ((input_num & uint64_t( 0xffff0000)) && (input_num >>= 16, last_bit |= 16)),
+ ((input_num & uint64_t( 0xff00)) && (input_num >>= 8, last_bit |= 8)),
+ ((input_num & uint64_t( 0xf0)) && (input_num >>= 4, last_bit |= 4)),
+ ((input_num & uint64_t( 0xc)) && (input_num >>= 2, last_bit |= 2)),
+ ((input_num & uint64_t( 0x2)) && (input_num >>= 1, last_bit |= 1)),
+ 63 - last_bit
+ );
+}
+
+/* result might be undefined when input_num is zero */
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+int leading_zeroes(uint64_t input_num) {
+ assert(input_num > 0);
+ if (cpp20_and_in_constexpr()) {
+ return leading_zeroes_generic(input_num);
+ }
+#ifdef BOOST_CHARCONV_FASTFLOAT_VISUAL_STUDIO
+ #if defined(_M_X64) || defined(_M_ARM64)
+ unsigned long leading_zero = 0;
+ // Search the mask data from most significant bit (MSB)
+ // to least significant bit (LSB) for a set bit (1).
+ _BitScanReverse64(&leading_zero, input_num);
+ return (int)(63 - leading_zero);
+ #else
+ return leading_zeroes_generic(input_num);
+ #endif
+#else
+ return __builtin_clzll(input_num);
+#endif
+}
+
+// slow emulation routine for 32-bit
+BOOST_FORCEINLINE constexpr uint64_t emulu(uint32_t x, uint32_t y) {
+ return x * static_cast<uint64_t>(y);
+}
+
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR14
+uint64_t umul128_generic(uint64_t ab, uint64_t cd, uint64_t *hi) {
+ uint64_t ad = emulu(static_cast<uint32_t>(ab >> 32), static_cast<uint32_t>(cd));
+ uint64_t bd = emulu(static_cast<uint32_t>(ab), static_cast<uint32_t>(cd));
+ uint64_t adbc = ad + emulu(static_cast<uint32_t>(ab), static_cast<uint32_t>(cd >> 32));
+ uint64_t adbc_carry = !!(adbc < ad);
+ uint64_t lo = bd + (adbc << 32);
+ *hi = emulu(static_cast<uint32_t>(ab >> 32), static_cast<uint32_t>(cd >> 32)) + (adbc >> 32) +
+ (adbc_carry << 32) + !!(lo < bd);
+ return lo;
+}
+
+#ifdef BOOST_CHARCONV_FASTFLOAT_32BIT
+
+// slow emulation routine for 32-bit
+#if !defined(__MINGW64__)
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR14
+uint64_t _umul128(uint64_t ab, uint64_t cd, uint64_t *hi) {
+ return umul128_generic(ab, cd, hi);
+}
+#endif // !__MINGW64__
+
+#endif // BOOST_CHARCONV_FASTFLOAT_32BIT
+
+
+// compute 64-bit a*b
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+value128 full_multiplication(uint64_t a, uint64_t b) {
+ if (cpp20_and_in_constexpr()) {
+ value128 answer;
+ answer.low = umul128_generic(a, b, &answer.high);
+ return answer;
+ }
+ value128 answer;
+#if defined(_M_ARM64) && !defined(__MINGW32__)
+ // ARM64 has native support for 64-bit multiplications, no need to emulate
+ // But MinGW on ARM64 doesn't have native support for 64-bit multiplications
+ answer.high = __umulh(a, b);
+ answer.low = a * b;
+#elif defined(BOOST_CHARCONV_FASTFLOAT_32BIT) || \
+ (defined(_WIN64) && !defined(__clang__) && !defined(_M_ARM64))
+ unsigned long long high;
+ answer.low = _umul128(a, b, &high); // _umul128 not available on ARM64
+ answer.high = static_cast<uint64_t>(high);
+#elif defined(BOOST_CHARCONV_FASTFLOAT_64BIT)
+ __uint128_t r = (static_cast<__uint128_t>(a)) * b;
+ answer.low = uint64_t(r);
+ answer.high = uint64_t(r >> 64);
+#else
+ answer.low = umul128_generic(a, b, &answer.high);
+#endif
+ return answer;
+}
+
+struct adjusted_mantissa {
+ uint64_t mantissa{0};
+ int32_t power2{0}; // a negative value indicates an invalid result
+ adjusted_mantissa() = default;
+ constexpr bool operator==(const adjusted_mantissa &o) const {
+ return mantissa == o.mantissa && power2 == o.power2;
+ }
+ constexpr bool operator!=(const adjusted_mantissa &o) const {
+ return mantissa != o.mantissa || power2 != o.power2;
+ }
+};
+
+// Bias so we can get the real exponent with an invalid adjusted_mantissa.
+constexpr static int32_t invalid_am_bias = -0x8000;
+
+// used for binary_format_lookup_tables<T>::max_mantissa
+constexpr uint64_t constant_55555 = 5 * 5 * 5 * 5 * 5;
+
+template <typename T, typename U = void>
+struct binary_format_lookup_tables;
+
+template <typename T> struct binary_format : binary_format_lookup_tables<T> {
+ using equiv_uint = typename std::conditional<sizeof(T) == 4, uint32_t, uint64_t>::type;
+
+ static inline constexpr int mantissa_explicit_bits();
+ static inline constexpr int minimum_exponent();
+ static inline constexpr int infinite_power();
+ static inline constexpr int sign_index();
+ static inline constexpr int min_exponent_fast_path(); // used when fegetround() == FE_TONEAREST
+ static inline constexpr int max_exponent_fast_path();
+ static inline constexpr int max_exponent_round_to_even();
+ static inline constexpr int min_exponent_round_to_even();
+ static inline constexpr uint64_t max_mantissa_fast_path(int64_t power);
+ static inline constexpr uint64_t max_mantissa_fast_path(); // used when fegetround() == FE_TONEAREST
+ static inline constexpr int largest_power_of_ten();
+ static inline constexpr int smallest_power_of_ten();
+ static inline constexpr T exact_power_of_ten(int64_t power);
+ static inline constexpr size_t max_digits();
+ static inline constexpr equiv_uint exponent_mask();
+ static inline constexpr equiv_uint mantissa_mask();
+ static inline constexpr equiv_uint hidden_bit_mask();
+};
+
+template <typename U>
+struct binary_format_lookup_tables<double, U> {
+ static constexpr double powers_of_ten[] = {
+ 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11,
+ 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22};
+
+ // Largest integer value v so that (5**index * v) <= 1<<53.
+ // 0x10000000000000 == 1 << 53
+ static constexpr std::uint64_t max_mantissa[] = {
+ UINT64_C(0x10000000000000),
+ UINT64_C(0x10000000000000) / UINT64_C(5),
+ UINT64_C(0x10000000000000) / (UINT64_C(5) * UINT64_C(5)),
+ UINT64_C(0x10000000000000) / (UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
+ UINT64_C(0x10000000000000) / (UINT64_C(5) * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
+ UINT64_C(0x10000000000000) / (constant_55555),
+ UINT64_C(0x10000000000000) / (constant_55555 * UINT64_C(5)),
+ UINT64_C(0x10000000000000) / (constant_55555 * UINT64_C(5) * UINT64_C(5)),
+ UINT64_C(0x10000000000000) / (constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
+ UINT64_C(0x10000000000000) / (constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
+ UINT64_C(0x10000000000000) / (constant_55555 * constant_55555),
+ UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * UINT64_C(5)),
+ UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * UINT64_C(5) * UINT64_C(5)),
+ UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
+ UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555),
+ UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * UINT64_C(5)),
+ UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * UINT64_C(5) * UINT64_C(5)),
+ UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
+ UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
+ UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * constant_55555),
+ UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * constant_55555 * UINT64_C(5)),
+ UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * constant_55555 * UINT64_C(5) * UINT64_C(5)),
+ UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
+ UINT64_C(0x10000000000000) / (constant_55555 * constant_55555 * constant_55555 * constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5) * UINT64_C(5))};
+};
+
+template <typename U>
+constexpr double binary_format_lookup_tables<double, U>::powers_of_ten[];
+
+template <typename U>
+constexpr uint64_t binary_format_lookup_tables<double, U>::max_mantissa[];
+
+template <typename U>
+struct binary_format_lookup_tables<float, U> {
+ static constexpr float powers_of_ten[] = {1e0f, 1e1f, 1e2f, 1e3f, 1e4f, 1e5f,
+ 1e6f, 1e7f, 1e8f, 1e9f, 1e10f};
+
+ // Largest integer value v so that (5**index * v) <= 1<<24.
+ // 0x1000000 == 1<<24
+ static constexpr uint64_t max_mantissa[] = {
+ UINT64_C(0x1000000),
+ UINT64_C(0x1000000) / UINT64_C(5),
+ UINT64_C(0x1000000) / (UINT64_C(5) * UINT64_C(5)),
+ UINT64_C(0x1000000) / (UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
+ UINT64_C(0x1000000) / (UINT64_C(5) * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
+ UINT64_C(0x1000000) / (constant_55555),
+ UINT64_C(0x1000000) / (constant_55555 * UINT64_C(5)),
+ UINT64_C(0x1000000) / (constant_55555 * UINT64_C(5) * UINT64_C(5)),
+ UINT64_C(0x1000000) / (constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
+ UINT64_C(0x1000000) / (constant_55555 * UINT64_C(5) * UINT64_C(5) * UINT64_C(5) * UINT64_C(5)),
+ UINT64_C(0x1000000) / (constant_55555 * constant_55555),
+ UINT64_C(0x1000000) / (constant_55555 * constant_55555 * UINT64_C(5))};
+};
+
+template <typename U>
+constexpr float binary_format_lookup_tables<float, U>::powers_of_ten[];
+
+template <typename U>
+constexpr uint64_t binary_format_lookup_tables<float, U>::max_mantissa[];
+
+template <> inline constexpr int binary_format<double>::min_exponent_fast_path() {
+#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)
+ return 0;
+#else
+ return -22;
+#endif
+}
+
+template <> inline constexpr int binary_format<float>::min_exponent_fast_path() {
+#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)
+ return 0;
+#else
+ return -10;
+#endif
+}
+
+template <> inline constexpr int binary_format<double>::mantissa_explicit_bits() {
+ return 52;
+}
+template <> inline constexpr int binary_format<float>::mantissa_explicit_bits() {
+ return 23;
+}
+
+template <> inline constexpr int binary_format<double>::max_exponent_round_to_even() {
+ return 23;
+}
+
+template <> inline constexpr int binary_format<float>::max_exponent_round_to_even() {
+ return 10;
+}
+
+template <> inline constexpr int binary_format<double>::min_exponent_round_to_even() {
+ return -4;
+}
+
+template <> inline constexpr int binary_format<float>::min_exponent_round_to_even() {
+ return -17;
+}
+
+template <> inline constexpr int binary_format<double>::minimum_exponent() {
+ return -1023;
+}
+template <> inline constexpr int binary_format<float>::minimum_exponent() {
+ return -127;
+}
+
+template <> inline constexpr int binary_format<double>::infinite_power() {
+ return 0x7FF;
+}
+template <> inline constexpr int binary_format<float>::infinite_power() {
+ return 0xFF;
+}
+
+template <> inline constexpr int binary_format<double>::sign_index() { return 63; }
+template <> inline constexpr int binary_format<float>::sign_index() { return 31; }
+
+template <> inline constexpr int binary_format<double>::max_exponent_fast_path() {
+ return 22;
+}
+template <> inline constexpr int binary_format<float>::max_exponent_fast_path() {
+ return 10;
+}
+
+template <> inline constexpr uint64_t binary_format<double>::max_mantissa_fast_path() {
+ return uint64_t(2) << mantissa_explicit_bits();
+}
+template <> inline constexpr uint64_t binary_format<double>::max_mantissa_fast_path(int64_t power) {
+ // caller is responsible to ensure that
+ // power >= 0 && power <= 22
+ //
+ // Work around clang bug https://godbolt.org/z/zedh7rrhc
+ return (void)max_mantissa[0], max_mantissa[power];
+}
+template <> inline constexpr uint64_t binary_format<float>::max_mantissa_fast_path() {
+ return uint64_t(2) << mantissa_explicit_bits();
+}
+template <> inline constexpr uint64_t binary_format<float>::max_mantissa_fast_path(int64_t power) {
+ // caller is responsible to ensure that
+ // power >= 0 && power <= 10
+ //
+ // Work around clang bug https://godbolt.org/z/zedh7rrhc
+ return (void)max_mantissa[0], max_mantissa[power];
+}
+
+template <>
+inline constexpr double binary_format<double>::exact_power_of_ten(int64_t power) {
+ // Work around clang bug https://godbolt.org/z/zedh7rrhc
+ return (void)powers_of_ten[0], powers_of_ten[power];
+}
+template <>
+inline constexpr float binary_format<float>::exact_power_of_ten(int64_t power) {
+ // Work around clang bug https://godbolt.org/z/zedh7rrhc
+ return (void)powers_of_ten[0], powers_of_ten[power];
+}
+
+
+template <>
+inline constexpr int binary_format<double>::largest_power_of_ten() {
+ return 308;
+}
+template <>
+inline constexpr int binary_format<float>::largest_power_of_ten() {
+ return 38;
+}
+
+template <>
+inline constexpr int binary_format<double>::smallest_power_of_ten() {
+ return -342;
+}
+template <>
+inline constexpr int binary_format<float>::smallest_power_of_ten() {
+ return -65;
+}
+
+template <> inline constexpr size_t binary_format<double>::max_digits() {
+ return 769;
+}
+template <> inline constexpr size_t binary_format<float>::max_digits() {
+ return 114;
+}
+
+template <> inline constexpr binary_format<float>::equiv_uint
+ binary_format<float>::exponent_mask() {
+ return 0x7F800000;
+}
+template <> inline constexpr binary_format<double>::equiv_uint
+ binary_format<double>::exponent_mask() {
+ return 0x7FF0000000000000;
+}
+
+template <> inline constexpr binary_format<float>::equiv_uint
+ binary_format<float>::mantissa_mask() {
+ return 0x007FFFFF;
+}
+template <> inline constexpr binary_format<double>::equiv_uint
+ binary_format<double>::mantissa_mask() {
+ return 0x000FFFFFFFFFFFFF;
+}
+
+template <> inline constexpr binary_format<float>::equiv_uint
+ binary_format<float>::hidden_bit_mask() {
+ return 0x00800000;
+}
+template <> inline constexpr binary_format<double>::equiv_uint
+ binary_format<double>::hidden_bit_mask() {
+ return 0x0010000000000000;
+}
+
+template<typename T>
+BOOST_FORCEINLINE BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+void to_float(bool negative, adjusted_mantissa am, T &value) {
+ using uint = typename binary_format<T>::equiv_uint;
+ uint word = static_cast<uint>(am.mantissa);
+ word |= uint(am.power2) << binary_format<T>::mantissa_explicit_bits();
+ word |= uint(negative) << binary_format<T>::sign_index();
+#if BOOST_CHARCONV_FASTFLOAT_HAS_BIT_CAST
+ value = std::bit_cast<T>(word);
+#else
+ ::memcpy(&value, &word, sizeof(T));
+#endif
+}
+
+#ifdef BOOST_CHARCONV_FASTFLOAT_SKIP_WHITE_SPACE // disabled by default
+template <typename = void>
+struct space_lut {
+ static constexpr bool value[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+};
+
+template <typename T>
+constexpr bool space_lut<T>::value[];
+
+inline constexpr bool is_space(uint8_t c) { return space_lut<>::value[c]; }
+#endif
+
+template<typename UC>
+static constexpr uint64_t int_cmp_zeros()
+{
+ static_assert((sizeof(UC) == 1) || (sizeof(UC) == 2) || (sizeof(UC) == 4), "Unsupported character size");
+ return (sizeof(UC) == 1) ? 0x3030303030303030 : (sizeof(UC) == 2) ? (uint64_t(UC('0')) << 48 | uint64_t(UC('0')) << 32 | uint64_t(UC('0')) << 16 | UC('0')) : (uint64_t(UC('0')) << 32 | UC('0'));
+}
+template<typename UC>
+static constexpr int int_cmp_len()
+{
+ return sizeof(uint64_t) / sizeof(UC);
+}
+template<typename UC>
+static constexpr UC const * str_const_nan()
+{
+ return nullptr;
+}
+template<>
+constexpr char const * str_const_nan<char>()
+{
+ return "nan";
+}
+template<>
+constexpr wchar_t const * str_const_nan<wchar_t>()
+{
+ return L"nan";
+}
+template<>
+constexpr char16_t const * str_const_nan<char16_t>()
+{
+ return u"nan";
+}
+template<>
+constexpr char32_t const * str_const_nan<char32_t>()
+{
+ return U"nan";
+}
+template<typename UC>
+static constexpr UC const * str_const_inf()
+{
+ return nullptr;
+}
+template<>
+constexpr char const * str_const_inf<char>()
+{
+ return "infinity";
+}
+template<>
+constexpr wchar_t const * str_const_inf<wchar_t>()
+{
+ return L"infinity";
+}
+template<>
+constexpr char16_t const * str_const_inf<char16_t>()
+{
+ return u"infinity";
+}
+template<>
+constexpr char32_t const * str_const_inf<char32_t>()
+{
+ return U"infinity";
+}
+
+}}}} // namespaces
+
+#endif
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/parse_number.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/parse_number.hpp
new file mode 100644
index 00000000000..9f71d45c246
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/fast_float/parse_number.hpp
@@ -0,0 +1,247 @@
+// Copyright 2020-2023 Daniel Lemire
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+//
+// Derivative of: https://github.com/fastfloat/fast_float
+
+#ifndef BOOST_CHARCONV_DETAIL_FASTFLOAT_PARSE_NUMBER_HPP
+#define BOOST_CHARCONV_DETAIL_FASTFLOAT_PARSE_NUMBER_HPP
+
+#include <boost/charconv/detail/fast_float/ascii_number.hpp>
+#include <boost/charconv/detail/fast_float/decimal_to_binary.hpp>
+#include <boost/charconv/detail/fast_float/digit_comparison.hpp>
+#include <boost/charconv/detail/fast_float/float_common.hpp>
+
+#include <cmath>
+#include <cstring>
+#include <limits>
+#include <system_error>
+
+namespace boost { namespace charconv { namespace detail { namespace fast_float {
+
+
+namespace detail {
+/**
+ * Special case +inf, -inf, nan, infinity, -infinity.
+ * The case comparisons could be made much faster given that we know that the
+ * strings a null-free and fixed.
+ **/
+
+#if defined(__GNUC__) && __GNUC__ < 5 && !defined(__clang__)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+#endif
+
+template <typename T, typename UC>
+from_chars_result_t<UC> BOOST_CHARCONV_FASTFLOAT_CONSTEXPR14
+parse_infnan(UC const * first, UC const * last, T &value) noexcept {
+ from_chars_result_t<UC> answer{};
+ answer.ptr = first;
+ answer.ec = std::errc(); // be optimistic
+ bool minusSign = false;
+ if (*first == UC('-')) { // assume first < last, so dereference without checks; C++17 20.19.3.(7.1) explicitly forbids '+' here
+ minusSign = true;
+ ++first;
+ }
+#ifdef BOOST_CHARCONV_FASTFLOAT_ALLOWS_LEADING_PLUS // disabled by default
+ if (*first == UC('+')) {
+ ++first;
+ }
+#endif
+ if (last - first >= 3) {
+ if (fastfloat_strncasecmp(first, str_const_nan<UC>(), 3)) {
+ answer.ptr = (first += 3);
+ value = minusSign ? -std::numeric_limits<T>::quiet_NaN() : std::numeric_limits<T>::quiet_NaN();
+ // Check for possible nan(n-char-seq-opt), C++17 20.19.3.7, C11 7.20.1.3.3. At least MSVC produces nan(ind) and nan(snan).
+ if(first != last && *first == UC('(')) {
+ for(UC const * ptr = first + 1; ptr != last; ++ptr) {
+ if (*ptr == UC(')')) {
+ answer.ptr = ptr + 1; // valid nan(n-char-seq-opt)
+ break;
+ }
+ else if(!((UC('a') <= *ptr && *ptr <= UC('z')) || (UC('A') <= *ptr && *ptr <= UC('Z')) || (UC('0') <= *ptr && *ptr <= UC('9')) || *ptr == UC('_')))
+ break; // forbidden char, not nan(n-char-seq-opt)
+ }
+ }
+ return answer;
+ }
+ if (fastfloat_strncasecmp(first, str_const_inf<UC>(), 3)) {
+ if ((last - first >= 8) && fastfloat_strncasecmp(first + 3, str_const_inf<UC>() + 3, 5)) {
+ answer.ptr = first + 8;
+ } else {
+ answer.ptr = first + 3;
+ }
+ value = minusSign ? -std::numeric_limits<T>::infinity() : std::numeric_limits<T>::infinity();
+ return answer;
+ }
+ }
+ answer.ec = std::errc::invalid_argument;
+ return answer;
+}
+
+#if defined(__GNUC__) && __GNUC__ < 5 && !defined(__clang__)
+# pragma GCC diagnostic pop
+#endif
+
+/**
+ * Returns true if the floating-pointing rounding mode is to 'nearest'.
+ * It is the default on most system. This function is meant to be inexpensive.
+ * Credit : @mwalcott3
+ */
+BOOST_FORCEINLINE bool rounds_to_nearest() noexcept {
+ // https://lemire.me/blog/2020/06/26/gcc-not-nearest/
+#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)
+ return false;
+#endif
+ // See
+ // A fast function to check your floating-point rounding mode
+ // https://lemire.me/blog/2022/11/16/a-fast-function-to-check-your-floating-point-rounding-mode/
+ //
+ // This function is meant to be equivalent to :
+ // prior: #include <cfenv>
+ // return fegetround() == FE_TONEAREST;
+ // However, it is expected to be much faster than the fegetround()
+ // function call.
+ //
+ // The volatile keywoard prevents the compiler from computing the function
+ // at compile-time.
+ // There might be other ways to prevent compile-time optimizations (e.g., asm).
+ // The value does not need to be (std::numeric_limits<float>::min)(), any small
+ // value so that 1 + x should round to 1 would do (after accounting for excess
+ // precision, as in 387 instructions).
+ static volatile float fmin = (std::numeric_limits<float>::min)();
+ float fmini = fmin; // we copy it so that it gets loaded at most once.
+ //
+ // Explanation:
+ // Only when fegetround() == FE_TONEAREST do we have that
+ // fmin + 1.0f == 1.0f - fmin.
+ //
+ // FE_UPWARD:
+ // fmin + 1.0f > 1
+ // 1.0f - fmin == 1
+ //
+ // FE_DOWNWARD or FE_TOWARDZERO:
+ // fmin + 1.0f == 1
+ // 1.0f - fmin < 1
+ //
+ // Note: This may fail to be accurate if fast-math has been
+ // enabled, as rounding conventions may not apply.
+ #ifdef BOOST_CHARCONV_FASTFLOAT_VISUAL_STUDIO
+ # pragma warning(push)
+ // todo: is there a VS warning?
+ // see https://stackoverflow.com/questions/46079446/is-there-a-warning-for-floating-point-equality-checking-in-visual-studio-2013
+ #elif defined(__clang__)
+ # pragma clang diagnostic push
+ # pragma clang diagnostic ignored "-Wfloat-equal"
+ #elif defined(__GNUC__)
+ # pragma GCC diagnostic push
+ # pragma GCC diagnostic ignored "-Wfloat-equal"
+ #endif
+ return (fmini + 1.0f == 1.0f - fmini);
+ #ifdef BOOST_CHARCONV_FASTFLOAT_VISUAL_STUDIO
+ # pragma warning(pop)
+ #elif defined(__clang__)
+ # pragma clang diagnostic pop
+ #elif defined(__GNUC__)
+ # pragma GCC diagnostic pop
+ #endif
+}
+
+} // namespace detail
+
+template<typename T, typename UC>
+BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+from_chars_result_t<UC> from_chars(UC const * first, UC const * last,
+ T &value, chars_format fmt /*= chars_format::general*/) noexcept {
+ return from_chars_advanced(first, last, value, parse_options_t<UC>{fmt});
+}
+
+template<typename T, typename UC>
+BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
+from_chars_result_t<UC> from_chars_advanced(UC const * first, UC const * last,
+ T &value, parse_options_t<UC> options) noexcept {
+
+ static_assert (std::is_same<T, double>::value || std::is_same<T, float>::value, "only float and double are supported");
+ static_assert (std::is_same<UC, char>::value ||
+ std::is_same<UC, wchar_t>::value ||
+ std::is_same<UC, char16_t>::value ||
+ std::is_same<UC, char32_t>::value , "only char, wchar_t, char16_t and char32_t are supported");
+
+ from_chars_result_t<UC> answer;
+#ifdef BOOST_CHARCONV_FASTFLOAT_SKIP_WHITE_SPACE // disabled by default
+ while ((first != last) && fast_float::is_space(uint8_t(*first))) {
+ first++;
+ }
+#endif
+ if (first == last) {
+ answer.ec = std::errc::invalid_argument;
+ answer.ptr = first;
+ return answer;
+ }
+ parsed_number_string_t<UC> pns = parse_number_string<UC>(first, last, options);
+ if (!pns.valid) {
+ return detail::parse_infnan(first, last, value);
+ }
+ answer.ec = std::errc(); // be optimistic
+ answer.ptr = pns.lastmatch;
+ // The implementation of the Clinger's fast path is convoluted because
+ // we want round-to-nearest in all cases, irrespective of the rounding mode
+ // selected on the thread.
+ // We proceed optimistically, assuming that detail::rounds_to_nearest() returns
+ // true.
+ if (binary_format<T>::min_exponent_fast_path() <= pns.exponent && pns.exponent <= binary_format<T>::max_exponent_fast_path() && !pns.too_many_digits) {
+ // Unfortunately, the conventional Clinger's fast path is only possible
+ // when the system rounds to the nearest float.
+ //
+ // We expect the next branch to almost always be selected.
+ // We could check it first (before the previous branch), but
+ // there might be performance advantages at having the check
+ // be last.
+ if(!cpp20_and_in_constexpr() && detail::rounds_to_nearest()) {
+ // We have that fegetround() == FE_TONEAREST.
+ // Next is Clinger's fast path.
+ if (pns.mantissa <=binary_format<T>::max_mantissa_fast_path()) {
+ value = T(pns.mantissa);
+ if (pns.exponent < 0) { value = value / binary_format<T>::exact_power_of_ten(-pns.exponent); }
+ else { value = value * binary_format<T>::exact_power_of_ten(pns.exponent); }
+ if (pns.negative) { value = -value; }
+ return answer;
+ }
+ } else {
+ // We do not have that fegetround() == FE_TONEAREST.
+ // Next is a modified Clinger's fast path, inspired by Jakub Jelínek's proposal
+ if (pns.exponent >= 0 && pns.mantissa <=binary_format<T>::max_mantissa_fast_path(pns.exponent)) {
+#if defined(__clang__)
+ // Clang may map 0 to -0.0 when fegetround() == FE_DOWNWARD
+ if(pns.mantissa == 0) {
+ value = pns.negative ? -0. : 0.;
+ return answer;
+ }
+#endif
+ value = T(pns.mantissa) * binary_format<T>::exact_power_of_ten(pns.exponent);
+ if (pns.negative) { value = -value; }
+ return answer;
+ }
+ }
+ }
+ adjusted_mantissa am = compute_float<binary_format<T>>(pns.exponent, pns.mantissa);
+ if(pns.too_many_digits && am.power2 >= 0) {
+ if(am != compute_float<binary_format<T>>(pns.exponent, pns.mantissa + 1)) {
+ am = compute_error<binary_format<T>>(pns.exponent, pns.mantissa);
+ }
+ }
+ // If we called compute_float<binary_format<T>>(pns.exponent, pns.mantissa) and we have an invalid power (am.power2 < 0),
+ // then we need to go the long way around again. This is very uncommon.
+ if(am.power2 < 0) { am = digit_comp<T>(pns, am); }
+ to_float(pns.negative, am, value);
+ // Test for over/underflow.
+ if ((pns.mantissa != 0 && am.mantissa == 0 && am.power2 == 0) || am.power2 == binary_format<T>::infinite_power()) {
+ answer.ec = std::errc::result_out_of_range;
+ }
+ return answer;
+}
+
+}}}} // namespace fast_float
+
+#endif
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/from_chars_integer_impl.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/from_chars_integer_impl.hpp
new file mode 100644
index 00000000000..a069fd96892
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/from_chars_integer_impl.hpp
@@ -0,0 +1,333 @@
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_CHARCONV_DETAIL_FROM_CHARS_INTEGER_IMPL_HPP
+#define BOOST_CHARCONV_DETAIL_FROM_CHARS_INTEGER_IMPL_HPP
+
+#include <boost/charconv/detail/apply_sign.hpp>
+#include <boost/charconv/detail/config.hpp>
+#include <boost/charconv/detail/from_chars_result.hpp>
+#include <boost/charconv/detail/emulated128.hpp>
+#include <boost/charconv/detail/type_traits.hpp>
+#include <boost/charconv/config.hpp>
+#include <boost/config.hpp>
+#include <system_error>
+#include <type_traits>
+#include <limits>
+#include <cstdlib>
+#include <cerrno>
+#include <cstddef>
+#include <cstdint>
+
+namespace boost { namespace charconv { namespace detail {
+
+static constexpr unsigned char uchar_values[] =
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255,
+ 255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 255, 255, 255, 255, 255,
+ 255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255};
+
+static_assert(sizeof(uchar_values) == 256, "uchar_values should represent all 256 values of unsigned char");
+
+static constexpr double log_2_table[] =
+{
+ 0.0,
+ 0.0,
+ 1.0,
+ 0.630929753571,
+ 0.5,
+ 0.430676558073,
+ 0.386852807235,
+ 0.356207187108,
+ 0.333333333333,
+ 0.315464876786,
+ 0.301029995664,
+ 0.289064826318,
+ 0.278942945651,
+ 0.270238154427,
+ 0.262649535037,
+ 0.255958024810,
+ 0.25,
+ 0.244650542118,
+ 0.239812466568,
+ 0.235408913367,
+ 0.231378213160,
+ 0.227670248697,
+ 0.224243824218,
+ 0.221064729458,
+ 0.218104291986,
+ 0.215338279037,
+ 0.212746053553,
+ 0.210309917857,
+ 0.208014597677,
+ 0.205846832460,
+ 0.203795047091,
+ 0.201849086582,
+ 0.2,
+ 0.198239863171,
+ 0.196561632233,
+ 0.194959021894,
+ 0.193426403617
+};
+
+// Convert characters for 0-9, A-Z, a-z to 0-35. Anything else is 255
+constexpr unsigned char digit_from_char(char val) noexcept
+{
+ return uchar_values[static_cast<unsigned char>(val)];
+}
+
+#ifdef BOOST_MSVC
+# pragma warning(push)
+# pragma warning(disable: 4146) // unary minus operator applied to unsigned type, result still unsigned
+# pragma warning(disable: 4189) // 'is_negative': local variable is initialized but not referenced
+
+#elif defined(__clang__)
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wconstant-conversion"
+
+#elif defined(__GNUC__) && (__GNUC__ < 7)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Woverflow"
+# pragma GCC diagnostic ignored "-Wconversion"
+# pragma GCC diagnostic ignored "-Wsign-conversion"
+
+#elif defined(__GNUC__) && (__GNUC__ >= 7)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+# pragma GCC diagnostic ignored "-Wconversion"
+
+#endif
+
+template <typename Integer, typename Unsigned_Integer>
+BOOST_CXX14_CONSTEXPR from_chars_result from_chars_integer_impl(const char* first, const char* last, Integer& value, int base) noexcept
+{
+ Unsigned_Integer result = 0;
+ Unsigned_Integer overflow_value = 0;
+ Unsigned_Integer max_digit = 0;
+
+ // Check pre-conditions
+ if (!((first <= last) && (base >= 2 && base <= 36)))
+ {
+ return {first, std::errc::invalid_argument};
+ }
+
+ const auto unsigned_base = static_cast<Unsigned_Integer>(base);
+
+ // Strip sign if the type is signed
+ // Negative sign will be appended at the end of parsing
+ BOOST_ATTRIBUTE_UNUSED bool is_negative = false;
+ auto next = first;
+
+ BOOST_CHARCONV_IF_CONSTEXPR (is_signed<Integer>::value)
+ {
+ if (next != last)
+ {
+ if (*next == '-')
+ {
+ is_negative = true;
+ ++next;
+ }
+ else if (*next == '+' || *next == ' ')
+ {
+ return {next, std::errc::invalid_argument};
+ }
+ }
+
+ #ifdef BOOST_CHARCONV_HAS_INT128
+ BOOST_IF_CONSTEXPR (std::is_same<Integer, boost::int128_type>::value)
+ {
+ overflow_value = BOOST_CHARCONV_INT128_MAX;
+ max_digit = BOOST_CHARCONV_INT128_MAX;
+ }
+ else
+ #endif
+ {
+ overflow_value = (std::numeric_limits<Integer>::max)();
+ max_digit = (std::numeric_limits<Integer>::max)();
+ }
+
+ if (is_negative)
+ {
+ ++overflow_value;
+ ++max_digit;
+ }
+ }
+ else
+ {
+ if (next != last && (*next == '-' || *next == '+' || *next == ' '))
+ {
+ return {first, std::errc::invalid_argument};
+ }
+
+ #ifdef BOOST_CHARCONV_HAS_INT128
+ BOOST_IF_CONSTEXPR (std::is_same<Integer, boost::uint128_type>::value)
+ {
+ overflow_value = BOOST_CHARCONV_UINT128_MAX;
+ max_digit = BOOST_CHARCONV_UINT128_MAX;
+ }
+ else
+ #endif
+ {
+ overflow_value = (std::numeric_limits<Unsigned_Integer>::max)();
+ max_digit = (std::numeric_limits<Unsigned_Integer>::max)();
+ }
+ }
+
+ #ifdef BOOST_CHARCONV_HAS_INT128
+ BOOST_IF_CONSTEXPR (std::is_same<Integer, boost::int128_type>::value)
+ {
+ overflow_value /= unsigned_base;
+ max_digit %= unsigned_base;
+ #ifndef __GLIBCXX_TYPE_INT_N_0
+ if (base != 10)
+ {
+ // Overflow value would cause INT128_MIN in non-base10 to fail
+ overflow_value *= static_cast<Unsigned_Integer>(2);
+ }
+ #endif
+ }
+ else
+ #endif
+ {
+ overflow_value /= unsigned_base;
+ max_digit %= unsigned_base;
+ }
+
+ // If the only character was a sign abort now
+ if (next == last)
+ {
+ return {first, std::errc::invalid_argument};
+ }
+
+ bool overflowed = false;
+
+ const std::ptrdiff_t nc = last - next;
+
+ // In non-GNU mode on GCC numeric limits may not be specialized
+ #if defined(BOOST_CHARCONV_HAS_INT128) && !defined(__GLIBCXX_TYPE_INT_N_0)
+ constexpr std::ptrdiff_t nd_2 = std::is_same<Integer, boost::int128_type>::value ? 127 :
+ std::is_same<Integer, boost::uint128_type>::value ? 128 :
+ std::numeric_limits<Integer>::digits10;
+ #else
+ constexpr std::ptrdiff_t nd_2 = std::numeric_limits<Integer>::digits;
+ #endif
+
+ const auto nd = static_cast<std::ptrdiff_t>(nd_2 * log_2_table[static_cast<std::size_t>(unsigned_base)]);
+
+ {
+ // Check that the first character is valid before proceeding
+ const unsigned char first_digit = digit_from_char(*next);
+
+ if (first_digit >= unsigned_base)
+ {
+ return {first, std::errc::invalid_argument};
+ }
+
+ result = static_cast<Unsigned_Integer>(result * unsigned_base + first_digit);
+ ++next;
+ std::ptrdiff_t i = 1;
+
+ for( ; i < nd && i < nc; ++i )
+ {
+ // overflow is not possible in the first nd characters
+
+ const unsigned char current_digit = digit_from_char(*next);
+
+ if (current_digit >= unsigned_base)
+ {
+ break;
+ }
+
+ result = static_cast<Unsigned_Integer>(result * unsigned_base + current_digit);
+ ++next;
+ }
+
+ for( ; i < nc; ++i )
+ {
+ const unsigned char current_digit = digit_from_char(*next);
+
+ if (current_digit >= unsigned_base)
+ {
+ break;
+ }
+
+ if (result < overflow_value || (result == overflow_value && current_digit <= max_digit))
+ {
+ result = static_cast<Unsigned_Integer>(result * unsigned_base + current_digit);
+ }
+ else
+ {
+ // Required to keep updating the value of next, but the result is garbage
+ overflowed = true;
+ }
+
+ ++next;
+ }
+ }
+
+ // Return the parsed value, adding the sign back if applicable
+ // If we have overflowed then we do not return the result
+ if (overflowed)
+ {
+ return {next, std::errc::result_out_of_range};
+ }
+
+ value = static_cast<Integer>(result);
+
+ BOOST_IF_CONSTEXPR (is_signed<Integer>::value)
+ {
+ if (is_negative)
+ {
+ value = static_cast<Integer>(-(static_cast<Unsigned_Integer>(value)));
+ }
+ }
+
+ return {next, std::errc()};
+}
+
+#ifdef BOOST_MSVC
+# pragma warning(pop)
+#elif defined(__clang__)
+# pragma clang diagnostic pop
+#elif defined(__GNUC__)
+# pragma GCC diagnostic pop
+#endif
+
+// Only from_chars for integer types is constexpr (as of C++23)
+template <typename Integer>
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, Integer& value, int base = 10) noexcept
+{
+ using Unsigned_Integer = typename std::make_unsigned<Integer>::type;
+ return detail::from_chars_integer_impl<Integer, Unsigned_Integer>(first, last, value, base);
+}
+
+#ifdef BOOST_CHARCONV_HAS_INT128
+template <typename Integer>
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars128(const char* first, const char* last, Integer& value, int base = 10) noexcept
+{
+ using Unsigned_Integer = boost::uint128_type;
+ return detail::from_chars_integer_impl<Integer, Unsigned_Integer>(first, last, value, base);
+}
+#endif
+
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars128(const char* first, const char* last, uint128& value, int base = 10) noexcept
+{
+ return from_chars_integer_impl<uint128, uint128>(first, last, value, base);
+}
+
+}}} // Namespaces
+
+#endif // BOOST_CHARCONV_DETAIL_FROM_CHARS_INTEGER_IMPL_HPP
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/from_chars_result.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/from_chars_result.hpp
new file mode 100644
index 00000000000..e4302cfab18
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/from_chars_result.hpp
@@ -0,0 +1,41 @@
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_CHARCONV_DETAIL_FROM_CHARS_RESULT_HPP
+#define BOOST_CHARCONV_DETAIL_FROM_CHARS_RESULT_HPP
+
+#include <system_error>
+
+namespace boost { namespace charconv {
+
+// 22.13.3, Primitive numerical input conversion
+
+template <typename UC>
+struct from_chars_result_t
+{
+ const UC* ptr;
+
+ // Values:
+ // 0 = no error
+ // EINVAL = invalid_argument
+ // ERANGE = result_out_of_range
+ std::errc ec;
+
+ friend constexpr bool operator==(const from_chars_result_t<UC>& lhs, const from_chars_result_t<UC>& rhs) noexcept
+ {
+ return lhs.ptr == rhs.ptr && lhs.ec == rhs.ec;
+ }
+
+ friend constexpr bool operator!=(const from_chars_result_t<UC>& lhs, const from_chars_result_t<UC>& rhs) noexcept
+ {
+ return !(lhs == rhs); // NOLINT : Expression can not be simplified since this is the definition
+ }
+
+ constexpr explicit operator bool() const noexcept { return ec == std::errc{}; }
+};
+using from_chars_result = from_chars_result_t<char>;
+
+}} // Namespaces
+
+#endif // BOOST_CHARCONV_DETAIL_FROM_CHARS_RESULT_HPP
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/integer_search_trees.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/integer_search_trees.hpp
new file mode 100644
index 00000000000..9b4de091357
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/integer_search_trees.hpp
@@ -0,0 +1,274 @@
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_CHARCONV_DETAIL_INTEGER_SEARCH_TREES_HPP
+#define BOOST_CHARCONV_DETAIL_INTEGER_SEARCH_TREES_HPP
+
+// https://stackoverflow.com/questions/1489830/efficient-way-to-determine-number-of-digits-in-an-integer?page=1&tab=scoredesc#tab-top
+// https://graphics.stanford.edu/~seander/bithacks.html
+
+#include <boost/charconv/detail/config.hpp>
+#include <boost/charconv/detail/emulated128.hpp>
+#include <limits>
+#include <array>
+#include <cstdint>
+
+namespace boost { namespace charconv { namespace detail {
+
+// Generic solution
+template <typename T>
+BOOST_CHARCONV_CXX14_CONSTEXPR int num_digits(T x) noexcept
+{
+ int digits = 0;
+
+ while (x)
+ {
+ x /= 10;
+ ++digits;
+ }
+
+ return digits;
+}
+
+template <>
+BOOST_CHARCONV_CXX14_CONSTEXPR int num_digits(std::uint32_t x) noexcept
+{
+ if (x >= UINT32_C(10000))
+ {
+ if (x >= UINT32_C(10000000))
+ {
+ if (x >= UINT32_C(100000000))
+ {
+ if (x >= UINT32_C(1000000000))
+ {
+ return 10;
+ }
+ return 9;
+ }
+ return 8;
+ }
+
+ else if (x >= UINT32_C(100000))
+ {
+ if (x >= UINT32_C(1000000))
+ {
+ return 7;
+ }
+ return 6;
+ }
+ return 5;
+ }
+ else if (x >= UINT32_C(100))
+ {
+ if (x >= UINT32_C(1000))
+ {
+ return 4;
+ }
+ return 3;
+ }
+ else if (x >= UINT32_C(10))
+ {
+ return 2;
+ }
+
+ return 1;
+}
+
+template <>
+BOOST_CHARCONV_CXX14_CONSTEXPR int num_digits(std::uint64_t x) noexcept
+{
+ if (x >= UINT64_C(10000000000))
+ {
+ if (x >= UINT64_C(100000000000000))
+ {
+ if (x >= UINT64_C(10000000000000000))
+ {
+ if (x >= UINT64_C(100000000000000000))
+ {
+ if (x >= UINT64_C(1000000000000000000))
+ {
+ if (x >= UINT64_C(10000000000000000000))
+ {
+ return 20;
+ }
+ return 19;
+ }
+ return 18;
+ }
+ return 17;
+ }
+ else if (x >= UINT64_C(1000000000000000))
+ {
+ return 16;
+ }
+ return 15;
+ }
+ if (x >= UINT64_C(1000000000000))
+ {
+ if (x >= UINT64_C(10000000000000))
+ {
+ return 14;
+ }
+ return 13;
+ }
+ if (x >= UINT64_C(100000000000))
+ {
+ return 12;
+ }
+ return 11;
+ }
+ else if (x >= UINT64_C(100000))
+ {
+ if (x >= UINT64_C(10000000))
+ {
+ if (x >= UINT64_C(100000000))
+ {
+ if (x >= UINT64_C(1000000000))
+ {
+ return 10;
+ }
+ return 9;
+ }
+ return 8;
+ }
+ if (x >= UINT64_C(1000000))
+ {
+ return 7;
+ }
+ return 6;
+ }
+ if (x >= UINT64_C(100))
+ {
+ if (x >= UINT64_C(1000))
+ {
+ if (x >= UINT64_C(10000))
+ {
+ return 5;
+ }
+ return 4;
+ }
+ return 3;
+ }
+ if (x >= UINT64_C(10))
+ {
+ return 2;
+ }
+ return 1;
+}
+
+#ifdef BOOST_MSVC
+# pragma warning(push)
+# pragma warning(disable: 4307) // MSVC 14.1 warns of intergral constant overflow
+#endif
+
+BOOST_CHARCONV_CXX14_CONSTEXPR int num_digits(uint128 x) noexcept
+{
+ if (x.high == 0)
+ {
+ return num_digits(x.low);
+ }
+
+ BOOST_CHARCONV_CXX14_CONSTEXPR_NO_INLINE uint128 digits_39 = static_cast<uint128>(UINT64_C(10000000000000000000)) *
+ static_cast<uint128>(UINT64_C(10000000000000000000));
+ uint128 current_power_of_10 = digits_39;
+
+ for (int i = 39; i > 0; --i)
+ {
+ if (x >= current_power_of_10)
+ {
+ return i;
+ }
+
+ current_power_of_10 /= 10U;
+ }
+
+ return 1;
+}
+
+#ifdef BOOST_MSVC
+# pragma warning(pop)
+#endif
+
+#ifdef BOOST_CHARCONV_HAS_INT128
+static constexpr std::array<std::uint64_t, 20> powers_of_10 =
+{{
+ UINT64_C(1), UINT64_C(10), UINT64_C(100), UINT64_C(1000), UINT64_C(10000), UINT64_C(100000), UINT64_C(1000000),
+ UINT64_C(10000000), UINT64_C(100000000), UINT64_C(1000000000), UINT64_C(10000000000), UINT64_C(100000000000),
+ UINT64_C(1000000000000), UINT64_C(10000000000000), UINT64_C(100000000000000), UINT64_C(1000000000000000),
+ UINT64_C(10000000000000000), UINT64_C(100000000000000000), UINT64_C(1000000000000000000), UINT64_C(10000000000000000000)
+}};
+
+// Assume that if someone is using 128 bit ints they are favoring the top end of the range
+// Max value is 340,282,366,920,938,463,463,374,607,431,768,211,455 (39 digits)
+BOOST_CHARCONV_CXX14_CONSTEXPR int num_digits(boost::uint128_type x) noexcept
+{
+ // There is no literal for boost::uint128_type, so we need to calculate them using the max value of the
+ // std::uint64_t powers of 10
+ constexpr boost::uint128_type digits_39 = static_cast<boost::uint128_type>(UINT64_C(10000000000000000000)) *
+ static_cast<boost::uint128_type>(UINT64_C(10000000000000000000));
+
+ constexpr boost::uint128_type digits_38 = digits_39 / 10;
+ constexpr boost::uint128_type digits_37 = digits_38 / 10;
+ constexpr boost::uint128_type digits_36 = digits_37 / 10;
+ constexpr boost::uint128_type digits_35 = digits_36 / 10;
+ constexpr boost::uint128_type digits_34 = digits_35 / 10;
+ constexpr boost::uint128_type digits_33 = digits_34 / 10;
+ constexpr boost::uint128_type digits_32 = digits_33 / 10;
+ constexpr boost::uint128_type digits_31 = digits_32 / 10;
+ constexpr boost::uint128_type digits_30 = digits_31 / 10;
+ constexpr boost::uint128_type digits_29 = digits_30 / 10;
+ constexpr boost::uint128_type digits_28 = digits_29 / 10;
+ constexpr boost::uint128_type digits_27 = digits_28 / 10;
+ constexpr boost::uint128_type digits_26 = digits_27 / 10;
+ constexpr boost::uint128_type digits_25 = digits_26 / 10;
+ constexpr boost::uint128_type digits_24 = digits_25 / 10;
+ constexpr boost::uint128_type digits_23 = digits_24 / 10;
+ constexpr boost::uint128_type digits_22 = digits_23 / 10;
+ constexpr boost::uint128_type digits_21 = digits_22 / 10;
+
+ return (x >= digits_39) ? 39 :
+ (x >= digits_38) ? 38 :
+ (x >= digits_37) ? 37 :
+ (x >= digits_36) ? 36 :
+ (x >= digits_35) ? 35 :
+ (x >= digits_34) ? 34 :
+ (x >= digits_33) ? 33 :
+ (x >= digits_32) ? 32 :
+ (x >= digits_31) ? 31 :
+ (x >= digits_30) ? 30 :
+ (x >= digits_29) ? 29 :
+ (x >= digits_28) ? 28 :
+ (x >= digits_27) ? 27 :
+ (x >= digits_26) ? 26 :
+ (x >= digits_25) ? 25 :
+ (x >= digits_24) ? 24 :
+ (x >= digits_23) ? 23 :
+ (x >= digits_22) ? 22 :
+ (x >= digits_21) ? 21 :
+ (x >= powers_of_10[19]) ? 20 :
+ (x >= powers_of_10[18]) ? 19 :
+ (x >= powers_of_10[17]) ? 18 :
+ (x >= powers_of_10[16]) ? 17 :
+ (x >= powers_of_10[15]) ? 16 :
+ (x >= powers_of_10[14]) ? 15 :
+ (x >= powers_of_10[13]) ? 14 :
+ (x >= powers_of_10[12]) ? 13 :
+ (x >= powers_of_10[11]) ? 12 :
+ (x >= powers_of_10[10]) ? 11 :
+ (x >= powers_of_10[9]) ? 10 :
+ (x >= powers_of_10[8]) ? 9 :
+ (x >= powers_of_10[7]) ? 8 :
+ (x >= powers_of_10[6]) ? 7 :
+ (x >= powers_of_10[5]) ? 6 :
+ (x >= powers_of_10[4]) ? 5 :
+ (x >= powers_of_10[3]) ? 4 :
+ (x >= powers_of_10[2]) ? 3 :
+ (x >= powers_of_10[1]) ? 2 :
+ (x >= powers_of_10[0]) ? 1 : 0;
+}
+#endif
+
+}}} // Namespace boost::charconv::detail
+
+#endif // BOOST_CHARCONV_DETAIL_INTEGER_SEARCH_TREES_HPP
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/issignaling.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/issignaling.hpp
new file mode 100644
index 00000000000..0780c2e8935
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/issignaling.hpp
@@ -0,0 +1,85 @@
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_CHARCONV_DETAIL_ISSIGNALING_HPP
+#define BOOST_CHARCONV_DETAIL_ISSIGNALING_HPP
+
+#include <boost/charconv/detail/config.hpp>
+#include <boost/charconv/detail/bit_layouts.hpp>
+#include <cstdint>
+#include <cstring>
+
+namespace boost { namespace charconv { namespace detail {
+
+template <typename T>
+inline bool issignaling BOOST_PREVENT_MACRO_SUBSTITUTION (T x) noexcept;
+
+#if BOOST_CHARCONV_LDBL_BITS == 128 || defined(BOOST_CHARCONV_HAS_QUADMATH)
+
+struct words128
+{
+#if BOOST_CHARCONV_ENDIAN_LITTLE_BYTE
+ std::uint64_t lo;
+ std::uint64_t hi;
+#else
+ std::uint64_t hi;
+ std::uint64_t lo;
+#endif
+};
+
+template <typename T>
+inline bool issignaling BOOST_PREVENT_MACRO_SUBSTITUTION (T x) noexcept
+{
+ words128 bits;
+ std::memcpy(&bits, &x, sizeof(T));
+
+ std::uint64_t hi_word = bits.hi;
+ std::uint64_t lo_word = bits.lo;
+
+ hi_word ^= UINT64_C(0x0000800000000000);
+ hi_word |= (lo_word | -lo_word) >> 63;
+ return ((hi_word & INT64_MAX) > UINT64_C(0x7FFF800000000000));
+}
+
+#endif
+
+// 16-bit non-finite bit values:
+//
+// float16_t
+// SNAN: 0x7D00
+// QNAN: 0x7E00
+// INF: 0x7C00
+//
+// bfloat16_t
+// SNAN: 0x7FA0
+// QNAN: 0x7FC0
+// INF: 0x7F80
+
+#ifdef BOOST_CHARCONV_HAS_FLOAT16
+
+template <>
+inline bool issignaling<std::float16_t> BOOST_PREVENT_MACRO_SUBSTITUTION (std::float16_t x) noexcept
+{
+ std::uint16_t bits;
+ std::memcpy(&bits, &x, sizeof(std::uint16_t));
+ return bits >= UINT16_C(0x7D00) && bits < UINT16_C(0x7E00);
+}
+
+#endif
+
+#ifdef BOOST_CHARCONV_HAS_BRAINFLOAT16
+
+template <>
+inline bool issignaling<std::bfloat16_t> BOOST_PREVENT_MACRO_SUBSTITUTION (std::bfloat16_t x) noexcept
+{
+ std::uint16_t bits;
+ std::memcpy(&bits, &x, sizeof(std::uint16_t));
+ return bits >= UINT16_C(0x7FA0) && bits < UINT16_C(0x7FC0);
+}
+
+#endif
+
+}}} // Namespaces
+
+#endif // BOOST_CHARCONV_DETAIL_ISSIGNALING_HPP
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/memcpy.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/memcpy.hpp
new file mode 100644
index 00000000000..1e68315f42f
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/memcpy.hpp
@@ -0,0 +1,78 @@
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_CHARCONV_DETAIL_MEMCPY_HPP
+#define BOOST_CHARCONV_DETAIL_MEMCPY_HPP
+
+#include <boost/charconv/detail/config.hpp>
+#include <cstring>
+#include <cstdint>
+
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89689
+// GCC 10 added checks for length of memcpy which yields the following warning (converted to error with -Werror)
+// /usr/include/x86_64-linux-gnu/bits/string_fortified.h:34:33: error:
+// ‘void* __builtin___memcpy_chk(void*, const void*, long unsigned int, long unsigned int)’ specified size between
+// 18446744071562067968 and 18446744073709551615 exceeds maximum object size 9223372036854775807 [-Werror=stringop-overflow=]
+//
+// memcpy is defined as taking a size_t for the count and the largest count this will recieve is the number of digits
+// in a 128-bit int (39) so we can safely ignore
+#if defined(__GNUC__) && __GNUC__ >= 10
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wstringop-overflow"
+# define BOOST_CHARCONV_STRINGOP_OVERFLOW_DISABLED
+#endif
+
+namespace boost { namespace charconv { namespace detail {
+
+#if !defined(BOOST_CHARCONV_NO_CONSTEXPR_DETECTION) && defined(BOOST_CXX14_CONSTEXPR)
+
+#define BOOST_CHARCONV_CONSTEXPR constexpr
+
+constexpr char* memcpy(char* dest, const char* src, std::size_t count)
+{
+ if (BOOST_CHARCONV_IS_CONSTANT_EVALUATED(count))
+ {
+ for (std::size_t i = 0; i < count; ++i)
+ {
+ *(dest + i) = *(src + i);
+ }
+
+ return dest;
+ }
+ else
+ {
+ // Workaround for GCC-11 because it does not honor GCC diagnostic ignored
+ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53431
+ // Hopefully the optimizer turns this into memcpy
+ #if defined(__GNUC__) && __GNUC__ == 11
+ for (std::size_t i = 0; i < count; ++i)
+ {
+ *(dest + i) = *(src + i);
+ }
+
+ return dest;
+ #else
+ return static_cast<char*>(std::memcpy(dest, src, count));
+ #endif
+ }
+}
+
+#else // Either not C++14 or no way of telling if we are in a constexpr context
+
+#define BOOST_CHARCONV_CONSTEXPR inline
+
+inline void* memcpy(void* dest, const void* src, std::size_t count)
+{
+ return std::memcpy(dest, src, count);
+}
+
+#endif
+
+}}} // Namespace boost::charconv::detail
+
+#ifdef BOOST_CHARCONV_STRINGOP_OVERFLOW_DISABLED
+# pragma GCC diagnostic pop
+#endif
+
+#endif // BOOST_CHARCONV_DETAIL_MEMCPY_HPP
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/parser.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/parser.hpp
new file mode 100644
index 00000000000..660de688495
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/parser.hpp
@@ -0,0 +1,471 @@
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_CHARCONV_DETAIL_PARSER_HPP
+#define BOOST_CHARCONV_DETAIL_PARSER_HPP
+
+#include <boost/charconv/detail/config.hpp>
+#include <boost/charconv/detail/from_chars_result.hpp>
+#include <boost/charconv/detail/from_chars_integer_impl.hpp>
+#include <boost/charconv/detail/integer_search_trees.hpp>
+#include <boost/charconv/limits.hpp>
+#include <boost/charconv/chars_format.hpp>
+#include <system_error>
+#include <type_traits>
+#include <limits>
+#include <cerrno>
+#include <cstdint>
+#include <cstring>
+
+#if defined(__GNUC__) && __GNUC__ < 5 && !defined(__clang__)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+#endif
+
+namespace boost { namespace charconv { namespace detail {
+
+inline bool is_integer_char(char c) noexcept
+{
+ return (c >= '0') && (c <= '9');
+}
+
+inline bool is_hex_char(char c) noexcept
+{
+ return is_integer_char(c) || (((c >= 'a') && (c <= 'f')) || ((c >= 'A') && (c <= 'F')));
+}
+
+inline bool is_delimiter(char c, chars_format fmt) noexcept
+{
+ if (fmt != chars_format::hex)
+ {
+ return !is_integer_char(c) && c != 'e' && c != 'E';
+ }
+
+ return !is_hex_char(c) && c != 'p' && c != 'P';
+}
+
+inline from_chars_result from_chars_dispatch(const char* first, const char* last, std::uint64_t& value, int base) noexcept
+{
+ return boost::charconv::detail::from_chars(first, last, value, base);
+}
+
+inline from_chars_result from_chars_dispatch(const char* first, const char* last, uint128& value, int base) noexcept
+{
+ return boost::charconv::detail::from_chars128(first, last, value, base);
+}
+
+#ifdef BOOST_CHARCONV_HAS_INT128
+inline from_chars_result from_chars_dispatch(const char* first, const char* last, boost::uint128_type& value, int base) noexcept
+{
+ return boost::charconv::detail::from_chars128(first, last, value, base);
+}
+#endif
+
+template<typename Unsigned_Integer>
+typename std::enable_if<std::is_unsigned<Unsigned_Integer>::value &&
+ std::numeric_limits<Unsigned_Integer>::is_integer &&
+ sizeof(Unsigned_Integer) < sizeof(std::uint64_t),
+ from_chars_result>::type
+ from_chars_dispatch(const char* first, const char* last, Unsigned_Integer& value, int base) noexcept
+{
+ std::uint64_t tmp_value;
+ auto result = boost::charconv::detail::from_chars(first, last, tmp_value, base);
+ if (result) {
+ if (tmp_value > (std::numeric_limits<Unsigned_Integer>::max)())
+ result.ec = std::errc::result_out_of_range;
+ else
+ value = static_cast<Unsigned_Integer>(tmp_value);
+ }
+ return result;
+}
+
+template <typename Unsigned_Integer, typename Integer>
+inline from_chars_result parser(const char* first, const char* last, bool& sign, Unsigned_Integer& significand, Integer& exponent, chars_format fmt = chars_format::general) noexcept
+{
+ if (first > last)
+ {
+ return {first, std::errc::invalid_argument};
+ }
+
+ auto next = first;
+ bool all_zeros = true;
+
+ // First extract the sign
+ if (*next == '-')
+ {
+ sign = true;
+ ++next;
+ }
+ else if (*next == '+')
+ {
+ return {next, std::errc::invalid_argument};
+ }
+ else
+ {
+ sign = false;
+ }
+
+ // Handle non-finite values
+ // Stl allows for string like "iNf" to return inf
+ //
+ // This is nested ifs rather than a big one-liner to ensure that once we hit an invalid character
+ // or an end of buffer we return the correct value of next
+ if (next != last && (*next == 'i' || *next == 'I'))
+ {
+ ++next;
+ if (next != last && (*next == 'n' || *next == 'N'))
+ {
+ ++next;
+ if (next != last && (*next == 'f' || *next == 'F'))
+ {
+ significand = 0;
+ return {next, std::errc::value_too_large};
+ }
+ }
+
+ return {next, std::errc::invalid_argument};
+ }
+ else if (next != last && (*next == 'n' || *next == 'N'))
+ {
+ ++next;
+ if (next != last && (*next == 'a' || *next == 'A'))
+ {
+ ++next;
+ if (next != last && (*next == 'n' || *next == 'N'))
+ {
+ ++next;
+ if (next != last && (*next == '('))
+ {
+ ++next;
+ if (next != last && (*next == 's' || *next == 'S'))
+ {
+ significand = 1;
+ return {next, std::errc::not_supported};
+ }
+ else if (next != last && (*next == 'i' || *next == 'I'))
+ {
+ significand = 0;
+ return {next, std::errc::not_supported};
+ }
+ }
+ else
+ {
+ significand = 0;
+ return {next, std::errc::not_supported};
+ }
+ }
+ }
+
+ return {next, std::errc::invalid_argument};
+ }
+
+ // Ignore leading zeros (e.g. 00005 or -002.3e+5)
+ while (next != last && *next == '0')
+ {
+ ++next;
+ }
+
+ // If the number is 0 we can abort now
+ char exp_char;
+ char capital_exp_char;
+ if (fmt != chars_format::hex)
+ {
+ exp_char = 'e';
+ capital_exp_char = 'E';
+ }
+ else
+ {
+ exp_char = 'p';
+ capital_exp_char = 'P';
+ }
+
+ if (next == last || *next == exp_char || *next == -capital_exp_char)
+ {
+ significand = 0;
+ exponent = 0;
+ return {next, std::errc()};
+ }
+
+ // Next we get the significand
+ constexpr std::size_t significand_buffer_size = limits<Unsigned_Integer>::max_chars10; // Base 10 or 16
+ char significand_buffer[significand_buffer_size] {};
+ std::size_t i = 0;
+ std::size_t dot_position = 0;
+ Integer extra_zeros = 0;
+ Integer leading_zero_powers = 0;
+ const auto char_validation_func = (fmt != boost::charconv::chars_format::hex) ? is_integer_char : is_hex_char;
+ const int base = (fmt != boost::charconv::chars_format::hex) ? 10 : 16;
+
+ while (next != last && char_validation_func(*next) && i < significand_buffer_size)
+ {
+ all_zeros = false;
+ significand_buffer[i] = *next;
+ ++next;
+ ++i;
+ }
+
+ bool fractional = false;
+ if (next == last)
+ {
+ // if fmt is chars_format::scientific the e is required
+ if (fmt == chars_format::scientific)
+ {
+ return {first, std::errc::invalid_argument};
+ }
+
+ exponent = 0;
+ std::size_t offset = i;
+
+ from_chars_result r = from_chars_dispatch(significand_buffer, significand_buffer + offset, significand, base);
+ switch (r.ec)
+ {
+ case std::errc::invalid_argument:
+ return {first, std::errc::invalid_argument};
+ case std::errc::result_out_of_range:
+ return {next, std::errc::result_out_of_range};
+ default:
+ return {next, std::errc()};
+ }
+ }
+ else if (*next == '.')
+ {
+ ++next;
+ fractional = true;
+ dot_position = i;
+
+ // Process the fractional part if we have it
+ //
+ // if fmt is chars_format::scientific the e is required
+ // if fmt is chars_format::fixed and not scientific the e is disallowed
+ // if fmt is chars_format::general (which is scientific and fixed) the e is optional
+
+ // If we have the value 0.00001 we can continue to chop zeros and adjust the exponent
+ // so that we get the useful parts of the fraction
+ if (all_zeros)
+ {
+ while (next != last && *next == '0')
+ {
+ ++next;
+ --leading_zero_powers;
+ }
+
+ if (next == last)
+ {
+ significand = 0;
+ exponent = 0;
+ return {last, std::errc()};
+ }
+ }
+
+ while (next != last && char_validation_func(*next) && i < significand_buffer_size)
+ {
+ significand_buffer[i] = *next;
+ ++next;
+ ++i;
+ }
+ }
+
+ if (i == significand_buffer_size)
+ {
+ // We can not process any more significant figures into the significand so skip to the end
+ // or the exponent part and capture the additional orders of magnitude for the exponent
+ bool found_dot = false;
+ while (next != last && (char_validation_func(*next) || *next == '.'))
+ {
+ ++next;
+ if (!fractional && !found_dot)
+ {
+ ++extra_zeros;
+ }
+ if (next != last && *next == '.')
+ {
+ found_dot = true;
+ }
+ }
+ }
+
+ if (next == last || is_delimiter(*next, fmt))
+ {
+ if (fmt == chars_format::scientific)
+ {
+ return {first, std::errc::invalid_argument};
+ }
+ if (dot_position != 0 || fractional)
+ {
+ exponent = static_cast<Integer>(dot_position) - static_cast<Integer>(i) + extra_zeros + leading_zero_powers;
+ }
+ else
+ {
+ exponent = extra_zeros + leading_zero_powers;
+ }
+ std::size_t offset = i;
+
+ from_chars_result r = from_chars_dispatch(significand_buffer, significand_buffer + offset, significand, base);
+ switch (r.ec)
+ {
+ case std::errc::invalid_argument:
+ return {first, std::errc::invalid_argument};
+ case std::errc::result_out_of_range:
+ return {next, std::errc::result_out_of_range};
+ default:
+ return {next, std::errc()};
+ }
+ }
+ else if (*next == exp_char || *next == capital_exp_char)
+ {
+ // Would be a number without a significand e.g. e+03
+ if (next == first)
+ {
+ return {next, std::errc::invalid_argument};
+ }
+
+ ++next;
+ if (fmt == chars_format::fixed)
+ {
+ return {first, std::errc::invalid_argument};
+ }
+
+ std::size_t offset = i;
+ bool round = false;
+ // If more digits are present than representable in the significand of the target type
+ // we set the maximum
+ if (offset > significand_buffer_size)
+ {
+ offset = significand_buffer_size - 1;
+ i = significand_buffer_size;
+ if (significand_buffer[offset] == '5' ||
+ significand_buffer[offset] == '6' ||
+ significand_buffer[offset] == '7' ||
+ significand_buffer[offset] == '8' ||
+ significand_buffer[offset] == '9')
+ {
+ round = true;
+ }
+ }
+
+ // If the significand is 0 from chars will return std::errc::invalid_argument because there is nothing in the buffer,
+ // but it is a valid value. We need to continue parsing to get the correct value of ptr even
+ // though we know we could bail now.
+ //
+ // See GitHub issue #29: https://github.com/cppalliance/charconv/issues/29
+ if (offset != 0)
+ {
+ from_chars_result r = from_chars_dispatch(significand_buffer, significand_buffer + offset, significand, base);
+ switch (r.ec)
+ {
+ case std::errc::invalid_argument:
+ return {first, std::errc::invalid_argument};
+ case std::errc::result_out_of_range:
+ return {next, std::errc::result_out_of_range};
+ default:
+ break;
+ }
+
+ if (round)
+ {
+ significand = static_cast<Unsigned_Integer>(significand + 1u);
+ }
+ }
+ else
+ significand = 0;
+ }
+ else
+ {
+ return {first, std::errc::invalid_argument};
+ }
+
+ // Finally we get the exponent
+ constexpr std::size_t exponent_buffer_size = 6; // Float128 min exp is −16382
+ char exponent_buffer[exponent_buffer_size] {};
+ const auto significand_digits = i;
+ i = 0;
+
+ // Get the sign first
+ if (next != last && *next == '-')
+ {
+ exponent_buffer[i] = *next;
+ ++next;
+ ++i;
+ }
+ else if (next != last && *next == '+')
+ {
+ ++next;
+ }
+
+ // Next strip any leading zeros
+ while (next != last && *next == '0')
+ {
+ ++next;
+ }
+
+ // Process the significant values
+ while (next != last && is_integer_char(*next) && i < exponent_buffer_size)
+ {
+ exponent_buffer[i] = *next;
+ ++next;
+ ++i;
+ }
+
+ // If the exponent can't fit in the buffer the number is not representable
+ if (next != last && i == exponent_buffer_size)
+ {
+ return {next, std::errc::result_out_of_range};
+ }
+
+ // If the exponent was e+00 or e-00
+ if (i == 0 || (i == 1 && exponent_buffer[0] == '-'))
+ {
+ if (fractional)
+ {
+ exponent = static_cast<Integer>(dot_position - significand_digits);
+ }
+ else
+ {
+ exponent = extra_zeros;
+ }
+
+ return {next, std::errc()};
+ }
+
+ const auto r = from_chars(exponent_buffer, exponent_buffer + i, exponent);
+
+ exponent += leading_zero_powers;
+
+ switch (r.ec)
+ {
+ case std::errc::invalid_argument:
+ return {first, std::errc::invalid_argument};
+ case std::errc::result_out_of_range:
+ return {next, std::errc::result_out_of_range};
+ default:
+ if (fractional)
+ {
+ // Need to take the offset from 1.xxx because compute_floatXXX assumes the significand is an integer
+ // so the exponent is off by the number of digits in the significand - 1
+ if (fmt == chars_format::hex)
+ {
+ // In hex the number of digits parsed is possibly less than the number of digits in base10
+ exponent -= num_digits(significand) - static_cast<Integer>(dot_position);
+ }
+ else
+ {
+ exponent -= static_cast<Integer>(significand_digits - dot_position);
+ }
+ }
+ else
+ {
+ exponent += extra_zeros;
+ }
+
+ return {next, std::errc()};
+ }
+}
+
+}}} // Namespaces
+
+#if defined(__GNUC__) && __GNUC__ < 5 && !defined(__clang__)
+# pragma GCC diagnostic pop
+#endif
+
+#endif // BOOST_CHARCONV_DETAIL_PARSER_HPP
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/ryu/generic_128.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/ryu/generic_128.hpp
new file mode 100644
index 00000000000..23c5234ddf4
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/ryu/generic_128.hpp
@@ -0,0 +1,558 @@
+// Copyright 2018 - 2023 Ulf Adams
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_CHARCONV_DETAIL_RYU_GENERIC_128_HPP
+#define BOOST_CHARCONV_DETAIL_RYU_GENERIC_128_HPP
+
+#include <boost/charconv/detail/config.hpp>
+#include <boost/charconv/detail/integer_search_trees.hpp>
+#include <boost/charconv/detail/emulated128.hpp>
+#include <cstdint>
+
+#define BOOST_CHARCONV_POW5_TABLE_SIZE 56
+#define BOOST_CHARCONV_POW5_BITCOUNT 249
+#define BOOST_CHARCONV_POW5_INV_BITCOUNT 249
+
+namespace boost { namespace charconv { namespace detail { namespace ryu {
+
+#ifdef BOOST_CHARCONV_HAS_INT128
+using unsigned_128_type = boost::uint128_type;
+#else
+using unsigned_128_type = uint128;
+#endif
+
+// These tables are ~4.5 kByte total, compared to ~160 kByte for the full tables.
+//
+// There's no way to define 128-bit constants in C, so we use little-endian
+// pairs of 64-bit constants.
+
+#if (!defined(BOOST_MSVC) || BOOST_MSVC != 1900)
+template <bool b>
+struct ryu_tables_template
+#else
+struct ryu_tables
+#endif
+{
+ static constexpr uint64_t GENERIC_POW5_TABLE[BOOST_CHARCONV_POW5_TABLE_SIZE][2] = {
+ {1u, 0u},
+ {5u, 0u},
+ {25u, 0u},
+ {125u, 0u},
+ {625u, 0u},
+ {3125u, 0u},
+ {15625u, 0u},
+ {78125u, 0u},
+ {390625u, 0u},
+ {1953125u, 0u},
+ {9765625u, 0u},
+ {48828125u, 0u},
+ {244140625u, 0u},
+ {1220703125u, 0u},
+ {6103515625u, 0u},
+ {30517578125u, 0u},
+ {152587890625u, 0u},
+ {762939453125u, 0u},
+ {3814697265625u, 0u},
+ {19073486328125u, 0u},
+ {95367431640625u, 0u},
+ {476837158203125u, 0u},
+ {2384185791015625u, 0u},
+ {11920928955078125u, 0u},
+ {59604644775390625u, 0u},
+ {298023223876953125u, 0u},
+ {1490116119384765625u, 0u},
+ {7450580596923828125u, 0u},
+ {359414837200037393u, 2u},
+ {1797074186000186965u, 10u},
+ {8985370930000934825u, 50u},
+ {8033366502585570893u, 252u},
+ {3273344365508751233u, 1262u},
+ {16366721827543756165u, 6310u},
+ {8046632842880574361u, 31554u},
+ {3339676066983768573u, 157772u},
+ {16698380334918842865u, 788860u},
+ {9704925379756007861u, 3944304u},
+ {11631138751360936073u, 19721522u},
+ {2815461535676025517u, 98607613u},
+ {14077307678380127585u, 493038065u},
+ {15046306170771983077u, 2465190328u},
+ {1444554559021708921u, 12325951644u},
+ {7222772795108544605u, 61629758220u},
+ {17667119901833171409u, 308148791101u},
+ {14548623214327650581u, 1540743955509u},
+ {17402883850509598057u, 7703719777548u},
+ {13227442957709783821u, 38518598887744u},
+ {10796982567420264257u, 192592994438723u},
+ {17091424689682218053u, 962964972193617u},
+ {11670147153572883801u, 4814824860968089u},
+ {3010503546735764157u, 24074124304840448u},
+ {15052517733678820785u, 120370621524202240u},
+ {1475612373555897461u, 601853107621011204u},
+ {7378061867779487305u, 3009265538105056020u},
+ {18443565265187884909u, 15046327690525280101u}
+ };
+
+ static constexpr uint64_t GENERIC_POW5_SPLIT[89][4] = {
+ {0u, 0u, 0u, 72057594037927936u},
+ {0u, 5206161169240293376u, 4575641699882439235u, 73468396926392969u},
+ {3360510775605221349u, 6983200512169538081u, 4325643253124434363u, 74906821675075173u},
+ {11917660854915489451u, 9652941469841108803u, 946308467778435600u, 76373409087490117u},
+ {1994853395185689235u, 16102657350889591545u, 6847013871814915412u, 77868710555449746u},
+ {958415760277438274u, 15059347134713823592u, 7329070255463483331u, 79393288266368765u},
+ {2065144883315240188u, 7145278325844925976u, 14718454754511147343u, 80947715414629833u},
+ {8980391188862868935u, 13709057401304208685u, 8230434828742694591u, 82532576417087045u},
+ {432148644612782575u, 7960151582448466064u, 12056089168559840552u, 84148467132788711u},
+ {484109300864744403u, 15010663910730448582u, 16824949663447227068u, 85795995087002057u},
+ {14793711725276144220u, 16494403799991899904u, 10145107106505865967u, 87475779699624060u},
+ {15427548291869817042u, 12330588654550505203u, 13980791795114552342u, 89188452518064298u},
+ {9979404135116626552u, 13477446383271537499u, 14459862802511591337u, 90934657454687378u},
+ {12385121150303452775u, 9097130814231585614u, 6523855782339765207u, 92715051028904201u},
+ {1822931022538209743u, 16062974719797586441u, 3619180286173516788u, 94530302614003091u},
+ {12318611738248470829u, 13330752208259324507u, 10986694768744162601u, 96381094688813589u},
+ {13684493829640282333u, 7674802078297225834u, 15208116197624593182u, 98268123094297527u},
+ {5408877057066295332u, 6470124174091971006u, 15112713923117703147u, 100192097295163851u},
+ {11407083166564425062u, 18189998238742408185u, 4337638702446708282u, 102153740646605557u},
+ {4112405898036935485u, 924624216579956435u, 14251108172073737125u, 104153790666259019u},
+ {16996739107011444789u, 10015944118339042475u, 2395188869672266257u, 106192999311487969u},
+ {4588314690421337879u, 5339991768263654604u, 15441007590670620066u, 108272133262096356u},
+ {2286159977890359825u, 14329706763185060248u, 5980012964059367667u, 110391974208576409u},
+ {9654767503237031099u, 11293544302844823188u, 11739932712678287805u, 112553319146000238u},
+ {11362964448496095896u, 7990659682315657680u, 251480263940996374u, 114756980673665505u},
+ {1423410421096377129u, 14274395557581462179u, 16553482793602208894u, 117003787300607788u},
+ {2070444190619093137u, 11517140404712147401u, 11657844572835578076u, 119294583757094535u},
+ {7648316884775828921u, 15264332483297977688u, 247182277434709002u, 121630231312217685u},
+ {17410896758132241352u, 10923914482914417070u, 13976383996795783649u, 124011608097704390u},
+ {9542674537907272703u, 3079432708831728956u, 14235189590642919676u, 126439609438067572u},
+ {10364666969937261816u, 8464573184892924210u, 12758646866025101190u, 128915148187220428u},
+ {14720354822146013883u, 11480204489231511423u, 7449876034836187038u, 131439155071681461u},
+ {1692907053653558553u, 17835392458598425233u, 1754856712536736598u, 134012579040499057u},
+ {5620591334531458755u, 11361776175667106627u, 13350215315297937856u, 136636387622027174u},
+ {17455759733928092601u, 10362573084069962561u, 11246018728801810510u, 139311567287686283u},
+ {2465404073814044982u, 17694822665274381860u, 1509954037718722697u, 142039123822846312u},
+ {2152236053329638369u, 11202280800589637091u, 16388426812920420176u, 72410041352485523u},
+ {17319024055671609028u, 10944982848661280484u, 2457150158022562661u, 73827744744583080u},
+ {17511219308535248024u, 5122059497846768077u, 2089605804219668451u, 75273205100637900u},
+ {10082673333144031533u, 14429008783411894887u, 12842832230171903890u, 76746965869337783u},
+ {16196653406315961184u, 10260180891682904501u, 10537411930446752461u, 78249581139456266u},
+ {15084422041749743389u, 234835370106753111u, 16662517110286225617u, 79781615848172976u},
+ {8199644021067702606u, 3787318116274991885u, 7438130039325743106u, 81343645993472659u},
+ {12039493937039359765u, 9773822153580393709u, 5945428874398357806u, 82936258850702722u},
+ {984543865091303961u, 7975107621689454830u, 6556665988501773347u, 84560053193370726u},
+ {9633317878125234244u, 16099592426808915028u, 9706674539190598200u, 86215639518264828u},
+ {6860695058870476186u, 4471839111886709592u, 7828342285492709568u, 87903640274981819u},
+ {14583324717644598331u, 4496120889473451238u, 5290040788305728466u, 89624690099949049u},
+ {18093669366515003715u, 12879506572606942994u, 18005739787089675377u, 91379436055028227u},
+ {17997493966862379937u, 14646222655265145582u, 10265023312844161858u, 93168537870790806u},
+ {12283848109039722318u, 11290258077250314935u, 9878160025624946825u, 94992668194556404u},
+ {8087752761883078164u, 5262596608437575693u, 11093553063763274413u, 96852512843287537u},
+ {15027787746776840781u, 12250273651168257752u, 9290470558712181914u, 98748771061435726u},
+ {15003915578366724489u, 2937334162439764327u, 5404085603526796602u, 100682155783835929u},
+ {5225610465224746757u, 14932114897406142027u, 2774647558180708010u, 102653393903748137u},
+ {17112957703385190360u, 12069082008339002412u, 3901112447086388439u, 104663226546146909u},
+ {4062324464323300238u, 3992768146772240329u, 15757196565593695724u, 106712409346361594u},
+ {5525364615810306701u, 11855206026704935156u, 11344868740897365300u, 108801712734172003u},
+ {9274143661888462646u, 4478365862348432381u, 18010077872551661771u, 110931922223466333u},
+ {12604141221930060148u, 8930937759942591500u, 9382183116147201338u, 113103838707570263u},
+ {14513929377491886653u, 1410646149696279084u, 587092196850797612u, 115318278760358235u},
+ {2226851524999454362u, 7717102471110805679u, 7187441550995571734u, 117576074943260147u},
+ {5527526061344932763u, 2347100676188369132u, 16976241418824030445u, 119878076118278875u},
+ {6088479778147221611u, 17669593130014777580u, 10991124207197663546u, 122225147767136307u},
+ {11107734086759692041u, 3391795220306863431u, 17233960908859089158u, 124618172316667879u},
+ {7913172514655155198u, 17726879005381242552u, 641069866244011540u, 127058049470587962u},
+ {12596991768458713949u, 15714785522479904446u, 6035972567136116512u, 129545696547750811u},
+ {16901996933781815980u, 4275085211437148707u, 14091642539965169063u, 132082048827034281u},
+ {7524574627987869240u, 15661204384239316051u, 2444526454225712267u, 134668059898975949u},
+ {8199251625090479942u, 6803282222165044067u, 16064817666437851504u, 137304702024293857u},
+ {4453256673338111920u, 15269922543084434181u, 3139961729834750852u, 139992966499426682u},
+ {15841763546372731299u, 3013174075437671812u, 4383755396295695606u, 142733864029230733u},
+ {9771896230907310329u, 4900659362437687569u, 12386126719044266361u, 72764212553486967u},
+ {9420455527449565190u, 1859606122611023693u, 6555040298902684281u, 74188850200884818u},
+ {5146105983135678095u, 2287300449992174951u, 4325371679080264751u, 75641380576797959u},
+ {11019359372592553360u, 8422686425957443718u, 7175176077944048210u, 77122349788024458u},
+ {11005742969399620716u, 4132174559240043701u, 9372258443096612118u, 78632314633490790u},
+ {8887589641394725840u, 8029899502466543662u, 14582206497241572853u, 80171842813591127u},
+ {360247523705545899u, 12568341805293354211u, 14653258284762517866u, 81741513143625247u},
+ {12314272731984275834u, 4740745023227177044u, 6141631472368337539u, 83341915771415304u},
+ {441052047733984759u, 7940090120939869826u, 11750200619921094248u, 84973652399183278u},
+ {3436657868127012749u, 9187006432149937667u, 16389726097323041290u, 86637336509772529u},
+ {13490220260784534044u, 15339072891382896702u, 8846102360835316895u, 88333593597298497u},
+ {4125672032094859833u, 158347675704003277u, 10592598512749774447u, 90063061402315272u},
+ {12189928252974395775u, 2386931199439295891u, 7009030566469913276u, 91826390151586454u},
+ {9256479608339282969u, 2844900158963599229u, 11148388908923225596u, 93624242802550437u},
+ {11584393507658707408u, 2863659090805147914u, 9873421561981063551u, 95457295292572042u},
+ {13984297296943171390u, 1931468383973130608u, 12905719743235082319u, 97326236793074198u},
+ {5837045222254987499u, 10213498696735864176u, 14893951506257020749u, 99231769968645227u}
+ };
+
+ // Unfortunately, the results are sometimes off by one or two. We use an additional
+ // lookup table to store those cases and adjust the result.
+ static constexpr uint64_t POW5_ERRORS[156] = {
+ 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x9555596400000000u,
+ 0x65a6569525565555u, 0x4415551445449655u, 0x5105015504144541u, 0x65a69969a6965964u,
+ 0x5054955969959656u, 0x5105154515554145u, 0x4055511051591555u, 0x5500514455550115u,
+ 0x0041140014145515u, 0x1005440545511051u, 0x0014405450411004u, 0x0414440010500000u,
+ 0x0044000440010040u, 0x5551155000004001u, 0x4554555454544114u, 0x5150045544005441u,
+ 0x0001111400054501u, 0x6550955555554554u, 0x1504159645559559u, 0x4105055141454545u,
+ 0x1411541410405454u, 0x0415555044545555u, 0x0014154115405550u, 0x1540055040411445u,
+ 0x0000000500000000u, 0x5644000000000000u, 0x1155555591596555u, 0x0410440054569565u,
+ 0x5145100010010005u, 0x0555041405500150u, 0x4141450455140450u, 0x0000000144000140u,
+ 0x5114004001105410u, 0x4444100404005504u, 0x0414014410001015u, 0x5145055155555015u,
+ 0x0141041444445540u, 0x0000100451541414u, 0x4105041104155550u, 0x0500501150451145u,
+ 0x1001050000004114u, 0x5551504400141045u, 0x5110545410151454u, 0x0100001400004040u,
+ 0x5040010111040000u, 0x0140000150541100u, 0x4400140400104110u, 0x5011014405545004u,
+ 0x0000000044155440u, 0x0000000010000000u, 0x1100401444440001u, 0x0040401010055111u,
+ 0x5155155551405454u, 0x0444440015514411u, 0x0054505054014101u, 0x0451015441115511u,
+ 0x1541411401140551u, 0x4155104514445110u, 0x4141145450145515u, 0x5451445055155050u,
+ 0x4400515554110054u, 0x5111145104501151u, 0x565a655455500501u, 0x5565555555525955u,
+ 0x0550511500405695u, 0x4415504051054544u, 0x6555595965555554u, 0x0100915915555655u,
+ 0x5540001510001001u, 0x5450051414000544u, 0x1405010555555551u, 0x5555515555644155u,
+ 0x5555055595496555u, 0x5451045004415000u, 0x5450510144040144u, 0x5554155555556455u,
+ 0x5051555495415555u, 0x5555554555555545u, 0x0000000010005455u, 0x4000005000040000u,
+ 0x5565555555555954u, 0x5554559555555505u, 0x9645545495552555u, 0x4000400055955564u,
+ 0x0040000000000001u, 0x4004100100000000u, 0x5540040440000411u, 0x4565555955545644u,
+ 0x1140659549651556u, 0x0100000410010000u, 0x5555515400004001u, 0x5955545555155255u,
+ 0x5151055545505556u, 0x5051454510554515u, 0x0501500050415554u, 0x5044154005441005u,
+ 0x1455445450550455u, 0x0010144055144545u, 0x0000401100000004u, 0x1050145050000010u,
+ 0x0415004554011540u, 0x1000510100151150u, 0x0100040400001144u, 0x0000000000000000u,
+ 0x0550004400000100u, 0x0151145041451151u, 0x0000400400005450u, 0x0000100044010004u,
+ 0x0100054100050040u, 0x0504400005410010u, 0x4011410445500105u, 0x0000404000144411u,
+ 0x0101504404500000u, 0x0000005044400400u, 0x0000000014000100u, 0x0404440414000000u,
+ 0x5554100410000140u, 0x4555455544505555u, 0x5454105055455455u, 0x0115454155454015u,
+ 0x4404110000045100u, 0x4400001100101501u, 0x6596955956966a94u, 0x0040655955665965u,
+ 0x5554144400100155u, 0xa549495401011041u, 0x5596555565955555u, 0x5569965959549555u,
+ 0x969565a655555456u, 0x0000001000000000u, 0x0000000040000140u, 0x0000040100000000u,
+ 0x1415454400000000u, 0x5410415411454114u, 0x0400040104000154u, 0x0504045000000411u,
+ 0x0000001000000010u, 0x5554000000001040u, 0x5549155551556595u, 0x1455541055515555u,
+ 0x0510555454554541u, 0x9555555555540455u, 0x6455456555556465u, 0x4524565555654514u,
+ 0x5554655255559545u, 0x9555455441155556u, 0x0000000051515555u, 0x0010005040000550u,
+ 0x5044044040000000u, 0x1045040440010500u, 0x0000400000040000u, 0x0000000000000000u
+ };
+
+ static constexpr uint64_t GENERIC_POW5_INV_SPLIT[89][4] = {
+ {0u, 0u, 0u, 144115188075855872u},
+ {1573859546583440065u, 2691002611772552616u, 6763753280790178510u, 141347765182270746u},
+ {12960290449513840412u, 12345512957918226762u, 18057899791198622765u, 138633484706040742u},
+ {7615871757716765416u, 9507132263365501332u, 4879801712092008245u, 135971326161092377u},
+ {7869961150745287587u, 5804035291554591636u, 8883897266325833928u, 133360288657597085u},
+ {2942118023529634767u, 15128191429820565086u, 10638459445243230718u, 130799390525667397u},
+ {14188759758411913794u, 5362791266439207815u, 8068821289119264054u, 128287668946279217u},
+ {7183196927902545212u, 1952291723540117099u, 12075928209936341512u, 125824179589281448u},
+ {5672588001402349748u, 17892323620748423487u, 9874578446960390364u, 123407996258356868u},
+ {4442590541217566325u, 4558254706293456445u, 10343828952663182727u, 121038210542800766u},
+ {3005560928406962566u, 2082271027139057888u, 13961184524927245081u, 118713931475986426u},
+ {13299058168408384786u, 17834349496131278595u, 9029906103900731664u, 116434285200389047u},
+ {5414878118283973035u, 13079825470227392078u, 17897304791683760280u, 114198414639042157u},
+ {14609755883382484834u, 14991702445765844156u, 3269802549772755411u, 112005479173303009u},
+ {15967774957605076027u, 2511532636717499923u, 16221038267832563171u, 109854654326805788u},
+ {9269330061621627145u, 3332501053426257392u, 16223281189403734630u, 107745131455483836u},
+ {16739559299223642282u, 1873986623300664530u, 6546709159471442872u, 105676117443544318u},
+ {17116435360051202055u, 1359075105581853924u, 2038341371621886470u, 103646834405281051u},
+ {17144715798009627550u, 3201623802661132408u, 9757551605154622431u, 101656519392613377u},
+ {17580479792687825857u, 6546633380567327312u, 15099972427870912398u, 99704424108241124u},
+ {9726477118325522902u, 14578369026754005435u, 11728055595254428803u, 97789814624307808u},
+ {134593949518343635u, 5715151379816901985u, 1660163707976377376u, 95911971106466306u},
+ {5515914027713859358u, 7124354893273815720u, 5548463282858794077u, 94070187543243255u},
+ {6188403395862945512u, 5681264392632320838u, 15417410852121406654u, 92263771480600430u},
+ {15908890877468271457u, 10398888261125597540u, 4817794962769172309u, 90492043761593298u},
+ {1413077535082201005u, 12675058125384151580u, 7731426132303759597u, 88754338271028867u},
+ {1486733163972670293u, 11369385300195092554u, 11610016711694864110u, 87050001685026843u},
+ {8788596583757589684u, 3978580923851924802u, 9255162428306775812u, 85378393225389919u},
+ {7203518319660962120u, 15044736224407683725u, 2488132019818199792u, 83738884418690858u},
+ {4004175967662388707u, 18236988667757575407u, 15613100370957482671u, 82130858859985791u},
+ {18371903370586036463u, 53497579022921640u, 16465963977267203307u, 80553711981064899u},
+ {10170778323887491315u, 1999668801648976001u, 10209763593579456445u, 79006850823153334u},
+ {17108131712433974546u, 16825784443029944237u, 2078700786753338945u, 77489693813976938u},
+ {17221789422665858532u, 12145427517550446164u, 5391414622238668005u, 76001670549108934u},
+ {4859588996898795878u, 1715798948121313204u, 3950858167455137171u, 74542221577515387u},
+ {13513469241795711526u, 631367850494860526u, 10517278915021816160u, 73110798191218799u},
+ {11757513142672073111u, 2581974932255022228u, 17498959383193606459u, 143413724438001539u},
+ {14524355192525042817u, 5640643347559376447u, 1309659274756813016u, 140659771648132296u},
+ {2765095348461978538u, 11021111021896007722u, 3224303603779962366u, 137958702611185230u},
+ {12373410389187981037u, 13679193545685856195u, 11644609038462631561u, 135309501808182158u},
+ {12813176257562780151u, 3754199046160268020u, 9954691079802960722u, 132711173221007413u},
+ {17557452279667723458u, 3237799193992485824u, 17893947919029030695u, 130162739957935629u},
+ {14634200999559435155u, 4123869946105211004u, 6955301747350769239u, 127663243886350468u},
+ {2185352760627740240u, 2864813346878886844u, 13049218671329690184u, 125211745272516185u},
+ {6143438674322183002u, 10464733336980678750u, 6982925169933978309u, 122807322428266620u},
+ {1099509117817174576u, 10202656147550524081u, 754997032816608484u, 120449071364478757u},
+ {2410631293559367023u, 17407273750261453804u, 15307291918933463037u, 118136105451200587u},
+ {12224968375134586697u, 1664436604907828062u, 11506086230137787358u, 115867555084305488u},
+ {3495926216898000888u, 18392536965197424288u, 10992889188570643156u, 113642567358547782u},
+ {8744506286256259680u, 3966568369496879937u, 18342264969761820037u, 111460305746896569u},
+ {7689600520560455039u, 5254331190877624630u, 9628558080573245556u, 109319949786027263u},
+ {11862637625618819436u, 3456120362318976488u, 14690471063106001082u, 107220694767852583u},
+ {5697330450030126444u, 12424082405392918899u, 358204170751754904u, 105161751436977040u},
+ {11257457505097373622u, 15373192700214208870u, 671619062372033814u, 103142345693961148u},
+ {16850355018477166700u, 1913910419361963966u, 4550257919755970531u, 101161718304283822u},
+ {9670835567561997011u, 10584031339132130638u, 3060560222974851757u, 99219124612893520u},
+ {7698686577353054710u, 11689292838639130817u, 11806331021588878241u, 97313834264240819u},
+ {12233569599615692137u, 3347791226108469959u, 10333904326094451110u, 95445130927687169u},
+ {13049400362825383933u, 17142621313007799680u, 3790542585289224168u, 93612312028186576u},
+ {12430457242474442072u, 5625077542189557960u, 14765055286236672238u, 91814688482138969u},
+ {4759444137752473128u, 2230562561567025078u, 4954443037339580076u, 90051584438315940u},
+ {7246913525170274758u, 8910297835195760709u, 4015904029508858381u, 88322337023761438u},
+ {12854430245836432067u, 8135139748065431455u, 11548083631386317976u, 86626296094571907u},
+ {4848827254502687803u, 4789491250196085625u, 3988192420450664125u, 84962823991462151u},
+ {7435538409611286684u, 904061756819742353u, 14598026519493048444u, 83331295300025028u},
+ {11042616160352530997u, 8948390828345326218u, 10052651191118271927u, 81731096615594853u},
+ {11059348291563778943u, 11696515766184685544u, 3783210511290897367u, 80161626312626082u},
+ {7020010856491885826u, 5025093219346041680u, 8960210401638911765u, 78622294318500592u},
+ {17732844474490699984u, 7820866704994446502u, 6088373186798844243u, 77112521891678506u},
+ {688278527545590501u, 3045610706602776618u, 8684243536999567610u, 75631741404109150u},
+ {2734573255120657297u, 3903146411440697663u, 9470794821691856713u, 74179396127820347u},
+ {15996457521023071259u, 4776627823451271680u, 12394856457265744744u, 72754940025605801u},
+ {13492065758834518331u, 7390517611012222399u, 1630485387832860230u, 142715675091463768u},
+ {13665021627282055864u, 9897834675523659302u, 17907668136755296849u, 139975126841173266u},
+ {9603773719399446181u, 10771916301484339398u, 10672699855989487527u, 137287204938390542u},
+ {3630218541553511265u, 8139010004241080614u, 2876479648932814543u, 134650898807055963u},
+ {8318835909686377084u, 9525369258927993371u, 2796120270400437057u, 132065217277054270u},
+ {11190003059043290163u, 12424345635599592110u, 12539346395388933763u, 129529188211565064u},
+ {8701968833973242276u, 820569587086330727u, 2315591597351480110u, 127041858141569228u},
+ {5115113890115690487u, 16906305245394587826u, 9899749468931071388u, 124602291907373862u},
+ {15543535488939245974u, 10945189844466391399u, 3553863472349432246u, 122209572307020975u},
+ {7709257252608325038u, 1191832167690640880u, 15077137020234258537u, 119862799751447719u},
+ {7541333244210021737u, 9790054727902174575u, 5160944773155322014u, 117561091926268545u},
+ {12297384708782857832u, 1281328873123467374u, 4827925254630475769u, 115303583460052092u},
+ {13243237906232367265u, 15873887428139547641u, 3607993172301799599u, 113089425598968120u},
+ {11384616453739611114u, 15184114243769211033u, 13148448124803481057u, 110917785887682141u},
+ {17727970963596660683u, 1196965221832671990u, 14537830463956404138u, 108787847856377790u},
+ {17241367586707330931u, 8880584684128262874u, 11173506540726547818u, 106698810713789254u},
+ {7184427196661305643u, 14332510582433188173u, 14230167953789677901u, 104649889046128358u}
+ };
+
+ static constexpr uint64_t POW5_INV_ERRORS[154] = {
+ 0x1144155514145504u, 0x0000541555401141u, 0x0000000000000000u, 0x0154454000000000u,
+ 0x4114105515544440u, 0x0001001111500415u, 0x4041411410011000u, 0x5550114515155014u,
+ 0x1404100041554551u, 0x0515000450404410u, 0x5054544401140004u, 0x5155501005555105u,
+ 0x1144141000105515u, 0x0541500000500000u, 0x1104105540444140u, 0x4000015055514110u,
+ 0x0054010450004005u, 0x4155515404100005u, 0x5155145045155555u, 0x1511555515440558u,
+ 0x5558544555515555u, 0x0000000000000010u, 0x5004000000000050u, 0x1415510100000010u,
+ 0x4545555444514500u, 0x5155151555555551u, 0x1441540144044554u, 0x5150104045544400u,
+ 0x5450545401444040u, 0x5554455045501400u, 0x4655155555555145u, 0x1000010055455055u,
+ 0x1000004000055004u, 0x4455405104000005u, 0x4500114504150545u, 0x0000000014000000u,
+ 0x5450000000000000u, 0x5514551511445555u, 0x4111501040555451u, 0x4515445500054444u,
+ 0x5101500104100441u, 0x1545115155545055u, 0x0000000000000000u, 0x1554000000100000u,
+ 0x5555545595551555u, 0x5555051851455955u, 0x5555555555555559u, 0x0000400011001555u,
+ 0x0000004400040000u, 0x5455511555554554u, 0x5614555544115445u, 0x6455156145555155u,
+ 0x5455855455415455u, 0x5515555144555545u, 0x0114400000145155u, 0x0000051000450511u,
+ 0x4455154554445100u, 0x4554150141544455u, 0x65955555559a5965u, 0x5555555854559559u,
+ 0x9569654559616595u, 0x1040044040005565u, 0x1010010500011044u, 0x1554015545154540u,
+ 0x4440555401545441u, 0x1014441450550105u, 0x4545400410504145u, 0x5015111541040151u,
+ 0x5145051154000410u, 0x1040001044545044u, 0x4001400000151410u, 0x0540000044040000u,
+ 0x0510555454411544u, 0x0400054054141550u, 0x1001041145001100u, 0x0000000140000000u,
+ 0x0000000014100000u, 0x1544005454000140u, 0x4050055505445145u, 0x0011511104504155u,
+ 0x5505544415045055u, 0x1155154445515554u, 0x0000000000004555u, 0x0000000000000000u,
+ 0x5101010510400004u, 0x1514045044440400u, 0x5515519555515555u, 0x4554545441555545u,
+ 0x1551055955551515u, 0x0150000011505515u, 0x0044005040400000u, 0x0004001004010050u,
+ 0x0000051004450414u, 0x0114001101001144u, 0x0401000001000001u, 0x4500010001000401u,
+ 0x0004100000005000u, 0x0105000441101100u, 0x0455455550454540u, 0x5404050144105505u,
+ 0x4101510540555455u, 0x1055541411451555u, 0x5451445110115505u, 0x1154110010101545u,
+ 0x1145140450054055u, 0x5555565415551554u, 0x1550559555555555u, 0x5555541545045141u,
+ 0x4555455450500100u, 0x5510454545554555u, 0x1510140115045455u, 0x1001050040111510u,
+ 0x5555454555555504u, 0x9954155545515554u, 0x6596656555555555u, 0x0140410051555559u,
+ 0x0011104010001544u, 0x965669659a680501u, 0x5655a55955556955u, 0x4015111014404514u,
+ 0x1414155554505145u, 0x0540040011051404u, 0x1010000000015005u, 0x0010054050004410u,
+ 0x5041104014000100u, 0x4440010500100001u, 0x1155510504545554u, 0x0450151545115541u,
+ 0x4000100400110440u, 0x1004440010514440u, 0x0000115050450000u, 0x0545404455541500u,
+ 0x1051051555505101u, 0x5505144554544144u, 0x4550545555515550u, 0x0015400450045445u,
+ 0x4514155400554415u, 0x4555055051050151u, 0x1511441450001014u, 0x4544554510404414u,
+ 0x4115115545545450u, 0x5500541555551555u, 0x5550010544155015u, 0x0144414045545500u,
+ 0x4154050001050150u, 0x5550511111000145u, 0x1114504055000151u, 0x5104041101451040u,
+ 0x0010501401051441u, 0x0010501450504401u, 0x4554585440044444u, 0x5155555951450455u,
+ 0x0040000400105555u, 0x0000000000000001u,
+ };
+
+};
+
+#if defined(BOOST_NO_CXX17_INLINE_VARIABLES) && (!defined(BOOST_MSVC) || BOOST_MSVC != 1900)
+
+template <bool b> constexpr uint64_t ryu_tables_template<b>::GENERIC_POW5_TABLE[BOOST_CHARCONV_POW5_TABLE_SIZE][2];
+template <bool b> constexpr uint64_t ryu_tables_template<b>::GENERIC_POW5_SPLIT[89][4];
+template <bool b> constexpr uint64_t ryu_tables_template<b>::GENERIC_POW5_INV_SPLIT[89][4];
+template <bool b> constexpr uint64_t ryu_tables_template<b>::POW5_ERRORS[156];
+template <bool b> constexpr uint64_t ryu_tables_template<b>::POW5_INV_ERRORS[154];
+
+#endif
+
+#if (!defined(BOOST_MSVC) || BOOST_MSVC != 1900)
+
+using ryu_tables = ryu_tables_template<true>;
+
+#endif
+
+// Returns e == 0 ? 1 : ceil(log_2(5^e)); requires 0 <= e <= 32768.
+static BOOST_CHARCONV_CXX14_CONSTEXPR uint32_t pow5bits(const uint32_t e) noexcept
+{
+ BOOST_CHARCONV_ASSERT(e <= 1 << 15);
+ return static_cast<uint32_t>(((e * UINT64_C(163391164108059)) >> 46) + 1);
+}
+
+static BOOST_CHARCONV_CXX14_CONSTEXPR
+void mul_128_256_shift(
+ const uint64_t* const a, const uint64_t* const b,
+ const uint32_t shift, const uint32_t corr,
+ uint64_t* const result) noexcept
+{
+ BOOST_CHARCONV_ASSERT(shift > 0);
+ BOOST_CHARCONV_ASSERT(shift < 256);
+ const unsigned_128_type b00 = static_cast<unsigned_128_type>(a[0]) * b[0]; // 0
+ const unsigned_128_type b01 = static_cast<unsigned_128_type>(a[0]) * b[1]; // 64
+ const unsigned_128_type b02 = static_cast<unsigned_128_type>(a[0]) * b[2]; // 128
+ const unsigned_128_type b03 = static_cast<unsigned_128_type>(a[0]) * b[3]; // 196
+ const unsigned_128_type b10 = static_cast<unsigned_128_type>(a[1]) * b[0]; // 64
+ const unsigned_128_type b11 = static_cast<unsigned_128_type>(a[1]) * b[1]; // 128
+ const unsigned_128_type b12 = static_cast<unsigned_128_type>(a[1]) * b[2]; // 196
+ const unsigned_128_type b13 = static_cast<unsigned_128_type>(a[1]) * b[3]; // 256
+
+ const unsigned_128_type s0 = b00; // 0 x
+ const unsigned_128_type s1 = b01 + b10; // 64 x
+ const unsigned_128_type c1 = s1 < b01; // 196 x
+ const unsigned_128_type s2 = b02 + b11; // 128 x
+ const unsigned_128_type c2 = s2 < b02; // 256 x
+ const unsigned_128_type s3 = b03 + b12; // 196 x
+ const unsigned_128_type c3 = s3 < b03; // 324 x
+
+ const unsigned_128_type p0 = s0 + (s1 << 64); // 0
+ const unsigned_128_type d0 = p0 < b00; // 128
+ const unsigned_128_type q1 = s2 + (s1 >> 64) + (s3 << 64); // 128
+ const unsigned_128_type d1 = q1 < s2; // 256
+ const unsigned_128_type p1 = q1 + (c1 << 64) + d0; // 128
+ const unsigned_128_type d2 = p1 < q1; // 256
+ const unsigned_128_type p2 = b13 + (s3 >> 64) + c2 + (c3 << 64) + d1 + d2; // 256
+
+ if (shift < 128)
+ {
+ const unsigned_128_type r0 = corr + ((p0 >> shift) | (p1 << (128 - shift)));
+ const unsigned_128_type r1 = ((p1 >> shift) | (p2 << (128 - shift))) + (r0 < corr);
+ result[0] = static_cast<uint64_t>(r0);
+ result[1] = static_cast<uint64_t>(r0 >> 64);
+ result[2] = static_cast<uint64_t>(r1);
+ result[3] = static_cast<uint64_t>(r1 >> 64);
+ }
+ else if (shift == 128)
+ {
+ const unsigned_128_type r0 = corr + p1;
+ const unsigned_128_type r1 = p2 + (r0 < corr);
+ result[0] = static_cast<uint64_t>(r0);
+ result[1] = static_cast<uint64_t>(r0 >> 64);
+ result[2] = static_cast<uint64_t>(r1);
+ result[3] = static_cast<uint64_t>(r1 >> 64);
+ }
+ else
+ {
+ const unsigned_128_type r0 = corr + ((p1 >> (shift - 128)) | (p2 << (256 - shift)));
+ const unsigned_128_type r1 = (p2 >> (shift - 128)) + (r0 < corr);
+ result[0] = static_cast<uint64_t>(r0);
+ result[1] = static_cast<uint64_t>(r0 >> 64);
+ result[2] = static_cast<uint64_t>(r1);
+ result[3] = static_cast<uint64_t>(r1 >> 64);
+ }
+}
+
+// Computes 5^i in the form required by Ryu, and stores it in the given pointer.
+static BOOST_CXX14_CONSTEXPR void generic_computePow5(const uint32_t i, uint64_t* const result) noexcept
+{
+ const uint32_t base = i / BOOST_CHARCONV_POW5_TABLE_SIZE;
+ const uint32_t base2 = base * BOOST_CHARCONV_POW5_TABLE_SIZE;
+ const uint64_t* const mul = ryu_tables::GENERIC_POW5_SPLIT[base];
+ if (i == base2)
+ {
+ result[0] = mul[0];
+ result[1] = mul[1];
+ result[2] = mul[2];
+ result[3] = mul[3];
+ }
+ else
+ {
+ const uint32_t offset = i - base2;
+ const uint64_t* const m = ryu_tables::GENERIC_POW5_TABLE[offset];
+ const uint32_t delta = pow5bits(i) - pow5bits(base2);
+ const uint32_t corr = static_cast<uint32_t>((ryu_tables::POW5_ERRORS[i / 32] >> (2 * (i % 32))) & 3);
+ mul_128_256_shift(m, mul, delta, corr, result);
+ }
+}
+
+// Computes 5^-i in the form required by Ryu, and stores it in the given pointer.
+static BOOST_CXX14_CONSTEXPR void generic_computeInvPow5(const uint32_t i, uint64_t* const result) noexcept
+{
+ const uint32_t base = (i + BOOST_CHARCONV_POW5_TABLE_SIZE - 1) / BOOST_CHARCONV_POW5_TABLE_SIZE;
+ const uint32_t base2 = base * BOOST_CHARCONV_POW5_TABLE_SIZE;
+ const uint64_t* const mul = ryu_tables::GENERIC_POW5_INV_SPLIT[base]; // 1/5^base2
+ if (i == base2)
+ {
+ result[0] = mul[0] + 1;
+ result[1] = mul[1];
+ result[2] = mul[2];
+ result[3] = mul[3];
+ }
+ else
+ {
+ const uint32_t offset = base2 - i;
+ const uint64_t* const m = ryu_tables::GENERIC_POW5_TABLE[offset]; // 5^offset
+ const uint32_t delta = pow5bits(base2) - pow5bits(i);
+ const uint32_t corr = static_cast<uint32_t>((ryu_tables::POW5_INV_ERRORS[i / 32] >> (2 * (i % 32))) & 3) + UINT32_C(1);
+ mul_128_256_shift(m, mul, delta, corr, result);
+ }
+}
+
+static BOOST_CXX14_CONSTEXPR uint32_t pow5Factor(unsigned_128_type value) noexcept
+{
+ for (uint32_t count = 0; value > 0; ++count)
+ {
+ if (value % 5 != 0)
+ {
+ return count;
+ }
+ value /= 5;
+ }
+ return 0;
+}
+
+// Returns true if value is divisible by 5^p.
+static BOOST_CHARCONV_CXX14_CONSTEXPR bool multipleOfPowerOf5(const unsigned_128_type value, const uint32_t p) noexcept
+{
+ // I tried a case distinction on p, but there was no performance difference.
+ return pow5Factor(value) >= p;
+}
+
+// Returns true if value is divisible by 2^p.
+static BOOST_CHARCONV_CXX14_CONSTEXPR bool multipleOfPowerOf2(const unsigned_128_type value, const uint32_t p) noexcept
+{
+ return (value & ((static_cast<unsigned_128_type>(1) << p) - 1)) == 0;
+}
+
+static BOOST_CHARCONV_CXX14_CONSTEXPR
+unsigned_128_type mulShift(const unsigned_128_type m, const uint64_t* const mul, const int32_t j) noexcept
+{
+ BOOST_CHARCONV_ASSERT(j > 128);
+ uint64_t a[2] {};
+ a[0] = static_cast<uint64_t>(m);
+ a[1] = static_cast<uint64_t>(m >> 64);
+ uint64_t result[4] {};
+ mul_128_256_shift(a, mul, static_cast<uint32_t>(j), 0, result);
+ return (static_cast<unsigned_128_type>(result[1]) << 64) | result[0];
+}
+
+// Returns floor(log_10(2^e)).
+static BOOST_CHARCONV_CXX14_CONSTEXPR uint32_t log10Pow2(const int32_t e) noexcept
+{
+ // The first value this approximation fails for is 2^1651 which is just greater than 10^297.
+ BOOST_CHARCONV_ASSERT(e >= 0);
+ BOOST_CHARCONV_ASSERT(e <= 1 << 15);
+ return static_cast<uint32_t>((static_cast<uint64_t>(e) * UINT64_C(169464822037455)) >> 49);
+}
+
+// Returns floor(log_10(5^e)).
+static BOOST_CHARCONV_CXX14_CONSTEXPR uint32_t log10Pow5(const int32_t e) noexcept
+{
+ // The first value this approximation fails for is 5^2621 which is just greater than 10^1832.
+ assert(e >= 0);
+ assert(e <= 1 << 15);
+ return static_cast<uint32_t>((static_cast<uint64_t>(e) * UINT64_C(196742565691928)) >> 48);
+}
+
+}}}} // Namespaces
+
+#endif // BOOST_CHARCONV_DETAIL_RYU_GENERIC_128_HPP
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/ryu/ryu_generic_128.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/ryu/ryu_generic_128.hpp
new file mode 100644
index 00000000000..2047d9a70f2
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/ryu/ryu_generic_128.hpp
@@ -0,0 +1,767 @@
+// Copyright 2018 - 2023 Ulf Adams
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_CHARCONV_DETAIL_RYU_RYU_GENERIC_128_HPP
+#define BOOST_CHARCONV_DETAIL_RYU_RYU_GENERIC_128_HPP
+
+#include <boost/charconv/detail/ryu/generic_128.hpp>
+#include <boost/charconv/detail/integer_search_trees.hpp>
+#include <boost/charconv/detail/config.hpp>
+#include <boost/charconv/detail/bit_layouts.hpp>
+#include <boost/charconv/to_chars.hpp>
+#include <cinttypes>
+#include <cstdio>
+#include <cstdint>
+
+#ifdef BOOST_CHARCONV_DEBUG
+# include <iostream>
+#endif
+
+namespace boost { namespace charconv { namespace detail { namespace ryu {
+
+static constexpr int32_t fd128_exceptional_exponent = 0x7FFFFFFF;
+static constexpr unsigned_128_type one = 1;
+
+struct floating_decimal_128
+{
+ unsigned_128_type mantissa;
+ int32_t exponent;
+ bool sign;
+};
+
+#ifdef BOOST_CHARCONV_DEBUG
+static char* s(unsigned_128_type v) {
+ int len = num_digits(v);
+ char* b = static_cast<char*>(malloc((len + 1) * sizeof(char)));
+ for (int i = 0; i < len; i++) {
+ const uint32_t c = static_cast<uint32_t>(v % 10);
+ v /= 10;
+ b[len - 1 - i] = static_cast<char>('0' + c);
+ }
+ b[len] = 0;
+ return b;
+}
+#endif
+
+static inline struct floating_decimal_128 generic_binary_to_decimal(
+ const unsigned_128_type bits,
+ const uint32_t mantissaBits, const uint32_t exponentBits, const bool explicitLeadingBit) noexcept
+{
+ #ifdef BOOST_CHARCONV_DEBUG
+ printf("IN=");
+ for (int32_t bit = 127; bit >= 0; --bit)
+ {
+ printf("%u", static_cast<uint32_t>((bits >> bit) & 1));
+ }
+ printf("\n");
+ #endif
+
+ const uint32_t bias = (1u << (exponentBits - 1)) - 1;
+ const bool ieeeSign = ((bits >> (mantissaBits + exponentBits)) & 1) != 0;
+ const unsigned_128_type ieeeMantissa = bits & ((one << mantissaBits) - 1);
+ const uint32_t ieeeExponent = static_cast<uint32_t>((bits >> mantissaBits) & ((one << exponentBits) - 1u));
+
+ if (ieeeExponent == 0 && ieeeMantissa == 0)
+ {
+ struct floating_decimal_128 fd {0, 0, ieeeSign};
+ return fd;
+ }
+ if (ieeeExponent == ((1u << exponentBits) - 1u))
+ {
+ struct floating_decimal_128 fd;
+ fd.mantissa = explicitLeadingBit ? ieeeMantissa & ((one << (mantissaBits - 1)) - 1) : ieeeMantissa;
+ fd.exponent = fd128_exceptional_exponent;
+ fd.sign = ieeeSign;
+ return fd;
+ }
+
+ int32_t e2;
+ unsigned_128_type m2;
+ // We subtract 2 in all cases so that the bounds computation has 2 additional bits.
+ if (explicitLeadingBit)
+ {
+ // mantissaBits includes the explicit leading bit, so we need to correct for that here.
+ if (ieeeExponent == 0)
+ {
+ e2 = static_cast<int32_t>(1 - bias - mantissaBits + 1 - 2);
+ }
+ else
+ {
+ e2 = static_cast<int32_t>(ieeeExponent - bias - mantissaBits + 1 - 2);
+ }
+ m2 = ieeeMantissa;
+ }
+ else
+ {
+ if (ieeeExponent == 0)
+ {
+ e2 = static_cast<int32_t>(1 - bias - mantissaBits - 2);
+ m2 = ieeeMantissa;
+ } else
+ {
+ e2 = static_cast<int32_t>(ieeeExponent - bias - mantissaBits - 2U);
+ m2 = (one << mantissaBits) | ieeeMantissa;
+ }
+ }
+ const bool even = (m2 & 1) == 0;
+ const bool acceptBounds = even;
+
+ #ifdef BOOST_CHARCONV_DEBUG
+ printf("-> %s %s * 2^%d\n", ieeeSign ? "-" : "+", s(m2), e2 + 2);
+ #endif
+
+ // Step 2: Determine the interval of legal decimal representations.
+ const unsigned_128_type mv = 4 * m2;
+ // Implicit bool -> int conversion. True is 1, false is 0.
+ const uint32_t mmShift =
+ (ieeeMantissa != (explicitLeadingBit ? one << (mantissaBits - 1) : 0))
+ || (ieeeExponent == 0);
+
+ // Step 3: Convert to a decimal power base using 128-bit arithmetic.
+ unsigned_128_type vr;
+ unsigned_128_type vp;
+ unsigned_128_type vm;
+ int32_t e10;
+ bool vmIsTrailingZeros = false;
+ bool vrIsTrailingZeros = false;
+ if (e2 >= 0)
+ {
+ // I tried special-casing q == 0, but there was no effect on performance.
+ // This expression is slightly faster than max(0, log10Pow2(e2) - 1).
+ const uint32_t q = log10Pow2(e2) - (e2 > 3);
+ e10 = static_cast<int32_t>(q);
+ const int32_t k = BOOST_CHARCONV_POW5_INV_BITCOUNT + static_cast<int32_t>(pow5bits(q)) - 1;
+ const int32_t i = -e2 + static_cast<int32_t>(q) + k;
+ uint64_t pow5[4];
+ generic_computeInvPow5(q, pow5);
+ vr = mulShift(4 * m2, pow5, i);
+ vp = mulShift(4 * m2 + 2, pow5, i);
+ vm = mulShift(4 * m2 - 1 - mmShift, pow5, i);
+
+ #ifdef BOOST_CHARCONV_DEBUG
+ printf("%s * 2^%d / 10^%d\n", s(mv), e2, q);
+ printf("V+=%s\nV =%s\nV-=%s\n", s(vp), s(vr), s(vm));
+ #endif
+
+ // floor(log_5(2^128)) = 55, this is very conservative
+ if (q <= 55)
+ {
+ // Only one of mp, mv, and mm can be a multiple of 5, if any.
+ if (mv % 5 == 0)
+ {
+ vrIsTrailingZeros = multipleOfPowerOf5(mv, q - 1);
+ }
+ else if (acceptBounds)
+ {
+ // Same as min(e2 + (~mm & 1), pow5Factor(mm)) >= q
+ // <=> e2 + (~mm & 1) >= q && pow5Factor(mm) >= q
+ // <=> true && pow5Factor(mm) >= q, since e2 >= q.
+ vmIsTrailingZeros = multipleOfPowerOf5(mv - 1 - mmShift, q);
+ }
+ else
+ {
+ // Same as min(e2 + 1, pow5Factor(mp)) >= q.
+ vp -= multipleOfPowerOf5(mv + 2, q);
+ }
+ }
+ }
+ else
+ {
+ // This expression is slightly faster than max(0, log10Pow5(-e2) - 1).
+ const uint32_t q = log10Pow5(-e2) - static_cast<uint32_t>(-e2 > 1);
+ e10 = static_cast<int32_t>(q) + e2;
+ const int32_t i = -e2 - static_cast<int32_t>(q);
+ const int32_t k = static_cast<int32_t>(pow5bits(static_cast<uint32_t>(i))) - BOOST_CHARCONV_POW5_BITCOUNT;
+ const int32_t j = static_cast<int32_t>(q) - k;
+ uint64_t pow5[4];
+ generic_computePow5(static_cast<uint32_t>(i), pow5);
+ vr = mulShift(4 * m2, pow5, j);
+ vp = mulShift(4 * m2 + 2, pow5, j);
+ vm = mulShift(4 * m2 - 1 - mmShift, pow5, j);
+
+ #ifdef BOOST_CHARCONV_DEBUG
+ printf("%s * 5^%d / 10^%d\n", s(mv), -e2, q);
+ printf("%d %d %d %d\n", q, i, k, j);
+ printf("V+=%s\nV =%s\nV-=%s\n", s(vp), s(vr), s(vm));
+ #endif
+
+ if (q <= 1)
+ {
+ // {vr,vp,vm} is trailing zeros if {mv,mp,mm} has at least q trailing 0 bits.
+ // mv = 4 m2, so it always has at least two trailing 0 bits.
+ vrIsTrailingZeros = true;
+ if (acceptBounds)
+ {
+ // mm = mv - 1 - mmShift, so it has 1 trailing 0 bit iff mmShift == 1.
+ vmIsTrailingZeros = mmShift == 1;
+ }
+ else
+ {
+ // mp = mv + 2, so it always has at least one trailing 0 bit.
+ --vp;
+ }
+ }
+ else if (q < 127)
+ {
+ // We need to compute min(ntz(mv), pow5Factor(mv) - e2) >= q-1
+ // <=> ntz(mv) >= q-1 && pow5Factor(mv) - e2 >= q-1
+ // <=> ntz(mv) >= q-1 (e2 is negative and -e2 >= q)
+ // <=> (mv & ((1 << (q-1)) - 1)) == 0
+ // We also need to make sure that the left shift does not overflow.
+ vrIsTrailingZeros = multipleOfPowerOf2(mv, q - 1);
+
+ #ifdef BOOST_CHARCONV_DEBUG
+ printf("vr is trailing zeros=%s\n", vrIsTrailingZeros ? "true" : "false");
+ #endif
+ }
+ }
+
+ #ifdef BOOST_CHARCONV_DEBUG
+ printf("e10=%d\n", e10);
+ printf("V+=%s\nV =%s\nV-=%s\n", s(vp), s(vr), s(vm));
+ printf("vm is trailing zeros=%s\n", vmIsTrailingZeros ? "true" : "false");
+ printf("vr is trailing zeros=%s\n", vrIsTrailingZeros ? "true" : "false");
+ #endif
+
+ // Step 4: Find the shortest decimal representation in the interval of legal representations.
+ uint32_t removed = 0;
+ uint8_t lastRemovedDigit = 0;
+ unsigned_128_type output;
+
+ while (vp / 10 > vm / 10)
+ {
+ vmIsTrailingZeros &= vm % 10 == 0;
+ vrIsTrailingZeros &= lastRemovedDigit == 0;
+ lastRemovedDigit = static_cast<uint8_t>(vr % 10);
+ vr /= 10;
+ vp /= 10;
+ vm /= 10;
+ ++removed;
+ }
+
+ #ifdef BOOST_CHARCONV_DEBUG
+ printf("V+=%s\nV =%s\nV-=%s\n", s(vp), s(vr), s(vm));
+ printf("d-10=%s\n", vmIsTrailingZeros ? "true" : "false");
+ #endif
+
+ if (vmIsTrailingZeros)
+ {
+ while (vm % 10 == 0)
+ {
+ vrIsTrailingZeros &= lastRemovedDigit == 0;
+ lastRemovedDigit = static_cast<uint8_t>(vr % 10);
+ vr /= 10;
+ vp /= 10;
+ vm /= 10;
+ ++removed;
+ }
+ }
+
+ #ifdef BOOST_CHARCONV_DEBUG
+ printf("%s %d\n", s(vr), lastRemovedDigit);
+ printf("vr is trailing zeros=%s\n", vrIsTrailingZeros ? "true" : "false");
+ #endif
+
+ if (vrIsTrailingZeros && (lastRemovedDigit == 5) && (vr % 2 == 0))
+ {
+ // Round even if the exact numbers is .....50..0.
+ lastRemovedDigit = 4;
+ }
+ // We need to take vr+1 if vr is outside bounds, or we need to round up.
+ output = vr + static_cast<unsigned_128_type>((vr == vm && (!acceptBounds || !vmIsTrailingZeros)) || (lastRemovedDigit >= 5));
+ const int32_t exp = e10 + static_cast<int32_t>(removed);
+
+ #ifdef BOOST_CHARCONV_DEBUG
+ printf("V+=%s\nV =%s\nV-=%s\n", s(vp), s(vr), s(vm));
+ printf("O=%s\n", s(output));
+ printf("EXP=%d\n", exp);
+ #endif
+
+ return {output, exp, ieeeSign};
+}
+
+static inline int copy_special_str(char* result, const std::ptrdiff_t result_size, const struct floating_decimal_128 fd) noexcept
+{
+ if (fd.sign)
+ {
+ *result = '-';
+ ++result;
+ }
+
+ if (fd.mantissa)
+ {
+ if (fd.sign)
+ {
+ if (fd.mantissa == static_cast<unsigned_128_type>(2305843009213693952) ||
+ fd.mantissa == static_cast<unsigned_128_type>(6917529027641081856) ||
+ fd.mantissa == static_cast<unsigned_128_type>(1) << 110) // 2^110
+ {
+ if (result_size >= 10)
+ {
+ std::memcpy(result, "nan(snan)", 9);
+ return 10;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ else
+ {
+ if (result_size >= 9)
+ {
+ std::memcpy(result, "nan(ind)", 8);
+ return 9;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ }
+ else
+ {
+ if (fd.mantissa == static_cast<unsigned_128_type>(2305843009213693952) ||
+ fd.mantissa == static_cast<unsigned_128_type>(6917529027641081856) ||
+ fd.mantissa == static_cast<unsigned_128_type>(1) << 110) // 2^110
+ {
+ if (result_size >= 9)
+ {
+ std::memcpy(result, "nan(snan)", 9);
+ return 9;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ else
+ {
+ if (result_size >= 3)
+ {
+ std::memcpy(result, "nan", 3);
+ return 3;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ }
+ }
+
+ if (result_size >= 3 + static_cast<std::ptrdiff_t>(fd.sign))
+ {
+ memcpy(result, "inf", 3);
+ return static_cast<int>(fd.sign) + 3;
+ }
+
+ return -1;
+}
+
+static inline int generic_to_chars_fixed(const struct floating_decimal_128 v, char* result, const ptrdiff_t result_size, int precision) noexcept
+{
+ if (v.exponent == fd128_exceptional_exponent)
+ {
+ return copy_special_str(result, result_size, v);
+ }
+
+ // Step 5: Print the decimal representation.
+ if (v.sign)
+ {
+ *result++ = '-';
+ }
+
+ unsigned_128_type output = v.mantissa;
+ const auto r = to_chars_128integer_impl(result, result + result_size, output);
+ if (r.ec != std::errc())
+ {
+ return -static_cast<int>(r.ec);
+ }
+
+ auto current_len = static_cast<int>(r.ptr - result);
+
+ #ifdef BOOST_CHARCONV_DEBUG
+ char* man_print = s(v.mantissa);
+ std::cerr << "Exp: " << v.exponent
+ << "\nMantissa: " << man_print
+ << "\nMan len: " << current_len << std::endl;
+ free(man_print);
+ #endif
+
+ if (v.exponent == 0)
+ {
+ // Option 1: We need to do nothing but insert 0s
+ if (precision > 0)
+ {
+ result[current_len++] = '.';
+ memset(result+current_len, '0', static_cast<size_t>(precision));
+ current_len += precision;
+ precision = 0;
+ }
+ }
+ else if (v.exponent > 0)
+ {
+ // Option 2: Append 0s to the end of the number until we get the proper significand value
+ // Then we need precison worth of zeros after the decimal point as applicable
+ if (current_len + v.exponent > result_size)
+ {
+ return -static_cast<int>(std::errc::value_too_large);
+ }
+
+ result = r.ptr;
+ memset(result, '0', static_cast<std::size_t>(v.exponent));
+ result += static_cast<std::size_t>(v.exponent);
+ *result++ = '.';
+ current_len += v.exponent + 1;
+ }
+ else if ((-v.exponent) < current_len)
+ {
+ // Option 3: Insert a decimal point into the middle of the existing number
+ if (current_len + v.exponent + 1 > result_size)
+ {
+ return -static_cast<int>(std::errc::result_out_of_range);
+ }
+
+ memmove(result + current_len + v.exponent + 1, result + current_len + v.exponent, static_cast<std::size_t>(-v.exponent));
+ const auto shift = result + current_len + v.exponent;
+ const auto shift_width = (shift - result) + 1;
+ memcpy(shift, ".", 1U);
+ ++current_len;
+ if (current_len - shift_width > precision)
+ {
+ if (precision > 0)
+ {
+ current_len = static_cast<int>(shift_width) + precision;
+ }
+
+ precision = 0;
+ // Since we wrote additional characters into the buffer we need to add a null terminator,
+ // so they are not read
+ const auto round_val = result[current_len];
+ result[current_len] = '\0';
+
+ // More complicated rounding situations like 9999.999999 are already handled
+ // so we don't need to worry about rounding past the decimal point
+ if (round_val >= '5')
+ {
+ auto current_spot = current_len - 1;
+ bool continue_rounding = true;
+ while (result[current_spot] != '.' && continue_rounding)
+ {
+ if (result[current_spot] < '9')
+ {
+ result[current_spot] = static_cast<char>(static_cast<int>(result[current_spot]) + 1);
+ continue_rounding = false;
+ }
+ else
+ {
+ result[current_spot] = '0';
+ continue_rounding = true;
+ }
+ --current_spot;
+ }
+ BOOST_CHARCONV_ASSERT(!continue_rounding);
+ }
+ }
+ else
+ {
+ precision -= current_len - static_cast<int>(shift_width);
+ result += current_len + v.exponent + 1;
+ }
+ }
+ else
+ {
+ // Option 4: Leading 0s
+ if (-v.exponent + 2 > result_size)
+ {
+ return -static_cast<int>(std::errc::value_too_large);
+ }
+
+ memmove(result - v.exponent - current_len + 2, result, static_cast<std::size_t>(current_len));
+ memcpy(result, "0.", 2U);
+ memset(result + 2, '0', static_cast<std::size_t>(0 - v.exponent - current_len));
+ current_len = -v.exponent + 2;
+ precision -= current_len - 2;
+ result += current_len;
+ }
+
+ if (precision > 0)
+ {
+ if (current_len + precision > result_size)
+ {
+ return -static_cast<int>(std::errc::result_out_of_range);
+ }
+
+ memset(result, '0', static_cast<std::size_t>(precision));
+ current_len += precision;
+ }
+
+ return current_len + static_cast<int>(v.sign);
+}
+
+// Converts the given decimal floating point number to a string, writing to result, and returning
+// the number characters written. Does not terminate the buffer with a 0. In the worst case, this
+// function can write up to 53 characters.
+//
+// Maximal char buffer requirement:
+// sign + mantissa digits + decimal dot + 'E' + exponent sign + exponent digits
+// = 1 + 39 + 1 + 1 + 1 + 10 = 53
+static inline int generic_to_chars(const struct floating_decimal_128 v, char* result, const ptrdiff_t result_size,
+ chars_format fmt = chars_format::general, int precision = -1) noexcept
+{
+ if (v.exponent == fd128_exceptional_exponent)
+ {
+ return copy_special_str(result, result_size, v);
+ }
+
+ unsigned_128_type output = v.mantissa;
+ const uint32_t olength = static_cast<uint32_t>(num_digits(output));
+
+ #ifdef BOOST_CHARCONV_DEBUG
+ printf("DIGITS=%s\n", s(v.mantissa));
+ printf("OLEN=%u\n", olength);
+ printf("EXP=%u\n", v.exponent + olength);
+ #endif
+
+ // See: https://github.com/cppalliance/charconv/issues/64
+ if (fmt == chars_format::general)
+ {
+ const int64_t exp = v.exponent + static_cast<int64_t>(olength);
+ if (std::abs(exp) <= olength)
+ {
+ auto ptr = generic_to_chars_fixed(v, result, result_size, precision);
+ if (ptr >= 1 && result[ptr - 1] == '0')
+ {
+ --ptr;
+ while (ptr > 0 && result[ptr] == '0')
+ {
+ --ptr;
+ }
+ ++ptr;
+ }
+ return ptr;
+ }
+ }
+
+ // Step 5: Print the decimal representation.
+ size_t index = 0;
+ if (v.sign)
+ {
+ result[index++] = '-';
+ }
+
+ if (index + olength > static_cast<size_t>(result_size))
+ {
+ return -static_cast<int>(std::errc::value_too_large);
+ }
+ else if (olength == 0)
+ {
+ return -2; // Something has gone horribly wrong
+ }
+
+ for (uint32_t i = 0; i < olength - 1; ++i)
+ {
+ const auto c = static_cast<uint32_t>(output % 10);
+ output /= 10;
+ result[index + olength - i] = static_cast<char>('0' + c);
+ }
+ BOOST_CHARCONV_ASSERT(output < 10);
+ result[index] = static_cast<char>('0' + static_cast<uint32_t>(output % 10)); // output should be < 10 by now.
+
+ // Print decimal point if needed.
+ if (olength > 1)
+ {
+ result[index + 1] = '.';
+ index += olength + 1;
+ }
+ else
+ {
+ ++index;
+ }
+
+ // Reset the index to where the required precision should be
+ if (precision != -1)
+ {
+ if (static_cast<size_t>(precision) < index)
+ {
+ if (fmt != chars_format::scientific)
+ {
+ index = static_cast<size_t>(precision) + 1 + static_cast<size_t>(v.sign); // Precision is number of characters not just the decimal portion
+ }
+ else
+ {
+ index = static_cast<size_t>(precision) + 2 + static_cast<size_t>(v.sign); // In scientific format the precision is just the decimal places
+ }
+
+ // Now we need to see if we need to round
+ if (result[index] >= '5' && index < olength + 1 + static_cast<size_t>(v.sign))
+ {
+ bool continue_rounding = false;
+ auto current_index = index;
+ do
+ {
+ --current_index;
+ if (result[current_index] == '9')
+ {
+ continue_rounding = true;
+ result[current_index] = '0';
+ }
+ else
+ {
+ continue_rounding = false;
+ result[current_index] = static_cast<char>(result[current_index] + static_cast<char>(1));
+ }
+ } while (continue_rounding && current_index > 2);
+ }
+
+ // If the last digit is a zero than overwrite that as well, but not in scientific formatting
+ if (fmt != chars_format::scientific)
+ {
+ while (result[index - 1] == '0')
+ {
+ --index;
+ }
+ }
+ else
+ {
+ // In scientific formatting we may need a final 0 to achieve the correct precision
+ if (precision + 1 > static_cast<int>(olength))
+ {
+ result[index - 1] = '0';
+ }
+ }
+ }
+ else if (static_cast<size_t>(precision) > index)
+ {
+ // Use our fallback routine that will capture more of the precision
+ return -1;
+ }
+ }
+
+ // Print the exponent.
+ result[index++] = 'e';
+ int32_t exp = v.exponent + static_cast<int32_t>(olength) - 1;
+ if (exp < 0)
+ {
+ result[index++] = '-';
+ exp = -exp;
+ }
+ else
+ {
+ result[index++] = '+';
+ }
+
+ uint32_t elength = static_cast<uint32_t>(num_digits(exp));
+ for (uint32_t i = 0; i < elength; ++i)
+ {
+ // Always print a minimum of 2 characters in the exponent field
+ if (elength == 1)
+ {
+ result[index + elength - 1 - i] = '0';
+ ++index;
+ }
+
+ const uint32_t c = static_cast<uint32_t>(exp % 10);
+ exp /= 10;
+ result[index + elength - 1 - i] = static_cast<char>('0' + c);
+ }
+ if (elength == 0)
+ {
+ result[index++] = '0';
+ result[index++] = '0';
+ }
+
+ index += elength;
+ return static_cast<int>(index);
+}
+
+static inline struct floating_decimal_128 float_to_fd128(float f) noexcept
+{
+ static_assert(sizeof(float) == sizeof(uint32_t), "Float is not 32 bits");
+ uint32_t bits = 0;
+ std::memcpy(&bits, &f, sizeof(float));
+ return generic_binary_to_decimal(bits, 23, 8, false);
+}
+
+static inline struct floating_decimal_128 double_to_fd128(double d) noexcept
+{
+ static_assert(sizeof(double) == sizeof(uint64_t), "Double is not 64 bits");
+ uint64_t bits = 0;
+ std::memcpy(&bits, &d, sizeof(double));
+ return generic_binary_to_decimal(bits, 52, 11, false);
+}
+
+// https://en.cppreference.com/w/cpp/types/floating-point#Fixed_width_floating-point_types
+
+#ifdef BOOST_CHARCONV_HAS_FLOAT16
+
+static inline struct floating_decimal_128 float16_t_to_fd128(std::float16_t f) noexcept
+{
+ uint16_t bits = 0;
+ std::memcpy(&bits, &f, sizeof(std::float16_t));
+ return generic_binary_to_decimal(bits, 10, 5, false);
+}
+
+#endif
+
+#ifdef BOOST_CHARCONV_HAS_BRAINFLOAT16
+
+static inline struct floating_decimal_128 float16_t_to_fd128(std::bfloat16_t f) noexcept
+{
+ uint16_t bits = 0;
+ std::memcpy(&bits, &f, sizeof(std::bfloat16_t));
+ return generic_binary_to_decimal(bits, 7, 8, false);
+}
+
+#endif
+
+#if BOOST_CHARCONV_LDBL_BITS == 80
+
+static inline struct floating_decimal_128 long_double_to_fd128(long double d) noexcept
+{
+ #ifdef BOOST_CHARCONV_HAS_INT128
+ unsigned_128_type bits = 0;
+ std::memcpy(&bits, &d, sizeof(long double));
+ #else
+ trivial_uint128 trivial_bits;
+ std::memcpy(&trivial_bits, &d, sizeof(long double));
+ unsigned_128_type bits {trivial_bits};
+ #endif
+
+ #ifdef BOOST_CHARCONV_DEBUG
+ // For some odd reason, this ends up with noise in the top 48 bits. We can
+ // clear out those bits with the following line; this is not required, the
+ // conversion routine should ignore those bits, but the debug output can be
+ // confusing if they aren't 0s.
+ bits &= (one << 80) - 1;
+ #endif
+
+ return generic_binary_to_decimal(bits, 64, 15, true);
+}
+
+#elif BOOST_CHARCONV_LDBL_BITS == 128
+
+static inline struct floating_decimal_128 long_double_to_fd128(long double d) noexcept
+{
+ unsigned_128_type bits = 0;
+ std::memcpy(&bits, &d, sizeof(long double));
+
+ #if LDBL_MANT_DIG == 113 // binary128 (e.g. ARM, S390X, PPC64LE)
+ # ifdef __PPC64__
+ return generic_binary_to_decimal(bits, 112, 15, false);
+ # else
+ return generic_binary_to_decimal(bits, 112, 15, true);
+ # endif
+ #elif LDBL_MANT_DIG == 106 // ibm128 (e.g. PowerPC)
+ return generic_binary_to_decimal(bits, 105, 11, true);
+ #endif
+}
+
+#endif
+
+}}}} // Namespaces
+
+#endif //BOOST_RYU_GENERIC_128_HPP
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/significand_tables.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/significand_tables.hpp
new file mode 100644
index 00000000000..51dd71f456e
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/significand_tables.hpp
@@ -0,0 +1,691 @@
+// Copyright 2020-2023 Daniel Lemire
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_CHARCONV_DETAIL_SIGNIFICAND_TABLES_HPP
+#define BOOST_CHARCONV_DETAIL_SIGNIFICAND_TABLES_HPP
+
+#include <boost/charconv/detail/config.hpp>
+#include <cstdint>
+
+// The significand of a floating point number is often referred to as the mantissa.
+// Using the term mantissa is discouraged by IEEE 1516
+
+namespace boost { namespace charconv { namespace detail {
+
+ // The significands of powers of ten from -308 to 308, extended out to sixty four
+ // bits. The array contains the powers of ten approximated
+ // as a 64-bit significand. It goes from 10^BOOST_CHARCONV_FASTFLOAT_SMALLEST_POWER to
+ // 10^BOOST_CHARCONV_FASTFLOAT_LARGEST_POWER (inclusively).
+ // The significand is truncated, and never rounded up.
+ // Uses about 5KB.
+
+#if (!defined(BOOST_MSVC) || BOOST_MSVC != 1900)
+template <bool b>
+struct significand_template
+#else
+struct significands_table
+#endif
+{
+ static constexpr std::uint64_t significand_64[] = {
+ 0xa5ced43b7e3e9188, 0xcf42894a5dce35ea,
+ 0x818995ce7aa0e1b2, 0xa1ebfb4219491a1f,
+ 0xca66fa129f9b60a6, 0xfd00b897478238d0,
+ 0x9e20735e8cb16382, 0xc5a890362fddbc62,
+ 0xf712b443bbd52b7b, 0x9a6bb0aa55653b2d,
+ 0xc1069cd4eabe89f8, 0xf148440a256e2c76,
+ 0x96cd2a865764dbca, 0xbc807527ed3e12bc,
+ 0xeba09271e88d976b, 0x93445b8731587ea3,
+ 0xb8157268fdae9e4c, 0xe61acf033d1a45df,
+ 0x8fd0c16206306bab, 0xb3c4f1ba87bc8696,
+ 0xe0b62e2929aba83c, 0x8c71dcd9ba0b4925,
+ 0xaf8e5410288e1b6f, 0xdb71e91432b1a24a,
+ 0x892731ac9faf056e, 0xab70fe17c79ac6ca,
+ 0xd64d3d9db981787d, 0x85f0468293f0eb4e,
+ 0xa76c582338ed2621, 0xd1476e2c07286faa,
+ 0x82cca4db847945ca, 0xa37fce126597973c,
+ 0xcc5fc196fefd7d0c, 0xff77b1fcbebcdc4f,
+ 0x9faacf3df73609b1, 0xc795830d75038c1d,
+ 0xf97ae3d0d2446f25, 0x9becce62836ac577,
+ 0xc2e801fb244576d5, 0xf3a20279ed56d48a,
+ 0x9845418c345644d6, 0xbe5691ef416bd60c,
+ 0xedec366b11c6cb8f, 0x94b3a202eb1c3f39,
+ 0xb9e08a83a5e34f07, 0xe858ad248f5c22c9,
+ 0x91376c36d99995be, 0xb58547448ffffb2d,
+ 0xe2e69915b3fff9f9, 0x8dd01fad907ffc3b,
+ 0xb1442798f49ffb4a, 0xdd95317f31c7fa1d,
+ 0x8a7d3eef7f1cfc52, 0xad1c8eab5ee43b66,
+ 0xd863b256369d4a40, 0x873e4f75e2224e68,
+ 0xa90de3535aaae202, 0xd3515c2831559a83,
+ 0x8412d9991ed58091, 0xa5178fff668ae0b6,
+ 0xce5d73ff402d98e3, 0x80fa687f881c7f8e,
+ 0xa139029f6a239f72, 0xc987434744ac874e,
+ 0xfbe9141915d7a922, 0x9d71ac8fada6c9b5,
+ 0xc4ce17b399107c22, 0xf6019da07f549b2b,
+ 0x99c102844f94e0fb, 0xc0314325637a1939,
+ 0xf03d93eebc589f88, 0x96267c7535b763b5,
+ 0xbbb01b9283253ca2, 0xea9c227723ee8bcb,
+ 0x92a1958a7675175f, 0xb749faed14125d36,
+ 0xe51c79a85916f484, 0x8f31cc0937ae58d2,
+ 0xb2fe3f0b8599ef07, 0xdfbdcece67006ac9,
+ 0x8bd6a141006042bd, 0xaecc49914078536d,
+ 0xda7f5bf590966848, 0x888f99797a5e012d,
+ 0xaab37fd7d8f58178, 0xd5605fcdcf32e1d6,
+ 0x855c3be0a17fcd26, 0xa6b34ad8c9dfc06f,
+ 0xd0601d8efc57b08b, 0x823c12795db6ce57,
+ 0xa2cb1717b52481ed, 0xcb7ddcdda26da268,
+ 0xfe5d54150b090b02, 0x9efa548d26e5a6e1,
+ 0xc6b8e9b0709f109a, 0xf867241c8cc6d4c0,
+ 0x9b407691d7fc44f8, 0xc21094364dfb5636,
+ 0xf294b943e17a2bc4, 0x979cf3ca6cec5b5a,
+ 0xbd8430bd08277231, 0xece53cec4a314ebd,
+ 0x940f4613ae5ed136, 0xb913179899f68584,
+ 0xe757dd7ec07426e5, 0x9096ea6f3848984f,
+ 0xb4bca50b065abe63, 0xe1ebce4dc7f16dfb,
+ 0x8d3360f09cf6e4bd, 0xb080392cc4349dec,
+ 0xdca04777f541c567, 0x89e42caaf9491b60,
+ 0xac5d37d5b79b6239, 0xd77485cb25823ac7,
+ 0x86a8d39ef77164bc, 0xa8530886b54dbdeb,
+ 0xd267caa862a12d66, 0x8380dea93da4bc60,
+ 0xa46116538d0deb78, 0xcd795be870516656,
+ 0x806bd9714632dff6, 0xa086cfcd97bf97f3,
+ 0xc8a883c0fdaf7df0, 0xfad2a4b13d1b5d6c,
+ 0x9cc3a6eec6311a63, 0xc3f490aa77bd60fc,
+ 0xf4f1b4d515acb93b, 0x991711052d8bf3c5,
+ 0xbf5cd54678eef0b6, 0xef340a98172aace4,
+ 0x9580869f0e7aac0e, 0xbae0a846d2195712,
+ 0xe998d258869facd7, 0x91ff83775423cc06,
+ 0xb67f6455292cbf08, 0xe41f3d6a7377eeca,
+ 0x8e938662882af53e, 0xb23867fb2a35b28d,
+ 0xdec681f9f4c31f31, 0x8b3c113c38f9f37e,
+ 0xae0b158b4738705e, 0xd98ddaee19068c76,
+ 0x87f8a8d4cfa417c9, 0xa9f6d30a038d1dbc,
+ 0xd47487cc8470652b, 0x84c8d4dfd2c63f3b,
+ 0xa5fb0a17c777cf09, 0xcf79cc9db955c2cc,
+ 0x81ac1fe293d599bf, 0xa21727db38cb002f,
+ 0xca9cf1d206fdc03b, 0xfd442e4688bd304a,
+ 0x9e4a9cec15763e2e, 0xc5dd44271ad3cdba,
+ 0xf7549530e188c128, 0x9a94dd3e8cf578b9,
+ 0xc13a148e3032d6e7, 0xf18899b1bc3f8ca1,
+ 0x96f5600f15a7b7e5, 0xbcb2b812db11a5de,
+ 0xebdf661791d60f56, 0x936b9fcebb25c995,
+ 0xb84687c269ef3bfb, 0xe65829b3046b0afa,
+ 0x8ff71a0fe2c2e6dc, 0xb3f4e093db73a093,
+ 0xe0f218b8d25088b8, 0x8c974f7383725573,
+ 0xafbd2350644eeacf, 0xdbac6c247d62a583,
+ 0x894bc396ce5da772, 0xab9eb47c81f5114f,
+ 0xd686619ba27255a2, 0x8613fd0145877585,
+ 0xa798fc4196e952e7, 0xd17f3b51fca3a7a0,
+ 0x82ef85133de648c4, 0xa3ab66580d5fdaf5,
+ 0xcc963fee10b7d1b3, 0xffbbcfe994e5c61f,
+ 0x9fd561f1fd0f9bd3, 0xc7caba6e7c5382c8,
+ 0xf9bd690a1b68637b, 0x9c1661a651213e2d,
+ 0xc31bfa0fe5698db8, 0xf3e2f893dec3f126,
+ 0x986ddb5c6b3a76b7, 0xbe89523386091465,
+ 0xee2ba6c0678b597f, 0x94db483840b717ef,
+ 0xba121a4650e4ddeb, 0xe896a0d7e51e1566,
+ 0x915e2486ef32cd60, 0xb5b5ada8aaff80b8,
+ 0xe3231912d5bf60e6, 0x8df5efabc5979c8f,
+ 0xb1736b96b6fd83b3, 0xddd0467c64bce4a0,
+ 0x8aa22c0dbef60ee4, 0xad4ab7112eb3929d,
+ 0xd89d64d57a607744, 0x87625f056c7c4a8b,
+ 0xa93af6c6c79b5d2d, 0xd389b47879823479,
+ 0x843610cb4bf160cb, 0xa54394fe1eedb8fe,
+ 0xce947a3da6a9273e, 0x811ccc668829b887,
+ 0xa163ff802a3426a8, 0xc9bcff6034c13052,
+ 0xfc2c3f3841f17c67, 0x9d9ba7832936edc0,
+ 0xc5029163f384a931, 0xf64335bcf065d37d,
+ 0x99ea0196163fa42e, 0xc06481fb9bcf8d39,
+ 0xf07da27a82c37088, 0x964e858c91ba2655,
+ 0xbbe226efb628afea, 0xeadab0aba3b2dbe5,
+ 0x92c8ae6b464fc96f, 0xb77ada0617e3bbcb,
+ 0xe55990879ddcaabd, 0x8f57fa54c2a9eab6,
+ 0xb32df8e9f3546564, 0xdff9772470297ebd,
+ 0x8bfbea76c619ef36, 0xaefae51477a06b03,
+ 0xdab99e59958885c4, 0x88b402f7fd75539b,
+ 0xaae103b5fcd2a881, 0xd59944a37c0752a2,
+ 0x857fcae62d8493a5, 0xa6dfbd9fb8e5b88e,
+ 0xd097ad07a71f26b2, 0x825ecc24c873782f,
+ 0xa2f67f2dfa90563b, 0xcbb41ef979346bca,
+ 0xfea126b7d78186bc, 0x9f24b832e6b0f436,
+ 0xc6ede63fa05d3143, 0xf8a95fcf88747d94,
+ 0x9b69dbe1b548ce7c, 0xc24452da229b021b,
+ 0xf2d56790ab41c2a2, 0x97c560ba6b0919a5,
+ 0xbdb6b8e905cb600f, 0xed246723473e3813,
+ 0x9436c0760c86e30b, 0xb94470938fa89bce,
+ 0xe7958cb87392c2c2, 0x90bd77f3483bb9b9,
+ 0xb4ecd5f01a4aa828, 0xe2280b6c20dd5232,
+ 0x8d590723948a535f, 0xb0af48ec79ace837,
+ 0xdcdb1b2798182244, 0x8a08f0f8bf0f156b,
+ 0xac8b2d36eed2dac5, 0xd7adf884aa879177,
+ 0x86ccbb52ea94baea, 0xa87fea27a539e9a5,
+ 0xd29fe4b18e88640e, 0x83a3eeeef9153e89,
+ 0xa48ceaaab75a8e2b, 0xcdb02555653131b6,
+ 0x808e17555f3ebf11, 0xa0b19d2ab70e6ed6,
+ 0xc8de047564d20a8b, 0xfb158592be068d2e,
+ 0x9ced737bb6c4183d, 0xc428d05aa4751e4c,
+ 0xf53304714d9265df, 0x993fe2c6d07b7fab,
+ 0xbf8fdb78849a5f96, 0xef73d256a5c0f77c,
+ 0x95a8637627989aad, 0xbb127c53b17ec159,
+ 0xe9d71b689dde71af, 0x9226712162ab070d,
+ 0xb6b00d69bb55c8d1, 0xe45c10c42a2b3b05,
+ 0x8eb98a7a9a5b04e3, 0xb267ed1940f1c61c,
+ 0xdf01e85f912e37a3, 0x8b61313bbabce2c6,
+ 0xae397d8aa96c1b77, 0xd9c7dced53c72255,
+ 0x881cea14545c7575, 0xaa242499697392d2,
+ 0xd4ad2dbfc3d07787, 0x84ec3c97da624ab4,
+ 0xa6274bbdd0fadd61, 0xcfb11ead453994ba,
+ 0x81ceb32c4b43fcf4, 0xa2425ff75e14fc31,
+ 0xcad2f7f5359a3b3e, 0xfd87b5f28300ca0d,
+ 0x9e74d1b791e07e48, 0xc612062576589dda,
+ 0xf79687aed3eec551, 0x9abe14cd44753b52,
+ 0xc16d9a0095928a27, 0xf1c90080baf72cb1,
+ 0x971da05074da7bee, 0xbce5086492111aea,
+ 0xec1e4a7db69561a5, 0x9392ee8e921d5d07,
+ 0xb877aa3236a4b449, 0xe69594bec44de15b,
+ 0x901d7cf73ab0acd9, 0xb424dc35095cd80f,
+ 0xe12e13424bb40e13, 0x8cbccc096f5088cb,
+ 0xafebff0bcb24aafe, 0xdbe6fecebdedd5be,
+ 0x89705f4136b4a597, 0xabcc77118461cefc,
+ 0xd6bf94d5e57a42bc, 0x8637bd05af6c69b5,
+ 0xa7c5ac471b478423, 0xd1b71758e219652b,
+ 0x83126e978d4fdf3b, 0xa3d70a3d70a3d70a,
+ 0xcccccccccccccccc, 0x8000000000000000,
+ 0xa000000000000000, 0xc800000000000000,
+ 0xfa00000000000000, 0x9c40000000000000,
+ 0xc350000000000000, 0xf424000000000000,
+ 0x9896800000000000, 0xbebc200000000000,
+ 0xee6b280000000000, 0x9502f90000000000,
+ 0xba43b74000000000, 0xe8d4a51000000000,
+ 0x9184e72a00000000, 0xb5e620f480000000,
+ 0xe35fa931a0000000, 0x8e1bc9bf04000000,
+ 0xb1a2bc2ec5000000, 0xde0b6b3a76400000,
+ 0x8ac7230489e80000, 0xad78ebc5ac620000,
+ 0xd8d726b7177a8000, 0x878678326eac9000,
+ 0xa968163f0a57b400, 0xd3c21bcecceda100,
+ 0x84595161401484a0, 0xa56fa5b99019a5c8,
+ 0xcecb8f27f4200f3a, 0x813f3978f8940984,
+ 0xa18f07d736b90be5, 0xc9f2c9cd04674ede,
+ 0xfc6f7c4045812296, 0x9dc5ada82b70b59d,
+ 0xc5371912364ce305, 0xf684df56c3e01bc6,
+ 0x9a130b963a6c115c, 0xc097ce7bc90715b3,
+ 0xf0bdc21abb48db20, 0x96769950b50d88f4,
+ 0xbc143fa4e250eb31, 0xeb194f8e1ae525fd,
+ 0x92efd1b8d0cf37be, 0xb7abc627050305ad,
+ 0xe596b7b0c643c719, 0x8f7e32ce7bea5c6f,
+ 0xb35dbf821ae4f38b, 0xe0352f62a19e306e,
+ 0x8c213d9da502de45, 0xaf298d050e4395d6,
+ 0xdaf3f04651d47b4c, 0x88d8762bf324cd0f,
+ 0xab0e93b6efee0053, 0xd5d238a4abe98068,
+ 0x85a36366eb71f041, 0xa70c3c40a64e6c51,
+ 0xd0cf4b50cfe20765, 0x82818f1281ed449f,
+ 0xa321f2d7226895c7, 0xcbea6f8ceb02bb39,
+ 0xfee50b7025c36a08, 0x9f4f2726179a2245,
+ 0xc722f0ef9d80aad6, 0xf8ebad2b84e0d58b,
+ 0x9b934c3b330c8577, 0xc2781f49ffcfa6d5,
+ 0xf316271c7fc3908a, 0x97edd871cfda3a56,
+ 0xbde94e8e43d0c8ec, 0xed63a231d4c4fb27,
+ 0x945e455f24fb1cf8, 0xb975d6b6ee39e436,
+ 0xe7d34c64a9c85d44, 0x90e40fbeea1d3a4a,
+ 0xb51d13aea4a488dd, 0xe264589a4dcdab14,
+ 0x8d7eb76070a08aec, 0xb0de65388cc8ada8,
+ 0xdd15fe86affad912, 0x8a2dbf142dfcc7ab,
+ 0xacb92ed9397bf996, 0xd7e77a8f87daf7fb,
+ 0x86f0ac99b4e8dafd, 0xa8acd7c0222311bc,
+ 0xd2d80db02aabd62b, 0x83c7088e1aab65db,
+ 0xa4b8cab1a1563f52, 0xcde6fd5e09abcf26,
+ 0x80b05e5ac60b6178, 0xa0dc75f1778e39d6,
+ 0xc913936dd571c84c, 0xfb5878494ace3a5f,
+ 0x9d174b2dcec0e47b, 0xc45d1df942711d9a,
+ 0xf5746577930d6500, 0x9968bf6abbe85f20,
+ 0xbfc2ef456ae276e8, 0xefb3ab16c59b14a2,
+ 0x95d04aee3b80ece5, 0xbb445da9ca61281f,
+ 0xea1575143cf97226, 0x924d692ca61be758,
+ 0xb6e0c377cfa2e12e, 0xe498f455c38b997a,
+ 0x8edf98b59a373fec, 0xb2977ee300c50fe7,
+ 0xdf3d5e9bc0f653e1, 0x8b865b215899f46c,
+ 0xae67f1e9aec07187, 0xda01ee641a708de9,
+ 0x884134fe908658b2, 0xaa51823e34a7eede,
+ 0xd4e5e2cdc1d1ea96, 0x850fadc09923329e,
+ 0xa6539930bf6bff45, 0xcfe87f7cef46ff16,
+ 0x81f14fae158c5f6e, 0xa26da3999aef7749,
+ 0xcb090c8001ab551c, 0xfdcb4fa002162a63,
+ 0x9e9f11c4014dda7e, 0xc646d63501a1511d,
+ 0xf7d88bc24209a565, 0x9ae757596946075f,
+ 0xc1a12d2fc3978937, 0xf209787bb47d6b84,
+ 0x9745eb4d50ce6332, 0xbd176620a501fbff,
+ 0xec5d3fa8ce427aff, 0x93ba47c980e98cdf,
+ 0xb8a8d9bbe123f017, 0xe6d3102ad96cec1d,
+ 0x9043ea1ac7e41392, 0xb454e4a179dd1877,
+ 0xe16a1dc9d8545e94, 0x8ce2529e2734bb1d,
+ 0xb01ae745b101e9e4, 0xdc21a1171d42645d,
+ 0x899504ae72497eba, 0xabfa45da0edbde69,
+ 0xd6f8d7509292d603, 0x865b86925b9bc5c2,
+ 0xa7f26836f282b732, 0xd1ef0244af2364ff,
+ 0x8335616aed761f1f, 0xa402b9c5a8d3a6e7,
+ 0xcd036837130890a1, 0x802221226be55a64,
+ 0xa02aa96b06deb0fd, 0xc83553c5c8965d3d,
+ 0xfa42a8b73abbf48c, 0x9c69a97284b578d7,
+ 0xc38413cf25e2d70d, 0xf46518c2ef5b8cd1,
+ 0x98bf2f79d5993802, 0xbeeefb584aff8603,
+ 0xeeaaba2e5dbf6784, 0x952ab45cfa97a0b2,
+ 0xba756174393d88df, 0xe912b9d1478ceb17,
+ 0x91abb422ccb812ee, 0xb616a12b7fe617aa,
+ 0xe39c49765fdf9d94, 0x8e41ade9fbebc27d,
+ 0xb1d219647ae6b31c, 0xde469fbd99a05fe3,
+ 0x8aec23d680043bee, 0xada72ccc20054ae9,
+ 0xd910f7ff28069da4, 0x87aa9aff79042286,
+ 0xa99541bf57452b28, 0xd3fa922f2d1675f2,
+ 0x847c9b5d7c2e09b7, 0xa59bc234db398c25,
+ 0xcf02b2c21207ef2e, 0x8161afb94b44f57d,
+ 0xa1ba1ba79e1632dc, 0xca28a291859bbf93,
+ 0xfcb2cb35e702af78, 0x9defbf01b061adab,
+ 0xc56baec21c7a1916, 0xf6c69a72a3989f5b,
+ 0x9a3c2087a63f6399, 0xc0cb28a98fcf3c7f,
+ 0xf0fdf2d3f3c30b9f, 0x969eb7c47859e743,
+ 0xbc4665b596706114, 0xeb57ff22fc0c7959,
+ 0x9316ff75dd87cbd8, 0xb7dcbf5354e9bece,
+ 0xe5d3ef282a242e81, 0x8fa475791a569d10,
+ 0xb38d92d760ec4455, 0xe070f78d3927556a,
+ 0x8c469ab843b89562, 0xaf58416654a6babb,
+ 0xdb2e51bfe9d0696a, 0x88fcf317f22241e2,
+ 0xab3c2fddeeaad25a, 0xd60b3bd56a5586f1,
+ 0x85c7056562757456, 0xa738c6bebb12d16c,
+ 0xd106f86e69d785c7, 0x82a45b450226b39c,
+ 0xa34d721642b06084, 0xcc20ce9bd35c78a5,
+ 0xff290242c83396ce, 0x9f79a169bd203e41,
+ 0xc75809c42c684dd1, 0xf92e0c3537826145,
+ 0x9bbcc7a142b17ccb, 0xc2abf989935ddbfe,
+ 0xf356f7ebf83552fe, 0x98165af37b2153de,
+ 0xbe1bf1b059e9a8d6, 0xeda2ee1c7064130c,
+ 0x9485d4d1c63e8be7, 0xb9a74a0637ce2ee1,
+ 0xe8111c87c5c1ba99, 0x910ab1d4db9914a0,
+ 0xb54d5e4a127f59c8, 0xe2a0b5dc971f303a,
+ 0x8da471a9de737e24, 0xb10d8e1456105dad,
+ 0xdd50f1996b947518, 0x8a5296ffe33cc92f,
+ 0xace73cbfdc0bfb7b, 0xd8210befd30efa5a,
+ 0x8714a775e3e95c78, 0xa8d9d1535ce3b396,
+ 0xd31045a8341ca07c, 0x83ea2b892091e44d,
+ 0xa4e4b66b68b65d60, 0xce1de40642e3f4b9,
+ 0x80d2ae83e9ce78f3, 0xa1075a24e4421730,
+ 0xc94930ae1d529cfc, 0xfb9b7cd9a4a7443c,
+ 0x9d412e0806e88aa5, 0xc491798a08a2ad4e,
+ 0xf5b5d7ec8acb58a2, 0x9991a6f3d6bf1765,
+ 0xbff610b0cc6edd3f, 0xeff394dcff8a948e,
+ 0x95f83d0a1fb69cd9, 0xbb764c4ca7a4440f,
+ 0xea53df5fd18d5513, 0x92746b9be2f8552c,
+ 0xb7118682dbb66a77, 0xe4d5e82392a40515,
+ 0x8f05b1163ba6832d, 0xb2c71d5bca9023f8,
+ 0xdf78e4b2bd342cf6, 0x8bab8eefb6409c1a,
+ 0xae9672aba3d0c320, 0xda3c0f568cc4f3e8,
+ 0x8865899617fb1871, 0xaa7eebfb9df9de8d,
+ 0xd51ea6fa85785631, 0x8533285c936b35de,
+ 0xa67ff273b8460356, 0xd01fef10a657842c,
+ 0x8213f56a67f6b29b, 0xa298f2c501f45f42,
+ 0xcb3f2f7642717713, 0xfe0efb53d30dd4d7,
+ 0x9ec95d1463e8a506, 0xc67bb4597ce2ce48,
+ 0xf81aa16fdc1b81da, 0x9b10a4e5e9913128,
+ 0xc1d4ce1f63f57d72, 0xf24a01a73cf2dccf,
+ 0x976e41088617ca01, 0xbd49d14aa79dbc82,
+ 0xec9c459d51852ba2, 0x93e1ab8252f33b45,
+ 0xb8da1662e7b00a17, 0xe7109bfba19c0c9d,
+ 0x906a617d450187e2, 0xb484f9dc9641e9da,
+ 0xe1a63853bbd26451, 0x8d07e33455637eb2,
+ 0xb049dc016abc5e5f, 0xdc5c5301c56b75f7,
+ 0x89b9b3e11b6329ba, 0xac2820d9623bf429,
+ 0xd732290fbacaf133, 0x867f59a9d4bed6c0,
+ 0xa81f301449ee8c70, 0xd226fc195c6a2f8c,
+ 0x83585d8fd9c25db7, 0xa42e74f3d032f525,
+ 0xcd3a1230c43fb26f, 0x80444b5e7aa7cf85,
+ 0xa0555e361951c366, 0xc86ab5c39fa63440,
+ 0xfa856334878fc150, 0x9c935e00d4b9d8d2,
+ 0xc3b8358109e84f07, 0xf4a642e14c6262c8,
+ 0x98e7e9cccfbd7dbd, 0xbf21e44003acdd2c,
+ 0xeeea5d5004981478, 0x95527a5202df0ccb,
+ 0xbaa718e68396cffd, 0xe950df20247c83fd,
+ 0x91d28b7416cdd27e, 0xb6472e511c81471d,
+ 0xe3d8f9e563a198e5, 0x8e679c2f5e44ff8f
+ };
+
+ // A complement to significand_64
+ // complete to a 128-bit significand.
+ // Uses about 5KB but is rarely accessed.
+ static constexpr std::uint64_t significand_128[] = {
+ 0x419ea3bd35385e2d, 0x52064cac828675b9,
+ 0x7343efebd1940993, 0x1014ebe6c5f90bf8,
+ 0xd41a26e077774ef6, 0x8920b098955522b4,
+ 0x55b46e5f5d5535b0, 0xeb2189f734aa831d,
+ 0xa5e9ec7501d523e4, 0x47b233c92125366e,
+ 0x999ec0bb696e840a, 0xc00670ea43ca250d,
+ 0x380406926a5e5728, 0xc605083704f5ecf2,
+ 0xf7864a44c633682e, 0x7ab3ee6afbe0211d,
+ 0x5960ea05bad82964, 0x6fb92487298e33bd,
+ 0xa5d3b6d479f8e056, 0x8f48a4899877186c,
+ 0x331acdabfe94de87, 0x9ff0c08b7f1d0b14,
+ 0x7ecf0ae5ee44dd9, 0xc9e82cd9f69d6150,
+ 0xbe311c083a225cd2, 0x6dbd630a48aaf406,
+ 0x92cbbccdad5b108, 0x25bbf56008c58ea5,
+ 0xaf2af2b80af6f24e, 0x1af5af660db4aee1,
+ 0x50d98d9fc890ed4d, 0xe50ff107bab528a0,
+ 0x1e53ed49a96272c8, 0x25e8e89c13bb0f7a,
+ 0x77b191618c54e9ac, 0xd59df5b9ef6a2417,
+ 0x4b0573286b44ad1d, 0x4ee367f9430aec32,
+ 0x229c41f793cda73f, 0x6b43527578c1110f,
+ 0x830a13896b78aaa9, 0x23cc986bc656d553,
+ 0x2cbfbe86b7ec8aa8, 0x7bf7d71432f3d6a9,
+ 0xdaf5ccd93fb0cc53, 0xd1b3400f8f9cff68,
+ 0x23100809b9c21fa1, 0xabd40a0c2832a78a,
+ 0x16c90c8f323f516c, 0xae3da7d97f6792e3,
+ 0x99cd11cfdf41779c, 0x40405643d711d583,
+ 0x482835ea666b2572, 0xda3243650005eecf,
+ 0x90bed43e40076a82, 0x5a7744a6e804a291,
+ 0x711515d0a205cb36, 0xd5a5b44ca873e03,
+ 0xe858790afe9486c2, 0x626e974dbe39a872,
+ 0xfb0a3d212dc8128f, 0x7ce66634bc9d0b99,
+ 0x1c1fffc1ebc44e80, 0xa327ffb266b56220,
+ 0x4bf1ff9f0062baa8, 0x6f773fc3603db4a9,
+ 0xcb550fb4384d21d3, 0x7e2a53a146606a48,
+ 0x2eda7444cbfc426d, 0xfa911155fefb5308,
+ 0x793555ab7eba27ca, 0x4bc1558b2f3458de,
+ 0x9eb1aaedfb016f16, 0x465e15a979c1cadc,
+ 0xbfacd89ec191ec9, 0xcef980ec671f667b,
+ 0x82b7e12780e7401a, 0xd1b2ecb8b0908810,
+ 0x861fa7e6dcb4aa15, 0x67a791e093e1d49a,
+ 0xe0c8bb2c5c6d24e0, 0x58fae9f773886e18,
+ 0xaf39a475506a899e, 0x6d8406c952429603,
+ 0xc8e5087ba6d33b83, 0xfb1e4a9a90880a64,
+ 0x5cf2eea09a55067f, 0xf42faa48c0ea481e,
+ 0xf13b94daf124da26, 0x76c53d08d6b70858,
+ 0x54768c4b0c64ca6e, 0xa9942f5dcf7dfd09,
+ 0xd3f93b35435d7c4c, 0xc47bc5014a1a6daf,
+ 0x359ab6419ca1091b, 0xc30163d203c94b62,
+ 0x79e0de63425dcf1d, 0x985915fc12f542e4,
+ 0x3e6f5b7b17b2939d, 0xa705992ceecf9c42,
+ 0x50c6ff782a838353, 0xa4f8bf5635246428,
+ 0x871b7795e136be99, 0x28e2557b59846e3f,
+ 0x331aeada2fe589cf, 0x3ff0d2c85def7621,
+ 0xfed077a756b53a9, 0xd3e8495912c62894,
+ 0x64712dd7abbbd95c, 0xbd8d794d96aacfb3,
+ 0xecf0d7a0fc5583a0, 0xf41686c49db57244,
+ 0x311c2875c522ced5, 0x7d633293366b828b,
+ 0xae5dff9c02033197, 0xd9f57f830283fdfc,
+ 0xd072df63c324fd7b, 0x4247cb9e59f71e6d,
+ 0x52d9be85f074e608, 0x67902e276c921f8b,
+ 0xba1cd8a3db53b6, 0x80e8a40eccd228a4,
+ 0x6122cd128006b2cd, 0x796b805720085f81,
+ 0xcbe3303674053bb0, 0xbedbfc4411068a9c,
+ 0xee92fb5515482d44, 0x751bdd152d4d1c4a,
+ 0xd262d45a78a0635d, 0x86fb897116c87c34,
+ 0xd45d35e6ae3d4da0, 0x8974836059cca109,
+ 0x2bd1a438703fc94b, 0x7b6306a34627ddcf,
+ 0x1a3bc84c17b1d542, 0x20caba5f1d9e4a93,
+ 0x547eb47b7282ee9c, 0xe99e619a4f23aa43,
+ 0x6405fa00e2ec94d4, 0xde83bc408dd3dd04,
+ 0x9624ab50b148d445, 0x3badd624dd9b0957,
+ 0xe54ca5d70a80e5d6, 0x5e9fcf4ccd211f4c,
+ 0x7647c3200069671f, 0x29ecd9f40041e073,
+ 0xf468107100525890, 0x7182148d4066eeb4,
+ 0xc6f14cd848405530, 0xb8ada00e5a506a7c,
+ 0xa6d90811f0e4851c, 0x908f4a166d1da663,
+ 0x9a598e4e043287fe, 0x40eff1e1853f29fd,
+ 0xd12bee59e68ef47c, 0x82bb74f8301958ce,
+ 0xe36a52363c1faf01, 0xdc44e6c3cb279ac1,
+ 0x29ab103a5ef8c0b9, 0x7415d448f6b6f0e7,
+ 0x111b495b3464ad21, 0xcab10dd900beec34,
+ 0x3d5d514f40eea742, 0xcb4a5a3112a5112,
+ 0x47f0e785eaba72ab, 0x59ed216765690f56,
+ 0x306869c13ec3532c, 0x1e414218c73a13fb,
+ 0xe5d1929ef90898fa, 0xdf45f746b74abf39,
+ 0x6b8bba8c328eb783, 0x66ea92f3f326564,
+ 0xc80a537b0efefebd, 0xbd06742ce95f5f36,
+ 0x2c48113823b73704, 0xf75a15862ca504c5,
+ 0x9a984d73dbe722fb, 0xc13e60d0d2e0ebba,
+ 0x318df905079926a8, 0xfdf17746497f7052,
+ 0xfeb6ea8bedefa633, 0xfe64a52ee96b8fc0,
+ 0x3dfdce7aa3c673b0, 0x6bea10ca65c084e,
+ 0x486e494fcff30a62, 0x5a89dba3c3efccfa,
+ 0xf89629465a75e01c, 0xf6bbb397f1135823,
+ 0x746aa07ded582e2c, 0xa8c2a44eb4571cdc,
+ 0x92f34d62616ce413, 0x77b020baf9c81d17,
+ 0xace1474dc1d122e, 0xd819992132456ba,
+ 0x10e1fff697ed6c69, 0xca8d3ffa1ef463c1,
+ 0xbd308ff8a6b17cb2, 0xac7cb3f6d05ddbde,
+ 0x6bcdf07a423aa96b, 0x86c16c98d2c953c6,
+ 0xe871c7bf077ba8b7, 0x11471cd764ad4972,
+ 0xd598e40d3dd89bcf, 0x4aff1d108d4ec2c3,
+ 0xcedf722a585139ba, 0xc2974eb4ee658828,
+ 0x733d226229feea32, 0x806357d5a3f525f,
+ 0xca07c2dcb0cf26f7, 0xfc89b393dd02f0b5,
+ 0xbbac2078d443ace2, 0xd54b944b84aa4c0d,
+ 0xa9e795e65d4df11, 0x4d4617b5ff4a16d5,
+ 0x504bced1bf8e4e45, 0xe45ec2862f71e1d6,
+ 0x5d767327bb4e5a4c, 0x3a6a07f8d510f86f,
+ 0x890489f70a55368b, 0x2b45ac74ccea842e,
+ 0x3b0b8bc90012929d, 0x9ce6ebb40173744,
+ 0xcc420a6a101d0515, 0x9fa946824a12232d,
+ 0x47939822dc96abf9, 0x59787e2b93bc56f7,
+ 0x57eb4edb3c55b65a, 0xede622920b6b23f1,
+ 0xe95fab368e45eced, 0x11dbcb0218ebb414,
+ 0xd652bdc29f26a119, 0x4be76d3346f0495f,
+ 0x6f70a4400c562ddb, 0xcb4ccd500f6bb952,
+ 0x7e2000a41346a7a7, 0x8ed400668c0c28c8,
+ 0x728900802f0f32fa, 0x4f2b40a03ad2ffb9,
+ 0xe2f610c84987bfa8, 0xdd9ca7d2df4d7c9,
+ 0x91503d1c79720dbb, 0x75a44c6397ce912a,
+ 0xc986afbe3ee11aba, 0xfbe85badce996168,
+ 0xfae27299423fb9c3, 0xdccd879fc967d41a,
+ 0x5400e987bbc1c920, 0x290123e9aab23b68,
+ 0xf9a0b6720aaf6521, 0xf808e40e8d5b3e69,
+ 0xb60b1d1230b20e04, 0xb1c6f22b5e6f48c2,
+ 0x1e38aeb6360b1af3, 0x25c6da63c38de1b0,
+ 0x579c487e5a38ad0e, 0x2d835a9df0c6d851,
+ 0xf8e431456cf88e65, 0x1b8e9ecb641b58ff,
+ 0xe272467e3d222f3f, 0x5b0ed81dcc6abb0f,
+ 0x98e947129fc2b4e9, 0x3f2398d747b36224,
+ 0x8eec7f0d19a03aad, 0x1953cf68300424ac,
+ 0x5fa8c3423c052dd7, 0x3792f412cb06794d,
+ 0xe2bbd88bbee40bd0, 0x5b6aceaeae9d0ec4,
+ 0xf245825a5a445275, 0xeed6e2f0f0d56712,
+ 0x55464dd69685606b, 0xaa97e14c3c26b886,
+ 0xd53dd99f4b3066a8, 0xe546a8038efe4029,
+ 0xde98520472bdd033, 0x963e66858f6d4440,
+ 0xdde7001379a44aa8, 0x5560c018580d5d52,
+ 0xaab8f01e6e10b4a6, 0xcab3961304ca70e8,
+ 0x3d607b97c5fd0d22, 0x8cb89a7db77c506a,
+ 0x77f3608e92adb242, 0x55f038b237591ed3,
+ 0x6b6c46dec52f6688, 0x2323ac4b3b3da015,
+ 0xabec975e0a0d081a, 0x96e7bd358c904a21,
+ 0x7e50d64177da2e54, 0xdde50bd1d5d0b9e9,
+ 0x955e4ec64b44e864, 0xbd5af13bef0b113e,
+ 0xecb1ad8aeacdd58e, 0x67de18eda5814af2,
+ 0x80eacf948770ced7, 0xa1258379a94d028d,
+ 0x96ee45813a04330, 0x8bca9d6e188853fc,
+ 0x775ea264cf55347d, 0x95364afe032a819d,
+ 0x3a83ddbd83f52204, 0xc4926a9672793542,
+ 0x75b7053c0f178293, 0x5324c68b12dd6338,
+ 0xd3f6fc16ebca5e03, 0x88f4bb1ca6bcf584,
+ 0x2b31e9e3d06c32e5, 0x3aff322e62439fcf,
+ 0x9befeb9fad487c2, 0x4c2ebe687989a9b3,
+ 0xf9d37014bf60a10, 0x538484c19ef38c94,
+ 0x2865a5f206b06fb9, 0xf93f87b7442e45d3,
+ 0xf78f69a51539d748, 0xb573440e5a884d1b,
+ 0x31680a88f8953030, 0xfdc20d2b36ba7c3d,
+ 0x3d32907604691b4c, 0xa63f9a49c2c1b10f,
+ 0xfcf80dc33721d53, 0xd3c36113404ea4a8,
+ 0x645a1cac083126e9, 0x3d70a3d70a3d70a3,
+ 0xcccccccccccccccc, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x4000000000000000,
+ 0x5000000000000000, 0xa400000000000000,
+ 0x4d00000000000000, 0xf020000000000000,
+ 0x6c28000000000000, 0xc732000000000000,
+ 0x3c7f400000000000, 0x4b9f100000000000,
+ 0x1e86d40000000000, 0x1314448000000000,
+ 0x17d955a000000000, 0x5dcfab0800000000,
+ 0x5aa1cae500000000, 0xf14a3d9e40000000,
+ 0x6d9ccd05d0000000, 0xe4820023a2000000,
+ 0xdda2802c8a800000, 0xd50b2037ad200000,
+ 0x4526f422cc340000, 0x9670b12b7f410000,
+ 0x3c0cdd765f114000, 0xa5880a69fb6ac800,
+ 0x8eea0d047a457a00, 0x72a4904598d6d880,
+ 0x47a6da2b7f864750, 0x999090b65f67d924,
+ 0xfff4b4e3f741cf6d, 0xbff8f10e7a8921a4,
+ 0xaff72d52192b6a0d, 0x9bf4f8a69f764490,
+ 0x2f236d04753d5b4, 0x1d762422c946590,
+ 0x424d3ad2b7b97ef5, 0xd2e0898765a7deb2,
+ 0x63cc55f49f88eb2f, 0x3cbf6b71c76b25fb,
+ 0x8bef464e3945ef7a, 0x97758bf0e3cbb5ac,
+ 0x3d52eeed1cbea317, 0x4ca7aaa863ee4bdd,
+ 0x8fe8caa93e74ef6a, 0xb3e2fd538e122b44,
+ 0x60dbbca87196b616, 0xbc8955e946fe31cd,
+ 0x6babab6398bdbe41, 0xc696963c7eed2dd1,
+ 0xfc1e1de5cf543ca2, 0x3b25a55f43294bcb,
+ 0x49ef0eb713f39ebe, 0x6e3569326c784337,
+ 0x49c2c37f07965404, 0xdc33745ec97be906,
+ 0x69a028bb3ded71a3, 0xc40832ea0d68ce0c,
+ 0xf50a3fa490c30190, 0x792667c6da79e0fa,
+ 0x577001b891185938, 0xed4c0226b55e6f86,
+ 0x544f8158315b05b4, 0x696361ae3db1c721,
+ 0x3bc3a19cd1e38e9, 0x4ab48a04065c723,
+ 0x62eb0d64283f9c76, 0x3ba5d0bd324f8394,
+ 0xca8f44ec7ee36479, 0x7e998b13cf4e1ecb,
+ 0x9e3fedd8c321a67e, 0xc5cfe94ef3ea101e,
+ 0xbba1f1d158724a12, 0x2a8a6e45ae8edc97,
+ 0xf52d09d71a3293bd, 0x593c2626705f9c56,
+ 0x6f8b2fb00c77836c, 0xb6dfb9c0f956447,
+ 0x4724bd4189bd5eac, 0x58edec91ec2cb657,
+ 0x2f2967b66737e3ed, 0xbd79e0d20082ee74,
+ 0xecd8590680a3aa11, 0xe80e6f4820cc9495,
+ 0x3109058d147fdcdd, 0xbd4b46f0599fd415,
+ 0x6c9e18ac7007c91a, 0x3e2cf6bc604ddb0,
+ 0x84db8346b786151c, 0xe612641865679a63,
+ 0x4fcb7e8f3f60c07e, 0xe3be5e330f38f09d,
+ 0x5cadf5bfd3072cc5, 0x73d9732fc7c8f7f6,
+ 0x2867e7fddcdd9afa, 0xb281e1fd541501b8,
+ 0x1f225a7ca91a4226, 0x3375788de9b06958,
+ 0x52d6b1641c83ae, 0xc0678c5dbd23a49a,
+ 0xf840b7ba963646e0, 0xb650e5a93bc3d898,
+ 0xa3e51f138ab4cebe, 0xc66f336c36b10137,
+ 0xb80b0047445d4184, 0xa60dc059157491e5,
+ 0x87c89837ad68db2f, 0x29babe4598c311fb,
+ 0xf4296dd6fef3d67a, 0x1899e4a65f58660c,
+ 0x5ec05dcff72e7f8f, 0x76707543f4fa1f73,
+ 0x6a06494a791c53a8, 0x487db9d17636892,
+ 0x45a9d2845d3c42b6, 0xb8a2392ba45a9b2,
+ 0x8e6cac7768d7141e, 0x3207d795430cd926,
+ 0x7f44e6bd49e807b8, 0x5f16206c9c6209a6,
+ 0x36dba887c37a8c0f, 0xc2494954da2c9789,
+ 0xf2db9baa10b7bd6c, 0x6f92829494e5acc7,
+ 0xcb772339ba1f17f9, 0xff2a760414536efb,
+ 0xfef5138519684aba, 0x7eb258665fc25d69,
+ 0xef2f773ffbd97a61, 0xaafb550ffacfd8fa,
+ 0x95ba2a53f983cf38, 0xdd945a747bf26183,
+ 0x94f971119aeef9e4, 0x7a37cd5601aab85d,
+ 0xac62e055c10ab33a, 0x577b986b314d6009,
+ 0xed5a7e85fda0b80b, 0x14588f13be847307,
+ 0x596eb2d8ae258fc8, 0x6fca5f8ed9aef3bb,
+ 0x25de7bb9480d5854, 0xaf561aa79a10ae6a,
+ 0x1b2ba1518094da04, 0x90fb44d2f05d0842,
+ 0x353a1607ac744a53, 0x42889b8997915ce8,
+ 0x69956135febada11, 0x43fab9837e699095,
+ 0x94f967e45e03f4bb, 0x1d1be0eebac278f5,
+ 0x6462d92a69731732, 0x7d7b8f7503cfdcfe,
+ 0x5cda735244c3d43e, 0x3a0888136afa64a7,
+ 0x88aaa1845b8fdd0, 0x8aad549e57273d45,
+ 0x36ac54e2f678864b, 0x84576a1bb416a7dd,
+ 0x656d44a2a11c51d5, 0x9f644ae5a4b1b325,
+ 0x873d5d9f0dde1fee, 0xa90cb506d155a7ea,
+ 0x9a7f12442d588f2, 0xc11ed6d538aeb2f,
+ 0x8f1668c8a86da5fa, 0xf96e017d694487bc,
+ 0x37c981dcc395a9ac, 0x85bbe253f47b1417,
+ 0x93956d7478ccec8e, 0x387ac8d1970027b2,
+ 0x6997b05fcc0319e, 0x441fece3bdf81f03,
+ 0xd527e81cad7626c3, 0x8a71e223d8d3b074,
+ 0xf6872d5667844e49, 0xb428f8ac016561db,
+ 0xe13336d701beba52, 0xecc0024661173473,
+ 0x27f002d7f95d0190, 0x31ec038df7b441f4,
+ 0x7e67047175a15271, 0xf0062c6e984d386,
+ 0x52c07b78a3e60868, 0xa7709a56ccdf8a82,
+ 0x88a66076400bb691, 0x6acff893d00ea435,
+ 0x583f6b8c4124d43, 0xc3727a337a8b704a,
+ 0x744f18c0592e4c5c, 0x1162def06f79df73,
+ 0x8addcb5645ac2ba8, 0x6d953e2bd7173692,
+ 0xc8fa8db6ccdd0437, 0x1d9c9892400a22a2,
+ 0x2503beb6d00cab4b, 0x2e44ae64840fd61d,
+ 0x5ceaecfed289e5d2, 0x7425a83e872c5f47,
+ 0xd12f124e28f77719, 0x82bd6b70d99aaa6f,
+ 0x636cc64d1001550b, 0x3c47f7e05401aa4e,
+ 0x65acfaec34810a71, 0x7f1839a741a14d0d,
+ 0x1ede48111209a050, 0x934aed0aab460432,
+ 0xf81da84d5617853f, 0x36251260ab9d668e,
+ 0xc1d72b7c6b426019, 0xb24cf65b8612f81f,
+ 0xdee033f26797b627, 0x169840ef017da3b1,
+ 0x8e1f289560ee864e, 0xf1a6f2bab92a27e2,
+ 0xae10af696774b1db, 0xacca6da1e0a8ef29,
+ 0x17fd090a58d32af3, 0xddfc4b4cef07f5b0,
+ 0x4abdaf101564f98e, 0x9d6d1ad41abe37f1,
+ 0x84c86189216dc5ed, 0x32fd3cf5b4e49bb4,
+ 0x3fbc8c33221dc2a1, 0xfabaf3feaa5334a,
+ 0x29cb4d87f2a7400e, 0x743e20e9ef511012,
+ 0x914da9246b255416, 0x1ad089b6c2f7548e,
+ 0xa184ac2473b529b1, 0xc9e5d72d90a2741e,
+ 0x7e2fa67c7a658892, 0xddbb901b98feeab7,
+ 0x552a74227f3ea565, 0xd53a88958f87275f,
+ 0x8a892abaf368f137, 0x2d2b7569b0432d85,
+ 0x9c3b29620e29fc73, 0x8349f3ba91b47b8f,
+ 0x241c70a936219a73, 0xed238cd383aa0110,
+ 0xf4363804324a40aa, 0xb143c6053edcd0d5,
+ 0xdd94b7868e94050a, 0xca7cf2b4191c8326,
+ 0xfd1c2f611f63a3f0, 0xbc633b39673c8cec,
+ 0xd5be0503e085d813, 0x4b2d8644d8a74e18,
+ 0xddf8e7d60ed1219e, 0xcabb90e5c942b503,
+ 0x3d6a751f3b936243, 0xcc512670a783ad4,
+ 0x27fb2b80668b24c5, 0xb1f9f660802dedf6,
+ 0x5e7873f8a0396973, 0xdb0b487b6423e1e8,
+ 0x91ce1a9a3d2cda62, 0x7641a140cc7810fb,
+ 0xa9e904c87fcb0a9d, 0x546345fa9fbdcd44,
+ 0xa97c177947ad4095, 0x49ed8eabcccc485d,
+ 0x5c68f256bfff5a74, 0x73832eec6fff3111,
+ 0xc831fd53c5ff7eab, 0xba3e7ca8b77f5e55,
+ 0x28ce1bd2e55f35eb, 0x7980d163cf5b81b3,
+ 0xd7e105bcc332621f, 0x8dd9472bf3fefaa7,
+ 0xb14f98f6f0feb951, 0x6ed1bf9a569f33d3,
+ 0xa862f80ec4700c8, 0xcd27bb612758c0fa,
+ 0x8038d51cb897789c, 0xe0470a63e6bd56c3,
+ 0x1858ccfce06cac74, 0xf37801e0c43ebc8,
+ 0xd30560258f54e6ba, 0x47c6b82ef32a2069,
+ 0x4cdc331d57fa5441, 0xe0133fe4adf8e952,
+ 0x58180fddd97723a6, 0x570f09eaa7ea7648
+ };
+
+};
+
+#if defined(BOOST_NO_CXX17_INLINE_VARIABLES) && (!defined(BOOST_MSVC) || BOOST_MSVC != 1900)
+
+template <bool b> constexpr std::uint64_t significand_template<b>::significand_64[];
+template <bool b> constexpr std::uint64_t significand_template<b>::significand_128[];
+
+#endif
+
+#if (!defined(BOOST_MSVC) || BOOST_MSVC != 1900)
+
+using significands_table = significand_template<true>;
+
+#endif
+
+}}} // Namespaces
+
+#endif // BOOST_CHARCONV_DETAIL_SIGNIFICAND_TABLES_HPP
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/to_chars_integer_impl.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/to_chars_integer_impl.hpp
new file mode 100644
index 00000000000..1ef54a2f061
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/to_chars_integer_impl.hpp
@@ -0,0 +1,459 @@
+// Copyright 2020-2023 Junekey Jeon
+// Copyright 2022 Peter Dimov
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_CHARCONV_DETAIL_TO_CHARS_INTEGER_IMPL_HPP
+#define BOOST_CHARCONV_DETAIL_TO_CHARS_INTEGER_IMPL_HPP
+
+#include <boost/charconv/detail/config.hpp>
+#include <boost/charconv/detail/memcpy.hpp>
+#include <boost/charconv/detail/to_chars_result.hpp>
+#include <boost/charconv/detail/integer_search_trees.hpp>
+#include <boost/charconv/detail/emulated128.hpp>
+#include <boost/charconv/detail/apply_sign.hpp>
+#include <limits>
+#include <system_error>
+#include <type_traits>
+#include <array>
+#include <limits>
+#include <utility>
+#include <cstring>
+#include <cstdio>
+#include <cerrno>
+#include <cstdint>
+#include <climits>
+#include <cmath>
+
+namespace boost { namespace charconv { namespace detail {
+
+
+static constexpr char radix_table[] = {
+ '0', '0', '0', '1', '0', '2', '0', '3', '0', '4',
+ '0', '5', '0', '6', '0', '7', '0', '8', '0', '9',
+ '1', '0', '1', '1', '1', '2', '1', '3', '1', '4',
+ '1', '5', '1', '6', '1', '7', '1', '8', '1', '9',
+ '2', '0', '2', '1', '2', '2', '2', '3', '2', '4',
+ '2', '5', '2', '6', '2', '7', '2', '8', '2', '9',
+ '3', '0', '3', '1', '3', '2', '3', '3', '3', '4',
+ '3', '5', '3', '6', '3', '7', '3', '8', '3', '9',
+ '4', '0', '4', '1', '4', '2', '4', '3', '4', '4',
+ '4', '5', '4', '6', '4', '7', '4', '8', '4', '9',
+ '5', '0', '5', '1', '5', '2', '5', '3', '5', '4',
+ '5', '5', '5', '6', '5', '7', '5', '8', '5', '9',
+ '6', '0', '6', '1', '6', '2', '6', '3', '6', '4',
+ '6', '5', '6', '6', '6', '7', '6', '8', '6', '9',
+ '7', '0', '7', '1', '7', '2', '7', '3', '7', '4',
+ '7', '5', '7', '6', '7', '7', '7', '8', '7', '9',
+ '8', '0', '8', '1', '8', '2', '8', '3', '8', '4',
+ '8', '5', '8', '6', '8', '7', '8', '8', '8', '9',
+ '9', '0', '9', '1', '9', '2', '9', '3', '9', '4',
+ '9', '5', '9', '6', '9', '7', '9', '8', '9', '9'
+};
+
+static constexpr char digit_table[] = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
+ 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
+ 'u', 'v', 'w', 'x', 'y', 'z'
+};
+
+// See: https://jk-jeon.github.io/posts/2022/02/jeaiii-algorithm/
+// https://arxiv.org/abs/2101.11408
+BOOST_CHARCONV_CONSTEXPR char* decompose32(std::uint32_t value, char* buffer) noexcept
+{
+ constexpr auto mask = (std::uint64_t(1) << 57) - 1;
+ auto y = value * std::uint64_t(1441151881);
+
+ for (std::size_t i {}; i < 10; i += 2)
+ {
+ boost::charconv::detail::memcpy(buffer + i, radix_table + static_cast<std::size_t>(y >> 57) * 2, 2);
+ y &= mask;
+ y *= 100;
+ }
+
+ return buffer + 10;
+}
+
+#ifdef BOOST_MSVC
+# pragma warning(push)
+# pragma warning(disable: 4127 4146)
+#endif
+
+template <typename Integer>
+BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_integer_impl(char* first, char* last, Integer value) noexcept
+{
+ using Unsigned_Integer = typename std::make_unsigned<Integer>::type;
+ Unsigned_Integer unsigned_value {};
+
+ char buffer[10] {};
+ int converted_value_digits {};
+ bool is_negative = false;
+
+ if (first > last)
+ {
+ return {last, std::errc::invalid_argument};
+ }
+
+ // Strip the sign from the value and apply at the end after parsing if the type is signed
+ BOOST_IF_CONSTEXPR (std::is_signed<Integer>::value)
+ {
+ if (value < 0)
+ {
+ is_negative = true;
+ unsigned_value = apply_sign(value);
+ }
+ else
+ {
+ unsigned_value = static_cast<Unsigned_Integer>(value);
+ }
+ }
+ else
+ {
+ unsigned_value = static_cast<Unsigned_Integer>(value);
+ }
+
+ const std::ptrdiff_t user_buffer_size = last - first - static_cast<std::ptrdiff_t>(is_negative);
+
+ // If the type is less than 32 bits we can use this without change
+ // If the type is greater than 32 bits we use a binary search tree to figure out how many digits
+ // are present and then decompose the value into two (or more) std::uint32_t of known length so that we
+ // don't have the issue of removing leading zeros from the least significant digits
+
+ // Yields: warning C4127: conditional expression is constant because first half of the expression is constant,
+ // but we need to short circuit to avoid UB on the second half
+ if (std::numeric_limits<Integer>::digits <= std::numeric_limits<std::uint32_t>::digits ||
+ unsigned_value <= static_cast<Unsigned_Integer>((std::numeric_limits<std::uint32_t>::max)()))
+ {
+ const auto converted_value = static_cast<std::uint32_t>(unsigned_value);
+ converted_value_digits = num_digits(converted_value);
+
+ if (converted_value_digits > user_buffer_size)
+ {
+ return {last, std::errc::value_too_large};
+ }
+
+ decompose32(converted_value, buffer);
+
+ if (is_negative)
+ {
+ *first++ = '-';
+ }
+
+ boost::charconv::detail::memcpy(first, buffer + (sizeof(buffer) - static_cast<unsigned>(converted_value_digits)),
+ static_cast<std::size_t>(converted_value_digits));
+ }
+ else if (std::numeric_limits<Integer>::digits <= std::numeric_limits<std::uint64_t>::digits ||
+ static_cast<std::uint64_t>(unsigned_value) <= (std::numeric_limits<std::uint64_t>::max)())
+ {
+ auto converted_value = static_cast<std::uint64_t>(unsigned_value);
+ converted_value_digits = num_digits(converted_value);
+
+ if (converted_value_digits > user_buffer_size)
+ {
+ return {last, std::errc::value_too_large};
+ }
+
+ if (is_negative)
+ {
+ *first++ = '-';
+ }
+
+ // Only store 9 digits in each to avoid overflow
+ if (num_digits(converted_value) <= 18)
+ {
+ const auto x = static_cast<std::uint32_t>(converted_value / UINT64_C(1000000000));
+ const auto y = static_cast<std::uint32_t>(converted_value % UINT64_C(1000000000));
+ const int first_value_chars = num_digits(x);
+
+ decompose32(x, buffer);
+ boost::charconv::detail::memcpy(first, buffer + (sizeof(buffer) - static_cast<unsigned>(first_value_chars)),
+ static_cast<std::size_t>(first_value_chars));
+
+ decompose32(y, buffer);
+ boost::charconv::detail::memcpy(first + first_value_chars, buffer + 1, sizeof(buffer) - 1);
+ }
+ else
+ {
+ const auto x = static_cast<std::uint32_t>(converted_value / UINT64_C(100000000000));
+ converted_value -= x * UINT64_C(100000000000);
+ const auto y = static_cast<std::uint32_t>(converted_value / UINT64_C(100));
+ const auto z = static_cast<std::uint32_t>(converted_value % UINT64_C(100));
+
+ if (converted_value_digits == 19)
+ {
+ decompose32(x, buffer);
+ boost::charconv::detail::memcpy(first, buffer + 2, sizeof(buffer) - 2);
+
+ decompose32(y, buffer);
+ boost::charconv::detail::memcpy(first + 8, buffer + 1, sizeof(buffer) - 1);
+
+ // Always prints 2 digits last
+ boost::charconv::detail::memcpy(first + 17, radix_table + z * 2, 2);
+ }
+ else // 20
+ {
+ decompose32(x, buffer);
+ boost::charconv::detail::memcpy(first, buffer + 1, sizeof(buffer) - 1);
+
+ decompose32(y, buffer);
+ boost::charconv::detail::memcpy(first + 9, buffer + 1, sizeof(buffer) - 1);
+
+ // Always prints 2 digits last
+ boost::charconv::detail::memcpy(first + 18, radix_table + z * 2, 2);
+ }
+ }
+ }
+
+ return {first + converted_value_digits, std::errc()};
+}
+
+// Prior to GCC 10.3 std::numeric_limits was not specialized for __int128 which breaks the above control flow
+// Here we find if the 128-bit type will fit into a 64-bit type and use the above, or we use string manipulation
+// to extract the digits
+//
+// See: https://quuxplusone.github.io/blog/2019/02/28/is-int128-integral/
+template <typename Integer>
+BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_128integer_impl(char* first, char* last, Integer value) noexcept
+{
+ #ifdef BOOST_CHARCONV_HAS_INT128
+ using Unsigned_Integer = boost::uint128_type;
+ #else
+ using Unsigned_Integer = uint128;
+ #endif
+
+ Unsigned_Integer unsigned_value {};
+
+ const std::ptrdiff_t user_buffer_size = last - first;
+ BOOST_ATTRIBUTE_UNUSED bool is_negative = false;
+
+ if (first > last)
+ {
+ return {last, std::errc::invalid_argument};
+ }
+
+ // Strip the sign from the value and apply at the end after parsing if the type is signed
+ #ifdef BOOST_CHARCONV_HAS_INT128
+ BOOST_IF_CONSTEXPR (std::is_same<boost::int128_type, Integer>::value)
+ {
+ if (value < 0)
+ {
+ is_negative = true;
+ unsigned_value = -(static_cast<Unsigned_Integer>(value));
+ }
+ else
+ {
+ unsigned_value = static_cast<Unsigned_Integer>(value);
+ }
+ }
+ else
+ #endif
+ {
+ unsigned_value = static_cast<Unsigned_Integer>(value);
+ }
+
+ auto converted_value = static_cast<Unsigned_Integer>(unsigned_value);
+
+ const int converted_value_digits = num_digits(converted_value);
+
+ if (converted_value_digits > user_buffer_size)
+ {
+ return {last, std::errc::value_too_large};
+ }
+
+ if (is_negative)
+ {
+ *first++ = '-';
+ }
+
+ // If the value fits into 64 bits use the other method of processing
+ if (converted_value < (std::numeric_limits<std::uint64_t>::max)())
+ {
+ return to_chars_integer_impl(first, last, static_cast<std::uint64_t>(value));
+ }
+
+ constexpr std::uint32_t ten_9 = UINT32_C(1000000000);
+ char buffer[5][10] {};
+ int num_chars[5] {};
+ int i = 0;
+
+ while (converted_value != 0)
+ {
+ auto digits = static_cast<std::uint32_t>(converted_value % ten_9);
+ num_chars[i] = num_digits(digits);
+ decompose32(digits, buffer[i]); // Always returns 10 digits (to include leading 0s) which we want
+ converted_value = (converted_value - digits) / ten_9;
+ ++i;
+ }
+
+ --i;
+ auto offset = static_cast<std::size_t>(num_chars[i]);
+ boost::charconv::detail::memcpy(first, buffer[i] + 10 - offset, offset);
+
+ while (i > 0)
+ {
+ --i;
+ boost::charconv::detail::memcpy(first + offset, buffer[i] + 1, 9);
+ offset += 9;
+ }
+
+ return {first + converted_value_digits, std::errc()};
+}
+
+// Conversion warning from shift operators with unsigned char
+#if defined(__GNUC__) && __GNUC__ >= 5
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wconversion"
+#elif defined(__clang__)
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wconversion"
+#endif
+
+// All other bases
+// Use a simple lookup table to put together the Integer in character form
+template <typename Integer, typename Unsigned_Integer>
+BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_integer_impl(char* first, char* last, Integer value, int base) noexcept
+{
+ if (!((first <= last) && (base >= 2 && base <= 36)))
+ {
+ return {last, std::errc::invalid_argument};
+ }
+
+ if (value == 0)
+ {
+ *first++ = '0';
+ return {first, std::errc()};
+ }
+
+ Unsigned_Integer unsigned_value {};
+ const auto unsigned_base = static_cast<Unsigned_Integer>(base);
+
+ BOOST_IF_CONSTEXPR (std::is_signed<Integer>::value)
+ {
+ if (value < 0)
+ {
+ *first++ = '-';
+ unsigned_value = static_cast<Unsigned_Integer>(detail::apply_sign(value));
+ }
+ else
+ {
+ unsigned_value = static_cast<Unsigned_Integer>(value);
+ }
+ }
+ else
+ {
+ unsigned_value = static_cast<Unsigned_Integer>(value);
+ }
+
+ const std::ptrdiff_t output_length = last - first;
+
+ constexpr Unsigned_Integer zero = 48U; // Char for '0'
+ constexpr auto buffer_size = sizeof(Unsigned_Integer) * CHAR_BIT;
+ char buffer[buffer_size] {};
+ const char* buffer_end = buffer + buffer_size;
+ char* end = buffer + buffer_size - 1;
+
+ // Work from LSB to MSB
+ switch (base)
+ {
+ case 2:
+ while (unsigned_value != 0)
+ {
+ *end-- = static_cast<char>(zero + (unsigned_value & 1U)); // 1<<1 - 1
+ unsigned_value >>= static_cast<Unsigned_Integer>(1);
+ }
+ break;
+
+ case 4:
+ while (unsigned_value != 0)
+ {
+ *end-- = static_cast<char>(zero + (unsigned_value & 3U)); // 1<<2 - 1
+ unsigned_value >>= static_cast<Unsigned_Integer>(2);
+ }
+ break;
+
+ case 8:
+ while (unsigned_value != 0)
+ {
+ *end-- = static_cast<char>(zero + (unsigned_value & 7U)); // 1<<3 - 1
+ unsigned_value >>= static_cast<Unsigned_Integer>(3);
+ }
+ break;
+
+ case 16:
+ while (unsigned_value != 0)
+ {
+ *end-- = digit_table[unsigned_value & 15U]; // 1<<4 - 1
+ unsigned_value >>= static_cast<Unsigned_Integer>(4);
+ }
+ break;
+
+ case 32:
+ while (unsigned_value != 0)
+ {
+ *end-- = digit_table[unsigned_value & 31U]; // 1<<5 - 1
+ unsigned_value >>= static_cast<Unsigned_Integer>(5);
+ }
+ break;
+
+ default:
+ while (unsigned_value != 0)
+ {
+ *end-- = digit_table[unsigned_value % unsigned_base];
+ unsigned_value /= unsigned_base;
+ }
+ break;
+ }
+
+ const std::ptrdiff_t num_chars = buffer_end - end - 1;
+
+ if (num_chars > output_length)
+ {
+ return {last, std::errc::value_too_large};
+ }
+
+ boost::charconv::detail::memcpy(first, buffer + (buffer_size - static_cast<unsigned long>(num_chars)),
+ static_cast<std::size_t>(num_chars));
+
+ return {first + num_chars, std::errc()};
+}
+
+#if defined(__GNUC__) && __GNUC__ >= 5
+# pragma GCC diagnostic pop
+#elif defined(__clang__)
+# pragma clang diagnostic pop
+#endif
+
+#ifdef BOOST_MSVC
+# pragma warning(pop)
+#endif
+
+template <typename Integer>
+BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_int(char* first, char* last, Integer value, int base = 10) noexcept
+{
+ using Unsigned_Integer = typename std::make_unsigned<Integer>::type;
+ if (base == 10)
+ {
+ return to_chars_integer_impl(first, last, value);
+ }
+
+ return to_chars_integer_impl<Integer, Unsigned_Integer>(first, last, value, base);
+}
+
+#ifdef BOOST_CHARCONV_HAS_INT128
+template <typename Integer>
+BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars128(char* first, char* last, Integer value, int base = 10) noexcept
+{
+ if (base == 10)
+ {
+ return to_chars_128integer_impl(first, last, value);
+ }
+
+ return to_chars_integer_impl<Integer, boost::uint128_type>(first, last, value, base);
+}
+#endif
+
+}}} // Namespaces
+
+#endif //BOOST_CHARCONV_DETAIL_TO_CHARS_INTEGER_IMPL_HPP
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/to_chars_result.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/to_chars_result.hpp
new file mode 100644
index 00000000000..e564fe6cd7b
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/to_chars_result.hpp
@@ -0,0 +1,34 @@
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_CHARCONV_DETAIL_TO_CHARS_RESULT_HPP
+#define BOOST_CHARCONV_DETAIL_TO_CHARS_RESULT_HPP
+
+#include <system_error>
+
+// 22.13.2, Primitive numerical output conversion
+
+namespace boost { namespace charconv {
+
+struct to_chars_result
+{
+ char *ptr;
+ std::errc ec;
+
+ constexpr friend bool operator==(const to_chars_result &lhs, const to_chars_result &rhs) noexcept
+ {
+ return lhs.ptr == rhs.ptr && lhs.ec == rhs.ec;
+ }
+
+ constexpr friend bool operator!=(const to_chars_result &lhs, const to_chars_result &rhs) noexcept
+ {
+ return !(lhs == rhs);
+ }
+
+ constexpr explicit operator bool() const noexcept { return ec == std::errc{}; }
+};
+
+}} // Namespaces
+
+#endif //BOOST_CHARCONV_DETAIL_TO_CHARS_RESULT_HPP
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/detail/type_traits.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/detail/type_traits.hpp
new file mode 100644
index 00000000000..4160555162d
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/detail/type_traits.hpp
@@ -0,0 +1,67 @@
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_CHARCONV_DETAIL_TYPE_TRAITS_HPP
+#define BOOST_CHARCONV_DETAIL_TYPE_TRAITS_HPP
+
+#include <boost/charconv/detail/config.hpp>
+#include <type_traits>
+
+namespace boost { namespace charconv { namespace detail {
+
+template <typename T>
+struct is_signed { static constexpr bool value = std::is_signed<T>::value; };
+
+#ifdef BOOST_CHARCONV_HAS_INT128
+
+template <>
+struct is_signed<boost::int128_type> { static constexpr bool value = true; };
+
+template <>
+struct is_signed<boost::uint128_type> { static constexpr bool value = false; };
+
+#endif
+
+#if defined(BOOST_NO_CXX17_INLINE_VARIABLES) && (!defined(BOOST_MSVC) || BOOST_MSVC != 1900)
+
+template <typename T>
+constexpr bool is_signed<T>::value;
+
+#endif
+
+template <typename T>
+struct make_unsigned { using type = typename std::make_unsigned<T>::type; };
+
+template <>
+struct make_unsigned<uint128> { using type = uint128; };
+
+#ifdef BOOST_CHARCONV_HAS_INT128
+
+template <>
+struct make_unsigned<boost::int128_type> { using type = boost::uint128_type; };
+
+template <>
+struct make_unsigned<boost::uint128_type> { using type = boost::uint128_type; };
+
+#endif
+
+template <typename T>
+using make_unsigned_t = typename make_unsigned<T>::type;
+
+template <typename T>
+struct make_signed { using type = typename std::make_signed<T>::type; };
+
+#ifdef BOOST_CHARCONV_HAS_INT128
+
+template <>
+struct make_signed<boost::int128_type> { using type = boost::int128_type; };
+
+template <>
+struct make_signed<boost::uint128_type> { using type = boost::int128_type; };
+
+#endif
+
+}}} // Namespaces
+
+#endif //BOOST_CHARCONV_DETAIL_TYPE_TRAITS_HPP
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/from_chars.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/from_chars.hpp
new file mode 100644
index 00000000000..0bef0b5f5db
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/from_chars.hpp
@@ -0,0 +1,255 @@
+// Copyright 2022 Peter Dimov
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_CHARCONV_FROM_CHARS_HPP_INCLUDED
+#define BOOST_CHARCONV_FROM_CHARS_HPP_INCLUDED
+
+#include <boost/charconv/detail/config.hpp>
+#include <boost/charconv/detail/from_chars_result.hpp>
+#include <boost/charconv/detail/from_chars_integer_impl.hpp>
+#include <boost/charconv/detail/bit_layouts.hpp>
+#include <boost/charconv/config.hpp>
+#include <boost/charconv/chars_format.hpp>
+#include <boost/core/detail/string_view.hpp>
+#include <system_error>
+
+namespace boost { namespace charconv {
+
+// integer overloads
+
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, bool& value, int base = 10) noexcept = delete;
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, char& value, int base = 10) noexcept
+{
+ return detail::from_chars(first, last, value, base);
+}
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, signed char& value, int base = 10) noexcept
+{
+ return detail::from_chars(first, last, value, base);
+}
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, unsigned char& value, int base = 10) noexcept
+{
+ return detail::from_chars(first, last, value, base);
+}
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, short& value, int base = 10) noexcept
+{
+ return detail::from_chars(first, last, value, base);
+}
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, unsigned short& value, int base = 10) noexcept
+{
+ return detail::from_chars(first, last, value, base);
+}
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, int& value, int base = 10) noexcept
+{
+ return detail::from_chars(first, last, value, base);
+}
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, unsigned int& value, int base = 10) noexcept
+{
+ return detail::from_chars(first, last, value, base);
+}
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, long& value, int base = 10) noexcept
+{
+ return detail::from_chars(first, last, value, base);
+}
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, unsigned long& value, int base = 10) noexcept
+{
+ return detail::from_chars(first, last, value, base);
+}
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, long long& value, int base = 10) noexcept
+{
+ return detail::from_chars(first, last, value, base);
+}
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, unsigned long long& value, int base = 10) noexcept
+{
+ return detail::from_chars(first, last, value, base);
+}
+
+#ifdef BOOST_CHARCONV_HAS_INT128
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, boost::int128_type& value, int base = 10) noexcept
+{
+ return detail::from_chars128(first, last, value, base);
+}
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, boost::uint128_type& value, int base = 10) noexcept
+{
+ return detail::from_chars128(first, last, value, base);
+}
+#endif
+
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(boost::core::string_view sv, bool& value, int base = 10) noexcept = delete;
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(boost::core::string_view sv, char& value, int base = 10) noexcept
+{
+ return detail::from_chars(sv.data(), sv.data() + sv.size(), value, base);
+}
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(boost::core::string_view sv, signed char& value, int base = 10) noexcept
+{
+ return detail::from_chars(sv.data(), sv.data() + sv.size(), value, base);
+}
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(boost::core::string_view sv, unsigned char& value, int base = 10) noexcept
+{
+ return detail::from_chars(sv.data(), sv.data() + sv.size(), value, base);
+}
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(boost::core::string_view sv, short& value, int base = 10) noexcept
+{
+ return detail::from_chars(sv.data(), sv.data() + sv.size(), value, base);
+}
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(boost::core::string_view sv, unsigned short& value, int base = 10) noexcept
+{
+ return detail::from_chars(sv.data(), sv.data() + sv.size(), value, base);
+}
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(boost::core::string_view sv, int& value, int base = 10) noexcept
+{
+ return detail::from_chars(sv.data(), sv.data() + sv.size(), value, base);
+}
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(boost::core::string_view sv, unsigned int& value, int base = 10) noexcept
+{
+ return detail::from_chars(sv.data(), sv.data() + sv.size(), value, base);
+}
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(boost::core::string_view sv, long& value, int base = 10) noexcept
+{
+ return detail::from_chars(sv.data(), sv.data() + sv.size(), value, base);
+}
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(boost::core::string_view sv, unsigned long& value, int base = 10) noexcept
+{
+ return detail::from_chars(sv.data(), sv.data() + sv.size(), value, base);
+}
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(boost::core::string_view sv, long long& value, int base = 10) noexcept
+{
+ return detail::from_chars(sv.data(), sv.data() + sv.size(), value, base);
+}
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(boost::core::string_view sv, unsigned long long& value, int base = 10) noexcept
+{
+ return detail::from_chars(sv.data(), sv.data() + sv.size(), value, base);
+}
+
+#ifdef BOOST_CHARCONV_HAS_INT128
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(boost::core::string_view sv, boost::int128_type& value, int base = 10) noexcept
+{
+ return detail::from_chars128(sv.data(), sv.data() + sv.size(), value, base);
+}
+BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(boost::core::string_view sv, boost::uint128_type& value, int base = 10) noexcept
+{
+ return detail::from_chars128(sv.data(), sv.data() + sv.size(), value, base);
+}
+#endif
+
+//----------------------------------------------------------------------------------------------------------------------
+// Floating Point
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_CHARCONV_DECL from_chars_result from_chars_erange(const char* first, const char* last, float& value, chars_format fmt = chars_format::general) noexcept;
+BOOST_CHARCONV_DECL from_chars_result from_chars_erange(const char* first, const char* last, double& value, chars_format fmt = chars_format::general) noexcept;
+
+#ifndef BOOST_CHARCONV_UNSUPPORTED_LONG_DOUBLE
+BOOST_CHARCONV_DECL from_chars_result from_chars_erange(const char* first, const char* last, long double& value, chars_format fmt = chars_format::general) noexcept;
+#endif
+
+#ifdef BOOST_CHARCONV_HAS_QUADMATH
+BOOST_CHARCONV_DECL from_chars_result from_chars_erange(const char* first, const char* last, __float128& value, chars_format fmt = chars_format::general) noexcept;
+#endif
+
+// <stdfloat> types
+#ifdef BOOST_CHARCONV_HAS_FLOAT16
+BOOST_CHARCONV_DECL from_chars_result from_chars_erange(const char* first, const char* last, std::float16_t& value, chars_format fmt = chars_format::general) noexcept;
+#endif
+#ifdef BOOST_CHARCONV_HAS_FLOAT32
+BOOST_CHARCONV_DECL from_chars_result from_chars_erange(const char* first, const char* last, std::float32_t& value, chars_format fmt = chars_format::general) noexcept;
+#endif
+#ifdef BOOST_CHARCONV_HAS_FLOAT64
+BOOST_CHARCONV_DECL from_chars_result from_chars_erange(const char* first, const char* last, std::float64_t& value, chars_format fmt = chars_format::general) noexcept;
+#endif
+#if defined(BOOST_CHARCONV_HAS_STDFLOAT128) && defined(BOOST_CHARCONV_HAS_QUADMATH)
+BOOST_CHARCONV_DECL from_chars_result from_chars_erange(const char* first, const char* last, std::float128_t& value, chars_format fmt = chars_format::general) noexcept;
+#endif
+#ifdef BOOST_CHARCONV_HAS_BRAINFLOAT16
+BOOST_CHARCONV_DECL from_chars_result from_chars_erange(const char* first, const char* last, std::bfloat16_t& value, chars_format fmt = chars_format::general) noexcept;
+#endif
+
+BOOST_CHARCONV_DECL from_chars_result from_chars_erange(boost::core::string_view sv, float& value, chars_format fmt = chars_format::general) noexcept;
+BOOST_CHARCONV_DECL from_chars_result from_chars_erange(boost::core::string_view sv, double& value, chars_format fmt = chars_format::general) noexcept;
+
+#ifndef BOOST_CHARCONV_UNSUPPORTED_LONG_DOUBLE
+BOOST_CHARCONV_DECL from_chars_result from_chars_erange(boost::core::string_view sv, long double& value, chars_format fmt = chars_format::general) noexcept;
+#endif
+
+#ifdef BOOST_CHARCONV_HAS_QUADMATH
+BOOST_CHARCONV_DECL from_chars_result from_chars_erange(boost::core::string_view sv, __float128& value, chars_format fmt = chars_format::general) noexcept;
+#endif
+
+// <stdfloat> types
+#ifdef BOOST_CHARCONV_HAS_FLOAT16
+BOOST_CHARCONV_DECL from_chars_result from_chars_erange(boost::core::string_view sv, std::float16_t& value, chars_format fmt = chars_format::general) noexcept;
+#endif
+#ifdef BOOST_CHARCONV_HAS_FLOAT32
+BOOST_CHARCONV_DECL from_chars_result from_chars_erange(boost::core::string_view sv, std::float32_t& value, chars_format fmt = chars_format::general) noexcept;
+#endif
+#ifdef BOOST_CHARCONV_HAS_FLOAT64
+BOOST_CHARCONV_DECL from_chars_result from_chars_erange(boost::core::string_view sv, std::float64_t& value, chars_format fmt = chars_format::general) noexcept;
+#endif
+#if defined(BOOST_CHARCONV_HAS_STDFLOAT128) && defined(BOOST_CHARCONV_HAS_QUADMATH)
+BOOST_CHARCONV_DECL from_chars_result from_chars_erange(boost::core::string_view sv, std::float128_t& value, chars_format fmt = chars_format::general) noexcept;
+#endif
+#ifdef BOOST_CHARCONV_HAS_BRAINFLOAT16
+BOOST_CHARCONV_DECL from_chars_result from_chars_erange(boost::core::string_view sv, std::bfloat16_t& value, chars_format fmt = chars_format::general) noexcept;
+#endif
+
+// The following adhere to the standard library definition with std::errc::result_out_of_range
+// Returns value unmodified
+// See: https://github.com/cppalliance/charconv/issues/110
+
+BOOST_CHARCONV_DECL from_chars_result from_chars(const char* first, const char* last, float& value, chars_format fmt = chars_format::general) noexcept;
+BOOST_CHARCONV_DECL from_chars_result from_chars(const char* first, const char* last, double& value, chars_format fmt = chars_format::general) noexcept;
+
+#ifndef BOOST_CHARCONV_UNSUPPORTED_LONG_DOUBLE
+BOOST_CHARCONV_DECL from_chars_result from_chars(const char* first, const char* last, long double& value, chars_format fmt = chars_format::general) noexcept;
+#endif
+
+#ifdef BOOST_CHARCONV_HAS_QUADMATH
+BOOST_CHARCONV_DECL from_chars_result from_chars(const char* first, const char* last, __float128& value, chars_format fmt = chars_format::general) noexcept;
+#endif
+#ifdef BOOST_CHARCONV_HAS_FLOAT16
+BOOST_CHARCONV_DECL from_chars_result from_chars(const char* first, const char* last, std::float16_t& value, chars_format fmt = chars_format::general) noexcept;
+#endif
+#ifdef BOOST_CHARCONV_HAS_FLOAT32
+BOOST_CHARCONV_DECL from_chars_result from_chars(const char* first, const char* last, std::float32_t& value, chars_format fmt = chars_format::general) noexcept;
+#endif
+#ifdef BOOST_CHARCONV_HAS_FLOAT64
+BOOST_CHARCONV_DECL from_chars_result from_chars(const char* first, const char* last, std::float64_t& value, chars_format fmt = chars_format::general) noexcept;
+#endif
+#if defined(BOOST_CHARCONV_HAS_STDFLOAT128) && defined(BOOST_CHARCONV_HAS_QUADMATH)
+BOOST_CHARCONV_DECL from_chars_result from_chars(const char* first, const char* last, std::float128_t& value, chars_format fmt = chars_format::general) noexcept;
+#endif
+#ifdef BOOST_CHARCONV_HAS_BRAINFLOAT16
+BOOST_CHARCONV_DECL from_chars_result from_chars(const char* first, const char* last, std::bfloat16_t& value, chars_format fmt = chars_format::general) noexcept;
+#endif
+
+BOOST_CHARCONV_DECL from_chars_result from_chars(boost::core::string_view sv, float& value, chars_format fmt = chars_format::general) noexcept;
+BOOST_CHARCONV_DECL from_chars_result from_chars(boost::core::string_view sv, double& value, chars_format fmt = chars_format::general) noexcept;
+
+#ifndef BOOST_CHARCONV_UNSUPPORTED_LONG_DOUBLE
+BOOST_CHARCONV_DECL from_chars_result from_chars(boost::core::string_view sv, long double& value, chars_format fmt = chars_format::general) noexcept;
+#endif
+
+#ifdef BOOST_CHARCONV_HAS_QUADMATH
+BOOST_CHARCONV_DECL from_chars_result from_chars(boost::core::string_view sv, __float128& value, chars_format fmt = chars_format::general) noexcept;
+#endif
+#ifdef BOOST_CHARCONV_HAS_FLOAT16
+BOOST_CHARCONV_DECL from_chars_result from_chars(boost::core::string_view sv, std::float16_t& value, chars_format fmt = chars_format::general) noexcept;
+#endif
+#ifdef BOOST_CHARCONV_HAS_FLOAT32
+BOOST_CHARCONV_DECL from_chars_result from_chars(boost::core::string_view sv, std::float32_t& value, chars_format fmt = chars_format::general) noexcept;
+#endif
+#ifdef BOOST_CHARCONV_HAS_FLOAT64
+BOOST_CHARCONV_DECL from_chars_result from_chars(boost::core::string_view sv, std::float64_t& value, chars_format fmt = chars_format::general) noexcept;
+#endif
+#if defined(BOOST_CHARCONV_HAS_STDFLOAT128) && defined(BOOST_CHARCONV_HAS_QUADMATH)
+BOOST_CHARCONV_DECL from_chars_result from_chars(boost::core::string_view sv, std::float128_t& value, chars_format fmt = chars_format::general) noexcept;
+#endif
+#ifdef BOOST_CHARCONV_HAS_BRAINFLOAT16
+BOOST_CHARCONV_DECL from_chars_result from_chars(boost::core::string_view sv, std::bfloat16_t& value, chars_format fmt = chars_format::general) noexcept;
+#endif
+
+} // namespace charconv
+} // namespace boost
+
+#endif // #ifndef BOOST_CHARCONV_FROM_CHARS_HPP_INCLUDED
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/limits.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/limits.hpp
new file mode 100644
index 00000000000..f62809f30c7
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/limits.hpp
@@ -0,0 +1,96 @@
+// Copyright 2023 Matt Borland
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_CHARCONV_LIMITS_HPP
+#define BOOST_CHARCONV_LIMITS_HPP
+
+#include <boost/charconv/detail/config.hpp>
+#include <limits>
+#include <type_traits>
+
+namespace boost { namespace charconv {
+
+// limits<T>::max_chars10: the minimum size of the buffer that needs to be
+// passed to to_chars to guarantee successful conversion for all values of
+// type T, when either no base is passed, or base 10 is passed
+//
+// limits<T>::max_chars: the minimum size of the buffer that needs to be
+// passed to to_chars to guarantee successful conversion for all values of
+// type T, for any value of base
+
+namespace detail
+{
+
+constexpr int exp_digits( int exp )
+{
+ return exp < 100? 2: exp < 1000? 3: exp < 10000? 4: 5;
+}
+
+#if defined(BOOST_HAS_INT128)
+
+template<class T> struct is_int128: std::is_same<T, boost::int128_type> {};
+template<class T> struct is_uint128: std::is_same<T, boost::int128_type> {};
+
+#else
+
+template<class T> struct is_int128: std::false_type {};
+template<class T> struct is_uint128: std::false_type {};
+
+#endif
+
+} // namespace detail
+
+template<typename T> struct limits
+{
+ BOOST_ATTRIBUTE_UNUSED static constexpr int max_chars10 =
+
+ // int128_t
+ detail::is_int128<T>::value? 38+2: // digits10 + 1 + sign
+
+ // uint128_t
+ detail::is_uint128<T>::value? 38+1: // digits10 + 1
+
+ // integral
+ std::numeric_limits<T>::is_integer? std::numeric_limits<T>::digits10 + 1 + std::numeric_limits<T>::is_signed:
+
+ // floating point
+ std::numeric_limits<T>::max_digits10 + 3 + 2 + detail::exp_digits( std::numeric_limits<T>::max_exponent10 ); // -1.(max_digits10)e+(max_exp)
+
+ BOOST_ATTRIBUTE_UNUSED static constexpr int max_chars =
+
+ // int128_t
+ detail::is_int128<T>::value? 127+2: // digits + 1 + sign
+
+ // uint128_t
+ detail::is_uint128<T>::value? 128+1: // digits + 1
+
+ // integral
+ std::numeric_limits<T>::is_integer? std::numeric_limits<T>::digits + 1 + std::numeric_limits<T>::is_signed:
+
+ // floating point
+ std::numeric_limits<T>::max_digits10 + 3 + 2 + detail::exp_digits( std::numeric_limits<T>::max_exponent10 ); // as above
+};
+
+#if defined(BOOST_CHARCONV_HAS_QUADMATH)
+
+template <> struct limits<__float128>
+{
+ BOOST_ATTRIBUTE_UNUSED static constexpr int max_chars10 = 33 + 3 + 2 + 5;
+ BOOST_ATTRIBUTE_UNUSED static constexpr int max_chars = max_chars10;
+};
+
+#endif
+
+#if defined(BOOST_NO_CXX17_INLINE_VARIABLES)
+
+// Definitions of in-class constexpr members are allowed but deprecated in C++17
+
+template<typename T> BOOST_ATTRIBUTE_UNUSED constexpr int limits<T>::max_chars10;
+template<typename T> BOOST_ATTRIBUTE_UNUSED constexpr int limits<T>::max_chars;
+
+#endif // defined(BOOST_NO_CXX17_INLINE_VARIABLES)
+
+}} // namespace boost::charconv
+
+#endif // BOOST_CHARCONV_LIMITS_HPP
diff --git a/contrib/restricted/boost/charconv/include/boost/charconv/to_chars.hpp b/contrib/restricted/boost/charconv/include/boost/charconv/to_chars.hpp
new file mode 100644
index 00000000000..7192fda578b
--- /dev/null
+++ b/contrib/restricted/boost/charconv/include/boost/charconv/to_chars.hpp
@@ -0,0 +1,147 @@
+// Copyright 2022 Peter Dimov
+// Copyright 2023 Matt Borland
+// Copyright 2023 Junekey Jeon
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_CHARCONV_TO_CHARS_HPP_INCLUDED
+#define BOOST_CHARCONV_TO_CHARS_HPP_INCLUDED
+
+#include <boost/charconv/detail/to_chars_integer_impl.hpp>
+#include <boost/charconv/detail/to_chars_result.hpp>
+#include <boost/charconv/config.hpp>
+#include <boost/charconv/chars_format.hpp>
+
+namespace boost {
+namespace charconv {
+
+// integer overloads
+BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, bool value, int base) noexcept = delete;
+BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, char value, int base = 10) noexcept
+{
+ return detail::to_chars_int(first, last, value, base);
+}
+BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, signed char value, int base = 10) noexcept
+{
+ return detail::to_chars_int(first, last, value, base);
+}
+BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, unsigned char value, int base = 10) noexcept
+{
+ return detail::to_chars_int(first, last, value, base);
+}
+BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, short value, int base = 10) noexcept
+{
+ return detail::to_chars_int(first, last, value, base);
+}
+BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, unsigned short value, int base = 10) noexcept
+{
+ return detail::to_chars_int(first, last, value, base);
+}
+BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, int value, int base = 10) noexcept
+{
+ return detail::to_chars_int(first, last, value, base);
+}
+BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, unsigned int value, int base = 10) noexcept
+{
+ return detail::to_chars_int(first, last, value, base);
+}
+BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, long value, int base = 10) noexcept
+{
+ return detail::to_chars_int(first, last, value, base);
+}
+BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, unsigned long value, int base = 10) noexcept
+{
+ return detail::to_chars_int(first, last, value, base);
+}
+BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, long long value, int base = 10) noexcept
+{
+ return detail::to_chars_int(first, last, value, base);
+}
+BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, unsigned long long value, int base = 10) noexcept
+{
+ return detail::to_chars_int(first, last, value, base);
+}
+
+#ifdef BOOST_CHARCONV_HAS_INT128
+BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, boost::int128_type value, int base = 10) noexcept
+{
+ return detail::to_chars128(first, last, value, base);
+}
+BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, boost::uint128_type value, int base = 10) noexcept
+{
+ return detail::to_chars128(first, last, value, base);
+}
+#endif
+
+//----------------------------------------------------------------------------------------------------------------------
+// Floating Point
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, float value,
+ chars_format fmt = chars_format::general) noexcept;
+BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, double value,
+ chars_format fmt = chars_format::general) noexcept;
+
+#ifndef BOOST_CHARCONV_UNSUPPORTED_LONG_DOUBLE
+BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, long double value,
+ chars_format fmt = chars_format::general) noexcept;
+#endif
+
+BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, float value,
+ chars_format fmt, int precision) noexcept;
+BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, double value,
+ chars_format fmt, int precision) noexcept;
+
+#ifndef BOOST_CHARCONV_UNSUPPORTED_LONG_DOUBLE
+BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, long double value,
+ chars_format fmt, int precision) noexcept;
+#endif
+
+#ifdef BOOST_CHARCONV_HAS_QUADMATH
+BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, __float128 value,
+ chars_format fmt = chars_format::general) noexcept;
+
+BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, __float128 value,
+ chars_format fmt, int precision) noexcept;
+#endif
+
+#ifdef BOOST_CHARCONV_HAS_FLOAT16
+BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, std::float16_t value,
+ chars_format fmt = chars_format::general) noexcept;
+
+BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, std::float16_t value,
+ chars_format fmt, int precision) noexcept;
+#endif
+#ifdef BOOST_CHARCONV_HAS_FLOAT32
+BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, std::float32_t value,
+ chars_format fmt = chars_format::general) noexcept;
+
+BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, std::float32_t value,
+ chars_format fmt, int precision) noexcept;
+#endif
+#ifdef BOOST_CHARCONV_HAS_FLOAT64
+BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, std::float64_t value,
+ chars_format fmt = chars_format::general) noexcept;
+
+BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, std::float64_t value,
+ chars_format fmt, int precision) noexcept;
+#endif
+#if defined(BOOST_CHARCONV_HAS_STDFLOAT128) && defined(BOOST_CHARCONV_HAS_QUADMATH)
+BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, std::float128_t value,
+ chars_format fmt = chars_format::general) noexcept;
+
+BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, std::float128_t value,
+ chars_format fmt, int precision) noexcept;
+#endif
+#ifdef BOOST_CHARCONV_HAS_BRAINFLOAT16
+BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, std::bfloat16_t value,
+ chars_format fmt = chars_format::general) noexcept;
+
+BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, std::bfloat16_t value,
+ chars_format fmt, int precision) noexcept;
+#endif
+
+} // namespace charconv
+} // namespace boost
+
+#endif // #ifndef BOOST_CHARCONV_TO_CHARS_HPP_INCLUDED
diff --git a/contrib/restricted/boost/charconv/ya.make b/contrib/restricted/boost/charconv/ya.make
new file mode 100644
index 00000000000..c502c16a98e
--- /dev/null
+++ b/contrib/restricted/boost/charconv/ya.make
@@ -0,0 +1,31 @@
+# Generated by devtools/yamaker from nixpkgs 24.05.
+
+LIBRARY()
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ BSL-1.0
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+VERSION(1.88.0)
+
+ORIGINAL_SOURCE(https://github.com/boostorg/charconv/archive/boost-1.88.0.tar.gz)
+
+PEERDIR(
+ contrib/restricted/boost/assert
+ contrib/restricted/boost/config
+ contrib/restricted/boost/core
+)
+
+ADDINCL(
+ GLOBAL contrib/restricted/boost/charconv/include
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+END()
diff --git a/contrib/restricted/boost/locale/.yandex_meta/__init__.py b/contrib/restricted/boost/locale/.yandex_meta/__init__.py
index dc25b4c73b1..84e7d1f0736 100644
--- a/contrib/restricted/boost/locale/.yandex_meta/__init__.py
+++ b/contrib/restricted/boost/locale/.yandex_meta/__init__.py
@@ -6,13 +6,13 @@ from devtools.yamaker.project import NixSourceProject
def post_install(self):
# fmt: off
posix_srcs = set(fileutil.files(
- f"{self.dstdir}/src/boost/locale/posix",
+ f"{self.dstdir}/src/posix",
rel=self.dstdir,
test=pathutil.is_source,
))
win_srcs = set(fileutil.files(
- f"{self.dstdir}/src/boost/locale/win32",
+ f"{self.dstdir}/src/win32",
rel=self.dstdir,
test=pathutil.is_source,
))
diff --git a/contrib/restricted/boost/locale/.yandex_meta/default.nix b/contrib/restricted/boost/locale/.yandex_meta/default.nix
index d2e5b89c52c..9c73e061e2b 100644
--- a/contrib/restricted/boost/locale/.yandex_meta/default.nix
+++ b/contrib/restricted/boost/locale/.yandex_meta/default.nix
@@ -1,13 +1,13 @@
self: super: with self; {
boost_locale = stdenv.mkDerivation rec {
pname = "boost_locale";
- version = "1.87.0";
+ version = "1.88.0";
src = fetchFromGitHub {
owner = "boostorg";
repo = "locale";
rev = "boost-${version}";
- hash = "sha256-KQg12DCqTqG3KcBLobg6+B/XEDzaag8JiC52p6ecJ6Y=";
+ hash = "sha256-2GL7iq6xpJDYbHk6B85CKTyV1E7873phb9MERw4Z2Cc=";
};
};
}
diff --git a/contrib/restricted/boost/locale/.yandex_meta/devtools.copyrights.report b/contrib/restricted/boost/locale/.yandex_meta/devtools.copyrights.report
index b8639e01536..3aa4d118eec 100644
--- a/contrib/restricted/boost/locale/.yandex_meta/devtools.copyrights.report
+++ b/contrib/restricted/boost/locale/.yandex_meta/devtools.copyrights.report
@@ -54,13 +54,13 @@ BELONGS ya.make
include/boost/locale/conversion.hpp [2:2]
include/boost/locale/date_time.hpp [2:2]
include/boost/locale/date_time_facet.hpp [2:2]
- include/boost/locale/encoding.hpp [2:2]
+ include/boost/locale/encoding.hpp [2:3]
include/boost/locale/encoding_errors.hpp [2:2]
include/boost/locale/encoding_utf.hpp [2:3]
include/boost/locale/format.hpp [2:3]
include/boost/locale/formatting.hpp [2:3]
include/boost/locale/generator.hpp [2:2]
- include/boost/locale/gnu_gettext.hpp [2:2]
+ include/boost/locale/gnu_gettext.hpp [2:3]
include/boost/locale/info.hpp [2:3]
include/boost/locale/localization_backend.hpp [2:2]
include/boost/locale/message.hpp [2:3]
@@ -68,75 +68,74 @@ BELONGS ya.make
include/boost/locale/utf.hpp [2:2]
include/boost/locale/util.hpp [2:3]
include/boost/locale/util/locale_data.hpp [2:3]
- src/boost/locale/encoding/codepage.cpp [2:3]
- src/boost/locale/encoding/iconv_converter.hpp [2:2]
- src/boost/locale/encoding/uconv_converter.hpp [2:2]
- src/boost/locale/encoding/wconv_converter.hpp [2:2]
- src/boost/locale/icu/all_generator.hpp [2:2]
- src/boost/locale/icu/boundary.cpp [2:3]
- src/boost/locale/icu/cdata.hpp [2:2]
- src/boost/locale/icu/codecvt.cpp [2:3]
- src/boost/locale/icu/codecvt.hpp [2:2]
- src/boost/locale/icu/collator.cpp [2:2]
- src/boost/locale/icu/conversion.cpp [2:3]
- src/boost/locale/icu/date_time.cpp [2:3]
- src/boost/locale/icu/formatter.cpp [2:3]
- src/boost/locale/icu/formatter.hpp [2:2]
- src/boost/locale/icu/formatters_cache.cpp [2:3]
- src/boost/locale/icu/formatters_cache.hpp [2:3]
- src/boost/locale/icu/icu_backend.cpp [2:3]
- src/boost/locale/icu/icu_backend.hpp [2:2]
- src/boost/locale/icu/icu_util.hpp [2:3]
- src/boost/locale/icu/numeric.cpp [2:2]
- src/boost/locale/icu/time_zone.cpp [2:2]
- src/boost/locale/icu/time_zone.hpp [2:2]
- src/boost/locale/icu/uconv.hpp [2:3]
- src/boost/locale/posix/all_generator.hpp [2:2]
- src/boost/locale/posix/codecvt.cpp [2:3]
- src/boost/locale/posix/collate.cpp [2:2]
- src/boost/locale/posix/converter.cpp [2:2]
- src/boost/locale/posix/numeric.cpp [2:2]
- src/boost/locale/posix/posix_backend.cpp [2:3]
- src/boost/locale/posix/posix_backend.hpp [2:2]
- src/boost/locale/shared/date_time.cpp [2:3]
- src/boost/locale/shared/format.cpp [2:2]
- src/boost/locale/shared/formatting.cpp [2:2]
- src/boost/locale/shared/generator.cpp [2:2]
- src/boost/locale/shared/iconv_codecvt.cpp [2:3]
- src/boost/locale/shared/iconv_codecvt.hpp [2:2]
- src/boost/locale/shared/ids.cpp [2:3]
- src/boost/locale/shared/ios_prop.hpp [2:3]
- src/boost/locale/shared/localization_backend.cpp [2:2]
- src/boost/locale/shared/mo_hash.hpp [2:2]
- src/boost/locale/shared/mo_lambda.cpp [2:3]
- src/boost/locale/shared/mo_lambda.hpp [2:3]
- src/boost/locale/std/all_generator.hpp [2:2]
- src/boost/locale/std/codecvt.cpp [2:2]
- src/boost/locale/std/collate.cpp [2:2]
- src/boost/locale/std/converter.cpp [2:2]
- src/boost/locale/std/numeric.cpp [2:2]
- src/boost/locale/std/std_backend.cpp [2:3]
- src/boost/locale/std/std_backend.hpp [2:2]
- src/boost/locale/util/codecvt_converter.cpp [2:3]
- src/boost/locale/util/default_locale.cpp [2:2]
- src/boost/locale/util/encoding.cpp [2:3]
- src/boost/locale/util/encoding.hpp [2:3]
- src/boost/locale/util/gregorian.cpp [2:2]
- src/boost/locale/util/gregorian.hpp [2:2]
- src/boost/locale/util/iconv.hpp [2:2]
- src/boost/locale/util/info.cpp [2:3]
- src/boost/locale/util/locale_data.cpp [2:3]
- src/boost/locale/util/numeric.hpp [2:2]
- src/boost/locale/util/timezone.hpp [2:2]
- src/boost/locale/win32/all_generator.hpp [2:2]
- src/boost/locale/win32/api.hpp [2:2]
- src/boost/locale/win32/collate.cpp [2:2]
- src/boost/locale/win32/converter.cpp [2:2]
- src/boost/locale/win32/lcid.cpp [2:2]
- src/boost/locale/win32/lcid.hpp [2:2]
- src/boost/locale/win32/numeric.cpp [2:2]
- src/boost/locale/win32/win_backend.cpp [2:3]
- src/boost/locale/win32/win_backend.hpp [2:2]
+ src/encoding/codepage.cpp [2:3]
+ src/encoding/iconv_converter.hpp [2:2]
+ src/encoding/uconv_converter.hpp [2:2]
+ src/encoding/wconv_converter.hpp [2:2]
+ src/icu/all_generator.hpp [2:2]
+ src/icu/boundary.cpp [2:3]
+ src/icu/cdata.hpp [2:2]
+ src/icu/codecvt.cpp [2:3]
+ src/icu/codecvt.hpp [2:2]
+ src/icu/collator.cpp [2:3]
+ src/icu/conversion.cpp [2:3]
+ src/icu/date_time.cpp [2:3]
+ src/icu/formatter.cpp [2:3]
+ src/icu/formatter.hpp [2:3]
+ src/icu/formatters_cache.cpp [2:3]
+ src/icu/formatters_cache.hpp [2:3]
+ src/icu/icu_backend.cpp [2:3]
+ src/icu/icu_backend.hpp [2:2]
+ src/icu/icu_util.hpp [2:3]
+ src/icu/numeric.cpp [2:3]
+ src/icu/time_zone.hpp [2:3]
+ src/icu/uconv.hpp [2:3]
+ src/posix/all_generator.hpp [2:2]
+ src/posix/codecvt.cpp [2:3]
+ src/posix/collate.cpp [2:2]
+ src/posix/converter.cpp [2:2]
+ src/posix/numeric.cpp [2:2]
+ src/posix/posix_backend.cpp [2:3]
+ src/posix/posix_backend.hpp [2:2]
+ src/shared/date_time.cpp [2:3]
+ src/shared/format.cpp [2:3]
+ src/shared/formatting.cpp [2:2]
+ src/shared/generator.cpp [2:3]
+ src/shared/iconv_codecvt.cpp [2:3]
+ src/shared/iconv_codecvt.hpp [2:2]
+ src/shared/ids.cpp [2:3]
+ src/shared/ios_prop.hpp [2:3]
+ src/shared/localization_backend.cpp [2:2]
+ src/shared/mo_hash.hpp [2:2]
+ src/shared/mo_lambda.cpp [2:3]
+ src/shared/mo_lambda.hpp [2:3]
+ src/std/all_generator.hpp [2:2]
+ src/std/codecvt.cpp [2:2]
+ src/std/collate.cpp [2:2]
+ src/std/converter.cpp [2:2]
+ src/std/numeric.cpp [2:2]
+ src/std/std_backend.cpp [2:3]
+ src/std/std_backend.hpp [2:2]
+ src/util/codecvt_converter.cpp [2:3]
+ src/util/default_locale.cpp [2:2]
+ src/util/encoding.cpp [2:3]
+ src/util/encoding.hpp [2:3]
+ src/util/gregorian.cpp [2:2]
+ src/util/gregorian.hpp [2:2]
+ src/util/iconv.hpp [2:2]
+ src/util/info.cpp [2:3]
+ src/util/locale_data.cpp [2:3]
+ src/util/numeric.hpp [2:2]
+ src/util/timezone.hpp [2:2]
+ src/win32/all_generator.hpp [2:2]
+ src/win32/api.hpp [2:2]
+ src/win32/collate.cpp [2:2]
+ src/win32/converter.cpp [2:2]
+ src/win32/lcid.cpp [2:2]
+ src/win32/lcid.hpp [2:2]
+ src/win32/numeric.cpp [2:2]
+ src/win32/win_backend.cpp [2:3]
+ src/win32/win_backend.hpp [2:2]
KEEP COPYRIGHT_SERVICE_LABEL 0aacc38a77bc0373054292f93600d25a
BELONGS ya.make
@@ -148,7 +147,19 @@ BELONGS ya.make
Score : 100.00
Match type : COPYRIGHT
Files with this license:
- src/boost/locale/icu/uconv.hpp [2:3]
+ src/icu/uconv.hpp [2:3]
+
+KEEP COPYRIGHT_SERVICE_LABEL 10d0d960009e0367294c74e986494399
+BELONGS ya.make
+ License text:
+ // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
+ // Copyright (c) 2025 Alexander Grund
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ include/boost/locale/encoding.hpp [2:3]
KEEP COPYRIGHT_SERVICE_LABEL 187d73eada66cef6d5d08ed727437603
BELONGS ya.make
@@ -160,8 +171,40 @@ BELONGS ya.make
Match type : COPYRIGHT
Files with this license:
include/boost/locale/detail/allocator_traits.hpp [2:2]
- src/boost/locale/shared/ids.cpp [2:3]
- src/boost/locale/shared/std_collate_adapter.hpp [2:2]
+ src/icu/formatter.hpp [2:3]
+ src/icu/numeric.cpp [2:3]
+ src/shared/format.cpp [2:3]
+ src/shared/generator.cpp [2:3]
+ src/shared/ids.cpp [2:3]
+ src/shared/std_collate_adapter.hpp [2:2]
+
+KEEP COPYRIGHT_SERVICE_LABEL 21fa899f7deb226d35fdddb2e22eb4ea
+BELONGS ya.make
+ License text:
+ // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
+ // Copyright (c) 2021-2025 Alexander Grund
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ src/icu/boundary.cpp [2:3]
+ src/shared/message.cpp [2:3]
+
+KEEP COPYRIGHT_SERVICE_LABEL 5283dadfabe6a307c3ae77a03b4204e6
+BELONGS ya.make
+ License text:
+ // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
+ // Copyright (c) 2021-2024 Alexander Grund
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ include/boost/locale/format.hpp [2:3]
+ src/icu/date_time.cpp [2:3]
+ src/icu/formatter.cpp [2:3]
+ src/icu/formatters_cache.cpp [2:3]
KEEP COPYRIGHT_SERVICE_LABEL 5f6f0ebf2d6180caac56d446585150fe
BELONGS ya.make
@@ -187,6 +230,11 @@ BELONGS ya.make
Match type : COPYRIGHT
Files with this license:
include/boost/locale/encoding_utf.hpp [2:3]
+ include/boost/locale/gnu_gettext.hpp [2:3]
+ src/icu/collator.cpp [2:3]
+ src/icu/conversion.cpp [2:3]
+ src/icu/time_zone.hpp [2:3]
+ src/util/locale_data.cpp [2:3]
KEEP COPYRIGHT_SERVICE_LABEL 8d04644911f5fff0cef0ea7eeadf74ee
BELONGS ya.make
@@ -198,11 +246,20 @@ BELONGS ya.make
Score : 100.00
Match type : COPYRIGHT
Files with this license:
- src/boost/locale/icu/boundary.cpp [2:3]
- src/boost/locale/icu/date_time.cpp [2:3]
- src/boost/locale/icu/formatters_cache.cpp [2:3]
- src/boost/locale/icu/formatters_cache.hpp [2:3]
- src/boost/locale/icu/icu_util.hpp [2:3]
+ src/icu/formatters_cache.hpp [2:3]
+ src/icu/icu_util.hpp [2:3]
+
+KEEP COPYRIGHT_SERVICE_LABEL a63a0062b2f0e3cc2d4c206ed25fb44c
+BELONGS ya.make
+ License text:
+ // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
+ // Copyright (c) 2023-2024 Alexander Grund
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ include/boost/locale/util/locale_data.hpp [2:3]
KEEP COPYRIGHT_SERVICE_LABEL a999dc6b43b371fa616fd4c0c30cf6f3
BELONGS ya.make
@@ -213,10 +270,23 @@ BELONGS ya.make
Score : 100.00
Match type : COPYRIGHT
Files with this license:
- include/boost/locale/detail/any_string.hpp [2:2]
- include/boost/locale/util/locale_data.hpp [2:3]
- src/boost/locale/shared/message.hpp [2:2]
- src/boost/locale/util/make_std_unique.hpp [2:2]
+ src/shared/message.hpp [2:2]
+ src/util/make_std_unique.hpp [2:2]
+
+KEEP COPYRIGHT_SERVICE_LABEL aa7339758a526244dab153b34cc3dcef
+BELONGS ya.make
+ License text:
+ // Copyright (c) 2022-2025 Alexander Grund
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ include/boost/locale/detail/encoding.hpp [2:2]
+ src/encoding/codepage.cpp [2:3]
+ src/icu/codecvt.cpp [2:3]
+ src/util/encoding.cpp [2:3]
+ src/util/encoding.hpp [2:3]
KEEP COPYRIGHT_SERVICE_LABEL c75aae6c76ff96e098e51412b5d4691b
BELONGS ya.make
@@ -228,40 +298,44 @@ BELONGS ya.make
Score : 100.00
Match type : COPYRIGHT
Files with this license:
- include/boost/locale/detail/encoding.hpp [2:2]
include/boost/locale/detail/facet_id.hpp [2:2]
include/boost/locale/detail/is_supported_char.hpp [2:2]
include/boost/locale/formatting.hpp [2:3]
include/boost/locale/info.hpp [2:3]
include/boost/locale/util.hpp [2:3]
include/boost/locale/util/string.hpp [2:2]
- src/boost/locale/encoding/codepage.cpp [2:3]
- src/boost/locale/icu/codecvt.cpp [2:3]
- src/boost/locale/icu/conversion.cpp [2:3]
- src/boost/locale/icu/icu_backend.cpp [2:3]
- src/boost/locale/posix/codecvt.cpp [2:3]
- src/boost/locale/posix/posix_backend.cpp [2:3]
- src/boost/locale/shared/date_time.cpp [2:3]
- src/boost/locale/shared/iconv_codecvt.cpp [2:3]
- src/boost/locale/std/std_backend.cpp [2:3]
- src/boost/locale/util/codecvt_converter.cpp [2:3]
- src/boost/locale/util/encoding.cpp [2:3]
- src/boost/locale/util/encoding.hpp [2:3]
- src/boost/locale/util/info.cpp [2:3]
- src/boost/locale/util/locale_data.cpp [2:3]
- src/boost/locale/win32/win_backend.cpp [2:3]
+ src/icu/icu_backend.cpp [2:3]
+ src/posix/codecvt.cpp [2:3]
+ src/posix/posix_backend.cpp [2:3]
+ src/shared/date_time.cpp [2:3]
+ src/shared/iconv_codecvt.cpp [2:3]
+ src/std/std_backend.cpp [2:3]
+ src/util/codecvt_converter.cpp [2:3]
+ src/util/info.cpp [2:3]
+ src/win32/win_backend.cpp [2:3]
+
+KEEP COPYRIGHT_SERVICE_LABEL c7b0fea325502e648cff49d8a76577a4
+BELONGS ya.make
+ License text:
+ // Copyright (c) 2024-2025 Alexander Grund
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ src/util/numeric_conversion.hpp [2:2]
KEEP COPYRIGHT_SERVICE_LABEL c9d011950648c03f29cc58f664ea728e
BELONGS ya.make
License text:
// Copyright (c) 2009-2015 Artyom Beilis (Tonkikh)
- // Copyright (c) 2021-2023 Alexander Grund
+ // Copyright (c) 2021-2025 Alexander Grund
Scancode info:
Original SPDX id: COPYRIGHT_SERVICE_LABEL
Score : 100.00
Match type : COPYRIGHT
Files with this license:
- src/boost/locale/shared/message.cpp [2:3]
+ src/shared/message.cpp [2:3]
KEEP COPYRIGHT_SERVICE_LABEL ce25033e7c274b09a88738980e8ddeb6
BELONGS ya.make
@@ -273,25 +347,33 @@ BELONGS ya.make
Score : 100.00
Match type : COPYRIGHT
Files with this license:
- src/boost/locale/shared/ios_prop.hpp [2:3]
+ src/shared/ios_prop.hpp [2:3]
+
+KEEP COPYRIGHT_SERVICE_LABEL d1d2857cd6a3cb1945f79fec36352462
+BELONGS ya.make
+ License text:
+ // Copyright (c) 2023-2025 Alexander Grund
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ include/boost/locale/detail/any_string.hpp [2:2]
KEEP COPYRIGHT_SERVICE_LABEL f3772b68b272fd4e5066ca5b643faab9
BELONGS ya.make
License text:
- // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
+ // Copyright (c) 2015 Artyom Beilis (Tonkikh)
// Copyright (c) 2021-2023 Alexander Grund
Scancode info:
Original SPDX id: COPYRIGHT_SERVICE_LABEL
Score : 100.00
Match type : COPYRIGHT
Files with this license:
- include/boost/locale/format.hpp [2:3]
include/boost/locale/generic_codecvt.hpp [2:3]
include/boost/locale/message.hpp [2:3]
- src/boost/locale/icu/formatter.cpp [2:3]
- src/boost/locale/shared/message.cpp [2:3]
- src/boost/locale/shared/mo_lambda.cpp [2:3]
- src/boost/locale/shared/mo_lambda.hpp [2:3]
+ src/shared/mo_lambda.cpp [2:3]
+ src/shared/mo_lambda.hpp [2:3]
KEEP COPYRIGHT_SERVICE_LABEL f9f21cf5cc873fe5cc18d20988035289
BELONGS ya.make
@@ -313,4 +395,4 @@ BELONGS ya.make
Score : 100.00
Match type : COPYRIGHT
Files with this license:
- src/boost/locale/util/foreach_char.hpp [2:2]
+ src/util/foreach_char.hpp [2:2]
diff --git a/contrib/restricted/boost/locale/.yandex_meta/devtools.licenses.report b/contrib/restricted/boost/locale/.yandex_meta/devtools.licenses.report
index 7173da13541..5c88ba923ad 100644
--- a/contrib/restricted/boost/locale/.yandex_meta/devtools.licenses.report
+++ b/contrib/restricted/boost/locale/.yandex_meta/devtools.licenses.report
@@ -53,7 +53,7 @@ BELONGS ya.make
Match type : NOTICE
Links : http://www.boost.org/LICENSE_1_0.txt, http://www.boost.org/users/license.html, https://spdx.org/licenses/BSL-1.0
Files with this license:
- README.md [64:64]
+ README.md [66:66]
KEEP BSL-1.0 a84b62b7fab19a18e7129119ab661542
BELONGS ya.make
@@ -89,7 +89,7 @@ BELONGS ya.make
include/boost/locale/detail/allocator_traits.hpp [5:5]
include/boost/locale/detail/encoding.hpp [5:5]
include/boost/locale/detail/is_supported_char.hpp [5:5]
- include/boost/locale/encoding.hpp [5:5]
+ include/boost/locale/encoding.hpp [6:6]
include/boost/locale/encoding_errors.hpp [5:5]
include/boost/locale/encoding_utf.hpp [6:6]
include/boost/locale/formatting.hpp [6:6]
@@ -99,49 +99,50 @@ BELONGS ya.make
include/boost/locale/time_zone.hpp [5:5]
include/boost/locale/utf8_codecvt.hpp [5:5]
include/boost/locale/util/locale_data.hpp [6:6]
- src/boost/locale/encoding/codepage.cpp [6:6]
- src/boost/locale/encoding/iconv_converter.hpp [5:5]
- src/boost/locale/icu/all_generator.hpp [5:5]
- src/boost/locale/icu/boundary.cpp [6:6]
- src/boost/locale/icu/cdata.hpp [5:5]
- src/boost/locale/icu/codecvt.hpp [5:5]
- src/boost/locale/icu/formatter.hpp [5:5]
- src/boost/locale/icu/icu_backend.hpp [5:5]
- src/boost/locale/icu/uconv.hpp [6:6]
- src/boost/locale/posix/all_generator.hpp [5:5]
- src/boost/locale/posix/codecvt.cpp [6:6]
- src/boost/locale/posix/collate.cpp [5:5]
- src/boost/locale/posix/converter.cpp [5:5]
- src/boost/locale/posix/numeric.cpp [5:5]
- src/boost/locale/posix/posix_backend.hpp [5:5]
- src/boost/locale/shared/date_time.cpp [6:6]
- src/boost/locale/shared/formatting.cpp [5:5]
- src/boost/locale/shared/iconv_codecvt.hpp [5:5]
- src/boost/locale/shared/ids.cpp [6:6]
- src/boost/locale/shared/ios_prop.hpp [6:6]
- src/boost/locale/shared/message.hpp [5:5]
- src/boost/locale/shared/std_collate_adapter.hpp [5:5]
- src/boost/locale/std/codecvt.cpp [5:5]
- src/boost/locale/std/collate.cpp [5:5]
- src/boost/locale/std/converter.cpp [5:5]
- src/boost/locale/std/numeric.cpp [5:5]
- src/boost/locale/std/std_backend.hpp [5:5]
- src/boost/locale/util/codecvt_converter.cpp [6:6]
- src/boost/locale/util/default_locale.cpp [5:5]
- src/boost/locale/util/encoding.cpp [6:6]
- src/boost/locale/util/encoding.hpp [6:6]
- src/boost/locale/util/foreach_char.hpp [5:5]
- src/boost/locale/util/gregorian.hpp [5:5]
- src/boost/locale/util/iconv.hpp [5:5]
- src/boost/locale/util/info.cpp [6:6]
- src/boost/locale/util/locale_data.cpp [6:6]
- src/boost/locale/util/make_std_unique.hpp [5:5]
- src/boost/locale/win32/all_generator.hpp [5:5]
- src/boost/locale/win32/collate.cpp [5:5]
- src/boost/locale/win32/converter.cpp [5:5]
- src/boost/locale/win32/lcid.cpp [5:5]
- src/boost/locale/win32/numeric.cpp [5:5]
- src/boost/locale/win32/win_backend.hpp [5:5]
+ src/encoding/codepage.cpp [6:6]
+ src/encoding/iconv_converter.hpp [5:5]
+ src/icu/all_generator.hpp [5:5]
+ src/icu/boundary.cpp [6:6]
+ src/icu/cdata.hpp [5:5]
+ src/icu/codecvt.hpp [5:5]
+ src/icu/formatter.hpp [6:6]
+ src/icu/icu_backend.hpp [5:5]
+ src/icu/uconv.hpp [6:6]
+ src/posix/all_generator.hpp [5:5]
+ src/posix/codecvt.cpp [6:6]
+ src/posix/collate.cpp [5:5]
+ src/posix/converter.cpp [5:5]
+ src/posix/numeric.cpp [5:5]
+ src/posix/posix_backend.hpp [5:5]
+ src/shared/date_time.cpp [6:6]
+ src/shared/formatting.cpp [5:5]
+ src/shared/iconv_codecvt.hpp [5:5]
+ src/shared/ids.cpp [6:6]
+ src/shared/ios_prop.hpp [6:6]
+ src/shared/message.hpp [5:5]
+ src/shared/std_collate_adapter.hpp [5:5]
+ src/std/codecvt.cpp [5:5]
+ src/std/collate.cpp [5:5]
+ src/std/converter.cpp [5:5]
+ src/std/numeric.cpp [5:5]
+ src/std/std_backend.hpp [5:5]
+ src/util/codecvt_converter.cpp [6:6]
+ src/util/default_locale.cpp [5:5]
+ src/util/encoding.cpp [6:6]
+ src/util/encoding.hpp [6:6]
+ src/util/foreach_char.hpp [5:5]
+ src/util/gregorian.hpp [5:5]
+ src/util/iconv.hpp [5:5]
+ src/util/info.cpp [6:6]
+ src/util/locale_data.cpp [6:6]
+ src/util/make_std_unique.hpp [5:5]
+ src/util/numeric.hpp [5:5]
+ src/win32/all_generator.hpp [5:5]
+ src/win32/collate.cpp [5:5]
+ src/win32/converter.cpp [5:5]
+ src/win32/lcid.cpp [5:5]
+ src/win32/numeric.cpp [5:5]
+ src/win32/win_backend.hpp [5:5]
KEEP BSL-1.0 e03c043ca7052925e34194f3fe2631e4
BELONGS ya.make
@@ -164,7 +165,7 @@ BELONGS ya.make
include/boost/locale/detail/allocator_traits.hpp [4:4]
include/boost/locale/detail/encoding.hpp [4:4]
include/boost/locale/detail/is_supported_char.hpp [4:4]
- include/boost/locale/encoding.hpp [4:4]
+ include/boost/locale/encoding.hpp [5:5]
include/boost/locale/encoding_errors.hpp [4:4]
include/boost/locale/encoding_utf.hpp [5:5]
include/boost/locale/formatting.hpp [5:5]
@@ -174,49 +175,50 @@ BELONGS ya.make
include/boost/locale/time_zone.hpp [4:4]
include/boost/locale/utf8_codecvt.hpp [4:4]
include/boost/locale/util/locale_data.hpp [5:5]
- src/boost/locale/encoding/codepage.cpp [5:5]
- src/boost/locale/encoding/iconv_converter.hpp [4:4]
- src/boost/locale/icu/all_generator.hpp [4:4]
- src/boost/locale/icu/boundary.cpp [5:5]
- src/boost/locale/icu/cdata.hpp [4:4]
- src/boost/locale/icu/codecvt.hpp [4:4]
- src/boost/locale/icu/formatter.hpp [4:4]
- src/boost/locale/icu/icu_backend.hpp [4:4]
- src/boost/locale/icu/uconv.hpp [5:5]
- src/boost/locale/posix/all_generator.hpp [4:4]
- src/boost/locale/posix/codecvt.cpp [5:5]
- src/boost/locale/posix/collate.cpp [4:4]
- src/boost/locale/posix/converter.cpp [4:4]
- src/boost/locale/posix/numeric.cpp [4:4]
- src/boost/locale/posix/posix_backend.hpp [4:4]
- src/boost/locale/shared/date_time.cpp [5:5]
- src/boost/locale/shared/formatting.cpp [4:4]
- src/boost/locale/shared/iconv_codecvt.hpp [4:4]
- src/boost/locale/shared/ids.cpp [5:5]
- src/boost/locale/shared/ios_prop.hpp [5:5]
- src/boost/locale/shared/message.hpp [4:4]
- src/boost/locale/shared/std_collate_adapter.hpp [4:4]
- src/boost/locale/std/codecvt.cpp [4:4]
- src/boost/locale/std/collate.cpp [4:4]
- src/boost/locale/std/converter.cpp [4:4]
- src/boost/locale/std/numeric.cpp [4:4]
- src/boost/locale/std/std_backend.hpp [4:4]
- src/boost/locale/util/codecvt_converter.cpp [5:5]
- src/boost/locale/util/default_locale.cpp [4:4]
- src/boost/locale/util/encoding.cpp [5:5]
- src/boost/locale/util/encoding.hpp [5:5]
- src/boost/locale/util/foreach_char.hpp [4:4]
- src/boost/locale/util/gregorian.hpp [4:4]
- src/boost/locale/util/iconv.hpp [4:4]
- src/boost/locale/util/info.cpp [5:5]
- src/boost/locale/util/locale_data.cpp [5:5]
- src/boost/locale/util/make_std_unique.hpp [4:4]
- src/boost/locale/win32/all_generator.hpp [4:4]
- src/boost/locale/win32/collate.cpp [4:4]
- src/boost/locale/win32/converter.cpp [4:4]
- src/boost/locale/win32/lcid.cpp [4:4]
- src/boost/locale/win32/numeric.cpp [4:4]
- src/boost/locale/win32/win_backend.hpp [4:4]
+ src/encoding/codepage.cpp [5:5]
+ src/encoding/iconv_converter.hpp [4:4]
+ src/icu/all_generator.hpp [4:4]
+ src/icu/boundary.cpp [5:5]
+ src/icu/cdata.hpp [4:4]
+ src/icu/codecvt.hpp [4:4]
+ src/icu/formatter.hpp [5:5]
+ src/icu/icu_backend.hpp [4:4]
+ src/icu/uconv.hpp [5:5]
+ src/posix/all_generator.hpp [4:4]
+ src/posix/codecvt.cpp [5:5]
+ src/posix/collate.cpp [4:4]
+ src/posix/converter.cpp [4:4]
+ src/posix/numeric.cpp [4:4]
+ src/posix/posix_backend.hpp [4:4]
+ src/shared/date_time.cpp [5:5]
+ src/shared/formatting.cpp [4:4]
+ src/shared/iconv_codecvt.hpp [4:4]
+ src/shared/ids.cpp [5:5]
+ src/shared/ios_prop.hpp [5:5]
+ src/shared/message.hpp [4:4]
+ src/shared/std_collate_adapter.hpp [4:4]
+ src/std/codecvt.cpp [4:4]
+ src/std/collate.cpp [4:4]
+ src/std/converter.cpp [4:4]
+ src/std/numeric.cpp [4:4]
+ src/std/std_backend.hpp [4:4]
+ src/util/codecvt_converter.cpp [5:5]
+ src/util/default_locale.cpp [4:4]
+ src/util/encoding.cpp [5:5]
+ src/util/encoding.hpp [5:5]
+ src/util/foreach_char.hpp [4:4]
+ src/util/gregorian.hpp [4:4]
+ src/util/iconv.hpp [4:4]
+ src/util/info.cpp [5:5]
+ src/util/locale_data.cpp [5:5]
+ src/util/make_std_unique.hpp [4:4]
+ src/util/numeric.hpp [4:4]
+ src/win32/all_generator.hpp [4:4]
+ src/win32/collate.cpp [4:4]
+ src/win32/converter.cpp [4:4]
+ src/win32/lcid.cpp [4:4]
+ src/win32/numeric.cpp [4:4]
+ src/win32/win_backend.hpp [4:4]
KEEP BSL-1.0 e9df2954141aa96551bf39192c39d2fe
BELONGS ya.make
@@ -237,40 +239,39 @@ BELONGS ya.make
include/boost/locale/detail/facet_id.hpp [4:5]
include/boost/locale/format.hpp [5:6]
include/boost/locale/generator.hpp [4:5]
- include/boost/locale/gnu_gettext.hpp [4:5]
+ include/boost/locale/gnu_gettext.hpp [5:6]
include/boost/locale/hold_ptr.hpp [4:5]
include/boost/locale/localization_backend.hpp [4:5]
include/boost/locale/utf.hpp [4:5]
include/boost/locale/util.hpp [5:6]
include/boost/locale/util/string.hpp [4:5]
- src/boost/locale/encoding/uconv_converter.hpp [4:5]
- src/boost/locale/encoding/wconv_converter.hpp [4:5]
- src/boost/locale/icu/codecvt.cpp [5:6]
- src/boost/locale/icu/collator.cpp [4:5]
- src/boost/locale/icu/conversion.cpp [5:6]
- src/boost/locale/icu/date_time.cpp [5:6]
- src/boost/locale/icu/formatter.cpp [5:6]
- src/boost/locale/icu/formatters_cache.cpp [5:6]
- src/boost/locale/icu/formatters_cache.hpp [5:6]
- src/boost/locale/icu/icu_backend.cpp [5:6]
- src/boost/locale/icu/icu_util.hpp [5:6]
- src/boost/locale/icu/numeric.cpp [4:5]
- src/boost/locale/icu/time_zone.cpp [4:5]
- src/boost/locale/icu/time_zone.hpp [4:5]
- src/boost/locale/posix/posix_backend.cpp [5:6]
- src/boost/locale/shared/format.cpp [4:5]
- src/boost/locale/shared/generator.cpp [4:5]
- src/boost/locale/shared/iconv_codecvt.cpp [5:6]
- src/boost/locale/shared/localization_backend.cpp [4:5]
- src/boost/locale/shared/message.cpp [5:6]
- src/boost/locale/shared/mo_hash.hpp [4:5]
- src/boost/locale/shared/mo_lambda.cpp [5:6]
- src/boost/locale/shared/mo_lambda.hpp [5:6]
- src/boost/locale/std/all_generator.hpp [4:5]
- src/boost/locale/std/std_backend.cpp [5:6]
- src/boost/locale/util/gregorian.cpp [4:5]
- src/boost/locale/util/numeric.hpp [4:5]
- src/boost/locale/util/timezone.hpp [4:5]
- src/boost/locale/win32/api.hpp [4:5]
- src/boost/locale/win32/lcid.hpp [4:5]
- src/boost/locale/win32/win_backend.cpp [5:6]
+ src/encoding/uconv_converter.hpp [4:5]
+ src/encoding/wconv_converter.hpp [4:5]
+ src/icu/codecvt.cpp [5:6]
+ src/icu/collator.cpp [5:6]
+ src/icu/conversion.cpp [5:6]
+ src/icu/date_time.cpp [5:6]
+ src/icu/formatter.cpp [5:6]
+ src/icu/formatters_cache.cpp [5:6]
+ src/icu/formatters_cache.hpp [5:6]
+ src/icu/icu_backend.cpp [5:6]
+ src/icu/icu_util.hpp [5:6]
+ src/icu/numeric.cpp [5:6]
+ src/icu/time_zone.hpp [5:6]
+ src/posix/posix_backend.cpp [5:6]
+ src/shared/format.cpp [5:6]
+ src/shared/generator.cpp [5:6]
+ src/shared/iconv_codecvt.cpp [5:6]
+ src/shared/localization_backend.cpp [4:5]
+ src/shared/message.cpp [5:6]
+ src/shared/mo_hash.hpp [4:5]
+ src/shared/mo_lambda.cpp [5:6]
+ src/shared/mo_lambda.hpp [5:6]
+ src/std/all_generator.hpp [4:5]
+ src/std/std_backend.cpp [5:6]
+ src/util/gregorian.cpp [4:5]
+ src/util/numeric_conversion.hpp [4:5]
+ src/util/timezone.hpp [4:5]
+ src/win32/api.hpp [4:5]
+ src/win32/lcid.hpp [4:5]
+ src/win32/win_backend.cpp [5:6]
diff --git a/contrib/restricted/boost/locale/.yandex_meta/licenses.list.txt b/contrib/restricted/boost/locale/.yandex_meta/licenses.list.txt
index 2769441dcd4..dcd90b21aef 100644
--- a/contrib/restricted/boost/locale/.yandex_meta/licenses.list.txt
+++ b/contrib/restricted/boost/locale/.yandex_meta/licenses.list.txt
@@ -62,7 +62,12 @@ DEALINGS IN THE SOFTWARE.
====================COPYRIGHT====================
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
-// Copyright (c) 2021-2023 Alexander Grund
+// Copyright (c) 2021-2024 Alexander Grund
+
+
+====================COPYRIGHT====================
+// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
+// Copyright (c) 2021-2025 Alexander Grund
====================COPYRIGHT====================
@@ -81,8 +86,18 @@ DEALINGS IN THE SOFTWARE.
====================COPYRIGHT====================
+// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
+// Copyright (c) 2023-2024 Alexander Grund
+
+
+====================COPYRIGHT====================
+// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
+// Copyright (c) 2025 Alexander Grund
+
+
+====================COPYRIGHT====================
// Copyright (c) 2009-2015 Artyom Beilis (Tonkikh)
-// Copyright (c) 2021-2023 Alexander Grund
+// Copyright (c) 2021-2025 Alexander Grund
====================COPYRIGHT====================
@@ -95,6 +110,10 @@ DEALINGS IN THE SOFTWARE.
====================COPYRIGHT====================
+// Copyright (c) 2022-2025 Alexander Grund
+
+
+====================COPYRIGHT====================
// Copyright (c) 2023 Alexander Grund
@@ -103,4 +122,12 @@ DEALINGS IN THE SOFTWARE.
====================COPYRIGHT====================
+// Copyright (c) 2023-2025 Alexander Grund
+
+
+====================COPYRIGHT====================
// Copyright (c) 2024 Alexander Grund
+
+
+====================COPYRIGHT====================
+// Copyright (c) 2024-2025 Alexander Grund
diff --git a/contrib/restricted/boost/locale/README.md b/contrib/restricted/boost/locale/README.md
index ea18e02d993..127384b09bb 100644
--- a/contrib/restricted/boost/locale/README.md
+++ b/contrib/restricted/boost/locale/README.md
@@ -35,9 +35,11 @@ Sacrificing some less important features, Boost.Locale becomes less powerful but
Distributed under the [Boost Software License, Version 1.0](https://www.boost.org/LICENSE_1_0.txt).
-### Properties
+### Properties / Requirements
* C++11
+* ICU 4.8.1 or newer for full feature support.
+ ICU 50.1 is not supported, please use a newer version.
* Formatted with clang-format, see [`tools/format_sources.sh`](https://github.com/boostorg/locale/blob/develop/tools/format_sources.sh)
### Build Status
diff --git a/contrib/restricted/boost/locale/include/boost/locale/boundary/boundary_point.hpp b/contrib/restricted/boost/locale/include/boost/locale/boundary/boundary_point.hpp
index 370dd5f816b..0743347cc3f 100644
--- a/contrib/restricted/boost/locale/include/boost/locale/boundary/boundary_point.hpp
+++ b/contrib/restricted/boost/locale/include/boost/locale/boundary/boundary_point.hpp
@@ -100,7 +100,7 @@ namespace boost { namespace locale { namespace boundary {
typedef boundary_point<std::string::const_iterator> sboundary_point; ///< convenience typedef
typedef boundary_point<std::wstring::const_iterator> wsboundary_point; ///< convenience typedef
-#ifndef BOOST_LOCALE_NO_CXX20_STRING8
+#ifdef __cpp_lib_char8_t
typedef boundary_point<std::u8string::const_iterator> u8sboundary_point; ///< convenience typedef
#endif
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
diff --git a/contrib/restricted/boost/locale/include/boost/locale/boundary/index.hpp b/contrib/restricted/boost/locale/include/boost/locale/boundary/index.hpp
index 92b7613fd3b..249ef877f2d 100644
--- a/contrib/restricted/boost/locale/include/boost/locale/boundary/index.hpp
+++ b/contrib/restricted/boost/locale/include/boost/locale/boundary/index.hpp
@@ -868,7 +868,7 @@ namespace boost { namespace locale { namespace boundary {
typedef segment_index<std::string::const_iterator> ssegment_index; ///< convenience typedef
typedef segment_index<std::wstring::const_iterator> wssegment_index; ///< convenience typedef
-#ifndef BOOST_LOCALE_NO_CXX20_STRING8
+#ifdef __cpp_lib_char8_t
typedef segment_index<std::u8string::const_iterator> u8ssegment_index; ///< convenience typedef
#endif
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
@@ -892,7 +892,7 @@ namespace boost { namespace locale { namespace boundary {
typedef boundary_point_index<std::string::const_iterator> sboundary_point_index; ///< convenience typedef
typedef boundary_point_index<std::wstring::const_iterator> wsboundary_point_index; ///< convenience typedef
-#ifndef BOOST_LOCALE_NO_CXX20_STRING8
+#ifdef __cpp_lib_char8_t
typedef boundary_point_index<std::u8string::const_iterator> u8sboundary_point_index; ///< convenience typedef
#endif
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
diff --git a/contrib/restricted/boost/locale/include/boost/locale/boundary/segment.hpp b/contrib/restricted/boost/locale/include/boost/locale/boundary/segment.hpp
index 24e129dcf1b..84243abea16 100644
--- a/contrib/restricted/boost/locale/include/boost/locale/boundary/segment.hpp
+++ b/contrib/restricted/boost/locale/include/boost/locale/boundary/segment.hpp
@@ -340,7 +340,7 @@ namespace boost { namespace locale { namespace boundary {
typedef segment<std::string::const_iterator> ssegment; ///< convenience typedef
typedef segment<std::wstring::const_iterator> wssegment; ///< convenience typedef
-#ifndef BOOST_LOCALE_NO_CXX20_STRING8
+#ifdef __cpp_lib_char8_t
typedef segment<std::u8string::const_iterator> u8ssegment; ///< convenience typedef
#endif
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
diff --git a/contrib/restricted/boost/locale/include/boost/locale/config.hpp b/contrib/restricted/boost/locale/include/boost/locale/config.hpp
index 1c69c92dc43..2064810d193 100644
--- a/contrib/restricted/boost/locale/include/boost/locale/config.hpp
+++ b/contrib/restricted/boost/locale/include/boost/locale/config.hpp
@@ -89,11 +89,6 @@
# define BOOST_LOCALE_NO_SANITIZE(what)
#endif
-#if !defined(__cpp_lib_char8_t) || BOOST_WORKAROUND(BOOST_CLANG_VERSION, < 150000)
-// No std::basic_string<char8_t> or bug in Clang: https://github.com/llvm/llvm-project/issues/55560
-# define BOOST_LOCALE_NO_CXX20_STRING8
-#endif
-
/// \endcond
#endif // boost/locale/config.hpp
diff --git a/contrib/restricted/boost/locale/include/boost/locale/detail/any_string.hpp b/contrib/restricted/boost/locale/include/boost/locale/detail/any_string.hpp
index c0cc7ffb3e0..473d07e7db1 100644
--- a/contrib/restricted/boost/locale/include/boost/locale/detail/any_string.hpp
+++ b/contrib/restricted/boost/locale/include/boost/locale/detail/any_string.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2023 Alexander Grund
+// Copyright (c) 2023-2025 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
@@ -9,7 +9,7 @@
#include <boost/locale/config.hpp>
#include <boost/assert.hpp>
-#include <boost/utility/string_view.hpp>
+#include <boost/core/detail/string_view.hpp>
#include <memory>
#include <stdexcept>
#include <string>
@@ -31,7 +31,7 @@ namespace boost { namespace locale { namespace detail {
};
template<typename Char>
struct BOOST_SYMBOL_VISIBLE impl : base {
- explicit impl(const boost::basic_string_view<Char> value) : s(value) {}
+ explicit impl(const core::basic_string_view<Char> value) : s(value) {}
impl* clone() const override { return new impl(*this); }
std::basic_string<Char> s;
};
@@ -49,7 +49,7 @@ namespace boost { namespace locale { namespace detail {
}
template<typename Char>
- void set(const boost::basic_string_view<Char> s)
+ void set(const core::basic_string_view<Char> s)
{
BOOST_ASSERT(!s.empty());
s_.reset(new impl<Char>(s));
diff --git a/contrib/restricted/boost/locale/include/boost/locale/detail/encoding.hpp b/contrib/restricted/boost/locale/include/boost/locale/detail/encoding.hpp
index ee669349a19..2e37c308a36 100644
--- a/contrib/restricted/boost/locale/include/boost/locale/detail/encoding.hpp
+++ b/contrib/restricted/boost/locale/include/boost/locale/detail/encoding.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2022-2023 Alexander Grund
+// Copyright (c) 2022-2025 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
@@ -9,7 +9,7 @@
#include <boost/locale/config.hpp>
#include <boost/locale/encoding_errors.hpp>
-#include <boost/utility/string_view.hpp>
+#include <boost/core/detail/string_view.hpp>
#include <memory>
#include <string>
@@ -24,7 +24,7 @@ namespace boost { namespace locale { namespace conv { namespace detail {
virtual ~charset_converter() = default;
virtual string_type convert(const CharIn* begin, const CharIn* end) = 0;
- string_type convert(const boost::basic_string_view<CharIn>& text)
+ string_type convert(const core::basic_string_view<CharIn> text)
{
return convert(text.data(), text.data() + text.length());
}
diff --git a/contrib/restricted/boost/locale/include/boost/locale/encoding.hpp b/contrib/restricted/boost/locale/include/boost/locale/encoding.hpp
index d0e1d9d07e9..abc68bacdf4 100644
--- a/contrib/restricted/boost/locale/include/boost/locale/encoding.hpp
+++ b/contrib/restricted/boost/locale/include/boost/locale/encoding.hpp
@@ -1,5 +1,6 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
+// Copyright (c) 2025 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
@@ -240,11 +241,11 @@ namespace boost { namespace locale {
/// Convert \a text to UTF
///
/// \throws conversion_error: Conversion failed
- string_type convert(const boost::string_view& text) const { return impl_->convert(text); }
+ string_type convert(const core::string_view text) const { return impl_->convert(text); }
/// Convert \a text to UTF
///
/// \throws conversion_error: Conversion failed
- string_type operator()(const boost::string_view& text) const { return convert(text); }
+ string_type operator()(const core::string_view text) const { return convert(text); }
};
/// Converter class to decode an UTF string and encode it using a local encoding
@@ -254,7 +255,7 @@ namespace boost { namespace locale {
public:
using char_type = CharType;
- using stringview_type = boost::basic_string_view<CharType>;
+ using stringview_type = core::basic_string_view<CharType>;
/// Create an instance to convert UTF text to text encoded with \a charset according to policy \a how
///
@@ -298,11 +299,11 @@ namespace boost { namespace locale {
/// Convert \a text
///
/// \throws conversion_error: Conversion failed
- std::string convert(const boost::string_view& text) const { return impl_->convert(text); }
+ std::string convert(const core::string_view text) const { return impl_->convert(text); }
/// Convert \a text
///
/// \throws conversion_error: Conversion failed
- std::string operator()(const boost::string_view& text) const { return convert(text); }
+ std::string operator()(const core::string_view text) const { return convert(text); }
};
} // namespace conv
}} // namespace boost::locale
diff --git a/contrib/restricted/boost/locale/include/boost/locale/format.hpp b/contrib/restricted/boost/locale/include/boost/locale/format.hpp
index 6adb844031d..68020a4c35a 100644
--- a/contrib/restricted/boost/locale/include/boost/locale/format.hpp
+++ b/contrib/restricted/boost/locale/include/boost/locale/format.hpp
@@ -1,6 +1,6 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
-// Copyright (c) 2021-2023 Alexander Grund
+// Copyright (c) 2021-2024 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
@@ -418,7 +418,7 @@ namespace boost { namespace locale {
typedef basic_format<char> format;
/// Definition of wchar_t based format
typedef basic_format<wchar_t> wformat;
-#ifndef BOOST_LOCALE_NO_CXX20_STRING8
+#ifdef __cpp_lib_char8_t
/// Definition of char8_t based format
typedef basic_format<char8_t> u8format;
#endif
diff --git a/contrib/restricted/boost/locale/include/boost/locale/formatting.hpp b/contrib/restricted/boost/locale/include/boost/locale/formatting.hpp
index e3c8619e489..1844398ad7a 100644
--- a/contrib/restricted/boost/locale/include/boost/locale/formatting.hpp
+++ b/contrib/restricted/boost/locale/include/boost/locale/formatting.hpp
@@ -122,7 +122,7 @@ namespace boost { namespace locale {
/// Set time zone for formatting dates and time
void time_zone(const std::string&);
/// Get time zone for formatting dates and time
- std::string time_zone() const;
+ const std::string& time_zone() const;
/// Set date/time pattern (strftime like)
template<typename CharType>
diff --git a/contrib/restricted/boost/locale/include/boost/locale/generator.hpp b/contrib/restricted/boost/locale/include/boost/locale/generator.hpp
index 675aa604b68..119e65659fc 100644
--- a/contrib/restricted/boost/locale/include/boost/locale/generator.hpp
+++ b/contrib/restricted/boost/locale/include/boost/locale/generator.hpp
@@ -190,9 +190,6 @@ namespace locale {
private:
void set_all_options(localization_backend& backend, const std::string& id) const;
- generator(const generator&);
- void operator=(const generator&);
-
struct data;
hold_ptr<data> d;
};
diff --git a/contrib/restricted/boost/locale/include/boost/locale/gnu_gettext.hpp b/contrib/restricted/boost/locale/include/boost/locale/gnu_gettext.hpp
index aff76b1cdca..6612e84ffd3 100644
--- a/contrib/restricted/boost/locale/include/boost/locale/gnu_gettext.hpp
+++ b/contrib/restricted/boost/locale/include/boost/locale/gnu_gettext.hpp
@@ -1,11 +1,12 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
+// Copyright (c) 2022-2024 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
-#ifndef BOOST_LOCLAE_GNU_GETTEXT_HPP
-#define BOOST_LOCLAE_GNU_GETTEXT_HPP
+#ifndef BOOST_LOCALE_GNU_GETTEXT_HPP
+#define BOOST_LOCALE_GNU_GETTEXT_HPP
#include <boost/locale/detail/is_supported_char.hpp>
#include <boost/locale/message.hpp>
diff --git a/contrib/restricted/boost/locale/include/boost/locale/message.hpp b/contrib/restricted/boost/locale/include/boost/locale/message.hpp
index 88a4aefbf11..fafff385167 100644
--- a/contrib/restricted/boost/locale/include/boost/locale/message.hpp
+++ b/contrib/restricted/boost/locale/include/boost/locale/message.hpp
@@ -341,7 +341,7 @@ namespace boost { namespace locale {
typedef basic_message<char> message;
/// Convenience typedef for wchar_t
typedef basic_message<wchar_t> wmessage;
-#ifndef BOOST_LOCALE_NO_CXX20_STRING8
+#ifdef __cpp_lib_char8_t
/// Convenience typedef for char8_t
typedef basic_message<char8_t> u8message;
#endif
diff --git a/contrib/restricted/boost/locale/include/boost/locale/util/locale_data.hpp b/contrib/restricted/boost/locale/include/boost/locale/util/locale_data.hpp
index 397c404d604..cbd7f696f52 100644
--- a/contrib/restricted/boost/locale/include/boost/locale/util/locale_data.hpp
+++ b/contrib/restricted/boost/locale/include/boost/locale/util/locale_data.hpp
@@ -1,6 +1,6 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
-// Copyright (c) 2023 Alexander Grund
+// Copyright (c) 2023-2024 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
@@ -21,6 +21,7 @@ namespace boost { namespace locale { namespace util {
/// Holder and parser for locale names/identifiers
class BOOST_LOCALE_DECL locale_data {
std::string language_;
+ std::string script_;
std::string country_;
std::string encoding_;
std::string variant_;
@@ -36,6 +37,8 @@ namespace boost { namespace locale { namespace util {
/// Return language (usually 2 lowercase letters, i.e. ISO-639 or 'C')
const std::string& language() const { return language_; }
+ /// Return the ISO-15924 abbreviation script code if present
+ const std::string& script() const { return script_; }
/// Return country (usually 2 uppercase letters, i.e. ISO-3166)
const std::string& country() const { return country_; }
/// Return encoding/codeset, e.g. ISO8859-1 or UTF-8
@@ -48,12 +51,13 @@ namespace boost { namespace locale { namespace util {
/// Return iff the encoding is UTF-8
bool is_utf8() const { return utf8_; }
- /// Parse a locale identifier of the form `[language[_territory][.codeset][@modifier]]`
+ /// Parse a locale identifier of the form `[language[_script][_territory][.codeset][@modifier]]`
///
/// Allows a dash as the delimiter: `[language-territory]`
/// Return true if the identifier is valid:
/// - `language` is given and consists of ASCII letters
- /// - `territory`, if given, consists of ASCII letters
+ /// - `script` is only considered if it consists of exactly 4 ASCII letters
+ /// - `territory`, if given, consists of ASCII letters (usually ISO-3166)
/// - Any field started by a delimiter (`_`, `-`, `.`, `@`) is not empty
/// Otherwise parsing is aborted. Valid values already parsed stay set, other are defaulted.
bool parse(const std::string& locale_name);
@@ -65,6 +69,7 @@ namespace boost { namespace locale { namespace util {
private:
void reset();
bool parse_from_lang(const std::string& input);
+ bool parse_from_script(const std::string& input);
bool parse_from_country(const std::string& input);
bool parse_from_encoding(const std::string& input);
bool parse_from_variant(const std::string& input);
diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/time_zone.cpp b/contrib/restricted/boost/locale/src/boost/locale/icu/time_zone.cpp
deleted file mode 100644
index 2f11862a59a..00000000000
--- a/contrib/restricted/boost/locale/src/boost/locale/icu/time_zone.cpp
+++ /dev/null
@@ -1,212 +0,0 @@
-//
-// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
-//
-// Distributed under the Boost Software License, Version 1.0.
-// https://www.boost.org/LICENSE_1_0.txt
-
-#include "boost/locale/icu/time_zone.hpp"
-#include <boost/locale/hold_ptr.hpp>
-#include "boost/locale/icu/icu_util.hpp"
-#include <boost/predef/os.h>
-
-//
-// Bug - when ICU tries to find a file that is equivalent to /etc/localtime it finds /usr/share/zoneinfo/localtime
-// that is just a symbolic link to /etc/localtime.
-//
-// It started in 4.0 and was fixed in version 4.6, also the fix was backported to the 4.4 branch so it should be
-// available from 4.4.3... So we test if the workaround is required
-//
-// It is also relevant only for Linux, BSD and Apple (as I see in ICU code)
-//
-
-#if BOOST_LOCALE_ICU_VERSION >= 400 && BOOST_LOCALE_ICU_VERSION <= 406 \
- && (BOOST_LOCALE_ICU_VERSION != 404 || U_ICU_VERSION_PATCHLEVEL_NUM >= 3)
-# if BOOST_OS_LINUX || BOOST_OS_BSD_FREE || defined(__APPLE__)
-# define BOOST_LOCALE_WORKAROUND_ICU_BUG
-# endif
-#endif
-
-#ifdef BOOST_LOCALE_WORKAROUND_ICU_BUG
-# include <cstring>
-# include <dirent.h>
-# include <fstream>
-# include <memory>
-# include <pthread.h>
-# include <sys/stat.h>
-# include <sys/types.h>
-# include <unistd.h>
-#endif
-
-namespace boost { namespace locale { namespace impl_icu {
-
-#ifndef BOOST_LOCALE_WORKAROUND_ICU_BUG
-
- // This is normal behavior
-
- icu::TimeZone* get_time_zone(const std::string& time_zone)
- {
- if(time_zone.empty())
- return icu::TimeZone::createDefault();
- else
- return icu::TimeZone::createTimeZone(time_zone.c_str());
- }
-
-#else
-
- // This is a workaround for an ICU timezone detection bug.
- // It is \b very ICU specific and should not be used
- // in general. It is also designed to work only on
- // specific patforms: Linux, BSD and Apple, where this bug may actually
- // occur
- namespace {
-
- // Under BSD, Linux and Mac OS X dirent has normal size
- // so no issues with readdir_r
-
- class directory {
- public:
- directory(const char* name) : d(0), read_result(0)
- {
- d = opendir(name);
- if(!d)
- return;
- }
- ~directory()
- {
- if(d)
- closedir(d);
- }
- bool is_open() { return d; }
- const char* next()
- {
- if(d && readdir_r(d, &de, &read_result) == 0 && read_result != 0)
- return de.d_name;
- return nullptr;
- }
-
- private:
- DIR* d;
- struct dirent de;
- struct dirent* read_result;
- };
-
- bool files_equal(const std::string& left, const std::string& right)
- {
- char l[256], r[256];
- std::ifstream ls(left);
- if(!ls)
- return false;
- std::ifstream rs(right);
- if(!rs)
- return false;
- do {
- ls.read(l, sizeof(l));
- rs.read(r, sizeof(r));
- size_t n;
- if((n = ls.gcount()) != size_t(rs.gcount()))
- return false;
- if(memcmp(l, r, n) != 0)
- return false;
- } while(!ls.eof() || !rs.eof());
- if(bool(ls.eof()) != bool(rs.eof()))
- return false;
- return true;
- }
-
- std::string find_file_in(const std::string& ref, size_t size, const std::string& dir)
- {
- directory d(dir.c_str());
- if(!d.is_open())
- return std::string();
-
- const char* name = nullptr;
- while((name = d.next()) != 0) {
- std::string file_name = name;
- if(file_name == "." || file_name == ".." || file_name == "posixrules" || file_name == "localtime")
- continue;
- struct stat st;
- std::string path = dir + "/" + file_name;
- if(stat(path.c_str(), &st) == 0) {
- if(S_ISDIR(st.st_mode)) {
- std::string res = find_file_in(ref, size, path);
- if(!res.empty())
- return file_name + "/" + res;
- } else {
- if(size_t(st.st_size) == size && files_equal(path, ref))
- return file_name;
- }
- }
- }
- return std::string();
- }
-
- // This actually emulates ICU's search
- // algorithm... just it ignores localtime
- std::string detect_correct_time_zone()
- {
- const char* tz_dir = "/usr/share/zoneinfo";
- const char* tz_file = "/etc/localtime";
-
- struct stat st;
- if(::stat(tz_file, &st) != 0)
- return std::string();
- size_t size = st.st_size;
- std::string r = find_file_in(tz_file, size, tz_dir);
- if(r.empty())
- return r;
- if(r.compare(0, 6, "posix/") == 0 || r.compare(0, 6, "right/", 6) == 0)
- return r.substr(6);
- return r;
- }
-
- // Using pthread as:
- // - This bug is relevant for only Linux, BSD, Mac OS X and
- // pthreads are native threading API
- // - The dependency on boost.thread may be removed when using
- // more recent ICU versions (so TLS would not be needed)
- //
- // This the dependency on Boost.Thread is eliminated
-
- pthread_once_t init_tz = PTHREAD_ONCE_INIT;
- std::string default_time_zone_name;
-
- extern "C" {
- static void init_tz_proc()
- {
- try {
- default_time_zone_name = detect_correct_time_zone();
- } catch(...) {
- }
- }
- }
-
- std::string get_time_zone_name()
- {
- pthread_once(&init_tz, init_tz_proc);
- return default_time_zone_name;
- }
-
- } // namespace
-
- icu::TimeZone* get_time_zone(const std::string& time_zone)
- {
- if(!time_zone.empty())
- return icu::TimeZone::createTimeZone(time_zone.c_str());
- hold_ptr<icu::TimeZone> tz(icu::TimeZone::createDefault());
- icu::UnicodeString id;
- tz->getID(id);
- // Check if there is a bug?
- if(id != icu::UnicodeString("localtime"))
- return tz.release();
- // Now let's deal with the bug and run the fixed
- // search loop as that of ICU
- std::string real_id = get_time_zone_name();
- if(real_id.empty()) {
- // if we failed fallback to ICU's time zone
- return tz.release();
- }
- return icu::TimeZone::createTimeZone(real_id.c_str());
- }
-#endif // bug workaround
-
-}}} // namespace boost::locale::impl_icu
diff --git a/contrib/restricted/boost/locale/src/boost/locale/encoding/codepage.cpp b/contrib/restricted/boost/locale/src/encoding/codepage.cpp
index 0ac9659ab56..814a8035df2 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/encoding/codepage.cpp
+++ b/contrib/restricted/boost/locale/src/encoding/codepage.cpp
@@ -1,24 +1,24 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
-// Copyright (c) 2022-2023 Alexander Grund
+// Copyright (c) 2022-2025 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/locale/encoding.hpp>
-#include "boost/locale/util/make_std_unique.hpp"
+#include "../util/make_std_unique.hpp"
#if BOOST_LOCALE_USE_WIN32_API
# define BOOST_LOCALE_WITH_WCONV
#endif
#ifdef BOOST_LOCALE_WITH_ICONV
-# include "boost/locale/encoding/iconv_converter.hpp"
+# include "iconv_converter.hpp"
#endif
#ifdef BOOST_LOCALE_WITH_ICU
-# include "boost/locale/encoding/uconv_converter.hpp"
+# include "uconv_converter.hpp"
#endif
#ifdef BOOST_LOCALE_WITH_WCONV
-# include "boost/locale/encoding/wconv_converter.hpp"
+# include "wconv_converter.hpp"
#endif
namespace boost { namespace locale { namespace conv {
@@ -224,7 +224,7 @@ namespace boost { namespace locale { namespace conv {
BOOST_LOCALE_INSTANTIATE(char);
BOOST_LOCALE_INSTANTIATE_NO_CHAR(wchar_t);
-#ifndef BOOST_LOCALE_NO_CXX20_STRING8
+#ifdef __cpp_lib_char8_t
BOOST_LOCALE_INSTANTIATE_NO_CHAR(char8_t);
#endif
diff --git a/contrib/restricted/boost/locale/src/boost/locale/encoding/iconv_converter.hpp b/contrib/restricted/boost/locale/src/encoding/iconv_converter.hpp
index 2877dbca5e5..8d26287b564 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/encoding/iconv_converter.hpp
+++ b/contrib/restricted/boost/locale/src/encoding/iconv_converter.hpp
@@ -8,8 +8,8 @@
#define BOOST_LOCALE_IMPL_ICONV_CODEPAGE_HPP
#include <boost/locale/encoding.hpp>
-#include "boost/locale/util/encoding.hpp"
-#include "boost/locale/util/iconv.hpp"
+#include "../util/encoding.hpp"
+#include "../util/iconv.hpp"
#include <boost/assert.hpp>
#include <cerrno>
#include <string>
diff --git a/contrib/restricted/boost/locale/src/boost/locale/encoding/uconv_converter.hpp b/contrib/restricted/boost/locale/src/encoding/uconv_converter.hpp
index 53a14055322..ae8913764ae 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/encoding/uconv_converter.hpp
+++ b/contrib/restricted/boost/locale/src/encoding/uconv_converter.hpp
@@ -8,8 +8,8 @@
#define BOOST_LOCALE_IMPL_UCONV_CODEPAGE_HPP
#include <boost/locale/encoding.hpp>
#include <boost/locale/hold_ptr.hpp>
-#include "boost/locale/icu/icu_util.hpp"
-#include "boost/locale/icu/uconv.hpp"
+#include "../icu/icu_util.hpp"
+#include "../icu/uconv.hpp"
#include <unicode/ucnv.h>
#include <unicode/ucnv_err.h>
diff --git a/contrib/restricted/boost/locale/src/boost/locale/encoding/wconv_converter.hpp b/contrib/restricted/boost/locale/src/encoding/wconv_converter.hpp
index 32cd78e21a9..e29b562edfa 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/encoding/wconv_converter.hpp
+++ b/contrib/restricted/boost/locale/src/encoding/wconv_converter.hpp
@@ -11,7 +11,7 @@
# define NOMINMAX
#endif
#include <boost/locale/encoding.hpp>
-#include "boost/locale/util/encoding.hpp"
+#include "../util/encoding.hpp"
#include <algorithm>
#include <cstddef>
#include <cstring>
diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/all_generator.hpp b/contrib/restricted/boost/locale/src/icu/all_generator.hpp
index b2f8c34a33b..b2f8c34a33b 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/icu/all_generator.hpp
+++ b/contrib/restricted/boost/locale/src/icu/all_generator.hpp
diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/boundary.cpp b/contrib/restricted/boost/locale/src/icu/boundary.cpp
index 4adada4f428..339cab50914 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/icu/boundary.cpp
+++ b/contrib/restricted/boost/locale/src/icu/boundary.cpp
@@ -1,17 +1,17 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
-// Copyright (c) 2021-2022 Alexander Grund
+// Copyright (c) 2021-2025 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/locale/boundary.hpp>
#include <boost/locale/generator.hpp>
-#include "boost/locale/icu/all_generator.hpp"
-#include "boost/locale/icu/cdata.hpp"
-#include "boost/locale/icu/icu_util.hpp"
-#include "boost/locale/icu/uconv.hpp"
-#include "boost/locale/util/encoding.hpp"
+#include "../util/encoding.hpp"
+#include "all_generator.hpp"
+#include "cdata.hpp"
+#include "icu_util.hpp"
+#include "uconv.hpp"
#if BOOST_LOCALE_ICU_VERSION >= 5502
# include <unicode/utext.h>
#endif
diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/cdata.hpp b/contrib/restricted/boost/locale/src/icu/cdata.hpp
index 37ce36888e6..37ce36888e6 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/icu/cdata.hpp
+++ b/contrib/restricted/boost/locale/src/icu/cdata.hpp
diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/codecvt.cpp b/contrib/restricted/boost/locale/src/icu/codecvt.cpp
index cdf958ab58f..3e6e24f7743 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/icu/codecvt.cpp
+++ b/contrib/restricted/boost/locale/src/icu/codecvt.cpp
@@ -1,20 +1,20 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
-// Copyright (c) 2022-2023 Alexander Grund
+// Copyright (c) 2022-2025 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
-#include "boost/locale/icu/codecvt.hpp"
+#include "codecvt.hpp"
#include <boost/locale/encoding.hpp>
#include <boost/locale/encoding_errors.hpp>
#include <boost/locale/hold_ptr.hpp>
#include <boost/locale/util.hpp>
-#include "boost/locale/icu/all_generator.hpp"
-#include "boost/locale/icu/icu_util.hpp"
-#include "boost/locale/icu/uconv.hpp"
-#include "boost/locale/util/encoding.hpp"
-#include "boost/locale/util/make_std_unique.hpp"
+#include "../util/encoding.hpp"
+#include "../util/make_std_unique.hpp"
+#include "all_generator.hpp"
+#include "icu_util.hpp"
+#include "uconv.hpp"
#include <unicode/ucnv.h>
#include <unicode/ucnv_err.h>
diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/codecvt.hpp b/contrib/restricted/boost/locale/src/icu/codecvt.hpp
index f406f7f5335..f406f7f5335 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/icu/codecvt.hpp
+++ b/contrib/restricted/boost/locale/src/icu/codecvt.hpp
diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/collator.cpp b/contrib/restricted/boost/locale/src/icu/collator.cpp
index 72ade74fbb7..43d921d5941 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/icu/collator.cpp
+++ b/contrib/restricted/boost/locale/src/icu/collator.cpp
@@ -1,28 +1,24 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
+// Copyright (c) 2022-2024 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/locale/collator.hpp>
#include <boost/locale/generator.hpp>
-#include "boost/locale/icu/all_generator.hpp"
-#include "boost/locale/icu/cdata.hpp"
-#include "boost/locale/icu/icu_util.hpp"
-#include "boost/locale/icu/uconv.hpp"
-#include "boost/locale/shared/mo_hash.hpp"
-#include "boost/locale/shared/std_collate_adapter.hpp"
+#include "../shared/mo_hash.hpp"
+#include "../shared/std_collate_adapter.hpp"
+#include "all_generator.hpp"
+#include "cdata.hpp"
+#include "icu_util.hpp"
+#include "uconv.hpp"
#include <boost/thread.hpp>
#include <limits>
#include <memory>
#include <unicode/coll.h>
+#include <unicode/stringpiece.h>
#include <vector>
-#if BOOST_LOCALE_ICU_VERSION >= 402
-# define BOOST_LOCALE_WITH_STRINGPIECE 1
-# include <unicode/stringpiece.h>
-#else
-# define BOOST_LOCALE_WITH_STRINGPIECE 0
-#endif
#ifdef BOOST_MSVC
# pragma warning(disable : 4244) // 'argument' : conversion from 'int'
@@ -43,7 +39,6 @@ namespace boost { namespace locale { namespace impl_icu {
return res;
}
-#if BOOST_LOCALE_WITH_STRINGPIECE
int do_utf8_compare(collate_level level,
const char* b1,
const char* e1,
@@ -55,7 +50,6 @@ namespace boost { namespace locale { namespace impl_icu {
icu::StringPiece right(b2, e2 - b2);
return get_collator(level).compareUTF8(left, right, status);
}
-#endif
int do_ustring_compare(collate_level level,
const CharType* b1,
@@ -159,7 +153,6 @@ namespace boost { namespace locale { namespace impl_icu {
bool is_utf8_;
};
-#if BOOST_LOCALE_WITH_STRINGPIECE
template<>
int collate_impl<char>::do_real_compare(collate_level level,
const char* b1,
@@ -173,7 +166,7 @@ namespace boost { namespace locale { namespace impl_icu {
else
return do_ustring_compare(level, b1, e1, b2, e2, status);
}
-#endif
+
std::locale create_collate(const std::locale& in, const cdata& cd, char_facet_t type)
{
switch(type) {
diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/conversion.cpp b/contrib/restricted/boost/locale/src/icu/conversion.cpp
index c619dd94a1e..a7fddb473ab 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/icu/conversion.cpp
+++ b/contrib/restricted/boost/locale/src/icu/conversion.cpp
@@ -1,23 +1,20 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
-// Copyright (c) 2022-2023 Alexander Grund
+// Copyright (c) 2022-2024 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/locale/conversion.hpp>
-#include "boost/locale/icu/all_generator.hpp"
-#include "boost/locale/icu/cdata.hpp"
-#include "boost/locale/icu/icu_util.hpp"
-#include "boost/locale/icu/uconv.hpp"
+#include "all_generator.hpp"
+#include "cdata.hpp"
+#include "icu_util.hpp"
+#include "uconv.hpp"
#include <limits>
#include <unicode/locid.h>
#include <unicode/normlzr.h>
+#include <unicode/ucasemap.h>
#include <unicode/ustring.h>
-#if BOOST_LOCALE_ICU_VERSION >= 308
-# include <unicode/ucasemap.h>
-# define BOOST_LOCALE_WITH_CASEMAP
-#endif
#include <vector>
namespace boost { namespace locale { namespace impl_icu {
@@ -72,7 +69,6 @@ namespace boost { namespace locale { namespace impl_icu {
std::string encoding_;
}; // converter_impl
-#ifdef BOOST_LOCALE_WITH_CASEMAP
template<typename T>
struct get_casemap_size_type;
@@ -193,26 +189,17 @@ namespace boost { namespace locale { namespace impl_icu {
raii_casemap<U8Char> map_;
}; // converter_impl
-#endif // BOOST_LOCALE_WITH_CASEMAP
-
std::locale create_convert(const std::locale& in, const cdata& cd, char_facet_t type)
{
switch(type) {
case char_facet_t::nochar: break;
case char_facet_t::char_f:
-#ifdef BOOST_LOCALE_WITH_CASEMAP
if(cd.is_utf8())
return std::locale(in, new utf8_converter_impl<char>(cd));
-#endif
return std::locale(in, new converter_impl<char>(cd));
case char_facet_t::wchar_f: return std::locale(in, new converter_impl<wchar_t>(cd));
-#ifndef BOOST_LOCALE_NO_CXX20_STRING8
- case char_facet_t::char8_f:
-# if defined(BOOST_LOCALE_WITH_CASEMAP)
- return std::locale(in, new utf8_converter_impl<char8_t>(cd));
-# else
- return std::locale(in, new converter_impl<char8_t>(cd));
-# endif
+#ifdef __cpp_lib_char8_t
+ case char_facet_t::char8_f: return std::locale(in, new utf8_converter_impl<char8_t>(cd));
#elif defined(__cpp_char8_t)
case char_facet_t::char8_f: break;
#endif
diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/date_time.cpp b/contrib/restricted/boost/locale/src/icu/date_time.cpp
index 14e21d9f155..76785ec6ce7 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/icu/date_time.cpp
+++ b/contrib/restricted/boost/locale/src/icu/date_time.cpp
@@ -1,6 +1,6 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
-// Copyright (c) 2021-2022 Alexander Grund
+// Copyright (c) 2021-2024 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
@@ -9,11 +9,11 @@
#include <boost/locale/date_time_facet.hpp>
#include <boost/locale/formatting.hpp>
#include <boost/locale/hold_ptr.hpp>
-#include "boost/locale/icu/all_generator.hpp"
-#include "boost/locale/icu/cdata.hpp"
-#include "boost/locale/icu/icu_util.hpp"
-#include "boost/locale/icu/time_zone.hpp"
-#include "boost/locale/icu/uconv.hpp"
+#include "all_generator.hpp"
+#include "cdata.hpp"
+#include "icu_util.hpp"
+#include "time_zone.hpp"
+#include "uconv.hpp"
#include <boost/thread.hpp>
#include <cmath>
#include <memory>
@@ -67,10 +67,6 @@ namespace boost { namespace locale { namespace impl_icu {
const double rounded_time = std::floor(calendar_->getTime(err) / U_MILLIS_PER_SECOND) * U_MILLIS_PER_SECOND;
calendar_->setTime(rounded_time, err);
check_and_throw_dt(err);
-#if BOOST_LOCALE_ICU_VERSION < 402
- // workaround old/invalid data, it should be 4 in general
- calendar_->setMinimalDaysInFirstWeek(4);
-#endif
encoding_ = dat.encoding();
}
calendar_impl(const calendar_impl& other)
@@ -79,15 +75,9 @@ namespace boost { namespace locale { namespace impl_icu {
encoding_ = other.encoding_;
}
- calendar_impl* clone() const override
- {
- return new calendar_impl(*this);
- }
+ calendar_impl* clone() const override { return new calendar_impl(*this); }
- void set_value(period::marks::period_mark p, int value) override
- {
- calendar_->set(to_icu(p), int32_t(value));
- }
+ void set_value(period::marks::period_mark p, int value) override { calendar_->set(to_icu(p), int32_t(value)); }
int get_value(period::marks::period_mark p, value_type type) const override
{
@@ -202,10 +192,7 @@ namespace boost { namespace locale { namespace impl_icu {
check_and_throw_dt(err);
return diff;
}
- void set_timezone(const std::string& tz) override
- {
- calendar_->adoptTimeZone(get_time_zone(tz));
- }
+ void set_timezone(const std::string& tz) override { calendar_->adoptTimeZone(get_time_zone(tz)); }
std::string get_timezone() const override
{
icu::UnicodeString tz;
diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/formatter.cpp b/contrib/restricted/boost/locale/src/icu/formatter.cpp
index 12cb73632e1..64f8e1e46da 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/icu/formatter.cpp
+++ b/contrib/restricted/boost/locale/src/icu/formatter.cpp
@@ -1,18 +1,22 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
-// Copyright (c) 2021-2023 Alexander Grund
+// Copyright (c) 2021-2024 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
-#include "boost/locale/icu/formatter.hpp"
+#include "formatter.hpp"
#include <boost/locale/formatting.hpp>
#include <boost/locale/info.hpp>
-#include "boost/locale/icu/formatters_cache.hpp"
-#include "boost/locale/icu/icu_util.hpp"
-#include "boost/locale/icu/time_zone.hpp"
-#include "boost/locale/icu/uconv.hpp"
-#include "boost/locale/util/foreach_char.hpp"
+#include "../util/foreach_char.hpp"
+#include "../util/numeric_conversion.hpp"
+#include "formatters_cache.hpp"
+#include "icu_util.hpp"
+#include "time_zone.hpp"
+#include "uconv.hpp"
+#include <boost/assert.hpp>
+#include <boost/charconv/limits.hpp>
+#include <boost/charconv/to_chars.hpp>
#include <limits>
#include <memory>
#ifdef BOOST_MSVC
@@ -20,7 +24,6 @@
# pragma warning(disable : 4251) // "identifier" : class "type" needs to have dll-interface...
#endif
#include <unicode/datefmt.h>
-#include <unicode/decimfmt.h>
#include <unicode/numfmt.h>
#include <unicode/rbnf.h>
#include <unicode/smpdtfmt.h>
@@ -54,41 +57,72 @@ namespace boost { namespace locale { namespace impl_icu {
public:
typedef std::basic_string<CharType> string_type;
- number_format(icu::NumberFormat& fmt, std::string codepage) : cvt_(codepage), icu_fmt_(fmt) {}
+ number_format(icu::NumberFormat& fmt, const std::string& codepage, bool isNumberOnly = false) :
+ cvt_(codepage), icu_fmt_(fmt), isNumberOnly_(isNumberOnly)
+ {}
string_type format(double value, size_t& code_points) const override { return do_format(value, code_points); }
string_type format(int64_t value, size_t& code_points) const override { return do_format(value, code_points); }
string_type format(int32_t value, size_t& code_points) const override { return do_format(value, code_points); }
size_t parse(const string_type& str, double& value) const override { return do_parse(str, value); }
+ size_t parse(const string_type& str, uint64_t& value) const override { return do_parse(str, value); }
size_t parse(const string_type& str, int64_t& value) const override { return do_parse(str, value); }
size_t parse(const string_type& str, int32_t& value) const override { return do_parse(str, value); }
+ string_type format(const uint64_t value, size_t& code_points) const override
+ {
+ // ICU only supports int64_t as the largest integer type
+ if(value <= static_cast<uint64_t>(std::numeric_limits<int64_t>::max()))
+ return format(static_cast<int64_t>(value), code_points);
+
+ // Fallback to using a StringPiece (decimal number) as input
+ char buffer[boost::charconv::limits<uint64_t>::max_chars10 + 1];
+ auto res = boost::charconv::to_chars(buffer, std::end(buffer), value);
+ BOOST_ASSERT(res);
+ BOOST_ASSERT(res.ptr < std::end(buffer));
+ *res.ptr = '\0'; // ICU expects a NULL-terminated string even for the StringPiece
+ icu::UnicodeString tmp;
+ UErrorCode err = U_ZERO_ERROR;
+ icu_fmt_.format(icu::StringPiece(buffer, res.ptr - buffer), tmp, nullptr, err);
+ check_and_throw_icu_error(err);
+ code_points = tmp.countChar32();
+ return cvt_.std(tmp);
+ }
+
private:
bool get_value(double& v, icu::Formattable& fmt) const
{
UErrorCode err = U_ZERO_ERROR;
v = fmt.getDouble(err);
- if(U_FAILURE(err))
- return false;
- return true;
+ return U_SUCCESS(err);
}
bool get_value(int64_t& v, icu::Formattable& fmt) const
{
UErrorCode err = U_ZERO_ERROR;
v = fmt.getInt64(err);
- if(U_FAILURE(err))
- return false;
- return true;
+ return U_SUCCESS(err);
+ }
+
+ bool get_value(uint64_t& v, icu::Formattable& fmt) const
+ {
+ UErrorCode err = U_ZERO_ERROR;
+ // ICU only supports int64_t as the largest integer type
+ const int64_t tmp = fmt.getInt64(err);
+ if(U_SUCCESS(err)) {
+ if(tmp < 0)
+ return false;
+ v = static_cast<uint64_t>(tmp);
+ return true;
+ }
+ return util::try_parse_icu(fmt, v);
}
bool get_value(int32_t& v, icu::Formattable& fmt) const
{
UErrorCode err = U_ZERO_ERROR;
v = fmt.getLong(err);
- if(U_FAILURE(err))
- return false;
- return true;
+ return U_SUCCESS(err);
}
template<typename ValueType>
@@ -107,21 +141,22 @@ namespace boost { namespace locale { namespace impl_icu {
icu::ParsePosition pp;
icu::UnicodeString tmp = cvt_.icu(str.data(), str.data() + str.size());
+ // For the plain number parsing (no currency etc) parse "123.456" as 2 ints
+ // not a float later converted to int
+ icu_fmt_.setParseIntegerOnly(std::is_integral<ValueType>::value && isNumberOnly_);
icu_fmt_.parse(tmp, val, pp);
- ValueType tmp_v;
-
- if(pp.getIndex() == 0 || !get_value(tmp_v, val))
+ if(pp.getIndex() == 0 || !get_value(v, val))
return 0;
size_t cut = cvt_.cut(tmp, str.data(), str.data() + str.size(), pp.getIndex());
if(cut == 0)
return 0;
- v = tmp_v;
return cut;
}
icu_std_converter<CharType> cvt_;
icu::NumberFormat& icu_fmt_;
+ const bool isNumberOnly_;
};
template<typename CharType>
@@ -130,11 +165,11 @@ namespace boost { namespace locale { namespace impl_icu {
typedef std::basic_string<CharType> string_type;
string_type format(double value, size_t& code_points) const override { return do_format(value, code_points); }
+ string_type format(uint64_t value, size_t& code_points) const override { return do_format(value, code_points); }
string_type format(int64_t value, size_t& code_points) const override { return do_format(value, code_points); }
-
string_type format(int32_t value, size_t& code_points) const override { return do_format(value, code_points); }
-
size_t parse(const string_type& str, double& value) const override { return do_parse(str, value); }
+ size_t parse(const string_type& str, uint64_t& value) const override { return do_parse(str, value); }
size_t parse(const string_type& str, int64_t& value) const override { return do_parse(str, value); }
size_t parse(const string_type& str, int32_t& value) const override { return do_parse(str, value); }
@@ -355,7 +390,7 @@ namespace boost { namespace locale { namespace impl_icu {
icu::NumberFormat& nf =
cache.number_format((how == std::ios_base::scientific) ? num_fmt_type::sci : num_fmt_type::number);
set_fraction_digits(nf, how, ios.precision());
- return ptr_type(new number_format<CharType>(nf, encoding));
+ return ptr_type(new number_format<CharType>(nf, encoding, true));
}
case currency: {
icu::NumberFormat& nf = cache.number_format(
diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/formatter.hpp b/contrib/restricted/boost/locale/src/icu/formatter.hpp
index 110a031551c..bcda2788ef8 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/icu/formatter.hpp
+++ b/contrib/restricted/boost/locale/src/icu/formatter.hpp
@@ -1,5 +1,6 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
+// Copyright (c) 2024 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
@@ -31,6 +32,8 @@ namespace boost { namespace locale { namespace impl_icu {
/// Format the value and return the number of Unicode code points
virtual string_type format(double value, size_t& code_points) const = 0;
/// Format the value and return the number of Unicode code points
+ virtual string_type format(uint64_t value, size_t& code_points) const = 0;
+ /// Format the value and return the number of Unicode code points
virtual string_type format(int64_t value, size_t& code_points) const = 0;
/// Format the value and return the number of Unicode code points
virtual string_type format(int32_t value, size_t& code_points) const = 0;
@@ -40,6 +43,9 @@ namespace boost { namespace locale { namespace impl_icu {
virtual size_t parse(const string_type& str, double& value) const = 0;
/// Parse the string and return the number of used characters. If it returns 0
/// then parsing failed.
+ virtual size_t parse(const string_type& str, uint64_t& value) const = 0;
+ /// Parse the string and return the number of used characters. If it returns 0
+ /// then parsing failed.
virtual size_t parse(const string_type& str, int64_t& value) const = 0;
/// Parse the string and return the number of used characters. If it returns 0
/// then parsing failed.
diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/formatters_cache.cpp b/contrib/restricted/boost/locale/src/icu/formatters_cache.cpp
index c9a8c46347a..101ffcc6504 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/icu/formatters_cache.cpp
+++ b/contrib/restricted/boost/locale/src/icu/formatters_cache.cpp
@@ -1,11 +1,11 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
-// Copyright (c) 2021-2022 Alexander Grund
+// Copyright (c) 2021-2024 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
-#include "boost/locale/icu/formatters_cache.hpp"
+#include "formatters_cache.hpp"
#include <boost/assert.hpp>
#include <boost/core/ignore_unused.hpp>
#include <memory>
@@ -87,22 +87,10 @@ namespace boost { namespace locale { namespace impl_icu {
switch(type) {
case num_fmt_type::number: return icu::NumberFormat::createInstance(locale_, err); break;
case num_fmt_type::sci: return icu::NumberFormat::createScientificInstance(locale_, err); break;
-#if BOOST_LOCALE_ICU_VERSION >= 408
case num_fmt_type::curr_nat: return icu::NumberFormat::createInstance(locale_, UNUM_CURRENCY, err); break;
case num_fmt_type::curr_iso:
return icu::NumberFormat::createInstance(locale_, UNUM_CURRENCY_ISO, err);
break;
-#elif BOOST_LOCALE_ICU_VERSION >= 402
- case num_fmt_type::curr_nat:
- return icu::NumberFormat::createInstance(locale_, icu::NumberFormat::kCurrencyStyle, err);
- break;
- case num_fmt_type::curr_iso:
- return icu::NumberFormat::createInstance(locale_, icu::NumberFormat::kIsoCurrencyStyle, err);
- break;
-#else
- case num_fmt_type::curr_nat:
- case num_fmt_type::curr_iso: return icu::NumberFormat::createCurrencyInstance(locale_, err); break;
-#endif
case num_fmt_type::percent: return icu::NumberFormat::createPercentInstance(locale_, err); break;
case num_fmt_type::spell: return new icu::RuleBasedNumberFormat(icu::URBNF_SPELLOUT, locale_, err); break;
case num_fmt_type::ordinal: return new icu::RuleBasedNumberFormat(icu::URBNF_ORDINAL, locale_, err); break;
diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/formatters_cache.hpp b/contrib/restricted/boost/locale/src/icu/formatters_cache.hpp
index d0e4978d550..2d4c950c543 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/icu/formatters_cache.hpp
+++ b/contrib/restricted/boost/locale/src/icu/formatters_cache.hpp
@@ -9,7 +9,7 @@
#define BOOST_LOCALE_PREDEFINED_FORMATTERS_HPP_INCLUDED
#include <boost/locale/config.hpp>
-#include "boost/locale/icu/icu_util.hpp"
+#include "icu_util.hpp"
#include <boost/thread/tss.hpp>
#include <locale>
diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/icu_backend.cpp b/contrib/restricted/boost/locale/src/icu/icu_backend.cpp
index ecb78ae45ca..4b70e9750fd 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/icu/icu_backend.cpp
+++ b/contrib/restricted/boost/locale/src/icu/icu_backend.cpp
@@ -5,14 +5,14 @@
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
-#include "boost/locale/icu/icu_backend.hpp"
+#include "icu_backend.hpp"
#include <boost/locale/gnu_gettext.hpp>
#include <boost/locale/localization_backend.hpp>
#include <boost/locale/util.hpp>
-#include "boost/locale/icu/all_generator.hpp"
-#include "boost/locale/icu/cdata.hpp"
-#include "boost/locale/shared/message.hpp"
-#include "boost/locale/util/make_std_unique.hpp"
+#include "../shared/message.hpp"
+#include "../util/make_std_unique.hpp"
+#include "all_generator.hpp"
+#include "cdata.hpp"
#include <unicode/ucnv.h>
diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/icu_backend.hpp b/contrib/restricted/boost/locale/src/icu/icu_backend.hpp
index 8266856dc1f..8266856dc1f 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/icu/icu_backend.hpp
+++ b/contrib/restricted/boost/locale/src/icu/icu_backend.hpp
diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/icu_util.hpp b/contrib/restricted/boost/locale/src/icu/icu_util.hpp
index 70f4cefa36b..70f4cefa36b 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/icu/icu_util.hpp
+++ b/contrib/restricted/boost/locale/src/icu/icu_util.hpp
diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/numeric.cpp b/contrib/restricted/boost/locale/src/icu/numeric.cpp
index d81f55f7baf..e54ab1c498a 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/icu/numeric.cpp
+++ b/contrib/restricted/boost/locale/src/icu/numeric.cpp
@@ -1,14 +1,15 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
+// Copyright (c) 2024 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/locale/formatting.hpp>
-#include "boost/locale/icu/all_generator.hpp"
-#include "boost/locale/icu/cdata.hpp"
-#include "boost/locale/icu/formatter.hpp"
-#include "boost/locale/icu/formatters_cache.hpp"
+#include "all_generator.hpp"
+#include "cdata.hpp"
+#include "formatter.hpp"
+#include "formatters_cache.hpp"
#include <algorithm>
#include <ios>
#include <limits>
@@ -19,41 +20,31 @@
namespace boost { namespace locale { namespace impl_icu {
namespace detail {
- template<typename T, bool integer = std::numeric_limits<T>::is_integer>
- struct icu_format_type;
+ template<typename T, typename PreferredType, typename AlternativeType>
+ struct choose_type_by_digits
+ : std::conditional<std::numeric_limits<T>::digits <= std::numeric_limits<PreferredType>::digits,
+ PreferredType,
+ AlternativeType> {};
- template<typename T>
- struct icu_format_type<T, true> {
- // ICU supports 32 and 64 bit ints, use the former as long as it fits, else the latter
- typedef typename std::conditional<std::numeric_limits<T>::digits <= 31, int32_t, int64_t>::type type;
+ template<typename T, bool integer = std::numeric_limits<T>::is_integer>
+ struct icu_format_type {
+ static_assert(sizeof(T) <= sizeof(int64_t), "Only up to 64 bit integer types are supported by ICU");
+ // ICU supports (only) int32_t and int64_t, use the former as long as it fits, else the latter
+ using large_type = typename choose_type_by_digits<T, int64_t, uint64_t>::type;
+ using type = typename choose_type_by_digits<T, int32_t, large_type>::type;
};
template<typename T>
struct icu_format_type<T, false> {
// Only float type ICU supports is double
- typedef double type;
- };
-
- // ICU does not support uint64_t values so fall back to the parent/std formatting
- // if the number is to large to fit into an int64_t
- template<typename T,
- bool BigUInt = !std::numeric_limits<T>::is_signed && std::numeric_limits<T>::is_integer
- && (sizeof(T) >= sizeof(uint64_t))>
- struct use_parent_traits {
- static bool use(T /*v*/) { return false; }
- };
- template<typename T>
- struct use_parent_traits<T, true> {
- static bool use(T v) { return v > static_cast<T>(std::numeric_limits<int64_t>::max()); }
+ using type = double;
};
template<typename ValueType>
- static bool use_parent(std::ios_base& ios, ValueType v)
+ static bool use_parent(std::ios_base& ios)
{
const uint64_t flg = ios_info::get(ios).display_flags();
if(flg == flags::posix)
return true;
- if(use_parent_traits<ValueType>::use(v))
- return true;
if(!std::numeric_limits<ValueType>::is_integer)
return false;
@@ -105,22 +96,23 @@ namespace boost { namespace locale { namespace impl_icu {
template<typename ValueType>
iter_type do_real_put(iter_type out, std::ios_base& ios, CharType fill, ValueType val) const
{
- if(detail::use_parent(ios, val))
+ if(detail::use_parent<ValueType>(ios))
return std::num_put<CharType>::do_put(out, ios, fill, val);
- const auto formatter = formatter_type::create(ios, loc_, enc_);
+ const std::unique_ptr<formatter_type> formatter = formatter_type::create(ios, loc_, enc_);
if(!formatter)
return std::num_put<CharType>::do_put(out, ios, fill, val);
+ using icu_type = typename detail::icu_format_type<ValueType>::type;
size_t code_points;
- typedef typename detail::icu_format_type<ValueType>::type icu_type;
- const string_type& str = formatter->format(static_cast<icu_type>(val), code_points);
+ const string_type str = formatter->format(static_cast<icu_type>(val), code_points);
+
std::streamsize on_left = 0, on_right = 0, points = code_points;
if(points < ios.width()) {
- std::streamsize n = ios.width() - points;
+ const std::streamsize n = ios.width() - points;
- std::ios_base::fmtflags flags = ios.flags() & std::ios_base::adjustfield;
+ const std::ios_base::fmtflags flags = ios.flags() & std::ios_base::adjustfield;
// We do not really know internal point, so we assume that it does not
// exist. So according to the standard field should be right aligned
@@ -239,10 +231,10 @@ namespace boost { namespace locale { namespace impl_icu {
do_real_get(iter_type in, iter_type end, std::ios_base& ios, std::ios_base::iostate& err, ValueType& val) const
{
stream_type* stream_ptr = dynamic_cast<stream_type*>(&ios);
- if(!stream_ptr || detail::use_parent(ios, ValueType(0)))
+ if(!stream_ptr || detail::use_parent<ValueType>(ios))
return std::num_get<CharType>::do_get(in, end, ios, err, val);
- const auto formatter = formatter_type::create(ios, loc_, enc_);
+ const std::unique_ptr<formatter_type> formatter = formatter_type::create(ios, loc_, enc_);
if(!formatter)
return std::num_get<CharType>::do_get(in, end, ios, err, val);
@@ -256,7 +248,7 @@ namespace boost { namespace locale { namespace impl_icu {
while(tmp.size() < 4096 && in != end && *in != '\n')
tmp += *in++;
- typedef typename detail::icu_format_type<ValueType>::type icu_type;
+ using icu_type = typename detail::icu_format_type<ValueType>::type;
icu_type value;
size_t parsed_chars;
diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/time_zone.hpp b/contrib/restricted/boost/locale/src/icu/time_zone.hpp
index 87ab0c44165..d265b1d6e45 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/icu/time_zone.hpp
+++ b/contrib/restricted/boost/locale/src/icu/time_zone.hpp
@@ -1,5 +1,6 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
+// Copyright (c) 2022-2024 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
@@ -14,9 +15,14 @@
namespace boost { namespace locale { namespace impl_icu {
- // Provides a workaround for an ICU default timezone bug and also
- // handles time_zone string correctly - if empty returns default
- // otherwise returns the instance created with time_zone
- icu::TimeZone* get_time_zone(const std::string& time_zone);
+ // Return an ICU time zone instance.
+ // If the argument is empty returns the default timezone.
+ inline icu::TimeZone* get_time_zone(const std::string& time_zone)
+ {
+ if(time_zone.empty())
+ return icu::TimeZone::createDefault();
+ else
+ return icu::TimeZone::createTimeZone(time_zone.c_str());
+ }
}}} // namespace boost::locale::impl_icu
#endif
diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/uconv.hpp b/contrib/restricted/boost/locale/src/icu/uconv.hpp
index 6563afb627b..f801f10edd7 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/icu/uconv.hpp
+++ b/contrib/restricted/boost/locale/src/icu/uconv.hpp
@@ -9,7 +9,7 @@
#define BOOST_SRC_LOCALE_ICU_UCONV_HPP
#include <boost/locale/encoding.hpp>
-#include "boost/locale/icu/icu_util.hpp"
+#include "icu_util.hpp"
#include <boost/core/exchange.hpp>
#include <memory>
diff --git a/contrib/restricted/boost/locale/src/boost/locale/posix/all_generator.hpp b/contrib/restricted/boost/locale/src/posix/all_generator.hpp
index da4d4a82d99..da4d4a82d99 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/posix/all_generator.hpp
+++ b/contrib/restricted/boost/locale/src/posix/all_generator.hpp
diff --git a/contrib/restricted/boost/locale/src/boost/locale/posix/codecvt.cpp b/contrib/restricted/boost/locale/src/posix/codecvt.cpp
index d2c5acf0065..3f0a0ed43c5 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/posix/codecvt.cpp
+++ b/contrib/restricted/boost/locale/src/posix/codecvt.cpp
@@ -6,9 +6,9 @@
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/locale/encoding_errors.hpp>
-#include "boost/locale/posix/all_generator.hpp"
-#include "boost/locale/shared/iconv_codecvt.hpp"
-#include "boost/locale/util/encoding.hpp"
+#include "../shared/iconv_codecvt.hpp"
+#include "../util/encoding.hpp"
+#include "all_generator.hpp"
#include <stdexcept>
namespace boost { namespace locale { namespace impl_posix {
diff --git a/contrib/restricted/boost/locale/src/boost/locale/posix/collate.cpp b/contrib/restricted/boost/locale/src/posix/collate.cpp
index c9fb0251ff3..bd8ab36053e 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/posix/collate.cpp
+++ b/contrib/restricted/boost/locale/src/posix/collate.cpp
@@ -8,6 +8,8 @@
#if defined(__FreeBSD__)
# include <xlocale.h>
#endif
+#include "../shared/mo_hash.hpp"
+#include "all_generator.hpp"
#include <clocale>
#include <cstring>
#include <ios>
@@ -17,9 +19,6 @@
#include <vector>
#include <wchar.h>
-#include "boost/locale/posix/all_generator.hpp"
-#include "boost/locale/shared/mo_hash.hpp"
-
namespace boost { namespace locale { namespace impl_posix {
template<typename CharType>
diff --git a/contrib/restricted/boost/locale/src/boost/locale/posix/converter.cpp b/contrib/restricted/boost/locale/src/posix/converter.cpp
index b787a562c5a..13477aa03bb 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/posix/converter.cpp
+++ b/contrib/restricted/boost/locale/src/posix/converter.cpp
@@ -7,7 +7,7 @@
#include <boost/locale/conversion.hpp>
#include <boost/locale/encoding.hpp>
#include <boost/locale/generator.hpp>
-#include "boost/locale/util/encoding.hpp"
+#include "../util/encoding.hpp"
#include <cctype>
#include <cstring>
#include <langinfo.h>
@@ -18,7 +18,7 @@
# include <xlocale.h>
#endif
-#include "boost/locale/posix/all_generator.hpp"
+#include "all_generator.hpp"
namespace boost { namespace locale { namespace impl_posix {
@@ -125,7 +125,7 @@ namespace boost { namespace locale { namespace impl_posix {
return std::locale(in, new std_converter<char>(std::move(lc)));
}
case char_facet_t::wchar_f: return std::locale(in, new std_converter<wchar_t>(std::move(lc)));
-#ifndef BOOST_LOCALE_NO_CXX20_STRING8
+#ifdef __cpp_lib_char8_t
case char_facet_t::char8_f: return std::locale(in, new utf8_converter<char8_t>(std::move(lc)));
#elif defined(__cpp_char8_t)
case char_facet_t::char8_f: break;
diff --git a/contrib/restricted/boost/locale/src/boost/locale/posix/numeric.cpp b/contrib/restricted/boost/locale/src/posix/numeric.cpp
index a3ee2c40551..2810b821af1 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/posix/numeric.cpp
+++ b/contrib/restricted/boost/locale/src/posix/numeric.cpp
@@ -27,8 +27,8 @@
#include <vector>
#include <wctype.h>
-#include "boost/locale/posix/all_generator.hpp"
-#include "boost/locale/util/numeric.hpp"
+#include "../util/numeric.hpp"
+#include "all_generator.hpp"
namespace boost { namespace locale { namespace impl_posix {
diff --git a/contrib/restricted/boost/locale/src/boost/locale/posix/posix_backend.cpp b/contrib/restricted/boost/locale/src/posix/posix_backend.cpp
index 020d0c77e0f..98aadf211e3 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/posix/posix_backend.cpp
+++ b/contrib/restricted/boost/locale/src/posix/posix_backend.cpp
@@ -5,7 +5,7 @@
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
-#include "boost/locale/posix/posix_backend.hpp"
+#include "posix_backend.hpp"
#include <boost/locale/gnu_gettext.hpp>
#include <boost/locale/info.hpp>
#include <boost/locale/localization_backend.hpp>
@@ -19,10 +19,10 @@
# include <xlocale.h>
#endif
-#include "boost/locale/posix/all_generator.hpp"
-#include "boost/locale/shared/message.hpp"
-#include "boost/locale/util/gregorian.hpp"
-#include "boost/locale/util/make_std_unique.hpp"
+#include "../shared/message.hpp"
+#include "../util/gregorian.hpp"
+#include "../util/make_std_unique.hpp"
+#include "all_generator.hpp"
namespace boost { namespace locale { namespace impl_posix {
diff --git a/contrib/restricted/boost/locale/src/boost/locale/posix/posix_backend.hpp b/contrib/restricted/boost/locale/src/posix/posix_backend.hpp
index 925c9580d53..925c9580d53 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/posix/posix_backend.hpp
+++ b/contrib/restricted/boost/locale/src/posix/posix_backend.hpp
diff --git a/contrib/restricted/boost/locale/src/boost/locale/shared/date_time.cpp b/contrib/restricted/boost/locale/src/shared/date_time.cpp
index c418406d18c..c418406d18c 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/shared/date_time.cpp
+++ b/contrib/restricted/boost/locale/src/shared/date_time.cpp
diff --git a/contrib/restricted/boost/locale/src/boost/locale/shared/format.cpp b/contrib/restricted/boost/locale/src/shared/format.cpp
index 7ee809fe709..9853c7ff622 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/shared/format.cpp
+++ b/contrib/restricted/boost/locale/src/shared/format.cpp
@@ -1,5 +1,6 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
+// Copyright (c) 2024 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
@@ -7,7 +8,7 @@
#include <boost/locale/format.hpp>
#include <boost/locale/generator.hpp>
#include <boost/locale/info.hpp>
-#include "boost/locale/util/numeric.hpp"
+#include "../util/numeric_conversion.hpp"
#include <algorithm>
#include <iostream>
#include <limits>
@@ -63,10 +64,9 @@ namespace boost { namespace locale { namespace detail {
{
if(key.empty())
return;
- int position;
- if(util::try_to_int(key, position) && position > 0) {
- static_assert(sizeof(unsigned) <= sizeof(decltype(d->position)), "Possible lossy conversion");
- d->position = static_cast<unsigned>(position - 1);
+ decltype(d->position) position;
+ if(util::try_to_int(key, position) && position > 0u) {
+ d->position = position - 1u;
} else if(key == "num" || key == "number") {
as::number(ios_);
diff --git a/contrib/restricted/boost/locale/src/boost/locale/shared/formatting.cpp b/contrib/restricted/boost/locale/src/shared/formatting.cpp
index 457ba782e94..53f436a30e3 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/shared/formatting.cpp
+++ b/contrib/restricted/boost/locale/src/shared/formatting.cpp
@@ -6,7 +6,7 @@
#include <boost/locale/date_time.hpp>
#include <boost/locale/formatting.hpp>
-#include "boost/locale/shared/ios_prop.hpp"
+#include "ios_prop.hpp"
namespace boost { namespace locale {
ios_info::ios_info() : flags_(0), domain_id_(0), time_zone_(time_zone::global()) {}
@@ -65,7 +65,7 @@ namespace boost { namespace locale {
{
time_zone_ = tz;
}
- std::string ios_info::time_zone() const
+ const std::string& ios_info::time_zone() const
{
return time_zone_;
}
diff --git a/contrib/restricted/boost/locale/src/boost/locale/shared/generator.cpp b/contrib/restricted/boost/locale/src/shared/generator.cpp
index baf424bea8c..ddff3ba655e 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/shared/generator.cpp
+++ b/contrib/restricted/boost/locale/src/shared/generator.cpp
@@ -1,5 +1,6 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
+// Copyright (c) 2024 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
@@ -93,9 +94,7 @@ namespace boost { namespace locale {
std::locale generator::generate(const std::string& id) const
{
- std::locale base = std::locale::classic();
-
- return generate(base, id);
+ return generate(std::locale::classic(), id);
}
std::locale generator::generate(const std::locale& base, const std::string& id) const
@@ -110,8 +109,8 @@ namespace boost { namespace locale {
set_all_options(*backend, id);
std::locale result = base;
- category_t facets = d->cats;
- char_facet_t chars = d->chars;
+ const category_t facets = d->cats;
+ const char_facet_t chars = d->chars;
for(category_t facet = per_character_facet_first; facet <= per_character_facet_last; ++facet) {
if(!(facets & facet))
diff --git a/contrib/restricted/boost/locale/src/boost/locale/shared/iconv_codecvt.cpp b/contrib/restricted/boost/locale/src/shared/iconv_codecvt.cpp
index 2ed618a0ae4..481973079fe 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/shared/iconv_codecvt.cpp
+++ b/contrib/restricted/boost/locale/src/shared/iconv_codecvt.cpp
@@ -12,9 +12,9 @@
#include <limits>
#include <vector>
#ifdef BOOST_LOCALE_WITH_ICONV
-# include "boost/locale/util/encoding.hpp"
-# include "boost/locale/util/iconv.hpp"
-# include "boost/locale/util/make_std_unique.hpp"
+# include "../util/encoding.hpp"
+# include "../util/iconv.hpp"
+# include "../util/make_std_unique.hpp"
#endif
namespace boost { namespace locale {
diff --git a/contrib/restricted/boost/locale/src/boost/locale/shared/iconv_codecvt.hpp b/contrib/restricted/boost/locale/src/shared/iconv_codecvt.hpp
index 51ddc71b683..51ddc71b683 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/shared/iconv_codecvt.hpp
+++ b/contrib/restricted/boost/locale/src/shared/iconv_codecvt.hpp
diff --git a/contrib/restricted/boost/locale/src/boost/locale/shared/ids.cpp b/contrib/restricted/boost/locale/src/shared/ids.cpp
index 819de7f9935..2d5ef255a39 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/shared/ids.cpp
+++ b/contrib/restricted/boost/locale/src/shared/ids.cpp
@@ -11,7 +11,7 @@
#include <boost/locale/date_time_facet.hpp>
#include <boost/locale/info.hpp>
#include <boost/locale/message.hpp>
-#include "boost/locale/util/foreach_char.hpp"
+#include "../util/foreach_char.hpp"
#include <boost/core/ignore_unused.hpp>
namespace boost { namespace locale {
diff --git a/contrib/restricted/boost/locale/src/boost/locale/shared/ios_prop.hpp b/contrib/restricted/boost/locale/src/shared/ios_prop.hpp
index d8256592f79..d8256592f79 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/shared/ios_prop.hpp
+++ b/contrib/restricted/boost/locale/src/shared/ios_prop.hpp
diff --git a/contrib/restricted/boost/locale/src/boost/locale/shared/localization_backend.cpp b/contrib/restricted/boost/locale/src/shared/localization_backend.cpp
index 951cb3beb49..beace3e3afe 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/shared/localization_backend.cpp
+++ b/contrib/restricted/boost/locale/src/shared/localization_backend.cpp
@@ -12,19 +12,19 @@
#include <vector>
#ifdef BOOST_LOCALE_WITH_ICU
-# include "boost/locale/icu/icu_backend.hpp"
+# include "../icu/icu_backend.hpp"
#endif
#ifndef BOOST_LOCALE_NO_POSIX_BACKEND
-# include "boost/locale/posix/posix_backend.hpp"
+# include "../posix/posix_backend.hpp"
#endif
#ifndef BOOST_LOCALE_NO_STD_BACKEND
-# include "boost/locale/std/std_backend.hpp"
+# include "../std/std_backend.hpp"
#endif
#ifndef BOOST_LOCALE_NO_WINAPI_BACKEND
-# include "boost/locale/win32/win_backend.hpp"
+# include "../win32/win_backend.hpp"
#endif
namespace boost { namespace locale {
diff --git a/contrib/restricted/boost/locale/src/boost/locale/shared/message.cpp b/contrib/restricted/boost/locale/src/shared/message.cpp
index da8b4b934f7..70eafd22e93 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/shared/message.cpp
+++ b/contrib/restricted/boost/locale/src/shared/message.cpp
@@ -1,6 +1,6 @@
//
// Copyright (c) 2009-2015 Artyom Beilis (Tonkikh)
-// Copyright (c) 2021-2023 Alexander Grund
+// Copyright (c) 2021-2025 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
@@ -20,13 +20,13 @@
#include <boost/locale/encoding.hpp>
#include <boost/locale/message.hpp>
-#include "boost/locale/shared/message.hpp"
-#include "boost/locale/shared/mo_hash.hpp"
-#include "boost/locale/shared/mo_lambda.hpp"
-#include "boost/locale/util/encoding.hpp"
-#include "boost/locale/util/foreach_char.hpp"
+#include "../util/encoding.hpp"
+#include "../util/foreach_char.hpp"
+#include "message.hpp"
+#include "mo_hash.hpp"
+#include "mo_lambda.hpp"
#include <boost/assert.hpp>
-#include <boost/utility/string_view.hpp>
+#include <boost/core/detail/string_view.hpp>
#include <cstdio>
#include <map>
#include <memory>
@@ -141,7 +141,7 @@ namespace boost { namespace locale { namespace gnu_gettext {
hash_offset_ = get(24);
}
- string_view find(const char* context_in, const char* key_in) const
+ core::string_view find(const char* context_in, const char* key_in) const
{
if(!has_hash())
return {};
@@ -192,20 +192,20 @@ namespace boost { namespace locale { namespace gnu_gettext {
return data_.data() + off;
}
- string_view value(unsigned id) const
+ core::string_view value(unsigned id) const
{
const uint32_t len = get(translations_offset_ + id * 8);
const uint32_t off = get(translations_offset_ + id * 8 + 4);
if(len > data_.size() || off > data_.size() - len)
throw std::runtime_error("Bad mo-file format");
- return string_view(&data_[off], len);
+ return core::string_view(&data_[off], len);
}
bool has_hash() const { return hash_size_ != 0; }
size_t size() const { return size_; }
- bool empty() { return size_ == 0; }
+ bool empty() const { return size_ == 0; }
private:
uint32_t get(unsigned offset) const
@@ -233,7 +233,7 @@ namespace boost { namespace locale { namespace gnu_gettext {
template<typename CharType>
struct mo_file_use_traits {
static constexpr bool in_use = false;
- using string_view_type = basic_string_view<CharType>;
+ using string_view_type = core::basic_string_view<CharType>;
static string_view_type use(const mo_file&, const CharType*, const CharType*)
{
throw std::logic_error("Unexpected call"); // LCOV_EXCL_LINE
@@ -243,7 +243,7 @@ namespace boost { namespace locale { namespace gnu_gettext {
template<>
struct mo_file_use_traits<char> {
static constexpr bool in_use = true;
- using string_view_type = basic_string_view<char>;
+ using string_view_type = core::basic_string_view<char>;
static string_view_type use(const mo_file& mo, const char* context, const char* key)
{
return mo.find(context, key);
@@ -254,10 +254,10 @@ namespace boost { namespace locale { namespace gnu_gettext {
template<>
struct mo_file_use_traits<char8_t> {
static constexpr bool in_use = true;
- using string_view_type = basic_string_view<char8_t>;
+ using string_view_type = core::basic_string_view<char8_t>;
static string_view_type use(const mo_file& mo, const char8_t* context, const char8_t* key)
{
- string_view res = mo.find(reinterpret_cast<const char*>(context), reinterpret_cast<const char*>(key));
+ core::string_view res = mo.find(reinterpret_cast<const char*>(context), reinterpret_cast<const char*>(key));
return {reinterpret_cast<const char8_t*>(res.data()), res.size()};
}
};
@@ -551,10 +551,10 @@ namespace boost { namespace locale { namespace gnu_gettext {
return true;
}
- static std::string extract(boost::string_view meta, const std::string& key, const boost::string_view separators)
+ static std::string extract(core::string_view meta, const std::string& key, const core::string_view separators)
{
const size_t pos = meta.find(key);
- if(pos == boost::string_view::npos)
+ if(pos == core::string_view::npos)
return "";
meta.remove_prefix(pos + key.size());
const size_t end_pos = meta.find_first_of(separators);
@@ -620,7 +620,7 @@ namespace boost { namespace locale { namespace detail {
case char_facet_t::nochar: break;
case char_facet_t::char_f: return std::locale(in, gnu_gettext::create_messages_facet<char>(minf));
case char_facet_t::wchar_f: return std::locale(in, gnu_gettext::create_messages_facet<wchar_t>(minf));
-#ifndef BOOST_LOCALE_NO_CXX20_STRING8
+#ifdef __cpp_lib_char8_t
case char_facet_t::char8_f: return std::locale(in, gnu_gettext::create_messages_facet<char8_t>(minf));
#elif defined(__cpp_char8_t)
case char_facet_t::char8_f: break;
diff --git a/contrib/restricted/boost/locale/src/boost/locale/shared/message.hpp b/contrib/restricted/boost/locale/src/shared/message.hpp
index a68cefcab66..a68cefcab66 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/shared/message.hpp
+++ b/contrib/restricted/boost/locale/src/shared/message.hpp
diff --git a/contrib/restricted/boost/locale/src/boost/locale/shared/mo_hash.hpp b/contrib/restricted/boost/locale/src/shared/mo_hash.hpp
index 702ea7aece6..702ea7aece6 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/shared/mo_hash.hpp
+++ b/contrib/restricted/boost/locale/src/shared/mo_hash.hpp
diff --git a/contrib/restricted/boost/locale/src/boost/locale/shared/mo_lambda.cpp b/contrib/restricted/boost/locale/src/shared/mo_lambda.cpp
index 7b37ca91e84..e2a16c8c60e 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/shared/mo_lambda.cpp
+++ b/contrib/restricted/boost/locale/src/shared/mo_lambda.cpp
@@ -5,7 +5,7 @@
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
-#include "boost/locale/shared/mo_lambda.hpp"
+#include "mo_lambda.hpp"
#include <boost/assert.hpp>
#include <algorithm>
#include <cstdlib>
diff --git a/contrib/restricted/boost/locale/src/boost/locale/shared/mo_lambda.hpp b/contrib/restricted/boost/locale/src/shared/mo_lambda.hpp
index ff415175def..ff415175def 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/shared/mo_lambda.hpp
+++ b/contrib/restricted/boost/locale/src/shared/mo_lambda.hpp
diff --git a/contrib/restricted/boost/locale/src/boost/locale/shared/std_collate_adapter.hpp b/contrib/restricted/boost/locale/src/shared/std_collate_adapter.hpp
index ee4ff43b8c8..ee4ff43b8c8 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/shared/std_collate_adapter.hpp
+++ b/contrib/restricted/boost/locale/src/shared/std_collate_adapter.hpp
diff --git a/contrib/restricted/boost/locale/src/boost/locale/std/all_generator.hpp b/contrib/restricted/boost/locale/src/std/all_generator.hpp
index 5dd020815bf..5dd020815bf 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/std/all_generator.hpp
+++ b/contrib/restricted/boost/locale/src/std/all_generator.hpp
diff --git a/contrib/restricted/boost/locale/src/boost/locale/std/codecvt.cpp b/contrib/restricted/boost/locale/src/std/codecvt.cpp
index 22af5d76399..58d4ff8df8e 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/std/codecvt.cpp
+++ b/contrib/restricted/boost/locale/src/std/codecvt.cpp
@@ -5,7 +5,7 @@
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/locale/util.hpp>
-#include "boost/locale/std/all_generator.hpp"
+#include "all_generator.hpp"
#include <locale>
namespace boost { namespace locale { namespace impl_std {
diff --git a/contrib/restricted/boost/locale/src/boost/locale/std/collate.cpp b/contrib/restricted/boost/locale/src/std/collate.cpp
index 48d80bcc972..d7e5e7af5ba 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/std/collate.cpp
+++ b/contrib/restricted/boost/locale/src/std/collate.cpp
@@ -5,7 +5,7 @@
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/locale/encoding.hpp>
-#include "boost/locale/std/all_generator.hpp"
+#include "all_generator.hpp"
#include <boost/assert.hpp>
#include <ios>
#include <locale>
diff --git a/contrib/restricted/boost/locale/src/boost/locale/std/converter.cpp b/contrib/restricted/boost/locale/src/std/converter.cpp
index ce08606b06e..ec60a58dc29 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/std/converter.cpp
+++ b/contrib/restricted/boost/locale/src/std/converter.cpp
@@ -11,7 +11,7 @@
#include <stdexcept>
#include <vector>
-#include "boost/locale/std/all_generator.hpp"
+#include "all_generator.hpp"
namespace boost { namespace locale { namespace impl_std {
@@ -104,7 +104,7 @@ namespace boost { namespace locale { namespace impl_std {
else
return std::locale(in, new std_converter<char>(locale_name));
case char_facet_t::wchar_f: return std::locale(in, new std_converter<wchar_t>(locale_name));
-#ifndef BOOST_LOCALE_NO_CXX20_STRING8
+#ifdef __cpp_lib_char8_t
case char_facet_t::char8_f: return std::locale(in, new utf8_converter<char8_t>(locale_name));
#elif defined(__cpp_char8_t)
case char_facet_t::char8_f: break;
diff --git a/contrib/restricted/boost/locale/src/boost/locale/std/numeric.cpp b/contrib/restricted/boost/locale/src/std/numeric.cpp
index fe3dc09515a..b88cbd56530 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/std/numeric.cpp
+++ b/contrib/restricted/boost/locale/src/std/numeric.cpp
@@ -14,8 +14,8 @@
#include <sstream>
#include <string>
-#include "boost/locale/std/all_generator.hpp"
-#include "boost/locale/util/numeric.hpp"
+#include "../util/numeric.hpp"
+#include "all_generator.hpp"
namespace boost { namespace locale { namespace impl_std {
/// Forwarding time_put facet
diff --git a/contrib/restricted/boost/locale/src/boost/locale/std/std_backend.cpp b/contrib/restricted/boost/locale/src/std/std_backend.cpp
index 4a134c25840..1eadfd2491c 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/std/std_backend.cpp
+++ b/contrib/restricted/boost/locale/src/std/std_backend.cpp
@@ -5,7 +5,7 @@
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
-#include "boost/locale/std/std_backend.hpp"
+#include "std_backend.hpp"
#include <boost/locale/gnu_gettext.hpp>
#include <boost/locale/localization_backend.hpp>
#include <boost/locale/util.hpp>
@@ -20,15 +20,15 @@
# ifndef NOMINMAX
# define NOMINMAX
# endif
-# include "boost/locale/win32/lcid.hpp"
+# include "../win32/lcid.hpp"
# include <windows.h>
#endif
-#include "boost/locale/shared/message.hpp"
-#include "boost/locale/std/all_generator.hpp"
-#include "boost/locale/util/encoding.hpp"
-#include "boost/locale/util/gregorian.hpp"
-#include "boost/locale/util/make_std_unique.hpp"
-#include "boost/locale/util/numeric.hpp"
+#include "../shared/message.hpp"
+#include "../util/encoding.hpp"
+#include "../util/gregorian.hpp"
+#include "../util/make_std_unique.hpp"
+#include "../util/numeric_conversion.hpp"
+#include "all_generator.hpp"
namespace {
struct windows_name {
diff --git a/contrib/restricted/boost/locale/src/boost/locale/std/std_backend.hpp b/contrib/restricted/boost/locale/src/std/std_backend.hpp
index 4ce6b271e36..4ce6b271e36 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/std/std_backend.hpp
+++ b/contrib/restricted/boost/locale/src/std/std_backend.hpp
diff --git a/contrib/restricted/boost/locale/src/boost/locale/util/codecvt_converter.cpp b/contrib/restricted/boost/locale/src/util/codecvt_converter.cpp
index b1cf9df9a9b..26af5005ed5 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/util/codecvt_converter.cpp
+++ b/contrib/restricted/boost/locale/src/util/codecvt_converter.cpp
@@ -15,8 +15,8 @@
#include <cstddef>
#include <cstring>
-#include "boost/locale/util/encoding.hpp"
-#include "boost/locale/util/make_std_unique.hpp"
+#include "encoding.hpp"
+#include "make_std_unique.hpp"
#ifdef BOOST_MSVC
# pragma warning(disable : 4244) // loose data
diff --git a/contrib/restricted/boost/locale/src/boost/locale/util/default_locale.cpp b/contrib/restricted/boost/locale/src/util/default_locale.cpp
index 74cf7705dc8..74cf7705dc8 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/util/default_locale.cpp
+++ b/contrib/restricted/boost/locale/src/util/default_locale.cpp
diff --git a/contrib/restricted/boost/locale/src/boost/locale/util/encoding.cpp b/contrib/restricted/boost/locale/src/util/encoding.cpp
index 8a6bf183be0..8b893f1c4a0 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/util/encoding.cpp
+++ b/contrib/restricted/boost/locale/src/util/encoding.cpp
@@ -1,14 +1,14 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
-// Copyright (c) 2022-2023 Alexander Grund
+// Copyright (c) 2022-2025 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
-#include "boost/locale/util/encoding.hpp"
-#include "boost/locale/util/string.hpp"
+#include "encoding.hpp"
+#include <boost/locale/util/string.hpp>
#if BOOST_LOCALE_USE_WIN32_API
-# include "boost/locale/util/win_codepages.hpp"
+# include "win_codepages.hpp"
# ifndef NOMINMAX
# define NOMINMAX
# endif
@@ -18,7 +18,7 @@
#include <cstring>
namespace boost { namespace locale { namespace util {
- std::string normalize_encoding(const string_view encoding)
+ std::string normalize_encoding(const core::string_view encoding)
{
std::string result;
result.reserve(encoding.length());
@@ -51,7 +51,7 @@ namespace boost { namespace locale { namespace util {
return -1;
}
- int encoding_to_windows_codepage(const string_view encoding)
+ int encoding_to_windows_codepage(const core::string_view encoding)
{
return normalized_encoding_to_windows_codepage(normalize_encoding(encoding));
}
diff --git a/contrib/restricted/boost/locale/src/boost/locale/util/encoding.hpp b/contrib/restricted/boost/locale/src/util/encoding.hpp
index 0f4c3b56e58..2f73d49a339 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/util/encoding.hpp
+++ b/contrib/restricted/boost/locale/src/util/encoding.hpp
@@ -1,6 +1,6 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
-// Copyright (c) 2022-2023 Alexander Grund
+// Copyright (c) 2022-2025 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
@@ -9,7 +9,7 @@
#define BOOST_LOCALE_UTIL_ENCODING_HPP
#include <boost/locale/config.hpp>
-#include <boost/utility/string_view.hpp>
+#include <boost/core/detail/string_view.hpp>
#include <cstdint>
#include <string>
#include <type_traits>
@@ -48,7 +48,7 @@ namespace boost { namespace locale { namespace util {
#endif
/// Make encoding lowercase and remove all non-alphanumeric characters
- BOOST_LOCALE_DECL std::string normalize_encoding(string_view encoding);
+ BOOST_LOCALE_DECL std::string normalize_encoding(core::string_view encoding);
/// True if the normalized encodings are equal
inline bool are_encodings_equal(const std::string& l, const std::string& r)
{
@@ -58,10 +58,10 @@ namespace boost { namespace locale { namespace util {
BOOST_LOCALE_DECL std::vector<std::string> get_simple_encodings();
#if BOOST_LOCALE_USE_WIN32_API
- int encoding_to_windows_codepage(string_view encoding);
+ int encoding_to_windows_codepage(core::string_view encoding);
#else
// Requires WinAPI -> Dummy returning invalid
- inline int encoding_to_windows_codepage(string_view) // LCOV_EXCL_LINE
+ inline int encoding_to_windows_codepage(core::string_view) // LCOV_EXCL_LINE
{
return -1; // LCOV_EXCL_LINE
}
diff --git a/contrib/restricted/boost/locale/src/boost/locale/util/foreach_char.hpp b/contrib/restricted/boost/locale/src/util/foreach_char.hpp
index 37328e12169..1c0dc35ff01 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/util/foreach_char.hpp
+++ b/contrib/restricted/boost/locale/src/util/foreach_char.hpp
@@ -9,7 +9,7 @@
#include <boost/locale/config.hpp>
-#ifndef BOOST_LOCALE_NO_CXX20_STRING8
+#ifdef __cpp_lib_char8_t
# define BOOST_LOCALE_FOREACH_CHAR_I_CHAR8_T(F) F(char8_t)
# define BOOST_LOCALE_FOREACH_CHAR_I2_CHAR8_T(F) F(char8_t)
#elif defined(__cpp_char8_t)
diff --git a/contrib/restricted/boost/locale/src/boost/locale/util/gregorian.cpp b/contrib/restricted/boost/locale/src/util/gregorian.cpp
index b0bc6e8a291..3183d4ae6cb 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/util/gregorian.cpp
+++ b/contrib/restricted/boost/locale/src/util/gregorian.cpp
@@ -4,11 +4,11 @@
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
-#include "boost/locale/util/gregorian.hpp"
+#include "gregorian.hpp"
#include <boost/locale/date_time.hpp>
#include <boost/locale/date_time_facet.hpp>
#include <boost/locale/hold_ptr.hpp>
-#include "boost/locale/util/timezone.hpp"
+#include "timezone.hpp"
#include <boost/assert.hpp>
#include <algorithm>
#include <cstdlib>
diff --git a/contrib/restricted/boost/locale/src/boost/locale/util/gregorian.hpp b/contrib/restricted/boost/locale/src/util/gregorian.hpp
index e3a3a462385..e3a3a462385 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/util/gregorian.hpp
+++ b/contrib/restricted/boost/locale/src/util/gregorian.hpp
diff --git a/contrib/restricted/boost/locale/src/boost/locale/util/iconv.hpp b/contrib/restricted/boost/locale/src/util/iconv.hpp
index ed8157ba978..ed8157ba978 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/util/iconv.hpp
+++ b/contrib/restricted/boost/locale/src/util/iconv.hpp
diff --git a/contrib/restricted/boost/locale/src/boost/locale/util/info.cpp b/contrib/restricted/boost/locale/src/util/info.cpp
index 2dcbbee1784..2dcbbee1784 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/util/info.cpp
+++ b/contrib/restricted/boost/locale/src/util/info.cpp
diff --git a/contrib/restricted/boost/locale/src/boost/locale/util/locale_data.cpp b/contrib/restricted/boost/locale/src/util/locale_data.cpp
index f95d28a5803..1fded47a90b 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/util/locale_data.cpp
+++ b/contrib/restricted/boost/locale/src/util/locale_data.cpp
@@ -1,19 +1,39 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
-// Copyright (c) 2022-2023 Alexander Grund
+// Copyright (c) 2022-2024 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/locale/util/locale_data.hpp>
-#include "boost/locale/util/encoding.hpp"
-#include "boost/locale/util/string.hpp"
+#include <boost/locale/util/string.hpp>
+#include "encoding.hpp"
#include <boost/assert.hpp>
#include <algorithm>
#include <stdexcept>
#include <string>
namespace boost { namespace locale { namespace util {
+ /// Convert uppercase ASCII to lower case, return true if converted
+ static bool make_lower(char& c)
+ {
+ if(is_upper_ascii(c)) {
+ c += 'a' - 'A';
+ return true;
+ } else
+ return false;
+ }
+
+ /// Convert lowercase ASCII to upper case, return true if converted
+ static bool make_upper(char& c)
+ {
+ if(is_lower_ascii(c)) {
+ c += 'A' - 'a';
+ return true;
+ } else
+ return false;
+ }
+
locale_data::locale_data()
{
reset();
@@ -28,6 +48,7 @@ namespace boost { namespace locale { namespace util {
void locale_data::reset()
{
language_ = "C";
+ script_.clear();
country_.clear();
encoding_ = "US-ASCII";
variant_.clear();
@@ -37,6 +58,8 @@ namespace boost { namespace locale { namespace util {
std::string locale_data::to_string() const
{
std::string result = language_;
+ if(!script_.empty())
+ (result += '_') += script_;
if(!country_.empty())
(result += '_') += country_;
if(!encoding_.empty() && !util::are_encodings_equal(encoding_, "US-ASCII"))
@@ -60,9 +83,7 @@ namespace boost { namespace locale { namespace util {
return false;
// lowercase ASCII
for(char& c : tmp) {
- if(is_upper_ascii(c))
- c += 'a' - 'A';
- else if(!is_lower_ascii(c))
+ if(!is_lower_ascii(c) && !make_lower(c))
return false;
}
if(tmp != "c" && tmp != "posix") // Keep default
@@ -71,6 +92,33 @@ namespace boost { namespace locale { namespace util {
if(end >= input.size())
return true;
else if(input[end] == '-' || input[end] == '_')
+ return parse_from_script(input.substr(end + 1));
+ else if(input[end] == '.')
+ return parse_from_encoding(input.substr(end + 1));
+ else {
+ BOOST_ASSERT_MSG(input[end] == '@', "Unexpected delimiter");
+ return parse_from_variant(input.substr(end + 1));
+ }
+ }
+
+ bool locale_data::parse_from_script(const std::string& input)
+ {
+ const auto end = input.find_first_of("-_@.");
+ std::string tmp = input.substr(0, end);
+ // Script is exactly 4 ASCII characters, otherwise it is not present
+ if(tmp.length() != 4)
+ return parse_from_country(input);
+
+ for(char& c : tmp) {
+ if(!is_lower_ascii(c) && !make_lower(c))
+ return parse_from_country(input);
+ }
+ make_upper(tmp[0]); // Capitalize first letter only
+ script_ = tmp;
+
+ if(end >= input.size())
+ return true;
+ else if(input[end] == '-' || input[end] == '_')
return parse_from_country(input.substr(end + 1));
else if(input[end] == '.')
return parse_from_encoding(input.substr(end + 1));
@@ -91,10 +139,9 @@ namespace boost { namespace locale { namespace util {
return false;
// Make uppercase
- for(char& c : tmp) {
- if(util::is_lower_ascii(c))
- c += 'A' - 'a';
- }
+ for(char& c : tmp)
+ make_upper(c);
+
// If it's ALL uppercase ASCII, assume ISO 3166 country id
if(std::find_if_not(tmp.begin(), tmp.end(), util::is_upper_ascii) != tmp.end()) {
// else handle special cases:
@@ -142,20 +189,16 @@ namespace boost { namespace locale { namespace util {
return false;
variant_ = input;
// No assumptions, just make it lowercase
- for(char& c : variant_) {
- if(util::is_upper_ascii(c))
- c += 'a' - 'A';
- }
+ for(char& c : variant_)
+ make_lower(c);
return true;
}
locale_data& locale_data::encoding(std::string new_encoding, const bool uppercase)
{
if(uppercase) {
- for(char& c : new_encoding) {
- if(util::is_lower_ascii(c))
- c += 'A' - 'a';
- }
+ for(char& c : new_encoding)
+ make_upper(c);
}
encoding_ = std::move(new_encoding);
utf8_ = util::normalize_encoding(encoding_) == "utf8";
diff --git a/contrib/restricted/boost/locale/src/boost/locale/util/make_std_unique.hpp b/contrib/restricted/boost/locale/src/util/make_std_unique.hpp
index d7492adc039..d7492adc039 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/util/make_std_unique.hpp
+++ b/contrib/restricted/boost/locale/src/util/make_std_unique.hpp
diff --git a/contrib/restricted/boost/locale/src/boost/locale/util/numeric.hpp b/contrib/restricted/boost/locale/src/util/numeric.hpp
index 146309e3576..e54c95c5580 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/util/numeric.hpp
+++ b/contrib/restricted/boost/locale/src/util/numeric.hpp
@@ -10,11 +10,8 @@
#include <boost/locale/info.hpp>
#include <boost/predef/os.h>
#include <algorithm>
-#include <cerrno>
-#include <cstdlib>
#include <ctime>
#include <ios>
-#include <limits>
#include <locale>
#include <sstream>
#include <string>
@@ -23,22 +20,6 @@
#include "timezone.hpp"
namespace boost { namespace locale { namespace util {
-
- inline bool try_to_int(const std::string& s, int& res)
- {
- if(s.empty())
- return false;
- errno = 0;
- char* end_char{};
- const auto v = std::strtol(s.c_str(), &end_char, 10);
- if(errno == ERANGE || end_char != s.c_str() + s.size())
- return false;
- if(v < std::numeric_limits<int>::min() || v > std::numeric_limits<int>::max())
- return false;
- res = v;
- return true;
- }
-
template<typename CharType>
struct formatting_size_traits {
static size_t size(const std::basic_string<CharType>& s, const std::locale& /*l*/) { return s.size(); }
@@ -175,11 +156,11 @@ namespace boost { namespace locale { namespace util {
iter_type
format_time(iter_type out, std::ios_base& ios, CharType fill, std::time_t time, const string_type& format) const
{
- std::string tz = ios_info::get(ios).time_zone();
- std::tm tm;
-#if BOOST_OS_LINUX || BOOST_OS_BSD_FREE || defined(__APPLE__)
- std::vector<char> tmp_buf(tz.c_str(), tz.c_str() + tz.size() + 1);
+ const std::string& tz = ios_info::get(ios).time_zone();
+#if BOOST_OS_BSD_FREE || defined(__APPLE__)
+ std::vector<char> tz_nonconst;
#endif
+ std::tm tm;
if(tz.empty()) {
#ifdef BOOST_WINDOWS
// Windows uses TLS
@@ -200,8 +181,13 @@ namespace boost { namespace locale { namespace util {
#if BOOST_OS_LINUX || BOOST_OS_BSD_FREE || defined(__APPLE__)
// These have extra fields to specify timezone
if(gmtoff != 0) {
+# if BOOST_OS_BSD_FREE || defined(__APPLE__)
// bsd and apple want tm_zone be non-const
- tm.tm_zone = tmp_buf.data();
+ tz_nonconst.assign(tz.begin(), tz.end());
+ tm.tm_zone = tz_nonconst.data();
+# else
+ tm.tm_zone = tz.data();
+# endif
tm.tm_gmtoff = gmtoff;
}
#endif
diff --git a/contrib/restricted/boost/locale/src/util/numeric_conversion.hpp b/contrib/restricted/boost/locale/src/util/numeric_conversion.hpp
new file mode 100644
index 00000000000..5cc15bf9e77
--- /dev/null
+++ b/contrib/restricted/boost/locale/src/util/numeric_conversion.hpp
@@ -0,0 +1,147 @@
+//
+// Copyright (c) 2024-2025 Alexander Grund
+//
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_LOCALE_IMPL_UTIL_NUMERIC_CONVERSIONS_HPP
+#define BOOST_LOCALE_IMPL_UTIL_NUMERIC_CONVERSIONS_HPP
+
+#include <boost/locale/config.hpp>
+#include <boost/assert.hpp>
+#include <boost/charconv/from_chars.hpp>
+#include <boost/core/detail/string_view.hpp>
+#include <algorithm>
+#include <array>
+#include <limits>
+#include <type_traits>
+#ifdef BOOST_LOCALE_WITH_ICU
+# include <unicode/fmtable.h>
+#endif
+
+namespace boost { namespace locale { namespace util {
+ namespace {
+
+ // Create lookup table where: powers_of_10[i] == 10**i
+ constexpr uint64_t pow10(unsigned exponent)
+ {
+ return (exponent == 0) ? 1 : pow10(exponent - 1) * 10u;
+ }
+ template<bool condition, std::size_t Length>
+ using array_if_true = typename std::enable_if<condition, std::array<uint64_t, Length>>::type;
+
+ template<std::size_t Length, typename... Values>
+ constexpr array_if_true<sizeof...(Values) == Length, Length> make_powers_of_10(Values... values)
+ {
+ return {{values...}};
+ }
+ template<std::size_t Length, typename... Values>
+ constexpr array_if_true<sizeof...(Values) < Length, Length> make_powers_of_10(Values... values)
+ {
+ return make_powers_of_10<Length>(values..., pow10(sizeof...(Values)));
+ }
+ constexpr auto powers_of_10 = make_powers_of_10<std::numeric_limits<uint64_t>::digits10 + 1>();
+#ifndef BOOST_NO_CXX14_CONSTEXPR
+ static_assert(powers_of_10[0] == 1u, "!");
+ static_assert(powers_of_10[1] == 10u, "!");
+ static_assert(powers_of_10[5] == 100000u, "!");
+#endif
+ } // namespace
+
+ template<typename Integer>
+ bool try_to_int(core::string_view s, Integer& value)
+ {
+ if(s.size() >= 2 && s[0] == '+') {
+ if(s[1] == '-') // "+-" is not allowed, invalid "+<number>" is detected by parser
+ return false;
+ s.remove_prefix(1);
+ }
+ const auto res = boost::charconv::from_chars(s, value);
+ return res && res.ptr == (s.data() + s.size());
+ }
+
+ /// Parse a string in scientific format to an integer.
+ /// In particular the "E notation" is used.
+ /// I.e. "\d.\d+E\d+", e.g. 5.12E3 == 5120; 5E2 == 500; 2E+1 == 20)
+ /// Additionally plain integers are recognized.
+ template<typename Integer>
+ bool try_scientific_to_int(const core::string_view s, Integer& value)
+ {
+ static_assert(std::is_integral<Integer>::value && std::is_unsigned<Integer>::value,
+ "Must be an unsigned integer");
+ if(s.size() < 3) // At least: iEj for E notation
+ return try_to_int(s, value);
+ if(s[0] == '-')
+ return false;
+ constexpr auto maxDigits = std::numeric_limits<Integer>::digits10 + 1;
+
+ const auto expPos = s.find('E', 1);
+ if(expPos == core::string_view::npos)
+ return (s[1] != '.') && try_to_int(s, value); // Shortcut: Regular integer
+ uint8_t exponent; // Negative exponent would be a fractional
+ if(BOOST_UNLIKELY(!try_to_int(s.substr(expPos + 1), exponent)))
+ return false;
+
+ core::string_view significant = s.substr(0, expPos);
+ Integer significant_value;
+ if(s[1] == '.') {
+ const auto numSignificantDigits = significant.size() - 1u; // Exclude dot
+ const auto numDigits = exponent + 1u; // E0 -> 1 digit
+ if(BOOST_UNLIKELY(numDigits < numSignificantDigits))
+ return false; // Fractional
+ else if(BOOST_UNLIKELY(numDigits > maxDigits))
+ return false; // Too large
+ // Factor to get from the fractional number to an integer
+ BOOST_ASSERT(numSignificantDigits - 1u < powers_of_10.size());
+ const auto factor = static_cast<Integer>(powers_of_10[numSignificantDigits - 1]);
+ exponent = static_cast<uint8_t>(numDigits - numSignificantDigits);
+
+ const unsigned firstDigit = significant[0] - '0';
+ if(firstDigit > 9u)
+ return false; // Not a digit
+ if(numSignificantDigits == maxDigits) {
+ const auto maxFirstDigit = std::numeric_limits<Integer>::max() / powers_of_10[maxDigits - 1];
+ if(firstDigit > maxFirstDigit)
+ return false;
+ }
+ significant.remove_prefix(2);
+ if(BOOST_UNLIKELY(!try_to_int(significant, significant_value)))
+ return false;
+ // firstDigit * factor + significant_value <= max
+ if(static_cast<Integer>(firstDigit) > (std::numeric_limits<Integer>::max() - significant_value) / factor)
+ return false;
+ significant_value += static_cast<Integer>(firstDigit * factor);
+ } else if(BOOST_UNLIKELY(significant.size() + exponent > maxDigits))
+ return false;
+ else if(BOOST_UNLIKELY(!try_to_int(significant, significant_value)))
+ return false;
+ // Add zeros if necessary
+ if(exponent > 0u) {
+ BOOST_ASSERT(exponent < powers_of_10.size());
+ const auto factor = static_cast<Integer>(powers_of_10[exponent]);
+ if(significant_value > std::numeric_limits<Integer>::max() / factor)
+ return false;
+ value = significant_value * factor;
+ } else
+ value = significant_value;
+ return true;
+ }
+
+#ifdef BOOST_LOCALE_WITH_ICU
+ template<typename Integer>
+ bool try_parse_icu(icu::Formattable& fmt, Integer& value)
+ {
+ if(!fmt.isNumeric())
+ return false;
+ // Get value as a decimal number and parse that
+ UErrorCode err = U_ZERO_ERROR;
+ const auto decimals = fmt.getDecimalNumber(err);
+ if(U_FAILURE(err))
+ return false; // Memory error LCOV_EXCL_LINE
+ const core::string_view s(decimals.data(), decimals.length());
+ return try_scientific_to_int(s, value);
+ }
+#endif
+}}} // namespace boost::locale::util
+
+#endif
diff --git a/contrib/restricted/boost/locale/src/boost/locale/util/timezone.hpp b/contrib/restricted/boost/locale/src/util/timezone.hpp
index 617f40a9772..617f40a9772 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/util/timezone.hpp
+++ b/contrib/restricted/boost/locale/src/util/timezone.hpp
diff --git a/contrib/restricted/boost/locale/src/boost/locale/util/win_codepages.hpp b/contrib/restricted/boost/locale/src/util/win_codepages.hpp
index 4c3df668b5d..4c3df668b5d 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/util/win_codepages.hpp
+++ b/contrib/restricted/boost/locale/src/util/win_codepages.hpp
diff --git a/contrib/restricted/boost/locale/src/boost/locale/win32/all_generator.hpp b/contrib/restricted/boost/locale/src/win32/all_generator.hpp
index 3cf7da94fb0..3cf7da94fb0 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/win32/all_generator.hpp
+++ b/contrib/restricted/boost/locale/src/win32/all_generator.hpp
diff --git a/contrib/restricted/boost/locale/src/boost/locale/win32/api.hpp b/contrib/restricted/boost/locale/src/win32/api.hpp
index 33791ef9689..e9b95b7ff5a 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/win32/api.hpp
+++ b/contrib/restricted/boost/locale/src/win32/api.hpp
@@ -15,7 +15,7 @@
#include <string>
#include <vector>
-#include "boost/locale/win32/lcid.hpp"
+#include "lcid.hpp"
#ifndef NOMINMAX
# define NOMINMAX
diff --git a/contrib/restricted/boost/locale/src/boost/locale/win32/collate.cpp b/contrib/restricted/boost/locale/src/win32/collate.cpp
index 16fe38d1f8d..dcdb2c99ea1 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/win32/collate.cpp
+++ b/contrib/restricted/boost/locale/src/win32/collate.cpp
@@ -6,9 +6,9 @@
#include <boost/locale/encoding.hpp>
#include <boost/locale/generator.hpp>
-#include "boost/locale/shared/mo_hash.hpp"
-#include "boost/locale/shared/std_collate_adapter.hpp"
-#include "boost/locale/win32/api.hpp"
+#include "../shared/mo_hash.hpp"
+#include "../shared/std_collate_adapter.hpp"
+#include "api.hpp"
#include <ios>
#include <locale>
#include <string>
diff --git a/contrib/restricted/boost/locale/src/boost/locale/win32/converter.cpp b/contrib/restricted/boost/locale/src/win32/converter.cpp
index ed29aedc69d..fe168df79d0 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/win32/converter.cpp
+++ b/contrib/restricted/boost/locale/src/win32/converter.cpp
@@ -7,8 +7,8 @@
#include <boost/locale/conversion.hpp>
#include <boost/locale/encoding.hpp>
#include <boost/locale/generator.hpp>
-#include "boost/locale/win32/all_generator.hpp"
-#include "boost/locale/win32/api.hpp"
+#include "all_generator.hpp"
+#include "api.hpp"
#include <cstring>
#include <locale>
#include <stdexcept>
@@ -62,7 +62,7 @@ namespace boost { namespace locale { namespace impl_win {
case char_facet_t::nochar: break;
case char_facet_t::char_f: return std::locale(in, new utf8_converter<char>(lc));
case char_facet_t::wchar_f: return std::locale(in, new wide_converter(lc));
-#ifndef BOOST_LOCALE_NO_CXX20_STRING8
+#ifdef __cpp_lib_char8_t
case char_facet_t::char8_f: return std::locale(in, new utf8_converter<char8_t>(lc));
#elif defined(__cpp_char8_t)
case char_facet_t::char8_f: break;
diff --git a/contrib/restricted/boost/locale/src/boost/locale/win32/lcid.cpp b/contrib/restricted/boost/locale/src/win32/lcid.cpp
index 1435455775c..e1b998d66b3 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/win32/lcid.cpp
+++ b/contrib/restricted/boost/locale/src/win32/lcid.cpp
@@ -8,7 +8,7 @@
# define NOMINMAX
#endif
-#include "boost/locale/win32/lcid.hpp"
+#include "lcid.hpp"
#include <boost/locale/util/locale_data.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/mutex.hpp>
diff --git a/contrib/restricted/boost/locale/src/boost/locale/win32/lcid.hpp b/contrib/restricted/boost/locale/src/win32/lcid.hpp
index 19a801d4a87..19a801d4a87 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/win32/lcid.hpp
+++ b/contrib/restricted/boost/locale/src/win32/lcid.hpp
diff --git a/contrib/restricted/boost/locale/src/boost/locale/win32/numeric.cpp b/contrib/restricted/boost/locale/src/win32/numeric.cpp
index 556de79a851..3286424e909 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/win32/numeric.cpp
+++ b/contrib/restricted/boost/locale/src/win32/numeric.cpp
@@ -4,12 +4,12 @@
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
-#include "boost/locale/util/numeric.hpp"
+#include "../util/numeric.hpp"
#include <boost/locale/encoding.hpp>
#include <boost/locale/formatting.hpp>
#include <boost/locale/generator.hpp>
-#include "boost/locale/win32/all_generator.hpp"
-#include "boost/locale/win32/api.hpp"
+#include "all_generator.hpp"
+#include "api.hpp"
#include <algorithm>
#include <cctype>
#include <cstdlib>
diff --git a/contrib/restricted/boost/locale/src/boost/locale/win32/win_backend.cpp b/contrib/restricted/boost/locale/src/win32/win_backend.cpp
index 48155d6c23c..2ce4d460892 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/win32/win_backend.cpp
+++ b/contrib/restricted/boost/locale/src/win32/win_backend.cpp
@@ -5,17 +5,17 @@
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
-#include "boost/locale/win32/win_backend.hpp"
+#include "win_backend.hpp"
#include <boost/locale/gnu_gettext.hpp>
#include <boost/locale/info.hpp>
#include <boost/locale/localization_backend.hpp>
#include <boost/locale/util.hpp>
#include <boost/locale/util/locale_data.hpp>
-#include "boost/locale/shared/message.hpp"
-#include "boost/locale/util/gregorian.hpp"
-#include "boost/locale/util/make_std_unique.hpp"
-#include "boost/locale/win32/all_generator.hpp"
-#include "boost/locale/win32/api.hpp"
+#include "../shared/message.hpp"
+#include "../util/gregorian.hpp"
+#include "../util/make_std_unique.hpp"
+#include "all_generator.hpp"
+#include "api.hpp"
#include <algorithm>
#include <iterator>
#include <vector>
diff --git a/contrib/restricted/boost/locale/src/boost/locale/win32/win_backend.hpp b/contrib/restricted/boost/locale/src/win32/win_backend.hpp
index 8980535e742..8980535e742 100644
--- a/contrib/restricted/boost/locale/src/boost/locale/win32/win_backend.hpp
+++ b/contrib/restricted/boost/locale/src/win32/win_backend.hpp
diff --git a/contrib/restricted/boost/locale/ya.make b/contrib/restricted/boost/locale/ya.make
index 9576428064a..f2b80c5b7af 100644
--- a/contrib/restricted/boost/locale/ya.make
+++ b/contrib/restricted/boost/locale/ya.make
@@ -6,19 +6,19 @@ LICENSE(BSL-1.0)
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-VERSION(1.87.0)
+VERSION(1.88.0)
-ORIGINAL_SOURCE(https://github.com/boostorg/locale/archive/boost-1.87.0.tar.gz)
+ORIGINAL_SOURCE(https://github.com/boostorg/locale/archive/boost-1.88.0.tar.gz)
PEERDIR(
contrib/libs/icu
contrib/restricted/boost/assert
+ contrib/restricted/boost/charconv
contrib/restricted/boost/config
contrib/restricted/boost/core
contrib/restricted/boost/iterator
contrib/restricted/boost/predef
contrib/restricted/boost/thread
- contrib/restricted/boost/utility
)
ADDINCL(
@@ -50,57 +50,56 @@ ELSEIF (OS_WINDOWS)
-DBOOST_LOCALE_NO_POSIX_BACKEND
)
SRCS(
- src/boost/locale/win32/collate.cpp
- src/boost/locale/win32/converter.cpp
- src/boost/locale/win32/lcid.cpp
- src/boost/locale/win32/numeric.cpp
- src/boost/locale/win32/win_backend.cpp
+ src/win32/collate.cpp
+ src/win32/converter.cpp
+ src/win32/lcid.cpp
+ src/win32/numeric.cpp
+ src/win32/win_backend.cpp
)
ELSE()
CFLAGS(
-DBOOST_LOCALE_NO_WINAPI_BACKEND
)
SRCS(
- src/boost/locale/posix/codecvt.cpp
- src/boost/locale/posix/collate.cpp
- src/boost/locale/posix/converter.cpp
- src/boost/locale/posix/numeric.cpp
- src/boost/locale/posix/posix_backend.cpp
+ src/posix/codecvt.cpp
+ src/posix/collate.cpp
+ src/posix/converter.cpp
+ src/posix/numeric.cpp
+ src/posix/posix_backend.cpp
)
ENDIF()
SRCS(
- src/boost/locale/encoding/codepage.cpp
- src/boost/locale/icu/boundary.cpp
- src/boost/locale/icu/codecvt.cpp
- src/boost/locale/icu/collator.cpp
- src/boost/locale/icu/conversion.cpp
- src/boost/locale/icu/date_time.cpp
- src/boost/locale/icu/formatter.cpp
- src/boost/locale/icu/formatters_cache.cpp
- src/boost/locale/icu/icu_backend.cpp
- src/boost/locale/icu/numeric.cpp
- src/boost/locale/icu/time_zone.cpp
- src/boost/locale/shared/date_time.cpp
- src/boost/locale/shared/format.cpp
- src/boost/locale/shared/formatting.cpp
- src/boost/locale/shared/generator.cpp
- src/boost/locale/shared/iconv_codecvt.cpp
- src/boost/locale/shared/ids.cpp
- src/boost/locale/shared/localization_backend.cpp
- src/boost/locale/shared/message.cpp
- src/boost/locale/shared/mo_lambda.cpp
- src/boost/locale/std/codecvt.cpp
- src/boost/locale/std/collate.cpp
- src/boost/locale/std/converter.cpp
- src/boost/locale/std/numeric.cpp
- src/boost/locale/std/std_backend.cpp
- src/boost/locale/util/codecvt_converter.cpp
- src/boost/locale/util/default_locale.cpp
- src/boost/locale/util/encoding.cpp
- src/boost/locale/util/gregorian.cpp
- src/boost/locale/util/info.cpp
- src/boost/locale/util/locale_data.cpp
+ src/encoding/codepage.cpp
+ src/icu/boundary.cpp
+ src/icu/codecvt.cpp
+ src/icu/collator.cpp
+ src/icu/conversion.cpp
+ src/icu/date_time.cpp
+ src/icu/formatter.cpp
+ src/icu/formatters_cache.cpp
+ src/icu/icu_backend.cpp
+ src/icu/numeric.cpp
+ src/shared/date_time.cpp
+ src/shared/format.cpp
+ src/shared/formatting.cpp
+ src/shared/generator.cpp
+ src/shared/iconv_codecvt.cpp
+ src/shared/ids.cpp
+ src/shared/localization_backend.cpp
+ src/shared/message.cpp
+ src/shared/mo_lambda.cpp
+ src/std/codecvt.cpp
+ src/std/collate.cpp
+ src/std/converter.cpp
+ src/std/numeric.cpp
+ src/std/std_backend.cpp
+ src/util/codecvt_converter.cpp
+ src/util/default_locale.cpp
+ src/util/encoding.cpp
+ src/util/gregorian.cpp
+ src/util/info.cpp
+ src/util/locale_data.cpp
)
END()