Commit 8476d272 authored by Jakob Kummerow's avatar Jakob Kummerow Committed by V8 LUCI CQ

[bigint] Move addition/subtraction to src/bigint/

Bug: v8:11515
Change-Id: I598e57de1c7d6219096dd2306fa206faf7247bb5
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2999869
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Cr-Commit-Position: refs/heads/master@{#75526}
parent f5752679
jkummerow@chromium.org
mslekova@chromium.org
thibaudm@chromium.org
......@@ -99,12 +99,5 @@ Status Processor::Modulo(RWDigits R, Digits A, Digits B) {
return impl->get_and_clear_status();
}
Status Processor::ToString(char* out, int* out_length, Digits X, int radix,
bool sign) {
ProcessorImpl* impl = static_cast<ProcessorImpl*>(this);
impl->ToString(out, out_length, X, radix, sign);
return impl->get_and_clear_status();
}
} // namespace bigint
} // namespace v8
......@@ -219,6 +219,18 @@ inline int Compare(Digits A, Digits B) {
return A[i] > B[i] ? 1 : -1;
}
// Z := X + Y
void Add(RWDigits Z, Digits X, Digits Y);
// Addition of signed integers. Returns true if the result is negative.
bool AddSigned(RWDigits Z, Digits X, bool x_negative, Digits Y,
bool y_negative);
// Z := X - Y. Requires X >= Y.
void Subtract(RWDigits Z, Digits X, Digits Y);
// Subtraction of signed integers. Returns true if the result is negative.
bool SubtractSigned(RWDigits Z, Digits X, bool x_negative, Digits Y,
bool y_negative);
enum class Status { kOk, kInterrupted };
class Processor {
......@@ -246,6 +258,19 @@ class Processor {
Status ToString(char* out, int* out_length, Digits X, int radix, bool sign);
};
inline int AddResultLength(int x_length, int y_length) {
return std::max(x_length, y_length) + 1;
}
inline int AddSignedResultLength(int x_length, int y_length, bool same_sign) {
return same_sign ? AddResultLength(x_length, y_length)
: std::max(x_length, y_length);
}
inline int SubtractResultLength(int x_length, int y_length) { return x_length; }
inline int SubtractSignedResultLength(int x_length, int y_length,
bool same_sign) {
return same_sign ? std::max(x_length, y_length)
: AddResultLength(x_length, y_length);
}
inline int MultiplyResultLength(Digits X, Digits Y) {
return X.len() + Y.len();
}
......
......@@ -269,6 +269,13 @@ void ProcessorImpl::ToString(char* out, int* out_length, Digits X, int radix,
*out_length -= excess;
}
Status Processor::ToString(char* out, int* out_length, Digits X, int radix,
bool sign) {
ProcessorImpl* impl = static_cast<ProcessorImpl*>(this);
impl->ToString(out, out_length, X, radix, sign);
return impl->get_and_clear_status();
}
int ToStringResultLength(Digits X, int radix, bool sign) {
const int bit_length = BitLength(X);
int result;
......
......@@ -90,5 +90,33 @@ digit_t SubtractAndReturnBorrow(RWDigits Z, Digits X, Digits Y) {
return borrow;
}
bool AddSigned(RWDigits Z, Digits X, bool x_negative, Digits Y,
bool y_negative) {
if (x_negative == y_negative) {
Add(Z, X, Y);
return x_negative;
}
if (GreaterThanOrEqual(X, Y)) {
Subtract(Z, X, Y);
return x_negative;
}
Subtract(Z, Y, X);
return !x_negative;
}
bool SubtractSigned(RWDigits Z, Digits X, bool x_negative, Digits Y,
bool y_negative) {
if (x_negative != y_negative) {
Add(Z, X, Y);
return x_negative;
}
if (GreaterThanOrEqual(X, Y)) {
Subtract(Z, X, Y);
return x_negative;
}
Subtract(Z, Y, X);
return !x_negative;
}
} // namespace bigint
} // namespace v8
......@@ -19,12 +19,6 @@ digit_t AddAndReturnOverflow(RWDigits Z, Digits X);
// Z -= X. Returns borrow on overflow.
digit_t SubAndReturnBorrow(RWDigits Z, Digits X);
// Z := X + Y.
void Add(RWDigits Z, Digits X, Digits Y);
// Z := X - Y.
void Subtract(RWDigits Z, Digits X, Digits Y);
// X += y.
inline void Add(RWDigits X, digit_t y) {
digit_t carry = y;
......
......@@ -97,15 +97,6 @@ class MutableBigInt : public FreshlyAllocatedBigInt {
Handle<BigInt> x,
bool result_sign);
static MaybeHandle<BigInt> AbsoluteAdd(Isolate* isolate, Handle<BigInt> x,
Handle<BigInt> y, bool result_sign);
static void AbsoluteAdd(MutableBigInt result, BigInt x, BigInt y);
static Handle<BigInt> AbsoluteSub(Isolate* isolate, Handle<BigInt> x,
Handle<BigInt> y, bool result_sign);
static void AbsoluteSub(MutableBigInt result, BigInt x, BigInt y);
static MaybeHandle<MutableBigInt> AbsoluteAddOne(
Isolate* isolate, Handle<BigIntBase> x, bool sign,
MutableBigInt result_storage = MutableBigInt());
......@@ -585,34 +576,42 @@ MaybeHandle<BigInt> BigInt::Remainder(Isolate* isolate, Handle<BigInt> x,
MaybeHandle<BigInt> BigInt::Add(Isolate* isolate, Handle<BigInt> x,
Handle<BigInt> y) {
if (x->is_zero()) return y;
if (y->is_zero()) return x;
bool xsign = x->sign();
if (xsign == y->sign()) {
// x + y == x + y
// -x + -y == -(x + y)
return MutableBigInt::AbsoluteAdd(isolate, x, y, xsign);
}
// x + -y == x - y == -(y - x)
// -x + y == y - x == -(x - y)
if (bigint::Compare(GetDigits(x), GetDigits(y)) >= 0) {
return MutableBigInt::AbsoluteSub(isolate, x, y, xsign);
bool ysign = y->sign();
int result_length =
bigint::AddSignedResultLength(x->length(), y->length(), xsign == ysign);
Handle<MutableBigInt> result;
if (!MutableBigInt::New(isolate, result_length).ToHandle(&result)) {
// Allocation fails when {result_length} exceeds the max BigInt size.
return {};
}
return MutableBigInt::AbsoluteSub(isolate, y, x, !xsign);
DisallowGarbageCollection no_gc;
bool result_sign = bigint::AddSigned(GetRWDigits(result), GetDigits(x), xsign,
GetDigits(y), ysign);
result->set_sign(result_sign);
return MutableBigInt::MakeImmutable(result);
}
MaybeHandle<BigInt> BigInt::Subtract(Isolate* isolate, Handle<BigInt> x,
Handle<BigInt> y) {
if (y->is_zero()) return x;
if (x->is_zero()) return UnaryMinus(isolate, y);
bool xsign = x->sign();
if (xsign != y->sign()) {
// x - (-y) == x + y
// (-x) - y == -(x + y)
return MutableBigInt::AbsoluteAdd(isolate, x, y, xsign);
}
// x - y == -(y - x)
// (-x) - (-y) == y - x == -(x - y)
if (bigint::Compare(GetDigits(x), GetDigits(y)) >= 0) {
return MutableBigInt::AbsoluteSub(isolate, x, y, xsign);
bool ysign = y->sign();
int result_length = bigint::SubtractSignedResultLength(
x->length(), y->length(), xsign == ysign);
Handle<MutableBigInt> result;
if (!MutableBigInt::New(isolate, result_length).ToHandle(&result)) {
// Allocation fails when {result_length} exceeds the max BigInt size.
return {};
}
return MutableBigInt::AbsoluteSub(isolate, y, x, !xsign);
DisallowGarbageCollection no_gc;
bool result_sign = bigint::SubtractSigned(GetRWDigits(result), GetDigits(x),
xsign, GetDigits(y), ysign);
result->set_sign(result_sign);
return MutableBigInt::MakeImmutable(result);
}
MaybeHandle<BigInt> BigInt::LeftShift(Isolate* isolate, Handle<BigInt> x,
......@@ -1238,88 +1237,6 @@ void BigInt::BigIntShortPrint(std::ostream& os) {
// Internal helpers.
void MutableBigInt::AbsoluteAdd(MutableBigInt result, BigInt x, BigInt y) {
DisallowGarbageCollection no_gc;
digit_t carry = 0;
int i = 0;
for (; i < y.length(); i++) {
digit_t new_carry = 0;
digit_t sum = digit_add(x.digit(i), y.digit(i), &new_carry);
sum = digit_add(sum, carry, &new_carry);
result.set_digit(i, sum);
carry = new_carry;
}
for (; i < x.length(); i++) {
digit_t new_carry = 0;
digit_t sum = digit_add(x.digit(i), carry, &new_carry);
result.set_digit(i, sum);
carry = new_carry;
}
result.set_digit(i, carry);
}
MaybeHandle<BigInt> MutableBigInt::AbsoluteAdd(Isolate* isolate,
Handle<BigInt> x,
Handle<BigInt> y,
bool result_sign) {
if (x->length() < y->length()) return AbsoluteAdd(isolate, y, x, result_sign);
if (x->is_zero()) {
DCHECK(y->is_zero());
return x;
}
if (y->is_zero()) {
return result_sign == x->sign() ? x : BigInt::UnaryMinus(isolate, x);
}
Handle<MutableBigInt> result;
if (!New(isolate, x->length() + 1).ToHandle(&result)) {
return MaybeHandle<BigInt>();
}
AbsoluteAdd(*result, *x, *y);
result->set_sign(result_sign);
return MakeImmutable(result);
}
Handle<BigInt> MutableBigInt::AbsoluteSub(Isolate* isolate, Handle<BigInt> x,
Handle<BigInt> y, bool result_sign) {
DCHECK(x->length() >= y->length());
SLOW_DCHECK(bigint::Compare(GetDigits(x), GetDigits(y)) >= 0);
if (x->is_zero()) {
DCHECK(y->is_zero());
return x;
}
if (y->is_zero()) {
return result_sign == x->sign() ? x : BigInt::UnaryMinus(isolate, x);
}
Handle<MutableBigInt> result = New(isolate, x->length()).ToHandleChecked();
AbsoluteSub(*result, *x, *y);
result->set_sign(result_sign);
return MakeImmutable(result);
}
void MutableBigInt::AbsoluteSub(MutableBigInt result, BigInt x, BigInt y) {
DisallowGarbageCollection no_gc;
digit_t borrow = 0;
int i = 0;
for (; i < y.length(); i++) {
digit_t new_borrow = 0;
digit_t difference = digit_sub(x.digit(i), y.digit(i), &new_borrow);
difference = digit_sub(difference, borrow, &new_borrow);
result.set_digit(i, difference);
borrow = new_borrow;
}
for (; i < x.length(); i++) {
digit_t new_borrow = 0;
digit_t difference = digit_sub(x.digit(i), borrow, &new_borrow);
result.set_digit(i, difference);
borrow = new_borrow;
}
DCHECK_EQ(0, borrow);
}
// Adds 1 to the absolute value of {x} and sets the result's sign to {sign}.
// {result_storage} is optional; if present, it will be used to store the
// result, otherwise a new BigInt will be allocated for the result.
......@@ -2211,7 +2128,7 @@ void MutableBigInt_AbsoluteAddAndCanonicalize(Address result_addr,
BigInt y = BigInt::cast(Object(y_addr));
MutableBigInt result = MutableBigInt::cast(Object(result_addr));
MutableBigInt::AbsoluteAdd(result, x, y);
bigint::Add(GetRWDigits(result), GetDigits(x), GetDigits(y));
MutableBigInt::Canonicalize(result);
}
......@@ -2228,7 +2145,7 @@ void MutableBigInt_AbsoluteSubAndCanonicalize(Address result_addr,
BigInt y = BigInt::cast(Object(y_addr));
MutableBigInt result = MutableBigInt::cast(Object(result_addr));
MutableBigInt::AbsoluteSub(result, x, y);
bigint::Subtract(GetRWDigits(result), GetDigits(x), GetDigits(y));
MutableBigInt::Canonicalize(result);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment