1//===-- Double-precision log10(x) function --------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "src/math/log10.h"
10#include "src/__support/FPUtil/FEnvImpl.h"
11#include "src/__support/FPUtil/FPBits.h"
12#include "src/__support/FPUtil/PolyEval.h"
13#include "src/__support/FPUtil/double_double.h"
14#include "src/__support/FPUtil/dyadic_float.h"
15#include "src/__support/FPUtil/multiply_add.h"
16#include "src/__support/common.h"
17#include "src/__support/integer_literals.h"
18#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
19
20#include "common_constants.h"
21#include "log_range_reduction.h"
22
23namespace LIBC_NAMESPACE {
24
25// 128-bit precision dyadic floating point numbers.
26using Float128 = typename fputil::DyadicFloat<128>;
27
28using LIBC_NAMESPACE::operator""_u128;
29
30namespace {
31
32constexpr fputil::DoubleDouble LOG10_E = {.lo: 0x1.95355baaafad3p-57,
33 .hi: 0x1.bcb7b1526e50ep-2};
34
35// A simple upper bound for the error of e_x * log(2) - log(r).
36constexpr double HI_ERR = 0x1.0p-85;
37
38// Extra errors from P is from using x^2 to reduce evaluation latency.
39constexpr double P_ERR = 0x1.0p-51;
40
41// log10(2) with 128-bit precision generated by SageMath with:
42// def format_hex(value):
43// l = hex(value)[2:]
44// n = 8
45// x = [l[i:i + n] for i in range(0, len(l), n)]
46// return "0x" + "'".join(x) + "_u128"
47// (s, m, e) = RealField(128)(2).log10().sign_exponent_mantissa();
48// print(format_hex(m));
49constexpr Float128 LOG10_2(Sign::POS, /*exponent=*/-129, /*mantissa=*/
50 0x9a209a84'fbcff798'8f8959ac'0b7c9178_u128);
51
52alignas(64) constexpr LogRR LOG10_TABLE = {
53 // -log10(r) with 128-bit precision generated by SageMath with:
54 //
55 // for i in range(128):
56 // r = 2^-8 * ceil( 2^8 * (1 - 2^(-8)) / (1 + i*2^(-7)) );
57 // s, m, e = RealField(128)(r).log10().sign_mantissa_exponent();
58 // print("{Sign::POS,", e, ", format_hex(m), "},");
59 /* .step_1 = */ {
60 {Sign::POS, 0, 0_u128},
61 {Sign::POS, -136, 0xdf3b5ebb'da7e186b'65af394f'e05eafd3_u128},
62 {Sign::POS, -135, 0xe01d4057'2f029c16'a8fb8d87'b30163b5_u128},
63 {Sign::POS, -134, 0xa8c1263a'c3f57eb3'6bb0170e'5bb5d630_u128},
64 {Sign::POS, -134, 0xe1e841bb'c26204e5'fc2ea6eb'0ea1370e_u128},
65 {Sign::POS, -133, 0x8dc2eb02'274d6ff4'dc8a199a'4bb63382_u128},
66 {Sign::POS, -133, 0xaacde920'361dd054'86b57ea6'10c7db33_u128},
67 {Sign::POS, -133, 0xc81618eb'15421bab'5f034a40'e6a2f09d_u128},
68 {Sign::POS, -133, 0xe59c7e66'c5fedb4b'594a31b2'c5cc891c_u128},
69 {Sign::POS, -133, 0xf477584f'97b654de'221efda5'8221904b_u128},
70 {Sign::POS, -132, 0x892e8219'75106e09'68a0dc47'567691c9_u128},
71 {Sign::POS, -132, 0x9841c66e'17dfe7da'10bc94f4'4d216b49_u128},
72 {Sign::POS, -132, 0x9fd7be33'18306cc5'e303ea7e'23c9d6fb_u128},
73 {Sign::POS, -132, 0xaf1cb35b'f494a8dd'ce697dba'a00d4c7d_u128},
74 {Sign::POS, -132, 0xbe8380a2'fa7eba5a'9c216079'dcf0ea96_u128},
75 {Sign::POS, -132, 0xc643c775'8283a271'75278940'eecfc3a9_u128},
76 {Sign::POS, -132, 0xd5de75ec'27e4fe68'2d3467d2'53e2d1fc_u128},
77 {Sign::POS, -132, 0xddb904e8'f1272a95'ead4055d'cdec7b22_u128},
78 {Sign::POS, -132, 0xed88f6bb'355fa196'e1e0dda0'b3d375a4_u128},
79 {Sign::POS, -132, 0xf57e8281'ade9d92d'38dc40c4'fe11e608_u128},
80 {Sign::POS, -131, 0x82c2941b'b20bbe1f'3bcdcfe7'b23976cd_u128},
81 {Sign::POS, -131, 0x86cb3663'2807cdcd'456350b0'bda452a6_u128},
82 {Sign::POS, -131, 0x8eeaa306'458b760a'78185dcc'37fda01a_u128},
83 {Sign::POS, -131, 0x93018395'12fc1168'307643ad'bbbde1b3_u128},
84 {Sign::POS, -131, 0x9b3dd1d5'50c41443'6c449d40'9f883fe3_u128},
85 {Sign::POS, -131, 0x9f6356aa'03c34389'8ea7b30c'8b4ad886_u128},
86 {Sign::POS, -131, 0xa7bd56cd'de5d76a2'961c6e69'0d8879b4_u128},
87 {Sign::POS, -131, 0xabf1ea3e'1d7bd7cf'042643ce'd81ec14a_u128},
88 {Sign::POS, -131, 0xb02b9af7'4c2f879e'4742fb3d'0b5cdd19_u128},
89 {Sign::POS, -131, 0xb8ae8671'b3d7dd6c'f7e2ab36'f09e9014_u128},
90 {Sign::POS, -131, 0xbcf7dabd'87c01afc'8d3fc634'85e7ff13_u128},
91 {Sign::POS, -131, 0xc1467f69'4d10a581'f3edc493'75fbc5a5_u128},
92 {Sign::POS, -131, 0xc9f3ef07'e1f3fc5e'5fcd7d0c'e937375f_u128},
93 {Sign::POS, -131, 0xce52d50b'94fa253a'58252dad'a9f06111_u128},
94 {Sign::POS, -131, 0xd2b74192'fae43777'62f01e5f'f43708ab_u128},
95 {Sign::POS, -131, 0xd72142a8'4ca85abd'481d9b31'31f52639_u128},
96 {Sign::POS, -131, 0xdb90e68b'8abf14af'b305ced1'419fe924_u128},
97 {Sign::POS, -131, 0xe48150cf'32888b9c'849266a8'5513dc6d_u128},
98 {Sign::POS, -131, 0xe90234c6'5a15e533'080ecf32'66b4dcf4_u128},
99 {Sign::POS, -131, 0xed88f6bb'355fa196'e1e0dda0'b3d375a4_u128},
100 {Sign::POS, -131, 0xf215a60b'6557943f'ce3537a3'a211b25b_u128},
101 {Sign::POS, -131, 0xf6a85251'3757dfbd'5dab6830'7fedefcd_u128},
102 {Sign::POS, -131, 0xffdfe15d'e3c01bac'1be2585c'279c50a5_u128},
103 {Sign::POS, -130, 0x8242724a'155219f3'18aa3021'71017dcb_u128},
104 {Sign::POS, -130, 0x849812d0'ccbb5cbd'abc7e698'502d43c0_u128},
105 {Sign::POS, -130, 0x86f0dab1'ab5822b6'c339089a'51663370_u128},
106 {Sign::POS, -130, 0x894cd27d'9f182c63'26f70b34'ce5cf201_u128},
107 {Sign::POS, -130, 0x8bac02e8'ac3e09ac'676f20a8'7ab433df_u128},
108 {Sign::POS, -130, 0x8e0e74ca'ae062e24'6db4169c'c4b83bc3_u128},
109 {Sign::POS, -130, 0x90743120'1c7f651a'cd3fdb2f'ad0d1fd6_u128},
110 {Sign::POS, -130, 0x92dd410a'd7bfe103'49d03e16'3250d1d4_u128},
111 {Sign::POS, -130, 0x9549add2'f8a3c7e0'9ec7dc02'd5e723b9_u128},
112 {Sign::POS, -130, 0x97b980e7'a743d71c'34698d03'a5442573_u128},
113 {Sign::POS, -130, 0x9a2cc3df'f7548556'0522904d'1e47f3de_u128},
114 {Sign::POS, -130, 0x9ca3807b'ca9fe93f'791a7264'6c87b976_u128},
115 {Sign::POS, -130, 0x9f1dc0a4'b9cea286'3826f190'd655d736_u128},
116 {Sign::POS, -130, 0xa19b8e6f'03b60e45'544ab3e4'8199b299_u128},
117 {Sign::POS, -130, 0xa41cf41a'83643487'be775fa8'2961114e_u128},
118 {Sign::POS, -130, 0xa6a1fc13'ad241953'45798e50'19e6c082_u128},
119 {Sign::POS, -130, 0xa92ab0f4'92b772bd'91fb1ed0'cdc4d1fb_u128},
120 {Sign::POS, -130, 0xabb71d85'ef05380d'818b8b9c'bbd17b72_u128},
121 {Sign::POS, -130, 0xae474cc0'397f0d4f'a50c2fea'60c5b3b2_u128},
122 {Sign::POS, -130, 0xb0db49cc'c1823c8e'58ea3498'0ad8b720_u128},
123 {Sign::POS, -130, 0xb3732006'd1fbbba5'4b5f7194'1be508a4_u128},
124 {Sign::POS, -130, 0xb60edafc'dd99ad1d'9e405fb8'bcb1ff1e_u128},
125 {Sign::POS, -130, 0xb60edafc'dd99ad1d'9e405fb8'bcb1ff1e_u128},
126 {Sign::POS, -130, 0xb8ae8671'b3d7dd6c'f7e2ab36'f09e9014_u128},
127 {Sign::POS, -130, 0xbb522e5d'bf37f63b'c6696396'40c305bb_u128},
128 {Sign::POS, -130, 0xbdf9def0'4cf980ff'a3dc9e46'4e98764b_u128},
129 {Sign::POS, -130, 0xc0a5a490'dea95b5e'ffd3256b'59fa9c59_u128},
130 {Sign::POS, -130, 0xc3558be0'85e3f4bc'b0a2d486'72a051a5_u128},
131 {Sign::POS, -130, 0xc3558be0'85e3f4bc'b0a2d486'72a051a5_u128},
132 {Sign::POS, -130, 0xc609a1bb'4aa98f59'acb2ca5d'4ca1c10e_u128},
133 {Sign::POS, -130, 0xc8c1f339'9ca7d33b'43690b9e'3cde0d02_u128},
134 {Sign::POS, -130, 0xcb7e8db1'cfe04827'18b1fd60'383f7e5a_u128},
135 {Sign::POS, -130, 0xce3f7eb9'a517c969'0248757e'5f45af3d_u128},
136 {Sign::POS, -130, 0xd104d427'de7fbcc4'7c4acd60'5be48bc1_u128},
137 {Sign::POS, -130, 0xd104d427'de7fbcc4'7c4acd60'5be48bc1_u128},
138 {Sign::POS, -130, 0xd3ce9c15'e10ec927'58ff6362'9a92652d_u128},
139 {Sign::POS, -130, 0xd69ce4e1'6303fcdd'6b49be3b'd8c89f10_u128},
140 {Sign::POS, -130, 0xd96fbd2e'2814c9cc'e6dd603a'881e9060_u128},
141 {Sign::POS, -130, 0xd96fbd2e'2814c9cc'e6dd603a'881e9060_u128},
142 {Sign::POS, -130, 0xdc4733e7'cbcbfc8c'89e281c9'8c1d705c_u128},
143 {Sign::POS, -130, 0xdf235843'9aa5dd12'dc0db7cf'0cce9f32_u128},
144 {Sign::POS, -130, 0xe20439c2'7a7c01b8'fdf1c5b8'46db9deb_u128},
145 {Sign::POS, -130, 0xe20439c2'7a7c01b8'fdf1c5b8'46db9deb_u128},
146 {Sign::POS, -130, 0xe4e9e832'e2da0c05'3dd7eab4'8869c402_u128},
147 {Sign::POS, -130, 0xe7d473b2'e5db8f2a'4e8fcc90'0b41daef_u128},
148 {Sign::POS, -130, 0xe7d473b2'e5db8f2a'4e8fcc90'0b41daef_u128},
149 {Sign::POS, -130, 0xeac3ecb2'4a3ac7b4'7593e1a9'e917359a_u128},
150 {Sign::POS, -130, 0xedb863f4'b73f982d'e7741396'b49e1ce5_u128},
151 {Sign::POS, -130, 0xedb863f4'b73f982d'e7741396'b49e1ce5_u128},
152 {Sign::POS, -130, 0xf0b1ea93'f34675a7'c8ba4f8f'47b85a5c_u128},
153 {Sign::POS, -130, 0xf3b09202'359f9787'7007c127'6821b705_u128},
154 {Sign::POS, -130, 0xf3b09202'359f9787'7007c127'6821b705_u128},
155 {Sign::POS, -130, 0xf6b46c0c'8c8fdea1'7ee19afe'6db7e324_u128},
156 {Sign::POS, -130, 0xf9bd8add'584687f0'edf54f37'f6d40420_u128},
157 {Sign::POS, -130, 0xf9bd8add'584687f0'edf54f37'f6d40420_u128},
158 {Sign::POS, -130, 0xfccc00fe'dba4e6fb'efe52ccf'03e7dee1_u128},
159 {Sign::POS, -130, 0xffdfe15d'e3c01bac'1be2585c'279c50a5_u128},
160 {Sign::POS, -130, 0xffdfe15d'e3c01bac'1be2585c'279c50a5_u128},
161 {Sign::POS, -129, 0x817c9fa6'43880404'e0b571f5'c91b0446_u128},
162 {Sign::POS, -129, 0x830c1742'7ea55eca'7178594b'ef2def59_u128},
163 {Sign::POS, -129, 0x830c1742'7ea55eca'7178594b'ef2def59_u128},
164 {Sign::POS, -129, 0x849e6196'487c1d1c'9a741bb1'71158d2a_u128},
165 {Sign::POS, -129, 0x849e6196'487c1d1c'9a741bb1'71158d2a_u128},
166 {Sign::POS, -129, 0x863388eb'55ebd295'1a618264'446cb495_u128},
167 {Sign::POS, -129, 0x87cb97c3'ff9eac18'71dbdbbe'c51d7657_u128},
168 {Sign::POS, -129, 0x87cb97c3'ff9eac18'71dbdbbe'c51d7657_u128},
169 {Sign::POS, -129, 0x896698dc'e4cff76c'abe0b522'230f7d14_u128},
170 {Sign::POS, -129, 0x896698dc'e4cff76c'abe0b522'230f7d14_u128},
171 {Sign::POS, -129, 0x8b04972e'9d4d3011'd28e8ada'fea703b4_u128},
172 {Sign::POS, -129, 0x8ca59def'7b5cefc5'208422d8'3be34b27_u128},
173 {Sign::POS, -129, 0x8ca59def'7b5cefc5'208422d8'3be34b27_u128},
174 {Sign::POS, -129, 0x8e49b895'5e3ffb8a'c385cf49'402af0e4_u128},
175 {Sign::POS, -129, 0x8e49b895'5e3ffb8a'c385cf49'402af0e4_u128},
176 {Sign::POS, -129, 0x8ff0f2d7'960a075c'da982a61'4e12c6dd_u128},
177 {Sign::POS, -129, 0x8ff0f2d7'960a075c'da982a61'4e12c6dd_u128},
178 {Sign::POS, -129, 0x919b58b0'd999bbc8'038401fc'1c1b5c2c_u128},
179 {Sign::POS, -129, 0x919b58b0'd999bbc8'038401fc'1c1b5c2c_u128},
180 {Sign::POS, -129, 0x9348f661'4f821394'a9b55d3f'16da746a_u128},
181 {Sign::POS, -129, 0x9348f661'4f821394'a9b55d3f'16da746a_u128},
182 {Sign::POS, -129, 0x94f9d870'aac256a5'088d2d14'73d4f7f5_u128},
183 {Sign::POS, -129, 0x94f9d870'aac256a5'088d2d14'73d4f7f5_u128},
184 {Sign::POS, -129, 0x96ae0bb0'5c35d5bd'7c1e117d'ea19e9e6_u128},
185 {Sign::POS, -129, 0x96ae0bb0'5c35d5bd'7c1e117d'ea19e9e6_u128},
186 {Sign::POS, -129, 0x98659d3d'd9b12532'336db063'0f536fb9_u128},
187 {Sign::POS, 0, 0_u128},
188 },
189 // -log10(r) for the second step, generated by SageMath with:
190 //
191 // for i in range(-2^6, 2^7 + 1):
192 // r = 2^-16 * round( 2^16 / (1 + i*2^(-14)) );
193 // s, m, e = RealField(128)(r).log10().sign_mantissa_exponent();
194 // print("{Sign::POS," if s == -1 else "{Sign::NEG,", e, ",
195 // format_hex(m), "},");
196 /* .step_2 = */
197 {
198 {Sign::NEG, -137, 0xdeca7290'13cd7c31'7f1ce002'fa34131b_u128},
199 {Sign::NEG, -137, 0xdb5475b4'4946d986'639afa08'5dd8b4c7_u128},
200 {Sign::NEG, -137, 0xd7de6b0e'10cab7d2'05512632'fe9a58cb_u128},
201 {Sign::NEG, -137, 0xd468529c'fc6fb395'b5380a99'53117d07_u128},
202 {Sign::NEG, -137, 0xd0f22c60'9e474741'70af2d7d'53be1f31_u128},
203 {Sign::NEG, -137, 0xcd7bf858'885dcae2'0ccd499c'49b74cc2_u128},
204 {Sign::NEG, -137, 0xca05b684'4cba73cf'5b51ddc3'987ebfb8_u128},
205 {Sign::NEG, -137, 0xc68f66e3'7d5f545a'49375f51'89b3782b_u128},
206 {Sign::NEG, -137, 0xc3190975'ac495b7a'f6e57738'865c712f_u128},
207 {Sign::NEG, -137, 0xbfa29e3a'6b70547e'ca02b10a'8c712acd_u128},
208 {Sign::NEG, -137, 0xbc2c2531'4cc6e6b6'78e50382'10208151_u128},
209 {Sign::NEG, -137, 0xb8b59e59'e23a9524'0fa099ec'd71ee0ea_u128},
210 {Sign::NEG, -137, 0xb53f09b3'bdb3be28'eeb445cc'b8fb09ed_u128},
211 {Sign::NEG, -137, 0xb1c8673e'71159b33'c352fff1'8a1c02fb_u128},
212 {Sign::NEG, -137, 0xae51b6f9'8e3e406e'7949e03e'cf9b390b_u128},
213 {Sign::NEG, -137, 0xaadaf8e4'a7069c6c'2681f33f'30aadedc_u128},
214 {Sign::NEG, -137, 0xa7642cff'4d4277d6'f01d5496'eea213b3_u128},
215 {Sign::NEG, -137, 0xa3ed5349'12c0751d'e92ef555'ff1de975_u128},
216 {Sign::NEG, -137, 0xa0766bc1'894a1022'eb0c7519'b3e7c1e0_u128},
217 {Sign::NEG, -137, 0x9c21b6e9'1e7f03a3'f60d204f'f0fe5296_u128},
218 {Sign::NEG, -137, 0x98aab049'1050bea8'125c19a4'f057c18b_u128},
219 {Sign::NEG, -137, 0x95339bd6'4cd953e7'7e9383ce'1bdf9575_u128},
220 {Sign::NEG, -137, 0x91bc7990'65cc57d6'bf274f4d'8f770253_u128},
221 {Sign::NEG, -137, 0x8e454976'ecd836ad'656bd9b7'58fe44ba_u128},
222 {Sign::NEG, -137, 0x8ace0b89'73a63413'bfdd2c7f'388fc014_u128},
223 {Sign::NEG, -137, 0x8756bfc7'8bda6ad0'83fbf6ed'936c493a_u128},
224 {Sign::NEG, -137, 0x83df6630'c713cc76'71bfa9a1'8bec01cc_u128},
225 {Sign::NEG, -137, 0x8067fec4'b6ec2111'f09d19f5'6dbfef72_u128},
226 {Sign::NEG, -138, 0xf9e11305'd9f00dad'4c422713'b1642228_u128},
227 {Sign::NEG, -138, 0xf2f20cd5'f58de39a'0c3c7c56'99b7a0a4_u128},
228 {Sign::NEG, -138, 0xec02eaf8'e3c656ff'b8db7c69'e3fa0797_u128},
229 {Sign::NEG, -138, 0xe513ad6d'c7a3a553'a083eb05'506ff7ed_u128},
230 {Sign::NEG, -138, 0xde245433'c425b5c5'c21595e7'45f1fa15_u128},
231 {Sign::NEG, -138, 0xd734df49'fc42189b'b9d5bcdb'fe719389_u128},
232 {Sign::NEG, -138, 0xd0454eaf'92e4068b'a17a1e85'e93461f4_u128},
233 {Sign::NEG, -138, 0xc955a263'aaec6016'e3537584'da333fda_u128},
234 {Sign::NEG, -138, 0xc265da65'6731ace5'00963177'f24682c2_u128},
235 {Sign::NEG, -138, 0xbb75f6b3'ea801b1e'4ac03734'7bcfc50e_u128},
236 {Sign::NEG, -138, 0xb485f74e'57997ec6'901a736a'4364cdfd_u128},
237 {Sign::NEG, -138, 0xad95dc33'd1355117'bb550acc'3b9d7247_u128},
238 {Sign::NEG, -138, 0xa6a5a563'7a00afdc'663cf2b2'7e8f1ffb_u128},
239 {Sign::NEG, -138, 0x9fb552dc'749e5cca'5f89bd08'feb39952_u128},
240 {Sign::NEG, -138, 0x98c4e49d'e3a6bcdd'23c2623c'73f494db_u128},
241 {Sign::NEG, -138, 0x91d45aa6'e9a7d7b0'4937d3b5'485af61e_u128},
242 {Sign::NEG, -138, 0x8ae3b4f6'a92556d9'df14214e'7a6d8111_u128},
243 {Sign::NEG, -138, 0x83f2f38c'44988544'bf7cfc14'999fb4bc_u128},
244 {Sign::NEG, -139, 0xfa042ccd'bce09d15'a990c0ee'569a8d51_u128},
245 {Sign::NEG, -139, 0xec223b0b'32227c9e'a38463e9'd941e1c2_u128},
246 {Sign::NEG, -139, 0xde4011cf'2daaff31'ba032453'0edaa03f_u128},
247 {Sign::NEG, -139, 0xd05db117'f419b857'5e997a02'dad7ace7_u128},
248 {Sign::NEG, -139, 0xc27b18e3'c9f977c7'4a14676d'4d0f817e_u128},
249 {Sign::NEG, -139, 0xb4984930'f3c0481c'857c002e'e7a1e473_u128},
250 {Sign::NEG, -139, 0xa6b541fd'b5cf6d89'5923b2eb'72d8012a_u128},
251 {Sign::NEG, -139, 0x98d20348'5473648b'21cde8f8'5ca1f9fd_u128},
252 {Sign::NEG, -139, 0x8aee8d0f'13e3e09e'0be08e08'b1d212d4_u128},
253 {Sign::NEG, -140, 0xfa15bea0'708795e1'69502399'8e6bd7b0_u128},
254 {Sign::NEG, -140, 0xde4df414'0b42822f'634cea67'50617a92_u128},
255 {Sign::NEG, -140, 0xc285ba75'7feb2781'fbd7e970'aef9dbb8_u128},
256 {Sign::NEG, -140, 0xa6bd11c1'564a8ace'9aedc1c1'ba7d0695_u128},
257 {Sign::NEG, -140, 0x8af3f9f4'1600120a'8d306ba2'07233c44_u128},
258 {Sign::NEG, -141, 0xde54e614'8d030322'856a0a3a'00fcf3c1_u128},
259 {Sign::NEG, -141, 0xa6c0fa00'de35f314'b3a2c140'7cf6d38d_u128},
260 {Sign::NEG, -142, 0xde585f4c'5bbbcd3d'd791cf6a'70c3a504_u128},
261 {Sign::NEG, -143, 0xde5a1bf6'27b1f68f'10a633f2'c4a8ea22_u128},
262 {Sign::NEG, 0, 0_u128},
263 {Sign::POS, -143, 0xde5d9565'8a729eab'ed4a68e5'e6e83ddf_u128},
264 {Sign::POS, -142, 0xde5f522b'21e3e25a'3281f187'2cdbee94_u128},
265 {Sign::POS, -141, 0xa6c8cb3b'7e5bbbfd'f1466eda'a96e356e_u128},
266 {Sign::POS, -141, 0xde62cbd2'1e895473'8a607fd6'95dfc3d9_u128},
267 {Sign::POS, -140, 0x8afed570'32bebc7c'c36b8713'ceefe2de_u128},
268 {Sign::POS, -140, 0xa6ccb436'a3c72fa4'5c2e76c9'53e3e3e6_u128},
269 {Sign::POS, -140, 0xc29b023f'dcb2dccf'8e4950fa'5c943bbf_u128},
270 {Sign::POS, -140, 0xde69bf8f'58005dfc'20fa8a73'c585f634_u128},
271 {Sign::POS, -140, 0xfa38ec28'905810a3'0aa106d9'b0a9717a_u128},
272 {Sign::POS, -139, 0x8b044407'80460c2a'85d70e03'2de41aec_u128},
273 {Sign::POS, -139, 0x98ec49a3'11cc30ab'beee21cb'b82a9a78_u128},
274 {Sign::POS, -139, 0xa6d486e8'ba5151a0'abd7b0fd'd8efe6f6_u128},
275 {Sign::POS, -139, 0xb4bcfbda'377d31cc'3221c56e'2c1aa912_u128},
276 {Sign::POS, -139, 0xc2a5a879'470c7c37'57b795a3'6d9c5f19_u128},
277 {Sign::POS, -139, 0xd08e8cc7'a6d0c580'131ec142'c053ac3b_u128},
278 {Sign::POS, -139, 0xde77a8c7'14b08d28'35e3298f'4bb2aa0a_u128},
279 {Sign::POS, -139, 0xec60fc79'4ea73ee4'7133dafd'fc44f160_u128},
280 {Sign::POS, -139, 0xfa4a87e0'12c533eb'74b37d23'121c59d5_u128},
281 {Sign::POS, -138, 0x841a257e'8f97da22'93bf5f42'07da8a4c_u128},
282 {Sign::POS, -138, 0x8b0f22e9'19107c0c'fdb5990e'c6057f4e_u128},
283 {Sign::POS, -138, 0x92043c30'84f41481'2d408a58'b1b202fe_u128},
284 {Sign::POS, -138, 0x98f97155'b274b1ab'1759381b'61dfbf01_u128},
285 {Sign::POS, -138, 0x9feec259'80cedbbe'41e90a05'4df4b9f1_u128},
286 {Sign::POS, -138, 0xa6e42f3c'cf49959d'a1e66c62'03725d50_u128},
287 {Sign::POS, -138, 0xadd9b800'7d365d83'8693d36a'b45bd7ce_u128},
288 {Sign::POS, -138, 0xb4cf5ca5'69f12da9'91e25bb4'0ad3f098_u128},
289 {Sign::POS, -138, 0xbbc51d2c'74e07cf0'bdf94392'c4cc7f6c_u128},
290 {Sign::POS, -138, 0xc2baf996'7d753f89'6fe37973'354a82f9_u128},
291 {Sign::POS, -138, 0xc9b0f1e4'632ae79b'97647b42'67bfd801_u128},
292 {Sign::POS, -138, 0xd0a70617'058765ee'dbf5c32a'454f7bdf_u128},
293 {Sign::POS, -138, 0xd79d362f'441b2a92'd6edfe04'c37ba916_u128},
294 {Sign::POS, -138, 0xde93822d'fe812587'5ad3480c'cfbe9890_u128},
295 {Sign::POS, -138, 0xe589ea14'145ec764'c7d9ac76'5be7e325_u128},
296 {Sign::POS, -138, 0xec806de2'65640204'6d8f24b9'a3ca011b_u128},
297 {Sign::POS, -138, 0xf3770d99'd14b4928'f9b65480'7dcdd5b2_u128},
298 {Sign::POS, -138, 0xfa6dc93b'37d99326'f4513f47'45663028_u128},
299 {Sign::POS, -137, 0x80b25063'bc6f2cc6'a46e9a72'd80da75f_u128},
300 {Sign::POS, -137, 0x842dca1f'ba19cce6'ee60992b'51ffac4b_u128},
301 {Sign::POS, -137, 0x87a951d2'04deeaf3'1977fa1c'786886b3_u128},
302 {Sign::POS, -137, 0x8b24e77b'0cb60a84'0e5f7c52'cdf119d5_u128},
303 {Sign::POS, -137, 0x8ea08b1b'419bf221'3bf9d70d'a1021a10_u128},
304 {Sign::POS, -137, 0x921c3cb3'1392ab94'fd0406b0'7523b8e6_u128},
305 {Sign::POS, -137, 0x9597fc42'f2a18441'0453ee32'c020f2a8_u128},
306 {Sign::POS, -137, 0x9913c9cb'4ed50d72'cfb3ec22'066bf7f6_u128},
307 {Sign::POS, -137, 0x9c8fa54c'983f1cb8'215c025b'd493ecf9_u128},
308 {Sign::POS, -137, 0x9f2c9319'2e68232b'39c116b7'ee3a83ec_u128},
309 {Sign::POS, -137, 0xa2a8870f'24ac5f66'f41f4b3e'de2782f0_u128},
310 {Sign::POS, -137, 0xa62488ff'3c735799'61196927'723eb75c_u128},
311 {Sign::POS, -137, 0xa9a098e9'e5e2a432'0e615e83'6cb1edab_u128},
312 {Sign::POS, -137, 0xad1cb6cf'91252372'6981331c'5fc71cfc_u128},
313 {Sign::POS, -137, 0xb098e2b0'ae6af9c2'5f6a4faa'054f11fa_u128},
314 {Sign::POS, -137, 0xb4151c8d'ade99205'02a68bc6'81a74c28_u128},
315 {Sign::POS, -137, 0xb7916466'ffdb9ded'382ba24d'90566403_u128},
316 {Sign::POS, -137, 0xbb0dba3d'14811652'6ad1abe5'1dd22e00_u128},
317 {Sign::POS, -137, 0xbe8a1e10'5c1f3b85'456d3f7f'59b13960_u128},
318 {Sign::POS, -137, 0xc2068fe1'470095a4'738dd8b7'd66e9058_u128},
319 {Sign::POS, -137, 0xc5830fb0'4574f4f1'68e123fe'd7ff11c6_u128},
320 {Sign::POS, -137, 0xc8ff9d7d'c7d17225'2f3bd097'80c3aa11_u128},
321 {Sign::POS, -137, 0xcc7c394a'3e706ec5'3b48887f'1ce36935_u128},
322 {Sign::POS, -137, 0xcff8e316'19b19578'47ddae65'5ecc4633_u128},
323 {Sign::POS, -137, 0xd3759ae1'c9f9da5b'37fa81ee'f4819c88_u128},
324 {Sign::POS, -137, 0xd6f260ad'bfb37b55'ff6c4a8d'747c65ed_u128},
325 {Sign::POS, -137, 0xda6f347a'6b4e0070'921c2949'3a33318c_u128},
326 {Sign::POS, -137, 0xddec1648'3d3e3c27'da0631eb'65e731d8_u128},
327 {Sign::POS, -137, 0xe1690617'a5fe4bc2'b3da6c07'd110babc_u128},
328 {Sign::POS, -137, 0xe4e603e9'160d97a6'f2485c78'68b8835a_u128},
329 {Sign::POS, -137, 0xe8630fbc'fdf0d3ae'67f5b7ed'01344055_u128},
330 {Sign::POS, -137, 0xebe02993'ce31ff7b'f820df44'5b1d0622_u128},
331 {Sign::POS, -137, 0xef5d516d'f76066d0'adefc674'b7eca5cd_u128},
332 {Sign::POS, -137, 0xf2da874b'ea10a1e0'da6be6dc'057d3235_u128},
333 {Sign::POS, -137, 0xf657cb2e'16dc95a9'392bdde1'52ab5ff5_u128},
334 {Sign::POS, -137, 0xf9d51d14'ee637444'1bab58e2'ec99cf73_u128},
335 {Sign::POS, -137, 0xfd527d00'e149bd3e'9b51ef7e'3388d692_u128},
336 {Sign::POS, -136, 0x8067f579'301c9ef6'e914c6a7'f3f22fa2_u128},
337 {Sign::POS, -136, 0x8226b374'edf088e2'0d22862e'b2081c94_u128},
338 {Sign::POS, -136, 0x83e57873'e27ad153'29ebd0b4'76cd8fd8_u128},
339 {Sign::POS, -136, 0x85a44476'461854a0'98feddc2'806d01ed_u128},
340 {Sign::POS, -136, 0x8763177c'512896af'471bfc26'1a401854_u128},
341 {Sign::POS, -136, 0x88b23a5b'61430a16'b6f89c19'b4cd1acd_u128},
342 {Sign::POS, -136, 0x8a7119a8'5909ebe9'b39aaf34'163fb099_u128},
343 {Sign::POS, -136, 0x8c2ffff9'9357e887'1665f0f8'21541c36_u128},
344 {Sign::POS, -136, 0x8deeed4f'489679a6'a5051754'e049c1cb_u128},
345 {Sign::POS, -136, 0x8fade1a9'b131c159'8c5a9a1c'57b2e986_u128},
346 {Sign::POS, -136, 0x916cdd09'05988a35'1d844843'8a26a9ae_u128},
347 {Sign::POS, -136, 0x932bdf6d'7e3c477d'8e3a0913'ecd2fd02_u128},
348 {Sign::POS, -136, 0x94eae8d7'53911550'bc881a45'f47f1d36_u128},
349 {Sign::POS, -136, 0x96a9f946'be0db8d0'f5e51c05'499b06d0_u128},
350 {Sign::POS, -136, 0x986910bb'f62ba04f'c1a43be8'1a243fde_u128},
351 {Sign::POS, -136, 0x9a282f37'3466e378'aec3cfeb'e971beb7_u128},
352 {Sign::POS, -136, 0x9be754b8'b13e437c'2518b293'28614989_u128},
353 {Sign::POS, -136, 0x9da68140'a5332b3a'39d6b147'cbe803a4_u128},
354 {Sign::POS, -136, 0x9f65b4cf'48c9af6d'87765e30'04ae428d_u128},
355 {Sign::POS, -136, 0xa124ef64'd4888ed6'08f896ab'28245bac_u128},
356 {Sign::POS, -136, 0xa2e43101'80f93263'f8880fb5'ca630c87_u128},
357 {Sign::POS, -136, 0xa4a379a5'86a7ad62'b179397c'f82e935c_u128},
358 {Sign::POS, -136, 0xa662c951'1e22bda3'95a8cb71'7197ad81_u128},
359 {Sign::POS, -136, 0xa8222004'7ffbcba8'f6394a34'b7f9a4a4_u128},
360 {Sign::POS, -136, 0xa9e17dbf'e4c6ead0'ffafd8c2'b57884e8_u128},
361 {Sign::POS, -136, 0xaba0e283'851ad980'a970a643'b8a6ac2b_u128},
362 {Sign::POS, -136, 0xad604e4f'9991014e'a89b49fb'749d47e0_u128},
363 {Sign::POS, -136, 0xaf1fc124'5ac5772e'66475ed2'ac983305_u128},
364 {Sign::POS, -136, 0xb06f5be1'bf1918e7'b4fd6209'364bb36f_u128},
365 {Sign::POS, -136, 0xb22edb06'36da31d6'8b5ce79b'0965962a_u128},
366 {Sign::POS, -136, 0xb3ee6133'f7149769'6724232b'07396427_u128},
367 {Sign::POS, -136, 0xb5adee6b'386e62ae'2f02b14d'cad8a49c_u128},
368 {Sign::POS, -136, 0xb76d82ac'339058db'bd6443a8'1f792e07_u128},
369 {Sign::POS, -136, 0xb92d1df7'2125eb7c'ea1cd962'5749939a_u128},
370 {Sign::POS, -136, 0xbaecc04c'39dd389b'97775e31'42198913_u128},
371 {Sign::POS, -136, 0xbcac69ab'b6670aeb'c2a701b8'09a2bc39_u128},
372 {Sign::POS, -136, 0xbe6c1a15'cf76d9f6'979b990f'39e662e3_u128},
373 {Sign::POS, -136, 0xc02bd18a'bdc2ca45'88395c46'3ddd82b2_u128},
374 {Sign::POS, -136, 0xc1eb900a'ba03ad8d'66f451bd'9ba5ed05_u128},
375 {Sign::POS, -136, 0xc3ab5595'fcf502d9'84cfb941'3f6437a6_u128},
376 {Sign::POS, -136, 0xc56b222c'bf54f6b6'd2c1c8d3'2943ca42_u128},
377 {Sign::POS, -136, 0xc72af5cf'39e4635f'067c0d1f'd95192e6_u128},
378 {Sign::POS, -136, 0xc8ead07d'a566d0e3'c298bf9e'db6441f2_u128},
379 {Sign::POS, -136, 0xcaaab238'3aa27559'c22d646a'ddde3910_u128},
380 {Sign::POS, -136, 0xcc6a9aff'32603504'07c301e5'c7d1ca40_u128},
381 {Sign::POS, -136, 0xce2a8ad2'c56ba27f'0fb44446'4df02505_u128},
382 {Sign::POS, -136, 0xcfea81b3'2c92feec'05f1df35'91ae898f_u128},
383 {Sign::POS, -136, 0xd13a7f7c'07506f7d'b43caf8e'7b891066_u128},
384 {Sign::POS, -136, 0xd2fa82b3'6a610c4f'597fb13f'0d0fdf19_u128},
385 {Sign::POS, -136, 0xd4ba8cf8'3dd2a06b'3c21f1c6'0a60b0d6_u128},
386 {Sign::POS, -136, 0xd67a9e4a'ba7d7ce5'2b745590'9a0428a4_u128},
387 {Sign::POS, -136, 0xd83ab6ab'193ca223'1438b605'73d2da10_u128},
388 {Sign::POS, -136, 0xd9fad619'92edc008'49f86400'c5ab2b11_u128},
389 {Sign::POS, -136, 0xdbbafc96'60713620'd3c313d1'48a23c35_u128},
390 {Sign::POS, -136, 0xdd7b2a21'baaa13cc'bc568523'55e0f0d5_u128},
391 },
392 // -log10(r) for the third step, generated by SageMath with:
393 //
394 // for i in range(-80, 81):
395 // r = 2^-21 * round( 2^21 / (1 + i*2^(-21)) );
396 // s, m, e = RealField(128)(r).log10().sign_mantissa_exponent();
397 // print("{Sign::POS," if (s == -1) else "{Sign::NEG,", e, "," ,
398 // format_hex(m), "},");
399 /* .step_3 = */
400 {
401 {Sign::NEG, -143, 0x8af8b9b3'22ba8c7d'54d7e498'98ca0093_u128},
402 {Sign::NEG, -143, 0x893c0652'9deffc3d'c321bbf1'6665f29c_u128},
403 {Sign::NEG, -143, 0x877f52e4'33ac7ec4'8246df71'40c3e4ae_u128},
404 {Sign::NEG, -143, 0x85c29f67'e3ef35bc'1deaa9e8'5780e4c1_u128},
405 {Sign::NEG, -143, 0x8405ebdd'aeb742cf'0cd8a512'1a9162d0_u128},
406 {Sign::NEG, -143, 0x82493845'9403c7a7'b10486fa'4644308d_u128},
407 {Sign::NEG, -143, 0x808c849f'93d3e5f0'578a2f61'eedd4be8_u128},
408 {Sign::NEG, -144, 0xfd9fa1d7'5c4d7ea6'715b4a49'1790e8a7_u128},
409 {Sign::NEG, -144, 0xfa263a53'c5f6eaf4'efb6273a'04c71573_u128},
410 {Sign::NEG, -144, 0xf6acd2b4'64a25420'474d9015'60c17807_u128},
411 {Sign::NEG, -144, 0xf3336af9'384dfd7c'6b9a5dec'eb80ec57_u128},
412 {Sign::NEG, -144, 0xefba0322'40f82a5d'2665a32f'7cc64f79_u128},
413 {Sign::NEG, -144, 0xec409b2f'7e9f1e16'17c8a673'16659363_u128},
414 {Sign::NEG, -144, 0xe8c73320'f1411bfa'b62cdd3e'f5c8673d_u128},
415 {Sign::NEG, -144, 0xe54dcaf6'98dc675e'4e4be6d5'a4a07422_u128},
416 {Sign::NEG, -144, 0xe1d462b0'756f4394'032f86ff'08c92e22_u128},
417 {Sign::NEG, -144, 0xde5afa4e'86f7f3ee'ce31a0d2'7359396f_u128},
418 {Sign::NEG, -144, 0xdae191d0'cd74bbc1'7efc3180'aee36373_u128},
419 {Sign::NEG, -144, 0xd7682937'48e3de5e'bb894b1e'0ce72fc4_u128},
420 {Sign::NEG, -144, 0xd3eec081'f9439f19'00230f6c'7270f8be_u128},
421 {Sign::NEG, -144, 0xd07557b0'de924142'9f63aaa5'63e9a399_u128},
422 {Sign::NEG, -144, 0xccfbeec3'f8ce082d'c2354e44'1015e7eb_u128},
423 {Sign::NEG, -144, 0xc98285bb'47f5372c'67d22bcf'5a452a4c_u128},
424 {Sign::NEG, -144, 0xc6091c96'cc061190'65c46fa3'e3afea18_u128},
425 {Sign::NEG, -144, 0xc28fb356'84fedaab'67e63bbe'1405c20d_u128},
426 {Sign::NEG, -144, 0xbf1649fa'72ddd5ce'f061a284'212afbad_u128},
427 {Sign::NEG, -144, 0xbb9ce082'95a1464c'57b0a190'1625b539_u128},
428 {Sign::NEG, -144, 0xb82376ee'ed476f74'cc9d1c79'd93a9a1e_u128},
429 {Sign::NEG, -144, 0xb4aa0d3f'79ce9499'5440d7a1'31392da8_u128},
430 {Sign::NEG, -144, 0xb130a374'3b34f90a'ca0572f7'c9f7a7de_u128},
431 {Sign::NEG, -144, 0xadb7398d'3178e019'dfa464cb'37fe6455_u128},
432 {Sign::NEG, -144, 0xaa3dcf8a'5c988d17'1d26f48e'fb62e2e0_u128},
433 {Sign::NEG, -144, 0xa6c4656b'bc924352'e0e635a6'81d259e2_u128},
434 {Sign::NEG, -144, 0xa34afb31'5164461d'5f8b022f'27cbda35_u128},
435 {Sign::NEG, -144, 0x9fd190db'1b0cd8c6'a40df5ca'390a0465_u128},
436 {Sign::NEG, -144, 0x9c582669'198a3e9e'8fb76866'f01c4f2d_u128},
437 {Sign::NEG, -144, 0x98debbdb'4cdabaf4'da1f690c'752fdeff_u128},
438 {Sign::NEG, -144, 0x95655131'b4fc9119'112db8a3'dc07ee78_u128},
439 {Sign::NEG, -144, 0x91ebe66c'51ee045a'9919c4c2'2125c79e_u128},
440 {Sign::NEG, -144, 0x8e727b8b'23ad5808'ac6aa272'26204db3_u128},
441 {Sign::NEG, -144, 0x8af9108e'2a38cf72'5bf708fe'ad2b1780_u128},
442 {Sign::NEG, -144, 0x877fa575'658eade6'8ee54cbc'53cd19ed_u128},
443 {Sign::NEG, -144, 0x84063a40'd5ad36b4'02ab59d3'8cc6e2c5_u128},
444 {Sign::NEG, -144, 0x808ccef0'7a92ad29'4b0eaf0a'99286378_u128},
445 {Sign::NEG, -145, 0xfa26c708'a87aa929'a448b11f'012c975c_u128},
446 {Sign::NEG, -145, 0xf333eff8'c556e089'b0a1d584'117de73b_u128},
447 {Sign::NEG, -145, 0xec4118b1'4bb6870e'e890f9fb'57fdabb6_u128},
448 {Sign::NEG, -145, 0xe54e4132'3b962355'261d48c7'1e693130_u128},
449 {Sign::NEG, -145, 0xde5b697b'94f23bf7'efecdd48'ed894c32_u128},
450 {Sign::NEG, -145, 0xd768918d'57c75792'7944b995'7598a88a_u128},
451 {Sign::NEG, -145, 0xd075b967'8411fcbf'a208bc08'75093645_u128},
452 {Sign::NEG, -145, 0xc982e10a'19ceb219'f6bb94d8'9da8b432_u128},
453 {Sign::NEG, -145, 0xc2900875'18f9fe3b'b07ebbab'782457b0_u128},
454 {Sign::NEG, -145, 0xbb9d2fa8'819067be'b5126529'45eb9165_u128},
455 {Sign::NEG, -145, 0xb4aa56a4'538e753c'96d57890'e171eea5_u128},
456 {Sign::NEG, -145, 0xadb77d68'8ef0ad4e'94c5854b'9cd01726_u128},
457 {Sign::NEG, -145, 0xa6c4a3f5'33b3968d'9a7eb881'1ec3e6bb_u128},
458 {Sign::NEG, -145, 0x9fd1ca4a'41d3b792'403bd2ab'3e0fa2d7_u128},
459 {Sign::NEG, -145, 0x98def067'b94d96f4'cad61d29'db384b6b_u128},
460 {Sign::NEG, -145, 0x91ec164d'9a1dbb4d'2bc55fd6'b8a306ec_u128},
461 {Sign::NEG, -145, 0x8af93bfb'e440ab33'011fd699'5111a927_u128},
462 {Sign::NEG, -145, 0x84066172'97b2ed3d'959a26fa'ac7e5494_u128},
463 {Sign::NEG, -146, 0xfa270d63'68e21007'c10eab72'66ac6bc0_u128},
464 {Sign::NEG, -146, 0xec415772'74ef0439'0bb178b9'0026b2b2_u128},
465 {Sign::NEG, -146, 0xde5ba112'5385c43b'ac3bfd92'5e6b33e1_u128},
466 {Sign::NEG, -146, 0xd075ea43'049f5d3b'9d0a01a9'5b355319_u128},
467 {Sign::NEG, -146, 0xc2903304'8834dc64'31b3b7b2'0a6a6496_u128},
468 {Sign::NEG, -146, 0xb4aa7b56'de3f4ee0'170da891'504620f4_u128},
469 {Sign::NEG, -146, 0xa6c4c33a'06b7c1d9'53289e84'744549cb_u128},
470 {Sign::NEG, -146, 0x98df0aae'01974279'45519048'b0ce7e7f_u128},
471 {Sign::NEG, -146, 0x8af951b2'ced6dde8'a6118c42'bf99407e_u128},
472 {Sign::NEG, -147, 0xfa273090'dcdf429f'0e5b474c'c5a64cf6_u128},
473 {Sign::NEG, -147, 0xde5bbcdd'c0b533aa'a74dab3b'd6067bc7_u128},
474 {Sign::NEG, -147, 0xc290484c'4921a941'9f73f4e3'7357341b_u128},
475 {Sign::NEG, -147, 0xa6c4d2dc'7616bdb0'31bf5d5f'815220e7_u128},
476 {Sign::NEG, -147, 0x8af95c8e'47868b41'4b987ca5'fca242d7_u128},
477 {Sign::NEG, -148, 0xde5bcac3'7ac6587d'19be3fab'd93832c5_u128},
478 {Sign::NEG, -148, 0xa6c4daad'af3d75e0'8fd43f0c'9ce444d3_u128},
479 {Sign::NEG, -149, 0xde5bd1b6'58ad4676'061cd853'e796bc2c_u128},
480 {Sign::NEG, -150, 0xde5bd52f'c7d8545f'87d6afab'fba0644f_u128},
481 {Sign::POS, 0, 0_u128},
482 {Sign::POS, -150, 0xde5bdc22'a69d9e19'a9bf3200'1043629d_u128},
483 {Sign::POS, -149, 0xde5bdf9c'1637d9ef'8014f0f3'60272d82_u128},
484 {Sign::POS, -148, 0xa6c4ea50'24795bd2'fe94a02f'c639c0e3_u128},
485 {Sign::POS, -148, 0xde5be68e'f5db7f99'bee710a5'ace7c8d4_u128},
486 {Sign::POS, -147, 0x8af97245'3faf11e8'1a778d81'00437e4f_u128},
487 {Sign::POS, -147, 0xa6c4f221'608e89fe'97d773f8'992f7051_u128},
488 {Sign::POS, -147, 0xc29072db'dd9a0dd5'0c9ee584'1a3afa95_u128},
489 {Sign::POS, -147, 0xde5bf474'b6df8331'7b644b13'993cf4ef_u128},
490 {Sign::POS, -147, 0xfa2776eb'ec6ccfdb'3448f66e'2bd7a0ca_u128},
491 {Sign::POS, -146, 0x8af97d20'bf27eccd'6a7ca5f1'a87a1a3c_u128},
492 {Sign::POS, -146, 0x98df3f3a'b64b431d'245675fe'3061108f_u128},
493 {Sign::POS, -146, 0xa6c501c3'dba75dc2'64136e97'019d0a3b_u128},
494 {Sign::POS, -146, 0xb4aac4bc'2f432fa3'6cdadac4'd6925bd4_u128},
495 {Sign::POS, -146, 0xc2908823'b125aba7'2899e237'91d29632_u128},
496 {Sign::POS, -146, 0xd0764bfa'6155c4b5'28039e1f'0323a4c1_u128},
497 {Sign::POS, -146, 0xde5c1040'3fda6db5'a2912e03'afc8cc28_u128},
498 {Sign::POS, -146, 0xec41d4f5'4cba9991'7681cc9f'9e0d89f9_u128},
499 {Sign::POS, -146, 0xfa279a19'87fd3b32'28dae4b7'241255e1_u128},
500 {Sign::POS, -145, 0x8406afd6'78d4a2c0'f2b412f8'dceda28e_u128},
501 {Sign::POS, -145, 0x8af992d7'c4e2d5b5'bf5dccd9'67504857_u128},
502 {Sign::POS, -145, 0x91ec7610'a82cafed'3716dbf9'50b07f85_u128},
503 {Sign::POS, -145, 0x98df5981'22b5aadd'69eebe0b'8e5b18e1_u128},
504 {Sign::POS, -145, 0x9fd23d29'34813ffc'bb583ce6'5af56beb_u128},
505 {Sign::POS, -145, 0xa6c52108'dd92e8c1'e22978ef'a7a962a0_u128},
506 {Sign::POS, -145, 0xadb80520'1dee1ea3'e89bf389'8ef27836_u128},
507 {Sign::POS, -145, 0xb4aae96e'f5965b1a'2c4c997e'c90bab0b_u128},
508 {Sign::POS, -145, 0xbb9dcdf5'648f179c'5e3bcd6f'21fe6224_u128},
509 {Sign::POS, -145, 0xc290b2b3'6adbcda2'82cd723b'f1524680_u128},
510 {Sign::POS, -145, 0xc98397a9'087ff6a4'f1c8f574'935e109b_u128},
511 {Sign::POS, -145, 0xd0767cd6'3d7f0c1c'565959c2'e4394a59_u128},
512 {Sign::POS, -145, 0xd769623b'09dc8781'af0d4157'bc4f05be_u128},
513 {Sign::POS, -145, 0xde5c47d7'6d9be24e'4dd6f857'6e9188b8_u128},
514 {Sign::POS, -145, 0xe54f2dab'68c095fb'd80c7f46'484eee3d_u128},
515 {Sign::POS, -145, 0xec4213b6'fb4e1c04'46679575'12a6bd26_u128},
516 {Sign::POS, -145, 0xf334f9fa'2547ede1'e505c36d'95a074fa_u128},
517 {Sign::POS, -145, 0xfa27e074'e6b1850f'5368655f'1ce3110b_u128},
518 {Sign::POS, -144, 0x808d6393'9fc72d83'c23a5ac5'7f06c112_u128},
519 {Sign::POS, -144, 0x8406d708'97f0f4a2'df39eb58'90580f93_u128},
520 {Sign::POS, -144, 0x87804a99'5bd7d4a2'cd896f3e'43f38669_u128},
521 {Sign::POS, -144, 0x8af9be45'eb7d8a41'83b16ff7'eecace8c_u128},
522 {Sign::POS, -144, 0x8e73320e'46e3d23d'21ec7ae8'ffa1531d_u128},
523 {Sign::POS, -144, 0x91eca5f2'6e0c6953'f227268d'464ae907_u128},
524 {Sign::POS, -144, 0x956619f2'60f90c44'680017af'3bbaf2d3_u128},
525 {Sign::POS, -144, 0x98df8e0e'1fab77cd'20c8069e'4ae400de_u128},
526 {Sign::POS, -144, 0x9c590245'aa2568ac'e381c465'1a67ee13_u128},
527 {Sign::POS, -144, 0x9fd27699'00689ba2'a0e23fff'd718794e_u128},
528 {Sign::POS, -144, 0xa34beb08'2276cd6d'73508b92'7f485b97_u128},
529 {Sign::POS, -144, 0xa6c55f93'1051bacc'9ee5e19f'2eecdb55_u128},
530 {Sign::POS, -144, 0xaa3ed439'c9fb207f'916daa3c'6c8fdc9d_u128},
531 {Sign::POS, -144, 0xadb848fc'4f74bb45'e265804b'77126ed3_u128},
532 {Sign::POS, -144, 0xb131bdda'a0c047df'52fd36ae'943fd7b4_u128},
533 {Sign::POS, -144, 0xb4ab32d4'bddf830b'ce16dd7f'60311bf6_u128},
534 {Sign::POS, -144, 0xb824a7ea'a6d4298b'6846c745'1d8105ac_u128},
535 {Sign::POS, -144, 0xbb9e1d1c'5b9ff81e'5fd38e2b'0650a884_u128},
536 {Sign::POS, -144, 0xbf179269'dc44ab85'1cb61936'9e1c641f_u128},
537 {Sign::POS, -144, 0xc29107d3'28c40080'3099a17e'0461648c_u128},
538 {Sign::POS, -144, 0xc60a7d58'411fb3d0'56dbb75e'4813a12b_u128},
539 {Sign::POS, -144, 0xc983f2f9'25598236'748c47b1'bbe45a07_u128},
540 {Sign::POS, -144, 0xccfd68b5'd5732873'986da106'4b5913e1_u128},
541 {Sign::POS, -144, 0xd076de8e'516e6348'faf478d3'd0b31300_u128},
542 {Sign::POS, -144, 0xd3f05482'994cef77'fe47f0b2'6ba754ff_u128},
543 {Sign::POS, -144, 0xd769ca92'ad1089c2'2e419b90'd8e709b7_u128},
544 {Sign::POS, -144, 0xdae340be'8cbaeee9'406d82ea'ca788b6f_u128},
545 {Sign::POS, -144, 0xde5cb706'384ddbaf'140a2bff'40e0d670_u128},
546 {Sign::POS, -144, 0xe1d62d69'afcb0cd5'b2089d06'e51d8034_u128},
547 {Sign::POS, -144, 0xe54fa3e8'f3343f1f'4d0c626a'636f2e4f_u128},
548 {Sign::POS, -144, 0xe8c91a84'028b2f4e'416b93f8'c6f48d30_u128},
549 {Sign::POS, -144, 0xec42913a'ddd19a25'152eda1d'd615c6f5_u128},
550 {Sign::POS, -144, 0xefbc080d'85093c66'78117318'6fc07a66_u128},
551 {Sign::POS, -144, 0xf3357efb'f833d2d5'43813830'e974324d_u128},
552 {Sign::POS, -144, 0xf6aef606'37531a34'7a9ea2ef'6e1f5d41_u128},
553 {Sign::POS, -144, 0xfa286d2c'4268cf47'4a3cd252'5dccc623_u128},
554 {Sign::POS, -144, 0xfda1e46e'1976aed1'08e19004'ae218d5d_u128},
555 {Sign::POS, -143, 0x808dade5'de3f3aca'9b62aaca'25d5d18a_u128},
556 {Sign::POS, -143, 0x824a69a2'95c0f02b'bee9a8d4'3e00613c_u128},
557 {Sign::POS, -143, 0x8407256d'334155ed'd8d4b69c'2056f729_u128},
558 {Sign::POS, -143, 0x85c3e145'b6c14a72'e7cc2860'5d7bb77e_u128},
559 {Sign::POS, -143, 0x87809d2c'2041ac1c'ff51b4bd'c834a8f1_u128},
560 {Sign::POS, -143, 0x893d5920'6fc3594e'47c0774a'a81c3561_u128},
561 {Sign::POS, -143, 0x8afa1522'a5473068'fe4cf331'ecb9eb62_u128},
562 },
563 // -log10(r) for the fourth step, generated by SageMath with:
564 //
565 // for i in range(-65, 65):
566 // r = 2^-28 * round( 2^28 / (1 + i*2^(-28)) );
567 // s, m, e = RealField(128)(r).log10().sign_mantissa_exponent();
568 // print("{Sign::POS," if (s == -1) else "{Sign::NEG,", e, ",",
569 // format_hex(m), "},");
570 /* .step_4 = */
571 {
572 {Sign::NEG, -151, 0xe1d54641'22cf95a4'e471a82b'bedbe0ae_u128},
573 {Sign::NEG, -151, 0xde5bd6ec'7f7bc110'af6e93be'8e4c1764_u128},
574 {Sign::NEG, -151, 0xdae26797'a490f80e'e44848f0'a5779499_u128},
575 {Sign::NEG, -151, 0xd768f842'920f3a98'90205533'f4e70566_u128},
576 {Sign::NEG, -151, 0xd3ef88ed'47f688a6'c01844ac'e3729e48_u128},
577 {Sign::NEG, -151, 0xd0761997'c646e232'8151a232'4e41c7c4_u128},
578 {Sign::NEG, -151, 0xccfcaa42'0d004734'e0edf74d'88cacafd_u128},
579 {Sign::NEG, -151, 0xc9833aec'1c22b7a6'ec0ecc3a'5cd27e58_u128},
580 {Sign::NEG, -151, 0xc609cb95'f3ae3381'afd5a7e7'0a6bf214_u128},
581 {Sign::NEG, -151, 0xc2905c3f'93a2babe'39640ff4'47f81ceb_u128},
582 {Sign::NEG, -151, 0xbf16ece8'fc004d55'95db88b5'422588b1_u128},
583 {Sign::NEG, -151, 0xbb9d7d92'2cc6eb40'd25d952f'9beffeec_u128},
584 {Sign::NEG, -151, 0xb8240e3b'25f69478'fc0bb71b'6ea03578_u128},
585 {Sign::NEG, -151, 0xb4aa9ee3'e78f48f7'20076ee3'49cb7b20_u128},
586 {Sign::NEG, -151, 0xb1312f8c'719108b4'4b723ba4'3353643d_u128},
587 {Sign::NEG, -151, 0xadb7c034'c3fbd3a9'8b6d9b2d'a7657754_u128},
588 {Sign::NEG, -151, 0xaa3e50dc'decfa9cf'ed1b0a01'987ad9b4_u128},
589 {Sign::NEG, -151, 0xa6c4e184'c20c8b20'7d9c0354'6f57fc11_u128},
590 {Sign::NEG, -151, 0xa34b722c'6db27794'4a12010d'0b0c4727_u128},
591 {Sign::NEG, -151, 0x9fd202d3'e1c16f24'5f9e7bc4'c0f1c851_u128},
592 {Sign::NEG, -151, 0x9c58937b'1e3971c9'cb62eac7'5cacde29_u128},
593 {Sign::NEG, -151, 0x98df2422'231a7f7d'9a80c413'202be52a_u128},
594 {Sign::NEG, -151, 0x9565b4c8'f0649838'da197c58'c3a6e445_u128},
595 {Sign::NEG, -151, 0x91ec456f'8617bbf4'974e86fb'759f3988_u128},
596 {Sign::NEG, -151, 0x8e72d615'e433eaa9'df415610'dadf46b3_u128},
597 {Sign::NEG, -151, 0x8af966bc'0ab92451'bf135a61'0e7a1ddc_u128},
598 {Sign::NEG, -151, 0x877ff761'f9a768e5'43e60366'a1cb2e09_u128},
599 {Sign::NEG, -151, 0x84068807'b0feb85d'7adabf4e'9c75efce_u128},
600 {Sign::NEG, -151, 0x808d18ad'30bf12b3'7112faf8'7c6591ee_u128},
601 {Sign::NEG, -152, 0xfa2752a4'f1d0efc0'676043ec'6b994be5_u128},
602 {Sign::NEG, -152, 0xf33473ef'12f5cfb9'9fa73d18'6649999d_u128},
603 {Sign::NEG, -152, 0xec419538'c4ecc544'a53db362'aa5cc6f0_u128},
604 {Sign::NEG, -152, 0xe54eb682'07b5d053'9266761d'e5e05f13_u128},
605 {Sign::NEG, -152, 0xde5bd7ca'db50f0d8'81645201'b36e17ba_u128},
606 {Sign::NEG, -152, 0xd768f913'3fbe26c5'8c7a112a'9a2b2a52_u128},
607 {Sign::NEG, -152, 0xd0761a5b'34fd720c'cdea7b1a'0dc7ad42_u128},
608 {Sign::NEG, -152, 0xc9833ba2'bb0ed2a0'5ff854b6'6e7ded1f_u128},
609 {Sign::NEG, -152, 0xc2905ce9'd1f24872'5ce6604b'0911c5ed_u128},
610 {Sign::NEG, -152, 0xbb9d7e30'79a7d374'def75d88'16cffc59_u128},
611 {Sign::NEG, -152, 0xb4aa9f76'b22f739a'006e0982'bd8d96ef_u128},
612 {Sign::NEG, -152, 0xadb7c0bc'7b8928d3'db8d1eb5'0fa7375c_u128},
613 {Sign::NEG, -152, 0xa6c4e201'd5b4f314'8a9754fe'0c0073a7_u128},
614 {Sign::NEG, -152, 0x9fd20346'c0b2d24e'27cf61a1'9e032f69_u128},
615 {Sign::NEG, -152, 0x98df248b'3c82c672'cd77f748'9d9ef50b_u128},
616 {Sign::NEG, -152, 0x91ec45cf'4924cf74'95d3c600'cf484f03_u128},
617 {Sign::NEG, -152, 0x8af96712'e698ed45'9b257b3c'e3f82109_u128},
618 {Sign::NEG, -152, 0x84068856'14df1fd7'f7afc1d4'792b015a_u128},
619 {Sign::NEG, -153, 0xfa275331'a7eece3b'8b6a8408'31c123d8_u128},
620 {Sign::NEG, -153, 0xec4195b6'47c38612'3ef142da'7335b35a_u128},
621 {Sign::NEG, -153, 0xde5bd83a'093c6718'3e79062c'7cbb3b7d_u128},
622 {Sign::NEG, -153, 0xd0761abc'ec597131'be870ed4'ed5b755b_u128},
623 {Sign::NEG, -153, 0xc2905d3e'f11aa442'f3a09874'3d20fb64_u128},
624 {Sign::NEG, -153, 0xb4aa9fc0'17800030'124ad974'bd15fbca_u128},
625 {Sign::NEG, -153, 0xa6c4e240'5f8984dd'4f0b030a'9742eb00_u128},
626 {Sign::NEG, -153, 0x98df24bf'c937322e'de664133'cead362d_u128},
627 {Sign::NEG, -153, 0x8af9673e'54890808'f4e1bab8'3f55f5a1_u128},
628 {Sign::NEG, -154, 0xfa275378'02fe0c9f'8e052253'3c713e98_u128},
629 {Sign::NEG, -154, 0xde5bd871'a03259cf'129bc1c6'f293726e_u128},
630 {Sign::NEG, -154, 0xc2905d69'80aef768'e0918216'6eeb17eb_u128},
631 {Sign::NEG, -154, 0xa6c4e25f'a473e535'60f08720'313daa3f_u128},
632 {Sign::NEG, -154, 0x8af96754'0b8122fc'fcc2ea56'6b3af38b_u128},
633 {Sign::NEG, -155, 0xde5bd88d'6bad6110'3a25757e'00f4e3a0_u128},
634 {Sign::NEG, -155, 0xa6c4e26f'46e91b3e'55d3f9e7'0cf177b8_u128},
635 {Sign::NEG, -156, 0xde5bd89b'516ae82a'3d4aac85'125398d0_u128},
636 {Sign::NEG, -157, 0xde5bd8a2'4449ac95'9ab5a849'a06f400d_u128},
637 {Sign::POS, 0, 0_u128},
638 {Sign::POS, -157, 0xde5bd8b0'2a073729'0d3cc88f'd4ef34c2_u128},
639 {Sign::POS, -156, 0xde5bd8b7'1ce5fd51'225916c2'b3f33c90_u128},
640 {Sign::POS, -155, 0xa6c4e28e'8bd3930a'17847f98'acf08d54_u128},
641 {Sign::POS, -155, 0xde5bd8c5'02a38b5e'04439783'0931fddd_u128},
642 {Sign::POS, -154, 0x8af9677f'79717409'c2ab3859'13176984_u128},
643 {Sign::POS, -154, 0xa6c4e29e'2e48d4cc'e454dec8'2bde52e5_u128},
644 {Sign::POS, -154, 0xc2905dbe'9fd7e82f'fe1522b0'470d7d7f_u128},
645 {Sign::POS, -154, 0xde5bd8e0'ce1eae6a'a6e2721f'2afc3cce_u128},
646 {Sign::POS, -154, 0xfa275404'b91d27b4'75b3458e'ec3c106c_u128},
647 {Sign::POS, -153, 0x8af96795'3069aa22'80bf0ff2'f6cd9f93_u128},
648 {Sign::POS, -153, 0x98df2528'e2a09a29'f09cc73b'7013b906_u128},
649 {Sign::POS, -153, 0xa6c4e2bd'7333640c'55ee1480'619827c4_u128},
650 {Sign::POS, -153, 0xb4aaa052'e22207e5'7c2e48d7'72250b3c_u128},
651 {Sign::POS, -153, 0xc2905de9'2f6c85d1'2ed8ba8c'6fa81c98_u128},
652 {Sign::POS, -153, 0xd0761b80'5b12ddeb'3968c521'4f33fc4f_u128},
653 {Sign::POS, -153, 0xde5bd918'6515104f'6759c94e'2d017fad_u128},
654 {Sign::POS, -153, 0xec4196b1'4d731d19'84272d01'4c70fe58_u128},
655 {Sign::POS, -153, 0xfa27544b'142d0465'5b4c5b5f'180b9fe1_u128},
656 {Sign::POS, -152, 0x840688f2'dca16327'5c226261'10c254a4_u128},
657 {Sign::POS, -152, 0x8af967c0'9e5a3178'b345ef5d'90dd6545_u128},
658 {Sign::POS, -152, 0x91ec468e'cf40ed34'98ce9208'7c5cb614_u128},
659 {Sign::POS, -152, 0x98df255d'6f559668'f27a0a60'56dcfe57_u128},
660 {Sign::POS, -152, 0x9fd2042c'7e982d23'a6061afe'b7929f24_u128},
661 {Sign::POS, -152, 0xa6c4e2fb'fd08b172'99308918'494a4a20_u128},
662 {Sign::POS, -152, 0xadb7c1cb'eaa72363'b1b71c7c'ca69a844_u128},
663 {Sign::POS, -152, 0xb4aaa09c'47738304'd5579f97'0cf000a9_u128},
664 {Sign::POS, -152, 0xbb9d7f6d'136dd063'e9cfdf6c'f676df42_u128},
665 {Sign::POS, -152, 0xc2905e3e'4e960b8e'd4ddab9f'8032bbab_u128},
666 {Sign::POS, -152, 0xc9833d0f'f8ec3493'7c3ed66a'b6f39fe9_u128},
667 {Sign::POS, -152, 0xd0761be2'12704b7f'c5b134a5'bb25cf2e_u128},
668 {Sign::POS, -152, 0xd768fab4'9b225061'96f29dc2'c0d26ca0_u128},
669 {Sign::POS, -152, 0xde5bd987'93024346'd5c0ebcf'0fa0221e_u128},
670 {Sign::POS, -152, 0xe54eb85a'fa10243d'67d9fb73'02d3c705_u128},
671 {Sign::POS, -152, 0xec41972e'd04bf353'32fbabf2'095106f1_u128},
672 {Sign::POS, -152, 0xf3347603'15b5b096'1ce3df2a'a59b0889_u128},
673 {Sign::POS, -152, 0xfa2754d7'ca4d5c14'0b507996'6dd5143e_u128},
674 {Sign::POS, -151, 0x808d19d6'77097aed'71ffb125'05e19d89_u128},
675 {Sign::POS, -151, 0x84068941'40833efc'4657417a'9e657eae_u128},
676 {Sign::POS, -151, 0x877ff8ac'4193fa3d'758de3f1'68f9f8c9_u128},
677 {Sign::POS, -151, 0x8af96817'7a3bacb7'f2828ffc'57f43581_u128},
678 {Sign::POS, -151, 0x8e72d782'ea7a5672'b0143e5b'e77b1053_u128},
679 {Sign::POS, -151, 0x91ec46ee'924ff774'a121e91e'1d8769ef_u128},
680 {Sign::POS, -151, 0x9565b65a'71bc8fc4'b88a8b9e'89e47b9c_u128},
681 {Sign::POS, -151, 0x98df25c6'88c01f69'e92d2286'46302a9c_u128},
682 {Sign::POS, -151, 0x9c589532'd75aa66b'25e8abcb'f5db5b8c_u128},
683 {Sign::POS, -151, 0x9fd2049f'5d8c24cf'619c26b3'c62a45c8_u128},
684 {Sign::POS, -151, 0xa34b740c'1b549a9d'8f2693cf'6e34c6cc_u128},
685 {Sign::POS, -151, 0xa6c4e379'10b407dc'a166f4fe'2ee6b59a_u128},
686 {Sign::POS, -151, 0xaa3e52e6'3daa6c93'8b3c4d6c'd3003616_u128},
687 {Sign::POS, -151, 0xadb7c253'a237c8c9'3f85a195'af160c71_u128},
688 {Sign::POS, -151, 0xb13131c1'3e5c1c84'b121f740'a191f084_u128},
689 {Sign::POS, -151, 0xb4aaa12f'121767cc'd2f05583'12b2e136_u128},
690 {Sign::POS, -151, 0xb824109d'1d69aaa8'97cfc4bf'f48d77de_u128},
691 {Sign::POS, -151, 0xbb9d800b'6052e51e'f29f4ea7'c30c3ba5_u128},
692 {Sign::POS, -151, 0xbf16ef79'dad31736'd63dfe38'83eff4e9_u128},
693 {Sign::POS, -151, 0xc2905ee8'8cea40f7'358adfbd'c6d0009f_u128},
694 {Sign::POS, -151, 0xc609ce57'76986267'036500d0'a51aa3b6_u128},
695 {Sign::POS, -151, 0xc9833dc6'97dd7b8d'32ab7057'c2155e78_u128},
696 {Sign::POS, -151, 0xccfcad35'f0b98c70'b63d3e87'4add3ff0_u128},
697 {Sign::POS, -151, 0xd0761ca5'812c9518'80f97ce0'f6673948_u128},
698 {Sign::POS, -151, 0xd3ef8c15'4936958b'85bf3e34'0580712d_u128},
699 {Sign::POS, -151, 0xd768fb85'48d78dd0'b76d969d'42ce9734_u128},
700 {Sign::POS, -151, 0xdae26af5'800f7def'08e39b87'02d0373a_u128},
701 {Sign::POS, -151, 0xde5bda65'eede65ed'6d0063a9'23dd0cc6_u128},
702 }};
703
704// > P = fpminimax(log10(1 + x)/x, 3, [|128...|], [-0x1.0002143p-29 , 0x1p-29]);
705// > P;
706// > dirtyinfnorm(log10(1 + x)/x - P, [-0x1.0002143p-29 , 0x1p-29]);
707// 0x1.64fb8...p-123
708constexpr Float128 BIG_COEFFS[4]{
709 {Sign::NEG, -131, 0xde5bd8a9'373f89a7'6903c4ce'1582517d_u128},
710 {Sign::POS, -130, 0x943d3b1b'7a1af679'b8a21791'624e2e8a_u128},
711 {Sign::NEG, -130, 0xde5bd8a9'37287195'355baaaf'abc25990_u128},
712 {Sign::POS, -129, 0xde5bd8a9'37287195'355baaaf'ad33dbd9_u128},
713};
714
715// Reuse the output of the fast pass range reduction.
716// -2^-8 <= m_x < 2^-7
717double log10_accurate(int e_x, int index, double m_x) {
718
719 Float128 e_x_f128(static_cast<float>(e_x));
720 Float128 sum = fputil::quick_mul(a: LOG10_2, b: e_x_f128);
721 sum = fputil::quick_add(a: sum, b: LOG10_TABLE.step_1[index]);
722
723 Float128 v_f128 = log_range_reduction(m_x, log_table: LOG10_TABLE, sum);
724
725 // Polynomial approximation
726 Float128 p = fputil::quick_mul(a: v_f128, b: BIG_COEFFS[0]);
727 p = fputil::quick_mul(a: v_f128, b: fputil::quick_add(a: p, b: BIG_COEFFS[1]));
728 p = fputil::quick_mul(a: v_f128, b: fputil::quick_add(a: p, b: BIG_COEFFS[2]));
729 p = fputil::quick_mul(a: v_f128, b: fputil::quick_add(a: p, b: BIG_COEFFS[3]));
730
731 Float128 r = fputil::quick_add(a: sum, b: p);
732
733 return static_cast<double>(r);
734}
735
736} // namespace
737
738LLVM_LIBC_FUNCTION(double, log10, (double x)) {
739 using FPBits_t = typename fputil::FPBits<double>;
740
741 FPBits_t xbits(x);
742 uint64_t x_u = xbits.uintval();
743
744 int x_e = -FPBits_t::EXP_BIAS;
745
746 if (LIBC_UNLIKELY(xbits == FPBits_t::one())) {
747 // log10(1.0) = +0.0
748 return 0.0;
749 }
750
751 if (LIBC_UNLIKELY(xbits.uintval() < FPBits_t::min_normal().uintval() ||
752 xbits.uintval() > FPBits_t::max_normal().uintval())) {
753 if (xbits.is_zero()) {
754 // return -Inf and raise FE_DIVBYZERO.
755 fputil::set_errno_if_required(ERANGE);
756 fputil::raise_except_if_required(FE_DIVBYZERO);
757 return FPBits_t::inf(sign: Sign::NEG).get_val();
758 }
759 if (xbits.is_neg() && !xbits.is_nan()) {
760 fputil::set_errno_if_required(EDOM);
761 fputil::raise_except_if_required(FE_INVALID);
762 return FPBits_t::quiet_nan().get_val();
763 }
764 if (xbits.is_inf_or_nan()) {
765 return x;
766 }
767 // Normalize denormal inputs.
768 xbits = FPBits_t(x * 0x1.0p52);
769 x_e -= 52;
770 x_u = xbits.uintval();
771 }
772
773 // log10(x) = log10(2^x_e * x_m)
774 // = x_e * log10(2) + log10(x_m)
775
776 // Range reduction for log10(x_m):
777 // For each x_m, we would like to find r such that:
778 // -2^-8 <= r * x_m - 1 < 2^-7
779 int shifted = static_cast<int>(x_u >> 45);
780 int index = shifted & 0x7F;
781 double r = RD[index];
782
783 // Add unbiased exponent. Add an extra 1 if the 8 leading fractional bits are
784 // all 1's.
785 x_e += static_cast<int>((x_u + (1ULL << 45)) >> 52);
786 double e_x = static_cast<double>(x_e);
787
788 // hi is exact
789 double hi = fputil::multiply_add(x: e_x, y: LOG_2_HI, z: LOG_R_DD[index].hi);
790 // lo errors ~ e_x * LSB(LOG_2_LO) + LSB(LOG_R[index].lo) + rounding err
791 // <= 2 * (e_x * LSB(LOG_2_LO) + LSB(LOG_R[index].lo))
792 double lo = fputil::multiply_add(x: e_x, y: LOG_2_LO, z: LOG_R_DD[index].lo);
793
794 // Set m = 1.mantissa.
795 uint64_t x_m = (x_u & 0x000F'FFFF'FFFF'FFFFULL) | 0x3FF0'0000'0000'0000ULL;
796 double m = FPBits_t(x_m).get_val();
797
798 double u, u_sq, err;
799 fputil::DoubleDouble r1;
800
801 // Perform exact range reduction
802#ifdef LIBC_TARGET_CPU_HAS_FMA
803 u = fputil::multiply_add(x: r, y: m, z: -1.0); // exact
804#else
805 uint64_t c_m = x_m & 0x3FFF'E000'0000'0000ULL;
806 double c = FPBits_t(c_m).get_val();
807 u = fputil::multiply_add(r, m - c, CD[index]); // exact
808#endif // LIBC_TARGET_CPU_HAS_FMA
809
810 // Error of u_sq = ulp(u^2);
811 u_sq = u * u;
812 // Degree-7 minimax polynomial
813 double p0 = fputil::multiply_add(x: u, y: LOG_COEFFS[1], z: LOG_COEFFS[0]);
814 double p1 = fputil::multiply_add(x: u, y: LOG_COEFFS[3], z: LOG_COEFFS[2]);
815 double p2 = fputil::multiply_add(x: u, y: LOG_COEFFS[5], z: LOG_COEFFS[4]);
816 double p = fputil::polyeval(x: u_sq, a0: lo, a: p0, a: p1, a: p2);
817
818 // Exact sum:
819 // r1.hi + r1.lo = e_x * log(2)_hi - log(r)_hi + u
820 r1 = fputil::exact_add(a: hi, b: u);
821 r1.lo += p;
822
823 // Quick double-double multiplication:
824 // r2.hi + r2.lo ~ r1 * log10(e),
825 // with error bounded by:
826 // 4*ulp( ulp(r2.hi) )
827 fputil::DoubleDouble r2 = fputil::quick_mult(a: r1, b: LOG10_E);
828
829 // Technicallly error of r1.lo is bounded by:
830 // |hi|*ulp(log(2)_lo) + C*ulp(u^2)
831 // To simplify the error computation a bit, we replace |hi|*ulp(log(2)_lo)
832 // with the upper bound: 2^11 * ulp(log(2)_lo) = 2^-85.
833 // Total error is bounded by ~ C * ulp(u^2) + 2^-85.
834 err = fputil::multiply_add(x: u_sq, y: P_ERR, z: HI_ERR);
835
836 // Lower bound from the result
837 double left = r2.hi + (r2.lo - err);
838 // Upper bound from the result
839 double right = r2.hi + (r2.lo + err);
840
841 // Ziv's test if fast pass is accurate enough.
842 if (left == right)
843 return left;
844
845 // Exact cases:
846 if (LIBC_UNLIKELY((x_u & 0x3FFFFF) == 0)) {
847 switch (x_u) {
848 case 0x4024000000000000: // x = 10.0
849 return 1.0;
850 case 0x4059000000000000: // x = 10^2
851 return 2.0;
852 case 0x408f400000000000: // x = 10^3
853 return 3.0;
854 case 0x40c3880000000000: // x = 10^4
855 return 4.0;
856 case 0x40f86a0000000000: // x = 10^5
857 return 5.0;
858 case 0x412e848000000000: // x = 10^6
859 return 6.0;
860 case 0x416312d000000000: // x = 10^7
861 return 7.0;
862 case 0x4197d78400000000: // x = 10^8
863 return 8.0;
864 case 0x41cdcd6500000000: // x = 10^9
865 return 9.0;
866 case 0x4202a05f20000000: // x = 10^10
867 return 10.0;
868 case 0x42374876e8000000: // x = 10^11
869 return 11.0;
870 case 0x426d1a94a2000000: // x = 10^12
871 return 12.0;
872 case 0x42a2309ce5400000: // x = 10^13
873 return 13.0;
874 }
875 } else {
876 switch (x_u) {
877 case 0x42d6bcc41e900000: // x = 10^14
878 return 14.0;
879 case 0x430c6bf526340000: // x = 10^15
880 return 15.0;
881 case 0x4341c37937e08000: // x = 10^16
882 return 16.0;
883 case 0x4376345785d8a000: // x = 10^17
884 return 17.0;
885 case 0x43abc16d674ec800: // x = 10^18
886 return 18.0;
887 case 0x43e158e460913d00: // x = 10^19
888 return 19.0;
889 case 0x4415af1d78b58c40: // x = 10^20
890 return 20.0;
891 case 0x444b1ae4d6e2ef50: // x = 10^21
892 return 21.0;
893 case 0x4480f0cf064dd592: // x = 10^22
894 return 22.0;
895 }
896 }
897
898 return log10_accurate(e_x: x_e, index, m_x: u);
899}
900
901} // namespace LIBC_NAMESPACE
902

source code of libc/src/math/generic/log10.cpp