]>
Commit | Line | Data |
---|---|---|
0f5d89e8 A |
1 | // © 2018 and later: Unicode, Inc. and others. |
2 | // License & terms of use: http://www.unicode.org/copyright.html | |
3 | // | |
4 | // From the double-conversion library. Original license: | |
5 | // | |
6 | // Copyright 2010 the V8 project authors. All rights reserved. | |
7 | // Redistribution and use in source and binary forms, with or without | |
8 | // modification, are permitted provided that the following conditions are | |
9 | // met: | |
10 | // | |
11 | // * Redistributions of source code must retain the above copyright | |
12 | // notice, this list of conditions and the following disclaimer. | |
13 | // * Redistributions in binary form must reproduce the above | |
14 | // copyright notice, this list of conditions and the following | |
15 | // disclaimer in the documentation and/or other materials provided | |
16 | // with the distribution. | |
17 | // * Neither the name of Google Inc. nor the names of its | |
18 | // contributors may be used to endorse or promote products derived | |
19 | // from this software without specific prior written permission. | |
20 | // | |
21 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
22 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
23 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
24 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
25 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
26 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
27 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
28 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
29 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
30 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
31 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
32 | ||
33 | // ICU PATCH: ifdef around UCONFIG_NO_FORMATTING | |
34 | #include "unicode/utypes.h" | |
35 | #if !UCONFIG_NO_FORMATTING | |
36 | ||
37 | // ICU PATCH: Customize header file paths for ICU. | |
38 | ||
39 | #include "double-conversion-bignum.h" | |
40 | #include "double-conversion-utils.h" | |
41 | ||
42 | // ICU PATCH: Wrap in ICU namespace | |
43 | U_NAMESPACE_BEGIN | |
44 | ||
45 | namespace double_conversion { | |
46 | ||
47 | Bignum::Bignum() | |
3d1f044b | 48 | : bigits_buffer_(), bigits_(bigits_buffer_, kBigitCapacity), used_digits_(0), exponent_(0) { |
0f5d89e8 A |
49 | for (int i = 0; i < kBigitCapacity; ++i) { |
50 | bigits_[i] = 0; | |
51 | } | |
52 | } | |
53 | ||
54 | ||
55 | template<typename S> | |
56 | static int BitSize(S value) { | |
57 | (void) value; // Mark variable as used. | |
58 | return 8 * sizeof(value); | |
59 | } | |
60 | ||
61 | // Guaranteed to lie in one Bigit. | |
62 | void Bignum::AssignUInt16(uint16_t value) { | |
63 | ASSERT(kBigitSize >= BitSize(value)); | |
64 | Zero(); | |
65 | if (value == 0) return; | |
66 | ||
67 | EnsureCapacity(1); | |
68 | bigits_[0] = value; | |
69 | used_digits_ = 1; | |
70 | } | |
71 | ||
72 | ||
73 | void Bignum::AssignUInt64(uint64_t value) { | |
74 | const int kUInt64Size = 64; | |
75 | ||
76 | Zero(); | |
77 | if (value == 0) return; | |
78 | ||
79 | int needed_bigits = kUInt64Size / kBigitSize + 1; | |
80 | EnsureCapacity(needed_bigits); | |
81 | for (int i = 0; i < needed_bigits; ++i) { | |
82 | bigits_[i] = value & kBigitMask; | |
83 | value = value >> kBigitSize; | |
84 | } | |
85 | used_digits_ = needed_bigits; | |
86 | Clamp(); | |
87 | } | |
88 | ||
89 | ||
90 | void Bignum::AssignBignum(const Bignum& other) { | |
91 | exponent_ = other.exponent_; | |
92 | for (int i = 0; i < other.used_digits_; ++i) { | |
93 | bigits_[i] = other.bigits_[i]; | |
94 | } | |
95 | // Clear the excess digits (if there were any). | |
96 | for (int i = other.used_digits_; i < used_digits_; ++i) { | |
97 | bigits_[i] = 0; | |
98 | } | |
99 | used_digits_ = other.used_digits_; | |
100 | } | |
101 | ||
102 | ||
103 | static uint64_t ReadUInt64(Vector<const char> buffer, | |
104 | int from, | |
105 | int digits_to_read) { | |
106 | uint64_t result = 0; | |
107 | for (int i = from; i < from + digits_to_read; ++i) { | |
108 | int digit = buffer[i] - '0'; | |
109 | ASSERT(0 <= digit && digit <= 9); | |
110 | result = result * 10 + digit; | |
111 | } | |
112 | return result; | |
113 | } | |
114 | ||
115 | ||
116 | void Bignum::AssignDecimalString(Vector<const char> value) { | |
117 | // 2^64 = 18446744073709551616 > 10^19 | |
118 | const int kMaxUint64DecimalDigits = 19; | |
119 | Zero(); | |
120 | int length = value.length(); | |
121 | unsigned int pos = 0; | |
122 | // Let's just say that each digit needs 4 bits. | |
123 | while (length >= kMaxUint64DecimalDigits) { | |
124 | uint64_t digits = ReadUInt64(value, pos, kMaxUint64DecimalDigits); | |
125 | pos += kMaxUint64DecimalDigits; | |
126 | length -= kMaxUint64DecimalDigits; | |
127 | MultiplyByPowerOfTen(kMaxUint64DecimalDigits); | |
128 | AddUInt64(digits); | |
129 | } | |
130 | uint64_t digits = ReadUInt64(value, pos, length); | |
131 | MultiplyByPowerOfTen(length); | |
132 | AddUInt64(digits); | |
133 | Clamp(); | |
134 | } | |
135 | ||
136 | ||
137 | static int HexCharValue(char c) { | |
138 | if ('0' <= c && c <= '9') return c - '0'; | |
139 | if ('a' <= c && c <= 'f') return 10 + c - 'a'; | |
140 | ASSERT('A' <= c && c <= 'F'); | |
141 | return 10 + c - 'A'; | |
142 | } | |
143 | ||
144 | ||
145 | void Bignum::AssignHexString(Vector<const char> value) { | |
146 | Zero(); | |
147 | int length = value.length(); | |
148 | ||
149 | int needed_bigits = length * 4 / kBigitSize + 1; | |
150 | EnsureCapacity(needed_bigits); | |
151 | int string_index = length - 1; | |
152 | for (int i = 0; i < needed_bigits - 1; ++i) { | |
153 | // These bigits are guaranteed to be "full". | |
154 | Chunk current_bigit = 0; | |
155 | for (int j = 0; j < kBigitSize / 4; j++) { | |
156 | current_bigit += HexCharValue(value[string_index--]) << (j * 4); | |
157 | } | |
158 | bigits_[i] = current_bigit; | |
159 | } | |
160 | used_digits_ = needed_bigits - 1; | |
161 | ||
162 | Chunk most_significant_bigit = 0; // Could be = 0; | |
163 | for (int j = 0; j <= string_index; ++j) { | |
164 | most_significant_bigit <<= 4; | |
165 | most_significant_bigit += HexCharValue(value[j]); | |
166 | } | |
167 | if (most_significant_bigit != 0) { | |
168 | bigits_[used_digits_] = most_significant_bigit; | |
169 | used_digits_++; | |
170 | } | |
171 | Clamp(); | |
172 | } | |
173 | ||
174 | ||
175 | void Bignum::AddUInt64(uint64_t operand) { | |
176 | if (operand == 0) return; | |
177 | Bignum other; | |
178 | other.AssignUInt64(operand); | |
179 | AddBignum(other); | |
180 | } | |
181 | ||
182 | ||
183 | void Bignum::AddBignum(const Bignum& other) { | |
184 | ASSERT(IsClamped()); | |
185 | ASSERT(other.IsClamped()); | |
186 | ||
187 | // If this has a greater exponent than other append zero-bigits to this. | |
188 | // After this call exponent_ <= other.exponent_. | |
189 | Align(other); | |
190 | ||
191 | // There are two possibilities: | |
192 | // aaaaaaaaaaa 0000 (where the 0s represent a's exponent) | |
193 | // bbbbb 00000000 | |
194 | // ---------------- | |
195 | // ccccccccccc 0000 | |
196 | // or | |
197 | // aaaaaaaaaa 0000 | |
198 | // bbbbbbbbb 0000000 | |
199 | // ----------------- | |
200 | // cccccccccccc 0000 | |
201 | // In both cases we might need a carry bigit. | |
202 | ||
203 | EnsureCapacity(1 + Max(BigitLength(), other.BigitLength()) - exponent_); | |
204 | Chunk carry = 0; | |
205 | int bigit_pos = other.exponent_ - exponent_; | |
206 | ASSERT(bigit_pos >= 0); | |
207 | for (int i = 0; i < other.used_digits_; ++i) { | |
208 | Chunk sum = bigits_[bigit_pos] + other.bigits_[i] + carry; | |
209 | bigits_[bigit_pos] = sum & kBigitMask; | |
210 | carry = sum >> kBigitSize; | |
211 | bigit_pos++; | |
212 | } | |
213 | ||
214 | while (carry != 0) { | |
215 | Chunk sum = bigits_[bigit_pos] + carry; | |
216 | bigits_[bigit_pos] = sum & kBigitMask; | |
217 | carry = sum >> kBigitSize; | |
218 | bigit_pos++; | |
219 | } | |
220 | used_digits_ = Max(bigit_pos, used_digits_); | |
221 | ASSERT(IsClamped()); | |
222 | } | |
223 | ||
224 | ||
225 | void Bignum::SubtractBignum(const Bignum& other) { | |
226 | ASSERT(IsClamped()); | |
227 | ASSERT(other.IsClamped()); | |
228 | // We require this to be bigger than other. | |
229 | ASSERT(LessEqual(other, *this)); | |
230 | ||
231 | Align(other); | |
232 | ||
233 | int offset = other.exponent_ - exponent_; | |
234 | Chunk borrow = 0; | |
235 | int i; | |
236 | for (i = 0; i < other.used_digits_; ++i) { | |
237 | ASSERT((borrow == 0) || (borrow == 1)); | |
238 | Chunk difference = bigits_[i + offset] - other.bigits_[i] - borrow; | |
239 | bigits_[i + offset] = difference & kBigitMask; | |
240 | borrow = difference >> (kChunkSize - 1); | |
241 | } | |
242 | while (borrow != 0) { | |
243 | Chunk difference = bigits_[i + offset] - borrow; | |
244 | bigits_[i + offset] = difference & kBigitMask; | |
245 | borrow = difference >> (kChunkSize - 1); | |
246 | ++i; | |
247 | } | |
248 | Clamp(); | |
249 | } | |
250 | ||
251 | ||
252 | void Bignum::ShiftLeft(int shift_amount) { | |
253 | if (used_digits_ == 0) return; | |
254 | exponent_ += shift_amount / kBigitSize; | |
255 | int local_shift = shift_amount % kBigitSize; | |
256 | EnsureCapacity(used_digits_ + 1); | |
257 | BigitsShiftLeft(local_shift); | |
258 | } | |
259 | ||
260 | ||
261 | void Bignum::MultiplyByUInt32(uint32_t factor) { | |
262 | if (factor == 1) return; | |
263 | if (factor == 0) { | |
264 | Zero(); | |
265 | return; | |
266 | } | |
267 | if (used_digits_ == 0) return; | |
268 | ||
269 | // The product of a bigit with the factor is of size kBigitSize + 32. | |
270 | // Assert that this number + 1 (for the carry) fits into double chunk. | |
271 | ASSERT(kDoubleChunkSize >= kBigitSize + 32 + 1); | |
272 | DoubleChunk carry = 0; | |
273 | for (int i = 0; i < used_digits_; ++i) { | |
274 | DoubleChunk product = static_cast<DoubleChunk>(factor) * bigits_[i] + carry; | |
275 | bigits_[i] = static_cast<Chunk>(product & kBigitMask); | |
276 | carry = (product >> kBigitSize); | |
277 | } | |
278 | while (carry != 0) { | |
279 | EnsureCapacity(used_digits_ + 1); | |
280 | bigits_[used_digits_] = carry & kBigitMask; | |
281 | used_digits_++; | |
282 | carry >>= kBigitSize; | |
283 | } | |
284 | } | |
285 | ||
286 | ||
287 | void Bignum::MultiplyByUInt64(uint64_t factor) { | |
288 | if (factor == 1) return; | |
289 | if (factor == 0) { | |
290 | Zero(); | |
291 | return; | |
292 | } | |
293 | ASSERT(kBigitSize < 32); | |
294 | uint64_t carry = 0; | |
295 | uint64_t low = factor & 0xFFFFFFFF; | |
296 | uint64_t high = factor >> 32; | |
297 | for (int i = 0; i < used_digits_; ++i) { | |
298 | uint64_t product_low = low * bigits_[i]; | |
299 | uint64_t product_high = high * bigits_[i]; | |
300 | uint64_t tmp = (carry & kBigitMask) + product_low; | |
301 | bigits_[i] = tmp & kBigitMask; | |
302 | carry = (carry >> kBigitSize) + (tmp >> kBigitSize) + | |
303 | (product_high << (32 - kBigitSize)); | |
304 | } | |
305 | while (carry != 0) { | |
306 | EnsureCapacity(used_digits_ + 1); | |
307 | bigits_[used_digits_] = carry & kBigitMask; | |
308 | used_digits_++; | |
309 | carry >>= kBigitSize; | |
310 | } | |
311 | } | |
312 | ||
313 | ||
314 | void Bignum::MultiplyByPowerOfTen(int exponent) { | |
315 | const uint64_t kFive27 = UINT64_2PART_C(0x6765c793, fa10079d); | |
316 | const uint16_t kFive1 = 5; | |
317 | const uint16_t kFive2 = kFive1 * 5; | |
318 | const uint16_t kFive3 = kFive2 * 5; | |
319 | const uint16_t kFive4 = kFive3 * 5; | |
320 | const uint16_t kFive5 = kFive4 * 5; | |
321 | const uint16_t kFive6 = kFive5 * 5; | |
322 | const uint32_t kFive7 = kFive6 * 5; | |
323 | const uint32_t kFive8 = kFive7 * 5; | |
324 | const uint32_t kFive9 = kFive8 * 5; | |
325 | const uint32_t kFive10 = kFive9 * 5; | |
326 | const uint32_t kFive11 = kFive10 * 5; | |
327 | const uint32_t kFive12 = kFive11 * 5; | |
328 | const uint32_t kFive13 = kFive12 * 5; | |
329 | const uint32_t kFive1_to_12[] = | |
330 | { kFive1, kFive2, kFive3, kFive4, kFive5, kFive6, | |
331 | kFive7, kFive8, kFive9, kFive10, kFive11, kFive12 }; | |
332 | ||
333 | ASSERT(exponent >= 0); | |
334 | if (exponent == 0) return; | |
335 | if (used_digits_ == 0) return; | |
336 | ||
337 | // We shift by exponent at the end just before returning. | |
338 | int remaining_exponent = exponent; | |
339 | while (remaining_exponent >= 27) { | |
340 | MultiplyByUInt64(kFive27); | |
341 | remaining_exponent -= 27; | |
342 | } | |
343 | while (remaining_exponent >= 13) { | |
344 | MultiplyByUInt32(kFive13); | |
345 | remaining_exponent -= 13; | |
346 | } | |
347 | if (remaining_exponent > 0) { | |
348 | MultiplyByUInt32(kFive1_to_12[remaining_exponent - 1]); | |
349 | } | |
350 | ShiftLeft(exponent); | |
351 | } | |
352 | ||
353 | ||
354 | void Bignum::Square() { | |
355 | ASSERT(IsClamped()); | |
356 | int product_length = 2 * used_digits_; | |
357 | EnsureCapacity(product_length); | |
358 | ||
359 | // Comba multiplication: compute each column separately. | |
360 | // Example: r = a2a1a0 * b2b1b0. | |
361 | // r = 1 * a0b0 + | |
362 | // 10 * (a1b0 + a0b1) + | |
363 | // 100 * (a2b0 + a1b1 + a0b2) + | |
364 | // 1000 * (a2b1 + a1b2) + | |
365 | // 10000 * a2b2 | |
366 | // | |
367 | // In the worst case we have to accumulate nb-digits products of digit*digit. | |
368 | // | |
369 | // Assert that the additional number of bits in a DoubleChunk are enough to | |
370 | // sum up used_digits of Bigit*Bigit. | |
371 | if ((1 << (2 * (kChunkSize - kBigitSize))) <= used_digits_) { | |
372 | UNIMPLEMENTED(); | |
373 | } | |
374 | DoubleChunk accumulator = 0; | |
375 | // First shift the digits so we don't overwrite them. | |
376 | int copy_offset = used_digits_; | |
377 | for (int i = 0; i < used_digits_; ++i) { | |
378 | bigits_[copy_offset + i] = bigits_[i]; | |
379 | } | |
380 | // We have two loops to avoid some 'if's in the loop. | |
381 | for (int i = 0; i < used_digits_; ++i) { | |
382 | // Process temporary digit i with power i. | |
383 | // The sum of the two indices must be equal to i. | |
384 | int bigit_index1 = i; | |
385 | int bigit_index2 = 0; | |
386 | // Sum all of the sub-products. | |
387 | while (bigit_index1 >= 0) { | |
388 | Chunk chunk1 = bigits_[copy_offset + bigit_index1]; | |
389 | Chunk chunk2 = bigits_[copy_offset + bigit_index2]; | |
390 | accumulator += static_cast<DoubleChunk>(chunk1) * chunk2; | |
391 | bigit_index1--; | |
392 | bigit_index2++; | |
393 | } | |
394 | bigits_[i] = static_cast<Chunk>(accumulator) & kBigitMask; | |
395 | accumulator >>= kBigitSize; | |
396 | } | |
397 | for (int i = used_digits_; i < product_length; ++i) { | |
398 | int bigit_index1 = used_digits_ - 1; | |
399 | int bigit_index2 = i - bigit_index1; | |
400 | // Invariant: sum of both indices is again equal to i. | |
401 | // Inner loop runs 0 times on last iteration, emptying accumulator. | |
402 | while (bigit_index2 < used_digits_) { | |
403 | Chunk chunk1 = bigits_[copy_offset + bigit_index1]; | |
404 | Chunk chunk2 = bigits_[copy_offset + bigit_index2]; | |
405 | accumulator += static_cast<DoubleChunk>(chunk1) * chunk2; | |
406 | bigit_index1--; | |
407 | bigit_index2++; | |
408 | } | |
409 | // The overwritten bigits_[i] will never be read in further loop iterations, | |
410 | // because bigit_index1 and bigit_index2 are always greater | |
411 | // than i - used_digits_. | |
412 | bigits_[i] = static_cast<Chunk>(accumulator) & kBigitMask; | |
413 | accumulator >>= kBigitSize; | |
414 | } | |
415 | // Since the result was guaranteed to lie inside the number the | |
416 | // accumulator must be 0 now. | |
417 | ASSERT(accumulator == 0); | |
418 | ||
419 | // Don't forget to update the used_digits and the exponent. | |
420 | used_digits_ = product_length; | |
421 | exponent_ *= 2; | |
422 | Clamp(); | |
423 | } | |
424 | ||
425 | ||
426 | void Bignum::AssignPowerUInt16(uint16_t base, int power_exponent) { | |
427 | ASSERT(base != 0); | |
428 | ASSERT(power_exponent >= 0); | |
429 | if (power_exponent == 0) { | |
430 | AssignUInt16(1); | |
431 | return; | |
432 | } | |
433 | Zero(); | |
434 | int shifts = 0; | |
435 | // We expect base to be in range 2-32, and most often to be 10. | |
436 | // It does not make much sense to implement different algorithms for counting | |
437 | // the bits. | |
438 | while ((base & 1) == 0) { | |
439 | base >>= 1; | |
440 | shifts++; | |
441 | } | |
442 | int bit_size = 0; | |
443 | int tmp_base = base; | |
444 | while (tmp_base != 0) { | |
445 | tmp_base >>= 1; | |
446 | bit_size++; | |
447 | } | |
448 | int final_size = bit_size * power_exponent; | |
449 | // 1 extra bigit for the shifting, and one for rounded final_size. | |
450 | EnsureCapacity(final_size / kBigitSize + 2); | |
451 | ||
452 | // Left to Right exponentiation. | |
453 | int mask = 1; | |
454 | while (power_exponent >= mask) mask <<= 1; | |
455 | ||
456 | // The mask is now pointing to the bit above the most significant 1-bit of | |
457 | // power_exponent. | |
458 | // Get rid of first 1-bit; | |
459 | mask >>= 2; | |
460 | uint64_t this_value = base; | |
461 | ||
3d1f044b | 462 | bool delayed_multiplication = false; |
0f5d89e8 A |
463 | const uint64_t max_32bits = 0xFFFFFFFF; |
464 | while (mask != 0 && this_value <= max_32bits) { | |
465 | this_value = this_value * this_value; | |
466 | // Verify that there is enough space in this_value to perform the | |
467 | // multiplication. The first bit_size bits must be 0. | |
468 | if ((power_exponent & mask) != 0) { | |
3d1f044b | 469 | ASSERT(bit_size > 0); |
0f5d89e8 A |
470 | uint64_t base_bits_mask = |
471 | ~((static_cast<uint64_t>(1) << (64 - bit_size)) - 1); | |
472 | bool high_bits_zero = (this_value & base_bits_mask) == 0; | |
473 | if (high_bits_zero) { | |
474 | this_value *= base; | |
475 | } else { | |
3d1f044b | 476 | delayed_multiplication = true; |
0f5d89e8 A |
477 | } |
478 | } | |
479 | mask >>= 1; | |
480 | } | |
481 | AssignUInt64(this_value); | |
3d1f044b | 482 | if (delayed_multiplication) { |
0f5d89e8 A |
483 | MultiplyByUInt32(base); |
484 | } | |
485 | ||
486 | // Now do the same thing as a bignum. | |
487 | while (mask != 0) { | |
488 | Square(); | |
489 | if ((power_exponent & mask) != 0) { | |
490 | MultiplyByUInt32(base); | |
491 | } | |
492 | mask >>= 1; | |
493 | } | |
494 | ||
495 | // And finally add the saved shifts. | |
496 | ShiftLeft(shifts * power_exponent); | |
497 | } | |
498 | ||
499 | ||
500 | // Precondition: this/other < 16bit. | |
501 | uint16_t Bignum::DivideModuloIntBignum(const Bignum& other) { | |
502 | ASSERT(IsClamped()); | |
503 | ASSERT(other.IsClamped()); | |
504 | ASSERT(other.used_digits_ > 0); | |
505 | ||
506 | // Easy case: if we have less digits than the divisor than the result is 0. | |
507 | // Note: this handles the case where this == 0, too. | |
508 | if (BigitLength() < other.BigitLength()) { | |
509 | return 0; | |
510 | } | |
511 | ||
512 | Align(other); | |
513 | ||
514 | uint16_t result = 0; | |
515 | ||
516 | // Start by removing multiples of 'other' until both numbers have the same | |
517 | // number of digits. | |
518 | while (BigitLength() > other.BigitLength()) { | |
519 | // This naive approach is extremely inefficient if `this` divided by other | |
520 | // is big. This function is implemented for doubleToString where | |
521 | // the result should be small (less than 10). | |
522 | ASSERT(other.bigits_[other.used_digits_ - 1] >= ((1 << kBigitSize) / 16)); | |
523 | ASSERT(bigits_[used_digits_ - 1] < 0x10000); | |
524 | // Remove the multiples of the first digit. | |
525 | // Example this = 23 and other equals 9. -> Remove 2 multiples. | |
526 | result += static_cast<uint16_t>(bigits_[used_digits_ - 1]); | |
527 | SubtractTimes(other, bigits_[used_digits_ - 1]); | |
528 | } | |
529 | ||
530 | ASSERT(BigitLength() == other.BigitLength()); | |
531 | ||
532 | // Both bignums are at the same length now. | |
533 | // Since other has more than 0 digits we know that the access to | |
534 | // bigits_[used_digits_ - 1] is safe. | |
535 | Chunk this_bigit = bigits_[used_digits_ - 1]; | |
536 | Chunk other_bigit = other.bigits_[other.used_digits_ - 1]; | |
537 | ||
538 | if (other.used_digits_ == 1) { | |
539 | // Shortcut for easy (and common) case. | |
540 | int quotient = this_bigit / other_bigit; | |
541 | bigits_[used_digits_ - 1] = this_bigit - other_bigit * quotient; | |
542 | ASSERT(quotient < 0x10000); | |
543 | result += static_cast<uint16_t>(quotient); | |
544 | Clamp(); | |
545 | return result; | |
546 | } | |
547 | ||
548 | int division_estimate = this_bigit / (other_bigit + 1); | |
549 | ASSERT(division_estimate < 0x10000); | |
550 | result += static_cast<uint16_t>(division_estimate); | |
551 | SubtractTimes(other, division_estimate); | |
552 | ||
553 | if (other_bigit * (division_estimate + 1) > this_bigit) { | |
554 | // No need to even try to subtract. Even if other's remaining digits were 0 | |
555 | // another subtraction would be too much. | |
556 | return result; | |
557 | } | |
558 | ||
559 | while (LessEqual(other, *this)) { | |
560 | SubtractBignum(other); | |
561 | result++; | |
562 | } | |
563 | return result; | |
564 | } | |
565 | ||
566 | ||
567 | template<typename S> | |
568 | static int SizeInHexChars(S number) { | |
569 | ASSERT(number > 0); | |
570 | int result = 0; | |
571 | while (number != 0) { | |
572 | number >>= 4; | |
573 | result++; | |
574 | } | |
575 | return result; | |
576 | } | |
577 | ||
578 | ||
579 | static char HexCharOfValue(int value) { | |
580 | ASSERT(0 <= value && value <= 16); | |
581 | if (value < 10) return static_cast<char>(value + '0'); | |
582 | return static_cast<char>(value - 10 + 'A'); | |
583 | } | |
584 | ||
585 | ||
586 | bool Bignum::ToHexString(char* buffer, int buffer_size) const { | |
587 | ASSERT(IsClamped()); | |
588 | // Each bigit must be printable as separate hex-character. | |
589 | ASSERT(kBigitSize % 4 == 0); | |
590 | const int kHexCharsPerBigit = kBigitSize / 4; | |
591 | ||
592 | if (used_digits_ == 0) { | |
593 | if (buffer_size < 2) return false; | |
594 | buffer[0] = '0'; | |
595 | buffer[1] = '\0'; | |
596 | return true; | |
597 | } | |
598 | // We add 1 for the terminating '\0' character. | |
599 | int needed_chars = (BigitLength() - 1) * kHexCharsPerBigit + | |
600 | SizeInHexChars(bigits_[used_digits_ - 1]) + 1; | |
601 | if (needed_chars > buffer_size) return false; | |
602 | int string_index = needed_chars - 1; | |
603 | buffer[string_index--] = '\0'; | |
604 | for (int i = 0; i < exponent_; ++i) { | |
605 | for (int j = 0; j < kHexCharsPerBigit; ++j) { | |
606 | buffer[string_index--] = '0'; | |
607 | } | |
608 | } | |
609 | for (int i = 0; i < used_digits_ - 1; ++i) { | |
610 | Chunk current_bigit = bigits_[i]; | |
611 | for (int j = 0; j < kHexCharsPerBigit; ++j) { | |
612 | buffer[string_index--] = HexCharOfValue(current_bigit & 0xF); | |
613 | current_bigit >>= 4; | |
614 | } | |
615 | } | |
616 | // And finally the last bigit. | |
617 | Chunk most_significant_bigit = bigits_[used_digits_ - 1]; | |
618 | while (most_significant_bigit != 0) { | |
619 | buffer[string_index--] = HexCharOfValue(most_significant_bigit & 0xF); | |
620 | most_significant_bigit >>= 4; | |
621 | } | |
622 | return true; | |
623 | } | |
624 | ||
625 | ||
626 | Bignum::Chunk Bignum::BigitAt(int index) const { | |
627 | if (index >= BigitLength()) return 0; | |
628 | if (index < exponent_) return 0; | |
629 | return bigits_[index - exponent_]; | |
630 | } | |
631 | ||
632 | ||
633 | int Bignum::Compare(const Bignum& a, const Bignum& b) { | |
634 | ASSERT(a.IsClamped()); | |
635 | ASSERT(b.IsClamped()); | |
636 | int bigit_length_a = a.BigitLength(); | |
637 | int bigit_length_b = b.BigitLength(); | |
638 | if (bigit_length_a < bigit_length_b) return -1; | |
639 | if (bigit_length_a > bigit_length_b) return +1; | |
640 | for (int i = bigit_length_a - 1; i >= Min(a.exponent_, b.exponent_); --i) { | |
641 | Chunk bigit_a = a.BigitAt(i); | |
642 | Chunk bigit_b = b.BigitAt(i); | |
643 | if (bigit_a < bigit_b) return -1; | |
644 | if (bigit_a > bigit_b) return +1; | |
645 | // Otherwise they are equal up to this digit. Try the next digit. | |
646 | } | |
647 | return 0; | |
648 | } | |
649 | ||
650 | ||
651 | int Bignum::PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c) { | |
652 | ASSERT(a.IsClamped()); | |
653 | ASSERT(b.IsClamped()); | |
654 | ASSERT(c.IsClamped()); | |
655 | if (a.BigitLength() < b.BigitLength()) { | |
656 | return PlusCompare(b, a, c); | |
657 | } | |
658 | if (a.BigitLength() + 1 < c.BigitLength()) return -1; | |
659 | if (a.BigitLength() > c.BigitLength()) return +1; | |
660 | // The exponent encodes 0-bigits. So if there are more 0-digits in 'a' than | |
661 | // 'b' has digits, then the bigit-length of 'a'+'b' must be equal to the one | |
662 | // of 'a'. | |
663 | if (a.exponent_ >= b.BigitLength() && a.BigitLength() < c.BigitLength()) { | |
664 | return -1; | |
665 | } | |
666 | ||
667 | Chunk borrow = 0; | |
668 | // Starting at min_exponent all digits are == 0. So no need to compare them. | |
669 | int min_exponent = Min(Min(a.exponent_, b.exponent_), c.exponent_); | |
670 | for (int i = c.BigitLength() - 1; i >= min_exponent; --i) { | |
671 | Chunk chunk_a = a.BigitAt(i); | |
672 | Chunk chunk_b = b.BigitAt(i); | |
673 | Chunk chunk_c = c.BigitAt(i); | |
674 | Chunk sum = chunk_a + chunk_b; | |
675 | if (sum > chunk_c + borrow) { | |
676 | return +1; | |
677 | } else { | |
678 | borrow = chunk_c + borrow - sum; | |
679 | if (borrow > 1) return -1; | |
680 | borrow <<= kBigitSize; | |
681 | } | |
682 | } | |
683 | if (borrow == 0) return 0; | |
684 | return -1; | |
685 | } | |
686 | ||
687 | ||
688 | void Bignum::Clamp() { | |
689 | while (used_digits_ > 0 && bigits_[used_digits_ - 1] == 0) { | |
690 | used_digits_--; | |
691 | } | |
692 | if (used_digits_ == 0) { | |
693 | // Zero. | |
694 | exponent_ = 0; | |
695 | } | |
696 | } | |
697 | ||
698 | ||
699 | bool Bignum::IsClamped() const { | |
700 | return used_digits_ == 0 || bigits_[used_digits_ - 1] != 0; | |
701 | } | |
702 | ||
703 | ||
704 | void Bignum::Zero() { | |
705 | for (int i = 0; i < used_digits_; ++i) { | |
706 | bigits_[i] = 0; | |
707 | } | |
708 | used_digits_ = 0; | |
709 | exponent_ = 0; | |
710 | } | |
711 | ||
712 | ||
713 | void Bignum::Align(const Bignum& other) { | |
714 | if (exponent_ > other.exponent_) { | |
715 | // If "X" represents a "hidden" digit (by the exponent) then we are in the | |
716 | // following case (a == this, b == other): | |
717 | // a: aaaaaaXXXX or a: aaaaaXXX | |
718 | // b: bbbbbbX b: bbbbbbbbXX | |
719 | // We replace some of the hidden digits (X) of a with 0 digits. | |
720 | // a: aaaaaa000X or a: aaaaa0XX | |
721 | int zero_digits = exponent_ - other.exponent_; | |
722 | EnsureCapacity(used_digits_ + zero_digits); | |
723 | for (int i = used_digits_ - 1; i >= 0; --i) { | |
724 | bigits_[i + zero_digits] = bigits_[i]; | |
725 | } | |
726 | for (int i = 0; i < zero_digits; ++i) { | |
727 | bigits_[i] = 0; | |
728 | } | |
729 | used_digits_ += zero_digits; | |
730 | exponent_ -= zero_digits; | |
731 | ASSERT(used_digits_ >= 0); | |
732 | ASSERT(exponent_ >= 0); | |
733 | } | |
734 | } | |
735 | ||
736 | ||
737 | void Bignum::BigitsShiftLeft(int shift_amount) { | |
738 | ASSERT(shift_amount < kBigitSize); | |
739 | ASSERT(shift_amount >= 0); | |
740 | Chunk carry = 0; | |
741 | for (int i = 0; i < used_digits_; ++i) { | |
742 | Chunk new_carry = bigits_[i] >> (kBigitSize - shift_amount); | |
743 | bigits_[i] = ((bigits_[i] << shift_amount) + carry) & kBigitMask; | |
744 | carry = new_carry; | |
745 | } | |
746 | if (carry != 0) { | |
747 | bigits_[used_digits_] = carry; | |
748 | used_digits_++; | |
749 | } | |
750 | } | |
751 | ||
752 | ||
753 | void Bignum::SubtractTimes(const Bignum& other, int factor) { | |
754 | ASSERT(exponent_ <= other.exponent_); | |
755 | if (factor < 3) { | |
756 | for (int i = 0; i < factor; ++i) { | |
757 | SubtractBignum(other); | |
758 | } | |
759 | return; | |
760 | } | |
761 | Chunk borrow = 0; | |
762 | int exponent_diff = other.exponent_ - exponent_; | |
763 | for (int i = 0; i < other.used_digits_; ++i) { | |
764 | DoubleChunk product = static_cast<DoubleChunk>(factor) * other.bigits_[i]; | |
765 | DoubleChunk remove = borrow + product; | |
766 | Chunk difference = bigits_[i + exponent_diff] - (remove & kBigitMask); | |
767 | bigits_[i + exponent_diff] = difference & kBigitMask; | |
768 | borrow = static_cast<Chunk>((difference >> (kChunkSize - 1)) + | |
769 | (remove >> kBigitSize)); | |
770 | } | |
771 | for (int i = other.used_digits_ + exponent_diff; i < used_digits_; ++i) { | |
772 | if (borrow == 0) return; | |
773 | Chunk difference = bigits_[i] - borrow; | |
774 | bigits_[i] = difference & kBigitMask; | |
775 | borrow = difference >> (kChunkSize - 1); | |
776 | } | |
777 | Clamp(); | |
778 | } | |
779 | ||
780 | ||
781 | } // namespace double_conversion | |
782 | ||
783 | // ICU PATCH: Close ICU namespace | |
784 | U_NAMESPACE_END | |
785 | #endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING |