[bigint] Implement BigInt.asIntN.

Bug: v8:6791
Change-Id: I10f8c6c88c534ee1e3c893176b6563af0c9f99d3
Reviewed-on: https://chromium-review.googlesource.com/753904
Commit-Queue: Georg Neis <neis@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49180}
This commit is contained in:
Georg Neis 2017-11-07 12:16:27 +01:00 committed by Commit Bot
parent 6e1c57eaa9
commit 55062ced0b
4 changed files with 198 additions and 9 deletions

View File

@ -86,11 +86,16 @@ BUILTIN(BigIntAsIntN) {
Handle<Object> bits_obj = args.atOrUndefined(isolate, 1);
Handle<Object> bigint_obj = args.atOrUndefined(isolate, 2);
// TODO(jkummerow): Implement.
USE(bits_obj);
USE(bigint_obj);
Handle<Object> bits;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, bits,
Object::ToIndex(isolate, bits_obj, MessageTemplate::kInvalidIndex));
UNIMPLEMENTED();
Handle<BigInt> bigint;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, bigint,
BigInt::FromObject(isolate, bigint_obj));
return *BigInt::AsIntN(bits->Number(), bigint);
}
BUILTIN(BigIntPrototypeToLocaleString) {

View File

@ -1588,15 +1588,61 @@ MaybeHandle<String> BigInt::ToStringGeneric(Handle<BigInt> x, int radix) {
return result;
}
Handle<BigInt> BigInt::AsIntN(uint64_t n, Handle<BigInt> x) {
DCHECK_LE(n, kMaxSafeInteger);
Isolate* isolate = x->GetIsolate();
Handle<BigInt> result = AbsoluteAsUintN(n, x);
if (result->is_zero()) return result;
DCHECK_NE(n, 0);
DCHECK(!x->is_zero());
// Compare abs(result) against 2^(n-1).
int comparison;
{
// 2^(n-1) needs n bits.
uint64_t power_length = (n + kDigitBits - 1) / kDigitBits;
if (static_cast<uint64_t>(result->length()) < power_length) {
comparison = -1;
} else {
DCHECK_EQ(result->length(), power_length);
DCHECK_LE(n, kMaxInt);
// TODO(neis): Ideally we shouldn't allocate here at all.
comparison = AbsoluteCompare(result, PowerOfTwo(isolate, n - 1));
}
}
if (!x->sign()) {
// x is positive. Note that result == x mod 2^n.
if (comparison < 0) return result;
// Return (x mod 2^n) - 2^n, which is -(2^n - x mod 2^n).
return AbsoluteSub(PowerOfTwo(isolate, n), result, true);
}
// x is negative. Note that abs(result) == -x mod 2^n.
// We use the following facts:
// a) (x mod 2^n) == 2^n - abs(result)
// b) (x mod 2^n) >= 2^(n-1) iff
// 2^n - abs(result) >= 2^(n-1) iff
// 2^(n-1) >= abs(result) iff
// comparison <= 0
if (comparison <= 0) {
// Return (x mod 2^n) - 2^n, which is -abs(result).
return result->sign() ? result : UnaryMinus(result);
}
// Return x mod 2^n.
return AbsoluteSub(PowerOfTwo(isolate, n), result, false);
}
Handle<BigInt> BigInt::AsUintN(uint64_t n, Handle<BigInt> x) {
DCHECK_LE(n, kMaxSafeInteger);
Handle<BigInt> result = AbsoluteAsUintN(n, x);
if (!x->sign()) return result;
// x is negative.
// Note that result == -x % 2^n. We use the following facts:
// If result == 0, then x % 2^n == 0.
// If result != 0, then x % 2^n == 2^n - result.
// x is negative. Note that abs(result) == -x mod 2^n.
// We use the following facts:
// a) If result == 0, then (x mod 2^n) == 0.
// b) If result != 0, then (x mod 2^n) == 2^n - abs(result).
if (result->is_zero()) return result;
return AbsoluteSub(PowerOfTwo(x->GetIsolate(), n), result, false);
}

View File

@ -59,6 +59,7 @@ class V8_EXPORT_PRIVATE BigInt : public HeapObject {
// Exposed for tests, do not call directly. Use CompareToNumber() instead.
static ComparisonResult CompareToDouble(Handle<BigInt> x, double y);
static Handle<BigInt> AsIntN(uint64_t n, Handle<BigInt> x);
static Handle<BigInt> AsUintN(uint64_t n, Handle<BigInt> x);
DECL_CAST(BigInt)

View File

@ -276,9 +276,146 @@ const six = BigInt(6);
}
}
// .asUintN
// BigInt.asIntN
{
assertEquals(2, BigInt.asIntN.length);
}{
assertEquals(254n, BigInt.asIntN(10, 254n));
assertEquals(255n, BigInt.asIntN(10, 255n));
assertEquals(256n, BigInt.asIntN(10, 256n));
assertEquals(257n, BigInt.asIntN(10, 257n));
assertEquals(510n, BigInt.asIntN(10, 510n));
assertEquals(511n, BigInt.asIntN(10, 511n));
assertEquals(-512n, BigInt.asIntN(10, 512n));
assertEquals(-511n, BigInt.asIntN(10, 513n));
assertEquals(-2n, BigInt.asIntN(10, 1022n));
assertEquals(-1n, BigInt.asIntN(10, 1023n));
assertEquals(0n, BigInt.asIntN(10, 1024n));
assertEquals(1n, BigInt.asIntN(10, 1025n));
}{
assertEquals(-254n, BigInt.asIntN(10, -254n));
assertEquals(-255n, BigInt.asIntN(10, -255n));
assertEquals(-256n, BigInt.asIntN(10, -256n));
assertEquals(-257n, BigInt.asIntN(10, -257n));
assertEquals(-510n, BigInt.asIntN(10, -510n));
assertEquals(-511n, BigInt.asIntN(10, -511n));
assertEquals(-512n, BigInt.asIntN(10, -512n));
assertEquals(511n, BigInt.asIntN(10, -513n));
assertEquals(2n, BigInt.asIntN(10, -1022n));
assertEquals(1n, BigInt.asIntN(10, -1023n));
assertEquals(0n, BigInt.asIntN(10, -1024n));
assertEquals(-1n, BigInt.asIntN(10, -1025n));
}{
assertEquals(0n, BigInt.asIntN(0, 0n));
assertEquals(0n, BigInt.asIntN(1, 0n));
assertEquals(0n, BigInt.asIntN(16, 0n));
assertEquals(0n, BigInt.asIntN(31, 0n));
assertEquals(0n, BigInt.asIntN(32, 0n));
assertEquals(0n, BigInt.asIntN(33, 0n));
assertEquals(0n, BigInt.asIntN(63, 0n));
assertEquals(0n, BigInt.asIntN(64, 0n));
assertEquals(0n, BigInt.asIntN(65, 0n));
assertEquals(0n, BigInt.asIntN(127, 0n));
assertEquals(0n, BigInt.asIntN(128, 0n));
assertEquals(0n, BigInt.asIntN(129, 0n));
}{
assertEquals(0n, BigInt.asIntN(0, 42n));
assertEquals(0n, BigInt.asIntN(1, 42n));
assertEquals(42n, BigInt.asIntN(16, 42n));
assertEquals(42n, BigInt.asIntN(31, 42n));
assertEquals(42n, BigInt.asIntN(32, 42n));
assertEquals(42n, BigInt.asIntN(33, 42n));
assertEquals(42n, BigInt.asIntN(63, 42n));
assertEquals(42n, BigInt.asIntN(64, 42n));
assertEquals(42n, BigInt.asIntN(65, 42n));
assertEquals(42n, BigInt.asIntN(127, 42n));
assertEquals(42n, BigInt.asIntN(128, 42n));
assertEquals(42n, BigInt.asIntN(129, 42n));
}{
assertEquals(0n, BigInt.asIntN(0, -42n));
assertEquals(0n, BigInt.asIntN(1, -42n));
assertEquals(-42n, BigInt.asIntN(16, -42n));
assertEquals(-42n, BigInt.asIntN(31, -42n));
assertEquals(-42n, BigInt.asIntN(32, -42n));
assertEquals(-42n, BigInt.asIntN(33, -42n));
assertEquals(-42n, BigInt.asIntN(63, -42n));
assertEquals(-42n, BigInt.asIntN(64, -42n));
assertEquals(-42n, BigInt.asIntN(65, -42n));
assertEquals(-42n, BigInt.asIntN(127, -42n));
assertEquals(-42n, BigInt.asIntN(128, -42n));
assertEquals(-42n, BigInt.asIntN(129, -42n));
}{
assertEquals(0n, BigInt.asIntN(0, 4294967295n));
assertEquals(-1n, BigInt.asIntN(1, 4294967295n));
assertEquals(-1n, BigInt.asIntN(16, 4294967295n));
assertEquals(-1n, BigInt.asIntN(31, 4294967295n));
assertEquals(-1n, BigInt.asIntN(32, 4294967295n));
assertEquals(4294967295n, BigInt.asIntN(33, 4294967295n));
assertEquals(4294967295n, BigInt.asIntN(63, 4294967295n));
assertEquals(4294967295n, BigInt.asIntN(64, 4294967295n));
assertEquals(4294967295n, BigInt.asIntN(65, 4294967295n));
assertEquals(4294967295n, BigInt.asIntN(127, 4294967295n));
assertEquals(4294967295n, BigInt.asIntN(128, 4294967295n));
assertEquals(4294967295n, BigInt.asIntN(129, 4294967295n));
}{
assertEquals(0n, BigInt.asIntN(0, -4294967295n));
assertEquals(-1n, BigInt.asIntN(1, -4294967295n));
assertEquals(1n, BigInt.asIntN(16, -4294967295n));
assertEquals(1n, BigInt.asIntN(31, -4294967295n));
assertEquals(1n, BigInt.asIntN(32, -4294967295n));
assertEquals(-4294967295n, BigInt.asIntN(33, -4294967295n));
assertEquals(-4294967295n, BigInt.asIntN(63, -4294967295n));
assertEquals(-4294967295n, BigInt.asIntN(64,-4294967295n));
assertEquals(-4294967295n, BigInt.asIntN(65, -4294967295n));
assertEquals(-4294967295n, BigInt.asIntN(127, -4294967295n));
assertEquals(-4294967295n, BigInt.asIntN(128, -4294967295n));
assertEquals(-4294967295n, BigInt.asIntN(129, -4294967295n));
}{
assertEquals(42n, BigInt.asIntN(2**32, 42n));
assertEquals(4294967295n, BigInt.asIntN(2**32, 4294967295n));
assertEquals(4294967296n, BigInt.asIntN(2**32, 4294967296n));
assertEquals(4294967297n, BigInt.asIntN(2**32, 4294967297n));
}{
assertThrows(() => BigInt.asIntN(2n, 12n), TypeError);
assertThrows(() => BigInt.asIntN(-1, 0n), RangeError);
assertThrows(() => BigInt.asIntN(2**53, 0n), RangeError);
assertEquals(0n, BigInt.asIntN({}, 12n));
assertEquals(0n, BigInt.asIntN(2.9999, 12n));
assertEquals(-4n, BigInt.asIntN(3.1234, 12n));
}{
assertThrows(() => BigInt.asIntN(3, 12), TypeError);
assertEquals(-4n, BigInt.asIntN(3, "12"));
}
// BigInt.asUintN
{
assertEquals(2, BigInt.asUintN.length);
}{
assertEquals(254n, BigInt.asUintN(10, 254n));
assertEquals(255n, BigInt.asUintN(10, 255n));
assertEquals(256n, BigInt.asUintN(10, 256n));
assertEquals(257n, BigInt.asUintN(10, 257n));
assertEquals(510n, BigInt.asUintN(10, 510n));
assertEquals(511n, BigInt.asUintN(10, 511n));
assertEquals(512n, BigInt.asUintN(10, 512n));
assertEquals(513n, BigInt.asUintN(10, 513n));
assertEquals(1022n, BigInt.asUintN(10, 1022n));
assertEquals(1023n, BigInt.asUintN(10, 1023n));
assertEquals(0n, BigInt.asUintN(10, 1024n));
assertEquals(1n, BigInt.asUintN(10, 1025n));
}{
assertEquals(1024n - 254n, BigInt.asUintN(10, -254n));
assertEquals(1024n - 255n, BigInt.asUintN(10, -255n));
assertEquals(1024n - 256n, BigInt.asUintN(10, -256n));
assertEquals(1024n - 257n, BigInt.asUintN(10, -257n));
assertEquals(1024n - 510n, BigInt.asUintN(10, -510n));
assertEquals(1024n - 511n, BigInt.asUintN(10, -511n));
assertEquals(1024n - 512n, BigInt.asUintN(10, -512n));
assertEquals(1024n - 513n, BigInt.asUintN(10, -513n));
assertEquals(1024n - 1022n, BigInt.asUintN(10, -1022n));
assertEquals(1024n - 1023n, BigInt.asUintN(10, -1023n));
assertEquals(0n, BigInt.asUintN(10, -1024n));
assertEquals(1023n, BigInt.asUintN(10, -1025n));
}{
assertEquals(0n, BigInt.asUintN(0, 0n));
assertEquals(0n, BigInt.asUintN(1, 0n));