@lucent-lang/lucent 0.0.4 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +97 -0
- package/app.plugin.js +46 -10
- package/dist/{bench-CR3E7e2e.js → bench-B555m0wU.js} +10 -6
- package/dist/{build-CAIrRSYA.js → build-UZ5Zm5m6.js} +1 -1
- package/dist/{build-check-QozuNJm5.js → build-check-Dmf8_yiw.js} +28 -13
- package/dist/{check-1SCmYlqA.js → check-D-H9WLG4.js} +1 -1
- package/dist/cli.js +62 -13
- package/dist/{codes-CIuwXt1S.js → codes-D-6LxUqD.js} +163 -7
- package/dist/compiler.js +4 -4
- package/dist/{dashboard-B-NzjjaN.js → dashboard-C8iF5-6T.js} +2 -2
- package/dist/{dev-BYWMP7oC.js → dev-B3lSx5CF.js} +62 -23
- package/dist/{diagnostic-BM9sXmwl.js → diagnostic-BvwLZQS1.js} +3 -1
- package/dist/{doctor-C0PrfWT6.js → doctor-CTAX3euc.js} +1 -1
- package/dist/{doctor-DdR4JnVc.js → doctor-CrgOAV5L.js} +1 -1
- package/dist/{explain--vV1oaRl.js → explain-Byit07F-.js} +1 -1
- package/dist/{packages-HyskKIsY.js → packages-CSmKeaAh.js} +2 -33
- package/dist/pipeline-BBY0df_2.js +700 -0
- package/dist/project-BLhWwnns.js +342 -0
- package/dist/sdk-coverage-DFGiDOzR.js +113 -0
- package/dist/sdk-diff-DpPYWzrl.js +109 -0
- package/dist/sdk-lock-QOxEFD1o.js +38 -0
- package/dist/{sdk-prefetch-mo04JDZV.js → sdk-prefetch-DX6ztlPN.js} +2 -2
- package/dist/{sdk-search-Iv4K3-8a.js → sdk-search-BShBL1LL.js} +2 -2
- package/dist/{sdk-show-CkrdlqlP.js → sdk-show-B3bI-0M7.js} +5 -4
- package/dist/sdk-usage-ljX5bTuZ.js +95 -0
- package/dist/src-DlICbK91.js +39682 -0
- package/dist/trace-Bi4hkmPx.js +139 -0
- package/lib/core.cjs +368 -1
- package/lib/sdk/android.d.ts +54 -1
- package/lib/sdk/compose.d.ts +94 -0
- package/lib/sdk/compose.schemas.json.gz +0 -0
- package/lib/sdk/core.d.ts +201 -0
- package/lib/sdk/ios.d.ts +75 -2
- package/lib/sdk/ui.d.ts +129 -0
- package/metro/transformer.cjs +11 -2
- package/package.json +2 -1
- package/runtime/cpp/lucent/abort.cpp +59 -11
- package/runtime/cpp/lucent/abort.h +22 -6
- package/runtime/cpp/lucent/array.h +12 -2
- package/runtime/cpp/lucent/async.h +101 -21
- package/runtime/cpp/lucent/bigint.cpp +898 -0
- package/runtime/cpp/lucent/bigint.h +302 -0
- package/runtime/cpp/lucent/buffer.cpp +228 -0
- package/runtime/cpp/lucent/buffer.h +328 -0
- package/runtime/cpp/lucent/builtins.cpp +4 -1
- package/runtime/cpp/lucent/bytes.h +21 -2
- package/runtime/cpp/lucent/callback.cpp +29 -0
- package/runtime/cpp/lucent/callback.h +230 -0
- package/runtime/cpp/lucent/compute.cpp +370 -0
- package/runtime/cpp/lucent/compute.h +455 -0
- package/runtime/cpp/lucent/conversions.h +111 -0
- package/runtime/cpp/lucent/core.h +16 -5
- package/runtime/cpp/lucent/equality.h +107 -28
- package/runtime/cpp/lucent/execution.cpp +416 -0
- package/runtime/cpp/lucent/execution.h +270 -0
- package/runtime/cpp/lucent/extension.cpp +97 -0
- package/runtime/cpp/lucent/extension.h +210 -0
- package/runtime/cpp/lucent/helpers.h +12 -5
- package/runtime/cpp/lucent/items.h +52 -0
- package/runtime/cpp/lucent/jserror.cpp +9 -0
- package/runtime/cpp/lucent/jserror.h +11 -0
- package/runtime/cpp/lucent/jsi/convert.cpp +138 -0
- package/runtime/cpp/lucent/jsi/convert.h +128 -59
- package/runtime/cpp/lucent/jsi/host.cpp +213 -35
- package/runtime/cpp/lucent/jsi/host.h +116 -16
- package/runtime/cpp/lucent/json.h +19 -1
- package/runtime/cpp/lucent/lifecycle.cpp +260 -0
- package/runtime/cpp/lucent/lifecycle.h +124 -0
- package/runtime/cpp/lucent/lucent.h +7 -0
- package/runtime/cpp/lucent/map.h +41 -7
- package/runtime/cpp/lucent/native.cpp +35 -47
- package/runtime/cpp/lucent/native.h +116 -26
- package/runtime/cpp/lucent/number.cpp +38 -38
- package/runtime/cpp/lucent/number.h +33 -0
- package/runtime/cpp/lucent/operation.h +65 -0
- package/runtime/cpp/lucent/ops.h +14 -6
- package/runtime/cpp/lucent/platform/android.cpp +223 -10
- package/runtime/cpp/lucent/platform/android.h +227 -4
- package/runtime/cpp/lucent/platform/android_activity.cpp +258 -0
- package/runtime/cpp/lucent/platform/android_requests.h +140 -0
- package/runtime/cpp/lucent/platform/compose.h +256 -0
- package/runtime/cpp/lucent/platform/ios.h +325 -25
- package/runtime/cpp/lucent/platform/ios.mm +1 -14
- package/runtime/cpp/lucent/platform/ios_ui.h +192 -0
- package/runtime/cpp/lucent/platform/ios_ui.mm +454 -0
- package/runtime/cpp/lucent/platform/swiftui.h +190 -0
- package/runtime/cpp/lucent/presentation.cpp +11 -0
- package/runtime/cpp/lucent/presentation.h +109 -0
- package/runtime/cpp/lucent/reactive.cpp +406 -0
- package/runtime/cpp/lucent/reactive.h +566 -0
- package/runtime/cpp/lucent/report.cpp +40 -0
- package/runtime/cpp/lucent/report.h +16 -0
- package/runtime/cpp/lucent/resource.cpp +83 -0
- package/runtime/cpp/lucent/resource.h +75 -0
- package/runtime/cpp/lucent/scheduler.cpp +38 -124
- package/runtime/cpp/lucent/scheduler.h +102 -83
- package/runtime/cpp/lucent/scope.cpp +308 -0
- package/runtime/cpp/lucent/scope.h +452 -0
- package/runtime/cpp/lucent/sizing.h +263 -0
- package/runtime/cpp/lucent/slots.h +231 -0
- package/runtime/cpp/lucent/trace.cpp +539 -0
- package/runtime/cpp/lucent/trace.h +251 -0
- package/runtime/cpp/lucent/transport.cpp +9 -0
- package/runtime/cpp/lucent/transport.h +341 -0
- package/runtime/cpp/lucent/view.cpp +123 -0
- package/runtime/cpp/lucent/view.h +157 -0
- package/runtime/cpp/rn/LucentComponentView.h +121 -0
- package/runtime/cpp/rn/LucentComponentView.mm +479 -0
- package/runtime/cpp/rn/LucentModule.cpp +37 -7
- package/runtime/cpp/rn/LucentModule.h +3 -0
- package/runtime/cpp/rn/LucentViewChildren.h +80 -0
- package/runtime/cpp/rn/LucentViewChildren.mm +211 -0
- package/runtime/cpp/rn/LucentViewRegistry.h +62 -0
- package/runtime/cpp/rn/LucentViewRequests.cpp +91 -0
- package/runtime/cpp/rn/LucentViewRequests.h +104 -0
- package/runtime/cpp/rn/LucentViewSizing.h +345 -0
- package/runtime/cpp/rn/LucentViewSlots.h +242 -0
- package/runtime/cpp/rn/LucentViewValues.h +125 -0
- package/runtime/cpp/rn/LucentViews.h +440 -0
- package/runtime/cpp/rn/LucentViewsAndroid.cpp +439 -0
- package/runtime/cpp/rn/LucentViewsAndroid.h +138 -0
- package/runtime/cpp/third_party/dragonbox/LICENSE-Boost +23 -0
- package/runtime/cpp/third_party/dragonbox/README.md +16 -0
- package/runtime/cpp/third_party/dragonbox/dragonbox.h +4440 -0
- package/runtime/js/index.d.ts +11 -1
- package/runtime/js/index.js +84 -8
- package/runtime/js/views.d.ts +38 -0
- package/runtime/js/views.js +226 -0
- package/runtime/native/android/CMakeLists.txt +4 -1
- package/runtime/native/android/src/compose/java/dev/lucent/compose/CompositionRules.kt +44 -0
- package/runtime/native/android/src/compose/java/dev/lucent/compose/LucentComposition.kt +161 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentActivities.java +292 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentChildren.java +174 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentHostView.java +232 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentInitializer.java +46 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentPackage.java +4 -3
- package/runtime/native/android/src/main/java/dev/lucent/LucentRequestActivity.java +92 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentSlotView.java +102 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentViewManager.java +149 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentViewManagers.java +16 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentViews.java +44 -0
- package/runtime/test/jsi/harness.cpp +9 -0
- package/schemas/build.schema.json +96 -1
- package/schemas/check.schema.json +56 -1
- package/schemas/lucent.schema.json +495 -9
- package/schemas/sdk-diff.schema.json +70 -0
- package/schemas/sdk-lock.schema.json +67 -0
- package/ts-plugin/index.js +77 -4
- package/dist/pipeline-CH7-2cxu.js +0 -232
- package/dist/project-D8tEet0k.js +0 -150
- package/dist/sdk-coverage-BoW_3Efd.js +0 -64
- package/dist/src-BD7f1_aZ.js +0 -11493
|
@@ -0,0 +1,4440 @@
|
|
|
1
|
+
// Copyright 2020-2025 Junekey Jeon
|
|
2
|
+
//
|
|
3
|
+
// The contents of this file may be used under the terms of
|
|
4
|
+
// the Apache License v2.0 with LLVM Exceptions.
|
|
5
|
+
//
|
|
6
|
+
// (See accompanying file LICENSE-Apache or copy at
|
|
7
|
+
// https://llvm.org/foundation/relicensing/LICENSE.txt)
|
|
8
|
+
//
|
|
9
|
+
// Alternatively, the contents of this file may be used under the terms of
|
|
10
|
+
// the Boost Software License, Version 1.0.
|
|
11
|
+
// (See accompanying file LICENSE-Boost or copy at
|
|
12
|
+
// https://www.boost.org/LICENSE_1_0.txt)
|
|
13
|
+
//
|
|
14
|
+
// Unless required by applicable law or agreed to in writing, this software
|
|
15
|
+
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
16
|
+
// KIND, either express or implied.
|
|
17
|
+
|
|
18
|
+
// We want to achieve the followings regarding the macro leakage of this header file:
|
|
19
|
+
// - Normally, no macro other than the header guard JKJ_HEADER_DRAGONBOX is leaked.
|
|
20
|
+
// - For internal library use, macros defined below are leaked if explicitly requested.
|
|
21
|
+
// - This header file does not include any other header file in this library.
|
|
22
|
+
// - The order of inclusions and repeated inclusions of header files in this library must not matter.
|
|
23
|
+
// To achieve all of these at once, we do some preprocessing hack:
|
|
24
|
+
// - Macros are populated if JKJ_HEADER_DRAGONBOX is not defined (which means the header file is being
|
|
25
|
+
// included for the first time), or JKJ_DRAGONBOX_LEAK_MACROS is defined and
|
|
26
|
+
// JKJ_DRAGONBOX_MACROS_DEFINED is not defined at the same time.
|
|
27
|
+
// - JKJ_DRAGONBOX_MACROS_DEFINED is defined at the end of this header file if (and only if)
|
|
28
|
+
// JKJ_DRAGONBOX_LEAK_MACROS is defined.
|
|
29
|
+
// - The actual content (excluding the macros) of this header file is guarded by JKJ_HEADER_DRAGONBOX
|
|
30
|
+
// as usual.
|
|
31
|
+
// - JKJ_DRAGONBOX_MACROS_DEFINED and all macros defined below except for JKJ_HEADER_DRAGONBOX are
|
|
32
|
+
// #undef-ed at the end of this header if JKJ_DRAGONBOX_LEAK_MACROS is not defined.
|
|
33
|
+
|
|
34
|
+
#ifndef JKJ_HEADER_DRAGONBOX
|
|
35
|
+
// User-provided header file that contains declarations of custom implementations and config macros.
|
|
36
|
+
#ifdef JKJ_DRAGONBOX_CONFIG_HEADER_NAMES
|
|
37
|
+
#include JKJ_DRAGONBOX_CONFIG_HEADER_NAME
|
|
38
|
+
#endif
|
|
39
|
+
#endif
|
|
40
|
+
|
|
41
|
+
#if !defined(JKJ_HEADER_DRAGONBOX) || \
|
|
42
|
+
(defined(JKJ_DRAGONBOX_LEAK_MACROS) && !defined(JKJ_DRAGONBOX_MACROS_DEFINED))
|
|
43
|
+
// Users vendoring this library are advised to define the macro JKJ_NAMESPACE to avoid potential
|
|
44
|
+
// clash with other libraries vendoring this library. Every (non-macro) entity in this library will
|
|
45
|
+
// live inside the namespace JKJ_NAMESPACE, whose default is "jkj".
|
|
46
|
+
#ifndef JKJ_NAMESPACE
|
|
47
|
+
#define JKJ_NAMESPACE jkj
|
|
48
|
+
#else
|
|
49
|
+
#define JKJ_NAMESPACE_DEFINED 1
|
|
50
|
+
#endif
|
|
51
|
+
|
|
52
|
+
// Attribute for storing static data into a dedicated place, e.g. flash memory. Every ODR-used
|
|
53
|
+
// static data declaration will be decorated with this macro. The users may define this macro,
|
|
54
|
+
// before including the library headers, into whatever they want.
|
|
55
|
+
#ifndef JKJ_STATIC_DATA_SECTION
|
|
56
|
+
#define JKJ_STATIC_DATA_SECTION
|
|
57
|
+
#else
|
|
58
|
+
#define JKJ_STATIC_DATA_SECTION_DEFINED 1
|
|
59
|
+
#endif
|
|
60
|
+
|
|
61
|
+
// To use the library with toolchains without standard C++ headers, the users may define this macro
|
|
62
|
+
// into their custom namespace which contains the definitions of all the standard C++ library
|
|
63
|
+
// features used in this header. (The list can be found below.)
|
|
64
|
+
#ifndef JKJ_STD_REPLACEMENT_NAMESPACE
|
|
65
|
+
#define JKJ_STD_REPLACEMENT_NAMESPACE std
|
|
66
|
+
#include <cassert>
|
|
67
|
+
#include <cstdint>
|
|
68
|
+
#include <cstring>
|
|
69
|
+
#include <limits>
|
|
70
|
+
#include <type_traits>
|
|
71
|
+
|
|
72
|
+
#ifdef __has_include
|
|
73
|
+
#if __has_include(<version>)
|
|
74
|
+
#include <version>
|
|
75
|
+
#endif
|
|
76
|
+
#endif
|
|
77
|
+
#else
|
|
78
|
+
#define JKJ_STD_REPLACEMENT_NAMESPACE_DEFINED 1
|
|
79
|
+
#endif
|
|
80
|
+
|
|
81
|
+
// The compressed cache handling for IEEE-754 binary32 performs 64-bit x 32-bit -> 96-bit
|
|
82
|
+
// multiplication. The library chooses between 64-bit + 32-bit and 32-bit + 64-bit splittings of the
|
|
83
|
+
// 96-bit result depending on availability of fast 64-bit x 64-bit -> 64-bit multiplication of
|
|
84
|
+
// unsigned integers. By default, the latter is used if and only if one of the macros listed below
|
|
85
|
+
// is defined, but the user can override this behavior by defining JKJ_FAST_MUL64. This should have
|
|
86
|
+
// no impact on the codegen if compact cache for IEEE-754 binary32 is not used.
|
|
87
|
+
#ifndef JKJ_FAST_MUL64
|
|
88
|
+
#if defined(__x86_64__) || defined(__aarch64__) || defined(__ppc64__) || defined(_M_X64) || \
|
|
89
|
+
defined(_M_ARM64)
|
|
90
|
+
#define JKJ_FAST_MUL64 1
|
|
91
|
+
#else
|
|
92
|
+
#define JKJ_FAST_MUL64 0
|
|
93
|
+
#endif
|
|
94
|
+
#else
|
|
95
|
+
#define JKJ_FAST_MUL64_DEFINED 1
|
|
96
|
+
#endif
|
|
97
|
+
|
|
98
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
99
|
+
// Language feature detections.
|
|
100
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
101
|
+
|
|
102
|
+
// C++14 variable templates
|
|
103
|
+
#if defined(__cpp_variable_templates) && __cpp_variable_templates >= 201304L
|
|
104
|
+
#define JKJ_HAS_VARIABLE_TEMPLATES 1
|
|
105
|
+
#elif __cplusplus >= 201402L
|
|
106
|
+
#define JKJ_HAS_VARIABLE_TEMPLATES 1
|
|
107
|
+
#elif defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023918L && _MSVC_LANG >= 201402L
|
|
108
|
+
#define JKJ_HAS_VARIABLE_TEMPLATES 1
|
|
109
|
+
#else
|
|
110
|
+
#define JKJ_HAS_VARIABLE_TEMPLATES 0
|
|
111
|
+
#endif
|
|
112
|
+
|
|
113
|
+
// C++14 constexpr
|
|
114
|
+
#if defined(__cpp_constexpr) && __cpp_constexpr >= 201304L
|
|
115
|
+
#define JKJ_HAS_CONSTEXPR14 1
|
|
116
|
+
#elif __cplusplus >= 201402L
|
|
117
|
+
#define JKJ_HAS_CONSTEXPR14 1
|
|
118
|
+
#elif defined(_MSC_VER) && _MSC_VER >= 1910 && _MSVC_LANG >= 201402L
|
|
119
|
+
#define JKJ_HAS_CONSTEXPR14 1
|
|
120
|
+
#else
|
|
121
|
+
#define JKJ_HAS_CONSTEXPR14 0
|
|
122
|
+
#endif
|
|
123
|
+
|
|
124
|
+
#if JKJ_HAS_CONSTEXPR14
|
|
125
|
+
#define JKJ_CONSTEXPR14 constexpr
|
|
126
|
+
#else
|
|
127
|
+
#define JKJ_CONSTEXPR14
|
|
128
|
+
#endif
|
|
129
|
+
|
|
130
|
+
// C++17 constexpr lambdas
|
|
131
|
+
#if defined(__cpp_constexpr) && __cpp_constexpr >= 201603L
|
|
132
|
+
#define JKJ_HAS_CONSTEXPR17 1
|
|
133
|
+
#elif __cplusplus >= 201703L
|
|
134
|
+
#define JKJ_HAS_CONSTEXPR17 1
|
|
135
|
+
#elif defined(_MSC_VER) && _MSC_VER >= 1911 && _MSVC_LANG >= 201703L
|
|
136
|
+
#define JKJ_HAS_CONSTEXPR17 1
|
|
137
|
+
#else
|
|
138
|
+
#define JKJ_HAS_CONSTEXPR17 0
|
|
139
|
+
#endif
|
|
140
|
+
|
|
141
|
+
// C++17 inline variables
|
|
142
|
+
#if defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L
|
|
143
|
+
#define JKJ_HAS_INLINE_VARIABLE 1
|
|
144
|
+
#elif __cplusplus >= 201703L
|
|
145
|
+
#define JKJ_HAS_INLINE_VARIABLE 1
|
|
146
|
+
#elif defined(_MSC_VER) && _MSC_VER >= 1912 && _MSVC_LANG >= 201703L
|
|
147
|
+
#define JKJ_HAS_INLINE_VARIABLE 1
|
|
148
|
+
#else
|
|
149
|
+
#define JKJ_HAS_INLINE_VARIABLE 0
|
|
150
|
+
#endif
|
|
151
|
+
|
|
152
|
+
#if JKJ_HAS_INLINE_VARIABLE
|
|
153
|
+
#define JKJ_INLINE_VARIABLE inline constexpr
|
|
154
|
+
#else
|
|
155
|
+
#define JKJ_INLINE_VARIABLE static constexpr
|
|
156
|
+
#endif
|
|
157
|
+
|
|
158
|
+
// C++17 if constexpr
|
|
159
|
+
#if defined(__cpp_if_constexpr) && __cpp_if_constexpr >= 201606L
|
|
160
|
+
#define JKJ_HAS_IF_CONSTEXPR 1
|
|
161
|
+
#elif __cplusplus >= 201703L
|
|
162
|
+
#define JKJ_HAS_IF_CONSTEXPR 1
|
|
163
|
+
#elif defined(_MSC_VER) && _MSC_VER >= 1911 && _MSVC_LANG >= 201703L
|
|
164
|
+
#define JKJ_HAS_IF_CONSTEXPR 1
|
|
165
|
+
#else
|
|
166
|
+
#define JKJ_HAS_IF_CONSTEXPR 0
|
|
167
|
+
#endif
|
|
168
|
+
|
|
169
|
+
#if JKJ_HAS_IF_CONSTEXPR
|
|
170
|
+
#define JKJ_IF_CONSTEXPR if constexpr
|
|
171
|
+
#else
|
|
172
|
+
#define JKJ_IF_CONSTEXPR if
|
|
173
|
+
#endif
|
|
174
|
+
|
|
175
|
+
// C++20 std::bit_cast
|
|
176
|
+
#if JKJ_STD_REPLACEMENT_NAMESPACE_DEFINED
|
|
177
|
+
#if JKJ_STD_REPLACEMENT_HAS_BIT_CAST
|
|
178
|
+
#define JKJ_HAS_BIT_CAST 1
|
|
179
|
+
#else
|
|
180
|
+
#define JKJ_HAS_BIT_CAST 0
|
|
181
|
+
#endif
|
|
182
|
+
#elif defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L
|
|
183
|
+
#include <bit>
|
|
184
|
+
#define JKJ_HAS_BIT_CAST 1
|
|
185
|
+
#else
|
|
186
|
+
#define JKJ_HAS_BIT_CAST 0
|
|
187
|
+
#endif
|
|
188
|
+
|
|
189
|
+
// C++23 if consteval or C++20 std::is_constant_evaluated
|
|
190
|
+
#if defined(__cpp_if_consteval) && __cpp_is_consteval >= 202106L
|
|
191
|
+
#define JKJ_IF_CONSTEVAL if consteval
|
|
192
|
+
#define JKJ_IF_NOT_CONSTEVAL if !consteval
|
|
193
|
+
#define JKJ_CAN_BRANCH_ON_CONSTEVAL 1
|
|
194
|
+
#define JKJ_USE_IS_CONSTANT_EVALUATED 0
|
|
195
|
+
#elif JKJ_STD_REPLACEMENT_NAMESPACE_DEFINED
|
|
196
|
+
#if JKJ_STD_REPLACEMENT_HAS_IS_CONSTANT_EVALUATED
|
|
197
|
+
#define JKJ_IF_CONSTEVAL if (stdr::is_constant_evaluated())
|
|
198
|
+
#define JKJ_IF_NOT_CONSTEVAL if (!stdr::is_constant_evaluated())
|
|
199
|
+
#define JKJ_CAN_BRANCH_ON_CONSTEVAL 1
|
|
200
|
+
#define JKJ_USE_IS_CONSTANT_EVALUATED 1
|
|
201
|
+
#elif JKJ_HAS_IF_CONSTEXPR
|
|
202
|
+
#define JKJ_IF_CONSTEVAL if constexpr (false)
|
|
203
|
+
#define JKJ_IF_NOT_CONSTEVAL if constexpr (true)
|
|
204
|
+
#define JKJ_CAN_BRANCH_ON_CONSTEVAL 0
|
|
205
|
+
#define JKJ_USE_IS_CONSTANT_EVALUATED 0
|
|
206
|
+
#else
|
|
207
|
+
#define JKJ_IF_CONSTEVAL if (false)
|
|
208
|
+
#define JKJ_IF_NOT_CONSTEVAL if (true)
|
|
209
|
+
#define JKJ_CAN_BRANCH_ON_CONSTEVAL 0
|
|
210
|
+
#define JKJ_USE_IS_CONSTANT_EVALUATED 0
|
|
211
|
+
#endif
|
|
212
|
+
#else
|
|
213
|
+
#if defined(__cpp_lib_is_constant_evaluated) && __cpp_lib_is_constant_evaluated >= 201811L
|
|
214
|
+
#define JKJ_IF_CONSTEVAL if (stdr::is_constant_evaluated())
|
|
215
|
+
#define JKJ_IF_NOT_CONSTEVAL if (!stdr::is_constant_evaluated())
|
|
216
|
+
#define JKJ_CAN_BRANCH_ON_CONSTEVAL 1
|
|
217
|
+
#define JKJ_USE_IS_CONSTANT_EVALUATED 1
|
|
218
|
+
#elif JKJ_HAS_IF_CONSTEXPR
|
|
219
|
+
#define JKJ_IF_CONSTEVAL if constexpr (false)
|
|
220
|
+
#define JKJ_IF_NOT_CONSTEVAL if constexpr (true)
|
|
221
|
+
#define JKJ_CAN_BRANCH_ON_CONSTEVAL 0
|
|
222
|
+
#define JKJ_USE_IS_CONSTANT_EVALUATED 0
|
|
223
|
+
#else
|
|
224
|
+
#define JKJ_IF_CONSTEVAL if (false)
|
|
225
|
+
#define JKJ_IF_NOT_CONSTEVAL if (true)
|
|
226
|
+
#define JKJ_CAN_BRANCH_ON_CONSTEVAL 0
|
|
227
|
+
#define JKJ_USE_IS_CONSTANT_EVALUATED 0
|
|
228
|
+
#endif
|
|
229
|
+
#endif
|
|
230
|
+
|
|
231
|
+
#if JKJ_CAN_BRANCH_ON_CONSTEVAL && JKJ_HAS_BIT_CAST
|
|
232
|
+
#define JKJ_CONSTEXPR20 constexpr
|
|
233
|
+
#else
|
|
234
|
+
#define JKJ_CONSTEXPR20
|
|
235
|
+
#endif
|
|
236
|
+
|
|
237
|
+
// Suppress additional buffer overrun check.
|
|
238
|
+
// I have no idea why MSVC thinks some functions here are vulnerable to the buffer overrun
|
|
239
|
+
// attacks. No, they aren't.
|
|
240
|
+
#if defined(__GNUC__) || defined(__clang__)
|
|
241
|
+
#define JKJ_SAFEBUFFERS
|
|
242
|
+
#define JKJ_FORCEINLINE inline __attribute__((always_inline))
|
|
243
|
+
#elif defined(_MSC_VER)
|
|
244
|
+
#define JKJ_SAFEBUFFERS __declspec(safebuffers)
|
|
245
|
+
#define JKJ_FORCEINLINE __forceinline
|
|
246
|
+
#else
|
|
247
|
+
#define JKJ_SAFEBUFFERS
|
|
248
|
+
#define JKJ_FORCEINLINE inline
|
|
249
|
+
#endif
|
|
250
|
+
|
|
251
|
+
#if defined(__has_builtin)
|
|
252
|
+
#define JKJ_HAS_BUILTIN(x) __has_builtin(x)
|
|
253
|
+
#else
|
|
254
|
+
#define JKJ_HAS_BUILTIN(x) false
|
|
255
|
+
#endif
|
|
256
|
+
|
|
257
|
+
#if defined(_MSC_VER)
|
|
258
|
+
#include <intrin.h>
|
|
259
|
+
#elif defined(__INTEL_COMPILER)
|
|
260
|
+
#include <immintrin.h>
|
|
261
|
+
#endif
|
|
262
|
+
#endif
|
|
263
|
+
|
|
264
|
+
#ifndef JKJ_HEADER_DRAGONBOX
|
|
265
|
+
#define JKJ_HEADER_DRAGONBOX
|
|
266
|
+
|
|
267
|
+
namespace JKJ_NAMESPACE {
|
|
268
|
+
namespace dragonbox {
|
|
269
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
270
|
+
// The Compatibility layer for toolchains without standard C++ headers.
|
|
271
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
272
|
+
namespace detail {
|
|
273
|
+
namespace stdr {
|
|
274
|
+
// <bit>
|
|
275
|
+
#if JKJ_HAS_BIT_CAST
|
|
276
|
+
using JKJ_STD_REPLACEMENT_NAMESPACE::bit_cast;
|
|
277
|
+
#endif
|
|
278
|
+
|
|
279
|
+
// <cassert>
|
|
280
|
+
// We need assert() macro, but it is not namespaced anyway, so nothing to do here.
|
|
281
|
+
|
|
282
|
+
// <cstdint>
|
|
283
|
+
using JKJ_STD_REPLACEMENT_NAMESPACE::int_least8_t;
|
|
284
|
+
using JKJ_STD_REPLACEMENT_NAMESPACE::int_least16_t;
|
|
285
|
+
using JKJ_STD_REPLACEMENT_NAMESPACE::int_least32_t;
|
|
286
|
+
using JKJ_STD_REPLACEMENT_NAMESPACE::int_fast8_t;
|
|
287
|
+
using JKJ_STD_REPLACEMENT_NAMESPACE::int_fast16_t;
|
|
288
|
+
using JKJ_STD_REPLACEMENT_NAMESPACE::int_fast32_t;
|
|
289
|
+
using JKJ_STD_REPLACEMENT_NAMESPACE::uint_least8_t;
|
|
290
|
+
using JKJ_STD_REPLACEMENT_NAMESPACE::uint_least16_t;
|
|
291
|
+
using JKJ_STD_REPLACEMENT_NAMESPACE::uint_least32_t;
|
|
292
|
+
using JKJ_STD_REPLACEMENT_NAMESPACE::uint_least64_t;
|
|
293
|
+
using JKJ_STD_REPLACEMENT_NAMESPACE::uint_fast8_t;
|
|
294
|
+
using JKJ_STD_REPLACEMENT_NAMESPACE::uint_fast16_t;
|
|
295
|
+
using JKJ_STD_REPLACEMENT_NAMESPACE::uint_fast32_t;
|
|
296
|
+
using JKJ_STD_REPLACEMENT_NAMESPACE::uint_fast64_t;
|
|
297
|
+
// We need INT32_C, UINT32_C and UINT64_C macros too, but again there is nothing to do
|
|
298
|
+
// here.
|
|
299
|
+
|
|
300
|
+
// <cstring>
|
|
301
|
+
using JKJ_STD_REPLACEMENT_NAMESPACE::size_t;
|
|
302
|
+
using JKJ_STD_REPLACEMENT_NAMESPACE::memcpy;
|
|
303
|
+
|
|
304
|
+
// <limits>
|
|
305
|
+
template <class T>
|
|
306
|
+
using numeric_limits = JKJ_STD_REPLACEMENT_NAMESPACE::numeric_limits<T>;
|
|
307
|
+
|
|
308
|
+
// <type_traits>
|
|
309
|
+
template <bool cond, class T = void>
|
|
310
|
+
using enable_if = JKJ_STD_REPLACEMENT_NAMESPACE::enable_if<cond, T>;
|
|
311
|
+
template <class T>
|
|
312
|
+
using add_rvalue_reference = JKJ_STD_REPLACEMENT_NAMESPACE::add_rvalue_reference<T>;
|
|
313
|
+
template <bool cond, class T_true, class T_false>
|
|
314
|
+
using conditional = JKJ_STD_REPLACEMENT_NAMESPACE::conditional<cond, T_true, T_false>;
|
|
315
|
+
#if JKJ_USE_IS_CONSTANT_EVALUATED
|
|
316
|
+
using JKJ_STD_REPLACEMENT_NAMESPACE::is_constant_evaluated;
|
|
317
|
+
#endif
|
|
318
|
+
template <class T1, class T2>
|
|
319
|
+
using is_same = JKJ_STD_REPLACEMENT_NAMESPACE::is_same<T1, T2>;
|
|
320
|
+
#if !JKJ_HAS_BIT_CAST
|
|
321
|
+
template <class T>
|
|
322
|
+
using is_trivially_copyable = JKJ_STD_REPLACEMENT_NAMESPACE::is_trivially_copyable<T>;
|
|
323
|
+
#endif
|
|
324
|
+
template <class T>
|
|
325
|
+
using is_integral = JKJ_STD_REPLACEMENT_NAMESPACE::is_integral<T>;
|
|
326
|
+
template <class T>
|
|
327
|
+
using is_signed = JKJ_STD_REPLACEMENT_NAMESPACE::is_signed<T>;
|
|
328
|
+
template <class T>
|
|
329
|
+
using is_unsigned = JKJ_STD_REPLACEMENT_NAMESPACE::is_unsigned<T>;
|
|
330
|
+
|
|
331
|
+
template <class T>
|
|
332
|
+
using make_unsigned = JKJ_STD_REPLACEMENT_NAMESPACE::make_unsigned<T>;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
338
|
+
// Some general utilities for C++11-compatibility.
|
|
339
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
340
|
+
namespace detail {
|
|
341
|
+
#if !JKJ_HAS_CONSTEXPR17
|
|
342
|
+
template <stdr::size_t... indices>
|
|
343
|
+
struct index_sequence {};
|
|
344
|
+
|
|
345
|
+
template <stdr::size_t current, stdr::size_t total, class Dummy, stdr::size_t... indices>
|
|
346
|
+
struct make_index_sequence_impl {
|
|
347
|
+
using type = typename make_index_sequence_impl<current + 1, total, Dummy, indices...,
|
|
348
|
+
current>::type;
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
template <stdr::size_t total, class Dummy, stdr::size_t... indices>
|
|
352
|
+
struct make_index_sequence_impl<total, total, Dummy, indices...> {
|
|
353
|
+
using type = index_sequence<indices...>;
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
template <stdr::size_t N>
|
|
357
|
+
using make_index_sequence = typename make_index_sequence_impl<0, N, void>::type;
|
|
358
|
+
#endif
|
|
359
|
+
|
|
360
|
+
// Available since C++11, but including <utility> just for this is an overkill.
|
|
361
|
+
template <class T>
|
|
362
|
+
typename stdr::add_rvalue_reference<T>::type declval() noexcept;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
367
|
+
// Utilities for static data.
|
|
368
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
369
|
+
namespace detail {
|
|
370
|
+
// Including <array> is an overkill.
|
|
371
|
+
template <class T, stdr::size_t N>
|
|
372
|
+
struct array {
|
|
373
|
+
T data_[N];
|
|
374
|
+
constexpr T const* data() const noexcept { return data_; }
|
|
375
|
+
constexpr T operator[](stdr::size_t idx) const noexcept { return data_[idx]; }
|
|
376
|
+
JKJ_CONSTEXPR14 T& operator[](stdr::size_t idx) noexcept { return data_[idx]; }
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
// Platforms may require special instructions for reading static data declared with
|
|
380
|
+
// JKJ_STATIC_DATA_SECTION. Users can specify such instructions by defining the macro
|
|
381
|
+
// JKJ_READ_STATIC_DATA.
|
|
382
|
+
template <class T>
|
|
383
|
+
JKJ_CONSTEXPR20 T read_static_data(T const* ptr) noexcept {
|
|
384
|
+
JKJ_IF_CONSTEVAL { return *ptr; }
|
|
385
|
+
else {
|
|
386
|
+
#ifdef JKJ_READ_STATIC_DATA
|
|
387
|
+
return JKJ_READ_STATIC_DATA(ptr);
|
|
388
|
+
#else
|
|
389
|
+
return *ptr;
|
|
390
|
+
#endif
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
397
|
+
// Some basic features for encoding/decoding IEEE-754 formats.
|
|
398
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
399
|
+
namespace detail {
|
|
400
|
+
template <class T>
|
|
401
|
+
struct physical_bits {
|
|
402
|
+
static constexpr stdr::size_t value =
|
|
403
|
+
sizeof(T) * stdr::numeric_limits<unsigned char>::digits;
|
|
404
|
+
};
|
|
405
|
+
template <class T>
|
|
406
|
+
struct value_bits {
|
|
407
|
+
static constexpr stdr::size_t value = stdr::numeric_limits<
|
|
408
|
+
typename stdr::enable_if<stdr::is_integral<T>::value, T>::type>::digits;
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
template <typename To, typename From>
|
|
412
|
+
JKJ_CONSTEXPR20 To bit_cast(const From& from) {
|
|
413
|
+
#if JKJ_HAS_BIT_CAST
|
|
414
|
+
return stdr::bit_cast<To>(from);
|
|
415
|
+
#else
|
|
416
|
+
static_assert(sizeof(From) == sizeof(To), "");
|
|
417
|
+
static_assert(stdr::is_trivially_copyable<To>::value, "");
|
|
418
|
+
static_assert(stdr::is_trivially_copyable<From>::value, "");
|
|
419
|
+
To to;
|
|
420
|
+
stdr::memcpy(&to, &from, sizeof(To));
|
|
421
|
+
return to;
|
|
422
|
+
#endif
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// These classes expose encoding specs of IEEE-754-like floating-point formats.
|
|
427
|
+
// Currently available formats are IEEE-754 binary32 & IEEE-754 binary64.
|
|
428
|
+
|
|
429
|
+
struct ieee754_binary32 {
|
|
430
|
+
static constexpr int total_bits = 32;
|
|
431
|
+
static constexpr int significand_bits = 23;
|
|
432
|
+
static constexpr int exponent_bits = 8;
|
|
433
|
+
static constexpr int min_exponent = -126;
|
|
434
|
+
static constexpr int max_exponent = 127;
|
|
435
|
+
static constexpr int exponent_bias = -127;
|
|
436
|
+
static constexpr int decimal_significand_digits = 9;
|
|
437
|
+
static constexpr int decimal_exponent_digits = 2;
|
|
438
|
+
static constexpr int max_abs_decimal_exponent = 45;
|
|
439
|
+
};
|
|
440
|
+
struct ieee754_binary64 {
|
|
441
|
+
static constexpr int total_bits = 64;
|
|
442
|
+
static constexpr int significand_bits = 52;
|
|
443
|
+
static constexpr int exponent_bits = 11;
|
|
444
|
+
static constexpr int min_exponent = -1022;
|
|
445
|
+
static constexpr int max_exponent = 1023;
|
|
446
|
+
static constexpr int exponent_bias = -1023;
|
|
447
|
+
static constexpr int decimal_significand_digits = 17;
|
|
448
|
+
static constexpr int decimal_exponent_digits = 3;
|
|
449
|
+
static constexpr int max_abs_decimal_exponent = 324;
|
|
450
|
+
};
|
|
451
|
+
|
|
452
|
+
// A floating-point format traits class defines ways to interpret a bit pattern of given size as
|
|
453
|
+
// an encoding of floating-point number. This is an implementation of such a traits class,
|
|
454
|
+
// supporting ways to interpret IEEE-754 binary floating-point numbers.
|
|
455
|
+
template <class Format, class CarrierUInt, class ExponentInt = int>
|
|
456
|
+
struct ieee754_binary_traits {
|
|
457
|
+
// CarrierUInt needs to have enough size to hold the entire contents of floating-point
|
|
458
|
+
// numbers. The actual bits are assumed to be aligned to the LSB, and every other bits are
|
|
459
|
+
// assumed to be zeroed.
|
|
460
|
+
static_assert(detail::value_bits<CarrierUInt>::value >= Format::total_bits,
|
|
461
|
+
"jkj::dragonbox: insufficient number of bits");
|
|
462
|
+
static_assert(detail::stdr::is_unsigned<CarrierUInt>::value, "");
|
|
463
|
+
|
|
464
|
+
// ExponentUInt needs to be large enough to hold (unsigned) exponent bits as well as the
|
|
465
|
+
// (signed) actual exponent.
|
|
466
|
+
// TODO: static overflow guard against intermediate computations.
|
|
467
|
+
static_assert(detail::value_bits<ExponentInt>::value >= Format::exponent_bits + 1,
|
|
468
|
+
"jkj::dragonbox: insufficient number of bits");
|
|
469
|
+
static_assert(detail::stdr::is_signed<ExponentInt>::value, "");
|
|
470
|
+
|
|
471
|
+
using format = Format;
|
|
472
|
+
using carrier_uint = CarrierUInt;
|
|
473
|
+
static constexpr int carrier_bits = int(detail::value_bits<carrier_uint>::value);
|
|
474
|
+
using exponent_int = ExponentInt;
|
|
475
|
+
|
|
476
|
+
// Extract exponent bits from a bit pattern.
|
|
477
|
+
// The result must be aligned to the LSB so that there is no additional zero paddings
|
|
478
|
+
// on the right. This function does not do bias adjustment.
|
|
479
|
+
static constexpr exponent_int extract_exponent_bits(carrier_uint u) noexcept {
|
|
480
|
+
return exponent_int((u >> format::significand_bits) &
|
|
481
|
+
((exponent_int(1) << format::exponent_bits) - 1));
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// Extract significand bits from a bit pattern.
|
|
485
|
+
// The result must be aligned to the LSB so that there is no additional zero paddings
|
|
486
|
+
// on the right. The result does not contain the implicit bit.
|
|
487
|
+
static constexpr carrier_uint extract_significand_bits(carrier_uint u) noexcept {
|
|
488
|
+
return carrier_uint(u & ((carrier_uint(1) << format::significand_bits) - 1u));
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// Remove the exponent bits and extract significand bits together with the sign bit.
|
|
492
|
+
static constexpr carrier_uint remove_exponent_bits(carrier_uint u) noexcept {
|
|
493
|
+
return carrier_uint(u & ~(((carrier_uint(1) << format::exponent_bits) - 1u)
|
|
494
|
+
<< format::significand_bits));
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// Shift the obtained signed significand bits to the left by 1 to remove the sign bit.
|
|
498
|
+
static constexpr carrier_uint remove_sign_bit_and_shift(carrier_uint u) noexcept {
|
|
499
|
+
return carrier_uint((carrier_uint(u) << 1) &
|
|
500
|
+
((((carrier_uint(1) << (Format::total_bits - 1)) - 1u) << 1) | 1u));
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// Obtain the actual value of the binary exponent from the extracted exponent bits.
|
|
504
|
+
static constexpr exponent_int binary_exponent(exponent_int exponent_bits) noexcept {
|
|
505
|
+
return exponent_int(exponent_bits == 0 ? format::min_exponent
|
|
506
|
+
: exponent_bits + format::exponent_bias);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
// Obtain the actual value of the binary significand from the extracted significand bits
|
|
510
|
+
// and exponent bits.
|
|
511
|
+
static constexpr carrier_uint binary_significand(carrier_uint significand_bits,
|
|
512
|
+
exponent_int exponent_bits) noexcept {
|
|
513
|
+
return carrier_uint(
|
|
514
|
+
exponent_bits == 0
|
|
515
|
+
? significand_bits
|
|
516
|
+
: (significand_bits | (carrier_uint(1) << format::significand_bits)));
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
/* Various boolean observer functions */
|
|
520
|
+
|
|
521
|
+
static constexpr bool is_nonzero(carrier_uint u) noexcept {
|
|
522
|
+
return (u & ((carrier_uint(1) << (format::significand_bits + format::exponent_bits)) -
|
|
523
|
+
1u)) != 0;
|
|
524
|
+
}
|
|
525
|
+
static constexpr bool is_positive(carrier_uint u) noexcept {
|
|
526
|
+
return u < (carrier_uint(1) << (format::significand_bits + format::exponent_bits));
|
|
527
|
+
}
|
|
528
|
+
static constexpr bool is_negative(carrier_uint u) noexcept { return !is_positive(u); }
|
|
529
|
+
static constexpr bool is_finite(exponent_int exponent_bits) noexcept {
|
|
530
|
+
return exponent_bits != ((exponent_int(1) << format::exponent_bits) - 1);
|
|
531
|
+
}
|
|
532
|
+
static constexpr bool has_all_zero_significand_bits(carrier_uint u) noexcept {
|
|
533
|
+
return ((u << 1) &
|
|
534
|
+
((((carrier_uint(1) << (Format::total_bits - 1)) - 1u) << 1) | 1u)) == 0;
|
|
535
|
+
}
|
|
536
|
+
static constexpr bool has_even_significand_bits(carrier_uint u) noexcept {
|
|
537
|
+
return u % 2 == 0;
|
|
538
|
+
}
|
|
539
|
+
};
|
|
540
|
+
|
|
541
|
+
// Convert between bit patterns stored in carrier_uint and instances of an actual
|
|
542
|
+
// floating-point type. Depending on format and carrier_uint, this operation might not
|
|
543
|
+
// be possible for some specific bit patterns. However, the contract is that u always
|
|
544
|
+
// denotes a valid bit pattern, so the functions here are assumed to be noexcept.
|
|
545
|
+
// Users might specialize this class to change the behavior for certain types.
|
|
546
|
+
// The default provided by the library is to treat the given floating-point type Float as either
|
|
547
|
+
// IEEE-754 binary32 or IEEE-754 binary64, depending on the bitwise size of Float.
|
|
548
|
+
template <class Float>
|
|
549
|
+
struct default_float_bit_carrier_conversion_traits {
|
|
550
|
+
// Guards against types that have different internal representations than IEEE-754
|
|
551
|
+
// binary32/64. I don't know if there is a truly reliable way of detecting IEEE-754 binary
|
|
552
|
+
// formats. I just did my best here. Note that in some cases
|
|
553
|
+
// numeric_limits<Float>::is_iec559 may report false even if the internal representation is
|
|
554
|
+
// IEEE-754 compatible. In such a case, the user can specialize this traits template and
|
|
555
|
+
// remove this static sanity check in order to make Dragonbox work for Float.
|
|
556
|
+
static_assert(detail::stdr::numeric_limits<Float>::is_iec559 &&
|
|
557
|
+
detail::stdr::numeric_limits<Float>::radix == 2 &&
|
|
558
|
+
(detail::physical_bits<Float>::value == 32 ||
|
|
559
|
+
detail::physical_bits<Float>::value == 64),
|
|
560
|
+
"jkj::dragonbox: Float may not be of IEEE-754 binary32/binary64");
|
|
561
|
+
|
|
562
|
+
// Specifies the unsigned integer type to hold bitwise value of Float.
|
|
563
|
+
using carrier_uint =
|
|
564
|
+
typename detail::stdr::conditional<detail::physical_bits<Float>::value == 32,
|
|
565
|
+
detail::stdr::uint_least32_t,
|
|
566
|
+
detail::stdr::uint_least64_t>::type;
|
|
567
|
+
|
|
568
|
+
// Specifies the floating-point format.
|
|
569
|
+
using format = typename detail::stdr::conditional<detail::physical_bits<Float>::value == 32,
|
|
570
|
+
ieee754_binary32, ieee754_binary64>::type;
|
|
571
|
+
|
|
572
|
+
// Converts the floating-point type into the bit-carrier unsigned integer type.
|
|
573
|
+
static JKJ_CONSTEXPR20 carrier_uint float_to_carrier(Float x) noexcept {
|
|
574
|
+
return detail::bit_cast<carrier_uint>(x);
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
// Converts the bit-carrier unsigned integer type into the floating-point type.
|
|
578
|
+
static JKJ_CONSTEXPR20 Float carrier_to_float(carrier_uint x) noexcept {
|
|
579
|
+
return detail::bit_cast<Float>(x);
|
|
580
|
+
}
|
|
581
|
+
};
|
|
582
|
+
|
|
583
|
+
// Convenient wrappers for floating-point traits classes.
|
|
584
|
+
// In order to reduce the argument passing overhead, these classes should be as simple as
|
|
585
|
+
// possible (e.g., no inheritance, no private non-static data member, etc.; this is an
|
|
586
|
+
// unfortunate fact about common ABI convention).
|
|
587
|
+
|
|
588
|
+
template <class FormatTraits>
|
|
589
|
+
struct signed_significand_bits {
|
|
590
|
+
using format_traits = FormatTraits;
|
|
591
|
+
using carrier_uint = typename format_traits::carrier_uint;
|
|
592
|
+
|
|
593
|
+
carrier_uint u;
|
|
594
|
+
|
|
595
|
+
signed_significand_bits() = default;
|
|
596
|
+
constexpr explicit signed_significand_bits(carrier_uint bit_pattern) noexcept
|
|
597
|
+
: u{bit_pattern} {}
|
|
598
|
+
|
|
599
|
+
// Shift the obtained signed significand bits to the left by 1 to remove the sign bit.
|
|
600
|
+
constexpr carrier_uint remove_sign_bit_and_shift() const noexcept {
|
|
601
|
+
return format_traits::remove_sign_bit_and_shift(u);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
constexpr bool is_positive() const noexcept { return format_traits::is_positive(u); }
|
|
605
|
+
constexpr bool is_negative() const noexcept { return format_traits::is_negative(u); }
|
|
606
|
+
constexpr bool has_all_zero_significand_bits() const noexcept {
|
|
607
|
+
return format_traits::has_all_zero_significand_bits(u);
|
|
608
|
+
}
|
|
609
|
+
constexpr bool has_even_significand_bits() const noexcept {
|
|
610
|
+
return format_traits::has_even_significand_bits(u);
|
|
611
|
+
}
|
|
612
|
+
};
|
|
613
|
+
|
|
614
|
+
template <class FormatTraits>
|
|
615
|
+
struct float_bits {
|
|
616
|
+
using format_traits = FormatTraits;
|
|
617
|
+
using carrier_uint = typename format_traits::carrier_uint;
|
|
618
|
+
using exponent_int = typename format_traits::exponent_int;
|
|
619
|
+
|
|
620
|
+
carrier_uint u;
|
|
621
|
+
|
|
622
|
+
float_bits() = default;
|
|
623
|
+
constexpr explicit float_bits(carrier_uint bit_pattern) noexcept : u{bit_pattern} {}
|
|
624
|
+
|
|
625
|
+
// Extract exponent bits from a bit pattern.
|
|
626
|
+
// The result must be aligned to the LSB so that there is no additional zero paddings
|
|
627
|
+
// on the right. This function does not do bias adjustment.
|
|
628
|
+
constexpr exponent_int extract_exponent_bits() const noexcept {
|
|
629
|
+
return format_traits::extract_exponent_bits(u);
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
// Extract significand bits from a bit pattern.
|
|
633
|
+
// The result must be aligned to the LSB so that there is no additional zero paddings
|
|
634
|
+
// on the right. The result does not contain the implicit bit.
|
|
635
|
+
constexpr carrier_uint extract_significand_bits() const noexcept {
|
|
636
|
+
return format_traits::extract_significand_bits(u);
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
// Remove the exponent bits and extract significand bits together with the sign bit.
|
|
640
|
+
constexpr signed_significand_bits<format_traits> remove_exponent_bits() const noexcept {
|
|
641
|
+
return signed_significand_bits<format_traits>(format_traits::remove_exponent_bits(u));
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
// Obtain the actual value of the binary exponent from the extracted exponent bits.
|
|
645
|
+
static constexpr exponent_int binary_exponent(exponent_int exponent_bits) noexcept {
|
|
646
|
+
return format_traits::binary_exponent(exponent_bits);
|
|
647
|
+
}
|
|
648
|
+
constexpr exponent_int binary_exponent() const noexcept {
|
|
649
|
+
return binary_exponent(extract_exponent_bits());
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
// Obtain the actual value of the binary exponent from the extracted significand bits
|
|
653
|
+
// and exponent bits.
|
|
654
|
+
static constexpr carrier_uint binary_significand(carrier_uint significand_bits,
|
|
655
|
+
exponent_int exponent_bits) noexcept {
|
|
656
|
+
return format_traits::binary_significand(significand_bits, exponent_bits);
|
|
657
|
+
}
|
|
658
|
+
constexpr carrier_uint binary_significand() const noexcept {
|
|
659
|
+
return binary_significand(extract_significand_bits(), extract_exponent_bits());
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
constexpr bool is_nonzero() const noexcept { return format_traits::is_nonzero(u); }
|
|
663
|
+
constexpr bool is_positive() const noexcept { return format_traits::is_positive(u); }
|
|
664
|
+
constexpr bool is_negative() const noexcept { return format_traits::is_negative(u); }
|
|
665
|
+
constexpr bool is_finite(exponent_int exponent_bits) const noexcept {
|
|
666
|
+
return format_traits::is_finite(exponent_bits);
|
|
667
|
+
}
|
|
668
|
+
constexpr bool is_finite() const noexcept {
|
|
669
|
+
return format_traits::is_finite(extract_exponent_bits());
|
|
670
|
+
}
|
|
671
|
+
constexpr bool has_even_significand_bits() const noexcept {
|
|
672
|
+
return format_traits::has_even_significand_bits(u);
|
|
673
|
+
}
|
|
674
|
+
};
|
|
675
|
+
|
|
676
|
+
template <class Float,
|
|
677
|
+
class ConversionTraits = default_float_bit_carrier_conversion_traits<Float>,
|
|
678
|
+
class FormatTraits = ieee754_binary_traits<typename ConversionTraits::format,
|
|
679
|
+
typename ConversionTraits::carrier_uint>>
|
|
680
|
+
JKJ_CONSTEXPR20 float_bits<FormatTraits> make_float_bits(Float x) noexcept {
|
|
681
|
+
return float_bits<FormatTraits>(ConversionTraits::float_to_carrier(x));
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
namespace detail {
|
|
685
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
686
|
+
// Bit operation intrinsics.
|
|
687
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
688
|
+
|
|
689
|
+
namespace bits {
|
|
690
|
+
// Most compilers should be able to optimize this into the ROR instruction.
|
|
691
|
+
// n is assumed to be at most of bit_width bits.
|
|
692
|
+
template <stdr::size_t bit_width, class UInt>
|
|
693
|
+
JKJ_CONSTEXPR14 UInt rotr(UInt n, unsigned int r) noexcept {
|
|
694
|
+
static_assert(bit_width > 0, "jkj::dragonbox: rotation bit-width must be positive");
|
|
695
|
+
static_assert(bit_width <= value_bits<UInt>::value,
|
|
696
|
+
"jkj::dragonbox: rotation bit-width is too large");
|
|
697
|
+
r &= (bit_width - 1);
|
|
698
|
+
return (n >> r) | (n << ((bit_width - r) & (bit_width - 1)));
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
703
|
+
// Utilities for wide unsigned integer arithmetic.
|
|
704
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
705
|
+
|
|
706
|
+
namespace wuint {
|
|
707
|
+
// Compilers might support built-in 128-bit integer types. However, it seems that
|
|
708
|
+
// emulating them with a pair of 64-bit integers actually produces a better code,
|
|
709
|
+
// so we avoid using those built-ins. That said, they are still useful for
|
|
710
|
+
// implementing 64-bit x 64-bit -> 128-bit multiplication.
|
|
711
|
+
|
|
712
|
+
// clang-format off
|
|
713
|
+
#if defined(__SIZEOF_INT128__)
|
|
714
|
+
// To silence "error: ISO C++ does not support '__int128' for 'type name'
|
|
715
|
+
// [-Wpedantic]"
|
|
716
|
+
#if defined(__GNUC__)
|
|
717
|
+
__extension__
|
|
718
|
+
#endif
|
|
719
|
+
using builtin_uint128_t = unsigned __int128;
|
|
720
|
+
#endif
|
|
721
|
+
// clang-format on
|
|
722
|
+
|
|
723
|
+
struct uint128 {
|
|
724
|
+
uint128() = default;
|
|
725
|
+
|
|
726
|
+
stdr::uint_least64_t high_;
|
|
727
|
+
stdr::uint_least64_t low_;
|
|
728
|
+
|
|
729
|
+
constexpr uint128(stdr::uint_least64_t high, stdr::uint_least64_t low) noexcept
|
|
730
|
+
: high_{high}, low_{low} {}
|
|
731
|
+
|
|
732
|
+
constexpr stdr::uint_least64_t high() const noexcept { return high_; }
|
|
733
|
+
constexpr stdr::uint_least64_t low() const noexcept { return low_; }
|
|
734
|
+
|
|
735
|
+
JKJ_CONSTEXPR20 uint128& operator+=(stdr::uint_least64_t n) & noexcept {
|
|
736
|
+
auto const generic_impl = [&] {
|
|
737
|
+
auto const sum = (low_ + n) & UINT64_C(0xffffffffffffffff);
|
|
738
|
+
high_ += (sum < low_ ? 1 : 0);
|
|
739
|
+
low_ = sum;
|
|
740
|
+
};
|
|
741
|
+
// To suppress warning.
|
|
742
|
+
static_cast<void>(generic_impl);
|
|
743
|
+
|
|
744
|
+
JKJ_IF_CONSTEXPR(value_bits<stdr::uint_least64_t>::value > 64) {
|
|
745
|
+
generic_impl();
|
|
746
|
+
return *this;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
JKJ_IF_CONSTEVAL {
|
|
750
|
+
generic_impl();
|
|
751
|
+
return *this;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
// See https://github.com/fmtlib/fmt/pull/2985.
|
|
755
|
+
#if JKJ_HAS_BUILTIN(__builtin_addcll) && !defined(__ibmxl__)
|
|
756
|
+
JKJ_IF_CONSTEXPR(
|
|
757
|
+
stdr::is_same<stdr::uint_least64_t, unsigned long long>::value) {
|
|
758
|
+
unsigned long long carry{};
|
|
759
|
+
low_ = stdr::uint_least64_t(__builtin_addcll(low_, n, 0, &carry));
|
|
760
|
+
high_ = stdr::uint_least64_t(__builtin_addcll(high_, 0, carry, &carry));
|
|
761
|
+
return *this;
|
|
762
|
+
}
|
|
763
|
+
#endif
|
|
764
|
+
#if JKJ_HAS_BUILTIN(__builtin_addcl) && !defined(__ibmxl__)
|
|
765
|
+
JKJ_IF_CONSTEXPR(stdr::is_same<stdr::uint_least64_t, unsigned long>::value) {
|
|
766
|
+
unsigned long carry{};
|
|
767
|
+
low_ = stdr::uint_least64_t(
|
|
768
|
+
__builtin_addcl(static_cast<unsigned long>(low_),
|
|
769
|
+
static_cast<unsigned long>(n), 0, &carry));
|
|
770
|
+
high_ = stdr::uint_least64_t(
|
|
771
|
+
__builtin_addcl(static_cast<unsigned long>(high_), 0, carry, &carry));
|
|
772
|
+
return *this;
|
|
773
|
+
}
|
|
774
|
+
#endif
|
|
775
|
+
#if JKJ_HAS_BUILTIN(__builtin_addc) && !defined(__ibmxl__)
|
|
776
|
+
JKJ_IF_CONSTEXPR(stdr::is_same<stdr::uint_least64_t, unsigned int>::value) {
|
|
777
|
+
unsigned int carry{};
|
|
778
|
+
low_ = stdr::uint_least64_t(__builtin_addc(static_cast<unsigned int>(low_),
|
|
779
|
+
static_cast<unsigned int>(n), 0,
|
|
780
|
+
&carry));
|
|
781
|
+
high_ = stdr::uint_least64_t(
|
|
782
|
+
__builtin_addc(static_cast<unsigned int>(high_), 0, carry, &carry));
|
|
783
|
+
return *this;
|
|
784
|
+
}
|
|
785
|
+
#endif
|
|
786
|
+
|
|
787
|
+
#if JKJ_HAS_BUILTIN(__builtin_ia32_addcarry_u64)
|
|
788
|
+
// __builtin_ia32_addcarry_u64 is not documented, but it seems it takes unsigned
|
|
789
|
+
// long long arguments.
|
|
790
|
+
unsigned long long result{};
|
|
791
|
+
auto const carry = __builtin_ia32_addcarry_u64(0, low_, n, &result);
|
|
792
|
+
low_ = stdr::uint_least64_t(result);
|
|
793
|
+
__builtin_ia32_addcarry_u64(carry, high_, 0, &result);
|
|
794
|
+
high_ = stdr::uint_least64_t(result);
|
|
795
|
+
#elif defined(_MSC_VER) && defined(_M_X64)
|
|
796
|
+
// On MSVC, uint_least64_t and __int64 must be unsigned long long; see
|
|
797
|
+
// https://learn.microsoft.com/en-us/cpp/c-runtime-library/standard-types
|
|
798
|
+
// and https://learn.microsoft.com/en-us/cpp/cpp/int8-int16-int32-int64.
|
|
799
|
+
static_assert(stdr::is_same<unsigned long long, stdr::uint_least64_t>::value,
|
|
800
|
+
"");
|
|
801
|
+
auto const carry = _addcarry_u64(0, low_, n, &low_);
|
|
802
|
+
_addcarry_u64(carry, high_, 0, &high_);
|
|
803
|
+
#elif defined(__INTEL_COMPILER) && (defined(_M_X64) || defined(__x86_64))
|
|
804
|
+
// Cannot find any documentation on how things are defined, but hopefully this
|
|
805
|
+
// is always true...
|
|
806
|
+
static_assert(stdr::is_same<unsigned __int64, stdr::uint_least64_t>::value, "");
|
|
807
|
+
auto const carry = _addcarry_u64(0, low_, n, &low_);
|
|
808
|
+
_addcarry_u64(carry, high_, 0, &high_);
|
|
809
|
+
#else
|
|
810
|
+
generic_impl();
|
|
811
|
+
#endif
|
|
812
|
+
return *this;
|
|
813
|
+
}
|
|
814
|
+
};
|
|
815
|
+
|
|
816
|
+
struct uint32_64 {
|
|
817
|
+
stdr::uint_least64_t low64_;
|
|
818
|
+
stdr::uint_least32_t high32_;
|
|
819
|
+
|
|
820
|
+
constexpr uint32_64(stdr::uint_least32_t high32,
|
|
821
|
+
stdr::uint_least64_t low64) noexcept
|
|
822
|
+
: low64_{low64}, high32_{high32} {}
|
|
823
|
+
|
|
824
|
+
constexpr stdr::uint_least32_t high32() const noexcept { return high32_; }
|
|
825
|
+
constexpr stdr::uint_least64_t low64() const noexcept { return low64_; }
|
|
826
|
+
};
|
|
827
|
+
|
|
828
|
+
struct uint64_32 {
|
|
829
|
+
stdr::uint_least64_t high64_;
|
|
830
|
+
stdr::uint_least32_t low32_;
|
|
831
|
+
|
|
832
|
+
constexpr uint64_32(stdr::uint_least64_t high64,
|
|
833
|
+
stdr::uint_least32_t low32) noexcept
|
|
834
|
+
: high64_{high64}, low32_{low32} {}
|
|
835
|
+
|
|
836
|
+
constexpr stdr::uint_least64_t high64() const noexcept { return high64_; }
|
|
837
|
+
constexpr stdr::uint_least32_t low32() const noexcept { return low32_; }
|
|
838
|
+
};
|
|
839
|
+
|
|
840
|
+
inline JKJ_CONSTEXPR20 stdr::uint_least64_t umul64(stdr::uint_least32_t x,
|
|
841
|
+
stdr::uint_least32_t y) noexcept {
|
|
842
|
+
#if defined(_MSC_VER) && defined(_M_IX86)
|
|
843
|
+
JKJ_IF_NOT_CONSTEVAL { return __emulu(x, y); }
|
|
844
|
+
#endif
|
|
845
|
+
return x * stdr::uint_least64_t(y);
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
// Get 128-bit result of multiplication of two 64-bit unsigned integers.
|
|
849
|
+
JKJ_SAFEBUFFERS inline JKJ_CONSTEXPR20 uint128
|
|
850
|
+
umul128(stdr::uint_least64_t x, stdr::uint_least64_t y) noexcept {
|
|
851
|
+
auto const generic_impl = [=]() -> uint128 {
|
|
852
|
+
auto const a = stdr::uint_least32_t(x >> 32);
|
|
853
|
+
auto const b = stdr::uint_least32_t(x);
|
|
854
|
+
auto const c = stdr::uint_least32_t(y >> 32);
|
|
855
|
+
auto const d = stdr::uint_least32_t(y);
|
|
856
|
+
|
|
857
|
+
auto const ac = umul64(a, c);
|
|
858
|
+
auto const bc = umul64(b, c);
|
|
859
|
+
auto const ad = umul64(a, d);
|
|
860
|
+
auto const bd = umul64(b, d);
|
|
861
|
+
|
|
862
|
+
auto const intermediate =
|
|
863
|
+
(bd >> 32) + stdr::uint_least32_t(ad) + stdr::uint_least32_t(bc);
|
|
864
|
+
|
|
865
|
+
return {ac + (intermediate >> 32) + (ad >> 32) + (bc >> 32),
|
|
866
|
+
(intermediate << 32) + stdr::uint_least32_t(bd)};
|
|
867
|
+
};
|
|
868
|
+
// To silence warning.
|
|
869
|
+
static_cast<void>(generic_impl);
|
|
870
|
+
|
|
871
|
+
#if defined(__SIZEOF_INT128__)
|
|
872
|
+
auto const result = builtin_uint128_t(x) * builtin_uint128_t(y);
|
|
873
|
+
return {stdr::uint_least64_t(result >> 64), stdr::uint_least64_t(result)};
|
|
874
|
+
#elif defined(_MSC_VER) && defined(_M_X64)
|
|
875
|
+
JKJ_IF_CONSTEVAL {
|
|
876
|
+
// This redundant variable is to workaround MSVC's codegen bug caused by the
|
|
877
|
+
// interaction of NRVO and intrinsics.
|
|
878
|
+
auto const result = generic_impl();
|
|
879
|
+
return result;
|
|
880
|
+
}
|
|
881
|
+
uint128 result;
|
|
882
|
+
#if defined(__AVX2__)
|
|
883
|
+
result.low_ = _mulx_u64(x, y, &result.high_);
|
|
884
|
+
#else
|
|
885
|
+
result.low_ = _umul128(x, y, &result.high_);
|
|
886
|
+
#endif
|
|
887
|
+
return result;
|
|
888
|
+
#else
|
|
889
|
+
return generic_impl();
|
|
890
|
+
#endif
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
// Get high half of the 128-bit result of multiplication of two 64-bit unsigned
|
|
894
|
+
// integers.
|
|
895
|
+
JKJ_SAFEBUFFERS inline JKJ_CONSTEXPR20 stdr::uint_least64_t
|
|
896
|
+
umul128_upper64(stdr::uint_least64_t x, stdr::uint_least64_t y) noexcept {
|
|
897
|
+
auto const generic_impl = [=]() -> stdr::uint_least64_t {
|
|
898
|
+
auto const a = stdr::uint_least32_t(x >> 32);
|
|
899
|
+
auto const b = stdr::uint_least32_t(x);
|
|
900
|
+
auto const c = stdr::uint_least32_t(y >> 32);
|
|
901
|
+
auto const d = stdr::uint_least32_t(y);
|
|
902
|
+
|
|
903
|
+
auto const ac = umul64(a, c);
|
|
904
|
+
auto const bc = umul64(b, c);
|
|
905
|
+
auto const ad = umul64(a, d);
|
|
906
|
+
auto const bd = umul64(b, d);
|
|
907
|
+
|
|
908
|
+
auto const intermediate =
|
|
909
|
+
(bd >> 32) + stdr::uint_least32_t(ad) + stdr::uint_least32_t(bc);
|
|
910
|
+
|
|
911
|
+
return ac + (intermediate >> 32) + (ad >> 32) + (bc >> 32);
|
|
912
|
+
};
|
|
913
|
+
// To silence warning.
|
|
914
|
+
static_cast<void>(generic_impl);
|
|
915
|
+
|
|
916
|
+
#if defined(__SIZEOF_INT128__)
|
|
917
|
+
auto const result = builtin_uint128_t(x) * builtin_uint128_t(y);
|
|
918
|
+
return stdr::uint_least64_t(result >> 64);
|
|
919
|
+
#elif defined(_MSC_VER) && defined(_M_X64)
|
|
920
|
+
JKJ_IF_CONSTEVAL {
|
|
921
|
+
// This redundant variable is to workaround MSVC's codegen bug caused by the
|
|
922
|
+
// interaction of NRVO and intrinsics.
|
|
923
|
+
auto const result = generic_impl();
|
|
924
|
+
return result;
|
|
925
|
+
}
|
|
926
|
+
stdr::uint_least64_t result;
|
|
927
|
+
#if defined(__AVX2__)
|
|
928
|
+
_mulx_u64(x, y, &result);
|
|
929
|
+
#else
|
|
930
|
+
result = __umulh(x, y);
|
|
931
|
+
#endif
|
|
932
|
+
return result;
|
|
933
|
+
#else
|
|
934
|
+
return generic_impl();
|
|
935
|
+
#endif
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
// Get upper 128-bits of multiplication of a 64-bit unsigned integer and a 128-bit
|
|
939
|
+
// unsigned integer.
|
|
940
|
+
JKJ_SAFEBUFFERS inline JKJ_CONSTEXPR20 uint128 umul192_upper128(stdr::uint_least64_t x,
|
|
941
|
+
uint128 y) noexcept {
|
|
942
|
+
auto r = umul128(x, y.high());
|
|
943
|
+
r += umul128_upper64(x, y.low());
|
|
944
|
+
return r;
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
// Get 96-bit result of multiplication of a 32-bit unsigned integer and a 64-bit
|
|
948
|
+
// unsigned integer.
|
|
949
|
+
JKJ_SAFEBUFFERS inline JKJ_CONSTEXPR20
|
|
950
|
+
#if JKJ_FAST_MUL64
|
|
951
|
+
uint32_64
|
|
952
|
+
#else
|
|
953
|
+
uint64_32
|
|
954
|
+
#endif
|
|
955
|
+
umul96(stdr::uint_fast32_t x, stdr::uint_least64_t y) noexcept {
|
|
956
|
+
#if defined(__SIZEOF_INT128__) || (defined(_MSC_VER) && defined(_M_X64))
|
|
957
|
+
auto const r128 = umul128(stdr::uint_least64_t(x), y);
|
|
958
|
+
|
|
959
|
+
auto const high = stdr::uint_least32_t(r128.high());
|
|
960
|
+
auto const middle = stdr::uint_least32_t(r128.low() >> 32);
|
|
961
|
+
auto const low = stdr::uint_least32_t(r128.low());
|
|
962
|
+
#else
|
|
963
|
+
auto const yh = stdr::uint_least32_t(y >> 32);
|
|
964
|
+
auto const yl = stdr::uint_least32_t(y);
|
|
965
|
+
|
|
966
|
+
auto xyh = umul64(x, yh);
|
|
967
|
+
auto const xyl = umul64(x, yl);
|
|
968
|
+
|
|
969
|
+
xyh += (xyl >> 32);
|
|
970
|
+
|
|
971
|
+
auto const high = stdr::uint_least32_t(xyh >> 32);
|
|
972
|
+
auto const middle = stdr::uint_least32_t(xyh);
|
|
973
|
+
auto const low = stdr::uint_least32_t(xyl);
|
|
974
|
+
#endif
|
|
975
|
+
|
|
976
|
+
#if JKJ_FAST_MUL64
|
|
977
|
+
uint32_64 r{high, (stdr::uint_least64_t(middle) << 32) | low};
|
|
978
|
+
#else
|
|
979
|
+
uint64_32 r{(stdr::uint_least64_t(high) << 32) | middle, low};
|
|
980
|
+
#endif
|
|
981
|
+
return r;
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
// Get upper 64-bits of multiplication of a 32-bit unsigned integer and a 64-bit
|
|
985
|
+
// unsigned integer.
|
|
986
|
+
inline JKJ_CONSTEXPR20 stdr::uint_least64_t
|
|
987
|
+
umul96_upper64(stdr::uint_least32_t x, stdr::uint_least64_t y) noexcept {
|
|
988
|
+
#if defined(__SIZEOF_INT128__) || (defined(_MSC_VER) && defined(_M_X64))
|
|
989
|
+
return umul128_upper64(stdr::uint_least64_t(x) << 32, y);
|
|
990
|
+
#else
|
|
991
|
+
auto const yh = stdr::uint_least32_t(y >> 32);
|
|
992
|
+
auto const yl = stdr::uint_least32_t(y);
|
|
993
|
+
|
|
994
|
+
auto const xyh = umul64(x, yh);
|
|
995
|
+
auto const xyl = umul64(x, yl);
|
|
996
|
+
|
|
997
|
+
return xyh + (xyl >> 32);
|
|
998
|
+
#endif
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
// Get lower 128-bits of multiplication of a 64-bit unsigned integer and a 128-bit
|
|
1002
|
+
// unsigned integer.
|
|
1003
|
+
JKJ_SAFEBUFFERS inline JKJ_CONSTEXPR20 uint128 umul192_lower128(stdr::uint_least64_t x,
|
|
1004
|
+
uint128 y) noexcept {
|
|
1005
|
+
auto const high = x * y.high();
|
|
1006
|
+
auto const high_low = umul128(x, y.low());
|
|
1007
|
+
return {(high + high_low.high()) & UINT64_C(0xffffffffffffffff), high_low.low()};
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
// Get lower 64-bits of multiplication of a 32-bit unsigned integer and a 64-bit
|
|
1011
|
+
// unsigned integer.
|
|
1012
|
+
constexpr stdr::uint_least64_t umul96_lower64(stdr::uint_least32_t x,
|
|
1013
|
+
stdr::uint_least64_t y) noexcept {
|
|
1014
|
+
return (x * y) & UINT64_C(0xffffffffffffffff);
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
1019
|
+
// Some simple utilities for constexpr computation.
|
|
1020
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
1021
|
+
|
|
1022
|
+
template <int k, class Int>
|
|
1023
|
+
constexpr Int compute_power(Int a) noexcept {
|
|
1024
|
+
static_assert(k >= 0, "");
|
|
1025
|
+
#if JKJ_HAS_CONSTEXPR14
|
|
1026
|
+
Int p = 1;
|
|
1027
|
+
for (int i = 0; i < k; ++i) {
|
|
1028
|
+
p *= a;
|
|
1029
|
+
}
|
|
1030
|
+
return p;
|
|
1031
|
+
#else
|
|
1032
|
+
return k == 0 ? 1
|
|
1033
|
+
: k % 2 == 0 ? compute_power<k / 2, Int>(a * a)
|
|
1034
|
+
: a * compute_power<k / 2, Int>(a * a);
|
|
1035
|
+
#endif
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
template <int a, class UInt>
|
|
1039
|
+
constexpr int count_factors(UInt n) noexcept {
|
|
1040
|
+
static_assert(a > 1, "");
|
|
1041
|
+
#if JKJ_HAS_CONSTEXPR14
|
|
1042
|
+
int c = 0;
|
|
1043
|
+
while (n % a == 0) {
|
|
1044
|
+
n /= a;
|
|
1045
|
+
++c;
|
|
1046
|
+
}
|
|
1047
|
+
return c;
|
|
1048
|
+
#else
|
|
1049
|
+
return n % a == 0 ? count_factors<a, UInt>(n / a) + 1 : 0;
|
|
1050
|
+
#endif
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
1054
|
+
// Utilities for fast/constexpr log computation.
|
|
1055
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
1056
|
+
|
|
1057
|
+
namespace log {
|
|
1058
|
+
static_assert((stdr::int_fast32_t(-1) >> 1) == stdr::int_fast32_t(-1) &&
|
|
1059
|
+
(stdr::int_fast16_t(-1) >> 1) == stdr::int_fast16_t(-1),
|
|
1060
|
+
"jkj::dragonbox: right-shift for signed integers must be arithmetic");
|
|
1061
|
+
|
|
1062
|
+
// Only for constexpr computation.
|
|
1063
|
+
// Returns -1 when n = 0.
|
|
1064
|
+
template <class UInt>
|
|
1065
|
+
constexpr int floor_log2(UInt n) noexcept {
|
|
1066
|
+
#if JKJ_HAS_CONSTEXPR14
|
|
1067
|
+
int count = -1;
|
|
1068
|
+
while (n != 0) {
|
|
1069
|
+
++count;
|
|
1070
|
+
n >>= 1;
|
|
1071
|
+
}
|
|
1072
|
+
return count;
|
|
1073
|
+
#else
|
|
1074
|
+
return n == 0 ? -1 : floor_log2<UInt>(n / 2) + 1;
|
|
1075
|
+
#endif
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
// Implementations of various log computations using binary approximations.
|
|
1079
|
+
// On less powerful platforms, using smaller integer types and magic numbers for these
|
|
1080
|
+
// computations significantly improve codegen, so depending on the range of input we try
|
|
1081
|
+
// to choose the smallest possible magic numbers that result in the best codegen.
|
|
1082
|
+
// To generically achieve that goal, we list multiple sets of magic numbers with
|
|
1083
|
+
// associated ranges of inputs, called "tiers", so that we choose the smallest tier
|
|
1084
|
+
// whose associated range covers the requested range of input.
|
|
1085
|
+
|
|
1086
|
+
// Check if the given tier covers the requested range.
|
|
1087
|
+
// Info<current_tier> is supposed to hold the magic numbers needed for the computation
|
|
1088
|
+
// and the supported range of input (i.e. the range of input where the computation with
|
|
1089
|
+
// the given magic numbers must be valid).
|
|
1090
|
+
template <template <stdr::size_t> class Info, stdr::int_least32_t min_exponent,
|
|
1091
|
+
stdr::int_least32_t max_exponent, stdr::size_t current_tier,
|
|
1092
|
+
stdr::int_least32_t supported_min_exponent = Info<current_tier>::min_exponent,
|
|
1093
|
+
stdr::int_least32_t supported_max_exponent = Info<current_tier>::max_exponent>
|
|
1094
|
+
constexpr bool is_in_range(int) noexcept {
|
|
1095
|
+
return min_exponent >= supported_min_exponent &&
|
|
1096
|
+
max_exponent <= supported_max_exponent;
|
|
1097
|
+
}
|
|
1098
|
+
// This overload generates a compile-error and is called only if the former overload is
|
|
1099
|
+
// removed via SFINAE, which happens if and only if every provided tier fails to cover
|
|
1100
|
+
// the requested range.
|
|
1101
|
+
template <template <stdr::size_t> class Info, stdr::int_least32_t min_exponent,
|
|
1102
|
+
stdr::int_least32_t max_exponent, stdr::size_t current_tier>
|
|
1103
|
+
constexpr bool is_in_range(...) noexcept {
|
|
1104
|
+
// Supposed to be always false, but formally dependent on the template parameters.
|
|
1105
|
+
static_assert(min_exponent > max_exponent,
|
|
1106
|
+
"jkj::dragonbox: exponent range is too wide");
|
|
1107
|
+
return false;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
// Generic implementation of log computations.
|
|
1111
|
+
template <template <stdr::size_t> class Info, stdr::int_least32_t min_exponent,
|
|
1112
|
+
stdr::int_least32_t max_exponent, stdr::size_t current_tier = 0,
|
|
1113
|
+
bool = is_in_range<Info, min_exponent, max_exponent, current_tier>(0)>
|
|
1114
|
+
struct compute_impl;
|
|
1115
|
+
|
|
1116
|
+
// Specialization for the case when the given tier covers the requested range of input.
|
|
1117
|
+
// In this case, do the computation with the given magic numbers.
|
|
1118
|
+
template <template <stdr::size_t> class Info, stdr::int_least32_t min_exponent,
|
|
1119
|
+
stdr::int_least32_t max_exponent, stdr::size_t current_tier>
|
|
1120
|
+
struct compute_impl<Info, min_exponent, max_exponent, current_tier, true> {
|
|
1121
|
+
using info = Info<current_tier>;
|
|
1122
|
+
using default_return_type = typename info::default_return_type;
|
|
1123
|
+
template <class ReturnType, class Int>
|
|
1124
|
+
static constexpr ReturnType compute(Int e) noexcept {
|
|
1125
|
+
#if JKJ_HAS_CONSTEXPR14
|
|
1126
|
+
assert(min_exponent <= e && e <= max_exponent);
|
|
1127
|
+
#endif
|
|
1128
|
+
// The sign is irrelevant for the mathematical validity of the formula, but
|
|
1129
|
+
// assuming positivity makes the overflow analysis simpler.
|
|
1130
|
+
static_assert(info::multiply >= 0 && info::subtract >= 0, "");
|
|
1131
|
+
return static_cast<ReturnType>((e * info::multiply - info::subtract) >>
|
|
1132
|
+
info::shift);
|
|
1133
|
+
}
|
|
1134
|
+
};
|
|
1135
|
+
|
|
1136
|
+
// Specialization for the case when the given tier does not cover the requested range of
|
|
1137
|
+
// input. In this case, delegate the computation to the next tier. If the next tier does
|
|
1138
|
+
// not exist, then the compilation must fail.
|
|
1139
|
+
template <template <stdr::size_t> class Info, stdr::int_least32_t min_exponent,
|
|
1140
|
+
stdr::int_least32_t max_exponent, stdr::size_t current_tier>
|
|
1141
|
+
struct compute_impl<Info, min_exponent, max_exponent, current_tier, false> {
|
|
1142
|
+
using next_tier = compute_impl<Info, min_exponent, max_exponent, current_tier + 1>;
|
|
1143
|
+
using default_return_type = typename next_tier::default_return_type;
|
|
1144
|
+
template <class ReturnType, class Int>
|
|
1145
|
+
static constexpr ReturnType compute(Int e) noexcept {
|
|
1146
|
+
return next_tier::template compute<ReturnType>(e);
|
|
1147
|
+
}
|
|
1148
|
+
};
|
|
1149
|
+
|
|
1150
|
+
template <stdr::size_t tier>
|
|
1151
|
+
struct floor_log10_pow2_info;
|
|
1152
|
+
template <>
|
|
1153
|
+
struct floor_log10_pow2_info<0> {
|
|
1154
|
+
using default_return_type = stdr::int_fast8_t;
|
|
1155
|
+
static constexpr stdr::int_fast16_t multiply = 77;
|
|
1156
|
+
static constexpr stdr::int_fast16_t subtract = 0;
|
|
1157
|
+
static constexpr stdr::size_t shift = 8;
|
|
1158
|
+
static constexpr stdr::int_least32_t min_exponent = -102;
|
|
1159
|
+
static constexpr stdr::int_least32_t max_exponent = 102;
|
|
1160
|
+
};
|
|
1161
|
+
template <>
|
|
1162
|
+
struct floor_log10_pow2_info<1> {
|
|
1163
|
+
using default_return_type = stdr::int_fast8_t;
|
|
1164
|
+
// 24-bits are enough in fact.
|
|
1165
|
+
static constexpr stdr::int_fast32_t multiply = 1233;
|
|
1166
|
+
static constexpr stdr::int_fast32_t subtract = 0;
|
|
1167
|
+
static constexpr stdr::size_t shift = 12;
|
|
1168
|
+
// Formula itself holds on [-680,680]; [-425,425] is to ensure that the output is
|
|
1169
|
+
// within [-127,127].
|
|
1170
|
+
static constexpr stdr::int_least32_t min_exponent = -425;
|
|
1171
|
+
static constexpr stdr::int_least32_t max_exponent = 425;
|
|
1172
|
+
};
|
|
1173
|
+
template <>
|
|
1174
|
+
struct floor_log10_pow2_info<2> {
|
|
1175
|
+
using default_return_type = stdr::int_fast16_t;
|
|
1176
|
+
static constexpr stdr::int_fast32_t multiply = INT32_C(315653);
|
|
1177
|
+
static constexpr stdr::int_fast32_t subtract = 0;
|
|
1178
|
+
static constexpr stdr::size_t shift = 20;
|
|
1179
|
+
static constexpr stdr::int_least32_t min_exponent = -2620;
|
|
1180
|
+
static constexpr stdr::int_least32_t max_exponent = 2620;
|
|
1181
|
+
};
|
|
1182
|
+
template <stdr::int_least32_t min_exponent = -2620,
|
|
1183
|
+
stdr::int_least32_t max_exponent = 2620,
|
|
1184
|
+
class ReturnType = typename compute_impl<floor_log10_pow2_info, min_exponent,
|
|
1185
|
+
max_exponent>::default_return_type,
|
|
1186
|
+
class Int>
|
|
1187
|
+
constexpr ReturnType floor_log10_pow2(Int e) noexcept {
|
|
1188
|
+
return compute_impl<floor_log10_pow2_info, min_exponent,
|
|
1189
|
+
max_exponent>::template compute<ReturnType>(e);
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
template <stdr::size_t tier>
|
|
1193
|
+
struct floor_log2_pow10_info;
|
|
1194
|
+
template <>
|
|
1195
|
+
struct floor_log2_pow10_info<0> {
|
|
1196
|
+
using default_return_type = stdr::int_fast8_t;
|
|
1197
|
+
static constexpr stdr::int_fast16_t multiply = 53;
|
|
1198
|
+
static constexpr stdr::int_fast16_t subtract = 0;
|
|
1199
|
+
static constexpr stdr::size_t shift = 4;
|
|
1200
|
+
static constexpr stdr::int_least32_t min_exponent = -15;
|
|
1201
|
+
static constexpr stdr::int_least32_t max_exponent = 18;
|
|
1202
|
+
};
|
|
1203
|
+
template <>
|
|
1204
|
+
struct floor_log2_pow10_info<1> {
|
|
1205
|
+
using default_return_type = stdr::int_fast16_t;
|
|
1206
|
+
// 24-bits are enough in fact.
|
|
1207
|
+
static constexpr stdr::int_fast32_t multiply = 1701;
|
|
1208
|
+
static constexpr stdr::int_fast32_t subtract = 0;
|
|
1209
|
+
static constexpr stdr::size_t shift = 9;
|
|
1210
|
+
static constexpr stdr::int_least32_t min_exponent = -58;
|
|
1211
|
+
static constexpr stdr::int_least32_t max_exponent = 58;
|
|
1212
|
+
};
|
|
1213
|
+
template <>
|
|
1214
|
+
struct floor_log2_pow10_info<2> {
|
|
1215
|
+
using default_return_type = stdr::int_fast16_t;
|
|
1216
|
+
static constexpr stdr::int_fast32_t multiply = INT32_C(1741647);
|
|
1217
|
+
static constexpr stdr::int_fast32_t subtract = 0;
|
|
1218
|
+
static constexpr stdr::size_t shift = 19;
|
|
1219
|
+
// Formula itself holds on [-4003,4003]; [-1233,1233] is to ensure no overflow.
|
|
1220
|
+
static constexpr stdr::int_least32_t min_exponent = -1233;
|
|
1221
|
+
static constexpr stdr::int_least32_t max_exponent = 1233;
|
|
1222
|
+
};
|
|
1223
|
+
template <stdr::int_least32_t min_exponent = -1233,
|
|
1224
|
+
stdr::int_least32_t max_exponent = 1233,
|
|
1225
|
+
class ReturnType = typename compute_impl<floor_log2_pow10_info, min_exponent,
|
|
1226
|
+
max_exponent>::default_return_type,
|
|
1227
|
+
class Int>
|
|
1228
|
+
constexpr ReturnType floor_log2_pow10(Int e) noexcept {
|
|
1229
|
+
return compute_impl<floor_log2_pow10_info, min_exponent,
|
|
1230
|
+
max_exponent>::template compute<ReturnType>(e);
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
template <stdr::size_t tier>
|
|
1234
|
+
struct floor_log10_pow2_minus_log10_4_over_3_info;
|
|
1235
|
+
template <>
|
|
1236
|
+
struct floor_log10_pow2_minus_log10_4_over_3_info<0> {
|
|
1237
|
+
using default_return_type = stdr::int_fast8_t;
|
|
1238
|
+
static constexpr stdr::int_fast16_t multiply = 77;
|
|
1239
|
+
static constexpr stdr::int_fast16_t subtract = 31;
|
|
1240
|
+
static constexpr stdr::size_t shift = 8;
|
|
1241
|
+
static constexpr stdr::int_least32_t min_exponent = -75;
|
|
1242
|
+
static constexpr stdr::int_least32_t max_exponent = 129;
|
|
1243
|
+
};
|
|
1244
|
+
template <>
|
|
1245
|
+
struct floor_log10_pow2_minus_log10_4_over_3_info<1> {
|
|
1246
|
+
using default_return_type = stdr::int_fast8_t;
|
|
1247
|
+
// 24-bits are enough in fact.
|
|
1248
|
+
static constexpr stdr::int_fast32_t multiply = 19728;
|
|
1249
|
+
static constexpr stdr::int_fast32_t subtract = 8241;
|
|
1250
|
+
static constexpr stdr::size_t shift = 16;
|
|
1251
|
+
// Formula itself holds on [-849,315]; [-424,315] is to ensure that the output is
|
|
1252
|
+
// within [-127,127].
|
|
1253
|
+
static constexpr stdr::int_least32_t min_exponent = -424;
|
|
1254
|
+
static constexpr stdr::int_least32_t max_exponent = 315;
|
|
1255
|
+
};
|
|
1256
|
+
template <>
|
|
1257
|
+
struct floor_log10_pow2_minus_log10_4_over_3_info<2> {
|
|
1258
|
+
using default_return_type = stdr::int_fast16_t;
|
|
1259
|
+
static constexpr stdr::int_fast32_t multiply = INT32_C(631305);
|
|
1260
|
+
static constexpr stdr::int_fast32_t subtract = INT32_C(261663);
|
|
1261
|
+
static constexpr stdr::size_t shift = 21;
|
|
1262
|
+
static constexpr stdr::int_least32_t min_exponent = -2985;
|
|
1263
|
+
static constexpr stdr::int_least32_t max_exponent = 2936;
|
|
1264
|
+
};
|
|
1265
|
+
template <stdr::int_least32_t min_exponent = -2985,
|
|
1266
|
+
stdr::int_least32_t max_exponent = 2936,
|
|
1267
|
+
class ReturnType =
|
|
1268
|
+
typename compute_impl<floor_log10_pow2_minus_log10_4_over_3_info,
|
|
1269
|
+
min_exponent, max_exponent>::default_return_type,
|
|
1270
|
+
class Int>
|
|
1271
|
+
constexpr ReturnType floor_log10_pow2_minus_log10_4_over_3(Int e) noexcept {
|
|
1272
|
+
return compute_impl<floor_log10_pow2_minus_log10_4_over_3_info, min_exponent,
|
|
1273
|
+
max_exponent>::template compute<ReturnType>(e);
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
template <stdr::size_t tier>
|
|
1277
|
+
struct floor_log2_pow5_info;
|
|
1278
|
+
template <>
|
|
1279
|
+
struct floor_log2_pow5_info<0> {
|
|
1280
|
+
using default_return_type = stdr::int_fast8_t;
|
|
1281
|
+
// 24-bits are enough in fact.
|
|
1282
|
+
static constexpr stdr::int_fast32_t multiply = 1189;
|
|
1283
|
+
static constexpr stdr::int_fast32_t subtract = 0;
|
|
1284
|
+
static constexpr stdr::size_t shift = 9;
|
|
1285
|
+
// Formula itself holds on [-58,58]; [-55,55] is to ensure no overflow.
|
|
1286
|
+
static constexpr stdr::int_least32_t min_exponent = -55;
|
|
1287
|
+
static constexpr stdr::int_least32_t max_exponent = 55;
|
|
1288
|
+
};
|
|
1289
|
+
template <>
|
|
1290
|
+
struct floor_log2_pow5_info<1> {
|
|
1291
|
+
using default_return_type = stdr::int_fast16_t;
|
|
1292
|
+
static constexpr stdr::int_fast32_t multiply = INT32_C(76085);
|
|
1293
|
+
static constexpr stdr::int_fast32_t subtract = 0;
|
|
1294
|
+
static constexpr stdr::size_t shift = 15;
|
|
1295
|
+
static constexpr stdr::int_least32_t min_exponent = -642;
|
|
1296
|
+
static constexpr stdr::int_least32_t max_exponent = 642;
|
|
1297
|
+
};
|
|
1298
|
+
template <stdr::int_least32_t min_exponent = -642,
|
|
1299
|
+
stdr::int_least32_t max_exponent = 642,
|
|
1300
|
+
class ReturnType = typename compute_impl<floor_log2_pow5_info, min_exponent,
|
|
1301
|
+
max_exponent>::default_return_type,
|
|
1302
|
+
class Int>
|
|
1303
|
+
constexpr ReturnType floor_log2_pow5(Int e) noexcept {
|
|
1304
|
+
return compute_impl<floor_log2_pow5_info, min_exponent,
|
|
1305
|
+
max_exponent>::template compute<ReturnType>(e);
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
template <stdr::size_t tier>
|
|
1309
|
+
struct floor_log5_pow2_info;
|
|
1310
|
+
template <>
|
|
1311
|
+
struct floor_log5_pow2_info<0> {
|
|
1312
|
+
using default_return_type = stdr::int_fast32_t;
|
|
1313
|
+
static constexpr stdr::int_fast32_t multiply = INT32_C(225799);
|
|
1314
|
+
static constexpr stdr::int_fast32_t subtract = 0;
|
|
1315
|
+
static constexpr stdr::size_t shift = 19;
|
|
1316
|
+
static constexpr stdr::int_least32_t min_exponent = -1831;
|
|
1317
|
+
static constexpr stdr::int_least32_t max_exponent = 1831;
|
|
1318
|
+
};
|
|
1319
|
+
template <stdr::int_least32_t min_exponent = -1831,
|
|
1320
|
+
stdr::int_least32_t max_exponent = 1831,
|
|
1321
|
+
class ReturnType = typename compute_impl<floor_log5_pow2_info, min_exponent,
|
|
1322
|
+
max_exponent>::default_return_type,
|
|
1323
|
+
class Int>
|
|
1324
|
+
constexpr ReturnType floor_log5_pow2(Int e) noexcept {
|
|
1325
|
+
return compute_impl<floor_log5_pow2_info, min_exponent,
|
|
1326
|
+
max_exponent>::template compute<ReturnType>(e);
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1329
|
+
template <stdr::size_t tier>
|
|
1330
|
+
struct floor_log5_pow2_minus_log5_3_info;
|
|
1331
|
+
template <>
|
|
1332
|
+
struct floor_log5_pow2_minus_log5_3_info<0> {
|
|
1333
|
+
using default_return_type = stdr::int_fast32_t;
|
|
1334
|
+
static constexpr stdr::int_fast32_t multiply = INT32_C(451597);
|
|
1335
|
+
static constexpr stdr::int_fast32_t subtract = INT32_C(715764);
|
|
1336
|
+
static constexpr stdr::size_t shift = 20;
|
|
1337
|
+
static constexpr stdr::int_least32_t min_exponent = -3543;
|
|
1338
|
+
static constexpr stdr::int_least32_t max_exponent = 2427;
|
|
1339
|
+
};
|
|
1340
|
+
template <stdr::int_least32_t min_exponent = -3543,
|
|
1341
|
+
stdr::int_least32_t max_exponent = 2427,
|
|
1342
|
+
class ReturnType =
|
|
1343
|
+
typename compute_impl<floor_log5_pow2_minus_log5_3_info, min_exponent,
|
|
1344
|
+
max_exponent>::default_return_type,
|
|
1345
|
+
class Int>
|
|
1346
|
+
constexpr ReturnType floor_log5_pow2_minus_log5_3(Int e) noexcept {
|
|
1347
|
+
return compute_impl<floor_log5_pow2_minus_log5_3_info, min_exponent,
|
|
1348
|
+
max_exponent>::template compute<ReturnType>(e);
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
1353
|
+
// Utilities for fast divisibility tests.
|
|
1354
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
1355
|
+
|
|
1356
|
+
namespace div {
|
|
1357
|
+
// Replace n by floor(n / 10^N).
|
|
1358
|
+
// Returns true if and only if n is divisible by 10^N.
|
|
1359
|
+
// Precondition: n <= 10^(N+1)
|
|
1360
|
+
// !!It takes an in-out parameter!!
|
|
1361
|
+
template <int N, class UInt>
|
|
1362
|
+
struct divide_by_pow10_info;
|
|
1363
|
+
|
|
1364
|
+
template <class UInt>
|
|
1365
|
+
struct divide_by_pow10_info<1, UInt> {
|
|
1366
|
+
static constexpr stdr::uint_fast32_t magic_number = 6554;
|
|
1367
|
+
static constexpr int shift_amount = 16;
|
|
1368
|
+
};
|
|
1369
|
+
|
|
1370
|
+
template <>
|
|
1371
|
+
struct divide_by_pow10_info<1, stdr::uint_least8_t> {
|
|
1372
|
+
static constexpr stdr::uint_fast16_t magic_number = 103;
|
|
1373
|
+
static constexpr int shift_amount = 10;
|
|
1374
|
+
};
|
|
1375
|
+
|
|
1376
|
+
template <>
|
|
1377
|
+
struct divide_by_pow10_info<1, stdr::uint_least16_t> {
|
|
1378
|
+
static constexpr stdr::uint_fast16_t magic_number = 103;
|
|
1379
|
+
static constexpr int shift_amount = 10;
|
|
1380
|
+
};
|
|
1381
|
+
|
|
1382
|
+
template <class UInt>
|
|
1383
|
+
struct divide_by_pow10_info<2, UInt> {
|
|
1384
|
+
static constexpr stdr::uint_fast32_t magic_number = 656;
|
|
1385
|
+
static constexpr int shift_amount = 16;
|
|
1386
|
+
};
|
|
1387
|
+
|
|
1388
|
+
template <>
|
|
1389
|
+
struct divide_by_pow10_info<2, stdr::uint_least16_t> {
|
|
1390
|
+
static constexpr stdr::uint_fast32_t magic_number = 41;
|
|
1391
|
+
static constexpr int shift_amount = 12;
|
|
1392
|
+
};
|
|
1393
|
+
|
|
1394
|
+
template <int N, class UInt>
|
|
1395
|
+
JKJ_CONSTEXPR14 bool check_divisibility_and_divide_by_pow10(UInt& n) noexcept {
|
|
1396
|
+
// Make sure the computation for max_n does not overflow.
|
|
1397
|
+
static_assert(N + 1 <= log::floor_log10_pow2(int(value_bits<UInt>::value)), "");
|
|
1398
|
+
assert(n <= compute_power<N + 1>(UInt(10)));
|
|
1399
|
+
|
|
1400
|
+
using info = divide_by_pow10_info<N, UInt>;
|
|
1401
|
+
using intermediate_type = decltype(info::magic_number);
|
|
1402
|
+
auto const prod = intermediate_type(n * info::magic_number);
|
|
1403
|
+
|
|
1404
|
+
constexpr auto mask =
|
|
1405
|
+
intermediate_type((intermediate_type(1) << info::shift_amount) - 1);
|
|
1406
|
+
bool const result = ((prod & mask) < info::magic_number);
|
|
1407
|
+
|
|
1408
|
+
n = UInt(prod >> info::shift_amount);
|
|
1409
|
+
return result;
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
// Compute floor(n / 10^N) for small n and N.
|
|
1413
|
+
// Precondition: n <= 10^(N+1)
|
|
1414
|
+
template <int N, class UInt>
|
|
1415
|
+
JKJ_CONSTEXPR14 UInt small_division_by_pow10(UInt n) noexcept {
|
|
1416
|
+
// Make sure the computation for max_n does not overflow.
|
|
1417
|
+
static_assert(N + 1 <= log::floor_log10_pow2(int(value_bits<UInt>::value)), "");
|
|
1418
|
+
assert(n <= compute_power<N + 1>(UInt(10)));
|
|
1419
|
+
|
|
1420
|
+
return UInt((n * divide_by_pow10_info<N, UInt>::magic_number) >>
|
|
1421
|
+
divide_by_pow10_info<N, UInt>::shift_amount);
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1424
|
+
// Compute floor(n / 10^N) for small N.
|
|
1425
|
+
// Precondition: n <= n_max
|
|
1426
|
+
template <int N, class UInt, UInt n_max>
|
|
1427
|
+
JKJ_CONSTEXPR20 UInt divide_by_pow10(UInt n) noexcept {
|
|
1428
|
+
static_assert(N >= 0, "");
|
|
1429
|
+
|
|
1430
|
+
// Specialize for 32-bit division by 10.
|
|
1431
|
+
// Without the bound on n_max (which compilers these days never leverage), the
|
|
1432
|
+
// minimum needed amount of shift is larger than 32. Hence, this may generate better
|
|
1433
|
+
// code for 32-bit or smaller architectures. Even for 64-bit architectures, it seems
|
|
1434
|
+
// compilers tend to generate mov + mul instead of a single imul for an unknown
|
|
1435
|
+
// reason if we just write n / 10.
|
|
1436
|
+
JKJ_IF_CONSTEXPR(stdr::is_same<UInt, stdr::uint_least32_t>::value && N == 1 &&
|
|
1437
|
+
n_max <= UINT32_C(1073741828)) {
|
|
1438
|
+
return UInt(wuint::umul64(n, UINT32_C(429496730)) >> 32);
|
|
1439
|
+
}
|
|
1440
|
+
// Specialize for 64-bit division by 10.
|
|
1441
|
+
// Without the bound on n_max (which compilers these days never leverage), the
|
|
1442
|
+
// minimum needed amount of shift is larger than 64.
|
|
1443
|
+
else JKJ_IF_CONSTEXPR(stdr::is_same<UInt, stdr::uint_least64_t>::value && N == 1 &&
|
|
1444
|
+
n_max <= UINT64_C(4611686018427387908)) {
|
|
1445
|
+
return UInt(wuint::umul128_upper64(n, UINT64_C(1844674407370955162)));
|
|
1446
|
+
}
|
|
1447
|
+
// Specialize for 32-bit division by 100.
|
|
1448
|
+
// It seems compilers tend to generate mov + mul instead of a single imul for an
|
|
1449
|
+
// unknown reason if we just write n / 100.
|
|
1450
|
+
else JKJ_IF_CONSTEXPR(stdr::is_same<UInt, stdr::uint_least32_t>::value && N == 2) {
|
|
1451
|
+
return UInt(wuint::umul64(n, UINT32_C(1374389535)) >> 37);
|
|
1452
|
+
}
|
|
1453
|
+
// Specialize for 64-bit division by 1000.
|
|
1454
|
+
// Without the bound on n_max (which compilers these days never leverage), the
|
|
1455
|
+
// smallest magic number for this computation does not fit into 64-bits.
|
|
1456
|
+
else JKJ_IF_CONSTEXPR(stdr::is_same<UInt, stdr::uint_least64_t>::value && N == 3 &&
|
|
1457
|
+
n_max <= UINT64_C(15534100272597517998)) {
|
|
1458
|
+
return UInt(wuint::umul128_upper64(n, UINT64_C(4722366482869645214)) >> 8);
|
|
1459
|
+
}
|
|
1460
|
+
else {
|
|
1461
|
+
constexpr auto divisor = compute_power<N>(UInt(10));
|
|
1462
|
+
return n / divisor;
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
1469
|
+
// Return types for the main interface function.
|
|
1470
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
1471
|
+
|
|
1472
|
+
template <class SignificandType, class ExponentType, bool is_signed, bool trailing_zero_flag>
|
|
1473
|
+
struct decimal_fp;
|
|
1474
|
+
|
|
1475
|
+
template <class SignificandType, class ExponentType>
|
|
1476
|
+
struct decimal_fp<SignificandType, ExponentType, false, false> {
|
|
1477
|
+
SignificandType significand;
|
|
1478
|
+
ExponentType exponent;
|
|
1479
|
+
};
|
|
1480
|
+
|
|
1481
|
+
template <class SignificandType, class ExponentType>
|
|
1482
|
+
struct decimal_fp<SignificandType, ExponentType, true, false> {
|
|
1483
|
+
SignificandType significand;
|
|
1484
|
+
ExponentType exponent;
|
|
1485
|
+
bool is_negative;
|
|
1486
|
+
};
|
|
1487
|
+
|
|
1488
|
+
template <class SignificandType, class ExponentType>
|
|
1489
|
+
struct decimal_fp<SignificandType, ExponentType, false, true> {
|
|
1490
|
+
SignificandType significand;
|
|
1491
|
+
ExponentType exponent;
|
|
1492
|
+
bool may_have_trailing_zeros;
|
|
1493
|
+
};
|
|
1494
|
+
|
|
1495
|
+
template <class SignificandType, class ExponentType>
|
|
1496
|
+
struct decimal_fp<SignificandType, ExponentType, true, true> {
|
|
1497
|
+
SignificandType significand;
|
|
1498
|
+
ExponentType exponent;
|
|
1499
|
+
bool may_have_trailing_zeros;
|
|
1500
|
+
bool is_negative;
|
|
1501
|
+
};
|
|
1502
|
+
|
|
1503
|
+
template <class SignificandType, class ExponentType, bool trailing_zero_flag = false>
|
|
1504
|
+
using unsigned_decimal_fp =
|
|
1505
|
+
decimal_fp<SignificandType, ExponentType, false, trailing_zero_flag>;
|
|
1506
|
+
|
|
1507
|
+
template <class SignificandType, class ExponentType, bool trailing_zero_flag = false>
|
|
1508
|
+
using signed_decimal_fp = decimal_fp<SignificandType, ExponentType, true, trailing_zero_flag>;
|
|
1509
|
+
|
|
1510
|
+
template <class SignificandType, class ExponentType>
|
|
1511
|
+
constexpr signed_decimal_fp<SignificandType, ExponentType, false>
|
|
1512
|
+
add_sign_to_unsigned_decimal_fp(
|
|
1513
|
+
bool is_negative, unsigned_decimal_fp<SignificandType, ExponentType, false> r) noexcept {
|
|
1514
|
+
return {r.significand, r.exponent, is_negative};
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
template <class SignificandType, class ExponentType>
|
|
1518
|
+
constexpr signed_decimal_fp<SignificandType, ExponentType, true>
|
|
1519
|
+
add_sign_to_unsigned_decimal_fp(
|
|
1520
|
+
bool is_negative, unsigned_decimal_fp<SignificandType, ExponentType, true> r) noexcept {
|
|
1521
|
+
return {r.significand, r.exponent, r.may_have_trailing_zeros, is_negative};
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
namespace detail {
|
|
1525
|
+
template <class UnsignedDecimalFp>
|
|
1526
|
+
struct unsigned_decimal_fp_to_signed;
|
|
1527
|
+
|
|
1528
|
+
template <class SignificandType, class ExponentType, bool trailing_zero_flag>
|
|
1529
|
+
struct unsigned_decimal_fp_to_signed<
|
|
1530
|
+
unsigned_decimal_fp<SignificandType, ExponentType, trailing_zero_flag>> {
|
|
1531
|
+
using type = signed_decimal_fp<SignificandType, ExponentType, trailing_zero_flag>;
|
|
1532
|
+
};
|
|
1533
|
+
|
|
1534
|
+
template <class UnsignedDecimalFp>
|
|
1535
|
+
using unsigned_decimal_fp_to_signed_t =
|
|
1536
|
+
typename unsigned_decimal_fp_to_signed<UnsignedDecimalFp>::type;
|
|
1537
|
+
}
|
|
1538
|
+
|
|
1539
|
+
|
|
1540
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
1541
|
+
// Computed cache entries.
|
|
1542
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
1543
|
+
|
|
1544
|
+
template <class FloatFormat, class Dummy = void>
|
|
1545
|
+
struct cache_holder;
|
|
1546
|
+
|
|
1547
|
+
template <class Dummy>
|
|
1548
|
+
struct cache_holder<ieee754_binary32, Dummy> {
|
|
1549
|
+
using cache_entry_type = detail::stdr::uint_least64_t;
|
|
1550
|
+
static constexpr int cache_bits = 64;
|
|
1551
|
+
static constexpr int min_k = -31;
|
|
1552
|
+
static constexpr int max_k = 46;
|
|
1553
|
+
static constexpr detail::array<cache_entry_type, detail::stdr::size_t(max_k - min_k + 1)>
|
|
1554
|
+
cache JKJ_STATIC_DATA_SECTION = {
|
|
1555
|
+
{UINT64_C(0x81ceb32c4b43fcf5), UINT64_C(0xa2425ff75e14fc32),
|
|
1556
|
+
UINT64_C(0xcad2f7f5359a3b3f), UINT64_C(0xfd87b5f28300ca0e),
|
|
1557
|
+
UINT64_C(0x9e74d1b791e07e49), UINT64_C(0xc612062576589ddb),
|
|
1558
|
+
UINT64_C(0xf79687aed3eec552), UINT64_C(0x9abe14cd44753b53),
|
|
1559
|
+
UINT64_C(0xc16d9a0095928a28), UINT64_C(0xf1c90080baf72cb2),
|
|
1560
|
+
UINT64_C(0x971da05074da7bef), UINT64_C(0xbce5086492111aeb),
|
|
1561
|
+
UINT64_C(0xec1e4a7db69561a6), UINT64_C(0x9392ee8e921d5d08),
|
|
1562
|
+
UINT64_C(0xb877aa3236a4b44a), UINT64_C(0xe69594bec44de15c),
|
|
1563
|
+
UINT64_C(0x901d7cf73ab0acda), UINT64_C(0xb424dc35095cd810),
|
|
1564
|
+
UINT64_C(0xe12e13424bb40e14), UINT64_C(0x8cbccc096f5088cc),
|
|
1565
|
+
UINT64_C(0xafebff0bcb24aaff), UINT64_C(0xdbe6fecebdedd5bf),
|
|
1566
|
+
UINT64_C(0x89705f4136b4a598), UINT64_C(0xabcc77118461cefd),
|
|
1567
|
+
UINT64_C(0xd6bf94d5e57a42bd), UINT64_C(0x8637bd05af6c69b6),
|
|
1568
|
+
UINT64_C(0xa7c5ac471b478424), UINT64_C(0xd1b71758e219652c),
|
|
1569
|
+
UINT64_C(0x83126e978d4fdf3c), UINT64_C(0xa3d70a3d70a3d70b),
|
|
1570
|
+
UINT64_C(0xcccccccccccccccd), UINT64_C(0x8000000000000000),
|
|
1571
|
+
UINT64_C(0xa000000000000000), UINT64_C(0xc800000000000000),
|
|
1572
|
+
UINT64_C(0xfa00000000000000), UINT64_C(0x9c40000000000000),
|
|
1573
|
+
UINT64_C(0xc350000000000000), UINT64_C(0xf424000000000000),
|
|
1574
|
+
UINT64_C(0x9896800000000000), UINT64_C(0xbebc200000000000),
|
|
1575
|
+
UINT64_C(0xee6b280000000000), UINT64_C(0x9502f90000000000),
|
|
1576
|
+
UINT64_C(0xba43b74000000000), UINT64_C(0xe8d4a51000000000),
|
|
1577
|
+
UINT64_C(0x9184e72a00000000), UINT64_C(0xb5e620f480000000),
|
|
1578
|
+
UINT64_C(0xe35fa931a0000000), UINT64_C(0x8e1bc9bf04000000),
|
|
1579
|
+
UINT64_C(0xb1a2bc2ec5000000), UINT64_C(0xde0b6b3a76400000),
|
|
1580
|
+
UINT64_C(0x8ac7230489e80000), UINT64_C(0xad78ebc5ac620000),
|
|
1581
|
+
UINT64_C(0xd8d726b7177a8000), UINT64_C(0x878678326eac9000),
|
|
1582
|
+
UINT64_C(0xa968163f0a57b400), UINT64_C(0xd3c21bcecceda100),
|
|
1583
|
+
UINT64_C(0x84595161401484a0), UINT64_C(0xa56fa5b99019a5c8),
|
|
1584
|
+
UINT64_C(0xcecb8f27f4200f3a), UINT64_C(0x813f3978f8940985),
|
|
1585
|
+
UINT64_C(0xa18f07d736b90be6), UINT64_C(0xc9f2c9cd04674edf),
|
|
1586
|
+
UINT64_C(0xfc6f7c4045812297), UINT64_C(0x9dc5ada82b70b59e),
|
|
1587
|
+
UINT64_C(0xc5371912364ce306), UINT64_C(0xf684df56c3e01bc7),
|
|
1588
|
+
UINT64_C(0x9a130b963a6c115d), UINT64_C(0xc097ce7bc90715b4),
|
|
1589
|
+
UINT64_C(0xf0bdc21abb48db21), UINT64_C(0x96769950b50d88f5),
|
|
1590
|
+
UINT64_C(0xbc143fa4e250eb32), UINT64_C(0xeb194f8e1ae525fe),
|
|
1591
|
+
UINT64_C(0x92efd1b8d0cf37bf), UINT64_C(0xb7abc627050305ae),
|
|
1592
|
+
UINT64_C(0xe596b7b0c643c71a), UINT64_C(0x8f7e32ce7bea5c70),
|
|
1593
|
+
UINT64_C(0xb35dbf821ae4f38c), UINT64_C(0xe0352f62a19e306f)}};
|
|
1594
|
+
};
|
|
1595
|
+
#if !JKJ_HAS_INLINE_VARIABLE
|
|
1596
|
+
// decltype(...) should not depend on Dummy; see
|
|
1597
|
+
// https://stackoverflow.com/questions/76438400/decltype-on-static-variable-in-template-class.
|
|
1598
|
+
template <class Dummy>
|
|
1599
|
+
constexpr decltype(cache_holder<ieee754_binary32>::cache)
|
|
1600
|
+
cache_holder<ieee754_binary32, Dummy>::cache;
|
|
1601
|
+
#endif
|
|
1602
|
+
|
|
1603
|
+
template <class Dummy>
|
|
1604
|
+
struct cache_holder<ieee754_binary64, Dummy> {
|
|
1605
|
+
using cache_entry_type = detail::wuint::uint128;
|
|
1606
|
+
static constexpr int cache_bits = 128;
|
|
1607
|
+
static constexpr int min_k = -292;
|
|
1608
|
+
static constexpr int max_k = 326;
|
|
1609
|
+
static constexpr detail::array<cache_entry_type, detail::stdr::size_t(max_k - min_k + 1)>
|
|
1610
|
+
cache JKJ_STATIC_DATA_SECTION = {
|
|
1611
|
+
{{UINT64_C(0xff77b1fcbebcdc4f), UINT64_C(0x25e8e89c13bb0f7b)},
|
|
1612
|
+
{UINT64_C(0x9faacf3df73609b1), UINT64_C(0x77b191618c54e9ad)},
|
|
1613
|
+
{UINT64_C(0xc795830d75038c1d), UINT64_C(0xd59df5b9ef6a2418)},
|
|
1614
|
+
{UINT64_C(0xf97ae3d0d2446f25), UINT64_C(0x4b0573286b44ad1e)},
|
|
1615
|
+
{UINT64_C(0x9becce62836ac577), UINT64_C(0x4ee367f9430aec33)},
|
|
1616
|
+
{UINT64_C(0xc2e801fb244576d5), UINT64_C(0x229c41f793cda740)},
|
|
1617
|
+
{UINT64_C(0xf3a20279ed56d48a), UINT64_C(0x6b43527578c11110)},
|
|
1618
|
+
{UINT64_C(0x9845418c345644d6), UINT64_C(0x830a13896b78aaaa)},
|
|
1619
|
+
{UINT64_C(0xbe5691ef416bd60c), UINT64_C(0x23cc986bc656d554)},
|
|
1620
|
+
{UINT64_C(0xedec366b11c6cb8f), UINT64_C(0x2cbfbe86b7ec8aa9)},
|
|
1621
|
+
{UINT64_C(0x94b3a202eb1c3f39), UINT64_C(0x7bf7d71432f3d6aa)},
|
|
1622
|
+
{UINT64_C(0xb9e08a83a5e34f07), UINT64_C(0xdaf5ccd93fb0cc54)},
|
|
1623
|
+
{UINT64_C(0xe858ad248f5c22c9), UINT64_C(0xd1b3400f8f9cff69)},
|
|
1624
|
+
{UINT64_C(0x91376c36d99995be), UINT64_C(0x23100809b9c21fa2)},
|
|
1625
|
+
{UINT64_C(0xb58547448ffffb2d), UINT64_C(0xabd40a0c2832a78b)},
|
|
1626
|
+
{UINT64_C(0xe2e69915b3fff9f9), UINT64_C(0x16c90c8f323f516d)},
|
|
1627
|
+
{UINT64_C(0x8dd01fad907ffc3b), UINT64_C(0xae3da7d97f6792e4)},
|
|
1628
|
+
{UINT64_C(0xb1442798f49ffb4a), UINT64_C(0x99cd11cfdf41779d)},
|
|
1629
|
+
{UINT64_C(0xdd95317f31c7fa1d), UINT64_C(0x40405643d711d584)},
|
|
1630
|
+
{UINT64_C(0x8a7d3eef7f1cfc52), UINT64_C(0x482835ea666b2573)},
|
|
1631
|
+
{UINT64_C(0xad1c8eab5ee43b66), UINT64_C(0xda3243650005eed0)},
|
|
1632
|
+
{UINT64_C(0xd863b256369d4a40), UINT64_C(0x90bed43e40076a83)},
|
|
1633
|
+
{UINT64_C(0x873e4f75e2224e68), UINT64_C(0x5a7744a6e804a292)},
|
|
1634
|
+
{UINT64_C(0xa90de3535aaae202), UINT64_C(0x711515d0a205cb37)},
|
|
1635
|
+
{UINT64_C(0xd3515c2831559a83), UINT64_C(0x0d5a5b44ca873e04)},
|
|
1636
|
+
{UINT64_C(0x8412d9991ed58091), UINT64_C(0xe858790afe9486c3)},
|
|
1637
|
+
{UINT64_C(0xa5178fff668ae0b6), UINT64_C(0x626e974dbe39a873)},
|
|
1638
|
+
{UINT64_C(0xce5d73ff402d98e3), UINT64_C(0xfb0a3d212dc81290)},
|
|
1639
|
+
{UINT64_C(0x80fa687f881c7f8e), UINT64_C(0x7ce66634bc9d0b9a)},
|
|
1640
|
+
{UINT64_C(0xa139029f6a239f72), UINT64_C(0x1c1fffc1ebc44e81)},
|
|
1641
|
+
{UINT64_C(0xc987434744ac874e), UINT64_C(0xa327ffb266b56221)},
|
|
1642
|
+
{UINT64_C(0xfbe9141915d7a922), UINT64_C(0x4bf1ff9f0062baa9)},
|
|
1643
|
+
{UINT64_C(0x9d71ac8fada6c9b5), UINT64_C(0x6f773fc3603db4aa)},
|
|
1644
|
+
{UINT64_C(0xc4ce17b399107c22), UINT64_C(0xcb550fb4384d21d4)},
|
|
1645
|
+
{UINT64_C(0xf6019da07f549b2b), UINT64_C(0x7e2a53a146606a49)},
|
|
1646
|
+
{UINT64_C(0x99c102844f94e0fb), UINT64_C(0x2eda7444cbfc426e)},
|
|
1647
|
+
{UINT64_C(0xc0314325637a1939), UINT64_C(0xfa911155fefb5309)},
|
|
1648
|
+
{UINT64_C(0xf03d93eebc589f88), UINT64_C(0x793555ab7eba27cb)},
|
|
1649
|
+
{UINT64_C(0x96267c7535b763b5), UINT64_C(0x4bc1558b2f3458df)},
|
|
1650
|
+
{UINT64_C(0xbbb01b9283253ca2), UINT64_C(0x9eb1aaedfb016f17)},
|
|
1651
|
+
{UINT64_C(0xea9c227723ee8bcb), UINT64_C(0x465e15a979c1cadd)},
|
|
1652
|
+
{UINT64_C(0x92a1958a7675175f), UINT64_C(0x0bfacd89ec191eca)},
|
|
1653
|
+
{UINT64_C(0xb749faed14125d36), UINT64_C(0xcef980ec671f667c)},
|
|
1654
|
+
{UINT64_C(0xe51c79a85916f484), UINT64_C(0x82b7e12780e7401b)},
|
|
1655
|
+
{UINT64_C(0x8f31cc0937ae58d2), UINT64_C(0xd1b2ecb8b0908811)},
|
|
1656
|
+
{UINT64_C(0xb2fe3f0b8599ef07), UINT64_C(0x861fa7e6dcb4aa16)},
|
|
1657
|
+
{UINT64_C(0xdfbdcece67006ac9), UINT64_C(0x67a791e093e1d49b)},
|
|
1658
|
+
{UINT64_C(0x8bd6a141006042bd), UINT64_C(0xe0c8bb2c5c6d24e1)},
|
|
1659
|
+
{UINT64_C(0xaecc49914078536d), UINT64_C(0x58fae9f773886e19)},
|
|
1660
|
+
{UINT64_C(0xda7f5bf590966848), UINT64_C(0xaf39a475506a899f)},
|
|
1661
|
+
{UINT64_C(0x888f99797a5e012d), UINT64_C(0x6d8406c952429604)},
|
|
1662
|
+
{UINT64_C(0xaab37fd7d8f58178), UINT64_C(0xc8e5087ba6d33b84)},
|
|
1663
|
+
{UINT64_C(0xd5605fcdcf32e1d6), UINT64_C(0xfb1e4a9a90880a65)},
|
|
1664
|
+
{UINT64_C(0x855c3be0a17fcd26), UINT64_C(0x5cf2eea09a550680)},
|
|
1665
|
+
{UINT64_C(0xa6b34ad8c9dfc06f), UINT64_C(0xf42faa48c0ea481f)},
|
|
1666
|
+
{UINT64_C(0xd0601d8efc57b08b), UINT64_C(0xf13b94daf124da27)},
|
|
1667
|
+
{UINT64_C(0x823c12795db6ce57), UINT64_C(0x76c53d08d6b70859)},
|
|
1668
|
+
{UINT64_C(0xa2cb1717b52481ed), UINT64_C(0x54768c4b0c64ca6f)},
|
|
1669
|
+
{UINT64_C(0xcb7ddcdda26da268), UINT64_C(0xa9942f5dcf7dfd0a)},
|
|
1670
|
+
{UINT64_C(0xfe5d54150b090b02), UINT64_C(0xd3f93b35435d7c4d)},
|
|
1671
|
+
{UINT64_C(0x9efa548d26e5a6e1), UINT64_C(0xc47bc5014a1a6db0)},
|
|
1672
|
+
{UINT64_C(0xc6b8e9b0709f109a), UINT64_C(0x359ab6419ca1091c)},
|
|
1673
|
+
{UINT64_C(0xf867241c8cc6d4c0), UINT64_C(0xc30163d203c94b63)},
|
|
1674
|
+
{UINT64_C(0x9b407691d7fc44f8), UINT64_C(0x79e0de63425dcf1e)},
|
|
1675
|
+
{UINT64_C(0xc21094364dfb5636), UINT64_C(0x985915fc12f542e5)},
|
|
1676
|
+
{UINT64_C(0xf294b943e17a2bc4), UINT64_C(0x3e6f5b7b17b2939e)},
|
|
1677
|
+
{UINT64_C(0x979cf3ca6cec5b5a), UINT64_C(0xa705992ceecf9c43)},
|
|
1678
|
+
{UINT64_C(0xbd8430bd08277231), UINT64_C(0x50c6ff782a838354)},
|
|
1679
|
+
{UINT64_C(0xece53cec4a314ebd), UINT64_C(0xa4f8bf5635246429)},
|
|
1680
|
+
{UINT64_C(0x940f4613ae5ed136), UINT64_C(0x871b7795e136be9a)},
|
|
1681
|
+
{UINT64_C(0xb913179899f68584), UINT64_C(0x28e2557b59846e40)},
|
|
1682
|
+
{UINT64_C(0xe757dd7ec07426e5), UINT64_C(0x331aeada2fe589d0)},
|
|
1683
|
+
{UINT64_C(0x9096ea6f3848984f), UINT64_C(0x3ff0d2c85def7622)},
|
|
1684
|
+
{UINT64_C(0xb4bca50b065abe63), UINT64_C(0x0fed077a756b53aa)},
|
|
1685
|
+
{UINT64_C(0xe1ebce4dc7f16dfb), UINT64_C(0xd3e8495912c62895)},
|
|
1686
|
+
{UINT64_C(0x8d3360f09cf6e4bd), UINT64_C(0x64712dd7abbbd95d)},
|
|
1687
|
+
{UINT64_C(0xb080392cc4349dec), UINT64_C(0xbd8d794d96aacfb4)},
|
|
1688
|
+
{UINT64_C(0xdca04777f541c567), UINT64_C(0xecf0d7a0fc5583a1)},
|
|
1689
|
+
{UINT64_C(0x89e42caaf9491b60), UINT64_C(0xf41686c49db57245)},
|
|
1690
|
+
{UINT64_C(0xac5d37d5b79b6239), UINT64_C(0x311c2875c522ced6)},
|
|
1691
|
+
{UINT64_C(0xd77485cb25823ac7), UINT64_C(0x7d633293366b828c)},
|
|
1692
|
+
{UINT64_C(0x86a8d39ef77164bc), UINT64_C(0xae5dff9c02033198)},
|
|
1693
|
+
{UINT64_C(0xa8530886b54dbdeb), UINT64_C(0xd9f57f830283fdfd)},
|
|
1694
|
+
{UINT64_C(0xd267caa862a12d66), UINT64_C(0xd072df63c324fd7c)},
|
|
1695
|
+
{UINT64_C(0x8380dea93da4bc60), UINT64_C(0x4247cb9e59f71e6e)},
|
|
1696
|
+
{UINT64_C(0xa46116538d0deb78), UINT64_C(0x52d9be85f074e609)},
|
|
1697
|
+
{UINT64_C(0xcd795be870516656), UINT64_C(0x67902e276c921f8c)},
|
|
1698
|
+
{UINT64_C(0x806bd9714632dff6), UINT64_C(0x00ba1cd8a3db53b7)},
|
|
1699
|
+
{UINT64_C(0xa086cfcd97bf97f3), UINT64_C(0x80e8a40eccd228a5)},
|
|
1700
|
+
{UINT64_C(0xc8a883c0fdaf7df0), UINT64_C(0x6122cd128006b2ce)},
|
|
1701
|
+
{UINT64_C(0xfad2a4b13d1b5d6c), UINT64_C(0x796b805720085f82)},
|
|
1702
|
+
{UINT64_C(0x9cc3a6eec6311a63), UINT64_C(0xcbe3303674053bb1)},
|
|
1703
|
+
{UINT64_C(0xc3f490aa77bd60fc), UINT64_C(0xbedbfc4411068a9d)},
|
|
1704
|
+
{UINT64_C(0xf4f1b4d515acb93b), UINT64_C(0xee92fb5515482d45)},
|
|
1705
|
+
{UINT64_C(0x991711052d8bf3c5), UINT64_C(0x751bdd152d4d1c4b)},
|
|
1706
|
+
{UINT64_C(0xbf5cd54678eef0b6), UINT64_C(0xd262d45a78a0635e)},
|
|
1707
|
+
{UINT64_C(0xef340a98172aace4), UINT64_C(0x86fb897116c87c35)},
|
|
1708
|
+
{UINT64_C(0x9580869f0e7aac0e), UINT64_C(0xd45d35e6ae3d4da1)},
|
|
1709
|
+
{UINT64_C(0xbae0a846d2195712), UINT64_C(0x8974836059cca10a)},
|
|
1710
|
+
{UINT64_C(0xe998d258869facd7), UINT64_C(0x2bd1a438703fc94c)},
|
|
1711
|
+
{UINT64_C(0x91ff83775423cc06), UINT64_C(0x7b6306a34627ddd0)},
|
|
1712
|
+
{UINT64_C(0xb67f6455292cbf08), UINT64_C(0x1a3bc84c17b1d543)},
|
|
1713
|
+
{UINT64_C(0xe41f3d6a7377eeca), UINT64_C(0x20caba5f1d9e4a94)},
|
|
1714
|
+
{UINT64_C(0x8e938662882af53e), UINT64_C(0x547eb47b7282ee9d)},
|
|
1715
|
+
{UINT64_C(0xb23867fb2a35b28d), UINT64_C(0xe99e619a4f23aa44)},
|
|
1716
|
+
{UINT64_C(0xdec681f9f4c31f31), UINT64_C(0x6405fa00e2ec94d5)},
|
|
1717
|
+
{UINT64_C(0x8b3c113c38f9f37e), UINT64_C(0xde83bc408dd3dd05)},
|
|
1718
|
+
{UINT64_C(0xae0b158b4738705e), UINT64_C(0x9624ab50b148d446)},
|
|
1719
|
+
{UINT64_C(0xd98ddaee19068c76), UINT64_C(0x3badd624dd9b0958)},
|
|
1720
|
+
{UINT64_C(0x87f8a8d4cfa417c9), UINT64_C(0xe54ca5d70a80e5d7)},
|
|
1721
|
+
{UINT64_C(0xa9f6d30a038d1dbc), UINT64_C(0x5e9fcf4ccd211f4d)},
|
|
1722
|
+
{UINT64_C(0xd47487cc8470652b), UINT64_C(0x7647c32000696720)},
|
|
1723
|
+
{UINT64_C(0x84c8d4dfd2c63f3b), UINT64_C(0x29ecd9f40041e074)},
|
|
1724
|
+
{UINT64_C(0xa5fb0a17c777cf09), UINT64_C(0xf468107100525891)},
|
|
1725
|
+
{UINT64_C(0xcf79cc9db955c2cc), UINT64_C(0x7182148d4066eeb5)},
|
|
1726
|
+
{UINT64_C(0x81ac1fe293d599bf), UINT64_C(0xc6f14cd848405531)},
|
|
1727
|
+
{UINT64_C(0xa21727db38cb002f), UINT64_C(0xb8ada00e5a506a7d)},
|
|
1728
|
+
{UINT64_C(0xca9cf1d206fdc03b), UINT64_C(0xa6d90811f0e4851d)},
|
|
1729
|
+
{UINT64_C(0xfd442e4688bd304a), UINT64_C(0x908f4a166d1da664)},
|
|
1730
|
+
{UINT64_C(0x9e4a9cec15763e2e), UINT64_C(0x9a598e4e043287ff)},
|
|
1731
|
+
{UINT64_C(0xc5dd44271ad3cdba), UINT64_C(0x40eff1e1853f29fe)},
|
|
1732
|
+
{UINT64_C(0xf7549530e188c128), UINT64_C(0xd12bee59e68ef47d)},
|
|
1733
|
+
{UINT64_C(0x9a94dd3e8cf578b9), UINT64_C(0x82bb74f8301958cf)},
|
|
1734
|
+
{UINT64_C(0xc13a148e3032d6e7), UINT64_C(0xe36a52363c1faf02)},
|
|
1735
|
+
{UINT64_C(0xf18899b1bc3f8ca1), UINT64_C(0xdc44e6c3cb279ac2)},
|
|
1736
|
+
{UINT64_C(0x96f5600f15a7b7e5), UINT64_C(0x29ab103a5ef8c0ba)},
|
|
1737
|
+
{UINT64_C(0xbcb2b812db11a5de), UINT64_C(0x7415d448f6b6f0e8)},
|
|
1738
|
+
{UINT64_C(0xebdf661791d60f56), UINT64_C(0x111b495b3464ad22)},
|
|
1739
|
+
{UINT64_C(0x936b9fcebb25c995), UINT64_C(0xcab10dd900beec35)},
|
|
1740
|
+
{UINT64_C(0xb84687c269ef3bfb), UINT64_C(0x3d5d514f40eea743)},
|
|
1741
|
+
{UINT64_C(0xe65829b3046b0afa), UINT64_C(0x0cb4a5a3112a5113)},
|
|
1742
|
+
{UINT64_C(0x8ff71a0fe2c2e6dc), UINT64_C(0x47f0e785eaba72ac)},
|
|
1743
|
+
{UINT64_C(0xb3f4e093db73a093), UINT64_C(0x59ed216765690f57)},
|
|
1744
|
+
{UINT64_C(0xe0f218b8d25088b8), UINT64_C(0x306869c13ec3532d)},
|
|
1745
|
+
{UINT64_C(0x8c974f7383725573), UINT64_C(0x1e414218c73a13fc)},
|
|
1746
|
+
{UINT64_C(0xafbd2350644eeacf), UINT64_C(0xe5d1929ef90898fb)},
|
|
1747
|
+
{UINT64_C(0xdbac6c247d62a583), UINT64_C(0xdf45f746b74abf3a)},
|
|
1748
|
+
{UINT64_C(0x894bc396ce5da772), UINT64_C(0x6b8bba8c328eb784)},
|
|
1749
|
+
{UINT64_C(0xab9eb47c81f5114f), UINT64_C(0x066ea92f3f326565)},
|
|
1750
|
+
{UINT64_C(0xd686619ba27255a2), UINT64_C(0xc80a537b0efefebe)},
|
|
1751
|
+
{UINT64_C(0x8613fd0145877585), UINT64_C(0xbd06742ce95f5f37)},
|
|
1752
|
+
{UINT64_C(0xa798fc4196e952e7), UINT64_C(0x2c48113823b73705)},
|
|
1753
|
+
{UINT64_C(0xd17f3b51fca3a7a0), UINT64_C(0xf75a15862ca504c6)},
|
|
1754
|
+
{UINT64_C(0x82ef85133de648c4), UINT64_C(0x9a984d73dbe722fc)},
|
|
1755
|
+
{UINT64_C(0xa3ab66580d5fdaf5), UINT64_C(0xc13e60d0d2e0ebbb)},
|
|
1756
|
+
{UINT64_C(0xcc963fee10b7d1b3), UINT64_C(0x318df905079926a9)},
|
|
1757
|
+
{UINT64_C(0xffbbcfe994e5c61f), UINT64_C(0xfdf17746497f7053)},
|
|
1758
|
+
{UINT64_C(0x9fd561f1fd0f9bd3), UINT64_C(0xfeb6ea8bedefa634)},
|
|
1759
|
+
{UINT64_C(0xc7caba6e7c5382c8), UINT64_C(0xfe64a52ee96b8fc1)},
|
|
1760
|
+
{UINT64_C(0xf9bd690a1b68637b), UINT64_C(0x3dfdce7aa3c673b1)},
|
|
1761
|
+
{UINT64_C(0x9c1661a651213e2d), UINT64_C(0x06bea10ca65c084f)},
|
|
1762
|
+
{UINT64_C(0xc31bfa0fe5698db8), UINT64_C(0x486e494fcff30a63)},
|
|
1763
|
+
{UINT64_C(0xf3e2f893dec3f126), UINT64_C(0x5a89dba3c3efccfb)},
|
|
1764
|
+
{UINT64_C(0x986ddb5c6b3a76b7), UINT64_C(0xf89629465a75e01d)},
|
|
1765
|
+
{UINT64_C(0xbe89523386091465), UINT64_C(0xf6bbb397f1135824)},
|
|
1766
|
+
{UINT64_C(0xee2ba6c0678b597f), UINT64_C(0x746aa07ded582e2d)},
|
|
1767
|
+
{UINT64_C(0x94db483840b717ef), UINT64_C(0xa8c2a44eb4571cdd)},
|
|
1768
|
+
{UINT64_C(0xba121a4650e4ddeb), UINT64_C(0x92f34d62616ce414)},
|
|
1769
|
+
{UINT64_C(0xe896a0d7e51e1566), UINT64_C(0x77b020baf9c81d18)},
|
|
1770
|
+
{UINT64_C(0x915e2486ef32cd60), UINT64_C(0x0ace1474dc1d122f)},
|
|
1771
|
+
{UINT64_C(0xb5b5ada8aaff80b8), UINT64_C(0x0d819992132456bb)},
|
|
1772
|
+
{UINT64_C(0xe3231912d5bf60e6), UINT64_C(0x10e1fff697ed6c6a)},
|
|
1773
|
+
{UINT64_C(0x8df5efabc5979c8f), UINT64_C(0xca8d3ffa1ef463c2)},
|
|
1774
|
+
{UINT64_C(0xb1736b96b6fd83b3), UINT64_C(0xbd308ff8a6b17cb3)},
|
|
1775
|
+
{UINT64_C(0xddd0467c64bce4a0), UINT64_C(0xac7cb3f6d05ddbdf)},
|
|
1776
|
+
{UINT64_C(0x8aa22c0dbef60ee4), UINT64_C(0x6bcdf07a423aa96c)},
|
|
1777
|
+
{UINT64_C(0xad4ab7112eb3929d), UINT64_C(0x86c16c98d2c953c7)},
|
|
1778
|
+
{UINT64_C(0xd89d64d57a607744), UINT64_C(0xe871c7bf077ba8b8)},
|
|
1779
|
+
{UINT64_C(0x87625f056c7c4a8b), UINT64_C(0x11471cd764ad4973)},
|
|
1780
|
+
{UINT64_C(0xa93af6c6c79b5d2d), UINT64_C(0xd598e40d3dd89bd0)},
|
|
1781
|
+
{UINT64_C(0xd389b47879823479), UINT64_C(0x4aff1d108d4ec2c4)},
|
|
1782
|
+
{UINT64_C(0x843610cb4bf160cb), UINT64_C(0xcedf722a585139bb)},
|
|
1783
|
+
{UINT64_C(0xa54394fe1eedb8fe), UINT64_C(0xc2974eb4ee658829)},
|
|
1784
|
+
{UINT64_C(0xce947a3da6a9273e), UINT64_C(0x733d226229feea33)},
|
|
1785
|
+
{UINT64_C(0x811ccc668829b887), UINT64_C(0x0806357d5a3f5260)},
|
|
1786
|
+
{UINT64_C(0xa163ff802a3426a8), UINT64_C(0xca07c2dcb0cf26f8)},
|
|
1787
|
+
{UINT64_C(0xc9bcff6034c13052), UINT64_C(0xfc89b393dd02f0b6)},
|
|
1788
|
+
{UINT64_C(0xfc2c3f3841f17c67), UINT64_C(0xbbac2078d443ace3)},
|
|
1789
|
+
{UINT64_C(0x9d9ba7832936edc0), UINT64_C(0xd54b944b84aa4c0e)},
|
|
1790
|
+
{UINT64_C(0xc5029163f384a931), UINT64_C(0x0a9e795e65d4df12)},
|
|
1791
|
+
{UINT64_C(0xf64335bcf065d37d), UINT64_C(0x4d4617b5ff4a16d6)},
|
|
1792
|
+
{UINT64_C(0x99ea0196163fa42e), UINT64_C(0x504bced1bf8e4e46)},
|
|
1793
|
+
{UINT64_C(0xc06481fb9bcf8d39), UINT64_C(0xe45ec2862f71e1d7)},
|
|
1794
|
+
{UINT64_C(0xf07da27a82c37088), UINT64_C(0x5d767327bb4e5a4d)},
|
|
1795
|
+
{UINT64_C(0x964e858c91ba2655), UINT64_C(0x3a6a07f8d510f870)},
|
|
1796
|
+
{UINT64_C(0xbbe226efb628afea), UINT64_C(0x890489f70a55368c)},
|
|
1797
|
+
{UINT64_C(0xeadab0aba3b2dbe5), UINT64_C(0x2b45ac74ccea842f)},
|
|
1798
|
+
{UINT64_C(0x92c8ae6b464fc96f), UINT64_C(0x3b0b8bc90012929e)},
|
|
1799
|
+
{UINT64_C(0xb77ada0617e3bbcb), UINT64_C(0x09ce6ebb40173745)},
|
|
1800
|
+
{UINT64_C(0xe55990879ddcaabd), UINT64_C(0xcc420a6a101d0516)},
|
|
1801
|
+
{UINT64_C(0x8f57fa54c2a9eab6), UINT64_C(0x9fa946824a12232e)},
|
|
1802
|
+
{UINT64_C(0xb32df8e9f3546564), UINT64_C(0x47939822dc96abfa)},
|
|
1803
|
+
{UINT64_C(0xdff9772470297ebd), UINT64_C(0x59787e2b93bc56f8)},
|
|
1804
|
+
{UINT64_C(0x8bfbea76c619ef36), UINT64_C(0x57eb4edb3c55b65b)},
|
|
1805
|
+
{UINT64_C(0xaefae51477a06b03), UINT64_C(0xede622920b6b23f2)},
|
|
1806
|
+
{UINT64_C(0xdab99e59958885c4), UINT64_C(0xe95fab368e45ecee)},
|
|
1807
|
+
{UINT64_C(0x88b402f7fd75539b), UINT64_C(0x11dbcb0218ebb415)},
|
|
1808
|
+
{UINT64_C(0xaae103b5fcd2a881), UINT64_C(0xd652bdc29f26a11a)},
|
|
1809
|
+
{UINT64_C(0xd59944a37c0752a2), UINT64_C(0x4be76d3346f04960)},
|
|
1810
|
+
{UINT64_C(0x857fcae62d8493a5), UINT64_C(0x6f70a4400c562ddc)},
|
|
1811
|
+
{UINT64_C(0xa6dfbd9fb8e5b88e), UINT64_C(0xcb4ccd500f6bb953)},
|
|
1812
|
+
{UINT64_C(0xd097ad07a71f26b2), UINT64_C(0x7e2000a41346a7a8)},
|
|
1813
|
+
{UINT64_C(0x825ecc24c873782f), UINT64_C(0x8ed400668c0c28c9)},
|
|
1814
|
+
{UINT64_C(0xa2f67f2dfa90563b), UINT64_C(0x728900802f0f32fb)},
|
|
1815
|
+
{UINT64_C(0xcbb41ef979346bca), UINT64_C(0x4f2b40a03ad2ffba)},
|
|
1816
|
+
{UINT64_C(0xfea126b7d78186bc), UINT64_C(0xe2f610c84987bfa9)},
|
|
1817
|
+
{UINT64_C(0x9f24b832e6b0f436), UINT64_C(0x0dd9ca7d2df4d7ca)},
|
|
1818
|
+
{UINT64_C(0xc6ede63fa05d3143), UINT64_C(0x91503d1c79720dbc)},
|
|
1819
|
+
{UINT64_C(0xf8a95fcf88747d94), UINT64_C(0x75a44c6397ce912b)},
|
|
1820
|
+
{UINT64_C(0x9b69dbe1b548ce7c), UINT64_C(0xc986afbe3ee11abb)},
|
|
1821
|
+
{UINT64_C(0xc24452da229b021b), UINT64_C(0xfbe85badce996169)},
|
|
1822
|
+
{UINT64_C(0xf2d56790ab41c2a2), UINT64_C(0xfae27299423fb9c4)},
|
|
1823
|
+
{UINT64_C(0x97c560ba6b0919a5), UINT64_C(0xdccd879fc967d41b)},
|
|
1824
|
+
{UINT64_C(0xbdb6b8e905cb600f), UINT64_C(0x5400e987bbc1c921)},
|
|
1825
|
+
{UINT64_C(0xed246723473e3813), UINT64_C(0x290123e9aab23b69)},
|
|
1826
|
+
{UINT64_C(0x9436c0760c86e30b), UINT64_C(0xf9a0b6720aaf6522)},
|
|
1827
|
+
{UINT64_C(0xb94470938fa89bce), UINT64_C(0xf808e40e8d5b3e6a)},
|
|
1828
|
+
{UINT64_C(0xe7958cb87392c2c2), UINT64_C(0xb60b1d1230b20e05)},
|
|
1829
|
+
{UINT64_C(0x90bd77f3483bb9b9), UINT64_C(0xb1c6f22b5e6f48c3)},
|
|
1830
|
+
{UINT64_C(0xb4ecd5f01a4aa828), UINT64_C(0x1e38aeb6360b1af4)},
|
|
1831
|
+
{UINT64_C(0xe2280b6c20dd5232), UINT64_C(0x25c6da63c38de1b1)},
|
|
1832
|
+
{UINT64_C(0x8d590723948a535f), UINT64_C(0x579c487e5a38ad0f)},
|
|
1833
|
+
{UINT64_C(0xb0af48ec79ace837), UINT64_C(0x2d835a9df0c6d852)},
|
|
1834
|
+
{UINT64_C(0xdcdb1b2798182244), UINT64_C(0xf8e431456cf88e66)},
|
|
1835
|
+
{UINT64_C(0x8a08f0f8bf0f156b), UINT64_C(0x1b8e9ecb641b5900)},
|
|
1836
|
+
{UINT64_C(0xac8b2d36eed2dac5), UINT64_C(0xe272467e3d222f40)},
|
|
1837
|
+
{UINT64_C(0xd7adf884aa879177), UINT64_C(0x5b0ed81dcc6abb10)},
|
|
1838
|
+
{UINT64_C(0x86ccbb52ea94baea), UINT64_C(0x98e947129fc2b4ea)},
|
|
1839
|
+
{UINT64_C(0xa87fea27a539e9a5), UINT64_C(0x3f2398d747b36225)},
|
|
1840
|
+
{UINT64_C(0xd29fe4b18e88640e), UINT64_C(0x8eec7f0d19a03aae)},
|
|
1841
|
+
{UINT64_C(0x83a3eeeef9153e89), UINT64_C(0x1953cf68300424ad)},
|
|
1842
|
+
{UINT64_C(0xa48ceaaab75a8e2b), UINT64_C(0x5fa8c3423c052dd8)},
|
|
1843
|
+
{UINT64_C(0xcdb02555653131b6), UINT64_C(0x3792f412cb06794e)},
|
|
1844
|
+
{UINT64_C(0x808e17555f3ebf11), UINT64_C(0xe2bbd88bbee40bd1)},
|
|
1845
|
+
{UINT64_C(0xa0b19d2ab70e6ed6), UINT64_C(0x5b6aceaeae9d0ec5)},
|
|
1846
|
+
{UINT64_C(0xc8de047564d20a8b), UINT64_C(0xf245825a5a445276)},
|
|
1847
|
+
{UINT64_C(0xfb158592be068d2e), UINT64_C(0xeed6e2f0f0d56713)},
|
|
1848
|
+
{UINT64_C(0x9ced737bb6c4183d), UINT64_C(0x55464dd69685606c)},
|
|
1849
|
+
{UINT64_C(0xc428d05aa4751e4c), UINT64_C(0xaa97e14c3c26b887)},
|
|
1850
|
+
{UINT64_C(0xf53304714d9265df), UINT64_C(0xd53dd99f4b3066a9)},
|
|
1851
|
+
{UINT64_C(0x993fe2c6d07b7fab), UINT64_C(0xe546a8038efe402a)},
|
|
1852
|
+
{UINT64_C(0xbf8fdb78849a5f96), UINT64_C(0xde98520472bdd034)},
|
|
1853
|
+
{UINT64_C(0xef73d256a5c0f77c), UINT64_C(0x963e66858f6d4441)},
|
|
1854
|
+
{UINT64_C(0x95a8637627989aad), UINT64_C(0xdde7001379a44aa9)},
|
|
1855
|
+
{UINT64_C(0xbb127c53b17ec159), UINT64_C(0x5560c018580d5d53)},
|
|
1856
|
+
{UINT64_C(0xe9d71b689dde71af), UINT64_C(0xaab8f01e6e10b4a7)},
|
|
1857
|
+
{UINT64_C(0x9226712162ab070d), UINT64_C(0xcab3961304ca70e9)},
|
|
1858
|
+
{UINT64_C(0xb6b00d69bb55c8d1), UINT64_C(0x3d607b97c5fd0d23)},
|
|
1859
|
+
{UINT64_C(0xe45c10c42a2b3b05), UINT64_C(0x8cb89a7db77c506b)},
|
|
1860
|
+
{UINT64_C(0x8eb98a7a9a5b04e3), UINT64_C(0x77f3608e92adb243)},
|
|
1861
|
+
{UINT64_C(0xb267ed1940f1c61c), UINT64_C(0x55f038b237591ed4)},
|
|
1862
|
+
{UINT64_C(0xdf01e85f912e37a3), UINT64_C(0x6b6c46dec52f6689)},
|
|
1863
|
+
{UINT64_C(0x8b61313bbabce2c6), UINT64_C(0x2323ac4b3b3da016)},
|
|
1864
|
+
{UINT64_C(0xae397d8aa96c1b77), UINT64_C(0xabec975e0a0d081b)},
|
|
1865
|
+
{UINT64_C(0xd9c7dced53c72255), UINT64_C(0x96e7bd358c904a22)},
|
|
1866
|
+
{UINT64_C(0x881cea14545c7575), UINT64_C(0x7e50d64177da2e55)},
|
|
1867
|
+
{UINT64_C(0xaa242499697392d2), UINT64_C(0xdde50bd1d5d0b9ea)},
|
|
1868
|
+
{UINT64_C(0xd4ad2dbfc3d07787), UINT64_C(0x955e4ec64b44e865)},
|
|
1869
|
+
{UINT64_C(0x84ec3c97da624ab4), UINT64_C(0xbd5af13bef0b113f)},
|
|
1870
|
+
{UINT64_C(0xa6274bbdd0fadd61), UINT64_C(0xecb1ad8aeacdd58f)},
|
|
1871
|
+
{UINT64_C(0xcfb11ead453994ba), UINT64_C(0x67de18eda5814af3)},
|
|
1872
|
+
{UINT64_C(0x81ceb32c4b43fcf4), UINT64_C(0x80eacf948770ced8)},
|
|
1873
|
+
{UINT64_C(0xa2425ff75e14fc31), UINT64_C(0xa1258379a94d028e)},
|
|
1874
|
+
{UINT64_C(0xcad2f7f5359a3b3e), UINT64_C(0x096ee45813a04331)},
|
|
1875
|
+
{UINT64_C(0xfd87b5f28300ca0d), UINT64_C(0x8bca9d6e188853fd)},
|
|
1876
|
+
{UINT64_C(0x9e74d1b791e07e48), UINT64_C(0x775ea264cf55347e)},
|
|
1877
|
+
{UINT64_C(0xc612062576589dda), UINT64_C(0x95364afe032a819e)},
|
|
1878
|
+
{UINT64_C(0xf79687aed3eec551), UINT64_C(0x3a83ddbd83f52205)},
|
|
1879
|
+
{UINT64_C(0x9abe14cd44753b52), UINT64_C(0xc4926a9672793543)},
|
|
1880
|
+
{UINT64_C(0xc16d9a0095928a27), UINT64_C(0x75b7053c0f178294)},
|
|
1881
|
+
{UINT64_C(0xf1c90080baf72cb1), UINT64_C(0x5324c68b12dd6339)},
|
|
1882
|
+
{UINT64_C(0x971da05074da7bee), UINT64_C(0xd3f6fc16ebca5e04)},
|
|
1883
|
+
{UINT64_C(0xbce5086492111aea), UINT64_C(0x88f4bb1ca6bcf585)},
|
|
1884
|
+
{UINT64_C(0xec1e4a7db69561a5), UINT64_C(0x2b31e9e3d06c32e6)},
|
|
1885
|
+
{UINT64_C(0x9392ee8e921d5d07), UINT64_C(0x3aff322e62439fd0)},
|
|
1886
|
+
{UINT64_C(0xb877aa3236a4b449), UINT64_C(0x09befeb9fad487c3)},
|
|
1887
|
+
{UINT64_C(0xe69594bec44de15b), UINT64_C(0x4c2ebe687989a9b4)},
|
|
1888
|
+
{UINT64_C(0x901d7cf73ab0acd9), UINT64_C(0x0f9d37014bf60a11)},
|
|
1889
|
+
{UINT64_C(0xb424dc35095cd80f), UINT64_C(0x538484c19ef38c95)},
|
|
1890
|
+
{UINT64_C(0xe12e13424bb40e13), UINT64_C(0x2865a5f206b06fba)},
|
|
1891
|
+
{UINT64_C(0x8cbccc096f5088cb), UINT64_C(0xf93f87b7442e45d4)},
|
|
1892
|
+
{UINT64_C(0xafebff0bcb24aafe), UINT64_C(0xf78f69a51539d749)},
|
|
1893
|
+
{UINT64_C(0xdbe6fecebdedd5be), UINT64_C(0xb573440e5a884d1c)},
|
|
1894
|
+
{UINT64_C(0x89705f4136b4a597), UINT64_C(0x31680a88f8953031)},
|
|
1895
|
+
{UINT64_C(0xabcc77118461cefc), UINT64_C(0xfdc20d2b36ba7c3e)},
|
|
1896
|
+
{UINT64_C(0xd6bf94d5e57a42bc), UINT64_C(0x3d32907604691b4d)},
|
|
1897
|
+
{UINT64_C(0x8637bd05af6c69b5), UINT64_C(0xa63f9a49c2c1b110)},
|
|
1898
|
+
{UINT64_C(0xa7c5ac471b478423), UINT64_C(0x0fcf80dc33721d54)},
|
|
1899
|
+
{UINT64_C(0xd1b71758e219652b), UINT64_C(0xd3c36113404ea4a9)},
|
|
1900
|
+
{UINT64_C(0x83126e978d4fdf3b), UINT64_C(0x645a1cac083126ea)},
|
|
1901
|
+
{UINT64_C(0xa3d70a3d70a3d70a), UINT64_C(0x3d70a3d70a3d70a4)},
|
|
1902
|
+
{UINT64_C(0xcccccccccccccccc), UINT64_C(0xcccccccccccccccd)},
|
|
1903
|
+
{UINT64_C(0x8000000000000000), UINT64_C(0x0000000000000000)},
|
|
1904
|
+
{UINT64_C(0xa000000000000000), UINT64_C(0x0000000000000000)},
|
|
1905
|
+
{UINT64_C(0xc800000000000000), UINT64_C(0x0000000000000000)},
|
|
1906
|
+
{UINT64_C(0xfa00000000000000), UINT64_C(0x0000000000000000)},
|
|
1907
|
+
{UINT64_C(0x9c40000000000000), UINT64_C(0x0000000000000000)},
|
|
1908
|
+
{UINT64_C(0xc350000000000000), UINT64_C(0x0000000000000000)},
|
|
1909
|
+
{UINT64_C(0xf424000000000000), UINT64_C(0x0000000000000000)},
|
|
1910
|
+
{UINT64_C(0x9896800000000000), UINT64_C(0x0000000000000000)},
|
|
1911
|
+
{UINT64_C(0xbebc200000000000), UINT64_C(0x0000000000000000)},
|
|
1912
|
+
{UINT64_C(0xee6b280000000000), UINT64_C(0x0000000000000000)},
|
|
1913
|
+
{UINT64_C(0x9502f90000000000), UINT64_C(0x0000000000000000)},
|
|
1914
|
+
{UINT64_C(0xba43b74000000000), UINT64_C(0x0000000000000000)},
|
|
1915
|
+
{UINT64_C(0xe8d4a51000000000), UINT64_C(0x0000000000000000)},
|
|
1916
|
+
{UINT64_C(0x9184e72a00000000), UINT64_C(0x0000000000000000)},
|
|
1917
|
+
{UINT64_C(0xb5e620f480000000), UINT64_C(0x0000000000000000)},
|
|
1918
|
+
{UINT64_C(0xe35fa931a0000000), UINT64_C(0x0000000000000000)},
|
|
1919
|
+
{UINT64_C(0x8e1bc9bf04000000), UINT64_C(0x0000000000000000)},
|
|
1920
|
+
{UINT64_C(0xb1a2bc2ec5000000), UINT64_C(0x0000000000000000)},
|
|
1921
|
+
{UINT64_C(0xde0b6b3a76400000), UINT64_C(0x0000000000000000)},
|
|
1922
|
+
{UINT64_C(0x8ac7230489e80000), UINT64_C(0x0000000000000000)},
|
|
1923
|
+
{UINT64_C(0xad78ebc5ac620000), UINT64_C(0x0000000000000000)},
|
|
1924
|
+
{UINT64_C(0xd8d726b7177a8000), UINT64_C(0x0000000000000000)},
|
|
1925
|
+
{UINT64_C(0x878678326eac9000), UINT64_C(0x0000000000000000)},
|
|
1926
|
+
{UINT64_C(0xa968163f0a57b400), UINT64_C(0x0000000000000000)},
|
|
1927
|
+
{UINT64_C(0xd3c21bcecceda100), UINT64_C(0x0000000000000000)},
|
|
1928
|
+
{UINT64_C(0x84595161401484a0), UINT64_C(0x0000000000000000)},
|
|
1929
|
+
{UINT64_C(0xa56fa5b99019a5c8), UINT64_C(0x0000000000000000)},
|
|
1930
|
+
{UINT64_C(0xcecb8f27f4200f3a), UINT64_C(0x0000000000000000)},
|
|
1931
|
+
{UINT64_C(0x813f3978f8940984), UINT64_C(0x4000000000000000)},
|
|
1932
|
+
{UINT64_C(0xa18f07d736b90be5), UINT64_C(0x5000000000000000)},
|
|
1933
|
+
{UINT64_C(0xc9f2c9cd04674ede), UINT64_C(0xa400000000000000)},
|
|
1934
|
+
{UINT64_C(0xfc6f7c4045812296), UINT64_C(0x4d00000000000000)},
|
|
1935
|
+
{UINT64_C(0x9dc5ada82b70b59d), UINT64_C(0xf020000000000000)},
|
|
1936
|
+
{UINT64_C(0xc5371912364ce305), UINT64_C(0x6c28000000000000)},
|
|
1937
|
+
{UINT64_C(0xf684df56c3e01bc6), UINT64_C(0xc732000000000000)},
|
|
1938
|
+
{UINT64_C(0x9a130b963a6c115c), UINT64_C(0x3c7f400000000000)},
|
|
1939
|
+
{UINT64_C(0xc097ce7bc90715b3), UINT64_C(0x4b9f100000000000)},
|
|
1940
|
+
{UINT64_C(0xf0bdc21abb48db20), UINT64_C(0x1e86d40000000000)},
|
|
1941
|
+
{UINT64_C(0x96769950b50d88f4), UINT64_C(0x1314448000000000)},
|
|
1942
|
+
{UINT64_C(0xbc143fa4e250eb31), UINT64_C(0x17d955a000000000)},
|
|
1943
|
+
{UINT64_C(0xeb194f8e1ae525fd), UINT64_C(0x5dcfab0800000000)},
|
|
1944
|
+
{UINT64_C(0x92efd1b8d0cf37be), UINT64_C(0x5aa1cae500000000)},
|
|
1945
|
+
{UINT64_C(0xb7abc627050305ad), UINT64_C(0xf14a3d9e40000000)},
|
|
1946
|
+
{UINT64_C(0xe596b7b0c643c719), UINT64_C(0x6d9ccd05d0000000)},
|
|
1947
|
+
{UINT64_C(0x8f7e32ce7bea5c6f), UINT64_C(0xe4820023a2000000)},
|
|
1948
|
+
{UINT64_C(0xb35dbf821ae4f38b), UINT64_C(0xdda2802c8a800000)},
|
|
1949
|
+
{UINT64_C(0xe0352f62a19e306e), UINT64_C(0xd50b2037ad200000)},
|
|
1950
|
+
{UINT64_C(0x8c213d9da502de45), UINT64_C(0x4526f422cc340000)},
|
|
1951
|
+
{UINT64_C(0xaf298d050e4395d6), UINT64_C(0x9670b12b7f410000)},
|
|
1952
|
+
{UINT64_C(0xdaf3f04651d47b4c), UINT64_C(0x3c0cdd765f114000)},
|
|
1953
|
+
{UINT64_C(0x88d8762bf324cd0f), UINT64_C(0xa5880a69fb6ac800)},
|
|
1954
|
+
{UINT64_C(0xab0e93b6efee0053), UINT64_C(0x8eea0d047a457a00)},
|
|
1955
|
+
{UINT64_C(0xd5d238a4abe98068), UINT64_C(0x72a4904598d6d880)},
|
|
1956
|
+
{UINT64_C(0x85a36366eb71f041), UINT64_C(0x47a6da2b7f864750)},
|
|
1957
|
+
{UINT64_C(0xa70c3c40a64e6c51), UINT64_C(0x999090b65f67d924)},
|
|
1958
|
+
{UINT64_C(0xd0cf4b50cfe20765), UINT64_C(0xfff4b4e3f741cf6d)},
|
|
1959
|
+
{UINT64_C(0x82818f1281ed449f), UINT64_C(0xbff8f10e7a8921a5)},
|
|
1960
|
+
{UINT64_C(0xa321f2d7226895c7), UINT64_C(0xaff72d52192b6a0e)},
|
|
1961
|
+
{UINT64_C(0xcbea6f8ceb02bb39), UINT64_C(0x9bf4f8a69f764491)},
|
|
1962
|
+
{UINT64_C(0xfee50b7025c36a08), UINT64_C(0x02f236d04753d5b5)},
|
|
1963
|
+
{UINT64_C(0x9f4f2726179a2245), UINT64_C(0x01d762422c946591)},
|
|
1964
|
+
{UINT64_C(0xc722f0ef9d80aad6), UINT64_C(0x424d3ad2b7b97ef6)},
|
|
1965
|
+
{UINT64_C(0xf8ebad2b84e0d58b), UINT64_C(0xd2e0898765a7deb3)},
|
|
1966
|
+
{UINT64_C(0x9b934c3b330c8577), UINT64_C(0x63cc55f49f88eb30)},
|
|
1967
|
+
{UINT64_C(0xc2781f49ffcfa6d5), UINT64_C(0x3cbf6b71c76b25fc)},
|
|
1968
|
+
{UINT64_C(0xf316271c7fc3908a), UINT64_C(0x8bef464e3945ef7b)},
|
|
1969
|
+
{UINT64_C(0x97edd871cfda3a56), UINT64_C(0x97758bf0e3cbb5ad)},
|
|
1970
|
+
{UINT64_C(0xbde94e8e43d0c8ec), UINT64_C(0x3d52eeed1cbea318)},
|
|
1971
|
+
{UINT64_C(0xed63a231d4c4fb27), UINT64_C(0x4ca7aaa863ee4bde)},
|
|
1972
|
+
{UINT64_C(0x945e455f24fb1cf8), UINT64_C(0x8fe8caa93e74ef6b)},
|
|
1973
|
+
{UINT64_C(0xb975d6b6ee39e436), UINT64_C(0xb3e2fd538e122b45)},
|
|
1974
|
+
{UINT64_C(0xe7d34c64a9c85d44), UINT64_C(0x60dbbca87196b617)},
|
|
1975
|
+
{UINT64_C(0x90e40fbeea1d3a4a), UINT64_C(0xbc8955e946fe31ce)},
|
|
1976
|
+
{UINT64_C(0xb51d13aea4a488dd), UINT64_C(0x6babab6398bdbe42)},
|
|
1977
|
+
{UINT64_C(0xe264589a4dcdab14), UINT64_C(0xc696963c7eed2dd2)},
|
|
1978
|
+
{UINT64_C(0x8d7eb76070a08aec), UINT64_C(0xfc1e1de5cf543ca3)},
|
|
1979
|
+
{UINT64_C(0xb0de65388cc8ada8), UINT64_C(0x3b25a55f43294bcc)},
|
|
1980
|
+
{UINT64_C(0xdd15fe86affad912), UINT64_C(0x49ef0eb713f39ebf)},
|
|
1981
|
+
{UINT64_C(0x8a2dbf142dfcc7ab), UINT64_C(0x6e3569326c784338)},
|
|
1982
|
+
{UINT64_C(0xacb92ed9397bf996), UINT64_C(0x49c2c37f07965405)},
|
|
1983
|
+
{UINT64_C(0xd7e77a8f87daf7fb), UINT64_C(0xdc33745ec97be907)},
|
|
1984
|
+
{UINT64_C(0x86f0ac99b4e8dafd), UINT64_C(0x69a028bb3ded71a4)},
|
|
1985
|
+
{UINT64_C(0xa8acd7c0222311bc), UINT64_C(0xc40832ea0d68ce0d)},
|
|
1986
|
+
{UINT64_C(0xd2d80db02aabd62b), UINT64_C(0xf50a3fa490c30191)},
|
|
1987
|
+
{UINT64_C(0x83c7088e1aab65db), UINT64_C(0x792667c6da79e0fb)},
|
|
1988
|
+
{UINT64_C(0xa4b8cab1a1563f52), UINT64_C(0x577001b891185939)},
|
|
1989
|
+
{UINT64_C(0xcde6fd5e09abcf26), UINT64_C(0xed4c0226b55e6f87)},
|
|
1990
|
+
{UINT64_C(0x80b05e5ac60b6178), UINT64_C(0x544f8158315b05b5)},
|
|
1991
|
+
{UINT64_C(0xa0dc75f1778e39d6), UINT64_C(0x696361ae3db1c722)},
|
|
1992
|
+
{UINT64_C(0xc913936dd571c84c), UINT64_C(0x03bc3a19cd1e38ea)},
|
|
1993
|
+
{UINT64_C(0xfb5878494ace3a5f), UINT64_C(0x04ab48a04065c724)},
|
|
1994
|
+
{UINT64_C(0x9d174b2dcec0e47b), UINT64_C(0x62eb0d64283f9c77)},
|
|
1995
|
+
{UINT64_C(0xc45d1df942711d9a), UINT64_C(0x3ba5d0bd324f8395)},
|
|
1996
|
+
{UINT64_C(0xf5746577930d6500), UINT64_C(0xca8f44ec7ee3647a)},
|
|
1997
|
+
{UINT64_C(0x9968bf6abbe85f20), UINT64_C(0x7e998b13cf4e1ecc)},
|
|
1998
|
+
{UINT64_C(0xbfc2ef456ae276e8), UINT64_C(0x9e3fedd8c321a67f)},
|
|
1999
|
+
{UINT64_C(0xefb3ab16c59b14a2), UINT64_C(0xc5cfe94ef3ea101f)},
|
|
2000
|
+
{UINT64_C(0x95d04aee3b80ece5), UINT64_C(0xbba1f1d158724a13)},
|
|
2001
|
+
{UINT64_C(0xbb445da9ca61281f), UINT64_C(0x2a8a6e45ae8edc98)},
|
|
2002
|
+
{UINT64_C(0xea1575143cf97226), UINT64_C(0xf52d09d71a3293be)},
|
|
2003
|
+
{UINT64_C(0x924d692ca61be758), UINT64_C(0x593c2626705f9c57)},
|
|
2004
|
+
{UINT64_C(0xb6e0c377cfa2e12e), UINT64_C(0x6f8b2fb00c77836d)},
|
|
2005
|
+
{UINT64_C(0xe498f455c38b997a), UINT64_C(0x0b6dfb9c0f956448)},
|
|
2006
|
+
{UINT64_C(0x8edf98b59a373fec), UINT64_C(0x4724bd4189bd5ead)},
|
|
2007
|
+
{UINT64_C(0xb2977ee300c50fe7), UINT64_C(0x58edec91ec2cb658)},
|
|
2008
|
+
{UINT64_C(0xdf3d5e9bc0f653e1), UINT64_C(0x2f2967b66737e3ee)},
|
|
2009
|
+
{UINT64_C(0x8b865b215899f46c), UINT64_C(0xbd79e0d20082ee75)},
|
|
2010
|
+
{UINT64_C(0xae67f1e9aec07187), UINT64_C(0xecd8590680a3aa12)},
|
|
2011
|
+
{UINT64_C(0xda01ee641a708de9), UINT64_C(0xe80e6f4820cc9496)},
|
|
2012
|
+
{UINT64_C(0x884134fe908658b2), UINT64_C(0x3109058d147fdcde)},
|
|
2013
|
+
{UINT64_C(0xaa51823e34a7eede), UINT64_C(0xbd4b46f0599fd416)},
|
|
2014
|
+
{UINT64_C(0xd4e5e2cdc1d1ea96), UINT64_C(0x6c9e18ac7007c91b)},
|
|
2015
|
+
{UINT64_C(0x850fadc09923329e), UINT64_C(0x03e2cf6bc604ddb1)},
|
|
2016
|
+
{UINT64_C(0xa6539930bf6bff45), UINT64_C(0x84db8346b786151d)},
|
|
2017
|
+
{UINT64_C(0xcfe87f7cef46ff16), UINT64_C(0xe612641865679a64)},
|
|
2018
|
+
{UINT64_C(0x81f14fae158c5f6e), UINT64_C(0x4fcb7e8f3f60c07f)},
|
|
2019
|
+
{UINT64_C(0xa26da3999aef7749), UINT64_C(0xe3be5e330f38f09e)},
|
|
2020
|
+
{UINT64_C(0xcb090c8001ab551c), UINT64_C(0x5cadf5bfd3072cc6)},
|
|
2021
|
+
{UINT64_C(0xfdcb4fa002162a63), UINT64_C(0x73d9732fc7c8f7f7)},
|
|
2022
|
+
{UINT64_C(0x9e9f11c4014dda7e), UINT64_C(0x2867e7fddcdd9afb)},
|
|
2023
|
+
{UINT64_C(0xc646d63501a1511d), UINT64_C(0xb281e1fd541501b9)},
|
|
2024
|
+
{UINT64_C(0xf7d88bc24209a565), UINT64_C(0x1f225a7ca91a4227)},
|
|
2025
|
+
{UINT64_C(0x9ae757596946075f), UINT64_C(0x3375788de9b06959)},
|
|
2026
|
+
{UINT64_C(0xc1a12d2fc3978937), UINT64_C(0x0052d6b1641c83af)},
|
|
2027
|
+
{UINT64_C(0xf209787bb47d6b84), UINT64_C(0xc0678c5dbd23a49b)},
|
|
2028
|
+
{UINT64_C(0x9745eb4d50ce6332), UINT64_C(0xf840b7ba963646e1)},
|
|
2029
|
+
{UINT64_C(0xbd176620a501fbff), UINT64_C(0xb650e5a93bc3d899)},
|
|
2030
|
+
{UINT64_C(0xec5d3fa8ce427aff), UINT64_C(0xa3e51f138ab4cebf)},
|
|
2031
|
+
{UINT64_C(0x93ba47c980e98cdf), UINT64_C(0xc66f336c36b10138)},
|
|
2032
|
+
{UINT64_C(0xb8a8d9bbe123f017), UINT64_C(0xb80b0047445d4185)},
|
|
2033
|
+
{UINT64_C(0xe6d3102ad96cec1d), UINT64_C(0xa60dc059157491e6)},
|
|
2034
|
+
{UINT64_C(0x9043ea1ac7e41392), UINT64_C(0x87c89837ad68db30)},
|
|
2035
|
+
{UINT64_C(0xb454e4a179dd1877), UINT64_C(0x29babe4598c311fc)},
|
|
2036
|
+
{UINT64_C(0xe16a1dc9d8545e94), UINT64_C(0xf4296dd6fef3d67b)},
|
|
2037
|
+
{UINT64_C(0x8ce2529e2734bb1d), UINT64_C(0x1899e4a65f58660d)},
|
|
2038
|
+
{UINT64_C(0xb01ae745b101e9e4), UINT64_C(0x5ec05dcff72e7f90)},
|
|
2039
|
+
{UINT64_C(0xdc21a1171d42645d), UINT64_C(0x76707543f4fa1f74)},
|
|
2040
|
+
{UINT64_C(0x899504ae72497eba), UINT64_C(0x6a06494a791c53a9)},
|
|
2041
|
+
{UINT64_C(0xabfa45da0edbde69), UINT64_C(0x0487db9d17636893)},
|
|
2042
|
+
{UINT64_C(0xd6f8d7509292d603), UINT64_C(0x45a9d2845d3c42b7)},
|
|
2043
|
+
{UINT64_C(0x865b86925b9bc5c2), UINT64_C(0x0b8a2392ba45a9b3)},
|
|
2044
|
+
{UINT64_C(0xa7f26836f282b732), UINT64_C(0x8e6cac7768d7141f)},
|
|
2045
|
+
{UINT64_C(0xd1ef0244af2364ff), UINT64_C(0x3207d795430cd927)},
|
|
2046
|
+
{UINT64_C(0x8335616aed761f1f), UINT64_C(0x7f44e6bd49e807b9)},
|
|
2047
|
+
{UINT64_C(0xa402b9c5a8d3a6e7), UINT64_C(0x5f16206c9c6209a7)},
|
|
2048
|
+
{UINT64_C(0xcd036837130890a1), UINT64_C(0x36dba887c37a8c10)},
|
|
2049
|
+
{UINT64_C(0x802221226be55a64), UINT64_C(0xc2494954da2c978a)},
|
|
2050
|
+
{UINT64_C(0xa02aa96b06deb0fd), UINT64_C(0xf2db9baa10b7bd6d)},
|
|
2051
|
+
{UINT64_C(0xc83553c5c8965d3d), UINT64_C(0x6f92829494e5acc8)},
|
|
2052
|
+
{UINT64_C(0xfa42a8b73abbf48c), UINT64_C(0xcb772339ba1f17fa)},
|
|
2053
|
+
{UINT64_C(0x9c69a97284b578d7), UINT64_C(0xff2a760414536efc)},
|
|
2054
|
+
{UINT64_C(0xc38413cf25e2d70d), UINT64_C(0xfef5138519684abb)},
|
|
2055
|
+
{UINT64_C(0xf46518c2ef5b8cd1), UINT64_C(0x7eb258665fc25d6a)},
|
|
2056
|
+
{UINT64_C(0x98bf2f79d5993802), UINT64_C(0xef2f773ffbd97a62)},
|
|
2057
|
+
{UINT64_C(0xbeeefb584aff8603), UINT64_C(0xaafb550ffacfd8fb)},
|
|
2058
|
+
{UINT64_C(0xeeaaba2e5dbf6784), UINT64_C(0x95ba2a53f983cf39)},
|
|
2059
|
+
{UINT64_C(0x952ab45cfa97a0b2), UINT64_C(0xdd945a747bf26184)},
|
|
2060
|
+
{UINT64_C(0xba756174393d88df), UINT64_C(0x94f971119aeef9e5)},
|
|
2061
|
+
{UINT64_C(0xe912b9d1478ceb17), UINT64_C(0x7a37cd5601aab85e)},
|
|
2062
|
+
{UINT64_C(0x91abb422ccb812ee), UINT64_C(0xac62e055c10ab33b)},
|
|
2063
|
+
{UINT64_C(0xb616a12b7fe617aa), UINT64_C(0x577b986b314d600a)},
|
|
2064
|
+
{UINT64_C(0xe39c49765fdf9d94), UINT64_C(0xed5a7e85fda0b80c)},
|
|
2065
|
+
{UINT64_C(0x8e41ade9fbebc27d), UINT64_C(0x14588f13be847308)},
|
|
2066
|
+
{UINT64_C(0xb1d219647ae6b31c), UINT64_C(0x596eb2d8ae258fc9)},
|
|
2067
|
+
{UINT64_C(0xde469fbd99a05fe3), UINT64_C(0x6fca5f8ed9aef3bc)},
|
|
2068
|
+
{UINT64_C(0x8aec23d680043bee), UINT64_C(0x25de7bb9480d5855)},
|
|
2069
|
+
{UINT64_C(0xada72ccc20054ae9), UINT64_C(0xaf561aa79a10ae6b)},
|
|
2070
|
+
{UINT64_C(0xd910f7ff28069da4), UINT64_C(0x1b2ba1518094da05)},
|
|
2071
|
+
{UINT64_C(0x87aa9aff79042286), UINT64_C(0x90fb44d2f05d0843)},
|
|
2072
|
+
{UINT64_C(0xa99541bf57452b28), UINT64_C(0x353a1607ac744a54)},
|
|
2073
|
+
{UINT64_C(0xd3fa922f2d1675f2), UINT64_C(0x42889b8997915ce9)},
|
|
2074
|
+
{UINT64_C(0x847c9b5d7c2e09b7), UINT64_C(0x69956135febada12)},
|
|
2075
|
+
{UINT64_C(0xa59bc234db398c25), UINT64_C(0x43fab9837e699096)},
|
|
2076
|
+
{UINT64_C(0xcf02b2c21207ef2e), UINT64_C(0x94f967e45e03f4bc)},
|
|
2077
|
+
{UINT64_C(0x8161afb94b44f57d), UINT64_C(0x1d1be0eebac278f6)},
|
|
2078
|
+
{UINT64_C(0xa1ba1ba79e1632dc), UINT64_C(0x6462d92a69731733)},
|
|
2079
|
+
{UINT64_C(0xca28a291859bbf93), UINT64_C(0x7d7b8f7503cfdcff)},
|
|
2080
|
+
{UINT64_C(0xfcb2cb35e702af78), UINT64_C(0x5cda735244c3d43f)},
|
|
2081
|
+
{UINT64_C(0x9defbf01b061adab), UINT64_C(0x3a0888136afa64a8)},
|
|
2082
|
+
{UINT64_C(0xc56baec21c7a1916), UINT64_C(0x088aaa1845b8fdd1)},
|
|
2083
|
+
{UINT64_C(0xf6c69a72a3989f5b), UINT64_C(0x8aad549e57273d46)},
|
|
2084
|
+
{UINT64_C(0x9a3c2087a63f6399), UINT64_C(0x36ac54e2f678864c)},
|
|
2085
|
+
{UINT64_C(0xc0cb28a98fcf3c7f), UINT64_C(0x84576a1bb416a7de)},
|
|
2086
|
+
{UINT64_C(0xf0fdf2d3f3c30b9f), UINT64_C(0x656d44a2a11c51d6)},
|
|
2087
|
+
{UINT64_C(0x969eb7c47859e743), UINT64_C(0x9f644ae5a4b1b326)},
|
|
2088
|
+
{UINT64_C(0xbc4665b596706114), UINT64_C(0x873d5d9f0dde1fef)},
|
|
2089
|
+
{UINT64_C(0xeb57ff22fc0c7959), UINT64_C(0xa90cb506d155a7eb)},
|
|
2090
|
+
{UINT64_C(0x9316ff75dd87cbd8), UINT64_C(0x09a7f12442d588f3)},
|
|
2091
|
+
{UINT64_C(0xb7dcbf5354e9bece), UINT64_C(0x0c11ed6d538aeb30)},
|
|
2092
|
+
{UINT64_C(0xe5d3ef282a242e81), UINT64_C(0x8f1668c8a86da5fb)},
|
|
2093
|
+
{UINT64_C(0x8fa475791a569d10), UINT64_C(0xf96e017d694487bd)},
|
|
2094
|
+
{UINT64_C(0xb38d92d760ec4455), UINT64_C(0x37c981dcc395a9ad)},
|
|
2095
|
+
{UINT64_C(0xe070f78d3927556a), UINT64_C(0x85bbe253f47b1418)},
|
|
2096
|
+
{UINT64_C(0x8c469ab843b89562), UINT64_C(0x93956d7478ccec8f)},
|
|
2097
|
+
{UINT64_C(0xaf58416654a6babb), UINT64_C(0x387ac8d1970027b3)},
|
|
2098
|
+
{UINT64_C(0xdb2e51bfe9d0696a), UINT64_C(0x06997b05fcc0319f)},
|
|
2099
|
+
{UINT64_C(0x88fcf317f22241e2), UINT64_C(0x441fece3bdf81f04)},
|
|
2100
|
+
{UINT64_C(0xab3c2fddeeaad25a), UINT64_C(0xd527e81cad7626c4)},
|
|
2101
|
+
{UINT64_C(0xd60b3bd56a5586f1), UINT64_C(0x8a71e223d8d3b075)},
|
|
2102
|
+
{UINT64_C(0x85c7056562757456), UINT64_C(0xf6872d5667844e4a)},
|
|
2103
|
+
{UINT64_C(0xa738c6bebb12d16c), UINT64_C(0xb428f8ac016561dc)},
|
|
2104
|
+
{UINT64_C(0xd106f86e69d785c7), UINT64_C(0xe13336d701beba53)},
|
|
2105
|
+
{UINT64_C(0x82a45b450226b39c), UINT64_C(0xecc0024661173474)},
|
|
2106
|
+
{UINT64_C(0xa34d721642b06084), UINT64_C(0x27f002d7f95d0191)},
|
|
2107
|
+
{UINT64_C(0xcc20ce9bd35c78a5), UINT64_C(0x31ec038df7b441f5)},
|
|
2108
|
+
{UINT64_C(0xff290242c83396ce), UINT64_C(0x7e67047175a15272)},
|
|
2109
|
+
{UINT64_C(0x9f79a169bd203e41), UINT64_C(0x0f0062c6e984d387)},
|
|
2110
|
+
{UINT64_C(0xc75809c42c684dd1), UINT64_C(0x52c07b78a3e60869)},
|
|
2111
|
+
{UINT64_C(0xf92e0c3537826145), UINT64_C(0xa7709a56ccdf8a83)},
|
|
2112
|
+
{UINT64_C(0x9bbcc7a142b17ccb), UINT64_C(0x88a66076400bb692)},
|
|
2113
|
+
{UINT64_C(0xc2abf989935ddbfe), UINT64_C(0x6acff893d00ea436)},
|
|
2114
|
+
{UINT64_C(0xf356f7ebf83552fe), UINT64_C(0x0583f6b8c4124d44)},
|
|
2115
|
+
{UINT64_C(0x98165af37b2153de), UINT64_C(0xc3727a337a8b704b)},
|
|
2116
|
+
{UINT64_C(0xbe1bf1b059e9a8d6), UINT64_C(0x744f18c0592e4c5d)},
|
|
2117
|
+
{UINT64_C(0xeda2ee1c7064130c), UINT64_C(0x1162def06f79df74)},
|
|
2118
|
+
{UINT64_C(0x9485d4d1c63e8be7), UINT64_C(0x8addcb5645ac2ba9)},
|
|
2119
|
+
{UINT64_C(0xb9a74a0637ce2ee1), UINT64_C(0x6d953e2bd7173693)},
|
|
2120
|
+
{UINT64_C(0xe8111c87c5c1ba99), UINT64_C(0xc8fa8db6ccdd0438)},
|
|
2121
|
+
{UINT64_C(0x910ab1d4db9914a0), UINT64_C(0x1d9c9892400a22a3)},
|
|
2122
|
+
{UINT64_C(0xb54d5e4a127f59c8), UINT64_C(0x2503beb6d00cab4c)},
|
|
2123
|
+
{UINT64_C(0xe2a0b5dc971f303a), UINT64_C(0x2e44ae64840fd61e)},
|
|
2124
|
+
{UINT64_C(0x8da471a9de737e24), UINT64_C(0x5ceaecfed289e5d3)},
|
|
2125
|
+
{UINT64_C(0xb10d8e1456105dad), UINT64_C(0x7425a83e872c5f48)},
|
|
2126
|
+
{UINT64_C(0xdd50f1996b947518), UINT64_C(0xd12f124e28f7771a)},
|
|
2127
|
+
{UINT64_C(0x8a5296ffe33cc92f), UINT64_C(0x82bd6b70d99aaa70)},
|
|
2128
|
+
{UINT64_C(0xace73cbfdc0bfb7b), UINT64_C(0x636cc64d1001550c)},
|
|
2129
|
+
{UINT64_C(0xd8210befd30efa5a), UINT64_C(0x3c47f7e05401aa4f)},
|
|
2130
|
+
{UINT64_C(0x8714a775e3e95c78), UINT64_C(0x65acfaec34810a72)},
|
|
2131
|
+
{UINT64_C(0xa8d9d1535ce3b396), UINT64_C(0x7f1839a741a14d0e)},
|
|
2132
|
+
{UINT64_C(0xd31045a8341ca07c), UINT64_C(0x1ede48111209a051)},
|
|
2133
|
+
{UINT64_C(0x83ea2b892091e44d), UINT64_C(0x934aed0aab460433)},
|
|
2134
|
+
{UINT64_C(0xa4e4b66b68b65d60), UINT64_C(0xf81da84d56178540)},
|
|
2135
|
+
{UINT64_C(0xce1de40642e3f4b9), UINT64_C(0x36251260ab9d668f)},
|
|
2136
|
+
{UINT64_C(0x80d2ae83e9ce78f3), UINT64_C(0xc1d72b7c6b42601a)},
|
|
2137
|
+
{UINT64_C(0xa1075a24e4421730), UINT64_C(0xb24cf65b8612f820)},
|
|
2138
|
+
{UINT64_C(0xc94930ae1d529cfc), UINT64_C(0xdee033f26797b628)},
|
|
2139
|
+
{UINT64_C(0xfb9b7cd9a4a7443c), UINT64_C(0x169840ef017da3b2)},
|
|
2140
|
+
{UINT64_C(0x9d412e0806e88aa5), UINT64_C(0x8e1f289560ee864f)},
|
|
2141
|
+
{UINT64_C(0xc491798a08a2ad4e), UINT64_C(0xf1a6f2bab92a27e3)},
|
|
2142
|
+
{UINT64_C(0xf5b5d7ec8acb58a2), UINT64_C(0xae10af696774b1dc)},
|
|
2143
|
+
{UINT64_C(0x9991a6f3d6bf1765), UINT64_C(0xacca6da1e0a8ef2a)},
|
|
2144
|
+
{UINT64_C(0xbff610b0cc6edd3f), UINT64_C(0x17fd090a58d32af4)},
|
|
2145
|
+
{UINT64_C(0xeff394dcff8a948e), UINT64_C(0xddfc4b4cef07f5b1)},
|
|
2146
|
+
{UINT64_C(0x95f83d0a1fb69cd9), UINT64_C(0x4abdaf101564f98f)},
|
|
2147
|
+
{UINT64_C(0xbb764c4ca7a4440f), UINT64_C(0x9d6d1ad41abe37f2)},
|
|
2148
|
+
{UINT64_C(0xea53df5fd18d5513), UINT64_C(0x84c86189216dc5ee)},
|
|
2149
|
+
{UINT64_C(0x92746b9be2f8552c), UINT64_C(0x32fd3cf5b4e49bb5)},
|
|
2150
|
+
{UINT64_C(0xb7118682dbb66a77), UINT64_C(0x3fbc8c33221dc2a2)},
|
|
2151
|
+
{UINT64_C(0xe4d5e82392a40515), UINT64_C(0x0fabaf3feaa5334b)},
|
|
2152
|
+
{UINT64_C(0x8f05b1163ba6832d), UINT64_C(0x29cb4d87f2a7400f)},
|
|
2153
|
+
{UINT64_C(0xb2c71d5bca9023f8), UINT64_C(0x743e20e9ef511013)},
|
|
2154
|
+
{UINT64_C(0xdf78e4b2bd342cf6), UINT64_C(0x914da9246b255417)},
|
|
2155
|
+
{UINT64_C(0x8bab8eefb6409c1a), UINT64_C(0x1ad089b6c2f7548f)},
|
|
2156
|
+
{UINT64_C(0xae9672aba3d0c320), UINT64_C(0xa184ac2473b529b2)},
|
|
2157
|
+
{UINT64_C(0xda3c0f568cc4f3e8), UINT64_C(0xc9e5d72d90a2741f)},
|
|
2158
|
+
{UINT64_C(0x8865899617fb1871), UINT64_C(0x7e2fa67c7a658893)},
|
|
2159
|
+
{UINT64_C(0xaa7eebfb9df9de8d), UINT64_C(0xddbb901b98feeab8)},
|
|
2160
|
+
{UINT64_C(0xd51ea6fa85785631), UINT64_C(0x552a74227f3ea566)},
|
|
2161
|
+
{UINT64_C(0x8533285c936b35de), UINT64_C(0xd53a88958f872760)},
|
|
2162
|
+
{UINT64_C(0xa67ff273b8460356), UINT64_C(0x8a892abaf368f138)},
|
|
2163
|
+
{UINT64_C(0xd01fef10a657842c), UINT64_C(0x2d2b7569b0432d86)},
|
|
2164
|
+
{UINT64_C(0x8213f56a67f6b29b), UINT64_C(0x9c3b29620e29fc74)},
|
|
2165
|
+
{UINT64_C(0xa298f2c501f45f42), UINT64_C(0x8349f3ba91b47b90)},
|
|
2166
|
+
{UINT64_C(0xcb3f2f7642717713), UINT64_C(0x241c70a936219a74)},
|
|
2167
|
+
{UINT64_C(0xfe0efb53d30dd4d7), UINT64_C(0xed238cd383aa0111)},
|
|
2168
|
+
{UINT64_C(0x9ec95d1463e8a506), UINT64_C(0xf4363804324a40ab)},
|
|
2169
|
+
{UINT64_C(0xc67bb4597ce2ce48), UINT64_C(0xb143c6053edcd0d6)},
|
|
2170
|
+
{UINT64_C(0xf81aa16fdc1b81da), UINT64_C(0xdd94b7868e94050b)},
|
|
2171
|
+
{UINT64_C(0x9b10a4e5e9913128), UINT64_C(0xca7cf2b4191c8327)},
|
|
2172
|
+
{UINT64_C(0xc1d4ce1f63f57d72), UINT64_C(0xfd1c2f611f63a3f1)},
|
|
2173
|
+
{UINT64_C(0xf24a01a73cf2dccf), UINT64_C(0xbc633b39673c8ced)},
|
|
2174
|
+
{UINT64_C(0x976e41088617ca01), UINT64_C(0xd5be0503e085d814)},
|
|
2175
|
+
{UINT64_C(0xbd49d14aa79dbc82), UINT64_C(0x4b2d8644d8a74e19)},
|
|
2176
|
+
{UINT64_C(0xec9c459d51852ba2), UINT64_C(0xddf8e7d60ed1219f)},
|
|
2177
|
+
{UINT64_C(0x93e1ab8252f33b45), UINT64_C(0xcabb90e5c942b504)},
|
|
2178
|
+
{UINT64_C(0xb8da1662e7b00a17), UINT64_C(0x3d6a751f3b936244)},
|
|
2179
|
+
{UINT64_C(0xe7109bfba19c0c9d), UINT64_C(0x0cc512670a783ad5)},
|
|
2180
|
+
{UINT64_C(0x906a617d450187e2), UINT64_C(0x27fb2b80668b24c6)},
|
|
2181
|
+
{UINT64_C(0xb484f9dc9641e9da), UINT64_C(0xb1f9f660802dedf7)},
|
|
2182
|
+
{UINT64_C(0xe1a63853bbd26451), UINT64_C(0x5e7873f8a0396974)},
|
|
2183
|
+
{UINT64_C(0x8d07e33455637eb2), UINT64_C(0xdb0b487b6423e1e9)},
|
|
2184
|
+
{UINT64_C(0xb049dc016abc5e5f), UINT64_C(0x91ce1a9a3d2cda63)},
|
|
2185
|
+
{UINT64_C(0xdc5c5301c56b75f7), UINT64_C(0x7641a140cc7810fc)},
|
|
2186
|
+
{UINT64_C(0x89b9b3e11b6329ba), UINT64_C(0xa9e904c87fcb0a9e)},
|
|
2187
|
+
{UINT64_C(0xac2820d9623bf429), UINT64_C(0x546345fa9fbdcd45)},
|
|
2188
|
+
{UINT64_C(0xd732290fbacaf133), UINT64_C(0xa97c177947ad4096)},
|
|
2189
|
+
{UINT64_C(0x867f59a9d4bed6c0), UINT64_C(0x49ed8eabcccc485e)},
|
|
2190
|
+
{UINT64_C(0xa81f301449ee8c70), UINT64_C(0x5c68f256bfff5a75)},
|
|
2191
|
+
{UINT64_C(0xd226fc195c6a2f8c), UINT64_C(0x73832eec6fff3112)},
|
|
2192
|
+
{UINT64_C(0x83585d8fd9c25db7), UINT64_C(0xc831fd53c5ff7eac)},
|
|
2193
|
+
{UINT64_C(0xa42e74f3d032f525), UINT64_C(0xba3e7ca8b77f5e56)},
|
|
2194
|
+
{UINT64_C(0xcd3a1230c43fb26f), UINT64_C(0x28ce1bd2e55f35ec)},
|
|
2195
|
+
{UINT64_C(0x80444b5e7aa7cf85), UINT64_C(0x7980d163cf5b81b4)},
|
|
2196
|
+
{UINT64_C(0xa0555e361951c366), UINT64_C(0xd7e105bcc3326220)},
|
|
2197
|
+
{UINT64_C(0xc86ab5c39fa63440), UINT64_C(0x8dd9472bf3fefaa8)},
|
|
2198
|
+
{UINT64_C(0xfa856334878fc150), UINT64_C(0xb14f98f6f0feb952)},
|
|
2199
|
+
{UINT64_C(0x9c935e00d4b9d8d2), UINT64_C(0x6ed1bf9a569f33d4)},
|
|
2200
|
+
{UINT64_C(0xc3b8358109e84f07), UINT64_C(0x0a862f80ec4700c9)},
|
|
2201
|
+
{UINT64_C(0xf4a642e14c6262c8), UINT64_C(0xcd27bb612758c0fb)},
|
|
2202
|
+
{UINT64_C(0x98e7e9cccfbd7dbd), UINT64_C(0x8038d51cb897789d)},
|
|
2203
|
+
{UINT64_C(0xbf21e44003acdd2c), UINT64_C(0xe0470a63e6bd56c4)},
|
|
2204
|
+
{UINT64_C(0xeeea5d5004981478), UINT64_C(0x1858ccfce06cac75)},
|
|
2205
|
+
{UINT64_C(0x95527a5202df0ccb), UINT64_C(0x0f37801e0c43ebc9)},
|
|
2206
|
+
{UINT64_C(0xbaa718e68396cffd), UINT64_C(0xd30560258f54e6bb)},
|
|
2207
|
+
{UINT64_C(0xe950df20247c83fd), UINT64_C(0x47c6b82ef32a206a)},
|
|
2208
|
+
{UINT64_C(0x91d28b7416cdd27e), UINT64_C(0x4cdc331d57fa5442)},
|
|
2209
|
+
{UINT64_C(0xb6472e511c81471d), UINT64_C(0xe0133fe4adf8e953)},
|
|
2210
|
+
{UINT64_C(0xe3d8f9e563a198e5), UINT64_C(0x58180fddd97723a7)},
|
|
2211
|
+
{UINT64_C(0x8e679c2f5e44ff8f), UINT64_C(0x570f09eaa7ea7649)},
|
|
2212
|
+
{UINT64_C(0xb201833b35d63f73), UINT64_C(0x2cd2cc6551e513db)},
|
|
2213
|
+
{UINT64_C(0xde81e40a034bcf4f), UINT64_C(0xf8077f7ea65e58d2)},
|
|
2214
|
+
{UINT64_C(0x8b112e86420f6191), UINT64_C(0xfb04afaf27faf783)},
|
|
2215
|
+
{UINT64_C(0xadd57a27d29339f6), UINT64_C(0x79c5db9af1f9b564)},
|
|
2216
|
+
{UINT64_C(0xd94ad8b1c7380874), UINT64_C(0x18375281ae7822bd)},
|
|
2217
|
+
{UINT64_C(0x87cec76f1c830548), UINT64_C(0x8f2293910d0b15b6)},
|
|
2218
|
+
{UINT64_C(0xa9c2794ae3a3c69a), UINT64_C(0xb2eb3875504ddb23)},
|
|
2219
|
+
{UINT64_C(0xd433179d9c8cb841), UINT64_C(0x5fa60692a46151ec)},
|
|
2220
|
+
{UINT64_C(0x849feec281d7f328), UINT64_C(0xdbc7c41ba6bcd334)},
|
|
2221
|
+
{UINT64_C(0xa5c7ea73224deff3), UINT64_C(0x12b9b522906c0801)},
|
|
2222
|
+
{UINT64_C(0xcf39e50feae16bef), UINT64_C(0xd768226b34870a01)},
|
|
2223
|
+
{UINT64_C(0x81842f29f2cce375), UINT64_C(0xe6a1158300d46641)},
|
|
2224
|
+
{UINT64_C(0xa1e53af46f801c53), UINT64_C(0x60495ae3c1097fd1)},
|
|
2225
|
+
{UINT64_C(0xca5e89b18b602368), UINT64_C(0x385bb19cb14bdfc5)},
|
|
2226
|
+
{UINT64_C(0xfcf62c1dee382c42), UINT64_C(0x46729e03dd9ed7b6)},
|
|
2227
|
+
{UINT64_C(0x9e19db92b4e31ba9), UINT64_C(0x6c07a2c26a8346d2)},
|
|
2228
|
+
{UINT64_C(0xc5a05277621be293), UINT64_C(0xc7098b7305241886)},
|
|
2229
|
+
{UINT64_C(0xf70867153aa2db38), UINT64_C(0xb8cbee4fc66d1ea8)}}};
|
|
2230
|
+
};
|
|
2231
|
+
#if !JKJ_HAS_INLINE_VARIABLE
|
|
2232
|
+
// decltype(...) should not depend on Dummy; see
|
|
2233
|
+
// https://stackoverflow.com/questions/76438400/decltype-on-static-variable-in-template-class.
|
|
2234
|
+
template <class Dummy>
|
|
2235
|
+
constexpr decltype(cache_holder<ieee754_binary64>::cache)
|
|
2236
|
+
cache_holder<ieee754_binary64, Dummy>::cache;
|
|
2237
|
+
#endif
|
|
2238
|
+
|
|
2239
|
+
// Compressed cache.
|
|
2240
|
+
template <class FloatFormat, class Dummy = void>
|
|
2241
|
+
struct compressed_cache_holder {
|
|
2242
|
+
using cache_entry_type = typename cache_holder<FloatFormat>::cache_entry_type;
|
|
2243
|
+
static constexpr int cache_bits = cache_holder<FloatFormat>::cache_bits;
|
|
2244
|
+
static constexpr int min_k = cache_holder<FloatFormat>::min_k;
|
|
2245
|
+
static constexpr int max_k = cache_holder<FloatFormat>::max_k;
|
|
2246
|
+
|
|
2247
|
+
template <class ShiftAmountType, class DecimalExponentType>
|
|
2248
|
+
static JKJ_CONSTEXPR20 cache_entry_type get_cache(DecimalExponentType k) noexcept {
|
|
2249
|
+
return detail::read_static_data(cache_holder<FloatFormat>::cache.data() + k - min_k);
|
|
2250
|
+
}
|
|
2251
|
+
};
|
|
2252
|
+
|
|
2253
|
+
template <class Dummy>
|
|
2254
|
+
struct compressed_cache_holder<ieee754_binary32, Dummy> {
|
|
2255
|
+
using cache_entry_type = cache_holder<ieee754_binary32>::cache_entry_type;
|
|
2256
|
+
static constexpr int cache_bits = cache_holder<ieee754_binary32>::cache_bits;
|
|
2257
|
+
static constexpr int min_k = cache_holder<ieee754_binary32>::min_k;
|
|
2258
|
+
static constexpr int max_k = cache_holder<ieee754_binary32>::max_k;
|
|
2259
|
+
static constexpr int compression_ratio = 13;
|
|
2260
|
+
static constexpr detail::stdr::size_t compressed_table_size =
|
|
2261
|
+
detail::stdr::size_t((max_k - min_k + compression_ratio) / compression_ratio);
|
|
2262
|
+
static constexpr detail::stdr::size_t pow5_table_size =
|
|
2263
|
+
detail::stdr::size_t((compression_ratio + 1) / 2);
|
|
2264
|
+
|
|
2265
|
+
using cache_holder_t = detail::array<cache_entry_type, compressed_table_size>;
|
|
2266
|
+
using pow5_holder_t = detail::array<detail::stdr::uint_least16_t, pow5_table_size>;
|
|
2267
|
+
|
|
2268
|
+
#if JKJ_HAS_CONSTEXPR17
|
|
2269
|
+
static constexpr cache_holder_t cache JKJ_STATIC_DATA_SECTION = [] {
|
|
2270
|
+
cache_holder_t res{};
|
|
2271
|
+
for (detail::stdr::size_t i = 0; i < compressed_table_size; ++i) {
|
|
2272
|
+
res[i] = cache_holder<ieee754_binary32>::cache[i * compression_ratio];
|
|
2273
|
+
}
|
|
2274
|
+
return res;
|
|
2275
|
+
}();
|
|
2276
|
+
static constexpr pow5_holder_t pow5_table JKJ_STATIC_DATA_SECTION = [] {
|
|
2277
|
+
pow5_holder_t res{};
|
|
2278
|
+
detail::stdr::uint_least16_t p = 1;
|
|
2279
|
+
for (detail::stdr::size_t i = 0; i < pow5_table_size; ++i) {
|
|
2280
|
+
res[i] = p;
|
|
2281
|
+
p *= 5;
|
|
2282
|
+
}
|
|
2283
|
+
return res;
|
|
2284
|
+
}();
|
|
2285
|
+
#else
|
|
2286
|
+
template <detail::stdr::size_t... indices>
|
|
2287
|
+
static constexpr cache_holder_t make_cache(detail::index_sequence<indices...>) {
|
|
2288
|
+
return {cache_holder<ieee754_binary32>::cache[indices * compression_ratio]...};
|
|
2289
|
+
}
|
|
2290
|
+
static constexpr cache_holder_t cache JKJ_STATIC_DATA_SECTION =
|
|
2291
|
+
make_cache(detail::make_index_sequence<compressed_table_size>{});
|
|
2292
|
+
|
|
2293
|
+
template <detail::stdr::size_t... indices>
|
|
2294
|
+
static constexpr pow5_holder_t make_pow5_table(detail::index_sequence<indices...>) {
|
|
2295
|
+
return {detail::compute_power<indices>(detail::stdr::uint_least16_t(5))...};
|
|
2296
|
+
}
|
|
2297
|
+
static constexpr pow5_holder_t pow5_table JKJ_STATIC_DATA_SECTION =
|
|
2298
|
+
make_pow5_table(detail::make_index_sequence<pow5_table_size>{});
|
|
2299
|
+
#endif
|
|
2300
|
+
|
|
2301
|
+
template <class ShiftAmountType, class DecimalExponentType>
|
|
2302
|
+
static JKJ_CONSTEXPR20 cache_entry_type get_cache(DecimalExponentType k) noexcept {
|
|
2303
|
+
// Compute the base index.
|
|
2304
|
+
// Supposed to compute (k - min_k) / compression_ratio.
|
|
2305
|
+
// Parentheses around min/max are to prevent macro expansions (e.g. in Windows.h).
|
|
2306
|
+
static_assert(max_k - min_k <= 89 && compression_ratio == 13, "");
|
|
2307
|
+
static_assert(
|
|
2308
|
+
max_k - min_k <= (detail::stdr::numeric_limits<DecimalExponentType>::max)(), "");
|
|
2309
|
+
using unsigned_exponent_type =
|
|
2310
|
+
typename detail::stdr::make_unsigned<DecimalExponentType>::type;
|
|
2311
|
+
auto const cache_index =
|
|
2312
|
+
DecimalExponentType(detail::stdr::uint_fast16_t(unsigned_exponent_type(k - min_k) *
|
|
2313
|
+
detail::stdr::uint_fast16_t(79)) >>
|
|
2314
|
+
10);
|
|
2315
|
+
auto const kb = DecimalExponentType(cache_index * compression_ratio + min_k);
|
|
2316
|
+
auto const offset = DecimalExponentType(k - kb);
|
|
2317
|
+
|
|
2318
|
+
// Get the base cache.
|
|
2319
|
+
auto const base_cache = detail::read_static_data(cache.data() + cache_index);
|
|
2320
|
+
|
|
2321
|
+
if (offset == 0) {
|
|
2322
|
+
return base_cache;
|
|
2323
|
+
}
|
|
2324
|
+
else {
|
|
2325
|
+
// Compute the required amount of bit-shift.
|
|
2326
|
+
auto const alpha = ShiftAmountType(detail::log::floor_log2_pow5<min_k, max_k>(k) -
|
|
2327
|
+
detail::log::floor_log2_pow5<min_k, max_k>(kb));
|
|
2328
|
+
assert(alpha > 0 && alpha < 32);
|
|
2329
|
+
|
|
2330
|
+
// Try to recover the real cache.
|
|
2331
|
+
constexpr auto pow5_6 = detail::stdr::uint_fast32_t(pow5_table[6]);
|
|
2332
|
+
auto const pow5 =
|
|
2333
|
+
offset >= 7
|
|
2334
|
+
? detail::stdr::uint_fast32_t(
|
|
2335
|
+
pow5_6 * detail::read_static_data(pow5_table.data() + offset - 6))
|
|
2336
|
+
: detail::stdr::uint_fast32_t(
|
|
2337
|
+
detail::read_static_data(pow5_table.data() + offset));
|
|
2338
|
+
auto mul_result = detail::wuint::umul96(pow5, base_cache);
|
|
2339
|
+
|
|
2340
|
+
auto const recovered_cache =
|
|
2341
|
+
#if JKJ_FAST_MUL64
|
|
2342
|
+
cache_entry_type((((detail::stdr::uint_least64_t(mul_result.high32())
|
|
2343
|
+
<< ShiftAmountType(64 - alpha)) |
|
|
2344
|
+
(mul_result.low64() >> alpha)) +
|
|
2345
|
+
1) &
|
|
2346
|
+
UINT64_C(0xffffffffffffffff));
|
|
2347
|
+
#else
|
|
2348
|
+
cache_entry_type((((mul_result.high64() << ShiftAmountType(32 - alpha)) |
|
|
2349
|
+
(mul_result.low32() >> alpha)) +
|
|
2350
|
+
1) &
|
|
2351
|
+
UINT64_C(0xffffffffffffffff));
|
|
2352
|
+
#endif
|
|
2353
|
+
assert(recovered_cache != 0);
|
|
2354
|
+
|
|
2355
|
+
return recovered_cache;
|
|
2356
|
+
}
|
|
2357
|
+
}
|
|
2358
|
+
};
|
|
2359
|
+
#if !JKJ_HAS_INLINE_VARIABLE
|
|
2360
|
+
template <class Dummy>
|
|
2361
|
+
constexpr typename compressed_cache_holder<ieee754_binary32, Dummy>::cache_holder_t
|
|
2362
|
+
compressed_cache_holder<ieee754_binary32, Dummy>::cache;
|
|
2363
|
+
template <class Dummy>
|
|
2364
|
+
constexpr typename compressed_cache_holder<ieee754_binary32, Dummy>::pow5_holder_t
|
|
2365
|
+
compressed_cache_holder<ieee754_binary32, Dummy>::pow5_table;
|
|
2366
|
+
#endif
|
|
2367
|
+
|
|
2368
|
+
template <class Dummy>
|
|
2369
|
+
struct compressed_cache_holder<ieee754_binary64, Dummy> {
|
|
2370
|
+
using cache_entry_type = cache_holder<ieee754_binary64>::cache_entry_type;
|
|
2371
|
+
static constexpr int cache_bits = cache_holder<ieee754_binary64>::cache_bits;
|
|
2372
|
+
static constexpr int min_k = cache_holder<ieee754_binary64>::min_k;
|
|
2373
|
+
static constexpr int max_k = cache_holder<ieee754_binary64>::max_k;
|
|
2374
|
+
static constexpr int compression_ratio = 27;
|
|
2375
|
+
static constexpr detail::stdr::size_t compressed_table_size =
|
|
2376
|
+
detail::stdr::size_t((max_k - min_k + compression_ratio) / compression_ratio);
|
|
2377
|
+
static constexpr detail::stdr::size_t pow5_table_size =
|
|
2378
|
+
detail::stdr::size_t(compression_ratio);
|
|
2379
|
+
|
|
2380
|
+
using cache_holder_t = detail::array<cache_entry_type, compressed_table_size>;
|
|
2381
|
+
using pow5_holder_t = detail::array<detail::stdr::uint_least64_t, pow5_table_size>;
|
|
2382
|
+
|
|
2383
|
+
#if JKJ_HAS_CONSTEXPR17
|
|
2384
|
+
static constexpr cache_holder_t cache JKJ_STATIC_DATA_SECTION = [] {
|
|
2385
|
+
cache_holder_t res{};
|
|
2386
|
+
for (detail::stdr::size_t i = 0; i < compressed_table_size; ++i) {
|
|
2387
|
+
res[i] = cache_holder<ieee754_binary64>::cache[i * compression_ratio];
|
|
2388
|
+
}
|
|
2389
|
+
return res;
|
|
2390
|
+
}();
|
|
2391
|
+
static constexpr pow5_holder_t pow5_table JKJ_STATIC_DATA_SECTION = [] {
|
|
2392
|
+
pow5_holder_t res{};
|
|
2393
|
+
detail::stdr::uint_least64_t p = 1;
|
|
2394
|
+
for (detail::stdr::size_t i = 0; i < pow5_table_size; ++i) {
|
|
2395
|
+
res[i] = p;
|
|
2396
|
+
p *= 5;
|
|
2397
|
+
}
|
|
2398
|
+
return res;
|
|
2399
|
+
}();
|
|
2400
|
+
#else
|
|
2401
|
+
template <detail::stdr::size_t... indices>
|
|
2402
|
+
static constexpr cache_holder_t make_cache(detail::index_sequence<indices...>) {
|
|
2403
|
+
return {cache_holder<ieee754_binary64>::cache[indices * compression_ratio]...};
|
|
2404
|
+
}
|
|
2405
|
+
static constexpr cache_holder_t cache JKJ_STATIC_DATA_SECTION =
|
|
2406
|
+
make_cache(detail::make_index_sequence<compressed_table_size>{});
|
|
2407
|
+
|
|
2408
|
+
template <detail::stdr::size_t... indices>
|
|
2409
|
+
static constexpr pow5_holder_t make_pow5_table(detail::index_sequence<indices...>) {
|
|
2410
|
+
return {detail::compute_power<indices>(detail::stdr::uint_least64_t(5))...};
|
|
2411
|
+
}
|
|
2412
|
+
static constexpr pow5_holder_t pow5_table JKJ_STATIC_DATA_SECTION =
|
|
2413
|
+
make_pow5_table(detail::make_index_sequence<pow5_table_size>{});
|
|
2414
|
+
#endif
|
|
2415
|
+
|
|
2416
|
+
template <class ShiftAmountType, class DecimalExponentType>
|
|
2417
|
+
static JKJ_CONSTEXPR20 cache_entry_type get_cache(DecimalExponentType k) noexcept {
|
|
2418
|
+
// Compute the base index.
|
|
2419
|
+
// Supposed to compute (k - min_k) / compression_ratio.
|
|
2420
|
+
// Parentheses around min/max are to prevent macro expansions (e.g. in Windows.h).
|
|
2421
|
+
static_assert(max_k - min_k <= 619 && compression_ratio == 27, "");
|
|
2422
|
+
static_assert(
|
|
2423
|
+
max_k - min_k <= (detail::stdr::numeric_limits<DecimalExponentType>::max)(), "");
|
|
2424
|
+
using unsigned_exponent_type =
|
|
2425
|
+
typename detail::stdr::make_unsigned<DecimalExponentType>::type;
|
|
2426
|
+
auto const cache_index =
|
|
2427
|
+
DecimalExponentType(detail::stdr::uint_fast32_t(unsigned_exponent_type(k - min_k) *
|
|
2428
|
+
detail::stdr::uint_fast32_t(607)) >>
|
|
2429
|
+
14);
|
|
2430
|
+
auto const kb = DecimalExponentType(cache_index * compression_ratio + min_k);
|
|
2431
|
+
auto const offset = DecimalExponentType(k - kb);
|
|
2432
|
+
|
|
2433
|
+
// Get the base cache.
|
|
2434
|
+
auto const base_cache = detail::read_static_data(cache.data() + cache_index);
|
|
2435
|
+
|
|
2436
|
+
if (offset == 0) {
|
|
2437
|
+
return base_cache;
|
|
2438
|
+
}
|
|
2439
|
+
else {
|
|
2440
|
+
// Compute the required amount of bit-shift.
|
|
2441
|
+
auto const alpha = ShiftAmountType(detail::log::floor_log2_pow5<min_k, max_k>(k) -
|
|
2442
|
+
detail::log::floor_log2_pow5<min_k, max_k>(kb));
|
|
2443
|
+
assert(alpha > 0 && alpha < 64);
|
|
2444
|
+
|
|
2445
|
+
// Try to recover the real cache.
|
|
2446
|
+
auto const pow5 = detail::read_static_data(pow5_table.data() + offset);
|
|
2447
|
+
auto recovered_cache = detail::wuint::umul128(base_cache.high(), pow5);
|
|
2448
|
+
auto const middle_low = detail::wuint::umul128(base_cache.low(), pow5);
|
|
2449
|
+
|
|
2450
|
+
recovered_cache += middle_low.high();
|
|
2451
|
+
|
|
2452
|
+
auto const high_to_middle = detail::stdr::uint_least64_t(
|
|
2453
|
+
(recovered_cache.high() << ShiftAmountType(64 - alpha)) &
|
|
2454
|
+
UINT64_C(0xffffffffffffffff));
|
|
2455
|
+
auto const middle_to_low = detail::stdr::uint_least64_t(
|
|
2456
|
+
(recovered_cache.low() << ShiftAmountType(64 - alpha)) &
|
|
2457
|
+
UINT64_C(0xffffffffffffffff));
|
|
2458
|
+
|
|
2459
|
+
recovered_cache = {(recovered_cache.low() >> alpha) | high_to_middle,
|
|
2460
|
+
((middle_low.low() >> alpha) | middle_to_low)};
|
|
2461
|
+
|
|
2462
|
+
assert(recovered_cache.low() != UINT64_C(0xffffffffffffffff));
|
|
2463
|
+
recovered_cache = {recovered_cache.high(),
|
|
2464
|
+
detail::stdr::uint_least64_t(recovered_cache.low() + 1)};
|
|
2465
|
+
|
|
2466
|
+
return recovered_cache;
|
|
2467
|
+
}
|
|
2468
|
+
}
|
|
2469
|
+
};
|
|
2470
|
+
#if !JKJ_HAS_INLINE_VARIABLE
|
|
2471
|
+
template <class Dummy>
|
|
2472
|
+
constexpr typename compressed_cache_holder<ieee754_binary64, Dummy>::cache_holder_t
|
|
2473
|
+
compressed_cache_holder<ieee754_binary64, Dummy>::cache;
|
|
2474
|
+
template <class Dummy>
|
|
2475
|
+
constexpr typename compressed_cache_holder<ieee754_binary64, Dummy>::pow5_holder_t
|
|
2476
|
+
compressed_cache_holder<ieee754_binary64, Dummy>::pow5_table;
|
|
2477
|
+
#endif
|
|
2478
|
+
|
|
2479
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
2480
|
+
// Forward declarations of user-specializable templates used in the main algorithm.
|
|
2481
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
2482
|
+
|
|
2483
|
+
// Remove trailing zeros from significand and add the number of removed zeros into
|
|
2484
|
+
// exponent.
|
|
2485
|
+
template <class TrailingZeroPolicy, class Format, class DecimalSignificand,
|
|
2486
|
+
class DecimalExponentType>
|
|
2487
|
+
struct remove_trailing_zeros_traits;
|
|
2488
|
+
|
|
2489
|
+
// Users can specialize this traits class to make Dragonbox work with their own formats.
|
|
2490
|
+
// However, this requires detailed knowledge on how the algorithm works, so it is recommended to
|
|
2491
|
+
// read through the paper.
|
|
2492
|
+
template <class FormatTraits, class CacheEntryType, detail::stdr::size_t cache_bits_>
|
|
2493
|
+
struct multiplication_traits;
|
|
2494
|
+
|
|
2495
|
+
// A collection of some common definitions to reduce boilerplate.
|
|
2496
|
+
template <class FormatTraits, class CacheEntryType, detail::stdr::size_t cache_bits_>
|
|
2497
|
+
struct multiplication_traits_base {
|
|
2498
|
+
using format = typename FormatTraits::format;
|
|
2499
|
+
static constexpr int significand_bits = format::significand_bits;
|
|
2500
|
+
static constexpr int total_bits = format::total_bits;
|
|
2501
|
+
using carrier_uint = typename FormatTraits::carrier_uint;
|
|
2502
|
+
using cache_entry_type = CacheEntryType;
|
|
2503
|
+
static constexpr int cache_bits = int(cache_bits_);
|
|
2504
|
+
|
|
2505
|
+
struct compute_mul_result {
|
|
2506
|
+
carrier_uint integer_part;
|
|
2507
|
+
bool is_integer;
|
|
2508
|
+
};
|
|
2509
|
+
struct compute_mul_parity_result {
|
|
2510
|
+
bool parity;
|
|
2511
|
+
bool is_integer;
|
|
2512
|
+
};
|
|
2513
|
+
};
|
|
2514
|
+
|
|
2515
|
+
|
|
2516
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
2517
|
+
// Policies.
|
|
2518
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
2519
|
+
|
|
2520
|
+
namespace detail {
|
|
2521
|
+
template <class T>
|
|
2522
|
+
struct dummy {};
|
|
2523
|
+
}
|
|
2524
|
+
|
|
2525
|
+
namespace policy {
|
|
2526
|
+
namespace sign {
|
|
2527
|
+
JKJ_INLINE_VARIABLE struct ignore_t {
|
|
2528
|
+
using sign_policy = ignore_t;
|
|
2529
|
+
static constexpr bool return_has_sign = false;
|
|
2530
|
+
|
|
2531
|
+
#if defined(_MSC_VER) && !defined(__clang__)
|
|
2532
|
+
// See
|
|
2533
|
+
// https://developercommunity.visualstudio.com/t/Failure-to-optimize-intrinsics/10628226
|
|
2534
|
+
template <class SignedSignificandBits, class DecimalSignificand,
|
|
2535
|
+
class DecimalExponentType>
|
|
2536
|
+
static constexpr decimal_fp<DecimalSignificand, DecimalExponentType, false, false>
|
|
2537
|
+
handle_sign(
|
|
2538
|
+
SignedSignificandBits,
|
|
2539
|
+
decimal_fp<DecimalSignificand, DecimalExponentType, false, false> r) noexcept {
|
|
2540
|
+
return {r.significand, r.exponent};
|
|
2541
|
+
}
|
|
2542
|
+
template <class SignedSignificandBits, class DecimalSignificand,
|
|
2543
|
+
class DecimalExponentType>
|
|
2544
|
+
static constexpr decimal_fp<DecimalSignificand, DecimalExponentType, false, true>
|
|
2545
|
+
handle_sign(
|
|
2546
|
+
SignedSignificandBits,
|
|
2547
|
+
decimal_fp<DecimalSignificand, DecimalExponentType, false, true> r) noexcept {
|
|
2548
|
+
return {r.significand, r.exponent, r.may_have_trailing_zeros};
|
|
2549
|
+
}
|
|
2550
|
+
#else
|
|
2551
|
+
template <class SignedSignificandBits, class UnsignedDecimalFp>
|
|
2552
|
+
static constexpr UnsignedDecimalFp handle_sign(SignedSignificandBits,
|
|
2553
|
+
UnsignedDecimalFp r) noexcept {
|
|
2554
|
+
return r;
|
|
2555
|
+
}
|
|
2556
|
+
#endif
|
|
2557
|
+
} ignore = {};
|
|
2558
|
+
|
|
2559
|
+
JKJ_INLINE_VARIABLE struct return_sign_t {
|
|
2560
|
+
using sign_policy = return_sign_t;
|
|
2561
|
+
static constexpr bool return_has_sign = true;
|
|
2562
|
+
|
|
2563
|
+
template <class SignedSignificandBits, class UnsignedDecimalFp>
|
|
2564
|
+
static constexpr detail::unsigned_decimal_fp_to_signed_t<UnsignedDecimalFp>
|
|
2565
|
+
handle_sign(SignedSignificandBits s, UnsignedDecimalFp r) noexcept {
|
|
2566
|
+
return add_sign_to_unsigned_decimal_fp(s.is_negative(), r);
|
|
2567
|
+
}
|
|
2568
|
+
} return_sign = {};
|
|
2569
|
+
}
|
|
2570
|
+
|
|
2571
|
+
namespace trailing_zero {
|
|
2572
|
+
JKJ_INLINE_VARIABLE struct ignore_t {
|
|
2573
|
+
using trailing_zero_policy = ignore_t;
|
|
2574
|
+
static constexpr bool report_trailing_zeros = false;
|
|
2575
|
+
|
|
2576
|
+
template <class Format, class DecimalSignificand, class DecimalExponentType>
|
|
2577
|
+
static constexpr unsigned_decimal_fp<DecimalSignificand, DecimalExponentType, false>
|
|
2578
|
+
on_trailing_zeros(DecimalSignificand significand,
|
|
2579
|
+
DecimalExponentType exponent) noexcept {
|
|
2580
|
+
return {significand, exponent};
|
|
2581
|
+
}
|
|
2582
|
+
|
|
2583
|
+
template <class Format, class DecimalSignificand, class DecimalExponentType>
|
|
2584
|
+
static constexpr unsigned_decimal_fp<DecimalSignificand, DecimalExponentType, false>
|
|
2585
|
+
no_trailing_zeros(DecimalSignificand significand,
|
|
2586
|
+
DecimalExponentType exponent) noexcept {
|
|
2587
|
+
return {significand, exponent};
|
|
2588
|
+
}
|
|
2589
|
+
} ignore = {};
|
|
2590
|
+
|
|
2591
|
+
JKJ_INLINE_VARIABLE struct remove_t {
|
|
2592
|
+
using trailing_zero_policy = remove_t;
|
|
2593
|
+
static constexpr bool report_trailing_zeros = false;
|
|
2594
|
+
|
|
2595
|
+
template <class Format, class DecimalSignificand, class DecimalExponentType>
|
|
2596
|
+
JKJ_FORCEINLINE static JKJ_CONSTEXPR14
|
|
2597
|
+
unsigned_decimal_fp<DecimalSignificand, DecimalExponentType, false>
|
|
2598
|
+
on_trailing_zeros(DecimalSignificand significand,
|
|
2599
|
+
DecimalExponentType exponent) noexcept {
|
|
2600
|
+
remove_trailing_zeros_traits<
|
|
2601
|
+
remove_t, Format, DecimalSignificand,
|
|
2602
|
+
DecimalExponentType>::remove_trailing_zeros(significand, exponent);
|
|
2603
|
+
return {significand, exponent};
|
|
2604
|
+
}
|
|
2605
|
+
|
|
2606
|
+
template <class Format, class DecimalSignificand, class DecimalExponentType>
|
|
2607
|
+
static constexpr unsigned_decimal_fp<DecimalSignificand, DecimalExponentType, false>
|
|
2608
|
+
no_trailing_zeros(DecimalSignificand significand,
|
|
2609
|
+
DecimalExponentType exponent) noexcept {
|
|
2610
|
+
return {significand, exponent};
|
|
2611
|
+
}
|
|
2612
|
+
} remove = {};
|
|
2613
|
+
|
|
2614
|
+
JKJ_INLINE_VARIABLE struct remove_compact_t {
|
|
2615
|
+
using trailing_zero_policy = remove_compact_t;
|
|
2616
|
+
static constexpr bool report_trailing_zeros = false;
|
|
2617
|
+
|
|
2618
|
+
template <class Format, class DecimalSignificand, class DecimalExponentType>
|
|
2619
|
+
JKJ_FORCEINLINE static JKJ_CONSTEXPR14
|
|
2620
|
+
unsigned_decimal_fp<DecimalSignificand, DecimalExponentType, false>
|
|
2621
|
+
on_trailing_zeros(DecimalSignificand significand,
|
|
2622
|
+
DecimalExponentType exponent) noexcept {
|
|
2623
|
+
remove_trailing_zeros_traits<
|
|
2624
|
+
remove_compact_t, Format, DecimalSignificand,
|
|
2625
|
+
DecimalExponentType>::remove_trailing_zeros(significand, exponent);
|
|
2626
|
+
return {significand, exponent};
|
|
2627
|
+
}
|
|
2628
|
+
|
|
2629
|
+
template <class Format, class DecimalSignificand, class DecimalExponentType>
|
|
2630
|
+
static constexpr unsigned_decimal_fp<DecimalSignificand, DecimalExponentType, false>
|
|
2631
|
+
no_trailing_zeros(DecimalSignificand significand,
|
|
2632
|
+
DecimalExponentType exponent) noexcept {
|
|
2633
|
+
return {significand, exponent};
|
|
2634
|
+
}
|
|
2635
|
+
} remove_compact = {};
|
|
2636
|
+
|
|
2637
|
+
JKJ_INLINE_VARIABLE struct report_t {
|
|
2638
|
+
using trailing_zero_policy = report_t;
|
|
2639
|
+
static constexpr bool report_trailing_zeros = true;
|
|
2640
|
+
|
|
2641
|
+
template <class Format, class DecimalSignificand, class DecimalExponentType>
|
|
2642
|
+
static constexpr unsigned_decimal_fp<DecimalSignificand, DecimalExponentType, true>
|
|
2643
|
+
on_trailing_zeros(DecimalSignificand significand,
|
|
2644
|
+
DecimalExponentType exponent) noexcept {
|
|
2645
|
+
return {significand, exponent, true};
|
|
2646
|
+
}
|
|
2647
|
+
|
|
2648
|
+
template <class Format, class DecimalSignificand, class DecimalExponentType>
|
|
2649
|
+
static constexpr unsigned_decimal_fp<DecimalSignificand, DecimalExponentType, true>
|
|
2650
|
+
no_trailing_zeros(DecimalSignificand significand,
|
|
2651
|
+
DecimalExponentType exponent) noexcept {
|
|
2652
|
+
return {significand, exponent, false};
|
|
2653
|
+
}
|
|
2654
|
+
} report = {};
|
|
2655
|
+
}
|
|
2656
|
+
|
|
2657
|
+
namespace decimal_to_binary_rounding {
|
|
2658
|
+
enum class tag_t { to_nearest, left_closed_directed, right_closed_directed };
|
|
2659
|
+
|
|
2660
|
+
namespace interval_type {
|
|
2661
|
+
struct symmetric_boundary {
|
|
2662
|
+
static constexpr bool is_symmetric = true;
|
|
2663
|
+
bool is_closed;
|
|
2664
|
+
constexpr bool include_left_endpoint() const noexcept { return is_closed; }
|
|
2665
|
+
constexpr bool include_right_endpoint() const noexcept { return is_closed; }
|
|
2666
|
+
};
|
|
2667
|
+
struct asymmetric_boundary {
|
|
2668
|
+
static constexpr bool is_symmetric = false;
|
|
2669
|
+
bool is_left_closed;
|
|
2670
|
+
constexpr bool include_left_endpoint() const noexcept { return is_left_closed; }
|
|
2671
|
+
constexpr bool include_right_endpoint() const noexcept {
|
|
2672
|
+
return !is_left_closed;
|
|
2673
|
+
}
|
|
2674
|
+
};
|
|
2675
|
+
struct closed {
|
|
2676
|
+
static constexpr bool is_symmetric = true;
|
|
2677
|
+
static constexpr bool include_left_endpoint() noexcept { return true; }
|
|
2678
|
+
static constexpr bool include_right_endpoint() noexcept { return true; }
|
|
2679
|
+
};
|
|
2680
|
+
struct open {
|
|
2681
|
+
static constexpr bool is_symmetric = true;
|
|
2682
|
+
static constexpr bool include_left_endpoint() noexcept { return false; }
|
|
2683
|
+
static constexpr bool include_right_endpoint() noexcept { return false; }
|
|
2684
|
+
};
|
|
2685
|
+
struct left_closed_right_open {
|
|
2686
|
+
static constexpr bool is_symmetric = false;
|
|
2687
|
+
static constexpr bool include_left_endpoint() noexcept { return true; }
|
|
2688
|
+
static constexpr bool include_right_endpoint() noexcept { return false; }
|
|
2689
|
+
};
|
|
2690
|
+
struct right_closed_left_open {
|
|
2691
|
+
static constexpr bool is_symmetric = false;
|
|
2692
|
+
static constexpr bool include_left_endpoint() noexcept { return false; }
|
|
2693
|
+
static constexpr bool include_right_endpoint() noexcept { return true; }
|
|
2694
|
+
};
|
|
2695
|
+
}
|
|
2696
|
+
|
|
2697
|
+
JKJ_INLINE_VARIABLE struct nearest_to_even_t {
|
|
2698
|
+
using decimal_to_binary_rounding_policy = nearest_to_even_t;
|
|
2699
|
+
using interval_type_provider = nearest_to_even_t;
|
|
2700
|
+
static constexpr auto tag = tag_t::to_nearest;
|
|
2701
|
+
|
|
2702
|
+
template <class SignedSignificandBits, class Func, class... Args>
|
|
2703
|
+
JKJ_FORCEINLINE JKJ_SAFEBUFFERS static constexpr decltype(Func{}(
|
|
2704
|
+
dragonbox::detail::declval<nearest_to_even_t>(), Args{}...))
|
|
2705
|
+
delegate(SignedSignificandBits, Func f, Args... args) noexcept {
|
|
2706
|
+
return f(nearest_to_even_t{}, args...);
|
|
2707
|
+
}
|
|
2708
|
+
|
|
2709
|
+
template <class SignedSignificandBits>
|
|
2710
|
+
static constexpr interval_type::symmetric_boundary
|
|
2711
|
+
normal_interval(SignedSignificandBits s) noexcept {
|
|
2712
|
+
return {s.has_even_significand_bits()};
|
|
2713
|
+
}
|
|
2714
|
+
|
|
2715
|
+
template <class SignedSignificandBits>
|
|
2716
|
+
static constexpr interval_type::closed
|
|
2717
|
+
shorter_interval(SignedSignificandBits) noexcept {
|
|
2718
|
+
return {};
|
|
2719
|
+
}
|
|
2720
|
+
} nearest_to_even = {};
|
|
2721
|
+
|
|
2722
|
+
JKJ_INLINE_VARIABLE struct nearest_to_odd_t {
|
|
2723
|
+
using decimal_to_binary_rounding_policy = nearest_to_odd_t;
|
|
2724
|
+
using interval_type_provider = nearest_to_odd_t;
|
|
2725
|
+
static constexpr auto tag = tag_t::to_nearest;
|
|
2726
|
+
|
|
2727
|
+
template <class SignedSignificandBits, class Func, class... Args>
|
|
2728
|
+
JKJ_FORCEINLINE JKJ_SAFEBUFFERS static constexpr decltype(Func{}(
|
|
2729
|
+
dragonbox::detail::declval<nearest_to_odd_t>(), Args{}...))
|
|
2730
|
+
delegate(SignedSignificandBits, Func f, Args... args) noexcept {
|
|
2731
|
+
return f(nearest_to_odd_t{}, args...);
|
|
2732
|
+
}
|
|
2733
|
+
|
|
2734
|
+
template <class SignedSignificandBits>
|
|
2735
|
+
static constexpr interval_type::symmetric_boundary
|
|
2736
|
+
normal_interval(SignedSignificandBits s) noexcept {
|
|
2737
|
+
return {!s.has_even_significand_bits()};
|
|
2738
|
+
}
|
|
2739
|
+
template <class SignedSignificandBits>
|
|
2740
|
+
static constexpr interval_type::open
|
|
2741
|
+
shorter_interval(SignedSignificandBits) noexcept {
|
|
2742
|
+
return {};
|
|
2743
|
+
}
|
|
2744
|
+
} nearest_to_odd = {};
|
|
2745
|
+
|
|
2746
|
+
JKJ_INLINE_VARIABLE struct nearest_toward_plus_infinity_t {
|
|
2747
|
+
using decimal_to_binary_rounding_policy = nearest_toward_plus_infinity_t;
|
|
2748
|
+
using interval_type_provider = nearest_toward_plus_infinity_t;
|
|
2749
|
+
static constexpr auto tag = tag_t::to_nearest;
|
|
2750
|
+
|
|
2751
|
+
template <class SignedSignificandBits, class Func, class... Args>
|
|
2752
|
+
JKJ_FORCEINLINE JKJ_SAFEBUFFERS static constexpr decltype(Func{}(
|
|
2753
|
+
dragonbox::detail::declval<nearest_toward_plus_infinity_t>(), Args{}...))
|
|
2754
|
+
delegate(SignedSignificandBits, Func f, Args... args) noexcept {
|
|
2755
|
+
return f(nearest_toward_plus_infinity_t{}, args...);
|
|
2756
|
+
}
|
|
2757
|
+
|
|
2758
|
+
template <class SignedSignificandBits>
|
|
2759
|
+
static constexpr interval_type::asymmetric_boundary
|
|
2760
|
+
normal_interval(SignedSignificandBits s) noexcept {
|
|
2761
|
+
return {!s.is_negative()};
|
|
2762
|
+
}
|
|
2763
|
+
template <class SignedSignificandBits>
|
|
2764
|
+
static constexpr interval_type::asymmetric_boundary
|
|
2765
|
+
shorter_interval(SignedSignificandBits s) noexcept {
|
|
2766
|
+
return {!s.is_negative()};
|
|
2767
|
+
}
|
|
2768
|
+
} nearest_toward_plus_infinity = {};
|
|
2769
|
+
|
|
2770
|
+
JKJ_INLINE_VARIABLE struct nearest_toward_minus_infinity_t {
|
|
2771
|
+
using decimal_to_binary_rounding_policy = nearest_toward_minus_infinity_t;
|
|
2772
|
+
using interval_type_provider = nearest_toward_minus_infinity_t;
|
|
2773
|
+
static constexpr auto tag = tag_t::to_nearest;
|
|
2774
|
+
|
|
2775
|
+
template <class SignedSignificandBits, class Func, class... Args>
|
|
2776
|
+
JKJ_FORCEINLINE JKJ_SAFEBUFFERS static constexpr decltype(Func{}(
|
|
2777
|
+
dragonbox::detail::declval<nearest_toward_minus_infinity_t>(), Args{}...))
|
|
2778
|
+
delegate(SignedSignificandBits, Func f, Args... args) noexcept {
|
|
2779
|
+
return f(nearest_toward_minus_infinity_t{}, args...);
|
|
2780
|
+
}
|
|
2781
|
+
|
|
2782
|
+
template <class SignedSignificandBits>
|
|
2783
|
+
static constexpr interval_type::asymmetric_boundary
|
|
2784
|
+
normal_interval(SignedSignificandBits s) noexcept {
|
|
2785
|
+
return {s.is_negative()};
|
|
2786
|
+
}
|
|
2787
|
+
template <class SignedSignificandBits>
|
|
2788
|
+
static constexpr interval_type::asymmetric_boundary
|
|
2789
|
+
shorter_interval(SignedSignificandBits s) noexcept {
|
|
2790
|
+
return {s.is_negative()};
|
|
2791
|
+
}
|
|
2792
|
+
} nearest_toward_minus_infinity = {};
|
|
2793
|
+
|
|
2794
|
+
JKJ_INLINE_VARIABLE struct nearest_toward_zero_t {
|
|
2795
|
+
using decimal_to_binary_rounding_policy = nearest_toward_zero_t;
|
|
2796
|
+
using interval_type_provider = nearest_toward_zero_t;
|
|
2797
|
+
static constexpr auto tag = tag_t::to_nearest;
|
|
2798
|
+
|
|
2799
|
+
template <class SignedSignificandBits, class Func, class... Args>
|
|
2800
|
+
JKJ_FORCEINLINE JKJ_SAFEBUFFERS static constexpr decltype(Func{}(
|
|
2801
|
+
dragonbox::detail::declval<nearest_toward_zero_t>(), Args{}...))
|
|
2802
|
+
delegate(SignedSignificandBits, Func f, Args... args) noexcept {
|
|
2803
|
+
return f(nearest_toward_zero_t{}, args...);
|
|
2804
|
+
}
|
|
2805
|
+
|
|
2806
|
+
template <class SignedSignificandBits>
|
|
2807
|
+
static constexpr interval_type::right_closed_left_open
|
|
2808
|
+
normal_interval(SignedSignificandBits) noexcept {
|
|
2809
|
+
return {};
|
|
2810
|
+
}
|
|
2811
|
+
template <class SignedSignificandBits>
|
|
2812
|
+
static constexpr interval_type::right_closed_left_open
|
|
2813
|
+
shorter_interval(SignedSignificandBits) noexcept {
|
|
2814
|
+
return {};
|
|
2815
|
+
}
|
|
2816
|
+
} nearest_toward_zero = {};
|
|
2817
|
+
|
|
2818
|
+
JKJ_INLINE_VARIABLE struct nearest_away_from_zero_t {
|
|
2819
|
+
using decimal_to_binary_rounding_policy = nearest_away_from_zero_t;
|
|
2820
|
+
using interval_type_provider = nearest_away_from_zero_t;
|
|
2821
|
+
static constexpr auto tag = tag_t::to_nearest;
|
|
2822
|
+
|
|
2823
|
+
template <class SignedSignificandBits, class Func, class... Args>
|
|
2824
|
+
JKJ_FORCEINLINE JKJ_SAFEBUFFERS static constexpr decltype(Func{}(
|
|
2825
|
+
dragonbox::detail::declval<nearest_away_from_zero_t>(), Args{}...))
|
|
2826
|
+
delegate(SignedSignificandBits, Func f, Args... args) noexcept {
|
|
2827
|
+
return f(nearest_away_from_zero_t{}, args...);
|
|
2828
|
+
}
|
|
2829
|
+
|
|
2830
|
+
template <class SignedSignificandBits>
|
|
2831
|
+
static constexpr interval_type::left_closed_right_open
|
|
2832
|
+
normal_interval(SignedSignificandBits) noexcept {
|
|
2833
|
+
return {};
|
|
2834
|
+
}
|
|
2835
|
+
template <class SignedSignificandBits>
|
|
2836
|
+
static constexpr interval_type::left_closed_right_open
|
|
2837
|
+
shorter_interval(SignedSignificandBits) noexcept {
|
|
2838
|
+
return {};
|
|
2839
|
+
}
|
|
2840
|
+
} nearest_away_from_zero = {};
|
|
2841
|
+
|
|
2842
|
+
namespace detail {
|
|
2843
|
+
struct nearest_always_closed_t {
|
|
2844
|
+
using interval_type_provider = nearest_always_closed_t;
|
|
2845
|
+
static constexpr auto tag = tag_t::to_nearest;
|
|
2846
|
+
|
|
2847
|
+
template <class SignedSignificandBits>
|
|
2848
|
+
static constexpr interval_type::closed
|
|
2849
|
+
normal_interval(SignedSignificandBits) noexcept {
|
|
2850
|
+
return {};
|
|
2851
|
+
}
|
|
2852
|
+
template <class SignedSignificandBits>
|
|
2853
|
+
static constexpr interval_type::closed
|
|
2854
|
+
shorter_interval(SignedSignificandBits) noexcept {
|
|
2855
|
+
return {};
|
|
2856
|
+
}
|
|
2857
|
+
};
|
|
2858
|
+
struct nearest_always_open_t {
|
|
2859
|
+
using interval_type_provider = nearest_always_open_t;
|
|
2860
|
+
static constexpr auto tag = tag_t::to_nearest;
|
|
2861
|
+
|
|
2862
|
+
template <class SignedSignificandBits>
|
|
2863
|
+
static constexpr interval_type::open
|
|
2864
|
+
normal_interval(SignedSignificandBits) noexcept {
|
|
2865
|
+
return {};
|
|
2866
|
+
}
|
|
2867
|
+
template <class SignedSignificandBits>
|
|
2868
|
+
static constexpr interval_type::open
|
|
2869
|
+
shorter_interval(SignedSignificandBits) noexcept {
|
|
2870
|
+
return {};
|
|
2871
|
+
}
|
|
2872
|
+
};
|
|
2873
|
+
}
|
|
2874
|
+
|
|
2875
|
+
JKJ_INLINE_VARIABLE struct nearest_to_even_static_boundary_t {
|
|
2876
|
+
using decimal_to_binary_rounding_policy = nearest_to_even_static_boundary_t;
|
|
2877
|
+
|
|
2878
|
+
template <class SignedSignificandBits, class Func, class... Args>
|
|
2879
|
+
JKJ_FORCEINLINE JKJ_SAFEBUFFERS static constexpr decltype(Func{}(
|
|
2880
|
+
detail::nearest_always_closed_t{}, Args{}...))
|
|
2881
|
+
delegate(SignedSignificandBits s, Func f, Args... args) noexcept {
|
|
2882
|
+
return s.has_even_significand_bits()
|
|
2883
|
+
? f(detail::nearest_always_closed_t{}, args...)
|
|
2884
|
+
: f(detail::nearest_always_open_t{}, args...);
|
|
2885
|
+
}
|
|
2886
|
+
} nearest_to_even_static_boundary = {};
|
|
2887
|
+
|
|
2888
|
+
JKJ_INLINE_VARIABLE struct nearest_to_odd_static_boundary_t {
|
|
2889
|
+
using decimal_to_binary_rounding_policy = nearest_to_odd_static_boundary_t;
|
|
2890
|
+
|
|
2891
|
+
template <class SignedSignificandBits, class Func, class... Args>
|
|
2892
|
+
JKJ_FORCEINLINE JKJ_SAFEBUFFERS static constexpr decltype(Func{}(
|
|
2893
|
+
detail::nearest_always_closed_t{}, Args{}...))
|
|
2894
|
+
delegate(SignedSignificandBits s, Func f, Args... args) noexcept {
|
|
2895
|
+
return s.has_even_significand_bits()
|
|
2896
|
+
? f(detail::nearest_always_open_t{}, args...)
|
|
2897
|
+
: f(detail::nearest_always_closed_t{}, args...);
|
|
2898
|
+
}
|
|
2899
|
+
} nearest_to_odd_static_boundary = {};
|
|
2900
|
+
|
|
2901
|
+
JKJ_INLINE_VARIABLE struct nearest_toward_plus_infinity_static_boundary_t {
|
|
2902
|
+
using decimal_to_binary_rounding_policy =
|
|
2903
|
+
nearest_toward_plus_infinity_static_boundary_t;
|
|
2904
|
+
|
|
2905
|
+
template <class SignedSignificandBits, class Func, class... Args>
|
|
2906
|
+
JKJ_FORCEINLINE
|
|
2907
|
+
JKJ_SAFEBUFFERS static constexpr decltype(Func{}(nearest_toward_zero,
|
|
2908
|
+
Args{}...))
|
|
2909
|
+
delegate(SignedSignificandBits s, Func f, Args... args) noexcept {
|
|
2910
|
+
return s.is_negative() ? f(nearest_toward_zero, args...)
|
|
2911
|
+
: f(nearest_away_from_zero, args...);
|
|
2912
|
+
}
|
|
2913
|
+
} nearest_toward_plus_infinity_static_boundary = {};
|
|
2914
|
+
|
|
2915
|
+
JKJ_INLINE_VARIABLE struct nearest_toward_minus_infinity_static_boundary_t {
|
|
2916
|
+
using decimal_to_binary_rounding_policy =
|
|
2917
|
+
nearest_toward_minus_infinity_static_boundary_t;
|
|
2918
|
+
|
|
2919
|
+
template <class SignedSignificandBits, class Func, class... Args>
|
|
2920
|
+
JKJ_FORCEINLINE
|
|
2921
|
+
JKJ_SAFEBUFFERS static constexpr decltype(Func{}(nearest_toward_zero,
|
|
2922
|
+
Args{}...))
|
|
2923
|
+
delegate(SignedSignificandBits s, Func f, Args... args) noexcept {
|
|
2924
|
+
return s.is_negative() ? f(nearest_away_from_zero, args...)
|
|
2925
|
+
: f(nearest_toward_zero, args...);
|
|
2926
|
+
}
|
|
2927
|
+
} nearest_toward_minus_infinity_static_boundary = {};
|
|
2928
|
+
|
|
2929
|
+
namespace detail {
|
|
2930
|
+
struct left_closed_directed_t {
|
|
2931
|
+
static constexpr auto tag = tag_t::left_closed_directed;
|
|
2932
|
+
};
|
|
2933
|
+
struct right_closed_directed_t {
|
|
2934
|
+
static constexpr auto tag = tag_t::right_closed_directed;
|
|
2935
|
+
};
|
|
2936
|
+
}
|
|
2937
|
+
|
|
2938
|
+
JKJ_INLINE_VARIABLE struct toward_plus_infinity_t {
|
|
2939
|
+
using decimal_to_binary_rounding_policy = toward_plus_infinity_t;
|
|
2940
|
+
|
|
2941
|
+
template <class SignedSignificandBits, class Func, class... Args>
|
|
2942
|
+
JKJ_FORCEINLINE JKJ_SAFEBUFFERS static constexpr decltype(Func{}(
|
|
2943
|
+
detail::left_closed_directed_t{}, Args{}...))
|
|
2944
|
+
delegate(SignedSignificandBits s, Func f, Args... args) noexcept {
|
|
2945
|
+
return s.is_negative() ? f(detail::left_closed_directed_t{}, args...)
|
|
2946
|
+
: f(detail::right_closed_directed_t{}, args...);
|
|
2947
|
+
}
|
|
2948
|
+
} toward_plus_infinity = {};
|
|
2949
|
+
|
|
2950
|
+
JKJ_INLINE_VARIABLE struct toward_minus_infinity_t {
|
|
2951
|
+
using decimal_to_binary_rounding_policy = toward_minus_infinity_t;
|
|
2952
|
+
|
|
2953
|
+
template <class SignedSignificandBits, class Func, class... Args>
|
|
2954
|
+
JKJ_FORCEINLINE JKJ_SAFEBUFFERS static constexpr decltype(Func{}(
|
|
2955
|
+
detail::left_closed_directed_t{}, Args{}...))
|
|
2956
|
+
delegate(SignedSignificandBits s, Func f, Args... args) noexcept {
|
|
2957
|
+
return s.is_negative() ? f(detail::right_closed_directed_t{}, args...)
|
|
2958
|
+
: f(detail::left_closed_directed_t{}, args...);
|
|
2959
|
+
}
|
|
2960
|
+
} toward_minus_infinity = {};
|
|
2961
|
+
|
|
2962
|
+
JKJ_INLINE_VARIABLE struct toward_zero_t {
|
|
2963
|
+
using decimal_to_binary_rounding_policy = toward_zero_t;
|
|
2964
|
+
|
|
2965
|
+
template <class SignedSignificandBits, class Func, class... Args>
|
|
2966
|
+
JKJ_FORCEINLINE JKJ_SAFEBUFFERS static constexpr decltype(Func{}(
|
|
2967
|
+
detail::left_closed_directed_t{}, Args{}...))
|
|
2968
|
+
delegate(SignedSignificandBits, Func f, Args... args) noexcept {
|
|
2969
|
+
return f(detail::left_closed_directed_t{}, args...);
|
|
2970
|
+
}
|
|
2971
|
+
} toward_zero = {};
|
|
2972
|
+
|
|
2973
|
+
JKJ_INLINE_VARIABLE struct away_from_zero_t {
|
|
2974
|
+
using decimal_to_binary_rounding_policy = away_from_zero_t;
|
|
2975
|
+
|
|
2976
|
+
template <class SignedSignificandBits, class Func, class... Args>
|
|
2977
|
+
JKJ_FORCEINLINE JKJ_SAFEBUFFERS static constexpr decltype(Func{}(
|
|
2978
|
+
detail::right_closed_directed_t{}, Args{}...))
|
|
2979
|
+
delegate(SignedSignificandBits, Func f, Args... args) noexcept {
|
|
2980
|
+
return f(detail::right_closed_directed_t{}, args...);
|
|
2981
|
+
}
|
|
2982
|
+
} away_from_zero = {};
|
|
2983
|
+
}
|
|
2984
|
+
|
|
2985
|
+
namespace binary_to_decimal_rounding {
|
|
2986
|
+
// (Always assumes nearest rounding modes, as there can be no tie for other rounding
|
|
2987
|
+
// modes.)
|
|
2988
|
+
enum class tag_t { do_not_care, to_even, to_odd, away_from_zero, toward_zero };
|
|
2989
|
+
|
|
2990
|
+
// The parameter significand corresponds to 10\tilde{s}+t in the paper.
|
|
2991
|
+
|
|
2992
|
+
JKJ_INLINE_VARIABLE struct do_not_care_t {
|
|
2993
|
+
using binary_to_decimal_rounding_policy = do_not_care_t;
|
|
2994
|
+
static constexpr auto tag = tag_t::do_not_care;
|
|
2995
|
+
|
|
2996
|
+
template <class CarrierUInt>
|
|
2997
|
+
static constexpr bool prefer_round_down(CarrierUInt) noexcept {
|
|
2998
|
+
return false;
|
|
2999
|
+
}
|
|
3000
|
+
} do_not_care = {};
|
|
3001
|
+
|
|
3002
|
+
JKJ_INLINE_VARIABLE struct to_even_t {
|
|
3003
|
+
using binary_to_decimal_rounding_policy = to_even_t;
|
|
3004
|
+
static constexpr auto tag = tag_t::to_even;
|
|
3005
|
+
|
|
3006
|
+
template <class CarrierUInt>
|
|
3007
|
+
static constexpr bool prefer_round_down(CarrierUInt significand) noexcept {
|
|
3008
|
+
return significand % 2 != 0;
|
|
3009
|
+
}
|
|
3010
|
+
} to_even = {};
|
|
3011
|
+
|
|
3012
|
+
JKJ_INLINE_VARIABLE struct to_odd_t {
|
|
3013
|
+
using binary_to_decimal_rounding_policy = to_odd_t;
|
|
3014
|
+
static constexpr auto tag = tag_t::to_odd;
|
|
3015
|
+
|
|
3016
|
+
template <class CarrierUInt>
|
|
3017
|
+
static constexpr bool prefer_round_down(CarrierUInt significand) noexcept {
|
|
3018
|
+
return significand % 2 == 0;
|
|
3019
|
+
}
|
|
3020
|
+
} to_odd = {};
|
|
3021
|
+
|
|
3022
|
+
JKJ_INLINE_VARIABLE struct away_from_zero_t {
|
|
3023
|
+
using binary_to_decimal_rounding_policy = away_from_zero_t;
|
|
3024
|
+
static constexpr auto tag = tag_t::away_from_zero;
|
|
3025
|
+
|
|
3026
|
+
template <class CarrierUInt>
|
|
3027
|
+
static constexpr bool prefer_round_down(CarrierUInt) noexcept {
|
|
3028
|
+
return false;
|
|
3029
|
+
}
|
|
3030
|
+
} away_from_zero = {};
|
|
3031
|
+
|
|
3032
|
+
JKJ_INLINE_VARIABLE struct toward_zero_t {
|
|
3033
|
+
using binary_to_decimal_rounding_policy = toward_zero_t;
|
|
3034
|
+
static constexpr auto tag = tag_t::toward_zero;
|
|
3035
|
+
|
|
3036
|
+
template <class CarrierUInt>
|
|
3037
|
+
static constexpr bool prefer_round_down(CarrierUInt) noexcept {
|
|
3038
|
+
return true;
|
|
3039
|
+
}
|
|
3040
|
+
} toward_zero = {};
|
|
3041
|
+
}
|
|
3042
|
+
|
|
3043
|
+
namespace cache {
|
|
3044
|
+
JKJ_INLINE_VARIABLE struct full_t {
|
|
3045
|
+
using cache_policy = full_t;
|
|
3046
|
+
template <class FloatFormat>
|
|
3047
|
+
using cache_holder_type = cache_holder<FloatFormat>;
|
|
3048
|
+
|
|
3049
|
+
template <class FloatFormat, class ShiftAmountType, class DecimalExponentType>
|
|
3050
|
+
static JKJ_CONSTEXPR20 typename cache_holder_type<FloatFormat>::cache_entry_type
|
|
3051
|
+
get_cache(DecimalExponentType k) noexcept {
|
|
3052
|
+
assert(k >= cache_holder_type<FloatFormat>::min_k &&
|
|
3053
|
+
k <= cache_holder_type<FloatFormat>::max_k);
|
|
3054
|
+
|
|
3055
|
+
return detail::read_static_data(
|
|
3056
|
+
cache_holder_type<FloatFormat>::cache.data() +
|
|
3057
|
+
detail::stdr::size_t(k - cache_holder_type<FloatFormat>::min_k));
|
|
3058
|
+
}
|
|
3059
|
+
} full = {};
|
|
3060
|
+
|
|
3061
|
+
JKJ_INLINE_VARIABLE struct compact_t {
|
|
3062
|
+
using cache_policy = compact_t;
|
|
3063
|
+
template <class FloatFormat>
|
|
3064
|
+
using cache_holder_type = compressed_cache_holder<FloatFormat>;
|
|
3065
|
+
|
|
3066
|
+
template <class FloatFormat, class ShiftAmountType, class DecimalExponentType>
|
|
3067
|
+
static JKJ_CONSTEXPR20 typename cache_holder<FloatFormat>::cache_entry_type
|
|
3068
|
+
get_cache(DecimalExponentType k) noexcept {
|
|
3069
|
+
assert(k >= cache_holder<FloatFormat>::min_k &&
|
|
3070
|
+
k <= cache_holder<FloatFormat>::max_k);
|
|
3071
|
+
|
|
3072
|
+
return cache_holder_type<FloatFormat>::template get_cache<ShiftAmountType>(k);
|
|
3073
|
+
}
|
|
3074
|
+
} compact = {};
|
|
3075
|
+
}
|
|
3076
|
+
|
|
3077
|
+
namespace preferred_integer_types {
|
|
3078
|
+
JKJ_INLINE_VARIABLE struct match_t {
|
|
3079
|
+
using preferred_integer_types_policy = match_t;
|
|
3080
|
+
|
|
3081
|
+
template <class FormatTraits, detail::stdr::uint_least64_t upper_bound>
|
|
3082
|
+
using remainder_type = typename FormatTraits::carrier_uint;
|
|
3083
|
+
|
|
3084
|
+
template <class FormatTraits, detail::stdr::int_least32_t lower_bound,
|
|
3085
|
+
detail::stdr::uint_least32_t upper_bound>
|
|
3086
|
+
using decimal_exponent_type = typename FormatTraits::exponent_int;
|
|
3087
|
+
|
|
3088
|
+
template <class FormatTraits>
|
|
3089
|
+
using shift_amount_type = typename FormatTraits::exponent_int;
|
|
3090
|
+
} match;
|
|
3091
|
+
|
|
3092
|
+
JKJ_INLINE_VARIABLE struct prefer_32_t {
|
|
3093
|
+
using preferred_integer_types_policy = prefer_32_t;
|
|
3094
|
+
|
|
3095
|
+
// Parentheses around min/max are to prevent macro expansions (e.g. in Windows.h).
|
|
3096
|
+
template <class FormatTraits, detail::stdr::uint_least64_t upper_bound>
|
|
3097
|
+
using remainder_type = typename detail::stdr::conditional<
|
|
3098
|
+
upper_bound <=
|
|
3099
|
+
(detail::stdr::numeric_limits<detail::stdr::uint_least32_t>::max)(),
|
|
3100
|
+
detail::stdr::uint_least32_t, typename FormatTraits::carrier_uint>::type;
|
|
3101
|
+
|
|
3102
|
+
template <class FormatTraits, detail::stdr::int_least32_t lower_bound,
|
|
3103
|
+
detail::stdr::uint_least32_t upper_bound>
|
|
3104
|
+
using decimal_exponent_type = typename detail::stdr::conditional<
|
|
3105
|
+
FormatTraits::format::exponent_bits <=
|
|
3106
|
+
detail::value_bits<detail::stdr::int_least32_t>::value,
|
|
3107
|
+
detail::stdr::int_least32_t, typename FormatTraits::exponent_int>::type;
|
|
3108
|
+
|
|
3109
|
+
template <class FormatTraits>
|
|
3110
|
+
using shift_amount_type = detail::stdr::int_least32_t;
|
|
3111
|
+
} prefer_32;
|
|
3112
|
+
|
|
3113
|
+
JKJ_INLINE_VARIABLE struct minimal_t {
|
|
3114
|
+
using preferred_integer_types_policy = minimal_t;
|
|
3115
|
+
|
|
3116
|
+
// Parentheses around min/max are to prevent macro expansions (e.g. in Windows.h).
|
|
3117
|
+
template <class FormatTraits, detail::stdr::uint_least64_t upper_bound>
|
|
3118
|
+
using remainder_type = typename detail::stdr::conditional<
|
|
3119
|
+
upper_bound <=
|
|
3120
|
+
(detail::stdr::numeric_limits<detail::stdr::uint_least8_t>::max)(),
|
|
3121
|
+
detail::stdr::uint_least8_t,
|
|
3122
|
+
typename detail::stdr::conditional<
|
|
3123
|
+
upper_bound <=
|
|
3124
|
+
(detail::stdr::numeric_limits<detail::stdr::uint_least16_t>::max)(),
|
|
3125
|
+
detail::stdr::uint_least16_t,
|
|
3126
|
+
typename detail::stdr::conditional<
|
|
3127
|
+
upper_bound <=
|
|
3128
|
+
(detail::stdr::numeric_limits<detail::stdr::uint_least32_t>::max)(),
|
|
3129
|
+
detail::stdr::uint_least32_t,
|
|
3130
|
+
typename detail::stdr::conditional<
|
|
3131
|
+
upper_bound <= (detail::stdr::numeric_limits<
|
|
3132
|
+
detail::stdr::uint_least64_t>::max)(),
|
|
3133
|
+
detail::stdr::uint_least64_t,
|
|
3134
|
+
typename FormatTraits::carrier_uint>::type>::type>::type>::type;
|
|
3135
|
+
|
|
3136
|
+
// Parentheses around min/max are to prevent macro expansions (e.g. in Windows.h).
|
|
3137
|
+
template <class FormatTraits, detail::stdr::int_least32_t lower_bound,
|
|
3138
|
+
detail::stdr::uint_least32_t upper_bound>
|
|
3139
|
+
using decimal_exponent_type = typename detail::stdr::conditional<
|
|
3140
|
+
lower_bound >=
|
|
3141
|
+
(detail::stdr::numeric_limits<detail::stdr::int_least8_t>::min)() &&
|
|
3142
|
+
upper_bound <=
|
|
3143
|
+
(detail::stdr::numeric_limits<detail::stdr::int_least8_t>::max)(),
|
|
3144
|
+
detail::stdr::int_least8_t,
|
|
3145
|
+
typename detail::stdr::conditional<
|
|
3146
|
+
lower_bound >= (detail::stdr::numeric_limits<
|
|
3147
|
+
detail::stdr::int_least16_t>::min)() &&
|
|
3148
|
+
upper_bound <=
|
|
3149
|
+
(detail::stdr::numeric_limits<detail::stdr::int_least16_t>::max)(),
|
|
3150
|
+
detail::stdr::int_least16_t,
|
|
3151
|
+
typename detail::stdr::conditional<
|
|
3152
|
+
lower_bound >= (detail::stdr::numeric_limits<
|
|
3153
|
+
detail::stdr::int_least32_t>::min)() &&
|
|
3154
|
+
upper_bound <= (detail::stdr::numeric_limits<
|
|
3155
|
+
detail::stdr::int_least32_t>::max)(),
|
|
3156
|
+
detail::stdr::int_least32_t,
|
|
3157
|
+
typename FormatTraits::exponent_int>::type>::type>::type;
|
|
3158
|
+
|
|
3159
|
+
template <class FormatTraits>
|
|
3160
|
+
using shift_amount_type = detail::stdr::int_least8_t;
|
|
3161
|
+
} minimal;
|
|
3162
|
+
}
|
|
3163
|
+
}
|
|
3164
|
+
|
|
3165
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
3166
|
+
// Specializations of user-specializable templates used in the main algorithm.
|
|
3167
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
3168
|
+
|
|
3169
|
+
template <class DecimalExponentType>
|
|
3170
|
+
struct remove_trailing_zeros_traits<policy::trailing_zero::remove_t, ieee754_binary32,
|
|
3171
|
+
detail::stdr::uint_least32_t, DecimalExponentType> {
|
|
3172
|
+
JKJ_FORCEINLINE static JKJ_CONSTEXPR14 void
|
|
3173
|
+
remove_trailing_zeros(detail::stdr::uint_least32_t& significand,
|
|
3174
|
+
DecimalExponentType& exponent) noexcept {
|
|
3175
|
+
// See https://github.com/jk-jeon/rtz_benchmark.
|
|
3176
|
+
// The idea of branchless search below is by reddit users r/pigeon768 and
|
|
3177
|
+
// r/TheoreticalDumbass.
|
|
3178
|
+
|
|
3179
|
+
auto r = detail::bits::rotr<32>(
|
|
3180
|
+
detail::stdr::uint_least32_t(significand * UINT32_C(184254097)), 4);
|
|
3181
|
+
auto b = r < UINT32_C(429497);
|
|
3182
|
+
auto s = DecimalExponentType(b);
|
|
3183
|
+
significand = b ? r : significand;
|
|
3184
|
+
|
|
3185
|
+
r = detail::bits::rotr<32>(
|
|
3186
|
+
detail::stdr::uint_least32_t(significand * UINT32_C(42949673)), 2);
|
|
3187
|
+
b = r < UINT32_C(42949673);
|
|
3188
|
+
s = s * 2 + b;
|
|
3189
|
+
significand = b ? r : significand;
|
|
3190
|
+
|
|
3191
|
+
r = detail::bits::rotr<32>(
|
|
3192
|
+
detail::stdr::uint_least32_t(significand * UINT32_C(1288490189)), 1);
|
|
3193
|
+
b = r < UINT32_C(429496730);
|
|
3194
|
+
s = s * 2 + b;
|
|
3195
|
+
significand = b ? r : significand;
|
|
3196
|
+
|
|
3197
|
+
assert(detail::stdr::numeric_limits<DecimalExponentType>::max() - s >= exponent);
|
|
3198
|
+
exponent += s;
|
|
3199
|
+
}
|
|
3200
|
+
};
|
|
3201
|
+
|
|
3202
|
+
template <class DecimalExponentType>
|
|
3203
|
+
struct remove_trailing_zeros_traits<policy::trailing_zero::remove_t, ieee754_binary64,
|
|
3204
|
+
detail::stdr::uint_least64_t, DecimalExponentType> {
|
|
3205
|
+
JKJ_FORCEINLINE static JKJ_CONSTEXPR14 void
|
|
3206
|
+
remove_trailing_zeros(detail::stdr::uint_least64_t& significand,
|
|
3207
|
+
DecimalExponentType& exponent) noexcept {
|
|
3208
|
+
// See https://github.com/jk-jeon/rtz_benchmark.
|
|
3209
|
+
// The idea of branchless search below is by reddit users r/pigeon768 and
|
|
3210
|
+
// r/TheoreticalDumbass.
|
|
3211
|
+
|
|
3212
|
+
auto r = detail::bits::rotr<64>(
|
|
3213
|
+
detail::stdr::uint_least64_t(significand * UINT64_C(28999941890838049)), 8);
|
|
3214
|
+
auto b = r < UINT64_C(184467440738);
|
|
3215
|
+
auto s = DecimalExponentType(b);
|
|
3216
|
+
significand = b ? r : significand;
|
|
3217
|
+
|
|
3218
|
+
r = detail::bits::rotr<64>(
|
|
3219
|
+
detail::stdr::uint_least64_t(significand * UINT64_C(182622766329724561)), 4);
|
|
3220
|
+
b = r < UINT64_C(1844674407370956);
|
|
3221
|
+
s = s * 2 + b;
|
|
3222
|
+
significand = b ? r : significand;
|
|
3223
|
+
|
|
3224
|
+
r = detail::bits::rotr<64>(
|
|
3225
|
+
detail::stdr::uint_least64_t(significand * UINT64_C(10330176681277348905)), 2);
|
|
3226
|
+
b = r < UINT64_C(184467440737095517);
|
|
3227
|
+
s = s * 2 + b;
|
|
3228
|
+
significand = b ? r : significand;
|
|
3229
|
+
|
|
3230
|
+
r = detail::bits::rotr<64>(
|
|
3231
|
+
detail::stdr::uint_least64_t(significand * UINT64_C(14757395258967641293)), 1);
|
|
3232
|
+
b = r < UINT64_C(1844674407370955162);
|
|
3233
|
+
s = s * 2 + b;
|
|
3234
|
+
significand = b ? r : significand;
|
|
3235
|
+
|
|
3236
|
+
assert(detail::stdr::numeric_limits<DecimalExponentType>::max() - s >= exponent);
|
|
3237
|
+
exponent += s;
|
|
3238
|
+
}
|
|
3239
|
+
};
|
|
3240
|
+
|
|
3241
|
+
template <class DecimalExponentType>
|
|
3242
|
+
struct remove_trailing_zeros_traits<policy::trailing_zero::remove_compact_t, ieee754_binary32,
|
|
3243
|
+
detail::stdr::uint_least32_t, DecimalExponentType> {
|
|
3244
|
+
JKJ_FORCEINLINE static JKJ_CONSTEXPR14 void
|
|
3245
|
+
remove_trailing_zeros(detail::stdr::uint_least32_t& significand,
|
|
3246
|
+
DecimalExponentType& exponent) noexcept {
|
|
3247
|
+
// See https://github.com/jk-jeon/rtz_benchmark.
|
|
3248
|
+
while (true) {
|
|
3249
|
+
auto const r = detail::stdr::uint_least32_t(significand * UINT32_C(1288490189));
|
|
3250
|
+
if (r < UINT32_C(429496731)) {
|
|
3251
|
+
significand = detail::stdr::uint_least32_t(r >> 1);
|
|
3252
|
+
exponent += 1;
|
|
3253
|
+
}
|
|
3254
|
+
else {
|
|
3255
|
+
break;
|
|
3256
|
+
}
|
|
3257
|
+
}
|
|
3258
|
+
}
|
|
3259
|
+
};
|
|
3260
|
+
|
|
3261
|
+
template <class DecimalExponentType>
|
|
3262
|
+
struct remove_trailing_zeros_traits<policy::trailing_zero::remove_compact_t, ieee754_binary64,
|
|
3263
|
+
detail::stdr::uint_least64_t, DecimalExponentType> {
|
|
3264
|
+
JKJ_FORCEINLINE static JKJ_CONSTEXPR14 void
|
|
3265
|
+
remove_trailing_zeros(detail::stdr::uint_least64_t& significand,
|
|
3266
|
+
DecimalExponentType& exponent) noexcept {
|
|
3267
|
+
// See https://github.com/jk-jeon/rtz_benchmark.
|
|
3268
|
+
while (true) {
|
|
3269
|
+
auto const r =
|
|
3270
|
+
detail::stdr::uint_least64_t(significand * UINT64_C(5534023222112865485));
|
|
3271
|
+
if (r < UINT64_C(1844674407370955163)) {
|
|
3272
|
+
significand = detail::stdr::uint_least64_t(r >> 1);
|
|
3273
|
+
exponent += 1;
|
|
3274
|
+
}
|
|
3275
|
+
else {
|
|
3276
|
+
break;
|
|
3277
|
+
}
|
|
3278
|
+
}
|
|
3279
|
+
}
|
|
3280
|
+
};
|
|
3281
|
+
|
|
3282
|
+
template <class ExponentInt>
|
|
3283
|
+
struct multiplication_traits<
|
|
3284
|
+
ieee754_binary_traits<ieee754_binary32, detail::stdr::uint_least32_t, ExponentInt>,
|
|
3285
|
+
detail::stdr::uint_least64_t, 64>
|
|
3286
|
+
: public multiplication_traits_base<
|
|
3287
|
+
ieee754_binary_traits<ieee754_binary32, detail::stdr::uint_least32_t>,
|
|
3288
|
+
detail::stdr::uint_least64_t, 64> {
|
|
3289
|
+
static JKJ_CONSTEXPR20 compute_mul_result
|
|
3290
|
+
compute_mul(carrier_uint u, cache_entry_type const& cache) noexcept {
|
|
3291
|
+
auto const r = detail::wuint::umul96_upper64(u, cache);
|
|
3292
|
+
return {carrier_uint(r >> 32), carrier_uint(r) == 0};
|
|
3293
|
+
}
|
|
3294
|
+
|
|
3295
|
+
template <class ShiftAmountType>
|
|
3296
|
+
static constexpr detail::stdr::uint_least64_t compute_delta(cache_entry_type const& cache,
|
|
3297
|
+
ShiftAmountType beta) noexcept {
|
|
3298
|
+
return detail::stdr::uint_least64_t(cache >> ShiftAmountType(cache_bits - 1 - beta));
|
|
3299
|
+
}
|
|
3300
|
+
|
|
3301
|
+
template <class ShiftAmountType>
|
|
3302
|
+
static JKJ_CONSTEXPR20 compute_mul_parity_result compute_mul_parity(
|
|
3303
|
+
carrier_uint two_f, cache_entry_type const& cache, ShiftAmountType beta) noexcept {
|
|
3304
|
+
assert(beta >= 1);
|
|
3305
|
+
assert(beta <= 32);
|
|
3306
|
+
|
|
3307
|
+
auto const r = detail::wuint::umul96_lower64(two_f, cache);
|
|
3308
|
+
return {((r >> ShiftAmountType(64 - beta)) & 1) != 0,
|
|
3309
|
+
(UINT32_C(0xffffffff) & (r >> ShiftAmountType(32 - beta))) == 0};
|
|
3310
|
+
}
|
|
3311
|
+
|
|
3312
|
+
template <class ShiftAmountType>
|
|
3313
|
+
static constexpr carrier_uint
|
|
3314
|
+
compute_left_endpoint_for_shorter_interval_case(cache_entry_type const& cache,
|
|
3315
|
+
ShiftAmountType beta) noexcept {
|
|
3316
|
+
return carrier_uint((cache - (cache >> (significand_bits + 2))) >>
|
|
3317
|
+
ShiftAmountType(cache_bits - significand_bits - 1 - beta));
|
|
3318
|
+
}
|
|
3319
|
+
|
|
3320
|
+
template <class ShiftAmountType>
|
|
3321
|
+
static constexpr carrier_uint
|
|
3322
|
+
compute_right_endpoint_for_shorter_interval_case(cache_entry_type const& cache,
|
|
3323
|
+
ShiftAmountType beta) noexcept {
|
|
3324
|
+
return carrier_uint((cache + (cache >> (significand_bits + 1))) >>
|
|
3325
|
+
ShiftAmountType(cache_bits - significand_bits - 1 - beta));
|
|
3326
|
+
}
|
|
3327
|
+
|
|
3328
|
+
template <class ShiftAmountType>
|
|
3329
|
+
static constexpr carrier_uint
|
|
3330
|
+
compute_round_up_for_shorter_interval_case(cache_entry_type const& cache,
|
|
3331
|
+
ShiftAmountType beta) noexcept {
|
|
3332
|
+
return (carrier_uint(cache >>
|
|
3333
|
+
ShiftAmountType(cache_bits - significand_bits - 2 - beta)) +
|
|
3334
|
+
1) /
|
|
3335
|
+
2;
|
|
3336
|
+
}
|
|
3337
|
+
};
|
|
3338
|
+
|
|
3339
|
+
template <class ExponentInt>
|
|
3340
|
+
struct multiplication_traits<
|
|
3341
|
+
ieee754_binary_traits<ieee754_binary64, detail::stdr::uint_least64_t, ExponentInt>,
|
|
3342
|
+
detail::wuint::uint128, 128>
|
|
3343
|
+
: public multiplication_traits_base<
|
|
3344
|
+
ieee754_binary_traits<ieee754_binary64, detail::stdr::uint_least64_t>,
|
|
3345
|
+
detail::wuint::uint128, 128> {
|
|
3346
|
+
static JKJ_CONSTEXPR20 compute_mul_result
|
|
3347
|
+
compute_mul(carrier_uint u, cache_entry_type const& cache) noexcept {
|
|
3348
|
+
auto const r = detail::wuint::umul192_upper128(u, cache);
|
|
3349
|
+
return {r.high(), r.low() == 0};
|
|
3350
|
+
}
|
|
3351
|
+
|
|
3352
|
+
template <class ShiftAmountType>
|
|
3353
|
+
static constexpr detail::stdr::uint_least64_t compute_delta(cache_entry_type const& cache,
|
|
3354
|
+
ShiftAmountType beta) noexcept {
|
|
3355
|
+
return detail::stdr::uint_least64_t(cache.high() >>
|
|
3356
|
+
ShiftAmountType(total_bits - 1 - beta));
|
|
3357
|
+
}
|
|
3358
|
+
|
|
3359
|
+
template <class ShiftAmountType>
|
|
3360
|
+
static JKJ_CONSTEXPR20 compute_mul_parity_result compute_mul_parity(
|
|
3361
|
+
carrier_uint two_f, cache_entry_type const& cache, ShiftAmountType beta) noexcept {
|
|
3362
|
+
assert(beta >= 1);
|
|
3363
|
+
assert(beta < 64);
|
|
3364
|
+
|
|
3365
|
+
auto const r = detail::wuint::umul192_lower128(two_f, cache);
|
|
3366
|
+
return {((r.high() >> ShiftAmountType(64 - beta)) & 1) != 0,
|
|
3367
|
+
(((r.high() << beta) & UINT64_C(0xffffffffffffffff)) |
|
|
3368
|
+
(r.low() >> ShiftAmountType(64 - beta))) == 0};
|
|
3369
|
+
}
|
|
3370
|
+
|
|
3371
|
+
template <class ShiftAmountType>
|
|
3372
|
+
static constexpr carrier_uint
|
|
3373
|
+
compute_left_endpoint_for_shorter_interval_case(cache_entry_type const& cache,
|
|
3374
|
+
ShiftAmountType beta) noexcept {
|
|
3375
|
+
return (cache.high() - (cache.high() >> (significand_bits + 2))) >>
|
|
3376
|
+
ShiftAmountType(total_bits - significand_bits - 1 - beta);
|
|
3377
|
+
}
|
|
3378
|
+
|
|
3379
|
+
template <class ShiftAmountType>
|
|
3380
|
+
static constexpr carrier_uint
|
|
3381
|
+
compute_right_endpoint_for_shorter_interval_case(cache_entry_type const& cache,
|
|
3382
|
+
ShiftAmountType beta) noexcept {
|
|
3383
|
+
return (cache.high() + (cache.high() >> (significand_bits + 1))) >>
|
|
3384
|
+
ShiftAmountType(total_bits - significand_bits - 1 - beta);
|
|
3385
|
+
}
|
|
3386
|
+
|
|
3387
|
+
template <class ShiftAmountType>
|
|
3388
|
+
static constexpr carrier_uint
|
|
3389
|
+
compute_round_up_for_shorter_interval_case(cache_entry_type const& cache,
|
|
3390
|
+
ShiftAmountType beta) noexcept {
|
|
3391
|
+
return ((cache.high() >> ShiftAmountType(total_bits - significand_bits - 2 - beta)) +
|
|
3392
|
+
1) /
|
|
3393
|
+
2;
|
|
3394
|
+
}
|
|
3395
|
+
};
|
|
3396
|
+
|
|
3397
|
+
namespace detail {
|
|
3398
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
3399
|
+
// The main algorithm.
|
|
3400
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
3401
|
+
|
|
3402
|
+
template <class FormatTraits>
|
|
3403
|
+
struct impl : private FormatTraits::format {
|
|
3404
|
+
using format = typename FormatTraits::format;
|
|
3405
|
+
using carrier_uint = typename FormatTraits::carrier_uint;
|
|
3406
|
+
static constexpr int carrier_bits = FormatTraits::carrier_bits;
|
|
3407
|
+
using exponent_int = typename FormatTraits::exponent_int;
|
|
3408
|
+
|
|
3409
|
+
using format::significand_bits;
|
|
3410
|
+
using format::min_exponent;
|
|
3411
|
+
using format::max_exponent;
|
|
3412
|
+
using format::exponent_bias;
|
|
3413
|
+
|
|
3414
|
+
static constexpr int kappa =
|
|
3415
|
+
log::floor_log10_pow2(carrier_bits - significand_bits - 2) - 1;
|
|
3416
|
+
static_assert(kappa >= 1, "");
|
|
3417
|
+
static_assert(carrier_bits >= significand_bits + 2 + log::floor_log2_pow10(kappa + 1),
|
|
3418
|
+
"");
|
|
3419
|
+
|
|
3420
|
+
// Trailing underscores are to avoid name clash with macros (e.g. Windows.h).
|
|
3421
|
+
static constexpr int min_(int x, int y) noexcept { return x < y ? x : y; }
|
|
3422
|
+
static constexpr int max_(int x, int y) noexcept { return x > y ? x : y; }
|
|
3423
|
+
|
|
3424
|
+
static constexpr int min_k =
|
|
3425
|
+
min_(-log::floor_log10_pow2_minus_log10_4_over_3(max_exponent - significand_bits),
|
|
3426
|
+
-log::floor_log10_pow2(max_exponent - significand_bits) + kappa);
|
|
3427
|
+
|
|
3428
|
+
// We do invoke shorter_interval_case for exponent == min_exponent case,
|
|
3429
|
+
// so we should not add 1 here.
|
|
3430
|
+
static constexpr int max_k =
|
|
3431
|
+
max_(-log::floor_log10_pow2_minus_log10_4_over_3(min_exponent -
|
|
3432
|
+
significand_bits /*+ 1*/),
|
|
3433
|
+
-log::floor_log10_pow2(min_exponent - significand_bits) + kappa);
|
|
3434
|
+
|
|
3435
|
+
static constexpr int case_shorter_interval_left_endpoint_lower_threshold = 2;
|
|
3436
|
+
static constexpr int case_shorter_interval_left_endpoint_upper_threshold =
|
|
3437
|
+
2 +
|
|
3438
|
+
log::floor_log2(
|
|
3439
|
+
compute_power<
|
|
3440
|
+
count_factors<5>((carrier_uint(1) << (significand_bits + 2)) - 1) + 1>(10) /
|
|
3441
|
+
3);
|
|
3442
|
+
|
|
3443
|
+
static constexpr int case_shorter_interval_right_endpoint_lower_threshold = 0;
|
|
3444
|
+
static constexpr int case_shorter_interval_right_endpoint_upper_threshold =
|
|
3445
|
+
2 +
|
|
3446
|
+
log::floor_log2(
|
|
3447
|
+
compute_power<
|
|
3448
|
+
count_factors<5>((carrier_uint(1) << (significand_bits + 1)) + 1) + 1>(10) /
|
|
3449
|
+
3);
|
|
3450
|
+
|
|
3451
|
+
static constexpr int shorter_interval_tie_lower_threshold =
|
|
3452
|
+
-log::floor_log5_pow2_minus_log5_3(significand_bits + 4) - 2 - significand_bits;
|
|
3453
|
+
static constexpr int shorter_interval_tie_upper_threshold =
|
|
3454
|
+
-log::floor_log5_pow2(significand_bits + 2) - 2 - significand_bits;
|
|
3455
|
+
|
|
3456
|
+
template <class PreferredIntegerTypesPolicy>
|
|
3457
|
+
using remainder_type = typename PreferredIntegerTypesPolicy::template remainder_type<
|
|
3458
|
+
FormatTraits, compute_power<kappa + 1>(detail::stdr::uint_least64_t(10))>;
|
|
3459
|
+
|
|
3460
|
+
template <class PreferredIntegerTypesPolicy>
|
|
3461
|
+
using decimal_exponent_type =
|
|
3462
|
+
typename PreferredIntegerTypesPolicy::template decimal_exponent_type<
|
|
3463
|
+
FormatTraits, detail::stdr::int_least32_t(min_(-max_k, min_k)),
|
|
3464
|
+
detail::stdr::int_least32_t(max_(max_k, -min_k + kappa + 1))>;
|
|
3465
|
+
|
|
3466
|
+
template <class SignPolicy, class TrailingZeroPolicy, class PreferredIntegerTypesPolicy>
|
|
3467
|
+
using return_type =
|
|
3468
|
+
decimal_fp<carrier_uint, decimal_exponent_type<PreferredIntegerTypesPolicy>,
|
|
3469
|
+
SignPolicy::return_has_sign, TrailingZeroPolicy::report_trailing_zeros>;
|
|
3470
|
+
|
|
3471
|
+
//// The main algorithm assumes the input is a normal/subnormal finite number.
|
|
3472
|
+
|
|
3473
|
+
template <class SignPolicy, class TrailingZeroPolicy, class IntervalTypeProvider,
|
|
3474
|
+
class BinaryToDecimalRoundingPolicy, class CachePolicy,
|
|
3475
|
+
class PreferredIntegerTypesPolicy>
|
|
3476
|
+
JKJ_SAFEBUFFERS static JKJ_CONSTEXPR20
|
|
3477
|
+
return_type<SignPolicy, TrailingZeroPolicy, PreferredIntegerTypesPolicy>
|
|
3478
|
+
compute_nearest(signed_significand_bits<FormatTraits> s,
|
|
3479
|
+
exponent_int exponent_bits) noexcept {
|
|
3480
|
+
using cache_holder_type = typename CachePolicy::template cache_holder_type<format>;
|
|
3481
|
+
static_assert(
|
|
3482
|
+
min_k >= cache_holder_type::min_k && max_k <= cache_holder_type::max_k, "");
|
|
3483
|
+
|
|
3484
|
+
using remainder_type_ = remainder_type<PreferredIntegerTypesPolicy>;
|
|
3485
|
+
using decimal_exponent_type_ = decimal_exponent_type<PreferredIntegerTypesPolicy>;
|
|
3486
|
+
using shift_amount_type =
|
|
3487
|
+
typename PreferredIntegerTypesPolicy::template shift_amount_type<FormatTraits>;
|
|
3488
|
+
|
|
3489
|
+
using multiplication_traits_ =
|
|
3490
|
+
multiplication_traits<FormatTraits,
|
|
3491
|
+
typename cache_holder_type::cache_entry_type,
|
|
3492
|
+
cache_holder_type::cache_bits>;
|
|
3493
|
+
|
|
3494
|
+
auto two_fc = s.remove_sign_bit_and_shift();
|
|
3495
|
+
auto binary_exponent = exponent_bits;
|
|
3496
|
+
|
|
3497
|
+
// Is the input a normal number?
|
|
3498
|
+
if (binary_exponent != 0) {
|
|
3499
|
+
binary_exponent += format::exponent_bias - format::significand_bits;
|
|
3500
|
+
|
|
3501
|
+
// Shorter interval case; proceed like Schubfach.
|
|
3502
|
+
// One might think this condition is wrong, since when exponent_bits ==
|
|
3503
|
+
// 1 and two_fc == 0, the interval is actually regular. However, it
|
|
3504
|
+
// turns out that this seemingly wrong condition is actually fine,
|
|
3505
|
+
// because the end result is anyway the same.
|
|
3506
|
+
//
|
|
3507
|
+
// [binary32]
|
|
3508
|
+
// (fc-1/2) * 2^e = 1.175'494'28... * 10^-38
|
|
3509
|
+
// (fc-1/4) * 2^e = 1.175'494'31... * 10^-38
|
|
3510
|
+
// fc * 2^e = 1.175'494'35... * 10^-38
|
|
3511
|
+
// (fc+1/2) * 2^e = 1.175'494'42... * 10^-38
|
|
3512
|
+
//
|
|
3513
|
+
// Hence, shorter_interval_case will return 1.175'494'4 * 10^-38.
|
|
3514
|
+
// 1.175'494'3 * 10^-38 is also a correct shortest representation that
|
|
3515
|
+
// will be rejected if we assume shorter interval, but 1.175'494'4 *
|
|
3516
|
+
// 10^-38 is closer to the true value so it doesn't matter.
|
|
3517
|
+
//
|
|
3518
|
+
// [binary64]
|
|
3519
|
+
// (fc-1/2) * 2^e = 2.225'073'858'507'201'13... * 10^-308
|
|
3520
|
+
// (fc-1/4) * 2^e = 2.225'073'858'507'201'25... * 10^-308
|
|
3521
|
+
// fc * 2^e = 2.225'073'858'507'201'38... * 10^-308
|
|
3522
|
+
// (fc+1/2) * 2^e = 2.225'073'858'507'201'63... * 10^-308
|
|
3523
|
+
//
|
|
3524
|
+
// Hence, shorter_interval_case will return 2.225'073'858'507'201'4 *
|
|
3525
|
+
// 10^-308. This is indeed of the shortest length, and it is the unique
|
|
3526
|
+
// one closest to the true value among valid representations of the same
|
|
3527
|
+
// length.
|
|
3528
|
+
static_assert(stdr::is_same<format, ieee754_binary32>::value ||
|
|
3529
|
+
stdr::is_same<format, ieee754_binary64>::value,
|
|
3530
|
+
"");
|
|
3531
|
+
|
|
3532
|
+
// Shorter interval case.
|
|
3533
|
+
if (two_fc == 0) {
|
|
3534
|
+
auto interval_type = IntervalTypeProvider::shorter_interval(s);
|
|
3535
|
+
|
|
3536
|
+
// Compute k and beta.
|
|
3537
|
+
auto const minus_k = log::floor_log10_pow2_minus_log10_4_over_3<
|
|
3538
|
+
min_exponent - format::significand_bits,
|
|
3539
|
+
max_exponent - format::significand_bits, decimal_exponent_type_>(
|
|
3540
|
+
binary_exponent);
|
|
3541
|
+
auto const beta = shift_amount_type(
|
|
3542
|
+
binary_exponent +
|
|
3543
|
+
log::floor_log2_pow10<min_k, max_k>(decimal_exponent_type_(-minus_k)));
|
|
3544
|
+
|
|
3545
|
+
// Compute xi and zi.
|
|
3546
|
+
auto const cache =
|
|
3547
|
+
CachePolicy::template get_cache<format, shift_amount_type>(
|
|
3548
|
+
decimal_exponent_type_(-minus_k));
|
|
3549
|
+
|
|
3550
|
+
auto xi =
|
|
3551
|
+
multiplication_traits_::compute_left_endpoint_for_shorter_interval_case(
|
|
3552
|
+
cache, beta);
|
|
3553
|
+
auto zi = multiplication_traits_::
|
|
3554
|
+
compute_right_endpoint_for_shorter_interval_case(cache, beta);
|
|
3555
|
+
|
|
3556
|
+
// If we don't accept the right endpoint and
|
|
3557
|
+
// if the right endpoint is an integer, decrease it.
|
|
3558
|
+
if (!interval_type.include_right_endpoint() &&
|
|
3559
|
+
is_right_endpoint_integer_shorter_interval(binary_exponent)) {
|
|
3560
|
+
--zi;
|
|
3561
|
+
}
|
|
3562
|
+
// If we don't accept the left endpoint or
|
|
3563
|
+
// if the left endpoint is not an integer, increase it.
|
|
3564
|
+
if (!interval_type.include_left_endpoint() ||
|
|
3565
|
+
!is_left_endpoint_integer_shorter_interval(binary_exponent)) {
|
|
3566
|
+
++xi;
|
|
3567
|
+
}
|
|
3568
|
+
|
|
3569
|
+
// Try bigger divisor.
|
|
3570
|
+
// zi is at most floor((f_c + 1/2) * 2^e * 10^k0).
|
|
3571
|
+
// Substituting f_c = 2^p and k0 = -floor(log10(3 * 2^(e-2))), we get
|
|
3572
|
+
// zi <= floor((2^(p+1) + 1) * 20/3) <= ceil((2^(p+1) + 1)/3) * 20.
|
|
3573
|
+
// This computation does not overflow for any of the formats I care about.
|
|
3574
|
+
carrier_uint decimal_significand = div::divide_by_pow10<
|
|
3575
|
+
1, carrier_uint,
|
|
3576
|
+
carrier_uint(
|
|
3577
|
+
((((carrier_uint(1) << (significand_bits + 1)) + 1) / 3) + 1) *
|
|
3578
|
+
20)>(zi);
|
|
3579
|
+
|
|
3580
|
+
// If succeed, remove trailing zeros if necessary and return.
|
|
3581
|
+
if (decimal_significand * 10 >= xi) {
|
|
3582
|
+
return SignPolicy::handle_sign(
|
|
3583
|
+
s, TrailingZeroPolicy::template on_trailing_zeros<format>(
|
|
3584
|
+
decimal_significand, decimal_exponent_type_(minus_k + 1)));
|
|
3585
|
+
}
|
|
3586
|
+
|
|
3587
|
+
// Otherwise, compute the round-up of y.
|
|
3588
|
+
decimal_significand =
|
|
3589
|
+
multiplication_traits_::compute_round_up_for_shorter_interval_case(
|
|
3590
|
+
cache, beta);
|
|
3591
|
+
|
|
3592
|
+
// When tie occurs, choose one of them according to the rule.
|
|
3593
|
+
if (BinaryToDecimalRoundingPolicy::prefer_round_down(decimal_significand) &&
|
|
3594
|
+
binary_exponent >= shorter_interval_tie_lower_threshold &&
|
|
3595
|
+
binary_exponent <= shorter_interval_tie_upper_threshold) {
|
|
3596
|
+
--decimal_significand;
|
|
3597
|
+
}
|
|
3598
|
+
else if (decimal_significand < xi) {
|
|
3599
|
+
++decimal_significand;
|
|
3600
|
+
}
|
|
3601
|
+
return SignPolicy::handle_sign(
|
|
3602
|
+
s, TrailingZeroPolicy::template no_trailing_zeros<format>(
|
|
3603
|
+
decimal_significand, decimal_exponent_type_(minus_k)));
|
|
3604
|
+
}
|
|
3605
|
+
|
|
3606
|
+
// Normal interval case.
|
|
3607
|
+
two_fc |= (carrier_uint(1) << (format::significand_bits + 1));
|
|
3608
|
+
}
|
|
3609
|
+
// Is the input a subnormal number?
|
|
3610
|
+
else {
|
|
3611
|
+
// Normal interval case.
|
|
3612
|
+
binary_exponent = format::min_exponent - format::significand_bits;
|
|
3613
|
+
}
|
|
3614
|
+
|
|
3615
|
+
//////////////////////////////////////////////////////////////////////
|
|
3616
|
+
// Step 1: Schubfach multiplier calculation.
|
|
3617
|
+
//////////////////////////////////////////////////////////////////////
|
|
3618
|
+
|
|
3619
|
+
auto interval_type = IntervalTypeProvider::normal_interval(s);
|
|
3620
|
+
|
|
3621
|
+
// Compute k and beta.
|
|
3622
|
+
auto const minus_k = decimal_exponent_type_(
|
|
3623
|
+
log::floor_log10_pow2<min_exponent - format::significand_bits,
|
|
3624
|
+
max_exponent - format::significand_bits,
|
|
3625
|
+
decimal_exponent_type_>(binary_exponent) -
|
|
3626
|
+
kappa);
|
|
3627
|
+
auto const cache = CachePolicy::template get_cache<format, shift_amount_type>(
|
|
3628
|
+
decimal_exponent_type_(-minus_k));
|
|
3629
|
+
auto const beta =
|
|
3630
|
+
shift_amount_type(binary_exponent + log::floor_log2_pow10<min_k, max_k>(
|
|
3631
|
+
decimal_exponent_type_(-minus_k)));
|
|
3632
|
+
|
|
3633
|
+
// Compute zi and deltai.
|
|
3634
|
+
// 10^kappa <= deltai < 10^(kappa + 1)
|
|
3635
|
+
auto const deltai = static_cast<remainder_type_>(
|
|
3636
|
+
multiplication_traits_::compute_delta(cache, beta));
|
|
3637
|
+
// For the case of binary32, the result of integer check is not correct for
|
|
3638
|
+
// 29711844 * 2^-82
|
|
3639
|
+
// = 6.1442653300000000008655037797566933477355632930994033813476... * 10^-18
|
|
3640
|
+
// and 29711844 * 2^-81
|
|
3641
|
+
// = 1.2288530660000000001731007559513386695471126586198806762695... * 10^-17,
|
|
3642
|
+
// and they are the unique counterexamples. However, since 29711844 is even,
|
|
3643
|
+
// this does not cause any problem for the endpoints calculations; it can only
|
|
3644
|
+
// cause a problem when we need to perform integer check for the center.
|
|
3645
|
+
// Fortunately, with these inputs, that branch is never executed, so we are
|
|
3646
|
+
// fine.
|
|
3647
|
+
auto const z_result =
|
|
3648
|
+
multiplication_traits_::compute_mul(carrier_uint((two_fc | 1) << beta), cache);
|
|
3649
|
+
|
|
3650
|
+
|
|
3651
|
+
//////////////////////////////////////////////////////////////////////
|
|
3652
|
+
// Step 2: Try larger divisor; remove trailing zeros if necessary.
|
|
3653
|
+
//////////////////////////////////////////////////////////////////////
|
|
3654
|
+
|
|
3655
|
+
constexpr auto big_divisor = compute_power<kappa + 1>(remainder_type_(10));
|
|
3656
|
+
constexpr auto small_divisor = compute_power<kappa>(remainder_type_(10));
|
|
3657
|
+
|
|
3658
|
+
// Using an upper bound on zi, we might be able to optimize the division
|
|
3659
|
+
// better than the compiler; we are computing zi / big_divisor here.
|
|
3660
|
+
carrier_uint decimal_significand = div::divide_by_pow10<
|
|
3661
|
+
kappa + 1, carrier_uint,
|
|
3662
|
+
carrier_uint((carrier_uint(1) << (significand_bits + 1)) * big_divisor - 1)>(
|
|
3663
|
+
z_result.integer_part);
|
|
3664
|
+
auto r = remainder_type_(z_result.integer_part - big_divisor * decimal_significand);
|
|
3665
|
+
|
|
3666
|
+
do {
|
|
3667
|
+
if (r < deltai) {
|
|
3668
|
+
// Exclude the right endpoint if necessary.
|
|
3669
|
+
if ((r | remainder_type_(!z_result.is_integer) |
|
|
3670
|
+
remainder_type_(interval_type.include_right_endpoint())) == 0) {
|
|
3671
|
+
JKJ_IF_CONSTEXPR(
|
|
3672
|
+
BinaryToDecimalRoundingPolicy::tag ==
|
|
3673
|
+
policy::binary_to_decimal_rounding::tag_t::do_not_care) {
|
|
3674
|
+
decimal_significand *= 10;
|
|
3675
|
+
--decimal_significand;
|
|
3676
|
+
return SignPolicy::handle_sign(
|
|
3677
|
+
s, TrailingZeroPolicy::template no_trailing_zeros<format>(
|
|
3678
|
+
decimal_significand,
|
|
3679
|
+
decimal_exponent_type_(minus_k + kappa)));
|
|
3680
|
+
}
|
|
3681
|
+
else {
|
|
3682
|
+
--decimal_significand;
|
|
3683
|
+
r = big_divisor;
|
|
3684
|
+
break;
|
|
3685
|
+
}
|
|
3686
|
+
}
|
|
3687
|
+
}
|
|
3688
|
+
else if (r > deltai) {
|
|
3689
|
+
break;
|
|
3690
|
+
}
|
|
3691
|
+
else {
|
|
3692
|
+
// r == deltai; compare fractional parts.
|
|
3693
|
+
auto const x_result = multiplication_traits_::compute_mul_parity(
|
|
3694
|
+
carrier_uint(two_fc - 1), cache, beta);
|
|
3695
|
+
|
|
3696
|
+
if (!(x_result.parity |
|
|
3697
|
+
(x_result.is_integer & interval_type.include_left_endpoint()))) {
|
|
3698
|
+
break;
|
|
3699
|
+
}
|
|
3700
|
+
}
|
|
3701
|
+
|
|
3702
|
+
// We may need to remove trailing zeros.
|
|
3703
|
+
return SignPolicy::handle_sign(
|
|
3704
|
+
s, TrailingZeroPolicy::template on_trailing_zeros<format>(
|
|
3705
|
+
decimal_significand, decimal_exponent_type_(minus_k + kappa + 1)));
|
|
3706
|
+
} while (false);
|
|
3707
|
+
|
|
3708
|
+
|
|
3709
|
+
//////////////////////////////////////////////////////////////////////
|
|
3710
|
+
// Step 3: Find the significand with the smaller divisor.
|
|
3711
|
+
//////////////////////////////////////////////////////////////////////
|
|
3712
|
+
|
|
3713
|
+
decimal_significand *= 10;
|
|
3714
|
+
|
|
3715
|
+
JKJ_IF_CONSTEXPR(BinaryToDecimalRoundingPolicy::tag ==
|
|
3716
|
+
policy::binary_to_decimal_rounding::tag_t::do_not_care) {
|
|
3717
|
+
// Normally, we want to compute
|
|
3718
|
+
// significand += r / small_divisor
|
|
3719
|
+
// and return, but we need to take care of the case that the resulting
|
|
3720
|
+
// value is exactly the right endpoint, while that is not included in the
|
|
3721
|
+
// interval.
|
|
3722
|
+
if (!interval_type.include_right_endpoint()) {
|
|
3723
|
+
// Is r divisible by 10^kappa?
|
|
3724
|
+
if (div::check_divisibility_and_divide_by_pow10<kappa>(r) &&
|
|
3725
|
+
z_result.is_integer) {
|
|
3726
|
+
// This should be in the interval.
|
|
3727
|
+
decimal_significand += r - 1;
|
|
3728
|
+
}
|
|
3729
|
+
else {
|
|
3730
|
+
decimal_significand += r;
|
|
3731
|
+
}
|
|
3732
|
+
}
|
|
3733
|
+
else {
|
|
3734
|
+
decimal_significand += div::small_division_by_pow10<kappa>(r);
|
|
3735
|
+
}
|
|
3736
|
+
}
|
|
3737
|
+
else {
|
|
3738
|
+
// delta is equal to 10^(kappa + elog10(2) - floor(elog10(2))), so dist cannot
|
|
3739
|
+
// be larger than r.
|
|
3740
|
+
auto dist = remainder_type_(r - (deltai / 2) + (small_divisor / 2));
|
|
3741
|
+
bool const approx_y_parity = ((dist ^ (small_divisor / 2)) & 1) != 0;
|
|
3742
|
+
|
|
3743
|
+
// Is dist divisible by 10^kappa?
|
|
3744
|
+
bool const divisible_by_small_divisor =
|
|
3745
|
+
div::check_divisibility_and_divide_by_pow10<kappa>(dist);
|
|
3746
|
+
|
|
3747
|
+
// Add dist / 10^kappa to the significand.
|
|
3748
|
+
decimal_significand += dist;
|
|
3749
|
+
|
|
3750
|
+
if (divisible_by_small_divisor) {
|
|
3751
|
+
// Check z^(f) >= epsilon^(f).
|
|
3752
|
+
// We have either yi == zi - epsiloni or yi == (zi - epsiloni) - 1,
|
|
3753
|
+
// where yi == zi - epsiloni if and only if z^(f) >= epsilon^(f).
|
|
3754
|
+
// Since there are only 2 possibilities, we only need to care about the
|
|
3755
|
+
// parity. Also, zi and r should have the same parity since the divisor
|
|
3756
|
+
// is an even number.
|
|
3757
|
+
auto const y_result =
|
|
3758
|
+
multiplication_traits_::compute_mul_parity(two_fc, cache, beta);
|
|
3759
|
+
if (y_result.parity != approx_y_parity) {
|
|
3760
|
+
--decimal_significand;
|
|
3761
|
+
}
|
|
3762
|
+
else {
|
|
3763
|
+
// If z^(f) >= epsilon^(f), we might have a tie
|
|
3764
|
+
// when z^(f) == epsilon^(f), or equivalently, when y is an integer.
|
|
3765
|
+
// For tie-to-up case, we can just choose the upper one.
|
|
3766
|
+
if (BinaryToDecimalRoundingPolicy::prefer_round_down(
|
|
3767
|
+
decimal_significand) &
|
|
3768
|
+
y_result.is_integer) {
|
|
3769
|
+
--decimal_significand;
|
|
3770
|
+
}
|
|
3771
|
+
}
|
|
3772
|
+
}
|
|
3773
|
+
}
|
|
3774
|
+
return SignPolicy::handle_sign(
|
|
3775
|
+
s, TrailingZeroPolicy::template no_trailing_zeros<format>(
|
|
3776
|
+
decimal_significand, decimal_exponent_type_(minus_k + kappa)));
|
|
3777
|
+
}
|
|
3778
|
+
|
|
3779
|
+
template <class SignPolicy, class TrailingZeroPolicy, class CachePolicy,
|
|
3780
|
+
class PreferredIntegerTypesPolicy>
|
|
3781
|
+
JKJ_FORCEINLINE JKJ_SAFEBUFFERS static JKJ_CONSTEXPR20
|
|
3782
|
+
return_type<SignPolicy, TrailingZeroPolicy, PreferredIntegerTypesPolicy>
|
|
3783
|
+
compute_left_closed_directed(signed_significand_bits<FormatTraits> s,
|
|
3784
|
+
exponent_int exponent_bits) noexcept {
|
|
3785
|
+
using cache_holder_type = typename CachePolicy::template cache_holder_type<format>;
|
|
3786
|
+
static_assert(
|
|
3787
|
+
min_k >= cache_holder_type::min_k && max_k <= cache_holder_type::max_k, "");
|
|
3788
|
+
|
|
3789
|
+
using remainder_type_ = remainder_type<PreferredIntegerTypesPolicy>;
|
|
3790
|
+
using decimal_exponent_type_ = decimal_exponent_type<PreferredIntegerTypesPolicy>;
|
|
3791
|
+
using shift_amount_type =
|
|
3792
|
+
typename PreferredIntegerTypesPolicy::template shift_amount_type<FormatTraits>;
|
|
3793
|
+
|
|
3794
|
+
using multiplication_traits_ =
|
|
3795
|
+
multiplication_traits<FormatTraits,
|
|
3796
|
+
typename cache_holder_type::cache_entry_type,
|
|
3797
|
+
cache_holder_type::cache_bits>;
|
|
3798
|
+
|
|
3799
|
+
auto two_fc = s.remove_sign_bit_and_shift();
|
|
3800
|
+
auto binary_exponent = exponent_bits;
|
|
3801
|
+
|
|
3802
|
+
// Is the input a normal number?
|
|
3803
|
+
if (binary_exponent != 0) {
|
|
3804
|
+
binary_exponent += format::exponent_bias - format::significand_bits;
|
|
3805
|
+
two_fc |= (carrier_uint(1) << (format::significand_bits + 1));
|
|
3806
|
+
}
|
|
3807
|
+
// Is the input a subnormal number?
|
|
3808
|
+
else {
|
|
3809
|
+
binary_exponent = format::min_exponent - format::significand_bits;
|
|
3810
|
+
}
|
|
3811
|
+
|
|
3812
|
+
//////////////////////////////////////////////////////////////////////
|
|
3813
|
+
// Step 1: Schubfach multiplier calculation.
|
|
3814
|
+
//////////////////////////////////////////////////////////////////////
|
|
3815
|
+
|
|
3816
|
+
// Compute k and beta.
|
|
3817
|
+
auto const minus_k = decimal_exponent_type_(
|
|
3818
|
+
log::floor_log10_pow2<format::min_exponent - format::significand_bits,
|
|
3819
|
+
format::max_exponent - format::significand_bits,
|
|
3820
|
+
decimal_exponent_type_>(binary_exponent) -
|
|
3821
|
+
kappa);
|
|
3822
|
+
auto const cache = CachePolicy::template get_cache<format, shift_amount_type>(
|
|
3823
|
+
decimal_exponent_type_(-minus_k));
|
|
3824
|
+
auto const beta =
|
|
3825
|
+
shift_amount_type(binary_exponent + log::floor_log2_pow10<min_k, max_k>(
|
|
3826
|
+
decimal_exponent_type_(-minus_k)));
|
|
3827
|
+
|
|
3828
|
+
// Compute xi and deltai.
|
|
3829
|
+
// 10^kappa <= deltai < 10^(kappa + 1)
|
|
3830
|
+
auto const deltai = static_cast<remainder_type_>(
|
|
3831
|
+
multiplication_traits_::compute_delta(cache, beta));
|
|
3832
|
+
auto x_result =
|
|
3833
|
+
multiplication_traits_::compute_mul(carrier_uint(two_fc << beta), cache);
|
|
3834
|
+
|
|
3835
|
+
// Deal with the unique exceptional cases
|
|
3836
|
+
// 29711844 * 2^-82
|
|
3837
|
+
// = 6.1442653300000000008655037797566933477355632930994033813476... * 10^-18
|
|
3838
|
+
// and 29711844 * 2^-81
|
|
3839
|
+
// = 1.2288530660000000001731007559513386695471126586198806762695... * 10^-17
|
|
3840
|
+
// for binary32.
|
|
3841
|
+
JKJ_IF_CONSTEXPR(stdr::is_same<format, ieee754_binary32>::value) {
|
|
3842
|
+
if (binary_exponent <= -80) {
|
|
3843
|
+
x_result.is_integer = false;
|
|
3844
|
+
}
|
|
3845
|
+
}
|
|
3846
|
+
|
|
3847
|
+
if (!x_result.is_integer) {
|
|
3848
|
+
++x_result.integer_part;
|
|
3849
|
+
}
|
|
3850
|
+
|
|
3851
|
+
//////////////////////////////////////////////////////////////////////
|
|
3852
|
+
// Step 2: Try larger divisor; remove trailing zeros if necessary.
|
|
3853
|
+
//////////////////////////////////////////////////////////////////////
|
|
3854
|
+
|
|
3855
|
+
constexpr auto big_divisor = compute_power<kappa + 1>(remainder_type_(10));
|
|
3856
|
+
|
|
3857
|
+
// Using an upper bound on xi, we might be able to optimize the division
|
|
3858
|
+
// better than the compiler; we are computing xi / big_divisor here.
|
|
3859
|
+
carrier_uint decimal_significand = div::divide_by_pow10<
|
|
3860
|
+
kappa + 1, carrier_uint,
|
|
3861
|
+
carrier_uint((carrier_uint(1) << (significand_bits + 1)) * big_divisor - 1)>(
|
|
3862
|
+
x_result.integer_part);
|
|
3863
|
+
auto r = remainder_type_(x_result.integer_part - big_divisor * decimal_significand);
|
|
3864
|
+
|
|
3865
|
+
if (r != 0) {
|
|
3866
|
+
++decimal_significand;
|
|
3867
|
+
r = remainder_type_(big_divisor - r);
|
|
3868
|
+
}
|
|
3869
|
+
|
|
3870
|
+
do {
|
|
3871
|
+
if (r > deltai) {
|
|
3872
|
+
break;
|
|
3873
|
+
}
|
|
3874
|
+
else if (r == deltai) {
|
|
3875
|
+
// Compare the fractional parts.
|
|
3876
|
+
// This branch is never taken for the exceptional cases
|
|
3877
|
+
// 2f_c = 29711482, e = -81
|
|
3878
|
+
// (6.1442649164096937243516663440523473127541365101933479309082... *
|
|
3879
|
+
// 10^-18) and 2f_c = 29711482, e = -80
|
|
3880
|
+
// (1.2288529832819387448703332688104694625508273020386695861816... *
|
|
3881
|
+
// 10^-17).
|
|
3882
|
+
// For the case of compressed cache for binary32, there is another
|
|
3883
|
+
// exceptional case 2f_c = 33554430, e = -10 (16383.9990234375). In this
|
|
3884
|
+
// case, the recovered cache is two large to make compute_mul_parity
|
|
3885
|
+
// mistakenly conclude that z is not an integer, but actually z = 16384 is
|
|
3886
|
+
// an integer.
|
|
3887
|
+
JKJ_IF_CONSTEXPR(
|
|
3888
|
+
stdr::is_same<cache_holder_type,
|
|
3889
|
+
compressed_cache_holder<ieee754_binary32>>::value) {
|
|
3890
|
+
if (two_fc == 33554430 && binary_exponent == -10) {
|
|
3891
|
+
break;
|
|
3892
|
+
}
|
|
3893
|
+
}
|
|
3894
|
+
auto const z_result = multiplication_traits_::compute_mul_parity(
|
|
3895
|
+
carrier_uint(two_fc + 2), cache, beta);
|
|
3896
|
+
if (z_result.parity || z_result.is_integer) {
|
|
3897
|
+
break;
|
|
3898
|
+
}
|
|
3899
|
+
}
|
|
3900
|
+
|
|
3901
|
+
// The ceiling is inside, so we are done.
|
|
3902
|
+
return SignPolicy::handle_sign(
|
|
3903
|
+
s, TrailingZeroPolicy::template on_trailing_zeros<format>(
|
|
3904
|
+
decimal_significand, decimal_exponent_type_(minus_k + kappa + 1)));
|
|
3905
|
+
} while (false);
|
|
3906
|
+
|
|
3907
|
+
|
|
3908
|
+
//////////////////////////////////////////////////////////////////////
|
|
3909
|
+
// Step 3: Find the significand with the smaller divisor.
|
|
3910
|
+
//////////////////////////////////////////////////////////////////////
|
|
3911
|
+
|
|
3912
|
+
decimal_significand *= 10;
|
|
3913
|
+
decimal_significand -= div::small_division_by_pow10<kappa>(r);
|
|
3914
|
+
return SignPolicy::handle_sign(
|
|
3915
|
+
s, TrailingZeroPolicy::template no_trailing_zeros<format>(
|
|
3916
|
+
decimal_significand, decimal_exponent_type_(minus_k + kappa)));
|
|
3917
|
+
}
|
|
3918
|
+
|
|
3919
|
+
template <class SignPolicy, class TrailingZeroPolicy, class CachePolicy,
|
|
3920
|
+
class PreferredIntegerTypesPolicy>
|
|
3921
|
+
JKJ_FORCEINLINE JKJ_SAFEBUFFERS static JKJ_CONSTEXPR20
|
|
3922
|
+
return_type<SignPolicy, TrailingZeroPolicy, PreferredIntegerTypesPolicy>
|
|
3923
|
+
compute_right_closed_directed(signed_significand_bits<FormatTraits> s,
|
|
3924
|
+
exponent_int exponent_bits) noexcept {
|
|
3925
|
+
using cache_holder_type = typename CachePolicy::template cache_holder_type<format>;
|
|
3926
|
+
static_assert(
|
|
3927
|
+
min_k >= cache_holder_type::min_k && max_k <= cache_holder_type::max_k, "");
|
|
3928
|
+
|
|
3929
|
+
using remainder_type_ = remainder_type<PreferredIntegerTypesPolicy>;
|
|
3930
|
+
using decimal_exponent_type_ = decimal_exponent_type<PreferredIntegerTypesPolicy>;
|
|
3931
|
+
using shift_amount_type =
|
|
3932
|
+
typename PreferredIntegerTypesPolicy::template shift_amount_type<FormatTraits>;
|
|
3933
|
+
|
|
3934
|
+
using multiplication_traits_ =
|
|
3935
|
+
multiplication_traits<FormatTraits,
|
|
3936
|
+
typename cache_holder_type::cache_entry_type,
|
|
3937
|
+
cache_holder_type::cache_bits>;
|
|
3938
|
+
|
|
3939
|
+
auto two_fc = s.remove_sign_bit_and_shift();
|
|
3940
|
+
auto binary_exponent = exponent_bits;
|
|
3941
|
+
bool shorter_interval = false;
|
|
3942
|
+
|
|
3943
|
+
// Is the input a normal number?
|
|
3944
|
+
if (binary_exponent != 0) {
|
|
3945
|
+
if (two_fc == 0 && binary_exponent != 1) {
|
|
3946
|
+
shorter_interval = true;
|
|
3947
|
+
}
|
|
3948
|
+
binary_exponent += format::exponent_bias - format::significand_bits;
|
|
3949
|
+
two_fc |= (carrier_uint(1) << (format::significand_bits + 1));
|
|
3950
|
+
}
|
|
3951
|
+
// Is the input a subnormal number?
|
|
3952
|
+
else {
|
|
3953
|
+
binary_exponent = format::min_exponent - format::significand_bits;
|
|
3954
|
+
}
|
|
3955
|
+
|
|
3956
|
+
//////////////////////////////////////////////////////////////////////
|
|
3957
|
+
// Step 1: Schubfach multiplier calculation.
|
|
3958
|
+
//////////////////////////////////////////////////////////////////////
|
|
3959
|
+
|
|
3960
|
+
// Compute k and beta.
|
|
3961
|
+
auto const minus_k = decimal_exponent_type_(
|
|
3962
|
+
log::floor_log10_pow2<format::min_exponent - format::significand_bits,
|
|
3963
|
+
format::max_exponent - format::significand_bits,
|
|
3964
|
+
decimal_exponent_type_>(
|
|
3965
|
+
exponent_int(binary_exponent - (shorter_interval ? 1 : 0))) -
|
|
3966
|
+
kappa);
|
|
3967
|
+
auto const cache = CachePolicy::template get_cache<format, shift_amount_type>(
|
|
3968
|
+
decimal_exponent_type_(-minus_k));
|
|
3969
|
+
auto const beta = shift_amount_type(
|
|
3970
|
+
binary_exponent + log::floor_log2_pow10(decimal_exponent_type_(-minus_k)));
|
|
3971
|
+
|
|
3972
|
+
// Compute zi and deltai.
|
|
3973
|
+
// 10^kappa <= deltai < 10^(kappa + 1)
|
|
3974
|
+
auto const deltai =
|
|
3975
|
+
static_cast<remainder_type_>(multiplication_traits_::compute_delta(
|
|
3976
|
+
cache, shift_amount_type(beta - (shorter_interval ? 1 : 0))));
|
|
3977
|
+
carrier_uint const zi =
|
|
3978
|
+
multiplication_traits_::compute_mul(carrier_uint(two_fc << beta), cache)
|
|
3979
|
+
.integer_part;
|
|
3980
|
+
|
|
3981
|
+
|
|
3982
|
+
//////////////////////////////////////////////////////////////////////
|
|
3983
|
+
// Step 2: Try larger divisor; remove trailing zeros if necessary.
|
|
3984
|
+
//////////////////////////////////////////////////////////////////////
|
|
3985
|
+
|
|
3986
|
+
constexpr auto big_divisor = compute_power<kappa + 1>(remainder_type_(10));
|
|
3987
|
+
|
|
3988
|
+
// Using an upper bound on zi, we might be able to optimize the division better
|
|
3989
|
+
// than the compiler; we are computing zi / big_divisor here.
|
|
3990
|
+
carrier_uint decimal_significand = div::divide_by_pow10<
|
|
3991
|
+
kappa + 1, carrier_uint,
|
|
3992
|
+
carrier_uint((carrier_uint(1) << (significand_bits + 1)) * big_divisor - 1)>(
|
|
3993
|
+
zi);
|
|
3994
|
+
auto const r = remainder_type_(zi - big_divisor * decimal_significand);
|
|
3995
|
+
|
|
3996
|
+
do {
|
|
3997
|
+
if (r > deltai) {
|
|
3998
|
+
break;
|
|
3999
|
+
}
|
|
4000
|
+
else if (r == deltai) {
|
|
4001
|
+
// Compare the fractional parts.
|
|
4002
|
+
if (!multiplication_traits_::compute_mul_parity(
|
|
4003
|
+
carrier_uint(two_fc - (shorter_interval ? 1 : 2)), cache, beta)
|
|
4004
|
+
.parity) {
|
|
4005
|
+
break;
|
|
4006
|
+
}
|
|
4007
|
+
}
|
|
4008
|
+
|
|
4009
|
+
// The floor is inside, so we are done.
|
|
4010
|
+
return SignPolicy::handle_sign(
|
|
4011
|
+
s, TrailingZeroPolicy::template on_trailing_zeros<format>(
|
|
4012
|
+
decimal_significand, decimal_exponent_type_(minus_k + kappa + 1)));
|
|
4013
|
+
} while (false);
|
|
4014
|
+
|
|
4015
|
+
|
|
4016
|
+
//////////////////////////////////////////////////////////////////////
|
|
4017
|
+
// Step 3: Find the significand with the small divisor.
|
|
4018
|
+
//////////////////////////////////////////////////////////////////////
|
|
4019
|
+
|
|
4020
|
+
decimal_significand *= 10;
|
|
4021
|
+
decimal_significand += div::small_division_by_pow10<kappa>(r);
|
|
4022
|
+
return SignPolicy::handle_sign(
|
|
4023
|
+
s, TrailingZeroPolicy::template no_trailing_zeros<format>(
|
|
4024
|
+
decimal_significand, decimal_exponent_type_(minus_k + kappa)));
|
|
4025
|
+
}
|
|
4026
|
+
|
|
4027
|
+
static constexpr bool
|
|
4028
|
+
is_right_endpoint_integer_shorter_interval(exponent_int binary_exponent) noexcept {
|
|
4029
|
+
return binary_exponent >= case_shorter_interval_right_endpoint_lower_threshold &&
|
|
4030
|
+
binary_exponent <= case_shorter_interval_right_endpoint_upper_threshold;
|
|
4031
|
+
}
|
|
4032
|
+
|
|
4033
|
+
static constexpr bool
|
|
4034
|
+
is_left_endpoint_integer_shorter_interval(exponent_int binary_exponent) noexcept {
|
|
4035
|
+
return binary_exponent >= case_shorter_interval_left_endpoint_lower_threshold &&
|
|
4036
|
+
binary_exponent <= case_shorter_interval_left_endpoint_upper_threshold;
|
|
4037
|
+
}
|
|
4038
|
+
};
|
|
4039
|
+
|
|
4040
|
+
|
|
4041
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
4042
|
+
// Policy holder.
|
|
4043
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
4044
|
+
|
|
4045
|
+
// The library will specify a list of accepted kinds of policies and their defaults,
|
|
4046
|
+
// and the user will pass a list of policies parameters. The policy parameters are
|
|
4047
|
+
// supposed to be stateless and only convey information through their types.
|
|
4048
|
+
// The aim of the helper classes/functions given below is to do the following:
|
|
4049
|
+
// 1. Check if the policy parameters given by the user are all valid; that means,
|
|
4050
|
+
// each of them should be at least of one of the kinds specified by the library.
|
|
4051
|
+
// If that's not the case, then the compilation fails.
|
|
4052
|
+
// 2. Check if multiple policy parameters for the same kind is specified by the
|
|
4053
|
+
// user. If that's the case, then the compilation fails.
|
|
4054
|
+
// 3. Build a class deriving from all policies the user have given, and also from
|
|
4055
|
+
// the default policies if the user did not specify one for some kinds.
|
|
4056
|
+
// The library considers a certain policy parameter to belong to a specific kind if and only
|
|
4057
|
+
// if the parameter's type has a member type with a specific name; for example, it belongs
|
|
4058
|
+
// to "sign policy" kind if there is a member type sign_policy.
|
|
4059
|
+
|
|
4060
|
+
// For a given kind, find a policy belonging to that kind.
|
|
4061
|
+
// Check if there are more than one such policies.
|
|
4062
|
+
enum class policy_found_info { not_found, unique, repeated };
|
|
4063
|
+
template <class Policy, policy_found_info info>
|
|
4064
|
+
struct found_policy_pair {
|
|
4065
|
+
// Either the policy parameter type given by the user, or the default policy.
|
|
4066
|
+
using policy = Policy;
|
|
4067
|
+
static constexpr auto found_info = info;
|
|
4068
|
+
};
|
|
4069
|
+
|
|
4070
|
+
template <class KindDetector, class DefaultPolicy>
|
|
4071
|
+
struct detector_default_pair {
|
|
4072
|
+
using kind_detector = KindDetector;
|
|
4073
|
+
|
|
4074
|
+
// Iterate through all given policy parameter types and see if there is a policy
|
|
4075
|
+
// parameter type belonging to the policy kind specified by KindDetector.
|
|
4076
|
+
// 1. If there is none, get_found_policy_pair returns
|
|
4077
|
+
// found_policy_pair<DefaultPolicy, policy_found_info::not_found>.
|
|
4078
|
+
// 2. If there is only one parameter type belonging to the specified kind, then
|
|
4079
|
+
// get_found_policy_pair returns
|
|
4080
|
+
// found_policy_pair<Policy, policy_found_info::unique>
|
|
4081
|
+
// where Policy is the unique parameter type belonging to the specified kind.
|
|
4082
|
+
// 3. If there are multiple parameter types belonging to the specified kind, then
|
|
4083
|
+
// get_found_policy_pair returns
|
|
4084
|
+
// found_policy_pair<FirstPolicy, policy_found_info::repeated>
|
|
4085
|
+
// where FirstPolicy is the first parameter type belonging to the specified kind.
|
|
4086
|
+
// The compilation must fail if this happens.
|
|
4087
|
+
// This is done by first setting FoundPolicyInfo below to
|
|
4088
|
+
// found_policy_pair<DefaultPolicy, policy_found_info::not_found>, and then iterate
|
|
4089
|
+
// over Policies, replacing FoundPolicyInfo by the appropriate one if a parameter
|
|
4090
|
+
// type belonging to the specified kind is found.
|
|
4091
|
+
|
|
4092
|
+
template <class FoundPolicyInfo, class... Policies>
|
|
4093
|
+
struct get_found_policy_pair_impl;
|
|
4094
|
+
|
|
4095
|
+
template <class FoundPolicyInfo>
|
|
4096
|
+
struct get_found_policy_pair_impl<FoundPolicyInfo> {
|
|
4097
|
+
using type = FoundPolicyInfo;
|
|
4098
|
+
};
|
|
4099
|
+
|
|
4100
|
+
template <class FoundPolicyInfo, class FirstPolicy, class... RemainingPolicies>
|
|
4101
|
+
struct get_found_policy_pair_impl<FoundPolicyInfo, FirstPolicy, RemainingPolicies...> {
|
|
4102
|
+
using type = typename stdr::conditional<
|
|
4103
|
+
KindDetector{}(dummy<FirstPolicy>{}),
|
|
4104
|
+
typename stdr::conditional<
|
|
4105
|
+
FoundPolicyInfo::found_info == policy_found_info::not_found,
|
|
4106
|
+
typename get_found_policy_pair_impl<
|
|
4107
|
+
found_policy_pair<FirstPolicy, policy_found_info::unique>,
|
|
4108
|
+
RemainingPolicies...>::type,
|
|
4109
|
+
typename get_found_policy_pair_impl<
|
|
4110
|
+
found_policy_pair<FirstPolicy, policy_found_info::repeated>,
|
|
4111
|
+
RemainingPolicies...>::type>::type,
|
|
4112
|
+
typename get_found_policy_pair_impl<FoundPolicyInfo,
|
|
4113
|
+
RemainingPolicies...>::type>::type;
|
|
4114
|
+
};
|
|
4115
|
+
|
|
4116
|
+
template <class... Policies>
|
|
4117
|
+
using get_found_policy_pair = typename get_found_policy_pair_impl<
|
|
4118
|
+
found_policy_pair<DefaultPolicy, policy_found_info::not_found>, Policies...>::type;
|
|
4119
|
+
};
|
|
4120
|
+
|
|
4121
|
+
// Simple typelist of detector_default_pair's.
|
|
4122
|
+
template <class... DetectorDefaultPairs>
|
|
4123
|
+
struct detector_default_pair_list {};
|
|
4124
|
+
|
|
4125
|
+
// Check if a given policy belongs to one of the kinds specified by the library.
|
|
4126
|
+
template <class Policy>
|
|
4127
|
+
constexpr bool check_policy_validity(dummy<Policy>, detector_default_pair_list<>) noexcept {
|
|
4128
|
+
return false;
|
|
4129
|
+
}
|
|
4130
|
+
template <class Policy, class FirstDetectorDefaultPair,
|
|
4131
|
+
class... RemainingDetectorDefaultPairs>
|
|
4132
|
+
constexpr bool check_policy_validity(
|
|
4133
|
+
dummy<Policy>, detector_default_pair_list<FirstDetectorDefaultPair,
|
|
4134
|
+
RemainingDetectorDefaultPairs...>) noexcept {
|
|
4135
|
+
return typename FirstDetectorDefaultPair::kind_detector{}(dummy<Policy>{}) ||
|
|
4136
|
+
check_policy_validity(
|
|
4137
|
+
dummy<Policy>{},
|
|
4138
|
+
detector_default_pair_list<RemainingDetectorDefaultPairs...>{});
|
|
4139
|
+
}
|
|
4140
|
+
|
|
4141
|
+
// Check if all of policies belong to some of the kinds specified by the library.
|
|
4142
|
+
template <class DetectorDefaultPairList>
|
|
4143
|
+
constexpr bool check_policy_list_validity(DetectorDefaultPairList) noexcept {
|
|
4144
|
+
return true;
|
|
4145
|
+
}
|
|
4146
|
+
template <class DetectorDefaultPairList, class FirstPolicy, class... RemainingPolicies>
|
|
4147
|
+
constexpr bool check_policy_list_validity(DetectorDefaultPairList,
|
|
4148
|
+
dummy<FirstPolicy> first_policy,
|
|
4149
|
+
dummy<RemainingPolicies>... remaining_policies) {
|
|
4150
|
+
return check_policy_validity(first_policy, DetectorDefaultPairList{}) &&
|
|
4151
|
+
check_policy_list_validity(DetectorDefaultPairList{}, remaining_policies...);
|
|
4152
|
+
}
|
|
4153
|
+
|
|
4154
|
+
// Actual policy holder class deriving from all specified policy types.
|
|
4155
|
+
template <class... Policies>
|
|
4156
|
+
struct policy_holder : Policies... {};
|
|
4157
|
+
|
|
4158
|
+
// Iterate through the library-specified list of base-default pairs, i.e., the list of
|
|
4159
|
+
// policy kinds and their defaults. For each base-default pair, call
|
|
4160
|
+
// base_default_pair::get_found_policy_pair on the list of user-specified list of
|
|
4161
|
+
// policies to get found_policy_pair, and build the list of them.
|
|
4162
|
+
|
|
4163
|
+
template <bool repeated_, class... FoundPolicyPairs>
|
|
4164
|
+
struct found_policy_pair_list {
|
|
4165
|
+
// This will be set to be true if and only if there exists at least one
|
|
4166
|
+
// found_policy_pair inside FoundPolicyPairs with
|
|
4167
|
+
// found_info == policy_found_info::repeated, in which case the compilation must
|
|
4168
|
+
// fail.
|
|
4169
|
+
static constexpr bool repeated = repeated_;
|
|
4170
|
+
};
|
|
4171
|
+
|
|
4172
|
+
// Iterate through DetectorDefaultPairList and augment FoundPolicyPairList by one at each
|
|
4173
|
+
// iteration.
|
|
4174
|
+
template <class DetectorDefaultPairList, class FoundPolicyPairList, class... Policies>
|
|
4175
|
+
struct make_policy_pair_list_impl;
|
|
4176
|
+
|
|
4177
|
+
// When there is no more detector-default pair to iterate, then the current
|
|
4178
|
+
// found_policy_pair_list is the final result.
|
|
4179
|
+
template <bool repeated, class... FoundPolicyPairs, class... Policies>
|
|
4180
|
+
struct make_policy_pair_list_impl<detector_default_pair_list<>,
|
|
4181
|
+
found_policy_pair_list<repeated, FoundPolicyPairs...>,
|
|
4182
|
+
Policies...> {
|
|
4183
|
+
using type = found_policy_pair_list<repeated, FoundPolicyPairs...>;
|
|
4184
|
+
};
|
|
4185
|
+
|
|
4186
|
+
// For the first detector-default pair in the remaining list, call
|
|
4187
|
+
// detector_default_pair::get_found_policy_pair on Policies and add the returned
|
|
4188
|
+
// found_policy_pair into the current list of found_policy_pair's, and move to the next
|
|
4189
|
+
// detector-default pair.
|
|
4190
|
+
template <class FirstDetectorDefaultPair, class... RemainingDetectorDefaultPairs,
|
|
4191
|
+
bool repeated, class... FoundPolicyPairs, class... Policies>
|
|
4192
|
+
struct make_policy_pair_list_impl<
|
|
4193
|
+
detector_default_pair_list<FirstDetectorDefaultPair, RemainingDetectorDefaultPairs...>,
|
|
4194
|
+
found_policy_pair_list<repeated, FoundPolicyPairs...>, Policies...> {
|
|
4195
|
+
using new_found_policy_pair =
|
|
4196
|
+
typename FirstDetectorDefaultPair::template get_found_policy_pair<Policies...>;
|
|
4197
|
+
|
|
4198
|
+
using type = typename make_policy_pair_list_impl<
|
|
4199
|
+
detector_default_pair_list<RemainingDetectorDefaultPairs...>,
|
|
4200
|
+
found_policy_pair_list<(repeated || new_found_policy_pair::found_info ==
|
|
4201
|
+
policy_found_info::repeated),
|
|
4202
|
+
new_found_policy_pair, FoundPolicyPairs...>,
|
|
4203
|
+
Policies...>::type;
|
|
4204
|
+
};
|
|
4205
|
+
|
|
4206
|
+
template <class DetectorDefaultPairList, class... Policies>
|
|
4207
|
+
using policy_pair_list =
|
|
4208
|
+
typename make_policy_pair_list_impl<DetectorDefaultPairList,
|
|
4209
|
+
found_policy_pair_list<false>, Policies...>::type;
|
|
4210
|
+
|
|
4211
|
+
// Unpack FoundPolicyPairList into found_policy_pair's and build the policy_holder type
|
|
4212
|
+
// from the corresponding typelist of found_policy_pair::policy's.
|
|
4213
|
+
template <class FoundPolicyPairList, class... RawPolicies>
|
|
4214
|
+
struct convert_to_policy_holder_impl;
|
|
4215
|
+
|
|
4216
|
+
template <bool repeated, class... RawPolicies>
|
|
4217
|
+
struct convert_to_policy_holder_impl<found_policy_pair_list<repeated>, RawPolicies...> {
|
|
4218
|
+
using type = policy_holder<RawPolicies...>;
|
|
4219
|
+
};
|
|
4220
|
+
|
|
4221
|
+
template <bool repeated, class FirstFoundPolicyPair, class... RemainingFoundPolicyPairs,
|
|
4222
|
+
class... RawPolicies>
|
|
4223
|
+
struct convert_to_policy_holder_impl<
|
|
4224
|
+
found_policy_pair_list<repeated, FirstFoundPolicyPair, RemainingFoundPolicyPairs...>,
|
|
4225
|
+
RawPolicies...> {
|
|
4226
|
+
using type = typename convert_to_policy_holder_impl<
|
|
4227
|
+
found_policy_pair_list<repeated, RemainingFoundPolicyPairs...>,
|
|
4228
|
+
typename FirstFoundPolicyPair::policy, RawPolicies...>::type;
|
|
4229
|
+
};
|
|
4230
|
+
|
|
4231
|
+
template <class FoundPolicyPairList>
|
|
4232
|
+
using convert_to_policy_holder =
|
|
4233
|
+
typename convert_to_policy_holder_impl<FoundPolicyPairList>::type;
|
|
4234
|
+
|
|
4235
|
+
template <class DetectorDefaultPairList, class... Policies>
|
|
4236
|
+
struct make_policy_holder_impl {
|
|
4237
|
+
static_assert(check_policy_list_validity(DetectorDefaultPairList{},
|
|
4238
|
+
dummy<Policies>{}...),
|
|
4239
|
+
"jkj::dragonbox: an invalid policy is specified");
|
|
4240
|
+
|
|
4241
|
+
static_assert(
|
|
4242
|
+
!policy_pair_list<DetectorDefaultPairList, Policies...>::repeated,
|
|
4243
|
+
"jkj::dragonbox: at most one policy should be specified for each policy kind");
|
|
4244
|
+
|
|
4245
|
+
using type =
|
|
4246
|
+
convert_to_policy_holder<policy_pair_list<DetectorDefaultPairList, Policies...>>;
|
|
4247
|
+
};
|
|
4248
|
+
|
|
4249
|
+
template <class DetectorDefaultPairList, class... Policies>
|
|
4250
|
+
using make_policy_holder =
|
|
4251
|
+
typename make_policy_holder_impl<DetectorDefaultPairList, Policies...>::type;
|
|
4252
|
+
|
|
4253
|
+
// Policy kind detectors.
|
|
4254
|
+
struct is_sign_policy {
|
|
4255
|
+
constexpr bool operator()(...) noexcept { return false; }
|
|
4256
|
+
template <class Policy, class = typename Policy::sign_policy>
|
|
4257
|
+
constexpr bool operator()(dummy<Policy>) noexcept {
|
|
4258
|
+
return true;
|
|
4259
|
+
}
|
|
4260
|
+
};
|
|
4261
|
+
struct is_trailing_zero_policy {
|
|
4262
|
+
constexpr bool operator()(...) noexcept { return false; }
|
|
4263
|
+
template <class Policy, class = typename Policy::trailing_zero_policy>
|
|
4264
|
+
constexpr bool operator()(dummy<Policy>) noexcept {
|
|
4265
|
+
return true;
|
|
4266
|
+
}
|
|
4267
|
+
};
|
|
4268
|
+
struct is_decimal_to_binary_rounding_policy {
|
|
4269
|
+
constexpr bool operator()(...) noexcept { return false; }
|
|
4270
|
+
template <class Policy, class = typename Policy::decimal_to_binary_rounding_policy>
|
|
4271
|
+
constexpr bool operator()(dummy<Policy>) noexcept {
|
|
4272
|
+
return true;
|
|
4273
|
+
}
|
|
4274
|
+
};
|
|
4275
|
+
struct is_binary_to_decimal_rounding_policy {
|
|
4276
|
+
constexpr bool operator()(...) noexcept { return false; }
|
|
4277
|
+
template <class Policy, class = typename Policy::binary_to_decimal_rounding_policy>
|
|
4278
|
+
constexpr bool operator()(dummy<Policy>) noexcept {
|
|
4279
|
+
return true;
|
|
4280
|
+
}
|
|
4281
|
+
};
|
|
4282
|
+
struct is_cache_policy {
|
|
4283
|
+
constexpr bool operator()(...) noexcept { return false; }
|
|
4284
|
+
template <class Policy, class = typename Policy::cache_policy>
|
|
4285
|
+
constexpr bool operator()(dummy<Policy>) noexcept {
|
|
4286
|
+
return true;
|
|
4287
|
+
}
|
|
4288
|
+
};
|
|
4289
|
+
struct is_preferred_integer_types_policy {
|
|
4290
|
+
constexpr bool operator()(...) noexcept { return false; }
|
|
4291
|
+
template <class Policy, class = typename Policy::preferred_integer_types_policy>
|
|
4292
|
+
constexpr bool operator()(dummy<Policy>) noexcept {
|
|
4293
|
+
return true;
|
|
4294
|
+
}
|
|
4295
|
+
};
|
|
4296
|
+
|
|
4297
|
+
template <class... Policies>
|
|
4298
|
+
using to_decimal_policy_holder = make_policy_holder<
|
|
4299
|
+
detector_default_pair_list<
|
|
4300
|
+
detector_default_pair<is_sign_policy, policy::sign::return_sign_t>,
|
|
4301
|
+
detector_default_pair<is_trailing_zero_policy, policy::trailing_zero::remove_t>,
|
|
4302
|
+
detector_default_pair<is_decimal_to_binary_rounding_policy,
|
|
4303
|
+
policy::decimal_to_binary_rounding::nearest_to_even_t>,
|
|
4304
|
+
detector_default_pair<is_binary_to_decimal_rounding_policy,
|
|
4305
|
+
policy::binary_to_decimal_rounding::to_even_t>,
|
|
4306
|
+
detector_default_pair<is_cache_policy, policy::cache::full_t>,
|
|
4307
|
+
detector_default_pair<is_preferred_integer_types_policy,
|
|
4308
|
+
policy::preferred_integer_types::match_t>>,
|
|
4309
|
+
Policies...>;
|
|
4310
|
+
|
|
4311
|
+
template <class FormatTraits, class... Policies>
|
|
4312
|
+
using to_decimal_return_type = typename impl<FormatTraits>::template return_type<
|
|
4313
|
+
typename to_decimal_policy_holder<Policies...>::sign_policy,
|
|
4314
|
+
typename to_decimal_policy_holder<Policies...>::trailing_zero_policy,
|
|
4315
|
+
typename to_decimal_policy_holder<Policies...>::preferred_integer_types_policy>;
|
|
4316
|
+
|
|
4317
|
+
template <class FormatTraits, class PolicyHolder>
|
|
4318
|
+
struct to_decimal_dispatcher {
|
|
4319
|
+
using sign_policy = typename PolicyHolder::sign_policy;
|
|
4320
|
+
using trailing_zero_policy = typename PolicyHolder::trailing_zero_policy;
|
|
4321
|
+
using binary_to_decimal_rounding_policy =
|
|
4322
|
+
typename PolicyHolder::binary_to_decimal_rounding_policy;
|
|
4323
|
+
using cache_policy = typename PolicyHolder::cache_policy;
|
|
4324
|
+
using preferred_integer_types_policy =
|
|
4325
|
+
typename PolicyHolder::preferred_integer_types_policy;
|
|
4326
|
+
using return_type =
|
|
4327
|
+
typename impl<FormatTraits>::template return_type<sign_policy, trailing_zero_policy,
|
|
4328
|
+
preferred_integer_types_policy>;
|
|
4329
|
+
|
|
4330
|
+
template <class IntervalTypeProvider>
|
|
4331
|
+
JKJ_FORCEINLINE JKJ_SAFEBUFFERS JKJ_CONSTEXPR20 return_type
|
|
4332
|
+
operator()(IntervalTypeProvider, signed_significand_bits<FormatTraits> s,
|
|
4333
|
+
typename FormatTraits::exponent_int exponent_bits) noexcept {
|
|
4334
|
+
constexpr auto tag = IntervalTypeProvider::tag;
|
|
4335
|
+
|
|
4336
|
+
JKJ_IF_CONSTEXPR(tag == policy::decimal_to_binary_rounding::tag_t::to_nearest) {
|
|
4337
|
+
return impl<FormatTraits>::template compute_nearest<
|
|
4338
|
+
sign_policy, trailing_zero_policy, IntervalTypeProvider,
|
|
4339
|
+
binary_to_decimal_rounding_policy, cache_policy,
|
|
4340
|
+
preferred_integer_types_policy>(s, exponent_bits);
|
|
4341
|
+
}
|
|
4342
|
+
else JKJ_IF_CONSTEXPR(
|
|
4343
|
+
tag == policy::decimal_to_binary_rounding::tag_t::left_closed_directed) {
|
|
4344
|
+
return impl<FormatTraits>::template compute_left_closed_directed<
|
|
4345
|
+
sign_policy, trailing_zero_policy, cache_policy,
|
|
4346
|
+
preferred_integer_types_policy>(s, exponent_bits);
|
|
4347
|
+
}
|
|
4348
|
+
else {
|
|
4349
|
+
#if JKJ_HAS_IF_CONSTEXPR
|
|
4350
|
+
static_assert(
|
|
4351
|
+
tag == policy::decimal_to_binary_rounding::tag_t::right_closed_directed,
|
|
4352
|
+
"");
|
|
4353
|
+
#endif
|
|
4354
|
+
return impl<FormatTraits>::template compute_right_closed_directed<
|
|
4355
|
+
sign_policy, trailing_zero_policy, cache_policy,
|
|
4356
|
+
preferred_integer_types_policy>(s, exponent_bits);
|
|
4357
|
+
}
|
|
4358
|
+
}
|
|
4359
|
+
};
|
|
4360
|
+
}
|
|
4361
|
+
|
|
4362
|
+
|
|
4363
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
4364
|
+
// The interface function.
|
|
4365
|
+
////////////////////////////////////////////////////////////////////////////////////////
|
|
4366
|
+
|
|
4367
|
+
template <class FormatTraits, class ExponentBits, class... Policies>
|
|
4368
|
+
JKJ_FORCEINLINE
|
|
4369
|
+
JKJ_SAFEBUFFERS JKJ_CONSTEXPR20 detail::to_decimal_return_type<FormatTraits, Policies...>
|
|
4370
|
+
to_decimal_ex(signed_significand_bits<FormatTraits> s, ExponentBits exponent_bits,
|
|
4371
|
+
Policies...) noexcept {
|
|
4372
|
+
// Build policy holder type.
|
|
4373
|
+
using policy_holder = detail::to_decimal_policy_holder<Policies...>;
|
|
4374
|
+
|
|
4375
|
+
return policy_holder::delegate(
|
|
4376
|
+
s, detail::to_decimal_dispatcher<FormatTraits, policy_holder>{}, s, exponent_bits);
|
|
4377
|
+
}
|
|
4378
|
+
|
|
4379
|
+
template <class Float,
|
|
4380
|
+
class ConversionTraits = default_float_bit_carrier_conversion_traits<Float>,
|
|
4381
|
+
class FormatTraits = ieee754_binary_traits<typename ConversionTraits::format,
|
|
4382
|
+
typename ConversionTraits::carrier_uint>,
|
|
4383
|
+
class... Policies>
|
|
4384
|
+
JKJ_FORCEINLINE
|
|
4385
|
+
JKJ_SAFEBUFFERS JKJ_CONSTEXPR20 detail::to_decimal_return_type<FormatTraits, Policies...>
|
|
4386
|
+
to_decimal(Float x, Policies... policies) noexcept {
|
|
4387
|
+
auto const br = make_float_bits<Float, ConversionTraits, FormatTraits>(x);
|
|
4388
|
+
auto const exponent_bits = br.extract_exponent_bits();
|
|
4389
|
+
auto const s = br.remove_exponent_bits();
|
|
4390
|
+
assert(br.is_finite() && br.is_nonzero());
|
|
4391
|
+
|
|
4392
|
+
return to_decimal_ex(s, exponent_bits, policies...);
|
|
4393
|
+
}
|
|
4394
|
+
}
|
|
4395
|
+
}
|
|
4396
|
+
|
|
4397
|
+
#endif
|
|
4398
|
+
|
|
4399
|
+
#ifdef JKJ_DRAGONBOX_LEAK_MACROS
|
|
4400
|
+
#define JKJ_DRAGONBOX_MACROS_DEFINED
|
|
4401
|
+
#else
|
|
4402
|
+
#undef JKJ_HAS_BUILTIN
|
|
4403
|
+
#undef JKJ_FORCEINLINE
|
|
4404
|
+
#undef JKJ_SAFEBUFFERS
|
|
4405
|
+
#undef JKJ_CONSTEXPR20
|
|
4406
|
+
#undef JKJ_USE_IS_CONSTANT_EVALUATED
|
|
4407
|
+
#undef JKJ_CAN_BRANCH_ON_CONSTEVAL
|
|
4408
|
+
#undef JKJ_IF_NOT_CONSTEVAL
|
|
4409
|
+
#undef JKJ_IF_CONSTEVAL
|
|
4410
|
+
#undef JKJ_HAS_BIT_CAST
|
|
4411
|
+
#undef JKJ_IF_CONSTEXPR
|
|
4412
|
+
#undef JKJ_HAS_IF_CONSTEXPR
|
|
4413
|
+
#undef JKJ_INLINE_VARIABLE
|
|
4414
|
+
#undef JKJ_HAS_INLINE_VARIABLE
|
|
4415
|
+
#undef JKJ_HAS_CONSTEXPR17
|
|
4416
|
+
#undef JKJ_CONSTEXPR14
|
|
4417
|
+
#undef JKJ_HAS_CONSTEXPR14
|
|
4418
|
+
#undef JKJ_HAS_VARIABLE_TEMPLATES
|
|
4419
|
+
#if JKJ_FAST_MUL64_DEFINED
|
|
4420
|
+
#undef JKJ_FAST_MUL64_DEFINED
|
|
4421
|
+
#else
|
|
4422
|
+
#undef JKJ_FAST_MUL64
|
|
4423
|
+
#endif
|
|
4424
|
+
#if JKJ_STD_REPLACEMENT_NAMESPACE_DEFINED
|
|
4425
|
+
#undef JKJ_STD_REPLACEMENT_NAMESPACE_DEFINED
|
|
4426
|
+
#else
|
|
4427
|
+
#undef JKJ_STD_REPLACEMENT_NAMESPACE
|
|
4428
|
+
#endif
|
|
4429
|
+
#if JKJ_STATIC_DATA_SECTION_DEFINED
|
|
4430
|
+
#undef JKJ_STATIC_DATA_SECTION_DEFINED
|
|
4431
|
+
#else
|
|
4432
|
+
#undef JKJ_STATIC_DATA_SECTION
|
|
4433
|
+
#endif
|
|
4434
|
+
#if JKJ_NAMESPACE_DEFINED
|
|
4435
|
+
#undef JKJ_NAMESPACE_DEFINED
|
|
4436
|
+
#else
|
|
4437
|
+
#undef JKJ_NAMESPACE
|
|
4438
|
+
#endif
|
|
4439
|
+
#undef JKJ_DRAGONBOX_MACROS_DEFINED
|
|
4440
|
+
#endif
|