/src/abseil-cpp/absl/strings/internal/charconv_bigint.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2018 The Abseil Authors. |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | #include "absl/strings/internal/charconv_bigint.h" |
16 | | |
17 | | #include <algorithm> |
18 | | #include <cassert> |
19 | | #include <string> |
20 | | |
21 | | namespace absl { |
22 | | ABSL_NAMESPACE_BEGIN |
23 | | namespace strings_internal { |
24 | | |
25 | | namespace { |
26 | | |
27 | | // Table containing some large powers of 5, for fast computation. |
28 | | |
29 | | // Constant step size for entries in the kLargePowersOfFive table. Each entry |
30 | | // is larger than the previous entry by a factor of 5**kLargePowerOfFiveStep |
31 | | // (or 5**27). |
32 | | // |
33 | | // In other words, the Nth entry in the table is 5**(27*N). |
34 | | // |
35 | | // 5**27 is the largest power of 5 that fits in 64 bits. |
36 | | constexpr int kLargePowerOfFiveStep = 27; |
37 | | |
38 | | // The largest legal index into the kLargePowersOfFive table. |
39 | | // |
40 | | // In other words, the largest precomputed power of 5 is 5**(27*20). |
41 | | constexpr int kLargestPowerOfFiveIndex = 20; |
42 | | |
43 | | // Table of powers of (5**27), up to (5**27)**20 == 5**540. |
44 | | // |
45 | | // Used to generate large powers of 5 while limiting the number of repeated |
46 | | // multiplications required. |
47 | | // |
48 | | // clang-format off |
49 | | const uint32_t kLargePowersOfFive[] = { |
50 | | // 5**27 (i=1), start=0, end=2 |
51 | | 0xfa10079dU, 0x6765c793U, |
52 | | // 5**54 (i=2), start=2, end=6 |
53 | | 0x97d9f649U, 0x6664242dU, 0x29939b14U, 0x29c30f10U, |
54 | | // 5**81 (i=3), start=6, end=12 |
55 | | 0xc4f809c5U, 0x7bf3f22aU, 0x67bdae34U, 0xad340517U, 0x369d1b5fU, 0x10de1593U, |
56 | | // 5**108 (i=4), start=12, end=20 |
57 | | 0x92b260d1U, 0x9efff7c7U, 0x81de0ec6U, 0xaeba5d56U, 0x410664a4U, 0x4f40737aU, |
58 | | 0x20d3846fU, 0x06d00f73U, |
59 | | // 5**135 (i=5), start=20, end=30 |
60 | | 0xff1b172dU, 0x13a1d71cU, 0xefa07617U, 0x7f682d3dU, 0xff8c90c0U, 0x3f0131e7U, |
61 | | 0x3fdcb9feU, 0x917b0177U, 0x16c407a7U, 0x02c06b9dU, |
62 | | // 5**162 (i=6), start=30, end=42 |
63 | | 0x960f7199U, 0x056667ecU, 0xe07aefd8U, 0x80f2b9ccU, 0x8273f5e3U, 0xeb9a214aU, |
64 | | 0x40b38005U, 0x0e477ad4U, 0x277d08e6U, 0xfa28b11eU, 0xd3f7d784U, 0x011c835bU, |
65 | | // 5**189 (i=7), start=42, end=56 |
66 | | 0xf723d9d5U, 0x3282d3f3U, 0xe00857d1U, 0x69659d25U, 0x2cf117cfU, 0x24da6d07U, |
67 | | 0x954d1417U, 0x3e5d8cedU, 0x7a8bb766U, 0xfd785ae6U, 0x645436d2U, 0x40c78b34U, |
68 | | 0x94151217U, 0x0072e9f7U, |
69 | | // 5**216 (i=8), start=56, end=72 |
70 | | 0x2b416aa1U, 0x7893c5a7U, 0xe37dc6d4U, 0x2bad2beaU, 0xf0fc846cU, 0x7575ae4bU, |
71 | | 0x62587b14U, 0x83b67a34U, 0x02110cdbU, 0xf7992f55U, 0x00deb022U, 0xa4a23becU, |
72 | | 0x8af5c5cdU, 0xb85b654fU, 0x818df38bU, 0x002e69d2U, |
73 | | // 5**243 (i=9), start=72, end=90 |
74 | | 0x3518cbbdU, 0x20b0c15fU, 0x38756c2fU, 0xfb5dc3ddU, 0x22ad2d94U, 0xbf35a952U, |
75 | | 0xa699192aU, 0x9a613326U, 0xad2a9cedU, 0xd7f48968U, 0xe87dfb54U, 0xc8f05db6U, |
76 | | 0x5ef67531U, 0x31c1ab49U, 0xe202ac9fU, 0x9b2957b5U, 0xa143f6d3U, 0x0012bf07U, |
77 | | // 5**270 (i=10), start=90, end=110 |
78 | | 0x8b971de9U, 0x21aba2e1U, 0x63944362U, 0x57172336U, 0xd9544225U, 0xfb534166U, |
79 | | 0x08c563eeU, 0x14640ee2U, 0x24e40d31U, 0x02b06537U, 0x03887f14U, 0x0285e533U, |
80 | | 0xb744ef26U, 0x8be3a6c4U, 0x266979b4U, 0x6761ece2U, 0xd9cb39e4U, 0xe67de319U, |
81 | | 0x0d39e796U, 0x00079250U, |
82 | | // 5**297 (i=11), start=110, end=132 |
83 | | 0x260eb6e5U, 0xf414a796U, 0xee1a7491U, 0xdb9368ebU, 0xf50c105bU, 0x59157750U, |
84 | | 0x9ed2fb5cU, 0xf6e56d8bU, 0xeaee8d23U, 0x0f319f75U, 0x2aa134d6U, 0xac2908e9U, |
85 | | 0xd4413298U, 0x02f02a55U, 0x989d5a7aU, 0x70dde184U, 0xba8040a7U, 0x03200981U, |
86 | | 0xbe03b11cU, 0x3c1c2a18U, 0xd60427a1U, 0x00030ee0U, |
87 | | // 5**324 (i=12), start=132, end=156 |
88 | | 0xce566d71U, 0xf1c4aa25U, 0x4e93ca53U, 0xa72283d0U, 0x551a73eaU, 0x3d0538e2U, |
89 | | 0x8da4303fU, 0x6a58de60U, 0x0e660221U, 0x49cf61a6U, 0x8d058fc1U, 0xb9d1a14cU, |
90 | | 0x4bab157dU, 0xc85c6932U, 0x518c8b9eU, 0x9b92b8d0U, 0x0d8a0e21U, 0xbd855df9U, |
91 | | 0xb3ea59a1U, 0x8da29289U, 0x4584d506U, 0x3752d80fU, 0xb72569c6U, 0x00013c33U, |
92 | | // 5**351 (i=13), start=156, end=182 |
93 | | 0x190f354dU, 0x83695cfeU, 0xe5a4d0c7U, 0xb60fb7e8U, 0xee5bbcc4U, 0xb922054cU, |
94 | | 0xbb4f0d85U, 0x48394028U, 0x1d8957dbU, 0x0d7edb14U, 0x4ecc7587U, 0x505e9e02U, |
95 | | 0x4c87f36bU, 0x99e66bd6U, 0x44b9ed35U, 0x753037d4U, 0xe5fe5f27U, 0x2742c203U, |
96 | | 0x13b2ed2bU, 0xdc525d2cU, 0xe6fde59aU, 0x77ffb18fU, 0x13c5752cU, 0x08a84bccU, |
97 | | 0x859a4940U, 0x00007fb6U, |
98 | | // 5**378 (i=14), start=182, end=210 |
99 | | 0x4f98cb39U, 0xa60edbbcU, 0x83b5872eU, 0xa501acffU, 0x9cc76f78U, 0xbadd4c73U, |
100 | | 0x43e989faU, 0xca7acf80U, 0x2e0c824fU, 0xb19f4ffcU, 0x092fd81cU, 0xe4eb645bU, |
101 | | 0xa1ff84c2U, 0x8a5a83baU, 0xa8a1fae9U, 0x1db43609U, 0xb0fed50bU, 0x0dd7d2bdU, |
102 | | 0x7d7accd8U, 0x91fa640fU, 0x37dcc6c5U, 0x1c417fd5U, 0xe4d462adU, 0xe8a43399U, |
103 | | 0x131bf9a5U, 0x8df54d29U, 0x36547dc1U, 0x00003395U, |
104 | | // 5**405 (i=15), start=210, end=240 |
105 | | 0x5bd330f5U, 0x77d21967U, 0x1ac481b7U, 0x6be2f7ceU, 0x7f4792a9U, 0xe84c2c52U, |
106 | | 0x84592228U, 0x9dcaf829U, 0xdab44ce1U, 0x3d0c311bU, 0x532e297dU, 0x4704e8b4U, |
107 | | 0x9cdc32beU, 0x41e64d9dU, 0x7717bea1U, 0xa824c00dU, 0x08f50b27U, 0x0f198d77U, |
108 | | 0x49bbfdf0U, 0x025c6c69U, 0xd4e55cd3U, 0xf083602bU, 0xb9f0fecdU, 0xc0864aeaU, |
109 | | 0x9cb98681U, 0xaaf620e9U, 0xacb6df30U, 0x4faafe66U, 0x8af13c3bU, 0x000014d5U, |
110 | | // 5**432 (i=16), start=240, end=272 |
111 | | 0x682bb941U, 0x89a9f297U, 0xcba75d7bU, 0x404217b1U, 0xb4e519e9U, 0xa1bc162bU, |
112 | | 0xf7f5910aU, 0x98715af5U, 0x2ff53e57U, 0xe3ef118cU, 0x490c4543U, 0xbc9b1734U, |
113 | | 0x2affbe4dU, 0x4cedcb4cU, 0xfb14e99eU, 0x35e34212U, 0xece39c24U, 0x07673ab3U, |
114 | | 0xe73115ddU, 0xd15d38e7U, 0x093eed3bU, 0xf8e7eac5U, 0x78a8cc80U, 0x25227aacU, |
115 | | 0x3f590551U, 0x413da1cbU, 0xdf643a55U, 0xab65ad44U, 0xd70b23d7U, 0xc672cd76U, |
116 | | 0x3364ea62U, 0x0000086aU, |
117 | | // 5**459 (i=17), start=272, end=306 |
118 | | 0x22f163ddU, 0x23cf07acU, 0xbe2af6c2U, 0xf412f6f6U, 0xc3ff541eU, 0x6eeaf7deU, |
119 | | 0xa47047e0U, 0x408cda92U, 0x0f0eeb08U, 0x56deba9dU, 0xcfc6b090U, 0x8bbbdf04U, |
120 | | 0x3933cdb3U, 0x9e7bb67dU, 0x9f297035U, 0x38946244U, 0xee1d37bbU, 0xde898174U, |
121 | | 0x63f3559dU, 0x705b72fbU, 0x138d27d9U, 0xf8603a78U, 0x735eec44U, 0xe30987d5U, |
122 | | 0xc6d38070U, 0x9cfe548eU, 0x9ff01422U, 0x7c564aa8U, 0x91cc60baU, 0xcbc3565dU, |
123 | | 0x7550a50bU, 0x6909aeadU, 0x13234c45U, 0x00000366U, |
124 | | // 5**486 (i=18), start=306, end=342 |
125 | | 0x17954989U, 0x3a7d7709U, 0x98042de5U, 0xa9011443U, 0x45e723c2U, 0x269ffd6fU, |
126 | | 0x58852a46U, 0xaaa1042aU, 0x2eee8153U, 0xb2b6c39eU, 0xaf845b65U, 0xf6c365d7U, |
127 | | 0xe4cffb2bU, 0xc840e90cU, 0xabea8abbU, 0x5c58f8d2U, 0x5c19fa3aU, 0x4670910aU, |
128 | | 0x4449f21cU, 0xefa645b3U, 0xcc427decU, 0x083c3d73U, 0x467cb413U, 0x6fe10ae4U, |
129 | | 0x3caffc72U, 0x9f8da55eU, 0x5e5c8ea7U, 0x490594bbU, 0xf0871b0bU, 0xdd89816cU, |
130 | | 0x8e931df8U, 0xe85ce1c9U, 0xcca090a5U, 0x575fa16bU, 0x6b9f106cU, 0x0000015fU, |
131 | | // 5**513 (i=19), start=342, end=380 |
132 | | 0xee20d805U, 0x57bc3c07U, 0xcdea624eU, 0xd3f0f52dU, 0x9924b4f4U, 0xcf968640U, |
133 | | 0x61d41962U, 0xe87fb464U, 0xeaaf51c7U, 0x564c8b60U, 0xccda4028U, 0x529428bbU, |
134 | | 0x313a1fa8U, 0x96bd0f94U, 0x7a82ebaaU, 0xad99e7e9U, 0xf2668cd4U, 0xbe33a45eU, |
135 | | 0xfd0db669U, 0x87ee369fU, 0xd3ec20edU, 0x9c4d7db7U, 0xdedcf0d8U, 0x7cd2ca64U, |
136 | | 0xe25a6577U, 0x61003fd4U, 0xe56f54ccU, 0x10b7c748U, 0x40526e5eU, 0x7300ae87U, |
137 | | 0x5c439261U, 0x2c0ff469U, 0xbf723f12U, 0xb2379b61U, 0xbf59b4f5U, 0xc91b1c3fU, |
138 | | 0xf0046d27U, 0x0000008dU, |
139 | | // 5**540 (i=20), start=380, end=420 |
140 | | 0x525c9e11U, 0xf4e0eb41U, 0xebb2895dU, 0x5da512f9U, 0x7d9b29d4U, 0x452f4edcU, |
141 | | 0x0b90bc37U, 0x341777cbU, 0x63d269afU, 0x1da77929U, 0x0a5c1826U, 0x77991898U, |
142 | | 0x5aeddf86U, 0xf853a877U, 0x538c31ccU, 0xe84896daU, 0xb7a0010bU, 0x17ef4de5U, |
143 | | 0xa52a2adeU, 0x029fd81cU, 0x987ce701U, 0x27fefd77U, 0xdb46c66fU, 0x5d301900U, |
144 | | 0x496998c0U, 0xbb6598b9U, 0x5eebb607U, 0xe547354aU, 0xdf4a2f7eU, 0xf06c4955U, |
145 | | 0x96242ffaU, 0x1775fb27U, 0xbecc58ceU, 0xebf2a53bU, 0x3eaad82aU, 0xf41137baU, |
146 | | 0x573e6fbaU, 0xfb4866b8U, 0x54002148U, 0x00000039U, |
147 | | }; |
148 | | // clang-format on |
149 | | |
150 | | // Returns a pointer to the big integer data for (5**27)**i. i must be |
151 | | // between 1 and 20, inclusive. |
152 | 6.59k | const uint32_t* LargePowerOfFiveData(int i) { |
153 | 6.59k | return kLargePowersOfFive + i * (i - 1); |
154 | 6.59k | } |
155 | | |
156 | | // Returns the size of the big integer data for (5**27)**i, in words. i must be |
157 | | // between 1 and 20, inclusive. |
158 | 10.6k | int LargePowerOfFiveSize(int i) { return 2 * i; } |
159 | | } // namespace |
160 | | |
161 | | ABSL_DLL const uint32_t kFiveToNth[14] = { |
162 | | 1, 5, 25, 125, 625, 3125, 15625, |
163 | | 78125, 390625, 1953125, 9765625, 48828125, 244140625, 1220703125, |
164 | | }; |
165 | | |
166 | | ABSL_DLL const uint32_t kTenToNth[10] = { |
167 | | 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, |
168 | | }; |
169 | | |
170 | | template <int max_words> |
171 | | int BigUnsigned<max_words>::ReadFloatMantissa(const ParsedFloat& fp, |
172 | 10.4k | int significant_digits) { |
173 | 10.4k | SetToZero(); |
174 | 10.4k | assert(fp.type == FloatType::kNumber); |
175 | | |
176 | 10.4k | if (fp.subrange_begin == nullptr) { |
177 | | // We already exactly parsed the mantissa, so no more work is necessary. |
178 | 2.57k | words_[0] = fp.mantissa & 0xffffffffu; |
179 | 2.57k | words_[1] = fp.mantissa >> 32; |
180 | 2.57k | if (words_[1]) { |
181 | 914 | size_ = 2; |
182 | 1.66k | } else if (words_[0]) { |
183 | 1.66k | size_ = 1; |
184 | 1.66k | } |
185 | 2.57k | return fp.exponent; |
186 | 2.57k | } |
187 | 7.90k | int exponent_adjust = |
188 | 7.90k | ReadDigits(fp.subrange_begin, fp.subrange_end, significant_digits); |
189 | 7.90k | return fp.literal_exponent + exponent_adjust; |
190 | 10.4k | } Unexecuted instantiation: absl::strings_internal::BigUnsigned<4>::ReadFloatMantissa(absl::strings_internal::ParsedFloat const&, int) absl::strings_internal::BigUnsigned<84>::ReadFloatMantissa(absl::strings_internal::ParsedFloat const&, int) Line | Count | Source | 172 | 10.4k | int significant_digits) { | 173 | 10.4k | SetToZero(); | 174 | 10.4k | assert(fp.type == FloatType::kNumber); | 175 | | | 176 | 10.4k | if (fp.subrange_begin == nullptr) { | 177 | | // We already exactly parsed the mantissa, so no more work is necessary. | 178 | 2.57k | words_[0] = fp.mantissa & 0xffffffffu; | 179 | 2.57k | words_[1] = fp.mantissa >> 32; | 180 | 2.57k | if (words_[1]) { | 181 | 914 | size_ = 2; | 182 | 1.66k | } else if (words_[0]) { | 183 | 1.66k | size_ = 1; | 184 | 1.66k | } | 185 | 2.57k | return fp.exponent; | 186 | 2.57k | } | 187 | 7.90k | int exponent_adjust = | 188 | 7.90k | ReadDigits(fp.subrange_begin, fp.subrange_end, significant_digits); | 189 | 7.90k | return fp.literal_exponent + exponent_adjust; | 190 | 10.4k | } |
|
191 | | |
192 | | template <int max_words> |
193 | | int BigUnsigned<max_words>::ReadDigits(const char* begin, const char* end, |
194 | 7.90k | int significant_digits) { |
195 | 7.90k | assert(significant_digits <= Digits10() + 1); |
196 | 0 | SetToZero(); |
197 | | |
198 | 7.90k | bool after_decimal_point = false; |
199 | | // Discard any leading zeroes before the decimal point |
200 | 105k | while (begin < end && *begin == '0') { |
201 | 98.0k | ++begin; |
202 | 98.0k | } |
203 | 7.90k | int dropped_digits = 0; |
204 | | // Discard any trailing zeroes. These may or may not be after the decimal |
205 | | // point. |
206 | 1.85M | while (begin < end && *std::prev(end) == '0') { |
207 | 1.84M | --end; |
208 | 1.84M | ++dropped_digits; |
209 | 1.84M | } |
210 | 7.90k | if (begin < end && *std::prev(end) == '.') { |
211 | | // If the string ends in '.', either before or after dropping zeroes, then |
212 | | // drop the decimal point and look for more digits to drop. |
213 | 424 | dropped_digits = 0; |
214 | 424 | --end; |
215 | 674 | while (begin < end && *std::prev(end) == '0') { |
216 | 250 | --end; |
217 | 250 | ++dropped_digits; |
218 | 250 | } |
219 | 7.48k | } else if (dropped_digits) { |
220 | | // We dropped digits, and aren't sure if they're before or after the decimal |
221 | | // point. Figure that out now. |
222 | 892 | const char* dp = std::find(begin, end, '.'); |
223 | 892 | if (dp != end) { |
224 | | // The dropped trailing digits were after the decimal point, so don't |
225 | | // count them. |
226 | 636 | dropped_digits = 0; |
227 | 636 | } |
228 | 892 | } |
229 | | // Any non-fraction digits we dropped need to be accounted for in our exponent |
230 | | // adjustment. |
231 | 7.90k | int exponent_adjust = dropped_digits; |
232 | | |
233 | 7.90k | uint32_t queued = 0; |
234 | 7.90k | int digits_queued = 0; |
235 | 2.65M | for (; begin != end && significant_digits > 0; ++begin) { |
236 | 2.64M | if (*begin == '.') { |
237 | 6.02k | after_decimal_point = true; |
238 | 6.02k | continue; |
239 | 6.02k | } |
240 | 2.63M | if (after_decimal_point) { |
241 | | // For each fractional digit we emit in our parsed integer, adjust our |
242 | | // decimal exponent to compensate. |
243 | 2.23M | --exponent_adjust; |
244 | 2.23M | } |
245 | 2.63M | char digit = (*begin - '0'); |
246 | 2.63M | --significant_digits; |
247 | 2.63M | if (significant_digits == 0 && std::next(begin) != end && |
248 | 2.63M | (digit == 0 || digit == 5)) { |
249 | | // If this is the very last significant digit, but insignificant digits |
250 | | // remain, we know that the last of those remaining significant digits is |
251 | | // nonzero. (If it wasn't, we would have stripped it before we got here.) |
252 | | // So if this final digit is a 0 or 5, adjust it upward by 1. |
253 | | // |
254 | | // This adjustment is what allows incredibly large mantissas ending in |
255 | | // 500000...000000000001 to correctly round up, rather than to nearest. |
256 | 2.18k | ++digit; |
257 | 2.18k | } |
258 | 2.63M | queued = 10 * queued + static_cast<uint32_t>(digit); |
259 | 2.63M | ++digits_queued; |
260 | 2.63M | if (digits_queued == kMaxSmallPowerOfTen) { |
261 | 290k | MultiplyBy(kTenToNth[kMaxSmallPowerOfTen]); |
262 | 290k | AddWithCarry(0, queued); |
263 | 290k | queued = digits_queued = 0; |
264 | 290k | } |
265 | 2.63M | } |
266 | | // Encode any remaining digits. |
267 | 7.90k | if (digits_queued) { |
268 | 7.39k | MultiplyBy(kTenToNth[digits_queued]); |
269 | 7.39k | AddWithCarry(0, queued); |
270 | 7.39k | } |
271 | | |
272 | | // If any insignificant digits remain, we will drop them. But if we have not |
273 | | // yet read the decimal point, then we have to adjust the exponent to account |
274 | | // for the dropped digits. |
275 | 7.90k | if (begin < end && !after_decimal_point) { |
276 | | // This call to std::find will result in a pointer either to the decimal |
277 | | // point, or to the end of our buffer if there was none. |
278 | | // |
279 | | // Either way, [begin, decimal_point) will contain the set of dropped digits |
280 | | // that require an exponent adjustment. |
281 | 407 | const char* decimal_point = std::find(begin, end, '.'); |
282 | 407 | exponent_adjust += (decimal_point - begin); |
283 | 407 | } |
284 | 7.90k | return exponent_adjust; |
285 | 7.90k | } Unexecuted instantiation: absl::strings_internal::BigUnsigned<4>::ReadDigits(char const*, char const*, int) absl::strings_internal::BigUnsigned<84>::ReadDigits(char const*, char const*, int) Line | Count | Source | 194 | 7.90k | int significant_digits) { | 195 | 7.90k | assert(significant_digits <= Digits10() + 1); | 196 | 0 | SetToZero(); | 197 | | | 198 | 7.90k | bool after_decimal_point = false; | 199 | | // Discard any leading zeroes before the decimal point | 200 | 105k | while (begin < end && *begin == '0') { | 201 | 98.0k | ++begin; | 202 | 98.0k | } | 203 | 7.90k | int dropped_digits = 0; | 204 | | // Discard any trailing zeroes. These may or may not be after the decimal | 205 | | // point. | 206 | 1.85M | while (begin < end && *std::prev(end) == '0') { | 207 | 1.84M | --end; | 208 | 1.84M | ++dropped_digits; | 209 | 1.84M | } | 210 | 7.90k | if (begin < end && *std::prev(end) == '.') { | 211 | | // If the string ends in '.', either before or after dropping zeroes, then | 212 | | // drop the decimal point and look for more digits to drop. | 213 | 424 | dropped_digits = 0; | 214 | 424 | --end; | 215 | 674 | while (begin < end && *std::prev(end) == '0') { | 216 | 250 | --end; | 217 | 250 | ++dropped_digits; | 218 | 250 | } | 219 | 7.48k | } else if (dropped_digits) { | 220 | | // We dropped digits, and aren't sure if they're before or after the decimal | 221 | | // point. Figure that out now. | 222 | 892 | const char* dp = std::find(begin, end, '.'); | 223 | 892 | if (dp != end) { | 224 | | // The dropped trailing digits were after the decimal point, so don't | 225 | | // count them. | 226 | 636 | dropped_digits = 0; | 227 | 636 | } | 228 | 892 | } | 229 | | // Any non-fraction digits we dropped need to be accounted for in our exponent | 230 | | // adjustment. | 231 | 7.90k | int exponent_adjust = dropped_digits; | 232 | | | 233 | 7.90k | uint32_t queued = 0; | 234 | 7.90k | int digits_queued = 0; | 235 | 2.65M | for (; begin != end && significant_digits > 0; ++begin) { | 236 | 2.64M | if (*begin == '.') { | 237 | 6.02k | after_decimal_point = true; | 238 | 6.02k | continue; | 239 | 6.02k | } | 240 | 2.63M | if (after_decimal_point) { | 241 | | // For each fractional digit we emit in our parsed integer, adjust our | 242 | | // decimal exponent to compensate. | 243 | 2.23M | --exponent_adjust; | 244 | 2.23M | } | 245 | 2.63M | char digit = (*begin - '0'); | 246 | 2.63M | --significant_digits; | 247 | 2.63M | if (significant_digits == 0 && std::next(begin) != end && | 248 | 2.63M | (digit == 0 || digit == 5)) { | 249 | | // If this is the very last significant digit, but insignificant digits | 250 | | // remain, we know that the last of those remaining significant digits is | 251 | | // nonzero. (If it wasn't, we would have stripped it before we got here.) | 252 | | // So if this final digit is a 0 or 5, adjust it upward by 1. | 253 | | // | 254 | | // This adjustment is what allows incredibly large mantissas ending in | 255 | | // 500000...000000000001 to correctly round up, rather than to nearest. | 256 | 2.18k | ++digit; | 257 | 2.18k | } | 258 | 2.63M | queued = 10 * queued + static_cast<uint32_t>(digit); | 259 | 2.63M | ++digits_queued; | 260 | 2.63M | if (digits_queued == kMaxSmallPowerOfTen) { | 261 | 290k | MultiplyBy(kTenToNth[kMaxSmallPowerOfTen]); | 262 | 290k | AddWithCarry(0, queued); | 263 | 290k | queued = digits_queued = 0; | 264 | 290k | } | 265 | 2.63M | } | 266 | | // Encode any remaining digits. | 267 | 7.90k | if (digits_queued) { | 268 | 7.39k | MultiplyBy(kTenToNth[digits_queued]); | 269 | 7.39k | AddWithCarry(0, queued); | 270 | 7.39k | } | 271 | | | 272 | | // If any insignificant digits remain, we will drop them. But if we have not | 273 | | // yet read the decimal point, then we have to adjust the exponent to account | 274 | | // for the dropped digits. | 275 | 7.90k | if (begin < end && !after_decimal_point) { | 276 | | // This call to std::find will result in a pointer either to the decimal | 277 | | // point, or to the end of our buffer if there was none. | 278 | | // | 279 | | // Either way, [begin, decimal_point) will contain the set of dropped digits | 280 | | // that require an exponent adjustment. | 281 | 407 | const char* decimal_point = std::find(begin, end, '.'); | 282 | 407 | exponent_adjust += (decimal_point - begin); | 283 | 407 | } | 284 | 7.90k | return exponent_adjust; | 285 | 7.90k | } |
|
286 | | |
287 | | template <int max_words> |
288 | | /* static */ BigUnsigned<max_words> BigUnsigned<max_words>::FiveToTheNth( |
289 | 6.51k | int n) { |
290 | 6.51k | BigUnsigned answer(1u); |
291 | | |
292 | | // Seed from the table of large powers, if possible. |
293 | 6.51k | bool first_pass = true; |
294 | 13.1k | while (n >= kLargePowerOfFiveStep) { |
295 | 6.59k | int big_power = |
296 | 6.59k | std::min(n / kLargePowerOfFiveStep, kLargestPowerOfFiveIndex); |
297 | 6.59k | if (first_pass) { |
298 | | // just copy, rather than multiplying by 1 |
299 | 4.09k | std::copy_n(LargePowerOfFiveData(big_power), |
300 | 4.09k | LargePowerOfFiveSize(big_power), answer.words_); |
301 | 4.09k | answer.size_ = LargePowerOfFiveSize(big_power); |
302 | 4.09k | first_pass = false; |
303 | 4.09k | } else { |
304 | 2.50k | answer.MultiplyBy(LargePowerOfFiveSize(big_power), |
305 | 2.50k | LargePowerOfFiveData(big_power)); |
306 | 2.50k | } |
307 | 6.59k | n -= kLargePowerOfFiveStep * big_power; |
308 | 6.59k | } |
309 | 6.51k | answer.MultiplyByFiveToTheNth(n); |
310 | 6.51k | return answer; |
311 | 6.51k | } Unexecuted instantiation: absl::strings_internal::BigUnsigned<4>::FiveToTheNth(int) absl::strings_internal::BigUnsigned<84>::FiveToTheNth(int) Line | Count | Source | 289 | 6.51k | int n) { | 290 | 6.51k | BigUnsigned answer(1u); | 291 | | | 292 | | // Seed from the table of large powers, if possible. | 293 | 6.51k | bool first_pass = true; | 294 | 13.1k | while (n >= kLargePowerOfFiveStep) { | 295 | 6.59k | int big_power = | 296 | 6.59k | std::min(n / kLargePowerOfFiveStep, kLargestPowerOfFiveIndex); | 297 | 6.59k | if (first_pass) { | 298 | | // just copy, rather than multiplying by 1 | 299 | 4.09k | std::copy_n(LargePowerOfFiveData(big_power), | 300 | 4.09k | LargePowerOfFiveSize(big_power), answer.words_); | 301 | 4.09k | answer.size_ = LargePowerOfFiveSize(big_power); | 302 | 4.09k | first_pass = false; | 303 | 4.09k | } else { | 304 | 2.50k | answer.MultiplyBy(LargePowerOfFiveSize(big_power), | 305 | 2.50k | LargePowerOfFiveData(big_power)); | 306 | 2.50k | } | 307 | 6.59k | n -= kLargePowerOfFiveStep * big_power; | 308 | 6.59k | } | 309 | 6.51k | answer.MultiplyByFiveToTheNth(n); | 310 | 6.51k | return answer; | 311 | 6.51k | } |
|
312 | | |
313 | | template <int max_words> |
314 | | void BigUnsigned<max_words>::MultiplyStep(int original_size, |
315 | | const uint32_t* other_words, |
316 | 289k | int other_size, int step) { |
317 | 289k | int this_i = std::min(original_size - 1, step); |
318 | 289k | int other_i = step - this_i; |
319 | | |
320 | 289k | uint64_t this_word = 0; |
321 | 289k | uint64_t carry = 0; |
322 | 1.74M | for (; this_i >= 0 && other_i < other_size; --this_i, ++other_i) { |
323 | 1.45M | uint64_t product = words_[this_i]; |
324 | 1.45M | product *= other_words[other_i]; |
325 | 1.45M | this_word += product; |
326 | 1.45M | carry += (this_word >> 32); |
327 | 1.45M | this_word &= 0xffffffff; |
328 | 1.45M | } |
329 | 289k | AddWithCarry(step + 1, carry); |
330 | 289k | words_[step] = this_word & 0xffffffff; |
331 | 289k | if (this_word > 0 && size_ <= step) { |
332 | 4.31k | size_ = step + 1; |
333 | 4.31k | } |
334 | 289k | } Unexecuted instantiation: absl::strings_internal::BigUnsigned<4>::MultiplyStep(int, unsigned int const*, int, int) absl::strings_internal::BigUnsigned<84>::MultiplyStep(int, unsigned int const*, int, int) Line | Count | Source | 316 | 289k | int other_size, int step) { | 317 | 289k | int this_i = std::min(original_size - 1, step); | 318 | 289k | int other_i = step - this_i; | 319 | | | 320 | 289k | uint64_t this_word = 0; | 321 | 289k | uint64_t carry = 0; | 322 | 1.74M | for (; this_i >= 0 && other_i < other_size; --this_i, ++other_i) { | 323 | 1.45M | uint64_t product = words_[this_i]; | 324 | 1.45M | product *= other_words[other_i]; | 325 | 1.45M | this_word += product; | 326 | 1.45M | carry += (this_word >> 32); | 327 | 1.45M | this_word &= 0xffffffff; | 328 | 1.45M | } | 329 | 289k | AddWithCarry(step + 1, carry); | 330 | 289k | words_[step] = this_word & 0xffffffff; | 331 | 289k | if (this_word > 0 && size_ <= step) { | 332 | 4.31k | size_ = step + 1; | 333 | 4.31k | } | 334 | 289k | } |
|
335 | | |
336 | | template <int max_words> |
337 | 0 | std::string BigUnsigned<max_words>::ToString() const { |
338 | 0 | BigUnsigned<max_words> copy = *this; |
339 | 0 | std::string result; |
340 | | // Build result in reverse order |
341 | 0 | while (copy.size() > 0) { |
342 | 0 | uint32_t next_digit = copy.DivMod<10>(); |
343 | 0 | result.push_back('0' + static_cast<char>(next_digit)); |
344 | 0 | } |
345 | 0 | if (result.empty()) { |
346 | 0 | result.push_back('0'); |
347 | 0 | } |
348 | 0 | std::reverse(result.begin(), result.end()); |
349 | 0 | return result; |
350 | 0 | } Unexecuted instantiation: absl::strings_internal::BigUnsigned<4>::ToString() const Unexecuted instantiation: absl::strings_internal::BigUnsigned<84>::ToString() const |
351 | | |
352 | | template class BigUnsigned<4>; |
353 | | template class BigUnsigned<84>; |
354 | | |
355 | | } // namespace strings_internal |
356 | | ABSL_NAMESPACE_END |
357 | | } // namespace absl |