Support for conversions between MPs and C integers.
[u/mdw/catacomb] / mp.h
CommitLineData
d03ab969 1/* -*-c-*-
2 *
5b00a0ea 3 * $Id: mp.h,v 1.5 1999/11/22 20:50:37 mdw Exp $
d03ab969 4 *
d3409d5e 5 * Simple multiprecision arithmetic
d03ab969 6 *
7 * (c) 1999 Straylight/Edgeware
8 */
9
10/*----- Licensing notice --------------------------------------------------*
11 *
12 * This file is part of Catacomb.
13 *
14 * Catacomb is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU Library General Public License as
16 * published by the Free Software Foundation; either version 2 of the
17 * License, or (at your option) any later version.
18 *
19 * Catacomb is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Library General Public License for more details.
23 *
24 * You should have received a copy of the GNU Library General Public
25 * License along with Catacomb; if not, write to the Free
26 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
27 * MA 02111-1307, USA.
28 */
29
30/*----- Revision history --------------------------------------------------*
31 *
32 * $Log: mp.h,v $
5b00a0ea 33 * Revision 1.5 1999/11/22 20:50:37 mdw
34 * Add support for computing Jacobi symbols.
35 *
24e1e862 36 * Revision 1.4 1999/11/21 22:13:02 mdw
37 * Add mp version of MPX_BITS.
38 *
a790733d 39 * Revision 1.3 1999/11/19 13:19:14 mdw
40 * Fix const annotation.
41 *
d3409d5e 42 * Revision 1.2 1999/11/17 18:02:16 mdw
43 * New multiprecision integer arithmetic suite.
d03ab969 44 *
45 */
46
47#ifndef MP_H
48#define MP_H
49
50#ifdef __cplusplus
51 extern "C" {
52#endif
53
54/*----- Header files ------------------------------------------------------*/
55
d3409d5e 56#include <assert.h>
d03ab969 57#include <string.h>
58
d3409d5e 59#include <mLib/sub.h>
60
61#ifndef MPW_H
62# include "mpw.h"
d03ab969 63#endif
64
65#ifndef MPX_H
66# include "mpx.h"
67#endif
68
d03ab969 69/*----- Data structures ---------------------------------------------------*/
70
71typedef struct mp {
d3409d5e 72 mpw *v, *vl;
73 size_t sz;
74 unsigned f;
75 unsigned ref;
d03ab969 76} mp;
77
d3409d5e 78#define MP_NEG 1u
79#define MP_BURN 2u
80#define MP_CONST 4u
81#define MP_UNDEF 8u
d03ab969 82
d3409d5e 83/*----- Useful constants --------------------------------------------------*/
d03ab969 84
d3409d5e 85extern mp mp_const[];
d03ab969 86
d3409d5e 87#define MP_ZERO (&mp_const[0])
88#define MP_ONE (&mp_const[1])
89#define MP_TWO (&mp_const[2])
90#define MP_THREE (&mp_const[3])
91#define MP_FOUR (&mp_const[4])
92#define MP_FIVE (&mp_const[5])
93#define MP_TEN (&mp_const[6])
94#define MP_MONE (&mp_const[7])
d03ab969 95
d3409d5e 96#define MP_NEW ((mp *)0)
d03ab969 97
d3409d5e 98/*----- Memory allocation hooks -------------------------------------------*/
d03ab969 99
d3409d5e 100#ifndef MPARENA_H
101# include "mparena.h"
102#endif
103
104/* --- @MP_ARENA@ --- *
d03ab969 105 *
d3409d5e 106 * This selects where memory is allocated from. Tweak to use more fancy
107 * things like custom arenas.
108 */
109
110#ifndef MP_ARENA
111# define MP_ARENA MPARENA_GLOBAL
112#endif
113
114/* --- @MP_ALLOC@ --- *
d03ab969 115 *
d3409d5e 116 * Arguments: @size_t sz@ = size required
117 *
118 * Returns: Pointer to an allocated vector of the requested size.
d03ab969 119 *
d3409d5e 120 * Use: Hook for vector allocation.
d03ab969 121 */
122
d3409d5e 123#ifndef MP_ALLOC
124# define MP_ALLOC(sz) mpalloc(MP_ARENA, (sz))
125#endif
d03ab969 126
d3409d5e 127/* --- @MP_FREE@ --- *
128 *
129 * Arguments: @mpw *v@ = pointer to vector
d03ab969 130 *
d3409d5e 131 * Returns: ---
d03ab969 132 *
d3409d5e 133 * Use: Hook for vector deallocation.
d03ab969 134 */
135
d3409d5e 136#ifndef MP_FREE
137# define MP_FREE(v) mpfree(MP_ARENA, (v))
138#endif
d03ab969 139
d3409d5e 140/*----- Paranoia management -----------------------------------------------*/
141
142/* --- @mp_burn@ --- *
d03ab969 143 *
d3409d5e 144 * Arguments: @mp *m@ = pointer to a multiprecision integer
d03ab969 145 *
146 * Returns: ---
147 *
d3409d5e 148 * Use: Marks the integer as `burn-after-use'. When the integer's
149 * memory is deallocated, it is deleted so that traces can't
150 * remain in the swap file. In theory.
d03ab969 151 */
152
d3409d5e 153extern void mp_burn(mp */*m*/);
d03ab969 154
d3409d5e 155/*----- Trivial macros ----------------------------------------------------*/
156
157/* --- @MP_LEN@ --- *
d03ab969 158 *
d3409d5e 159 * Arguments: @mp *m@ = pointer to a multiprecision integer
d03ab969 160 *
d3409d5e 161 * Returns: Length of the integer, in words.
d03ab969 162 */
163
d3409d5e 164#define MP_LEN(m) ((m)->vl - ((m)->v))
d03ab969 165
d3409d5e 166/*----- Memory management and reference counting --------------------------*/
167
168/* --- @mp_create@ --- *
d03ab969 169 *
d3409d5e 170 * Arguments: @size_t sz@ = size of vector required
d03ab969 171 *
d3409d5e 172 * Returns: Pointer to pristine new MP structure with enough memory
173 * bolted onto it.
d03ab969 174 *
d3409d5e 175 * Use: Creates a new multiprecision integer with indeterminate
176 * contents. The integer has a single reference.
d03ab969 177 */
178
d3409d5e 179extern mp *mp_create(size_t /*sz*/);
d03ab969 180
d3409d5e 181/* --- @mp_build@ --- *
d03ab969 182 *
d3409d5e 183 * Arguments: @mp *m@ = pointer to an MP block to fill in
184 * @mpw *v@ = pointer to a word array
185 * @mpw *vl@ = pointer just past end of array
d03ab969 186 *
187 * Returns: ---
188 *
d3409d5e 189 * Use: Creates a multiprecision integer representing some smallish
190 * number. You must provide storage for the number and dispose
191 * of it when you've finished with it. The number is marked as
192 * constant while it exists.
d03ab969 193 */
194
d3409d5e 195extern void mp_build(mp */*m*/, mpw */*v*/, mpw */*vl*/);
d03ab969 196
d3409d5e 197/* --- @mp_destroy@ --- *
d03ab969 198 *
d3409d5e 199 * Arguments: @mp *m@ = pointer to a multiprecision integer
d03ab969 200 *
201 * Returns: ---
202 *
d3409d5e 203 * Use: Destroys a multiprecision integer. The reference count isn't
204 * checked. Don't use this function if you don't know what
205 * you're doing: use @mp_drop@ instead.
d03ab969 206 */
207
d3409d5e 208extern void mp_destroy(mp */*m*/);
d03ab969 209
d3409d5e 210/* --- @mp_copy@ --- *
d03ab969 211 *
d3409d5e 212 * Arguments: @mp *m@ = pointer to a multiprecision integer
d03ab969 213 *
d3409d5e 214 * Returns: A copy of the given multiprecision integer.
215 *
216 * Use: Copies the given integer. In fact you just get another
217 * reference to the same old one again.
d03ab969 218 */
219
d3409d5e 220extern mp *mp_copy(mp */*m*/);
d03ab969 221
d3409d5e 222#define MP_COPY(m) ((m)->ref++, (m))
223
224/* --- @mp_drop@ --- *
d03ab969 225 *
d3409d5e 226 * Arguments: @mp *m@ = pointer to a multiprecision integer
d03ab969 227 *
228 * Returns: ---
229 *
d3409d5e 230 * Use: Drops a reference to an integer which isn't wanted any more.
231 * If there are no more references, the integer is destroyed.
d03ab969 232 */
233
d3409d5e 234extern void mp_drop(mp */*m*/);
d03ab969 235
d3409d5e 236#define MP_DROP(m) do { \
237 mp *_mm = (m); \
238 if (_mm->ref > 1) \
239 _mm->ref--; \
240 else if (!(_mm->f & MP_CONST)) \
241 mp_destroy(_mm); \
242} while (0)
243
244/* --- @mp_split@ --- *
d03ab969 245 *
d3409d5e 246 * Arguments: @mp *m@ = pointer to a multiprecision integer
d03ab969 247 *
d3409d5e 248 * Returns: A reference to the same integer, possibly with a different
249 * address.
d03ab969 250 *
d3409d5e 251 * Use: Splits off a modifiable version of the integer referred to.
d03ab969 252 */
253
d3409d5e 254extern mp *mp_split(mp */*m*/);
255
256#define MP_SPLIT(m) do { \
257 mp *_mm = (m); \
258 if ((_mm->f & MP_CONST) || _mm->ref != 1) { \
259 mp *_dd = mp_create(_mm->sz); \
260 _dd->vl = _dd->v + MP_LEN(_mm); \
261 _dd->f = _mm->f & (MP_NEG | MP_BURN); \
262 memcpy(_dd->v, _mm->v, MPWS(MP_LEN(_mm))); \
263 _dd->ref = 1; \
264 _mm->ref--; \
265 (m) = _dd; \
266 } \
267} while (0)
d03ab969 268
d3409d5e 269/* --- @mp_resize@ --- *
d03ab969 270 *
d3409d5e 271 * Arguments: @mp *m@ = pointer to a multiprecision integer
272 * @size_t sz@ = new size
d03ab969 273 *
d3409d5e 274 * Returns: ---
d03ab969 275 *
d3409d5e 276 * Use: Resizes the vector containing the integer's digits. The new
277 * size must be at least as large as the current integer's
278 * length. The integer's length is increased and new digits are
279 * filled with zeroes. This isn't really intended for client
280 * use.
d03ab969 281 */
282
d3409d5e 283extern void mp_resize(mp */*m*/, size_t /*sz*/);
284
285#define MP_RESIZE(m, ssz) do { \
286 mp *_m = (m); \
287 size_t _sz = (ssz); \
288 size_t _len = MP_LEN(_m); \
289 mpw *_v = MP_ALLOC(_sz); \
290 memcpy(_v, _m->v, MPWS(_len)); \
291 if (_m->f & MP_BURN) \
292 memset(_m->v, 0, MPWS(_m->sz)); \
293 MP_FREE(_m->v); \
294 _m->v = _v; \
295 _m->vl = _v + _len; \
296 _m->sz = _sz; \
297} while (0)
d03ab969 298
d3409d5e 299/* --- @mp_ensure@ --- *
d03ab969 300 *
d3409d5e 301 * Arguments: @mp *m@ = pointer to a multiprecision integer
302 * @size_t sz@ = required size
d03ab969 303 *
304 * Returns: ---
305 *
d3409d5e 306 * Use: Ensures that the integer has enough space for @sz@ digits.
307 * The value is not changed.
d03ab969 308 */
309
d3409d5e 310extern void mp_ensure(mp */*m*/, size_t /*sz*/);
311
312#define MP_ENSURE(m, ssz) do { \
313 mp *_mm = (m); \
314 size_t _ssz = (ssz); \
315 size_t _len = MP_LEN(_mm); \
316 if (_ssz > _mm->sz) \
317 MP_RESIZE(_mm, _ssz); \
318 if (!(_mm->f & MP_UNDEF) && _ssz > _len) { \
319 memset(_mm->vl, 0, MPWS(_ssz - _len)); \
320 _mm->vl = _mm->v + _ssz; \
321 } \
322} while (0)
d03ab969 323
d3409d5e 324/* --- @mp_modify@ --- *
d03ab969 325 *
d3409d5e 326 * Arguments: @mp *m@ = pointer to a multiprecision integer
327 * @size_t sz@ = size required
d03ab969 328 *
d3409d5e 329 * Returns: Pointer to the integer (possibly different).
d03ab969 330 *
d3409d5e 331 * Use: Prepares an integer to be overwritten. It's split off from
332 * other references to the same integer, and sufficient space is
333 * allocated.
d03ab969 334 */
335
d3409d5e 336extern mp *mp_modify(mp */*m*/, size_t /*sz*/);
d03ab969 337
d3409d5e 338#define MP_MODIFY(m, sz) do { \
339 size_t _rq = (sz); \
340 mp *_m = (m); \
341 if (_m == MP_NEW) \
342 _m = mp_create(_rq); \
343 else { \
344 MP_SPLIT(_m); \
345 MP_ENSURE(_m, _rq); \
346 } \
347 _m->vl = _m->v + _rq; \
348 (m) = _m; \
349} while (0)
350
351/*----- Size manipulation -------------------------------------------------*/
352
353/* --- @mp_shrink@ --- *
d03ab969 354 *
d3409d5e 355 * Arguments: @mp *m@ = pointer to a multiprecision integer
d03ab969 356 *
357 * Returns: ---
358 *
d3409d5e 359 * Use: Reduces the recorded length of an integer. This doesn't
360 * reduce the amount of memory used, although it can improve
361 * performance a bit. To reduce memory, use @mp_minimize@
362 * instead. This can't change the value of an integer, and is
363 * therefore safe to use even when there are multiple
364 * references.
d03ab969 365 */
366
d3409d5e 367extern void mp_shrink(mp */*m*/);
d03ab969 368
d3409d5e 369#define MP_SHRINK(m) do { \
370 mp *_mm = (m); \
371 MPX_SHRINK(_mm->v, _mm->vl); \
372 if (!MP_LEN(_mm)) \
373 _mm->f &= ~MP_NEG; \
374} while (0)
375
376/* --- @mp_minimize@ --- *
d03ab969 377 *
d3409d5e 378 * Arguments: @mp *m@ = pointer to a multiprecision integer
d03ab969 379 *
380 * Returns: ---
381 *
d3409d5e 382 * Use: Reduces the amount of memory an integer uses. It's best to
383 * do this to numbers which aren't going to change in the
384 * future.
d03ab969 385 */
386
d3409d5e 387extern void mp_minimize(mp */*m*/);
d03ab969 388
d3409d5e 389/*----- Bit scanning ------------------------------------------------------*/
d03ab969 390
d3409d5e 391#ifndef MPSCAN_H
392# include "mpscan.h"
393#endif
394
395/* --- @mp_scan@ --- *
d03ab969 396 *
d3409d5e 397 * Arguments: @mpscan *sc@ = pointer to bitscanner block
398 * @const mp *m@ = pointer to a multiprecision integer
d03ab969 399 *
400 * Returns: ---
401 *
d3409d5e 402 * Use: Initializes a bitscanner on a multiprecision integer.
d03ab969 403 */
404
d3409d5e 405extern void mp_scan(mpscan */*sc*/, const mp */*m*/);
406
407#define MP_SCAN(sc, m) do { \
a790733d 408 const mp *_mm = (m); \
d3409d5e 409 mpscan *_sc = (sc); \
410 MPSCAN_INITX(_sc, _mm->v, _mm->vl); \
411} while (0)
412
413/* --- Other bitscanning aliases --- */
414
415#define mp_step mpscan_step
416#define mp_bit mpscan_bit
417
418#define MP_STEP MPSCAN_STEP
419#define MP_BIT MPSCAN_BIT
420
421/*----- Loading and storing -----------------------------------------------*/
d03ab969 422
d3409d5e 423/* --- @mp_octets@ --- *
d03ab969 424 *
d3409d5e 425 * Arguments: @const mp *m@ = a multiprecision integer
d03ab969 426 *
d3409d5e 427 * Returns: The number of octets required to represent @m@.
d03ab969 428 *
d3409d5e 429 * Use: Calculates the external storage required for a multiprecision
430 * integer.
d03ab969 431 */
432
24e1e862 433extern size_t mp_octets(const mp */*m*/);
434
435/* --- @mp_bits@ --- *
436 *
437 * Arguments: @const mp *m@ = a multiprecision integer
438 *
439 * Returns: The number of bits required to represent @m@.
440 *
441 * Use: Calculates the external storage required for a multiprecision
442 * integer.
443 */
444
445extern unsigned long mp_bits(const mp */*m*/);
d03ab969 446
d3409d5e 447/* --- @mp_loadl@ --- *
d03ab969 448 *
d3409d5e 449 * Arguments: @mp *d@ = destination
450 * @const void *pv@ = pointer to source data
451 * @size_t sz@ = size of the source data
d03ab969 452 *
d3409d5e 453 * Returns: Resulting multiprecision number.
d03ab969 454 *
d3409d5e 455 * Use: Loads a multiprecision number from an array of octets. The
456 * first byte in the array is the least significant. More
457 * formally, if the bytes are %$b_0, b_1, \ldots, b_{n-1}$%
458 * then the result is %$N = \sum_{0 \le i < n} b_i 2^{8i}$%.
d03ab969 459 */
460
d3409d5e 461extern mp *mp_loadl(mp */*d*/, const void */*pv*/, size_t /*sz*/);
d03ab969 462
d3409d5e 463/* --- @mp_storel@ --- *
464 *
465 * Arguments: @const mp *m@ = source
466 * @void *pv@ = pointer to output array
467 * @size_t sz@ = size of the output array
468 *
469 * Returns: ---
470 *
471 * Use: Stores a multiprecision number in an array of octets. The
472 * first byte in the array is the least significant. If the
473 * array is too small to represent the number, high-order bits
474 * are truncated; if the array is too large, high order bytes
475 * are filled with zeros. More formally, if the number is
476 * %$N = \sum{0 \le i} b_i 2^{8i}$% where %$0 \le b_i < 256$%,
477 * then the array is %$b_0, b_1, \ldots, b_{n-1}$%.
478 */
d03ab969 479
d3409d5e 480extern void mp_storel(const mp */*m*/, void */*pv*/, size_t /*sz*/);
d03ab969 481
d3409d5e 482/* --- @mp_loadb@ --- *
d03ab969 483 *
d3409d5e 484 * Arguments: @mp *d@ = destination
485 * @const void *pv@ = pointer to source data
486 * @size_t sz@ = size of the source data
d03ab969 487 *
d3409d5e 488 * Returns: Resulting multiprecision number.
d03ab969 489 *
d3409d5e 490 * Use: Loads a multiprecision number from an array of octets. The
491 * last byte in the array is the least significant. More
492 * formally, if the bytes are %$b_{n-1}, b_{n-2}, \ldots, b_0$%
493 * then the result is %$N = \sum_{0 \le i < n} b_i 2^{8i}$%.
d03ab969 494 */
495
d3409d5e 496extern mp *mp_loadb(mp */*d*/, const void */*pv*/, size_t /*sz*/);
d03ab969 497
d3409d5e 498/* --- @mp_storeb@ --- *
d03ab969 499 *
d3409d5e 500 * Arguments: @const mp *m@ = source
501 * @void *pv@ = pointer to output array
502 * @size_t sz@ = size of the output array
d03ab969 503 *
504 * Returns: ---
505 *
d3409d5e 506 * Use: Stores a multiprecision number in an array of octets. The
507 * last byte in the array is the least significant. If the
508 * array is too small to represent the number, high-order bits
509 * are truncated; if the array is too large, high order bytes
510 * are filled with zeros. More formally, if the number is
511 * %$N = \sum{0 \le i} b_i 2^{8i}$% where %$0 \le b_i < 256$%,
512 * then the array is %$b_{n-1}, b_{n-2}, \ldots, b_0$%.
d03ab969 513 */
514
d3409d5e 515extern void mp_storeb(const mp */*m*/, void */*pv*/, size_t /*sz*/);
d03ab969 516
d3409d5e 517/*----- Simple arithmetic -------------------------------------------------*/
d03ab969 518
d3409d5e 519/* --- @mp_2c@ --- *
d03ab969 520 *
d3409d5e 521 * Arguments: @mp *d@ = destination
522 * @mp *a@ = source
d03ab969 523 *
d3409d5e 524 * Returns: Result, @a@ converted to two's complement notation.
525 */
526
527extern mp *mp_2c(mp */*d*/, mp */*a*/);
528
529/* --- @mp_sm@ --- *
530 *
531 * Arguments: @mp *d@ = destination
532 * @mp *a@ = source
d03ab969 533 *
d3409d5e 534 * Returns: Result, @a@ converted to the native signed-magnitude
535 * notation.
d03ab969 536 */
537
d3409d5e 538extern mp *mp_sm(mp */*d*/, mp */*a*/);
d03ab969 539
d3409d5e 540/* --- @mp_lsl@ --- *
d03ab969 541 *
d3409d5e 542 * Arguments: @mp *d@ = destination
543 * @const mp *a@ = source
544 * @size_t n@ = number of bits to move
d03ab969 545 *
d3409d5e 546 * Returns: Result, @a@ shifted left by @n@.
547 */
548
549extern mp *mp_lsl(mp */*d*/, const mp */*a*/, size_t /*n*/);
550
551/* --- @mp_lsr@ --- *
552 *
553 * Arguments: @mp *d@ = destination
554 * @const mp *a@ = source
555 * @size_t n@ = number of bits to move
d03ab969 556 *
d3409d5e 557 * Returns: Result, @a@ shifted left by @n@.
d03ab969 558 */
559
d3409d5e 560extern mp *mp_lsr(mp */*d*/, const mp */*a*/, size_t /*n*/);
d03ab969 561
d3409d5e 562/* --- @mp_cmp@ --- *
d03ab969 563 *
d3409d5e 564 * Arguments: @const mp *a, *b@ = two numbers
d03ab969 565 *
d3409d5e 566 * Returns: Less than, equal to or greater than zero, according to
567 * whether @a@ is less than, equal to or greater than @b@.
568 */
569
570extern int mp_cmp(const mp */*a*/, const mp */*b*/);
571
572#define MP_CMP(a, op, b) (mp_cmp((a), (b)) op 0)
573
574/* --- @mp_add@ --- *
d03ab969 575 *
d3409d5e 576 * Arguments: @mp *d@ = destination
577 * @const mp *a, *b@ = sources
578 *
579 * Returns: Result, @a@ added to @b@.
d03ab969 580 */
581
d3409d5e 582extern mp *mp_add(mp */*d*/, const mp */*a*/, const mp */*b*/);
d03ab969 583
d3409d5e 584/* --- @mp_sub@ --- *
585 *
586 * Arguments: @mp *d@ = destination
587 * @const mp *a, *b@ = sources
588 *
589 * Returns: Result, @b@ subtracted from @a@.
590 */
d03ab969 591
d3409d5e 592extern mp *mp_sub(mp */*d*/, const mp */*a*/, const mp */*b*/);
593
594/* --- @mp_mul@ --- *
d03ab969 595 *
d3409d5e 596 * Arguments: @mp *d@ = destination
597 * @const mp *a, *b@ = sources
d03ab969 598 *
d3409d5e 599 * Returns: Result, @a@ multiplied by @b@.
600 */
601
602extern mp *mp_mul(mp */*d*/, const mp */*a*/, const mp */*b*/);
603
604/* --- @mp_sqr@ --- *
605 *
606 * Arguments: @mp *d@ = destination
607 * @const mp *a@ = source
608 *
609 * Returns: Result, @a@ squared.
610 */
611
612extern mp *mp_sqr(mp */*d*/, const mp */*a*/);
613
614/* --- @mp_div@ --- *
d03ab969 615 *
d3409d5e 616 * Arguments: @mp **qq, **rr@ = destination, quotient and remainder
617 * @const mp *a, *b@ = sources
618 *
619 * Use: Calculates the quotient and remainder when @a@ is divided by
620 * @b@.
d03ab969 621 */
622
d3409d5e 623extern void mp_div(mp **/*qq*/, mp **/*rr*/,
624 const mp */*a*/, const mp */*b*/);
625
626/*----- More advanced algorithms ------------------------------------------*/
d03ab969 627
d3409d5e 628/* --- @mp_gcd@ --- *
d03ab969 629 *
d3409d5e 630 * Arguments: @mp **gcd, **xx, **yy@ = where to write the results
631 * @mp *a, *b@ = sources (must be nonzero)
d03ab969 632 *
633 * Returns: ---
634 *
d3409d5e 635 * Use: Calculates @gcd(a, b)@, and two numbers @x@ and @y@ such that
636 * @ax + by = gcd(a, b)@. This is useful for computing modular
637 * inverses. Neither @a@ nor @b@ may be zero. Note that,
638 * unlike @mp_div@ for example, it is not possible to specify
639 * explicit destinations -- new MPs are always allocated.
d03ab969 640 */
641
d3409d5e 642extern void mp_gcd(mp **/*gcd*/, mp **/*xx*/, mp **/*yy*/,
643 mp */*a*/, mp */*b*/);
644
5b00a0ea 645/* --- @mp_jacobi@ --- *
646 *
647 * Arguments: @mp *a@ = an integer less than @n@
648 * @mp *n@ = an odd integer
649 *
650 * Returns: @-1@, @0@ or @1@ -- the Jacobi symbol %$J(a, n)$%.
651 *
652 * Use: Computes the Jacobi symbol. If @n@ is prime, this is the
653 * Legendre symbol and is equal to 1 if and only if @a@ is a
654 * quadratic residue mod @n@. The result is zero if and only if
655 * @a@ and @n@ have a common factor greater than one.
656 */
657
658int mp_jacobi(mp */*a*/, mp */*n*/);
659
d3409d5e 660/*----- Test harness support ----------------------------------------------*/
661
662#include <mLib/testrig.h>
663
664#ifndef MPTEXT_H
665# include "mptext.h"
666#endif
667
668extern const test_type type_mp;
d03ab969 669
670/*----- That's all, folks -------------------------------------------------*/
671
672#ifdef __cplusplus
673 }
674#endif
675
676#endif