// Copyright 2021 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "src/bigint/vector-arithmetic.h" #include "src/bigint/bigint-internal.h" #include "src/bigint/digit-arithmetic.h" namespace v8 { namespace bigint { digit_t AddAndReturnOverflow(RWDigits Z, Digits X) { X.Normalize(); if (X.len() == 0) return 0; digit_t carry = 0; int i = 0; for (; i < X.len(); i++) { Z[i] = digit_add3(Z[i], X[i], carry, &carry); } for (; i < Z.len() && carry != 0; i++) { Z[i] = digit_add2(Z[i], carry, &carry); } return carry; } digit_t SubAndReturnBorrow(RWDigits Z, Digits X) { X.Normalize(); if (X.len() == 0) return 0; digit_t borrow = 0; int i = 0; for (; i < X.len(); i++) { Z[i] = digit_sub2(Z[i], X[i], borrow, &borrow); } for (; i < Z.len() && borrow != 0; i++) { Z[i] = digit_sub(Z[i], borrow, &borrow); } return borrow; } void Add(RWDigits Z, Digits X, Digits Y) { if (X.len() < Y.len()) { return Add(Z, Y, X); } int i = 0; digit_t carry = 0; for (; i < Y.len(); i++) { Z[i] = digit_add3(X[i], Y[i], carry, &carry); } for (; i < X.len(); i++) { Z[i] = digit_add2(X[i], carry, &carry); } for (; i < Z.len(); i++) { Z[i] = carry; carry = 0; } } void Subtract(RWDigits Z, Digits X, Digits Y) { X.Normalize(); Y.Normalize(); DCHECK(X.len() >= Y.len()); int i = 0; digit_t borrow = 0; for (; i < Y.len(); i++) { Z[i] = digit_sub2(X[i], Y[i], borrow, &borrow); } for (; i < X.len(); i++) { Z[i] = digit_sub(X[i], borrow, &borrow); } DCHECK(borrow == 0); for (; i < Z.len(); i++) Z[i] = 0; } digit_t AddAndReturnCarry(RWDigits Z, Digits X, Digits Y) { DCHECK(Z.len() >= Y.len() && X.len() >= Y.len()); digit_t carry = 0; for (int i = 0; i < Y.len(); i++) { Z[i] = digit_add3(X[i], Y[i], carry, &carry); } return carry; } digit_t SubtractAndReturnBorrow(RWDigits Z, Digits X, Digits Y) { DCHECK(Z.len() >= Y.len() && X.len() >= Y.len()); digit_t borrow = 0; for (int i = 0; i < Y.len(); i++) { Z[i] = digit_sub2(X[i], Y[i], borrow, &borrow); } 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; } void AddOne(RWDigits Z, Digits X) { digit_t carry = 1; int i = 0; for (; carry > 0 && i < X.len(); i++) Z[i] = digit_add2(X[i], carry, &carry); if (carry > 0) Z[i++] = carry; for (; i < X.len(); i++) Z[i] = X[i]; for (; i < Z.len(); i++) Z[i] = 0; } void SubtractOne(RWDigits Z, Digits X) { digit_t borrow = 1; int i = 0; for (; borrow > 0; i++) Z[i] = digit_sub(X[i], borrow, &borrow); for (; i < X.len(); i++) Z[i] = X[i]; for (; i < Z.len(); i++) Z[i] = 0; } } // namespace bigint } // namespace v8