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