2828
2929namespace scl ::math {
3030
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+
3168/* *
3269 * @brief Arbitrary precision integer.
3370 */
3471class Number final : Print<Number> {
3572 public:
3673 /* *
3774 * @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.
4178 */
4279 static Number Random (std::size_t bits, util::PRG& prg);
4380
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+
4489 /* *
4590 * @brief Read a Number from a string
4691 * @param str the string
4792 * @return a Number.
4893 */
4994 static Number FromString (const std::string& str);
5095
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+
51103 /* *
52104 * @brief Construct a Number from an int.
53105 * @param value the int
@@ -85,7 +137,7 @@ class Number final : Print<Number> {
85137 Number copy (number);
86138 swap (*this , copy);
87139 return *this ;
88- };
140+ }
89141
90142 /* *
91143 * @brief Move assignment from a Number.
@@ -95,7 +147,7 @@ class Number final : Print<Number> {
95147 Number& operator =(Number&& number) noexcept {
96148 swap (*this , number);
97149 return *this ;
98- };
150+ }
99151
100152 /* *
101153 * @brief In-place addition of two numbers.
@@ -105,7 +157,7 @@ class Number final : Print<Number> {
105157 Number& operator +=(const Number& number) {
106158 *this = *this + number;
107159 return *this ;
108- };
160+ }
109161
110162 /* *
111163 * @brief Add two numbers.
@@ -122,7 +174,7 @@ class Number final : Print<Number> {
122174 Number& operator -=(const Number& number) {
123175 *this = *this - number;
124176 return *this ;
125- };
177+ }
126178
127179 /* *
128180 * @brief Subtract two Numbers.
@@ -145,7 +197,7 @@ class Number final : Print<Number> {
145197 Number& operator *=(const Number& number) {
146198 *this = *this * number;
147199 return *this ;
148- };
200+ }
149201
150202 /* *
151203 * @brief Multiply two Numbers.
@@ -162,7 +214,7 @@ class Number final : Print<Number> {
162214 Number& operator /=(const Number& number) {
163215 *this = *this / number;
164216 return *this ;
165- };
217+ }
166218
167219 /* *
168220 * @brief Divide two Numbers.
@@ -171,6 +223,23 @@ class Number final : Print<Number> {
171223 */
172224 Number operator /(const Number& number) const ;
173225
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+
174243 /* *
175244 * @brief In-place left shift.
176245 * @param shift the amount to left shift
@@ -179,7 +248,7 @@ class Number final : Print<Number> {
179248 Number& operator <<=(int shift) {
180249 *this = *this << shift;
181250 return *this ;
182- };
251+ }
183252
184253 /* *
185254 * @brief Perform a left shift of a Number.
@@ -196,7 +265,7 @@ class Number final : Print<Number> {
196265 Number& operator >>=(int shift) {
197266 *this = *this >> shift;
198267 return *this ;
199- };
268+ }
200269
201270 /* *
202271 * @brief Perform a right shift of a Number.
@@ -213,7 +282,7 @@ class Number final : Print<Number> {
213282 Number& operator ^=(const Number& number) {
214283 *this = *this ^ number;
215284 return *this ;
216- };
285+ }
217286
218287 /* *
219288 * @brief Exclusive or of two numbers.
@@ -230,7 +299,7 @@ class Number final : Print<Number> {
230299 Number& operator |=(const Number& number) {
231300 *this = *this | number;
232301 return *this ;
233- };
302+ }
234303
235304 /* *
236305 * @brief operator |
@@ -247,7 +316,7 @@ class Number final : Print<Number> {
247316 Number& operator &=(const Number& number) {
248317 *this = *this & number;
249318 return *this ;
250- };
319+ }
251320
252321 /* *
253322 * @brief operator &
@@ -280,42 +349,47 @@ class Number final : Print<Number> {
280349 */
281350 friend bool operator ==(const Number& lhs, const Number& rhs) {
282351 return lhs.Compare (rhs) == 0 ;
283- };
352+ }
284353
285354 /* *
286355 * @brief In-equality of two numbers.
287356 */
288357 friend bool operator !=(const Number& lhs, const Number& rhs) {
289358 return lhs.Compare (rhs) != 0 ;
290- };
359+ }
291360
292361 /* *
293362 * @brief Strictly less-than of two numbers.
294363 */
295364 friend bool operator <(const Number& lhs, const Number& rhs) {
296365 return lhs.Compare (rhs) < 0 ;
297- };
366+ }
298367
299368 /* *
300369 * @brief Less-than-or-equal of two numbers.
301370 */
302371 friend bool operator <=(const Number& lhs, const Number& rhs) {
303372 return lhs.Compare (rhs) <= 0 ;
304- };
373+ }
305374
306375 /* *
307376 * @brief Strictly greater-than of two numbers.
308377 */
309378 friend bool operator >(const Number& lhs, const Number& rhs) {
310379 return lhs.Compare (rhs) > 0 ;
311- };
380+ }
312381
313382 /* *
314383 * @brief Greater-than-or-equal of two numbers.
315384 */
316385 friend bool operator >=(const Number& lhs, const Number& rhs) {
317386 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 ;
319393
320394 /* *
321395 * @brief Get the size of this Number in bits.
@@ -340,15 +414,21 @@ class Number final : Print<Number> {
340414 */
341415 bool Odd () const {
342416 return TestBit (0 );
343- };
417+ }
344418
345419 /* *
346420 * @brief Test if this Number is even.
347421 * @return true if this Number is even.
348422 */
349423 bool Even () const {
350424 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 ;
352432
353433 /* *
354434 * @brief Return a string representation of this Number.
@@ -362,10 +442,17 @@ class Number final : Print<Number> {
362442 friend void swap (Number& first, Number& second) {
363443 using std::swap;
364444 swap (first.m_value , second.m_value );
365- };
445+ }
366446
367447 private:
368448 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);
369456};
370457
371458} // namespace scl::math
0 commit comments