[bigint] Implement .toString for power-of-2 radixes
Other radixes require Divide/Remainder to be implemented first. Bug: v8:6791 Change-Id: I95f1fad39a0a4df556a194094805ed93bd46d0db Reviewed-on: https://chromium-review.googlesource.com/664037 Commit-Queue: Jakob Kummerow <jkummerow@chromium.org> Reviewed-by: Georg Neis <neis@chromium.org> Cr-Commit-Position: refs/heads/master@{#48020}
This commit is contained in:
parent
0202a040c9
commit
a12f05e8fc
@ -81,14 +81,9 @@ Handle<BigInt> BigInt::BitwiseOr(Handle<BigInt> x, Handle<BigInt> y) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Handle<String> BigInt::ToString(Handle<BigInt> bigint, int radix) {
|
Handle<String> BigInt::ToString(Handle<BigInt> bigint, int radix) {
|
||||||
// TODO(jkummerow): Implement this properly.
|
// TODO(jkummerow): Support non-power-of-two radixes.
|
||||||
Factory* factory = bigint->GetIsolate()->factory();
|
if (!base::bits::IsPowerOfTwo(radix)) radix = 16;
|
||||||
if (bigint->is_zero()) return factory->NewStringFromStaticChars("0");
|
return bigint->ToStringBasePowerOfTwo(bigint, radix);
|
||||||
DCHECK(bigint->length() == 1);
|
|
||||||
int value = static_cast<uint32_t>(bigint->digit(0));
|
|
||||||
if (bigint->sign()) value = -value; // This can overflow. We don't care.
|
|
||||||
Handle<Object> number = factory->NewNumberFromInt(value);
|
|
||||||
return factory->NumberToString(number);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BigInt::Initialize(int length, bool zero_initialize) {
|
void BigInt::Initialize(int length, bool zero_initialize) {
|
||||||
@ -107,6 +102,55 @@ void BigInt::Initialize(int length, bool zero_initialize) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Private helpers for public methods.
|
||||||
|
|
||||||
|
static const char kConversionChars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||||
|
|
||||||
|
// TODO(jkummerow): Add more tests for this when it is exposed on
|
||||||
|
// BigInt.prototype.
|
||||||
|
Handle<String> BigInt::ToStringBasePowerOfTwo(Handle<BigInt> x, int radix) {
|
||||||
|
STATIC_ASSERT(base::bits::IsPowerOfTwo(kDigitBits));
|
||||||
|
DCHECK(base::bits::IsPowerOfTwo(radix));
|
||||||
|
DCHECK(radix >= 2 && radix <= 32);
|
||||||
|
Factory* factory = x->GetIsolate()->factory();
|
||||||
|
// TODO(jkummerow): check in caller?
|
||||||
|
if (is_zero()) return factory->NewStringFromStaticChars("0");
|
||||||
|
|
||||||
|
const int len = x->length();
|
||||||
|
const bool sign = x->sign();
|
||||||
|
const int bits_per_char = base::bits::CountTrailingZeros32(radix);
|
||||||
|
const int char_mask = radix - 1;
|
||||||
|
const int chars_per_digit = kDigitBits / bits_per_char;
|
||||||
|
// Compute the number of chars needed to represent the most significant
|
||||||
|
// bigint digit.
|
||||||
|
int chars_for_msd = 0;
|
||||||
|
for (digit_t msd = x->digit(len - 1); msd != 0; msd >>= bits_per_char) {
|
||||||
|
chars_for_msd++;
|
||||||
|
}
|
||||||
|
// All other digits need chars_per_digit characters; a leading "-" needs one.
|
||||||
|
const int chars = chars_for_msd + (len - 1) * chars_per_digit + sign;
|
||||||
|
|
||||||
|
Handle<SeqOneByteString> result =
|
||||||
|
factory->NewRawOneByteString(chars).ToHandleChecked();
|
||||||
|
uint8_t* buffer = result->GetChars();
|
||||||
|
// Print the number into the string, starting from the last position.
|
||||||
|
int pos = chars - 1;
|
||||||
|
for (int i = 0; i < len - 1; i++) {
|
||||||
|
digit_t digit = x->digit(i);
|
||||||
|
for (int j = 0; j < chars_per_digit; j++) {
|
||||||
|
buffer[pos--] = kConversionChars[digit & char_mask];
|
||||||
|
digit >>= bits_per_char;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Print the most significant digit.
|
||||||
|
for (digit_t msd = x->digit(len - 1); msd != 0; msd >>= bits_per_char) {
|
||||||
|
buffer[pos--] = kConversionChars[msd & char_mask];
|
||||||
|
}
|
||||||
|
if (sign) buffer[pos--] = '-';
|
||||||
|
DCHECK(pos == -1);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef OBJECT_PRINT
|
#ifdef OBJECT_PRINT
|
||||||
void BigInt::BigIntPrint(std::ostream& os) {
|
void BigInt::BigIntPrint(std::ostream& os) {
|
||||||
DisallowHeapAllocation no_gc;
|
DisallowHeapAllocation no_gc;
|
||||||
|
@ -88,6 +88,9 @@ class BigInt : public HeapObject {
|
|||||||
static const int kHalfDigitBits = kDigitBits / 2;
|
static const int kHalfDigitBits = kDigitBits / 2;
|
||||||
static const digit_t kHalfDigitMask = (1ull << kHalfDigitBits) - 1;
|
static const digit_t kHalfDigitMask = (1ull << kHalfDigitBits) - 1;
|
||||||
|
|
||||||
|
// Private helpers for public methods.
|
||||||
|
Handle<String> ToStringBasePowerOfTwo(Handle<BigInt> x, int radix);
|
||||||
|
|
||||||
class LengthBits : public BitField<int, 0, kMaxLengthBits> {};
|
class LengthBits : public BitField<int, 0, kMaxLengthBits> {};
|
||||||
class SignBits : public BitField<bool, LengthBits::kNext, 1> {};
|
class SignBits : public BitField<bool, LengthBits::kNext, 1> {};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user