Coverage Report

Created: 2023-02-13 06:21

/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
#include <botan/internal/divide.h>
11
#include <botan/internal/mp_core.h>
12
#include <botan/internal/bit_ops.h>
13
#include <algorithm>
14
15
namespace Botan {
16
17
//static
18
BigInt BigInt::add2(const BigInt& x, const word y[], size_t y_words, BigInt::Sign y_sign)
19
4.92M
   {
20
4.92M
   const size_t x_sw = x.sig_words();
21
22
4.92M
   BigInt z = BigInt::with_capacity(std::max(x_sw, y_words) + 1);
23
24
4.92M
   if(x.sign() == y_sign)
25
2.81M
      {
26
2.81M
      bigint_add3(z.mutable_data(), x.data(), x_sw, y, y_words);
27
2.81M
      z.set_sign(x.sign());
28
2.81M
      }
29
2.11M
   else
30
2.11M
      {
31
2.11M
      const int32_t relative_size = bigint_sub_abs(z.mutable_data(), x.data(), x_sw, y, y_words);
32
33
      //z.sign_fixup(relative_size, y_sign);
34
2.11M
      if(relative_size < 0)
35
405k
         z.set_sign(y_sign);
36
1.70M
      else if(relative_size == 0)
37
486
         z.set_sign(BigInt::Positive);
38
1.70M
      else
39
1.70M
         z.set_sign(x.sign());
40
2.11M
      }
41
42
4.92M
   return z;
43
4.92M
   }
44
45
/*
46
* Multiplication Operator
47
*/
48
BigInt operator*(const BigInt& x, const BigInt& y)
49
3.12M
   {
50
3.12M
   const size_t x_sw = x.sig_words();
51
3.12M
   const size_t y_sw = y.sig_words();
52
53
3.12M
   BigInt z = BigInt::with_capacity(x.size() + y.size());
54
55
3.12M
   if(x_sw == 1 && y_sw)
56
840k
      bigint_linmul3(z.mutable_data(), y.data(), y_sw, x.word_at(0));
57
2.28M
   else if(y_sw == 1 && x_sw)
58
729k
      bigint_linmul3(z.mutable_data(), x.data(), x_sw, y.word_at(0));
59
1.55M
   else if(x_sw && y_sw)
60
1.47M
      {
61
1.47M
      secure_vector<word> workspace(z.size());
62
63
1.47M
      bigint_mul(z.mutable_data(), z.size(),
64
1.47M
                 x.data(), x.size(), x_sw,
65
1.47M
                 y.data(), y.size(), y_sw,
66
1.47M
                 workspace.data(), workspace.size());
67
1.47M
      }
68
69
3.12M
   z.cond_flip_sign(x_sw > 0 && y_sw > 0 && x.sign() != y.sign());
70
71
3.12M
   return z;
72
3.12M
   }
73
74
/*
75
* Multiplication Operator
76
*/
77
BigInt operator*(const BigInt& x, word y)
78
6.70M
   {
79
6.70M
   const size_t x_sw = x.sig_words();
80
81
6.70M
   BigInt z = BigInt::with_capacity(x_sw + 1);
82
83
6.70M
   if(x_sw && y)
84
3.34M
      {
85
3.34M
      bigint_linmul3(z.mutable_data(), x.data(), x_sw, y);
86
3.34M
      z.set_sign(x.sign());
87
3.34M
      }
88
89
6.70M
   return z;
90
6.70M
   }
91
92
/*
93
* Division Operator
94
*/
95
BigInt operator/(const BigInt& x, const BigInt& y)
96
1.63k
   {
97
1.63k
   if(y.sig_words() == 1)
98
378
      {
99
378
      return x / y.word_at(0);
100
378
      }
101
102
1.25k
   BigInt q, r;
103
1.25k
   vartime_divide(x, y, q, r);
104
1.25k
   return q;
105
1.63k
   }
106
107
/*
108
* Division Operator
109
*/
110
BigInt operator/(const BigInt& x, word y)
111
3.57M
   {
112
3.57M
   if(y == 0)
113
0
      throw Invalid_Argument("BigInt::operator/ divide by zero");
114
115
3.57M
   BigInt q;
116
3.57M
   word r;
117
3.57M
   ct_divide_word(x, y, q, r);
118
3.57M
   return q;
119
3.57M
   }
120
121
/*
122
* Modulo Operator
123
*/
124
BigInt operator%(const BigInt& n, const BigInt& mod)
125
3.74M
   {
126
3.74M
   if(mod.is_zero())
127
0
      throw Invalid_Argument("BigInt::operator% divide by zero");
128
3.74M
   if(mod.is_negative())
129
0
      throw Invalid_Argument("BigInt::operator% modulus must be > 0");
130
3.74M
   if(n.is_positive() && mod.is_positive() && n < mod)
131
122k
      return n;
132
133
3.62M
   if(mod.sig_words() == 1)
134
671k
      {
135
671k
      return BigInt::from_word(n % mod.word_at(0));
136
671k
      }
137
138
2.95M
   BigInt q, r;
139
2.95M
   vartime_divide(n, mod, q, r);
140
2.95M
   return r;
141
3.62M
   }
142
143
/*
144
* Modulo Operator
145
*/
146
word operator%(const BigInt& n, word mod)
147
8.83M
   {
148
8.83M
   if(mod == 0)
149
0
      throw Invalid_Argument("BigInt::operator% divide by zero");
150
151
8.83M
   if(mod == 1)
152
858
      return 0;
153
154
8.83M
   word remainder = 0;
155
156
8.83M
   if(is_power_of_2(mod))
157
8.16M
      {
158
8.16M
      remainder = (n.word_at(0) & (mod - 1));
159
8.16M
      }
160
669k
   else
161
669k
      {
162
669k
      const size_t sw = n.sig_words();
163
1.44M
      for(size_t i = sw; i > 0; --i)
164
780k
         {
165
780k
         remainder = bigint_modop(remainder, n.word_at(i-1), mod);
166
780k
         }
167
669k
      }
168
169
8.83M
   if(remainder && n.sign() == BigInt::Negative)
170
753
      return mod - remainder;
171
8.83M
   return remainder;
172
8.83M
   }
173
174
/*
175
* Left Shift Operator
176
*/
177
BigInt operator<<(const BigInt& x, size_t shift)
178
2.95M
   {
179
2.95M
   const size_t shift_words = shift / BOTAN_MP_WORD_BITS,
180
2.95M
                shift_bits  = shift % BOTAN_MP_WORD_BITS;
181
182
2.95M
   const size_t x_sw = x.sig_words();
183
184
2.95M
   BigInt y = BigInt::with_capacity(x_sw + shift_words + (shift_bits ? 1 : 0));
185
2.95M
   bigint_shl2(y.mutable_data(), x.data(), x_sw, shift_words, shift_bits);
186
2.95M
   y.set_sign(x.sign());
187
2.95M
   return y;
188
2.95M
   }
189
190
/*
191
* Right Shift Operator
192
*/
193
BigInt operator>>(const BigInt& x, size_t shift)
194
25.0k
   {
195
25.0k
   const size_t shift_words = shift / BOTAN_MP_WORD_BITS;
196
25.0k
   const size_t shift_bits  = shift % BOTAN_MP_WORD_BITS;
197
25.0k
   const size_t x_sw = x.sig_words();
198
199
25.0k
   if(shift_words >= x_sw)
200
0
      return BigInt::zero();
201
202
25.0k
   BigInt y = BigInt::with_capacity(x_sw - shift_words);
203
25.0k
   bigint_shr2(y.mutable_data(), x.data(), x_sw, shift_words, shift_bits);
204
205
25.0k
   if(x.is_negative() && y.is_zero())
206
0
      y.set_sign(BigInt::Positive);
207
25.0k
   else
208
25.0k
      y.set_sign(x.sign());
209
210
25.0k
   return y;
211
25.0k
   }
212
213
}