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);
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