1 // Copyright 2021 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/bigint/vector-arithmetic.h"
6 
7 #include "src/bigint/bigint-internal.h"
8 #include "src/bigint/digit-arithmetic.h"
9 
10 namespace v8 {
11 namespace bigint {
12 
AddAndReturnOverflow(RWDigits Z,Digits X)13 digit_t AddAndReturnOverflow(RWDigits Z, Digits X) {
14   X.Normalize();
15   if (X.len() == 0) return 0;
16   digit_t carry = 0;
17   int i = 0;
18   for (; i < X.len(); i++) {
19     Z[i] = digit_add3(Z[i], X[i], carry, &carry);
20   }
21   for (; i < Z.len() && carry != 0; i++) {
22     Z[i] = digit_add2(Z[i], carry, &carry);
23   }
24   return carry;
25 }
26 
SubAndReturnBorrow(RWDigits Z,Digits X)27 digit_t SubAndReturnBorrow(RWDigits Z, Digits X) {
28   X.Normalize();
29   if (X.len() == 0) return 0;
30   digit_t borrow = 0;
31   int i = 0;
32   for (; i < X.len(); i++) {
33     Z[i] = digit_sub2(Z[i], X[i], borrow, &borrow);
34   }
35   for (; i < Z.len() && borrow != 0; i++) {
36     Z[i] = digit_sub(Z[i], borrow, &borrow);
37   }
38   return borrow;
39 }
40 
Add(RWDigits Z,Digits X,Digits Y)41 void Add(RWDigits Z, Digits X, Digits Y) {
42   if (X.len() < Y.len()) {
43     return Add(Z, Y, X);
44   }
45   int i = 0;
46   digit_t carry = 0;
47   for (; i < Y.len(); i++) {
48     Z[i] = digit_add3(X[i], Y[i], carry, &carry);
49   }
50   for (; i < X.len(); i++) {
51     Z[i] = digit_add2(X[i], carry, &carry);
52   }
53   for (; i < Z.len(); i++) {
54     Z[i] = carry;
55     carry = 0;
56   }
57 }
58 
Subtract(RWDigits Z,Digits X,Digits Y)59 void Subtract(RWDigits Z, Digits X, Digits Y) {
60   X.Normalize();
61   Y.Normalize();
62   DCHECK(X.len() >= Y.len());
63   int i = 0;
64   digit_t borrow = 0;
65   for (; i < Y.len(); i++) {
66     Z[i] = digit_sub2(X[i], Y[i], borrow, &borrow);
67   }
68   for (; i < X.len(); i++) {
69     Z[i] = digit_sub(X[i], borrow, &borrow);
70   }
71   DCHECK(borrow == 0);  // NOLINT(readability/check)
72   for (; i < Z.len(); i++) Z[i] = 0;
73 }
74 
AddAndReturnCarry(RWDigits Z,Digits X,Digits Y)75 digit_t AddAndReturnCarry(RWDigits Z, Digits X, Digits Y) {
76   DCHECK(Z.len() >= Y.len() && X.len() >= Y.len());
77   digit_t carry = 0;
78   for (int i = 0; i < Y.len(); i++) {
79     Z[i] = digit_add3(X[i], Y[i], carry, &carry);
80   }
81   return carry;
82 }
83 
SubtractAndReturnBorrow(RWDigits Z,Digits X,Digits Y)84 digit_t SubtractAndReturnBorrow(RWDigits Z, Digits X, Digits Y) {
85   DCHECK(Z.len() >= Y.len() && X.len() >= Y.len());
86   digit_t borrow = 0;
87   for (int i = 0; i < Y.len(); i++) {
88     Z[i] = digit_sub2(X[i], Y[i], borrow, &borrow);
89   }
90   return borrow;
91 }
92 
AddSigned(RWDigits Z,Digits X,bool x_negative,Digits Y,bool y_negative)93 bool AddSigned(RWDigits Z, Digits X, bool x_negative, Digits Y,
94                bool y_negative) {
95   if (x_negative == y_negative) {
96     Add(Z, X, Y);
97     return x_negative;
98   }
99   if (GreaterThanOrEqual(X, Y)) {
100     Subtract(Z, X, Y);
101     return x_negative;
102   }
103   Subtract(Z, Y, X);
104   return !x_negative;
105 }
106 
SubtractSigned(RWDigits Z,Digits X,bool x_negative,Digits Y,bool y_negative)107 bool SubtractSigned(RWDigits Z, Digits X, bool x_negative, Digits Y,
108                     bool y_negative) {
109   if (x_negative != y_negative) {
110     Add(Z, X, Y);
111     return x_negative;
112   }
113   if (GreaterThanOrEqual(X, Y)) {
114     Subtract(Z, X, Y);
115     return x_negative;
116   }
117   Subtract(Z, Y, X);
118   return !x_negative;
119 }
120 
AddOne(RWDigits Z,Digits X)121 void AddOne(RWDigits Z, Digits X) {
122   digit_t carry = 1;
123   int i = 0;
124   for (; carry > 0 && i < X.len(); i++) Z[i] = digit_add2(X[i], carry, &carry);
125   if (carry > 0) Z[i++] = carry;
126   for (; i < X.len(); i++) Z[i] = X[i];
127   for (; i < Z.len(); i++) Z[i] = 0;
128 }
129 
SubtractOne(RWDigits Z,Digits X)130 void SubtractOne(RWDigits Z, Digits X) {
131   digit_t borrow = 1;
132   int i = 0;
133   for (; borrow > 0; i++) Z[i] = digit_sub(X[i], borrow, &borrow);
134   for (; i < X.len(); i++) Z[i] = X[i];
135   for (; i < Z.len(); i++) Z[i] = 0;
136 }
137 
138 }  // namespace bigint
139 }  // namespace v8
140