[bigint] Implement toString(radix) for any radix
Power-of-two radixes were supported already; this adds all others (with 2 <= radix <= 36). Bonus: fix digit_div fallback path for divisors with no leading zeros. Bug: v8:6791 Change-Id: Id472667f057ad13338e0d8257a899490490e6f8f Reviewed-on: https://chromium-review.googlesource.com/693316 Commit-Queue: Jakob Kummerow <jkummerow@chromium.org> Reviewed-by: Daniel Ehrenberg <littledan@chromium.org> Cr-Commit-Position: refs/heads/master@{#48323}
This commit is contained in:
parent
8fc10b5af7
commit
da13b8971d
@ -77,6 +77,10 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT
|
||||
HeapNumber::cast(this)->HeapNumberPrint(os);
|
||||
os << ">\n";
|
||||
break;
|
||||
case BIGINT_TYPE:
|
||||
BigInt::cast(this)->BigIntPrint(os);
|
||||
os << "\n";
|
||||
break;
|
||||
case FIXED_DOUBLE_ARRAY_TYPE:
|
||||
FixedDoubleArray::cast(this)->FixedDoubleArrayPrint(os);
|
||||
break;
|
||||
|
@ -238,9 +238,14 @@ Handle<BigInt> BigInt::BitwiseOr(Handle<BigInt> x, Handle<BigInt> y) {
|
||||
}
|
||||
|
||||
MaybeHandle<String> BigInt::ToString(Handle<BigInt> bigint, int radix) {
|
||||
// TODO(jkummerow): Support non-power-of-two radixes.
|
||||
if (!base::bits::IsPowerOfTwo(radix)) radix = 16;
|
||||
return ToStringBasePowerOfTwo(bigint, radix);
|
||||
Isolate* isolate = bigint->GetIsolate();
|
||||
if (bigint->is_zero()) {
|
||||
return isolate->factory()->NewStringFromStaticChars("0");
|
||||
}
|
||||
if (base::bits::IsPowerOfTwo(radix)) {
|
||||
return ToStringBasePowerOfTwo(bigint, radix);
|
||||
}
|
||||
return ToStringGeneric(bigint, radix);
|
||||
}
|
||||
|
||||
void BigInt::Initialize(int length, bool zero_initialize) {
|
||||
@ -927,7 +932,7 @@ Handle<BigInt> BigInt::Copy(Handle<BigInt> source) {
|
||||
// base-N string representation of a number. To increase accuracy, the array
|
||||
// value is the actual value multiplied by 32. To generate this table:
|
||||
// for (var i = 0; i <= 36; i++) { print(Math.ceil(Math.log2(i) * 32) + ","); }
|
||||
uint8_t kMaxBitsPerChar[] = {
|
||||
constexpr uint8_t kMaxBitsPerChar[] = {
|
||||
0, 0, 32, 51, 64, 75, 83, 90, 96, // 0..8
|
||||
102, 107, 111, 115, 119, 122, 126, 128, // 9..16
|
||||
131, 134, 136, 139, 141, 143, 145, 147, // 17..24
|
||||
@ -942,25 +947,16 @@ MaybeHandle<BigInt> BigInt::AllocateFor(Isolate* isolate, int radix,
|
||||
int charcount) {
|
||||
DCHECK(2 <= radix && radix <= 36);
|
||||
DCHECK(charcount >= 0);
|
||||
size_t bits_min;
|
||||
size_t bits_per_char = kMaxBitsPerChar[radix];
|
||||
size_t chars = static_cast<size_t>(charcount);
|
||||
const int roundup = kBitsPerCharTableMultiplier - 1;
|
||||
if (chars <= 1000000) {
|
||||
// More precise path: multiply first, then divide.
|
||||
bits_min = bits_per_char * chars;
|
||||
// Divide by 32 (see table), rounding up.
|
||||
bits_min = (bits_min + roundup) >> kBitsPerCharTableShift;
|
||||
} else {
|
||||
// Overflow avoidance path: divide first, then multiply.
|
||||
// The addition can't overflow because of the int -> size_t cast.
|
||||
bits_min = ((chars + roundup) >> kBitsPerCharTableShift) * bits_per_char;
|
||||
// Check if overflow happened.
|
||||
if (bits_min < chars) {
|
||||
THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kBigIntTooBig),
|
||||
BigInt);
|
||||
}
|
||||
if ((std::numeric_limits<size_t>::max() - roundup) / bits_per_char < chars) {
|
||||
THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kBigIntTooBig),
|
||||
BigInt);
|
||||
}
|
||||
size_t bits_min = bits_per_char * chars;
|
||||
// Divide by 32 (see table), rounding up.
|
||||
bits_min = (bits_min + roundup) >> kBitsPerCharTableShift;
|
||||
if (bits_min > static_cast<size_t>(kMaxInt)) {
|
||||
THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kBigIntTooBig),
|
||||
BigInt);
|
||||
@ -991,16 +987,13 @@ void BigInt::RightTrim() {
|
||||
|
||||
static const char kConversionChars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
// TODO(jkummerow): Add more tests for this when we have a way to construct
|
||||
// multi-digit BigInts.
|
||||
MaybeHandle<String> BigInt::ToStringBasePowerOfTwo(Handle<BigInt> x,
|
||||
int radix) {
|
||||
STATIC_ASSERT(base::bits::IsPowerOfTwo(kDigitBits));
|
||||
DCHECK(base::bits::IsPowerOfTwo(radix));
|
||||
DCHECK(radix >= 2 && radix <= 32);
|
||||
DCHECK(!x->is_zero());
|
||||
Isolate* isolate = x->GetIsolate();
|
||||
// TODO(jkummerow): check in caller?
|
||||
if (x->is_zero()) return isolate->factory()->NewStringFromStaticChars("0");
|
||||
|
||||
const int length = x->length();
|
||||
const bool sign = x->sign();
|
||||
@ -1022,6 +1015,7 @@ MaybeHandle<String> BigInt::ToStringBasePowerOfTwo(Handle<BigInt> x,
|
||||
isolate->factory()
|
||||
->NewRawOneByteString(static_cast<int>(chars_required))
|
||||
.ToHandleChecked();
|
||||
DisallowHeapAllocation no_gc;
|
||||
uint8_t* buffer = result->GetChars();
|
||||
// Print the number into the string, starting from the last position.
|
||||
int pos = static_cast<int>(chars_required - 1);
|
||||
@ -1055,6 +1049,127 @@ MaybeHandle<String> BigInt::ToStringBasePowerOfTwo(Handle<BigInt> x,
|
||||
return result;
|
||||
}
|
||||
|
||||
MaybeHandle<String> BigInt::ToStringGeneric(Handle<BigInt> x, int radix) {
|
||||
DCHECK(radix >= 2 && radix <= 36);
|
||||
DCHECK(!x->is_zero());
|
||||
Heap* heap = x->GetHeap();
|
||||
Isolate* isolate = heap->isolate();
|
||||
|
||||
const int length = x->length();
|
||||
const bool sign = x->sign();
|
||||
|
||||
// Compute (an overapproximation of) the length of the resulting string:
|
||||
// Divide bit length of the BigInt by bits representable per character.
|
||||
const size_t bit_length =
|
||||
length * kDigitBits - base::bits::CountLeadingZeros(x->digit(length - 1));
|
||||
// Maximum number of bits we can represent with one character. We'll use this
|
||||
// to find an appropriate chunk size below.
|
||||
const uint8_t max_bits_per_char = kMaxBitsPerChar[radix];
|
||||
// For estimating result length, we have to be pessimistic and work with
|
||||
// the minimum number of bits one character can represent.
|
||||
const uint8_t min_bits_per_char = max_bits_per_char - 1;
|
||||
// Perform the following computation with uint64_t to avoid overflows.
|
||||
uint64_t chars_required = bit_length;
|
||||
chars_required *= kBitsPerCharTableMultiplier;
|
||||
chars_required += min_bits_per_char - 1; // Round up.
|
||||
chars_required /= min_bits_per_char;
|
||||
chars_required += sign;
|
||||
|
||||
if (chars_required > String::kMaxLength) {
|
||||
THROW_NEW_ERROR(isolate, NewInvalidStringLengthError(), String);
|
||||
}
|
||||
Handle<SeqOneByteString> result =
|
||||
isolate->factory()
|
||||
->NewRawOneByteString(static_cast<int>(chars_required))
|
||||
.ToHandleChecked();
|
||||
|
||||
#if DEBUG
|
||||
// Zap the string first.
|
||||
{
|
||||
DisallowHeapAllocation no_gc;
|
||||
uint8_t* chars = result->GetChars();
|
||||
for (int i = 0; i < static_cast<int>(chars_required); i++) chars[i] = '?';
|
||||
}
|
||||
#endif
|
||||
|
||||
// We assemble the result string in reverse order, and then reverse it.
|
||||
// TODO(jkummerow): Consider building the string from the right, and
|
||||
// left-shifting it if the length estimate was too large.
|
||||
int pos = 0;
|
||||
|
||||
digit_t last_digit;
|
||||
if (length == 1) {
|
||||
last_digit = x->digit(0);
|
||||
} else {
|
||||
int chunk_chars =
|
||||
kDigitBits * kBitsPerCharTableMultiplier / max_bits_per_char;
|
||||
digit_t chunk_divisor = digit_pow(radix, chunk_chars);
|
||||
// By construction of chunk_chars, there can't have been overflow.
|
||||
DCHECK(chunk_divisor != 0);
|
||||
int nonzero_digit = length - 1;
|
||||
DCHECK(x->digit(nonzero_digit) != 0);
|
||||
// {rest} holds the part of the BigInt that we haven't looked at yet.
|
||||
// Not to be confused with "remainder"!
|
||||
Handle<BigInt> rest;
|
||||
// In the first round, divide the input, allocating a new BigInt for
|
||||
// the result == rest; from then on divide the rest in-place.
|
||||
Handle<BigInt>* dividend = &x;
|
||||
do {
|
||||
digit_t chunk;
|
||||
AbsoluteDivSmall(*dividend, chunk_divisor, &rest, &chunk);
|
||||
DCHECK(!rest.is_null());
|
||||
dividend = &rest;
|
||||
DisallowHeapAllocation no_gc;
|
||||
uint8_t* chars = result->GetChars();
|
||||
for (int i = 0; i < chunk_chars; i++) {
|
||||
chars[pos++] = kConversionChars[chunk % radix];
|
||||
chunk /= radix;
|
||||
}
|
||||
DCHECK(chunk == 0);
|
||||
if (rest->digit(nonzero_digit) == 0) nonzero_digit--;
|
||||
// We can never clear more than one digit per iteration, because
|
||||
// chunk_divisor is smaller than max digit value.
|
||||
DCHECK(rest->digit(nonzero_digit) > 0);
|
||||
} while (nonzero_digit > 0);
|
||||
last_digit = rest->digit(0);
|
||||
}
|
||||
DisallowHeapAllocation no_gc;
|
||||
uint8_t* chars = result->GetChars();
|
||||
do {
|
||||
chars[pos++] = kConversionChars[last_digit % radix];
|
||||
last_digit /= radix;
|
||||
} while (last_digit > 0);
|
||||
DCHECK(pos >= 1);
|
||||
DCHECK(pos <= static_cast<int>(chars_required));
|
||||
// Remove leading zeroes.
|
||||
while (pos > 1 && chars[pos - 1] == '0') pos--;
|
||||
if (sign) chars[pos++] = '-';
|
||||
// Trim any over-allocation (which can happen due to conservative estimates).
|
||||
if (pos < static_cast<int>(chars_required)) {
|
||||
result->synchronized_set_length(pos);
|
||||
int string_size =
|
||||
SeqOneByteString::SizeFor(static_cast<int>(chars_required));
|
||||
int needed_size = SeqOneByteString::SizeFor(pos);
|
||||
if (needed_size < string_size) {
|
||||
Address new_end = result->address() + needed_size;
|
||||
heap->CreateFillerObjectAt(new_end, (string_size - needed_size),
|
||||
ClearRecordedSlots::kNo);
|
||||
}
|
||||
}
|
||||
// Reverse the string.
|
||||
for (int i = 0, j = pos - 1; i < j; i++, j--) {
|
||||
uint8_t tmp = chars[i];
|
||||
chars[i] = chars[j];
|
||||
chars[j] = tmp;
|
||||
}
|
||||
#if DEBUG
|
||||
// Verify that all characters have been written.
|
||||
DCHECK(result->length() == pos);
|
||||
for (int i = 0; i < pos; i++) DCHECK(chars[i] != '?');
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
// Digit arithmetic helpers.
|
||||
|
||||
#if V8_TARGET_ARCH_32_BIT
|
||||
@ -1152,7 +1267,12 @@ BigInt::digit_t BigInt::digit_div(digit_t high, digit_t low, digit_t divisor,
|
||||
|
||||
digit_t vn1 = divisor >> kHalfDigitBits;
|
||||
digit_t vn0 = divisor & kHalfDigitMask;
|
||||
digit_t un32 = (high << s) | (low >> (kDigitBits - s));
|
||||
// {s} can be 0. "low >> kDigitBits == low" on x86, so we "&" it with
|
||||
// {s_zero_mask} which is 0 if s == 0 and all 1-bits otherwise.
|
||||
STATIC_ASSERT(sizeof(intptr_t) == sizeof(digit_t));
|
||||
digit_t s_zero_mask =
|
||||
static_cast<digit_t>(static_cast<intptr_t>(-s) >> (kDigitBits - 1));
|
||||
digit_t un32 = (high << s) | ((low >> (kDigitBits - s)) & s_zero_mask);
|
||||
digit_t un10 = low << s;
|
||||
digit_t un1 = un10 >> kHalfDigitBits;
|
||||
digit_t un0 = un10 & kHalfDigitMask;
|
||||
@ -1180,6 +1300,19 @@ BigInt::digit_t BigInt::digit_div(digit_t high, digit_t low, digit_t divisor,
|
||||
#endif
|
||||
}
|
||||
|
||||
// Raises {base} to the power of {exponent}. Does not check for overflow.
|
||||
BigInt::digit_t BigInt::digit_pow(digit_t base, digit_t exponent) {
|
||||
digit_t result = 1ull;
|
||||
while (exponent > 0) {
|
||||
if (exponent & 1) {
|
||||
result *= base;
|
||||
}
|
||||
exponent >>= 1;
|
||||
base *= base;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#undef HAVE_TWODIGIT_T
|
||||
|
||||
#ifdef OBJECT_PRINT
|
||||
|
@ -157,6 +157,7 @@ class BigInt : public HeapObject {
|
||||
|
||||
static MaybeHandle<String> ToStringBasePowerOfTwo(Handle<BigInt> x,
|
||||
int radix);
|
||||
static MaybeHandle<String> ToStringGeneric(Handle<BigInt> x, int radix);
|
||||
|
||||
// Digit arithmetic helpers.
|
||||
static inline digit_t digit_add(digit_t a, digit_t b, digit_t* carry);
|
||||
@ -164,6 +165,7 @@ class BigInt : public HeapObject {
|
||||
static inline digit_t digit_mul(digit_t a, digit_t b, digit_t* high);
|
||||
static inline digit_t digit_div(digit_t high, digit_t low, digit_t divisor,
|
||||
digit_t* remainder);
|
||||
static digit_t digit_pow(digit_t base, digit_t exponent);
|
||||
static inline bool digit_ismax(digit_t x) {
|
||||
return static_cast<digit_t>(~x) == 0;
|
||||
}
|
||||
|
@ -42,18 +42,168 @@ const six = BigInt(6);
|
||||
|
||||
// .toString(radix)
|
||||
{
|
||||
// assertEquals(expected, BigInt(input).toString(n)) is generated by:
|
||||
// input = $(python -c "print(int('expected', n))")
|
||||
assertEquals("hello", BigInt(18306744).toString(32));
|
||||
assertEquals("-hello", BigInt(-18306744).toString(32));
|
||||
assertEquals("abcde", BigInt(0xabcde).toString(16));
|
||||
assertEquals("-abcde", BigInt(-0xabcde).toString(16));
|
||||
assertEquals("1234567", BigInt(342391).toString(8));
|
||||
assertEquals("-1234567", BigInt(-342391).toString(8));
|
||||
assertEquals("1230123", BigInt(6939).toString(4));
|
||||
assertEquals("-1230123", BigInt(-6939).toString(4));
|
||||
assertEquals("1011001110001", BigInt(5745).toString(2));
|
||||
assertEquals("-1011001110001", BigInt(-5745).toString(2));
|
||||
// Single-digit BigInts: random-generated inputs close to kMaxInt.
|
||||
// Expectations computed with the following Python program:
|
||||
// def Format(x, base):
|
||||
// s = ""
|
||||
// while x > 0:
|
||||
// s = "0123456789abcdefghijklmnopqrstuvwxyz"[x % base] + s
|
||||
// x = x / base
|
||||
// return s
|
||||
assertEquals("10100110000100101000011100101", BigInt(0x14c250e5).toString(2));
|
||||
assertEquals("-110110100010011111001011111", BigInt(-0x6d13e5f).toString(2));
|
||||
assertEquals("1001222020000100000", BigInt(0x18c72873).toString(3));
|
||||
assertEquals("-1212101122110102020", BigInt(-0x2b19aebe).toString(3));
|
||||
assertEquals("120303133110120", BigInt(0x18cdf518).toString(4));
|
||||
assertEquals("-113203101020122", BigInt(-0x178d121a).toString(4));
|
||||
assertEquals("1323302233400", BigInt(0x18de6256).toString(5));
|
||||
assertEquals("-2301033210212", BigInt(-0x25f7f454).toString(5));
|
||||
assertEquals("131050115130", BigInt(0x211f0d5e).toString(6));
|
||||
assertEquals("-104353333321", BigInt(-0x186bbe91).toString(6));
|
||||
assertEquals("25466260221", BigInt(0x2f69f47e).toString(7));
|
||||
assertEquals("-31051540346", BigInt(-0x352c7efa).toString(7));
|
||||
assertEquals("5004630525", BigInt(0x28133155).toString(8));
|
||||
assertEquals("-7633240703", BigInt(-0x3e6d41c3).toString(8));
|
||||
assertEquals("705082365", BigInt(0x121f4264).toString(9));
|
||||
assertEquals("-780654431", BigInt(-0x1443b36e).toString(9));
|
||||
assertEquals("297019028", BigInt(0x11b42694).toString(10));
|
||||
assertEquals("-721151126", BigInt(-0x2afbe496).toString(10));
|
||||
assertEquals("312914074", BigInt(0x27ca6879).toString(11));
|
||||
assertEquals("-198025592", BigInt(-0x1813d3a7).toString(11));
|
||||
assertEquals("191370997", BigInt(0x2d14f083).toString(12));
|
||||
assertEquals("-1b8aab4a2", BigInt(-0x32b52efa).toString(12));
|
||||
assertEquals("7818062c", BigInt(0x1c84a48c).toString(13));
|
||||
assertEquals("-7529695b", BigInt(-0x1badffee).toString(13));
|
||||
assertEquals("6bc929c4", BigInt(0x2b0a91d0).toString(14));
|
||||
assertEquals("-63042008", BigInt(-0x270dff78).toString(14));
|
||||
assertEquals("5e8b8dec", BigInt(0x3cd27d7f).toString(15));
|
||||
assertEquals("-4005433d", BigInt(-0x28c0821a).toString(15));
|
||||
assertEquals("10b35ca3", BigInt(0x10b35ca3).toString(16));
|
||||
assertEquals("-23d4d9d6", BigInt(-0x23d4d9d6).toString(16));
|
||||
assertEquals("28c3d5e3", BigInt(0x3d75d48c).toString(17));
|
||||
assertEquals("-10c06328", BigInt(-0x1979b7f0).toString(17));
|
||||
assertEquals("eb8d349", BigInt(0x1dacf0a5).toString(18));
|
||||
assertEquals("-1217015h", BigInt(-0x28b3c23f).toString(18));
|
||||
assertEquals("1018520b", BigInt(0x357da01a).toString(19));
|
||||
assertEquals("-9c64e33", BigInt(-0x1b0e9571).toString(19));
|
||||
assertEquals("d7bf9ab", BigInt(0x3309daa3).toString(20));
|
||||
assertEquals("-58h0h9h", BigInt(-0x14c30c55).toString(20));
|
||||
assertEquals("64igi9h", BigInt(0x1fdd329c).toString(21));
|
||||
assertEquals("-45cbc4a", BigInt(-0x15cf9682).toString(21));
|
||||
assertEquals("7bi7d1h", BigInt(0x32f0dfe3).toString(22));
|
||||
assertEquals("-61j743l", BigInt(-0x291ff61f).toString(22));
|
||||
assertEquals("5g5gg25", BigInt(0x325a10bd).toString(23));
|
||||
assertEquals("-3359flb", BigInt(-0x1bb653c9).toString(23));
|
||||
assertEquals("392f5ec", BigInt(0x267ed69c).toString(24));
|
||||
assertEquals("-2ab3icb", BigInt(-0x1bbf7bab).toString(24));
|
||||
assertEquals("3jb2afo", BigInt(0x36f93c24).toString(25));
|
||||
assertEquals("-30bcheh", BigInt(-0x2bec76fa).toString(25));
|
||||
assertEquals("3845agk", BigInt(0x3d04bf64).toString(26));
|
||||
assertEquals("-1gpjl3g", BigInt(-0x1e720b1a).toString(26));
|
||||
assertEquals("20bpaf0", BigInt(0x2e8ff627).toString(27));
|
||||
assertEquals("-292i3c2", BigInt(-0x35f751fe).toString(27));
|
||||
assertEquals("266113k", BigInt(0x3fd26738).toString(28));
|
||||
assertEquals("-1eh16bo", BigInt(-0x2bb5726c).toString(28));
|
||||
assertEquals("19gj7qa", BigInt(0x2f28e8d8).toString(29));
|
||||
assertEquals("-13a0apf", BigInt(-0x278b4588).toString(29));
|
||||
assertEquals("iasrb8", BigInt(0x1a99b3be).toString(30));
|
||||
assertEquals("-frlhoc", BigInt(-0x17106f48).toString(30));
|
||||
assertEquals("bfe4p2", BigInt(0x139f1ea3).toString(31));
|
||||
assertEquals("-ioal1a", BigInt(-0x200e49fa).toString(31));
|
||||
assertEquals("m0v0kf", BigInt(0x2c0f828f).toString(32));
|
||||
assertEquals("-g4bab5", BigInt(-0x2045a965).toString(32));
|
||||
assertEquals("9i1kit", BigInt(0x16450a9f).toString(33));
|
||||
assertEquals("-fqb0e7", BigInt(-0x24d9e889).toString(33));
|
||||
assertEquals("gb9r6m", BigInt(0x2c3acf46).toString(34));
|
||||
assertEquals("-jcaemv", BigInt(-0x346f72b3).toString(34));
|
||||
assertEquals("cw4mbk", BigInt(0x2870cdcb).toString(35));
|
||||
assertEquals("-hw4eki", BigInt(-0x3817c29b).toString(35));
|
||||
assertEquals("alzwgj", BigInt(0x263e2c13).toString(36));
|
||||
assertEquals("-bo4ukz", BigInt(-0x2a0f97d3).toString(36));
|
||||
|
||||
// Multi-digit BigInts.
|
||||
// Test parseInt/toString round trip on a list of randomly generated
|
||||
// string representations of numbers in various bases.
|
||||
var positive = [0, 0, // Skip base 0 and 1.
|
||||
"1100110001100010110011110110010010001011100111100101111000111101100001000",
|
||||
"1001200022210010220101120212021002011002201122200002211102120120021011020",
|
||||
"1111113020012203332320220022231110130001001320122012131311333110012023232",
|
||||
"4214313040222110434114402342013144321401424143322013320403411012033300312",
|
||||
"5025302003542512450341430541203424555035430434034243510233043041501130015",
|
||||
"6231052230016515343200525230300322104013130605414211331345043144525012021",
|
||||
"1146340505617030644211355340006353546230356336306352536433054143503442135",
|
||||
"7262360724624787621528668212168232276348417717770383567066203032200270570",
|
||||
"7573792356581293501680046955899735043496925151216904903504319328753434194",
|
||||
"4a627927557579898720a42647639128174a8689889766a219342133671449069a2235011",
|
||||
"1a574a5848289924996342a32893380690322330393633b587ba5a15b7b82080222400464",
|
||||
"5163304c74c387b7a443c92466688595b671a3329b42083b1499b0c10a74a9298a06c3a5a",
|
||||
"4b63c834356a03c80946133284a709cbbc2a75022757207dc31c14abd4c160dc122327c17",
|
||||
"d8d59cbb4ca2860de7c002eee4ab3c215b90069200d20dbdc0111cb1e1bab97e8c7609670",
|
||||
"22d4b69398a7f848e6ae36798811cd1a63d90f340d8607f3ce5566c97c18468787eb2b9fd",
|
||||
"1176gf69afd32cc105fa70c705927a384dbdb1g8d952f28028g31ebdc9e32a89f16e825ee",
|
||||
"5d64b74f4d70632h4ee07h7c1e2da9125c42g2727f4b6d95e5cec6ga49566hh731ab5f544",
|
||||
"7ff8cg7f05dd72916a09a4761ii7b0ibcg68ba39b10436f14efg76ge817317badcbi4gffc",
|
||||
"6d7c4hci6cd72e4ja26j354i12i71gb0cbj12gi145j91h02hde3b72c65geb7ff9bi9d0c2b",
|
||||
"c96997f50abe425d13a53kk4af631kg7db208ka5j5bfg8ca5f9c0bjf69j5kgg4jb5h7hi86",
|
||||
"3g5fd800d9ib9j0i8all5jgb23dh9483ab6le5ad9g4kja8a0b3j5jbjfge7k5fffg2kbheee",
|
||||
"9j1119d1cd61kmdm7kma105cki313f678fc3h25f4664281bbmg3fk97kfbh7d48j89j178ch",
|
||||
"d2933cdc9jfe4hl3794kb3e13dg2lihad968ib9jg19dgf1fi482b27ji0d10c6kfkdge5764",
|
||||
"bf6o0njkm1ij5in5nh7h94584bd80el02b07el5ojk9k9g0gn906do70gbbnckl048c0kdmao",
|
||||
"8gb7jnge9p9cdgigo394oa33gfaenc3gnb53eceg4b8511gkkm88b0dod85e5bggpc861d7d5",
|
||||
"qbbnqhkpleb4o8ndaddpc34h5b2iljn3jgnjdn5k57bi3n9i09hjle9hqgqdpgbnk499mak56",
|
||||
"akg7e2976arn8i2m53gif0dp59bmfd7mk9erlg2qm3fc76da9glf397eh4ooij9il0nfl9gac",
|
||||
"mehpbfrj5ah2ef3p2hl637gjp1pm5grqn4037pm1qfgfpr9cfljfc145hljehjjb48bb1n6en",
|
||||
"rg6ik3agnb3p6t2rtja9h4il76i8fkqlt6gplap3fq6pfr7bbcfcp5ffncf3nm4kamap39hse",
|
||||
"bk8rp9r9r8pltdqpb7euc6s9rcm33969pcq6uk3mtfoktt86di8589oacbam5tn29b9b6dq3j",
|
||||
"npth8juld44rss3e57iigjg65po3d1h02heo4r103jmg3ocv89buqtgiov35k39rdf8j9t4ca",
|
||||
"vrmqlwrrrd0uml1womae49jpa9tadh44fw7mucgk06l0uk4uqwuo37t6kwn7wwrm3a6oq081s",
|
||||
"n5cft6gvufqd8iksquu2amghokk17gbtpguidc290af634p7k7rhmfu7bf1s62ej4megoa1j4",
|
||||
"3v3gcrmlfc2tl0tefgkiogj41f6y2tmj9w5bxke8y03xqf49ox8gh9wbrhycrkluicqajtnur",
|
||||
"z2m7b0sy2tzergtkqts5yj0dkrlfkxls81ijgxgfequizpntcwggv2d4rdzcncd0kj9mrmnrb",
|
||||
];
|
||||
var negative = [0, 0, // Skip base 0 and 1.
|
||||
"-100010011110111010111111110001100100111010101000001011010010101100101000",
|
||||
"-110012122000122102021210112200001000122011010120101201001122000002022102",
|
||||
"-203210320111001002200122200001312300221100221321010300023323201113122333",
|
||||
"-133042441230110320040323303341320302144241224443231311022240124413104131",
|
||||
"-311325230504055004330150145105331121322231155401110315251422505233103112",
|
||||
"-643153641664240231336166403516403454646560261062114326443664602606315326",
|
||||
"-200057252627665476551635525303641543165622340301637556323453513664337277",
|
||||
"-826688166214270516331644053744613530235020517172322840763172114078364165",
|
||||
"-743042397390679269240157150971957535458122650450558451124173993544604852",
|
||||
"-73528688500003573942a56a504a2996a1384129563098512a63196697975038692aaa63",
|
||||
"-616576a2948a9029316290168b71137b027851639a0283150b125b664b74b767a3597805",
|
||||
"-b875467540719b371b7a36047a7886872a5399c4c630c37149bc3182917a7a7c124475bb",
|
||||
"-3860411b61d35977721bc81bd715c386c9b70a752940913d265505d8c7c5dd2624b591d7",
|
||||
"-bad5dd79b083ee0da9a6296664e72c246d827762357116ae7076a22bb369acbc3a201d03",
|
||||
"-f9b37352aff265124303942a463917a252ff1a2ff4a33777f490b4c103bdcd1a655dbe2c",
|
||||
"-805fg8c74125214g383a8d8g573c49fa7c4035fbc6db61g5gb5g6beb8f90dae4a9a5g7cc",
|
||||
"-70aae113459d3h5084b1gg209g3695d20e78d01gcbb71bh1bd4gdge31haf5hc02dghf14e",
|
||||
"-c55a57haf47b7ih2gh6ea93098ig02b42icga6ead254e0aeeic7g53h5fd6637ge03b2e20",
|
||||
"-e32f7204624ie596j731g72136cejc25ebbgb0140i4997fcdf477f021d86ci4e10db543a",
|
||||
"-i7f32c817i3cac1c24c7786k6ig185f47cj1471ki6bb7agiae838027gjge9g59if9f88g6",
|
||||
"-i30aha2030a9605c270h92e1ca3i02j996hl918gh52fbhb7i16ik1i919ieak3cj384kb61",
|
||||
"-58jmem8e59li67aellid2083dabh4kh51ci1jg7c6a3k4l1hdgfkdha0fglfm4805kida5b9",
|
||||
"-cl9iecjg9ak087cad4151lll44296heae2349g70fbjj37998m2ddn6427fgcl2aknhgn1a1",
|
||||
"-alfjfhho4gf8bi4j2bi3743mhg2aache4c6jcinkmf5ddm7kf9gg350hlja16ealbdlk201j",
|
||||
"-bhh1146ho3o2m3b839c565hbgjnhjh96oofbmdl7gn8h4f94kli94hkk180o79pc4d2l0721",
|
||||
"-p00gknh7e05k6a3apg6i9lb46f4a9qeeiq1778ak8il5dcponk5gl2fiednb4pmo1agmoqph",
|
||||
"-4j8lo4d4p508fnd2hkfb76e8ri81k6hq0op3pr14ca0cn96pccplk7rbahc9cdkdce1q16dn",
|
||||
"-ednlo3ogf2i8annrel9rm323bpf00meed3oi47n0qrdgnd2n3il4bnsc9s2jd7loh44im8ra",
|
||||
"-bjjg6fsbpcc2tc1o09m9r6fd6eoq5480har62a5offn9thcfahbno9kf9magl2akl0jgncj9",
|
||||
"-sonuhat2h60glpbpej9jjado2s5l86122d26tudoc1d6aic2oitu793gk0mlac3dk1dufp1q",
|
||||
"-i9pbvm53ubh8jqifuarauch8cbgk9cjsl6rlioka1phs1lskg1oosll23hjoli2subgr1rto",
|
||||
"-w1ncn5t60b5dv669ekwnvk8n2g7djrsl8cdkwun8o3m5divc3jhnkp2381rhj70gc71a6wff",
|
||||
"-buiq8v33p5ex44ps4s45enj6lrluivm19lcowkvntu72u0xguw13bxgxxe7mdlwt1a4qksae",
|
||||
"-woiycfmea6i12r2yai49mf4lbd7w2jdoebiogfhnh1i4rwgox57obci8qbsfpb4w07nu19m5",
|
||||
"-tbttuip1r6ioca6g6dw354o4m78qep9yh03nojx47yq29fqime6zstwllb74501qct8eskxn",
|
||||
];
|
||||
for (var base = 2; base <= 36; base++) {
|
||||
var input = positive[base];
|
||||
assertEquals(input, BigInt.parseInt(input, base).toString(base));
|
||||
input = negative[base];
|
||||
assertEquals(input, BigInt.parseInt(input, base).toString(base));
|
||||
}
|
||||
}
|
||||
|
||||
// .parseInt
|
||||
|
Loading…
Reference in New Issue
Block a user