3 * $Id: mp.h,v 1.6 1999/12/10 23:19:46 mdw Exp $
5 * Simple multiprecision arithmetic
7 * (c) 1999 Straylight/Edgeware
10 /*----- Licensing notice --------------------------------------------------*
12 * This file is part of Catacomb.
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.
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.
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,
30 /*----- Revision history --------------------------------------------------*
33 * Revision 1.6 1999/12/10 23:19:46 mdw
34 * Minor bugfixes. New interface for suggested destinations.
36 * Revision 1.5 1999/11/22 20:50:37 mdw
37 * Add support for computing Jacobi symbols.
39 * Revision 1.4 1999/11/21 22:13:02 mdw
40 * Add mp version of MPX_BITS.
42 * Revision 1.3 1999/11/19 13:19:14 mdw
43 * Fix const annotation.
45 * Revision 1.2 1999/11/17 18:02:16 mdw
46 * New multiprecision integer arithmetic suite.
57 /*----- Header files ------------------------------------------------------*/
64 #ifndef CATACOMB_MPW_H
68 #ifndef CATACOMB_MPX_H
72 /*----- Data structures ---------------------------------------------------*/
85 #define MP_DESTROYED 16u
87 /*----- Useful constants --------------------------------------------------*/
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])
100 #define MP_NEW ((mp *)0)
102 /*----- Memory allocation hooks -------------------------------------------*/
104 #ifndef CATACOMB_MPARENA_H
105 # include "mparena.h"
108 /* --- @MP_ARENA@ --- *
110 * This selects where memory is allocated from. Tweak to use more fancy
111 * things like custom arenas.
115 # define MP_ARENA MPARENA_GLOBAL
118 /* --- @MP_ALLOC@ --- *
120 * Arguments: @size_t sz@ = size required
122 * Returns: Pointer to an allocated vector of the requested size.
124 * Use: Hook for vector allocation.
128 # define MP_ALLOC(sz) mpalloc(MP_ARENA, (sz))
131 /* --- @MP_FREE@ --- *
133 * Arguments: @mpw *v@ = pointer to vector
137 * Use: Hook for vector deallocation.
141 # define MP_FREE(v) mpfree(MP_ARENA, (v))
144 /*----- Paranoia management -----------------------------------------------*/
146 /* --- @mp_burn@ --- *
148 * Arguments: @mp *m@ = pointer to a multiprecision integer
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.
157 extern void mp_burn(mp */
*m*/
);
159 /*----- Trivial macros ----------------------------------------------------*/
161 /* --- @MP_LEN@ --- *
163 * Arguments: @mp *m@ = pointer to a multiprecision integer
165 * Returns: Length of the integer, in words.
168 #define MP_LEN(m) ((m)->vl - ((m)->v))
170 /*----- Memory management and reference counting --------------------------*/
172 /* --- @mp_create@ --- *
174 * Arguments: @size_t sz@ = size of vector required
176 * Returns: Pointer to pristine new MP structure with enough memory
179 * Use: Creates a new multiprecision integer with indeterminate
180 * contents. The integer has a single reference.
183 extern mp
*mp_create(size_t /*sz*/);
185 /* --- @mp_build@ --- *
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
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.
199 extern void mp_build(mp */
*m*/
, mpw */
*v*/
, mpw */
*vl*/
);
201 /* --- @mp_destroy@ --- *
203 * Arguments: @mp *m@ = pointer to a multiprecision integer
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.
212 extern void mp_destroy(mp */
*m*/
);
214 /* --- @mp_copy@ --- *
216 * Arguments: @mp *m@ = pointer to a multiprecision integer
218 * Returns: A copy of the given multiprecision integer.
220 * Use: Copies the given integer. In fact you just get another
221 * reference to the same old one again.
224 extern mp
*mp_copy(mp */
*m*/
);
226 #define MP_COPY(m) ((m)->ref++, (m))
228 /* --- @mp_drop@ --- *
230 * Arguments: @mp *m@ = pointer to a multiprecision integer
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.
238 extern void mp_drop(mp */
*m*/
);
240 #define MP_DROP(m) do { \
244 else if (!(_mm->f & MP_CONST)) \
248 /* --- @mp_split@ --- *
250 * Arguments: @mp *m@ = pointer to a multiprecision integer
252 * Returns: A reference to the same integer, possibly with a different
255 * Use: Splits off a modifiable version of the integer referred to.
258 extern mp
*mp_split(mp */
*m*/
);
260 #define MP_SPLIT(m) do { \
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))); \
273 /* --- @mp_resize@ --- *
275 * Arguments: @mp *m@ = pointer to a multiprecision integer
276 * @size_t sz@ = new size
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
287 extern void mp_resize(mp */
*m*/
, size_t /*sz*/);
289 #define MP_RESIZE(m, ssz) do { \
291 size_t _sz = (ssz); \
292 size_t _len = MP_LEN(_m); \
293 mpw *_v = MP_ALLOC(_sz); \
294 if (!(_m->f & MP_UNDEF)) \
295 memcpy(_v, _m->v, MPWS(_len)); \
296 if (_m->f & MP_BURN) \
297 memset(_m->v, 0, MPWS(_m->sz)); \
300 _m->vl = _v + _len; \
304 /* --- @mp_ensure@ --- *
306 * Arguments: @mp *m@ = pointer to a multiprecision integer
307 * @size_t sz@ = required size
311 * Use: Ensures that the integer has enough space for @sz@ digits.
312 * The value is not changed.
315 extern void mp_ensure(mp */
*m*/
, size_t /*sz*/);
317 #define MP_ENSURE(m, ssz) do { \
319 size_t _ssz = (ssz); \
320 size_t _len = MP_LEN(_mm); \
321 if (_ssz > _mm->sz) \
322 MP_RESIZE(_mm, _ssz); \
323 if (!(_mm->f & MP_UNDEF) && _ssz > _len) \
324 memset(_mm->vl, 0, MPWS(_ssz - _len)); \
325 _mm->vl = _mm->v + _ssz; \
328 /* --- @mp_modify@ --- *
330 * Arguments: @mp *m@ = pointer to a multiprecision integer
331 * @size_t sz@ = size required
333 * Returns: Pointer to the integer (possibly different).
335 * Use: Prepares an integer to be overwritten. It's split off from
336 * other references to the same integer, and sufficient space is
340 extern mp
*mp_modify(mp */
*m*/
, size_t /*sz*/);
342 #define MP_MODIFY(m, sz) do { \
345 if (_m == MP_NEW || m->ref > 1 || (_m->f & MP_CONST)) { \
348 _m = mp_create(_rq); \
350 MP_ENSURE(_m, _rq); \
354 /*----- Size manipulation -------------------------------------------------*/
356 /* --- @mp_shrink@ --- *
358 * Arguments: @mp *m@ = pointer to a multiprecision integer
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
370 extern void mp_shrink(mp */
*m*/
);
372 #define MP_SHRINK(m) do { \
374 MPX_SHRINK(_mm->v, _mm->vl); \
379 /* --- @mp_minimize@ --- *
381 * Arguments: @mp *m@ = pointer to a multiprecision integer
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
390 extern void mp_minimize(mp */
*m*/
);
392 /*----- Bit scanning ------------------------------------------------------*/
394 #ifndef CATACOMB_MPSCAN_H
398 /* --- @mp_scan@ --- *
400 * Arguments: @mpscan *sc@ = pointer to bitscanner block
401 * @const mp *m@ = pointer to a multiprecision integer
405 * Use: Initializes a bitscanner on a multiprecision integer.
408 extern void mp_scan(mpscan */
*sc*/
, const mp */
*m*/
);
410 #define MP_SCAN(sc, m) do { \
411 const mp *_mm = (m); \
412 mpscan *_sc = (sc); \
413 MPSCAN_INITX(_sc, _mm->v, _mm->vl); \
416 /* --- Other bitscanning aliases --- */
418 #define mp_step mpscan_step
419 #define mp_bit mpscan_bit
421 #define MP_STEP MPSCAN_STEP
422 #define MP_BIT MPSCAN_BIT
424 /*----- Loading and storing -----------------------------------------------*/
426 /* --- @mp_octets@ --- *
428 * Arguments: @const mp *m@ = a multiprecision integer
430 * Returns: The number of octets required to represent @m@.
432 * Use: Calculates the external storage required for a multiprecision
436 extern size_t mp_octets(const mp */
*m*/
);
438 /* --- @mp_bits@ --- *
440 * Arguments: @const mp *m@ = a multiprecision integer
442 * Returns: The number of bits required to represent @m@.
444 * Use: Calculates the external storage required for a multiprecision
448 extern unsigned long mp_bits(const mp */
*m*/
);
450 /* --- @mp_loadl@ --- *
452 * Arguments: @mp *d@ = destination
453 * @const void *pv@ = pointer to source data
454 * @size_t sz@ = size of the source data
456 * Returns: Resulting multiprecision number.
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}$%.
464 extern mp
*mp_loadl(mp */
*d*/
, const void */
*pv*/
, size_t /*sz*/);
466 /* --- @mp_storel@ --- *
468 * Arguments: @const mp *m@ = source
469 * @void *pv@ = pointer to output array
470 * @size_t sz@ = size of the output array
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}$%.
483 extern void mp_storel(const mp */
*m*/
, void */
*pv*/
, size_t /*sz*/);
485 /* --- @mp_loadb@ --- *
487 * Arguments: @mp *d@ = destination
488 * @const void *pv@ = pointer to source data
489 * @size_t sz@ = size of the source data
491 * Returns: Resulting multiprecision number.
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}$%.
499 extern mp
*mp_loadb(mp */
*d*/
, const void */
*pv*/
, size_t /*sz*/);
501 /* --- @mp_storeb@ --- *
503 * Arguments: @const mp *m@ = source
504 * @void *pv@ = pointer to output array
505 * @size_t sz@ = size of the output array
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$%.
518 extern void mp_storeb(const mp */
*m*/
, void */
*pv*/
, size_t /*sz*/);
520 /*----- Simple arithmetic -------------------------------------------------*/
524 * Arguments: @mp *d@ = destination
527 * Returns: Result, @a@ converted to two's complement notation.
530 extern mp
*mp_2c(mp */
*d*/
, mp */
*a*/
);
534 * Arguments: @mp *d@ = destination
537 * Returns: Result, @a@ converted to the native signed-magnitude
541 extern mp
*mp_sm(mp */
*d*/
, mp */
*a*/
);
543 /* --- @mp_lsl@ --- *
545 * Arguments: @mp *d@ = destination
547 * @size_t n@ = number of bits to move
549 * Returns: Result, @a@ shifted left by @n@.
552 extern mp
*mp_lsl(mp */
*d*/
, mp */
*a*/
, size_t /*n*/);
554 /* --- @mp_lsr@ --- *
556 * Arguments: @mp *d@ = destination
558 * @size_t n@ = number of bits to move
560 * Returns: Result, @a@ shifted left by @n@.
563 extern mp
*mp_lsr(mp */
*d*/
, mp */
*a*/
, size_t /*n*/);
565 /* --- @mp_cmp@ --- *
567 * Arguments: @const mp *a, *b@ = two numbers
569 * Returns: Less than, equal to or greater than zero, according to
570 * whether @a@ is less than, equal to or greater than @b@.
573 extern int mp_cmp(const mp */
*a*/
, const mp */
*b*/
);
575 #define MP_CMP(a, op, b) (mp_cmp((a), (b)) op 0)
577 /* --- @mp_add@ --- *
579 * Arguments: @mp *d@ = destination
580 * @mp *a, *b@ = sources
582 * Returns: Result, @a@ added to @b@.
585 extern mp
*mp_add(mp */
*d*/
, mp */
*a*/
, mp */
*b*/
);
587 /* --- @mp_sub@ --- *
589 * Arguments: @mp *d@ = destination
590 * @mp *a, *b@ = sources
592 * Returns: Result, @b@ subtracted from @a@.
595 extern mp
*mp_sub(mp */
*d*/
, mp */
*a*/
, mp */
*b*/
);
597 /* --- @mp_mul@ --- *
599 * Arguments: @mp *d@ = destination
600 * @mp *a, *b@ = sources
602 * Returns: Result, @a@ multiplied by @b@.
605 extern mp
*mp_mul(mp */
*d*/
, mp */
*a*/
, mp */
*b*/
);
607 /* --- @mp_sqr@ --- *
609 * Arguments: @mp *d@ = destination
612 * Returns: Result, @a@ squared.
615 extern mp
*mp_sqr(mp */
*d*/
, mp */
*a*/
);
617 /* --- @mp_div@ --- *
619 * Arguments: @mp **qq, **rr@ = destination, quotient and remainder
620 * @mp *a, *b@ = sources
622 * Use: Calculates the quotient and remainder when @a@ is divided by
626 extern void mp_div(mp
**/
*qq*/
, mp
**/
*rr*/
, mp */
*a*/
, mp */
*b*/
);
628 /*----- More advanced algorithms ------------------------------------------*/
630 /* --- @mp_gcd@ --- *
632 * Arguments: @mp **gcd, **xx, **yy@ = where to write the results
633 * @mp *a, *b@ = sources (must be nonzero)
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
639 * inverses. Neither @a@ nor @b@ may be zero.
642 extern void mp_gcd(mp
**/
*gcd*/
, mp
**/
*xx*/
, mp
**/
*yy*/
,
643 mp */
*a*/
, mp */
*b*/
);
645 /* --- @mp_jacobi@ --- *
647 * Arguments: @mp *a@ = an integer less than @n@
648 * @mp *n@ = an odd integer
650 * Returns: @-1@, @0@ or @1@ -- the Jacobi symbol %$J(a, n)$%.
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.
658 int mp_jacobi(mp */
*a*/
, mp */
*n*/
);
660 /*----- Test harness support ----------------------------------------------*/
662 #include <mLib/testrig.h>
664 #ifndef CATACOMB_MPTEXT_H
668 extern const test_type type_mp
;
670 /*----- That's all, folks -------------------------------------------------*/