Coverage Report

Created: 2023-12-08 07:00

/src/botan/src/lib/math/bigint/big_ops3.cpp
Line
Count
Source (jump to first uncovered line)
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
1.42M
BigInt BigInt::add2(const BigInt& x, const word y[], size_t y_words, BigInt::Sign y_sign) {
20
1.42M
   const size_t x_sw = x.sig_words();
21
22
1.42M
   BigInt z = BigInt::with_capacity(std::max(x_sw, y_words) + 1);
23
24
1.42M
   if(x.sign() == y_sign) {
25
1.03M
      bigint_add3(z.mutable_data(), x.data(), x_sw, y, y_words);
26
1.03M
      z.set_sign(x.sign());
27
1.03M
   } else {
28
394k
      const int32_t relative_size = bigint_sub_abs(z.mutable_data(), x.data(), x_sw, y, y_words);
29
30
      //z.sign_fixup(relative_size, y_sign);
31
394k
      if(relative_size < 0) {
32
228k
         z.set_sign(y_sign);
33
228k
      } else if(relative_size == 0) {
34
143
         z.set_sign(BigInt::Positive);
35
165k
      } else {
36
165k
         z.set_sign(x.sign());
37
165k
      }
38
394k
   }
39
40
1.42M
   return z;
41
1.42M
}
42
43
/*
44
* Multiplication Operator
45
*/
46
1.25M
BigInt operator*(const BigInt& x, const BigInt& y) {
47
1.25M
   const size_t x_sw = x.sig_words();
48
1.25M
   const size_t y_sw = y.sig_words();
49
50
1.25M
   BigInt z = BigInt::with_capacity(x.size() + y.size());
51
52
1.25M
   if(x_sw == 1 && y_sw) {
53
416k
      bigint_linmul3(z.mutable_data(), y.data(), y_sw, x.word_at(0));
54
839k
   } else if(y_sw == 1 && x_sw) {
55
384k
      bigint_linmul3(z.mutable_data(), x.data(), x_sw, y.word_at(0));
56
455k
   } else if(x_sw && y_sw) {
57
438k
      secure_vector<word> workspace(z.size());
58
59
438k
      bigint_mul(z.mutable_data(),
60
438k
                 z.size(),
61
438k
                 x.data(),
62
438k
                 x.size(),
63
438k
                 x_sw,
64
438k
                 y.data(),
65
438k
                 y.size(),
66
438k
                 y_sw,
67
438k
                 workspace.data(),
68
438k
                 workspace.size());
69
438k
   }
70
71
1.25M
   z.cond_flip_sign(x_sw > 0 && y_sw > 0 && x.sign() != y.sign());
72
73
1.25M
   return z;
74
1.25M
}
75
76
/*
77
* Multiplication Operator
78
*/
79
133k
BigInt operator*(const BigInt& x, word y) {
80
133k
   const size_t x_sw = x.sig_words();
81
82
133k
   BigInt z = BigInt::with_capacity(x_sw + 1);
83
84
133k
   if(x_sw && y) {
85
66.8k
      bigint_linmul3(z.mutable_data(), x.data(), x_sw, y);
86
66.8k
      z.set_sign(x.sign());
87
66.8k
   }
88
89
133k
   return z;
90
133k
}
91
92
/*
93
* Division Operator
94
*/
95
1.74k
BigInt operator/(const BigInt& x, const BigInt& y) {
96
1.74k
   if(y.sig_words() == 1) {
97
232
      return x / y.word_at(0);
98
232
   }
99
100
1.51k
   BigInt q, r;
101
1.51k
   vartime_divide(x, y, q, r);
102
1.51k
   return q;
103
1.74k
}
104
105
/*
106
* Division Operator
107
*/
108
68.4k
BigInt operator/(const BigInt& x, word y) {
109
68.4k
   if(y == 0) {
110
0
      throw Invalid_Argument("BigInt::operator/ divide by zero");
111
0
   }
112
113
68.4k
   BigInt q;
114
68.4k
   word r;
115
68.4k
   ct_divide_word(x, y, q, r);
116
68.4k
   return q;
117
68.4k
}
118
119
/*
120
* Modulo Operator
121
*/
122
77.5k
BigInt operator%(const BigInt& n, const BigInt& mod) {
123
77.5k
   if(mod.is_zero()) {
124
4
      throw Invalid_Argument("BigInt::operator% divide by zero");
125
4
   }
126
77.5k
   if(mod.is_negative()) {
127
0
      throw Invalid_Argument("BigInt::operator% modulus must be > 0");
128
0
   }
129
77.5k
   if(n.is_positive() && mod.is_positive() && n < mod) {
130
12.6k
      return n;
131
12.6k
   }
132
133
64.8k
   if(mod.sig_words() == 1) {
134
21.8k
      return BigInt::from_word(n % mod.word_at(0));
135
21.8k
   }
136
137
43.0k
   BigInt q, r;
138
43.0k
   vartime_divide(n, mod, q, r);
139
43.0k
   return r;
140
64.8k
}
141
142
/*
143
* Modulo Operator
144
*/
145
440k
word operator%(const BigInt& n, word mod) {
146
440k
   if(mod == 0) {
147
0
      throw Invalid_Argument("BigInt::operator% divide by zero");
148
0
   }
149
150
440k
   if(mod == 1) {
151
3
      return 0;
152
3
   }
153
154
440k
   word remainder = 0;
155
156
440k
   if(is_power_of_2(mod)) {
157
152k
      remainder = (n.word_at(0) & (mod - 1));
158
287k
   } else {
159
287k
      const size_t sw = n.sig_words();
160
1.88M
      for(size_t i = sw; i > 0; --i) {
161
1.59M
         remainder = bigint_modop(remainder, n.word_at(i - 1), mod);
162
1.59M
      }
163
287k
   }
164
165
440k
   if(remainder && n.sign() == BigInt::Negative) {
166
208
      return mod - remainder;
167
208
   }
168
439k
   return remainder;
169
440k
}
170
171
/*
172
* Left Shift Operator
173
*/
174
45.3k
BigInt operator<<(const BigInt& x, size_t shift) {
175
45.3k
   const size_t shift_words = shift / BOTAN_MP_WORD_BITS, shift_bits = shift % BOTAN_MP_WORD_BITS;
176
177
45.3k
   const size_t x_sw = x.sig_words();
178
179
45.3k
   BigInt y = BigInt::with_capacity(x_sw + shift_words + (shift_bits ? 1 : 0));
180
45.3k
   bigint_shl2(y.mutable_data(), x.data(), x_sw, shift_words, shift_bits);
181
45.3k
   y.set_sign(x.sign());
182
45.3k
   return y;
183
45.3k
}
184
185
/*
186
* Right Shift Operator
187
*/
188
60.6k
BigInt operator>>(const BigInt& x, size_t shift) {
189
60.6k
   const size_t shift_words = shift / BOTAN_MP_WORD_BITS;
190
60.6k
   const size_t shift_bits = shift % BOTAN_MP_WORD_BITS;
191
60.6k
   const size_t x_sw = x.sig_words();
192
193
60.6k
   if(shift_words >= x_sw) {
194
191
      return BigInt::zero();
195
191
   }
196
197
60.4k
   BigInt y = BigInt::with_capacity(x_sw - shift_words);
198
60.4k
   bigint_shr2(y.mutable_data(), x.data(), x_sw, shift_words, shift_bits);
199
200
60.4k
   if(x.is_negative() && y.is_zero()) {
201
0
      y.set_sign(BigInt::Positive);
202
60.4k
   } else {
203
60.4k
      y.set_sign(x.sign());
204
60.4k
   }
205
206
60.4k
   return y;
207
60.6k
}
208
209
}  // namespace Botan