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