Coverage Report

Created: 2026-09-28 06:36

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/botan/src/lib/math/bigint/big_ops3.cpp
Line
Count
Source
1
/*
2
* BigInt Binary Operators
3
* (C) 1999-2007,2018 Jack Lloyd
4
*     2016 Matthias Gierlings
5
*
6
* Botan is released under the Simplified BSD License (see license.txt)
7
*/
8
9
#include <botan/bigint.h>
10
11
#include <botan/internal/bit_ops.h>
12
#include <botan/internal/divide.h>
13
#include <botan/internal/mp_core.h>
14
#include <algorithm>
15
16
namespace Botan {
17
18
//static
19
10.3k
BigInt BigInt::add2(const BigInt& x, const word y[], size_t y_size, BigInt::Sign y_sign) {
20
10.3k
   const size_t x_sw = x.sig_words();
21
22
10.3k
   BigInt z = BigInt::with_capacity(std::max(x_sw, y_size) + 1);
23
24
10.3k
   if(x.sign() == y_sign) {
25
522
      word carry = bigint_add3(z.mutable_data(), x._data(), x_sw, y, y_size);
26
522
      z.mutable_data()[std::max(x_sw, y_size)] += carry;
27
522
      z.set_sign(x.sign());
28
9.84k
   } else {
29
9.84k
      const int32_t relative_size = bigint_cmp(x.data(), x_sw, y, y_size);
30
31
9.84k
      if(relative_size < 0) {
32
         // x < y so z = abs(y - x)
33
         // NOLINTNEXTLINE(*-suspicious-call-argument) intentionally swapping x and y here
34
128
         bigint_sub3(z.mutable_data(), y, y_size, x.data(), x_sw);
35
128
         z.set_sign(y_sign);
36
9.71k
      } else if(relative_size == 0) {
37
         // Positive zero (nothing to do in this case)
38
9.70k
      } else {
39
         /*
40
         * We know at this point that x >= y so if y_size is larger than
41
         * x_sw, we are guaranteed they are just leading zeros which can
42
         * be ignored
43
         */
44
9.70k
         y_size = std::min(x_sw, y_size);
45
9.70k
         bigint_sub3(z.mutable_data(), x.data(), x_sw, y, y_size);
46
9.70k
         z.set_sign(x.sign());
47
9.70k
      }
48
9.84k
   }
49
50
10.3k
   return z;
51
10.3k
}
52
53
/*
54
* Multiplication Operator
55
*/
56
412
BigInt operator*(const BigInt& x, const BigInt& y) {
57
412
   const size_t x_sw = x.sig_words();
58
412
   const size_t y_sw = y.sig_words();
59
60
412
   BigInt z = BigInt::with_capacity(x.size() + y.size());
61
62
412
   if(x_sw == 1 && y_sw > 0) {
63
167
      bigint_linmul3(z.mutable_data(), y._data(), y_sw, x.word_at(0));
64
245
   } else if(y_sw == 1 && x_sw > 0) {
65
28
      bigint_linmul3(z.mutable_data(), x._data(), x_sw, y.word_at(0));
66
217
   } else if(x_sw > 0 && y_sw > 0) {
67
178
      secure_vector<word> workspace(z.size());
68
69
178
      bigint_mul(z.mutable_data(),
70
178
                 z.size(),
71
178
                 x._data(),
72
178
                 x.size(),
73
178
                 x_sw,
74
178
                 y._data(),
75
178
                 y.size(),
76
178
                 y_sw,
77
178
                 workspace.data(),
78
178
                 workspace.size());
79
178
   }
80
81
412
   z.cond_flip_sign(x_sw > 0 && y_sw > 0 && x.sign() != y.sign());
82
83
412
   return z;
84
412
}
85
86
/*
87
* Multiplication Operator
88
*/
89
40.6k
BigInt operator*(const BigInt& x, word y) {
90
40.6k
   const size_t x_sw = x.sig_words();
91
92
40.6k
   BigInt z = BigInt::with_capacity(x_sw + 1);
93
94
40.6k
   if(x_sw > 0 && y > 0) {
95
40.3k
      bigint_linmul3(z.mutable_data(), x._data(), x_sw, y);
96
40.3k
      z.set_sign(x.sign());
97
40.3k
   }
98
99
40.6k
   return z;
100
40.6k
}
101
102
/*
103
* Division Operator
104
*/
105
410
BigInt operator/(const BigInt& x, const BigInt& y) {
106
410
   if(y.sig_words() == 1) {
107
0
      return x / y.word_at(0);
108
0
   }
109
110
410
   BigInt q;
111
410
   BigInt r;
112
410
   vartime_divide(x, y, q, r);
113
410
   return q;
114
410
}
115
116
/*
117
* Division Operator
118
*/
119
21.5k
BigInt operator/(const BigInt& x, word y) {
120
21.5k
   if(y == 0) {
121
0
      throw Invalid_Argument("BigInt::operator/ divide by zero");
122
0
   }
123
124
21.5k
   BigInt q;
125
21.5k
   word r = 0;
126
21.5k
   ct_divide_word(x, y, q, r);
127
21.5k
   return q;
128
21.5k
}
129
130
/*
131
* Modulo Operator
132
*/
133
24.9k
BigInt operator%(const BigInt& n, const BigInt& mod) {
134
24.9k
   if(mod.is_zero()) {
135
0
      throw Invalid_Argument("BigInt::operator% divide by zero");
136
0
   }
137
24.9k
   if(mod.is_negative()) {
138
0
      throw Invalid_Argument("BigInt::operator% modulus must be > 0");
139
0
   }
140
24.9k
   if(n.is_positive() && mod.is_positive() && n < mod) {
141
3.98k
      return n;
142
3.98k
   }
143
144
20.9k
   if(mod.sig_words() == 1) {
145
9.05k
      return BigInt::from_word(n % mod.word_at(0));
146
9.05k
   }
147
148
11.8k
   BigInt q;
149
11.8k
   BigInt r;
150
11.8k
   vartime_divide(n, mod, q, r);
151
11.8k
   return r;
152
20.9k
}
153
154
/*
155
* Modulo Operator
156
*/
157
57.3k
word operator%(const BigInt& n, word mod) {
158
57.3k
   if(mod == 0) {
159
0
      throw Invalid_Argument("BigInt::operator% divide by zero");
160
0
   }
161
162
57.3k
   if(mod == 1) {
163
0
      return 0;
164
0
   }
165
166
57.3k
   word remainder = 0;
167
168
57.3k
   if(is_power_of_2(mod)) {
169
48.2k
      remainder = (n.word_at(0) & (mod - 1));
170
48.2k
   } else {
171
9.05k
      const size_t sw = n.sig_words();
172
20.7k
      for(size_t i = sw; i > 0; --i) {
173
11.6k
         remainder = bigint_modop_vartime(remainder, n.word_at(i - 1), mod);
174
11.6k
      }
175
9.05k
   }
176
177
57.3k
   if(remainder != 0 && n.sign() == BigInt::Negative) {
178
0
      return mod - remainder;
179
0
   }
180
57.3k
   return remainder;
181
57.3k
}
182
183
/*
184
* Left Shift Operator
185
*/
186
12.6k
BigInt operator<<(const BigInt& x, size_t shift) {
187
12.6k
   const size_t x_sw = x.sig_words();
188
189
12.6k
   const size_t new_size = x_sw + (shift + WordInfo<word>::bits - 1) / WordInfo<word>::bits;
190
12.6k
   BigInt y = BigInt::with_capacity(new_size);
191
12.6k
   bigint_shl2(y.mutable_data(), x._data(), x_sw, shift);
192
12.6k
   y.set_sign(x.sign());
193
12.6k
   return y;
194
12.6k
}
195
196
/*
197
* Right Shift Operator
198
*/
199
572
BigInt operator>>(const BigInt& x, size_t shift) {
200
572
   const size_t shift_words = shift / WordInfo<word>::bits;
201
572
   const size_t x_sw = x.sig_words();
202
203
572
   if(shift_words >= x_sw) {
204
86
      return BigInt::zero();
205
86
   }
206
207
486
   BigInt y = BigInt::with_capacity(x_sw - shift_words);
208
486
   bigint_shr2(y.mutable_data(), x._data(), x_sw, shift);
209
210
486
   if(x.is_negative() && y.is_zero()) {
211
0
      y.set_sign(BigInt::Positive);
212
486
   } else {
213
486
      y.set_sign(x.sign());
214
486
   }
215
216
486
   return y;
217
572
}
218
219
}  // namespace Botan