From 66f21389a74223b6a6372919f5c060faecad0fd8 Mon Sep 17 00:00:00 2001 From: Jakob Kummerow Date: Mon, 5 Mar 2018 19:02:21 -0800 Subject: [PATCH] [bigint] Fix Exponentiate for 1 ** multi_digit Bug: chromium:819026 Change-Id: I2c58d5e2892f683747966e00aa047153085ac121 Reviewed-on: https://chromium-review.googlesource.com/950472 Reviewed-by: Georg Neis Commit-Queue: Jakob Kummerow Cr-Commit-Position: refs/heads/master@{#51776} --- src/objects/bigint.cc | 10 +++++++++- test/mjsunit/harmony/bigint/exp.js | 3 +++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/objects/bigint.cc b/src/objects/bigint.cc index db00ab1bf1ff..ee21d52a5600 100644 --- a/src/objects/bigint.cc +++ b/src/objects/bigint.cc @@ -323,10 +323,18 @@ MaybeHandle BigInt::Exponentiate(Handle base, // 3. Return a BigInt representing the mathematical value of base raised // to the power exponent. if (base->is_zero()) return base; + if (base->length() == 1 && base->digit(0) == 1) { + // (-1) ** even_number == 1. + if (base->sign() && (exponent->digit(0) & 1) == 0) { + return UnaryMinus(base); + } + // (-1) ** odd_number == -1; 1 ** anything == 1. + return base; + } // For all bases >= 2, very large exponents would lead to unrepresentable // results. STATIC_ASSERT(kMaxLengthBits < std::numeric_limits::max()); - if (!(base->length() == 1 && base->digit(0) == 1) && exponent->length() > 1) { + if (exponent->length() > 1) { THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kBigIntTooBig), BigInt); } diff --git a/test/mjsunit/harmony/bigint/exp.js b/test/mjsunit/harmony/bigint/exp.js index 812173323982..54d5849373f5 100644 --- a/test/mjsunit/harmony/bigint/exp.js +++ b/test/mjsunit/harmony/bigint/exp.js @@ -9,6 +9,9 @@ assertEquals(-1n, (-1n) ** 1n); assertEquals(1n, (-1n) ** 2n); assertEquals(-1n, (-1n) ** 3n); assertEquals(1n, (-1n) ** 4n); +// Multi-digit exponents. +assertEquals(1n, (-1n) ** (2n ** 80n)); +assertEquals(-1n, (-1n) ** ((2n ** 80n) + 1n)); assertEquals(1n, 0n ** 0n); assertEquals(0n, 0n ** 1n);