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