/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 |