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