28
28
29
29
namespace scl ::math {
30
30
31
+ class Number ;
32
+
33
+ /* *
34
+ * @brief Compute the least common multiple of two numbers.
35
+ * @param a the first number.
36
+ * @param b the second number.
37
+ * @return \f$lcm(a, b)\f$.
38
+ */
39
+ Number LCM (const Number& a, const Number& b);
40
+
41
+ /* *
42
+ * @brief Compute the greatest common divisor of two numbers.
43
+ * @param a the first number.
44
+ * @param b the second number.
45
+ * @return \f$gcd(a, b)\f$.
46
+ */
47
+ Number GCD (const Number& a, const Number& b);
48
+
49
+ /* *
50
+ * @brief Compute the modular inverse of a number.
51
+ * @param val the value to invert.
52
+ * @param mod the modulus.
53
+ * @return \f$val^{-1} \mod mod \f$.
54
+ * @throws std::logic_error if \p val is not invertible.
55
+ * @throws std::invalid_argument if \p mod is 0.
56
+ */
57
+ Number ModInverse (const Number& val, const Number& mod);
58
+
59
+ /* *
60
+ * @brief Compute a modular exponentiation.
61
+ * @param base the base.
62
+ * @param exp the exponent.
63
+ * @param mod the modulus.
64
+ * @return \f$base^{exp} \mod mod\f$.
65
+ */
66
+ Number ModExp (const Number& base, const Number& exp, const Number& mod);
67
+
31
68
/* *
32
69
* @brief Arbitrary precision integer.
33
70
*/
34
71
class Number final : Print<Number> {
35
72
public:
36
73
/* *
37
74
* @brief Generate a random Number.
38
- * @param bits the number of bits in the resulting number
39
- * @param prg a prg for generating the random number
40
- * @return a random Number
75
+ * @param bits the number of bits in the resulting number.
76
+ * @param prg a prg for generating the random number.
77
+ * @return a random Number.
41
78
*/
42
79
static Number Random (std::size_t bits, util::PRG& prg);
43
80
81
+ /* *
82
+ * @brief Generate a random prime.
83
+ * @param bits the number of bits in the resulting prime.
84
+ * @param prg a prg for generating the random prime.
85
+ * @return a random prime.
86
+ */
87
+ static Number RandomPrime (std::size_t bits, util::PRG& prg);
88
+
44
89
/* *
45
90
* @brief Read a Number from a string
46
91
* @param str the string
47
92
* @return a Number.
48
93
*/
49
94
static Number FromString (const std::string& str);
50
95
96
+ /* *
97
+ * @brief Read a number from a buffer.
98
+ * @param buf the buffer.
99
+ * @return a Number.
100
+ */
101
+ static Number Read (const unsigned char * buf);
102
+
51
103
/* *
52
104
* @brief Construct a Number from an int.
53
105
* @param value the int
@@ -85,7 +137,7 @@ class Number final : Print<Number> {
85
137
Number copy (number);
86
138
swap (*this , copy);
87
139
return *this ;
88
- };
140
+ }
89
141
90
142
/* *
91
143
* @brief Move assignment from a Number.
@@ -95,7 +147,7 @@ class Number final : Print<Number> {
95
147
Number& operator =(Number&& number) noexcept {
96
148
swap (*this , number);
97
149
return *this ;
98
- };
150
+ }
99
151
100
152
/* *
101
153
* @brief In-place addition of two numbers.
@@ -105,7 +157,7 @@ class Number final : Print<Number> {
105
157
Number& operator +=(const Number& number) {
106
158
*this = *this + number;
107
159
return *this ;
108
- };
160
+ }
109
161
110
162
/* *
111
163
* @brief Add two numbers.
@@ -122,7 +174,7 @@ class Number final : Print<Number> {
122
174
Number& operator -=(const Number& number) {
123
175
*this = *this - number;
124
176
return *this ;
125
- };
177
+ }
126
178
127
179
/* *
128
180
* @brief Subtract two Numbers.
@@ -145,7 +197,7 @@ class Number final : Print<Number> {
145
197
Number& operator *=(const Number& number) {
146
198
*this = *this * number;
147
199
return *this ;
148
- };
200
+ }
149
201
150
202
/* *
151
203
* @brief Multiply two Numbers.
@@ -162,7 +214,7 @@ class Number final : Print<Number> {
162
214
Number& operator /=(const Number& number) {
163
215
*this = *this / number;
164
216
return *this ;
165
- };
217
+ }
166
218
167
219
/* *
168
220
* @brief Divide two Numbers.
@@ -171,6 +223,23 @@ class Number final : Print<Number> {
171
223
*/
172
224
Number operator /(const Number& number) const ;
173
225
226
+ /* *
227
+ * @brief In-place modulo operator.
228
+ * @param mod the modulus.
229
+ * @return this.
230
+ */
231
+ Number& operator %=(const Number& mod) {
232
+ *this = *this % mod;
233
+ return *this ;
234
+ }
235
+
236
+ /* *
237
+ * @brief Modulo operation.
238
+ * @param mod the modulus.
239
+ * @return \p this modulo \p mod.
240
+ */
241
+ Number operator %(const Number& mod) const ;
242
+
174
243
/* *
175
244
* @brief In-place left shift.
176
245
* @param shift the amount to left shift
@@ -179,7 +248,7 @@ class Number final : Print<Number> {
179
248
Number& operator <<=(int shift) {
180
249
*this = *this << shift;
181
250
return *this ;
182
- };
251
+ }
183
252
184
253
/* *
185
254
* @brief Perform a left shift of a Number.
@@ -196,7 +265,7 @@ class Number final : Print<Number> {
196
265
Number& operator >>=(int shift) {
197
266
*this = *this >> shift;
198
267
return *this ;
199
- };
268
+ }
200
269
201
270
/* *
202
271
* @brief Perform a right shift of a Number.
@@ -213,7 +282,7 @@ class Number final : Print<Number> {
213
282
Number& operator ^=(const Number& number) {
214
283
*this = *this ^ number;
215
284
return *this ;
216
- };
285
+ }
217
286
218
287
/* *
219
288
* @brief Exclusive or of two numbers.
@@ -230,7 +299,7 @@ class Number final : Print<Number> {
230
299
Number& operator |=(const Number& number) {
231
300
*this = *this | number;
232
301
return *this ;
233
- };
302
+ }
234
303
235
304
/* *
236
305
* @brief operator |
@@ -247,7 +316,7 @@ class Number final : Print<Number> {
247
316
Number& operator &=(const Number& number) {
248
317
*this = *this & number;
249
318
return *this ;
250
- };
319
+ }
251
320
252
321
/* *
253
322
* @brief operator &
@@ -280,42 +349,47 @@ class Number final : Print<Number> {
280
349
*/
281
350
friend bool operator ==(const Number& lhs, const Number& rhs) {
282
351
return lhs.Compare (rhs) == 0 ;
283
- };
352
+ }
284
353
285
354
/* *
286
355
* @brief In-equality of two numbers.
287
356
*/
288
357
friend bool operator !=(const Number& lhs, const Number& rhs) {
289
358
return lhs.Compare (rhs) != 0 ;
290
- };
359
+ }
291
360
292
361
/* *
293
362
* @brief Strictly less-than of two numbers.
294
363
*/
295
364
friend bool operator <(const Number& lhs, const Number& rhs) {
296
365
return lhs.Compare (rhs) < 0 ;
297
- };
366
+ }
298
367
299
368
/* *
300
369
* @brief Less-than-or-equal of two numbers.
301
370
*/
302
371
friend bool operator <=(const Number& lhs, const Number& rhs) {
303
372
return lhs.Compare (rhs) <= 0 ;
304
- };
373
+ }
305
374
306
375
/* *
307
376
* @brief Strictly greater-than of two numbers.
308
377
*/
309
378
friend bool operator >(const Number& lhs, const Number& rhs) {
310
379
return lhs.Compare (rhs) > 0 ;
311
- };
380
+ }
312
381
313
382
/* *
314
383
* @brief Greater-than-or-equal of two numbers.
315
384
*/
316
385
friend bool operator >=(const Number& lhs, const Number& rhs) {
317
386
return lhs.Compare (rhs) >= 0 ;
318
- };
387
+ }
388
+
389
+ /* *
390
+ * @brief Get the size of this number in bytes.
391
+ */
392
+ std::size_t ByteSize () const ;
319
393
320
394
/* *
321
395
* @brief Get the size of this Number in bits.
@@ -340,15 +414,21 @@ class Number final : Print<Number> {
340
414
*/
341
415
bool Odd () const {
342
416
return TestBit (0 );
343
- };
417
+ }
344
418
345
419
/* *
346
420
* @brief Test if this Number is even.
347
421
* @return true if this Number is even.
348
422
*/
349
423
bool Even () const {
350
424
return !Odd ();
351
- };
425
+ }
426
+
427
+ /* *
428
+ * @brief Write this number to a buffer.
429
+ * @param buf the buffer.
430
+ */
431
+ void Write (unsigned char * buf) const ;
352
432
353
433
/* *
354
434
* @brief Return a string representation of this Number.
@@ -362,10 +442,17 @@ class Number final : Print<Number> {
362
442
friend void swap (Number& first, Number& second) {
363
443
using std::swap;
364
444
swap (first.m_value , second.m_value );
365
- };
445
+ }
366
446
367
447
private:
368
448
mpz_t m_value;
449
+
450
+ friend Number LCM (const Number& a, const Number& b);
451
+ friend Number GCD (const Number& a, const Number& b);
452
+ friend Number ModInverse (const Number& val, const Number& mod);
453
+ friend Number ModExp (const Number& base,
454
+ const Number& exp,
455
+ const Number& mod);
369
456
};
370
457
371
458
} // namespace scl::math
0 commit comments