Add an internal-representation no-op function.
[u/mdw/catacomb] / mp.h
CommitLineData
d03ab969 1/* -*-c-*-
2 *
0f32e0f8 3 * $Id: mp.h,v 1.11 2001/04/03 19:36:05 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 $
0f32e0f8 33 * Revision 1.11 2001/04/03 19:36:05 mdw
34 * Add some simple bitwise operations so that Perl can use them.
35 *
740c9553 36 * Revision 1.10 2000/10/08 12:03:16 mdw
37 * Provide @mp_eq@ and @MP_EQ@ for rapidly testing equality of two
38 * integers.
39 *
5fbe3846 40 * Revision 1.9 2000/07/29 17:03:31 mdw
41 * Add support for left-to-right bitscanning, for use in modular
42 * exponentiation.
43 *
22a073c0 44 * Revision 1.8 2000/06/22 19:02:01 mdw
45 * Add new functions.
46 *
d34decd2 47 * Revision 1.7 2000/06/17 11:45:09 mdw
48 * Major memory management overhaul. Added arena support. Use the secure
49 * arena for secret integers. Replace and improve the MP management macros
50 * (e.g., replace MP_MODIFY by MP_DEST).
51 *
d9a8ae10 52 * Revision 1.6 1999/12/10 23:19:46 mdw
53 * Minor bugfixes. New interface for suggested destinations.
54 *
5b00a0ea 55 * Revision 1.5 1999/11/22 20:50:37 mdw
56 * Add support for computing Jacobi symbols.
57 *
24e1e862 58 * Revision 1.4 1999/11/21 22:13:02 mdw
59 * Add mp version of MPX_BITS.
60 *
a790733d 61 * Revision 1.3 1999/11/19 13:19:14 mdw
62 * Fix const annotation.
63 *
d3409d5e 64 * Revision 1.2 1999/11/17 18:02:16 mdw
65 * New multiprecision integer arithmetic suite.
d03ab969 66 *
67 */
68
d9a8ae10 69#ifndef CATACOMB_MP_H
70#define CATACOMB_MP_H
d03ab969 71
72#ifdef __cplusplus
73 extern "C" {
74#endif
75
76/*----- Header files ------------------------------------------------------*/
77
d3409d5e 78#include <assert.h>
d03ab969 79#include <string.h>
80
d3409d5e 81#include <mLib/sub.h>
82
d9a8ae10 83#ifndef CATACOMB_MPW_H
d3409d5e 84# include "mpw.h"
d03ab969 85#endif
86
d34decd2 87#ifndef CATACOMB_ARENA_H
88# include "arena.h"
89#endif
90
91#ifndef CATACOMB_MPARENA_H
92# include "mparena.h"
93#endif
94
d9a8ae10 95#ifndef CATACOMB_MPX_H
d03ab969 96# include "mpx.h"
97#endif
98
d03ab969 99/*----- Data structures ---------------------------------------------------*/
100
101typedef struct mp {
d3409d5e 102 mpw *v, *vl;
103 size_t sz;
d34decd2 104 mparena *a;
d3409d5e 105 unsigned f;
106 unsigned ref;
d03ab969 107} mp;
108
d3409d5e 109#define MP_NEG 1u
110#define MP_BURN 2u
111#define MP_CONST 4u
112#define MP_UNDEF 8u
d9a8ae10 113#define MP_DESTROYED 16u
d03ab969 114
d3409d5e 115/*----- Useful constants --------------------------------------------------*/
d03ab969 116
d3409d5e 117extern mp mp_const[];
d03ab969 118
d3409d5e 119#define MP_ZERO (&mp_const[0])
120#define MP_ONE (&mp_const[1])
121#define MP_TWO (&mp_const[2])
122#define MP_THREE (&mp_const[3])
123#define MP_FOUR (&mp_const[4])
124#define MP_FIVE (&mp_const[5])
125#define MP_TEN (&mp_const[6])
d34decd2 126#define MP_256 (&mp_const[7])
127#define MP_MONE (&mp_const[8])
d03ab969 128
d3409d5e 129#define MP_NEW ((mp *)0)
d34decd2 130#define MP_NEWSEC (&mp_const[9])
d03ab969 131
d34decd2 132/*----- Trivial macros ----------------------------------------------------*/
d03ab969 133
d34decd2 134/* --- @MP_LEN@ --- *
d03ab969 135 *
d34decd2 136 * Arguments: @mp *m@ = pointer to a multiprecision integer
d03ab969 137 *
d34decd2 138 * Returns: Length of the integer, in words.
d03ab969 139 */
140
d34decd2 141#define MP_LEN(m) ((m)->vl - ((m)->v))
d03ab969 142
d34decd2 143/*----- Memory management and reference counting --------------------------*/
d3409d5e 144
d34decd2 145/* --- @mp_new@ --- *
d03ab969 146 *
d34decd2 147 * Arguments: @size_t sz@ = size of vector required
148 * @unsigned f@ = flags to set
d03ab969 149 *
d34decd2 150 * Returns: Pointer to a new MP structure.
d03ab969 151 *
d34decd2 152 * Use: Allocates a new multiprecision integer. The data space is
153 * allocated from either the standard global or secret arena,
154 * depending on the initial flags requested.
d03ab969 155 */
156
d34decd2 157extern mp *mp_new(size_t /*sz*/, unsigned /*f*/);
d03ab969 158
d34decd2 159/* --- @mp_create@ --- *
d03ab969 160 *
d34decd2 161 * Arguments: @size_t sz@ = size of vector required
d03ab969 162 *
d34decd2 163 * Returns: Pointer to pristine new MP structure with enough memory
164 * bolted onto it.
165 *
166 * Use: Creates a new multiprecision integer with indeterminate
167 * contents. The integer has a single reference.
d03ab969 168 */
169
d34decd2 170extern mp *mp_create(size_t /*sz*/);
d3409d5e 171
d34decd2 172/* --- @mp_createsecure@ --- *
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
d34decd2 180 * contents. The integer has a single reference. The integer's
181 * data space is allocated from the secure arena. Its burn flag
182 * is set.
d03ab969 183 */
184
d34decd2 185extern mp *mp_createsecure(size_t /*sz*/);
d03ab969 186
d3409d5e 187/* --- @mp_build@ --- *
d03ab969 188 *
d3409d5e 189 * Arguments: @mp *m@ = pointer to an MP block to fill in
190 * @mpw *v@ = pointer to a word array
191 * @mpw *vl@ = pointer just past end of array
d03ab969 192 *
193 * Returns: ---
194 *
d3409d5e 195 * Use: Creates a multiprecision integer representing some smallish
196 * number. You must provide storage for the number and dispose
197 * of it when you've finished with it. The number is marked as
198 * constant while it exists.
d03ab969 199 */
200
d3409d5e 201extern void mp_build(mp */*m*/, mpw */*v*/, mpw */*vl*/);
d03ab969 202
d3409d5e 203/* --- @mp_destroy@ --- *
d03ab969 204 *
d3409d5e 205 * Arguments: @mp *m@ = pointer to a multiprecision integer
d03ab969 206 *
207 * Returns: ---
208 *
d3409d5e 209 * Use: Destroys a multiprecision integer. The reference count isn't
210 * checked. Don't use this function if you don't know what
211 * you're doing: use @mp_drop@ instead.
d03ab969 212 */
213
d3409d5e 214extern void mp_destroy(mp */*m*/);
d03ab969 215
d3409d5e 216/* --- @mp_copy@ --- *
d03ab969 217 *
d3409d5e 218 * Arguments: @mp *m@ = pointer to a multiprecision integer
d03ab969 219 *
d3409d5e 220 * Returns: A copy of the given multiprecision integer.
221 *
222 * Use: Copies the given integer. In fact you just get another
223 * reference to the same old one again.
d03ab969 224 */
225
d3409d5e 226extern mp *mp_copy(mp */*m*/);
d03ab969 227
d3409d5e 228#define MP_COPY(m) ((m)->ref++, (m))
229
230/* --- @mp_drop@ --- *
d03ab969 231 *
d3409d5e 232 * Arguments: @mp *m@ = pointer to a multiprecision integer
d03ab969 233 *
234 * Returns: ---
235 *
d3409d5e 236 * Use: Drops a reference to an integer which isn't wanted any more.
237 * If there are no more references, the integer is destroyed.
d03ab969 238 */
239
d3409d5e 240extern void mp_drop(mp */*m*/);
d03ab969 241
d3409d5e 242#define MP_DROP(m) do { \
243 mp *_mm = (m); \
d34decd2 244 _mm->ref--; \
245 if (_mm->ref == 0 && !(_mm->f & MP_CONST)) \
d3409d5e 246 mp_destroy(_mm); \
247} while (0)
248
249/* --- @mp_split@ --- *
d03ab969 250 *
d3409d5e 251 * Arguments: @mp *m@ = pointer to a multiprecision integer
d03ab969 252 *
d3409d5e 253 * Returns: A reference to the same integer, possibly with a different
254 * address.
d03ab969 255 *
d3409d5e 256 * Use: Splits off a modifiable version of the integer referred to.
d03ab969 257 */
258
d3409d5e 259extern mp *mp_split(mp */*m*/);
260
261#define MP_SPLIT(m) do { \
d34decd2 262 mp *_m = (m); \
263 if ((_m->f & MP_CONST) || _m->ref > 1) { \
264 size_t _len = MP_LEN(_m); \
265 mp *_mm = mp_new(_len, _m->f); \
266 if (!(_m->f & MP_UNDEF)) \
267 memcpy(_mm->v, _m->v, MPWS(_len)); \
268 _m->ref--; \
269 _m = _mm; \
d3409d5e 270 } \
d34decd2 271 (m) = _m; \
d3409d5e 272} while (0)
d03ab969 273
d3409d5e 274/* --- @mp_resize@ --- *
d03ab969 275 *
d3409d5e 276 * Arguments: @mp *m@ = pointer to a multiprecision integer
277 * @size_t sz@ = new size
d03ab969 278 *
d3409d5e 279 * Returns: ---
d03ab969 280 *
d3409d5e 281 * Use: Resizes the vector containing the integer's digits. The new
282 * size must be at least as large as the current integer's
d34decd2 283 * length. This isn't really intended for client use.
d03ab969 284 */
285
d3409d5e 286extern void mp_resize(mp */*m*/, size_t /*sz*/);
287
288#define MP_RESIZE(m, ssz) do { \
289 mp *_m = (m); \
290 size_t _sz = (ssz); \
d34decd2 291 mparena *_a = (_m->f & MP_BURN) ? MPARENA_SECURE : MPARENA_GLOBAL; \
292 mpw *_v; \
d3409d5e 293 size_t _len = MP_LEN(_m); \
d34decd2 294 assert(((void)"can't make size less than length", _sz >= _len)); \
295 _v = mpalloc(_a, _sz); \
d9a8ae10 296 if (!(_m->f & MP_UNDEF)) \
297 memcpy(_v, _m->v, MPWS(_len)); \
d3409d5e 298 if (_m->f & MP_BURN) \
299 memset(_m->v, 0, MPWS(_m->sz)); \
d34decd2 300 mpfree(_m->a, _m->v); \
301 _m->a = _a; \
d3409d5e 302 _m->v = _v; \
303 _m->vl = _v + _len; \
d3409d5e 304} while (0)
d03ab969 305
d3409d5e 306/* --- @mp_ensure@ --- *
d03ab969 307 *
d3409d5e 308 * Arguments: @mp *m@ = pointer to a multiprecision integer
309 * @size_t sz@ = required size
d03ab969 310 *
311 * Returns: ---
312 *
d3409d5e 313 * Use: Ensures that the integer has enough space for @sz@ digits.
314 * The value is not changed.
d03ab969 315 */
316
d3409d5e 317extern void mp_ensure(mp */*m*/, size_t /*sz*/);
318
319#define MP_ENSURE(m, ssz) do { \
d34decd2 320 mp *_m = (m); \
d3409d5e 321 size_t _ssz = (ssz); \
d34decd2 322 size_t _len = MP_LEN(_m); \
323 if (_ssz >= _len) { \
324 if (_ssz > _m->sz) \
325 mp_resize(_m, _ssz); \
326 if (!(_m->f & MP_UNDEF) && _ssz > _len) \
327 memset(_m->vl, 0, MPWS(_ssz - _len)); \
328 _m->vl = _m->v + _ssz; \
329 } \
d3409d5e 330} while (0)
d03ab969 331
d34decd2 332/* --- @mp_dest@ --- *
d03ab969 333 *
d34decd2 334 * Arguments: @mp *m@ = a suggested destination integer
335 * @size_t sz@ = size required for result, in digits
336 * @unsigned f@ = various flags
337 *
338 * Returns: A pointer to an appropriate destination.
339 *
340 * Use: Converts a suggested destination into a real destination with
341 * the required properties. If the real destination is @d@,
342 * then the following properties will hold:
343 *
344 * * @d@ will have exactly one reference.
d03ab969 345 *
d34decd2 346 * * If @m@ is not @MP_NEW@, then the contents of @m@ will not
347 * change, unless @f@ has the @MP_UNDEF@ flag set.
d03ab969 348 *
d34decd2 349 * * If @m@ is not @MP_NEW@, then he reference count of @m@ on
350 * entry is equal to the sum of the counts of @d@ and @m@ on
351 * exit.
352 *
353 * * The size of @d@ will be at least @sz@.
354 *
355 * * If @f@ has the @MP_BURN@ flag set, then @d@ will be
356 * allocated from @MPARENA_SECURE@.
357 *
358 * Understanding this function is crucial to using Catacomb's
359 * multiprecision integer library effectively.
d03ab969 360 */
361
d34decd2 362extern mp *mp_dest(mp */*m*/, size_t /*sz*/, unsigned /*f*/);
d03ab969 363
d34decd2 364#define MP_DEST(m, ssz, f) do { \
d3409d5e 365 mp *_m = (m); \
d34decd2 366 size_t _ssz = (ssz); \
367 unsigned _f = (f); \
368 _m = mp_dest(_m, _ssz, _f); \
d3409d5e 369 (m) = _m; \
370} while (0)
371
372/*----- Size manipulation -------------------------------------------------*/
373
374/* --- @mp_shrink@ --- *
d03ab969 375 *
d3409d5e 376 * Arguments: @mp *m@ = pointer to a multiprecision integer
d03ab969 377 *
378 * Returns: ---
379 *
d3409d5e 380 * Use: Reduces the recorded length of an integer. This doesn't
381 * reduce the amount of memory used, although it can improve
382 * performance a bit. To reduce memory, use @mp_minimize@
383 * instead. This can't change the value of an integer, and is
384 * therefore safe to use even when there are multiple
385 * references.
d03ab969 386 */
387
d3409d5e 388extern void mp_shrink(mp */*m*/);
d03ab969 389
d3409d5e 390#define MP_SHRINK(m) do { \
391 mp *_mm = (m); \
392 MPX_SHRINK(_mm->v, _mm->vl); \
393 if (!MP_LEN(_mm)) \
394 _mm->f &= ~MP_NEG; \
395} while (0)
396
397/* --- @mp_minimize@ --- *
d03ab969 398 *
d3409d5e 399 * Arguments: @mp *m@ = pointer to a multiprecision integer
d03ab969 400 *
401 * Returns: ---
402 *
d3409d5e 403 * Use: Reduces the amount of memory an integer uses. It's best to
404 * do this to numbers which aren't going to change in the
405 * future.
d03ab969 406 */
407
d3409d5e 408extern void mp_minimize(mp */*m*/);
d03ab969 409
d3409d5e 410/*----- Bit scanning ------------------------------------------------------*/
d03ab969 411
d9a8ae10 412#ifndef CATACOMB_MPSCAN_H
d3409d5e 413# include "mpscan.h"
414#endif
415
416/* --- @mp_scan@ --- *
d03ab969 417 *
d3409d5e 418 * Arguments: @mpscan *sc@ = pointer to bitscanner block
419 * @const mp *m@ = pointer to a multiprecision integer
d03ab969 420 *
421 * Returns: ---
422 *
d3409d5e 423 * Use: Initializes a bitscanner on a multiprecision integer.
d03ab969 424 */
425
d3409d5e 426extern void mp_scan(mpscan */*sc*/, const mp */*m*/);
427
428#define MP_SCAN(sc, m) do { \
a790733d 429 const mp *_mm = (m); \
d3409d5e 430 mpscan *_sc = (sc); \
431 MPSCAN_INITX(_sc, _mm->v, _mm->vl); \
432} while (0)
433
5fbe3846 434/* --- @mp_rscan@ --- *
435 *
436 * Arguments: @mpscan *sc@ = pointer to bitscanner block
437 * @const mp *m@ = pointer to a multiprecision integer
438 *
439 * Returns: ---
440 *
441 * Use: Initializes a reverse bitscanner on a multiprecision
442 * integer.
443 */
444
445extern void mp_rscan(mpscan */*sc*/, const mp */*m*/);
446
447#define MP_RSCAN(sc, m) do { \
448 const mp *_mm = (m); \
449 mpscan *_sc = (sc); \
450 MPSCAN_RINITX(_sc, _mm->v, _mm->vl); \
451} while (0)
452
d3409d5e 453/* --- Other bitscanning aliases --- */
454
455#define mp_step mpscan_step
456#define mp_bit mpscan_bit
5fbe3846 457#define mp_rstep mpscan_rstep
458#define mp_rbit mpscan_rbit
d3409d5e 459
460#define MP_STEP MPSCAN_STEP
461#define MP_BIT MPSCAN_BIT
5fbe3846 462#define MP_RSTEP MPSCAN_RSTEP
463#define MP_RBIT MPSCAN_RBIT
d3409d5e 464
465/*----- Loading and storing -----------------------------------------------*/
d03ab969 466
d3409d5e 467/* --- @mp_octets@ --- *
d03ab969 468 *
d3409d5e 469 * Arguments: @const mp *m@ = a multiprecision integer
d03ab969 470 *
d3409d5e 471 * Returns: The number of octets required to represent @m@.
d03ab969 472 *
d3409d5e 473 * Use: Calculates the external storage required for a multiprecision
474 * integer.
d03ab969 475 */
476
24e1e862 477extern size_t mp_octets(const mp */*m*/);
478
479/* --- @mp_bits@ --- *
480 *
481 * Arguments: @const mp *m@ = a multiprecision integer
482 *
483 * Returns: The number of bits required to represent @m@.
484 *
485 * Use: Calculates the external storage required for a multiprecision
486 * integer.
487 */
488
489extern unsigned long mp_bits(const mp */*m*/);
d03ab969 490
d3409d5e 491/* --- @mp_loadl@ --- *
d03ab969 492 *
d3409d5e 493 * Arguments: @mp *d@ = destination
494 * @const void *pv@ = pointer to source data
495 * @size_t sz@ = size of the source data
d03ab969 496 *
d3409d5e 497 * Returns: Resulting multiprecision number.
d03ab969 498 *
d3409d5e 499 * Use: Loads a multiprecision number from an array of octets. The
500 * first byte in the array is the least significant. More
501 * formally, if the bytes are %$b_0, b_1, \ldots, b_{n-1}$%
502 * then the result is %$N = \sum_{0 \le i < n} b_i 2^{8i}$%.
d03ab969 503 */
504
d3409d5e 505extern mp *mp_loadl(mp */*d*/, const void */*pv*/, size_t /*sz*/);
d03ab969 506
d3409d5e 507/* --- @mp_storel@ --- *
508 *
509 * Arguments: @const mp *m@ = source
510 * @void *pv@ = pointer to output array
511 * @size_t sz@ = size of the output array
512 *
513 * Returns: ---
514 *
515 * Use: Stores a multiprecision number in an array of octets. The
516 * first byte in the array is the least significant. If the
517 * array is too small to represent the number, high-order bits
518 * are truncated; if the array is too large, high order bytes
519 * are filled with zeros. More formally, if the number is
520 * %$N = \sum{0 \le i} b_i 2^{8i}$% where %$0 \le b_i < 256$%,
521 * then the array is %$b_0, b_1, \ldots, b_{n-1}$%.
522 */
d03ab969 523
d3409d5e 524extern void mp_storel(const mp */*m*/, void */*pv*/, size_t /*sz*/);
d03ab969 525
d3409d5e 526/* --- @mp_loadb@ --- *
d03ab969 527 *
d3409d5e 528 * Arguments: @mp *d@ = destination
529 * @const void *pv@ = pointer to source data
530 * @size_t sz@ = size of the source data
d03ab969 531 *
d3409d5e 532 * Returns: Resulting multiprecision number.
d03ab969 533 *
d3409d5e 534 * Use: Loads a multiprecision number from an array of octets. The
535 * last byte in the array is the least significant. More
536 * formally, if the bytes are %$b_{n-1}, b_{n-2}, \ldots, b_0$%
537 * then the result is %$N = \sum_{0 \le i < n} b_i 2^{8i}$%.
d03ab969 538 */
539
d3409d5e 540extern mp *mp_loadb(mp */*d*/, const void */*pv*/, size_t /*sz*/);
d03ab969 541
d3409d5e 542/* --- @mp_storeb@ --- *
d03ab969 543 *
d3409d5e 544 * Arguments: @const mp *m@ = source
545 * @void *pv@ = pointer to output array
546 * @size_t sz@ = size of the output array
d03ab969 547 *
548 * Returns: ---
549 *
d3409d5e 550 * Use: Stores a multiprecision number in an array of octets. The
551 * last byte in the array is the least significant. If the
552 * array is too small to represent the number, high-order bits
553 * are truncated; if the array is too large, high order bytes
554 * are filled with zeros. More formally, if the number is
555 * %$N = \sum{0 \le i} b_i 2^{8i}$% where %$0 \le b_i < 256$%,
556 * then the array is %$b_{n-1}, b_{n-2}, \ldots, b_0$%.
d03ab969 557 */
558
d3409d5e 559extern void mp_storeb(const mp */*m*/, void */*pv*/, size_t /*sz*/);
d03ab969 560
d3409d5e 561/*----- Simple arithmetic -------------------------------------------------*/
d03ab969 562
d3409d5e 563/* --- @mp_2c@ --- *
d03ab969 564 *
d3409d5e 565 * Arguments: @mp *d@ = destination
566 * @mp *a@ = source
d03ab969 567 *
d3409d5e 568 * Returns: Result, @a@ converted to two's complement notation.
569 */
570
571extern mp *mp_2c(mp */*d*/, mp */*a*/);
572
573/* --- @mp_sm@ --- *
574 *
575 * Arguments: @mp *d@ = destination
576 * @mp *a@ = source
d03ab969 577 *
d3409d5e 578 * Returns: Result, @a@ converted to the native signed-magnitude
579 * notation.
d03ab969 580 */
581
d3409d5e 582extern mp *mp_sm(mp */*d*/, mp */*a*/);
d03ab969 583
d3409d5e 584/* --- @mp_lsl@ --- *
d03ab969 585 *
d3409d5e 586 * Arguments: @mp *d@ = destination
d9a8ae10 587 * @mp *a@ = source
d3409d5e 588 * @size_t n@ = number of bits to move
d03ab969 589 *
d3409d5e 590 * Returns: Result, @a@ shifted left by @n@.
591 */
592
d9a8ae10 593extern mp *mp_lsl(mp */*d*/, mp */*a*/, size_t /*n*/);
d3409d5e 594
595/* --- @mp_lsr@ --- *
596 *
597 * Arguments: @mp *d@ = destination
d9a8ae10 598 * @mp *a@ = source
d3409d5e 599 * @size_t n@ = number of bits to move
d03ab969 600 *
d3409d5e 601 * Returns: Result, @a@ shifted left by @n@.
d03ab969 602 */
603
d9a8ae10 604extern mp *mp_lsr(mp */*d*/, mp */*a*/, size_t /*n*/);
d03ab969 605
740c9553 606/* --- @mp_eq@ --- *
607 *
608 * Arguments: @const mp *a, *b@ = two numbers
609 *
610 * Returns: Nonzero if the numbers are equal.
611 */
612
613extern int mp_eq(const mp */*a*/, const mp */*b*/);
614
615#define MP_EQ(a, b) \
616 ((((a)->f ^ (b)->f) & MP_NEG) == 0 && \
617 mpx_ueq((a)->v, (a)->vl, (b)->v, (b)->vl))
618
d3409d5e 619/* --- @mp_cmp@ --- *
d03ab969 620 *
d3409d5e 621 * Arguments: @const mp *a, *b@ = two numbers
d03ab969 622 *
d3409d5e 623 * Returns: Less than, equal to or greater than zero, according to
624 * whether @a@ is less than, equal to or greater than @b@.
625 */
626
627extern int mp_cmp(const mp */*a*/, const mp */*b*/);
628
629#define MP_CMP(a, op, b) (mp_cmp((a), (b)) op 0)
630
0f32e0f8 631/* --- @mpx_and@, @mpx_or@, @mpx_xor@, @mpx_not@ --- *
632 *
633 * Arguments: @mp *d@ = destination
634 * @mp *a, *b@ = sources
635 *
636 * Returns: The result of the obvious bitwise operation.
637 */
638
639extern mp *mp_and(mp */*d*/, mp */*a*/, mp */*b*/);
640extern mp *mp_or(mp */*d*/, mp */*a*/, mp */*b*/);
641extern mp *mp_xor(mp */*d*/, mp */*a*/, mp */*b*/);
642extern mp *mp_not(mp */*d*/, mp */*a*/);
643
d3409d5e 644/* --- @mp_add@ --- *
d03ab969 645 *
d3409d5e 646 * Arguments: @mp *d@ = destination
d9a8ae10 647 * @mp *a, *b@ = sources
d3409d5e 648 *
649 * Returns: Result, @a@ added to @b@.
d03ab969 650 */
651
d9a8ae10 652extern mp *mp_add(mp */*d*/, mp */*a*/, mp */*b*/);
d03ab969 653
d3409d5e 654/* --- @mp_sub@ --- *
655 *
656 * Arguments: @mp *d@ = destination
d9a8ae10 657 * @mp *a, *b@ = sources
d3409d5e 658 *
659 * Returns: Result, @b@ subtracted from @a@.
660 */
d03ab969 661
d9a8ae10 662extern mp *mp_sub(mp */*d*/, mp */*a*/, mp */*b*/);
d3409d5e 663
664/* --- @mp_mul@ --- *
d03ab969 665 *
d3409d5e 666 * Arguments: @mp *d@ = destination
d9a8ae10 667 * @mp *a, *b@ = sources
d03ab969 668 *
d3409d5e 669 * Returns: Result, @a@ multiplied by @b@.
670 */
671
d9a8ae10 672extern mp *mp_mul(mp */*d*/, mp */*a*/, mp */*b*/);
d3409d5e 673
674/* --- @mp_sqr@ --- *
675 *
676 * Arguments: @mp *d@ = destination
d9a8ae10 677 * @mp *a@ = source
d3409d5e 678 *
679 * Returns: Result, @a@ squared.
680 */
681
d9a8ae10 682extern mp *mp_sqr(mp */*d*/, mp */*a*/);
d3409d5e 683
684/* --- @mp_div@ --- *
d03ab969 685 *
d3409d5e 686 * Arguments: @mp **qq, **rr@ = destination, quotient and remainder
d9a8ae10 687 * @mp *a, *b@ = sources
d3409d5e 688 *
689 * Use: Calculates the quotient and remainder when @a@ is divided by
690 * @b@.
d03ab969 691 */
692
d9a8ae10 693extern void mp_div(mp **/*qq*/, mp **/*rr*/, mp */*a*/, mp */*b*/);
d3409d5e 694
22a073c0 695/* --- @mp_odd@ --- *
696 *
697 * Arguments: @mp *d@ = pointer to destination integer
698 * @mp *m@ = pointer to source integer
699 * @size_t *s@ = where to store the power of 2
700 *
701 * Returns: An odd integer integer %$t$% such that %$m = 2^s t$%.
702 *
703 * Use: Computes a power of two and an odd integer which, when
704 * multiplied, give a specified result. This sort of thing is
705 * useful in number theory quite often.
706 */
707
708extern mp *mp_odd(mp */*d*/, mp */*m*/, size_t */*s*/);
709
d3409d5e 710/*----- More advanced algorithms ------------------------------------------*/
d03ab969 711
22a073c0 712/* --- @mp_sqrt@ --- *
713 *
714 * Arguments: @mp *d@ = pointer to destination integer
715 * @mp *a@ = (nonnegative) integer to take square root of
716 *
717 * Returns: The largest integer %$x$% such that %$x^2 \le a$%.
718 *
719 * Use: Computes integer square roots.
720 *
721 * The current implementation isn't very good: it uses the
722 * Newton-Raphson method to find an approximation to %$a$%. If
723 * there's any demand for a better version, I'll write one.
724 */
725
726extern mp *mp_sqrt(mp */*d*/, mp */*a*/);
727
d3409d5e 728/* --- @mp_gcd@ --- *
d03ab969 729 *
d3409d5e 730 * Arguments: @mp **gcd, **xx, **yy@ = where to write the results
731 * @mp *a, *b@ = sources (must be nonzero)
d03ab969 732 *
733 * Returns: ---
734 *
d3409d5e 735 * Use: Calculates @gcd(a, b)@, and two numbers @x@ and @y@ such that
736 * @ax + by = gcd(a, b)@. This is useful for computing modular
d9a8ae10 737 * inverses. Neither @a@ nor @b@ may be zero.
d03ab969 738 */
739
d3409d5e 740extern void mp_gcd(mp **/*gcd*/, mp **/*xx*/, mp **/*yy*/,
741 mp */*a*/, mp */*b*/);
742
5b00a0ea 743/* --- @mp_jacobi@ --- *
744 *
745 * Arguments: @mp *a@ = an integer less than @n@
746 * @mp *n@ = an odd integer
747 *
748 * Returns: @-1@, @0@ or @1@ -- the Jacobi symbol %$J(a, n)$%.
749 *
750 * Use: Computes the Jacobi symbol. If @n@ is prime, this is the
751 * Legendre symbol and is equal to 1 if and only if @a@ is a
752 * quadratic residue mod @n@. The result is zero if and only if
753 * @a@ and @n@ have a common factor greater than one.
754 */
755
22a073c0 756extern int mp_jacobi(mp */*a*/, mp */*n*/);
757
758/* --- @mp_modsqrt@ --- *
759 *
760 * Arguments: @mp *d@ = destination integer
761 * @mp *a@ = source integer
762 * @mp *p@ = modulus (must be prime)
763 *
764 * Returns: If %$a$% is a quadratic residue, a square root of %$a$%; else
765 * a null pointer.
766 *
767 * Use: Returns an integer %$x$% such that %$x^2 \equiv a \pmod{p}$%,
768 * if one exists; else a null pointer. This function will not
769 * work if %$p$% is composite: you must factor the modulus, take
770 * a square root mod each factor, and recombine the results
771 * using the Chinese Remainder Theorem.
772 */
773
774extern mp *mp_modsqrt(mp */*d*/, mp */*a*/, mp */*p*/);
5b00a0ea 775
d3409d5e 776/*----- Test harness support ----------------------------------------------*/
777
778#include <mLib/testrig.h>
779
d9a8ae10 780#ifndef CATACOMB_MPTEXT_H
d3409d5e 781# include "mptext.h"
782#endif
783
784extern const test_type type_mp;
d03ab969 785
786/*----- That's all, folks -------------------------------------------------*/
787
788#ifdef __cplusplus
789 }
790#endif
791
792#endif