Rearrange the file tree.
[u/mdw/catacomb] / mp.h
diff --git a/mp.h b/mp.h
deleted file mode 100644 (file)
index 13f97d1..0000000
--- a/mp.h
+++ /dev/null
@@ -1,1026 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Simple multiprecision arithmetic
- *
- * (c) 1999 Straylight/Edgeware
- */
-
-/*----- Licensing notice --------------------------------------------------*
- *
- * This file is part of Catacomb.
- *
- * Catacomb is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * Catacomb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with Catacomb; if not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-#ifndef CATACOMB_MP_H
-#define CATACOMB_MP_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <string.h>
-
-#include <mLib/sub.h>
-
-#ifndef CATACOMB_MPW_H
-#  include "mpw.h"
-#endif
-
-#ifndef CATACOMB_ARENA_H
-#  include "arena.h"
-#endif
-
-#ifndef CATACOMB_MPARENA_H
-#  include "mparena.h"
-#endif
-
-#ifndef CATACOMB_MPX_H
-#  include "mpx.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-/* --- A multiprecision integer --- */
-
-typedef struct mp {
-  mpw *v, *vl;                         /* Vector of digits, current limit */
-  size_t sz;                           /* Size of digit buffer in words */
-  mparena *a;                          /* Arena for buffer allocation */
-  unsigned f;                          /* Flags (see below) */
-  unsigned ref;                                /* Reference counter */
-} mp;
-
-#define MP_NEG 1u                      /* Negative (signed magnitude) */
-#define MP_BURN 2u                     /* Secret (viral flag) */
-#define MP_CONST 4u                    /* Uses strange memory allocation */
-#define MP_UNDEF 8u                    /* Contains nothing interesting */
-#define MP_DESTROYED 16u               /* Has been destroyed */
-
-/* --- A factor for simultaneous exponentation --- *
- *
- * Used by the Montgomery and Barrett exponentiators.
- */
-
-typedef struct mp_expfactor {
-  mp *base;
-  mp *exp;
-} mp_expfactor;
-
-/*----- Useful constants --------------------------------------------------*/
-
-extern mp mp_const[];
-
-#define MP_ZERO         (&mp_const[0])
-#define MP_ONE  (&mp_const[1])
-#define MP_TWO  (&mp_const[2])
-#define MP_THREE (&mp_const[3])
-#define MP_FOUR         (&mp_const[4])
-#define MP_FIVE         (&mp_const[5])
-#define MP_TEN  (&mp_const[6])
-#define MP_256  (&mp_const[7])
-#define MP_MONE         (&mp_const[8])
-
-#define MP_NEW ((mp *)0)
-#define MP_NEWSEC (&mp_const[9])
-
-/*----- Trivial macros ----------------------------------------------------*/
-
-/* --- @MP_LEN@ --- *
- *
- * Arguments:  @mp *m@ = pointer to a multiprecision integer
- *
- * Returns:    Length of the integer, in words.
- */
-
-#define MP_LEN(m) ((m)->vl - ((m)->v))
-
-/*----- Memory management and reference counting --------------------------*/
-
-/* --- @mp_new@ --- *
- *
- * Arguments:  @size_t sz@ = size of vector required
- *             @unsigned f@ = flags to set
- *
- * Returns:    Pointer to a new MP structure.
- *
- * Use:                Allocates a new multiprecision integer.  The data space is
- *             allocated from either the standard global or secret arena,
- *             depending on the initial flags requested.
- */
-
-extern mp *mp_new(size_t /*sz*/, unsigned /*f*/);
-
-/* --- @mp_create@ --- *
- *
- * Arguments:  @size_t sz@ = size of vector required
- *
- * Returns:    Pointer to pristine new MP structure with enough memory
- *             bolted onto it.
- *
- * Use:                Creates a new multiprecision integer with indeterminate
- *             contents.  The integer has a single reference.
- */
-
-extern mp *mp_create(size_t /*sz*/);
-
-/* --- @mp_createsecure@ --- *
- *
- * Arguments:  @size_t sz@ = size of vector required
- *
- * Returns:    Pointer to pristine new MP structure with enough memory
- *             bolted onto it.
- *
- * Use:                Creates a new multiprecision integer with indeterminate
- *             contents.  The integer has a single reference.  The integer's
- *             data space is allocated from the secure arena.  Its burn flag
- *             is set.
- */
-
-extern mp *mp_createsecure(size_t /*sz*/);
-
-/* --- @mp_build@ --- *
- *
- * Arguments:  @mp *m@ = pointer to an MP block to fill in
- *             @mpw *v@ = pointer to a word array
- *             @mpw *vl@ = pointer just past end of array
- *
- * Returns:    ---
- *
- * Use:                Creates a multiprecision integer representing some smallish
- *             number.  You must provide storage for the number and dispose
- *             of it when you've finished with it.  The number is marked as
- *             constant while it exists.
- */
-
-extern void mp_build(mp */*m*/, mpw */*v*/, mpw */*vl*/);
-
-/* --- @mp_destroy@ --- *
- *
- * Arguments:  @mp *m@ = pointer to a multiprecision integer
- *
- * Returns:    ---
- *
- * Use:                Destroys a multiprecision integer. The reference count isn't
- *             checked.  Don't use this function if you don't know what
- *             you're doing: use @mp_drop@ instead.
- */
-
-extern void mp_destroy(mp */*m*/);
-
-/* --- @mp_copy@ --- *
- *
- * Arguments:  @mp *m@ = pointer to a multiprecision integer
- *
- * Returns:    A copy of the given multiprecision integer.
- *
- * Use:                Copies the given integer.  In fact you just get another
- *             reference to the same old one again.
- */
-
-extern mp *mp_copy(mp */*m*/);
-
-#define MP_COPY(m) ((m)->ref++, (m))
-
-/* --- @mp_drop@ --- *
- *
- * Arguments:  @mp *m@ = pointer to a multiprecision integer
- *
- * Returns:    ---
- *
- * Use:                Drops a reference to an integer which isn't wanted any more.
- *             If there are no more references, the integer is destroyed.
- */
-
-extern void mp_drop(mp */*m*/);
-
-#define MP_DROP(m) do {                                                        \
-  mp *_mm = (m);                                                       \
-  _mm->ref--;                                                          \
-  if (_mm->ref == 0 && !(_mm->f & MP_CONST))                           \
-    mp_destroy(_mm);                                                   \
-} while (0)
-
-/* --- @mp_split@ --- *
- *
- * Arguments:  @mp *m@ = pointer to a multiprecision integer
- *
- * Returns:    A reference to the same integer, possibly with a different
- *             address.
- *
- * Use:                Splits off a modifiable version of the integer referred to.
- */
-
-extern mp *mp_split(mp */*m*/);
-
-#define MP_SPLIT(m) do {                                               \
-  mp *_m = (m);                                                                \
-  if ((_m->f & MP_CONST) || _m->ref > 1) {                             \
-    size_t _len = MP_LEN(_m);                                          \
-    mp *_mm = mp_new(_len, _m->f);                                     \
-    if (!(_m->f & MP_UNDEF))                                           \
-      memcpy(_mm->v, _m->v, MPWS(_len));                               \
-    _m->ref--;                                                         \
-    _m = _mm;                                                          \
-  }                                                                    \
-  (m) = _m;                                                            \
-} while (0)
-
-/* --- @mp_resize@ --- *
- *
- * Arguments:  @mp *m@ = pointer to a multiprecision integer
- *             @size_t sz@ = new size
- *
- * Returns:    ---
- *
- * Use:                Resizes the vector containing the integer's digits.  The new
- *             size must be at least as large as the current integer's
- *             length.  This isn't really intended for client use.
- */
-
-extern void mp_resize(mp */*m*/, size_t /*sz*/);
-
-#define MP_RESIZE(m, ssz) do {                                         \
-  mp *_m = (m);                                                                \
-  size_t _sz = (ssz);                                                  \
-  mparena *_a = (_m->f & MP_BURN) ? MPARENA_SECURE : MPARENA_GLOBAL;   \
-  mpw *_v;                                                             \
-  size_t _len = MP_LEN(_m);                                            \
-  assert(((void)"can't make size less than length", _sz >= _len));     \
-  _v = mpalloc(_a, _sz);                                               \
-  if (!(_m->f & MP_UNDEF))                                             \
-    memcpy(_v, _m->v, MPWS(_len));                                     \
-  if (_m->f & MP_BURN)                                                 \
-    memset(_m->v, 0, MPWS(_m->sz));                                    \
-  mpfree(_m->a, _m->v);                                                        \
-  _m->a = _a;                                                          \
-  _m->v = _v;                                                          \
-  _m->vl = _v + _len;                                                  \
-} while (0)
-
-/* --- @mp_ensure@ --- *
- *
- * Arguments:  @mp *m@ = pointer to a multiprecision integer
- *             @size_t sz@ = required size
- *
- * Returns:    ---
- *
- * Use:                Ensures that the integer has enough space for @sz@ digits.
- *             The value is not changed.
- */
-
-extern void mp_ensure(mp */*m*/, size_t /*sz*/);
-
-#define MP_ENSURE(m, ssz) do {                                         \
-  mp *_m = (m);                                                                \
-  size_t _ssz = (ssz);                                                 \
-  size_t _len = MP_LEN(_m);                                            \
-  if (_ssz >= _len) {                                                  \
-    if (_ssz > _m->sz)                                                 \
-      mp_resize(_m, _ssz);                                             \
-    if (!(_m->f & MP_UNDEF) && _ssz > _len)                            \
-      memset(_m->vl, 0, MPWS(_ssz - _len));                            \
-    _m->vl = _m->v + _ssz;                                             \
-  }                                                                    \
-} while (0)
-
-/* --- @mp_dest@ --- *
- *
- * Arguments:  @mp *m@ = a suggested destination integer
- *             @size_t sz@ = size required for result, in digits
- *             @unsigned f@ = various flags
- *
- * Returns:    A pointer to an appropriate destination.
- *
- * Use:                Converts a suggested destination into a real destination with
- *             the required properties.  If the real destination is @d@,
- *             then the following properties will hold:
- *
- *               * @d@ will have exactly one reference.
- *
- *               * If @m@ is not @MP_NEW@, then the contents of @m@ will not
- *                 change, unless @f@ has the @MP_UNDEF@ flag set.
- *
- *               * If @m@ is not @MP_NEW@, then he reference count of @m@ on
- *                 entry is equal to the sum of the counts of @d@ and @m@ on
- *                 exit.
- *
- *               * The size of @d@ will be at least @sz@.
- *
- *               * If @f@ has the @MP_BURN@ flag set, then @d@ will be
- *                 allocated from @MPARENA_SECURE@.
- *
- *             Understanding this function is crucial to using Catacomb's
- *             multiprecision integer library effectively.
- */
-
-extern mp *mp_dest(mp */*m*/, size_t /*sz*/, unsigned /*f*/);
-
-#define MP_DEST(m, ssz, f) do {                                                \
-  mp *_m = (m);                                                                \
-  size_t _ssz = (ssz);                                                 \
-  unsigned _f = (f);                                                   \
-  _m = mp_dest(_m, _ssz, _f);                                          \
-  (m) = _m;                                                            \
-} while (0)
-
-/*----- Size manipulation -------------------------------------------------*/
-
-/* --- @mp_shrink@ --- *
- *
- * Arguments:  @mp *m@ = pointer to a multiprecision integer
- *
- * Returns:    ---
- *
- * Use:                Reduces the recorded length of an integer.  This doesn't
- *             reduce the amount of memory used, although it can improve
- *             performance a bit.  To reduce memory, use @mp_minimize@
- *             instead.  This can't change the value of an integer, and is
- *             therefore safe to use even when there are multiple
- *             references.
- */
-
-extern void mp_shrink(mp */*m*/);
-
-#define MP_SHRINK(m) do {                                              \
-  mp *_mm = (m);                                                       \
-  MPX_SHRINK(_mm->v, _mm->vl);                                         \
-  if (MP_ZEROP(_mm))                                                   \
-    _mm->f &= ~MP_NEG;                                                 \
-} while (0)
-
-/* --- @mp_minimize@ --- *
- *
- * Arguments:  @mp *m@ = pointer to a multiprecision integer
- *
- * Returns:    ---
- *
- * Use:                Reduces the amount of memory an integer uses.  It's best to
- *             do this to numbers which aren't going to change in the
- *             future.
- */
-
-extern void mp_minimize(mp */*m*/);
-
-/*----- Bit scanning ------------------------------------------------------*/
-
-#ifndef CATACOMB_MPSCAN_H
-#  include "mpscan.h"
-#endif
-
-/* --- @mp_scan@ --- *
- *
- * Arguments:  @mpscan *sc@ = pointer to bitscanner block
- *             @const mp *m@ = pointer to a multiprecision integer
- *
- * Returns:    ---
- *
- * Use:                Initializes a bitscanner on a multiprecision integer.
- */
-
-extern void mp_scan(mpscan */*sc*/, const mp */*m*/);
-
-#define MP_SCAN(sc, m) do {                                            \
-  const mp *_mm = (m);                                                 \
-  mpscan *_sc = (sc);                                                  \
-  MPSCAN_INITX(_sc, _mm->v, _mm->vl);                                  \
-} while (0)
-
-/* --- @mp_rscan@ --- *
- *
- * Arguments:  @mpscan *sc@ = pointer to bitscanner block
- *             @const mp *m@ = pointer to a multiprecision integer
- *
- * Returns:    ---
- *
- * Use:                Initializes a reverse bitscanner on a multiprecision
- *             integer.
- */
-
-extern void mp_rscan(mpscan */*sc*/, const mp */*m*/);
-
-#define MP_RSCAN(sc, m) do {                                           \
-  const mp *_mm = (m);                                                 \
-  mpscan *_sc = (sc);                                                  \
-  MPSCAN_RINITX(_sc, _mm->v, _mm->vl);                                 \
-} while (0)
-
-/* --- Other bitscanning aliases --- */
-
-#define mp_step mpscan_step
-#define mp_bit mpscan_bit
-#define mp_rstep mpscan_rstep
-#define mp_rbit mpscan_rbit
-
-#define MP_STEP MPSCAN_STEP
-#define MP_BIT MPSCAN_BIT
-#define MP_RSTEP MPSCAN_RSTEP
-#define MP_RBIT MPSCAN_RBIT
-
-/*----- Loading and storing -----------------------------------------------*/
-
-/* --- @mp_octets@ --- *
- *
- * Arguments:  @const mp *m@ = a multiprecision integer
- *
- * Returns:    The number of octets required to represent @m@.
- *
- * Use:                Calculates the external storage required for a multiprecision
- *             integer.
- */
-
-extern size_t mp_octets(const mp */*m*/);
-
-/* --- @mp_octets2c@ --- *
- *
- * Arguments:  @const mp *m@ = a multiprecision integer
- *
- * Returns:    The number of octets required to represent @m@.
- *
- * Use:                Calculates the external storage required for a multiprecision
- *             integer represented as two's complement.
- */
-
-extern size_t mp_octets2c(const mp */*m*/);
-
-/* --- @mp_bits@ --- *
- *
- * Arguments:  @const mp *m@ = a multiprecision integer
- *
- * Returns:    The number of bits required to represent @m@.
- *
- * Use:                Calculates the external storage required for a multiprecision
- *             integer.
- */
-
-extern unsigned long mp_bits(const mp */*m*/);
-
-/* --- @mp_loadl@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @const void *pv@ = pointer to source data
- *             @size_t sz@ = size of the source data
- *
- * Returns:    Resulting multiprecision number.
- *
- * Use:                Loads a multiprecision number from an array of octets.  The
- *             first byte in the array is the least significant.  More
- *             formally, if the bytes are %$b_0, b_1, \ldots, b_{n-1}$%
- *             then the result is %$N = \sum_{0 \le i < n} b_i 2^{8i}$%.
- */
-
-extern mp *mp_loadl(mp */*d*/, const void */*pv*/, size_t /*sz*/);
-
-/* --- @mp_storel@ --- *
- *
- * Arguments:  @const mp *m@ = source
- *             @void *pv@ = pointer to output array
- *             @size_t sz@ = size of the output array
- *
- * Returns:    ---
- *
- * Use:                Stores a multiprecision number in an array of octets.  The
- *             first byte in the array is the least significant.  If the
- *             array is too small to represent the number, high-order bits
- *             are truncated; if the array is too large, high order bytes
- *             are filled with zeros.  More formally, if the number is
- *             %$N = \sum{0 \le i} b_i 2^{8i}$% where %$0 \le b_i < 256$%,
- *             then the array is %$b_0, b_1, \ldots, b_{n-1}$%.
- */
-
-extern void mp_storel(const mp */*m*/, void */*pv*/, size_t /*sz*/);
-
-/* --- @mp_loadb@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @const void *pv@ = pointer to source data
- *             @size_t sz@ = size of the source data
- *
- * Returns:    Resulting multiprecision number.
- *
- * Use:                Loads a multiprecision number from an array of octets.  The
- *             last byte in the array is the least significant.  More
- *             formally, if the bytes are %$b_{n-1}, b_{n-2}, \ldots, b_0$%
- *             then the result is %$N = \sum_{0 \le i < n} b_i 2^{8i}$%.
- */
-
-extern mp *mp_loadb(mp */*d*/, const void */*pv*/, size_t /*sz*/);
-
-/* --- @mp_storeb@ --- *
- *
- * Arguments:  @const mp *m@ = source
- *             @void *pv@ = pointer to output array
- *             @size_t sz@ = size of the output array
- *
- * Returns:    ---
- *
- * Use:                Stores a multiprecision number in an array of octets.  The
- *             last byte in the array is the least significant.  If the
- *             array is too small to represent the number, high-order bits
- *             are truncated; if the array is too large, high order bytes
- *             are filled with zeros.  More formally, if the number is
- *             %$N = \sum{0 \le i} b_i 2^{8i}$% where %$0 \le b_i < 256$%,
- *             then the array is %$b_{n-1}, b_{n-2}, \ldots, b_0$%.
- */
-
-extern void mp_storeb(const mp */*m*/, void */*pv*/, size_t /*sz*/);
-
-/* --- @mp_loadl2c@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @const void *pv@ = pointer to source data
- *             @size_t sz@ = size of the source data
- *
- * Returns:    Resulting multiprecision number.
- *
- * Use:                Loads a multiprecision number from an array of octets as
- *             two's complement.  The first byte in the array is the least
- *             significant.
- */
-
-extern mp *mp_loadl2c(mp */*d*/, const void */*pv*/, size_t /*sz*/);
-
-/* --- @mp_storel2c@ --- *
- *
- * Arguments:  @const mp *m@ = source
- *             @void *pv@ = pointer to output array
- *             @size_t sz@ = size of the output array
- *
- * Returns:    ---
- *
- * Use:                Stores a multiprecision number in an array of octets as two's
- *             complement.  The first byte in the array is the least
- *             significant.  If the array is too small to represent the
- *             number, high-order bits are truncated; if the array is too
- *             large, high order bytes are sign-extended.
- */
-
-extern void mp_storel2c(const mp */*m*/, void */*pv*/, size_t /*sz*/);
-
-/* --- @mp_loadb2c@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @const void *pv@ = pointer to source data
- *             @size_t sz@ = size of the source data
- *
- * Returns:    Resulting multiprecision number.
- *
- * Use:                Loads a multiprecision number from an array of octets as
- *             two's complement.  The last byte in the array is the least
- *             significant.
- */
-
-extern mp *mp_loadb2c(mp */*d*/, const void */*pv*/, size_t /*sz*/);
-
-/* --- @mp_storeb2c@ --- *
- *
- * Arguments:  @const mp *m@ = source
- *             @void *pv@ = pointer to output array
- *             @size_t sz@ = size of the output array
- *
- * Returns:    ---
- *
- * Use:                Stores a multiprecision number in an array of octets, as
- *             two's complement.  The last byte in the array is the least
- *             significant.  If the array is too small to represent the
- *             number, high-order bits are truncated; if the array is too
- *             large, high order bytes are sign-extended.
- */
-
-extern void mp_storeb2c(const mp */*m*/, void */*pv*/, size_t /*sz*/);
-
-/*----- Bit operations ----------------------------------------------------*/
-
-/* --- @mp_not@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a@ = source
- *
- * Returns:    The bitwise complement of the source.
- */
-
-extern mp *mp_not(mp */*d*/, mp */*a*/);
-
-/* --- @mp_bitop@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a, *b@ = sources
- *
- * Returns:    The result of the given bitwise operation.  These functions
- *             don't handle negative numbers at all sensibly.  For that, use
- *             the @...2c@ variants.  The functions are named after the
- *             truth tables they generate:
- *
- *                     a:      0011
- *                     b:      0101
- *                     @mpx_bitXXXX@
- */
-
-#define MP_BITDECL(string)                                             \
-  extern mp *mp_bit##string(mp */*d*/, mp */*a*/, mp */*b*/);
-MPX_DOBIN(MP_BITDECL)
-
-/* --- @mp_[n]and@, @mp_[n]or@, @mp_[n]xor@, @mp_not@ --- *
- *
- * Synonyms for the commonly-used functions.
- */
-
-#define mp_and mp_bit0001
-#define mp_or  mp_bit0111
-#define mp_nand mp_bit1110
-#define mp_nor mp_bit1000
-#define mp_xor mp_bit0110
-
-/* --- @mp_testbit@ --- *
- *
- * Arguments:  @mp *x@ = a large integer
- *             @unsigned long n@ = which bit to test
- *
- * Returns:    Nonzero if the bit is set, zero if not.
- */
-
-extern int mp_testbit(mp */*x*/, unsigned long /*n*/);
-
-/* --- @mp_setbit@, @mp_clearbit@ --- *
- *
- * Arguments:  @mp *d@ = a destination
- *             @mp *x@ = a large integer
- *             @unsigned long n@ = which bit to modify
- *
- * Returns:    The argument @x@, with the appropriate bit set or cleared.
- */
-
-extern mp *mp_setbit(mp */*d*/, mp */*x*/, unsigned long /*n*/);
-extern mp *mp_clearbit(mp */*d*/, mp */*x*/, unsigned long /*n*/);
-
-/* --- @mp_lsl@, @mp_lslc@, @mp_lsr@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a@ = source
- *             @size_t n@ = number of bits to move
- *
- * Returns:    Result, @a@ shifted left or right by @n@.
- *
- * Use:                Bitwise shift operators.  @mp_lslc@ fills the bits introduced
- *             on the right with ones instead of zeroes: it's used
- *             internally by @mp_lsl2c@, though it may be useful on its
- *             own.
- */
-
-extern mp *mp_lsl(mp */*d*/, mp */*a*/, size_t /*n*/);
-extern mp *mp_lslc(mp */*d*/, mp */*a*/, size_t /*n*/);
-extern mp *mp_lsr(mp */*d*/, mp */*a*/, size_t /*n*/);
-
-/* --- @mp_not2c@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a@ = source
- *
- * Returns:    The sign-extended complement of the argument.
- */
-
-extern mp *mp_not2c(mp */*d*/, mp */*a*/);
-
-/* --- @mp_bitop2c@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a, *b@ = sources
- *
- * Returns:    The result of the given bitwise operation.  Negative numbers
- *             are treated as two's complement, sign-extended infinitely to
- *             the left.  The functions are named after the truth tables
- *             they generate:
- *
- *                     a:      0011
- *                     b:      0101
- *                     @mpx_bitXXXX@
- */
-
-#define MP_BIT2CDECL(string)                                           \
-  extern mp *mp_bit##string##2c(mp */*d*/, mp */*a*/, mp */*b*/);
-MPX_DOBIN(MP_BIT2CDECL)
-
-/* --- @mp_[n]and@, @mp_[n]or@, @mp_[n]xor@, @mp_not@ --- *
- *
- * Synonyms for the commonly-used functions.
- */
-
-#define mp_and2c  mp_bit00012c
-#define mp_or2c          mp_bit01112c
-#define mp_nand2c mp_bit11102c
-#define mp_nor2c  mp_bit10002c
-#define mp_xor2c  mp_bit01102c
-
-/* --- @mp_lsl2c@, @mp_lsr2c@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a@ = source
- *             @size_t n@ = number of bits to move
- *
- * Returns:    Result, @a@ shifted left or right by @n@.  Handles the
- *             pretence of sign-extension for negative numbers.
- */
-
-extern mp *mp_lsl2c(mp */*d*/, mp */*a*/, size_t /*n*/);
-extern mp *mp_lsr2c(mp */*d*/, mp */*a*/, size_t /*n*/);
-
-/* --- @mp_testbit2c@ --- *
- *
- * Arguments:  @mp *x@ = a large integer
- *             @unsigned long n@ = which bit to test
- *
- * Returns:    Nonzero if the bit is set, zero if not.  Fakes up two's
- *             complement representation.
- */
-
-extern int mp_testbit2c(mp */*x*/, unsigned long /*n*/);
-
-/* --- @mp_setbit2c@, @mp_clearbit2c@ --- *
- *
- * Arguments:  @mp *d@ = a destination
- *             @mp *x@ = a large integer
- *             @unsigned long n@ = which bit to modify
- *
- * Returns:    The argument @x@, with the appropriate bit set or cleared.
- *             Fakes up two's complement representation.
- */
-
-extern mp *mp_setbit2c(mp */*d*/, mp */*x*/, unsigned long /*n*/);
-extern mp *mp_clearbit2c(mp */*d*/, mp */*x*/, unsigned long /*n*/);
-
-/*----- Comparisons -------------------------------------------------------*/
-
-/* --- @mp_eq@ --- *
- *
- * Arguments:  @const mp *a, *b@ = two numbers
- *
- * Returns:    Nonzero if the numbers are equal.
- */
-
-extern int mp_eq(const mp */*a*/, const mp */*b*/);
-
-#define MP_EQ(a, b)                                                    \
-  ((((a)->f ^ (b)->f) & MP_NEG) == 0 &&                                        \
-   mpx_ueq((a)->v, (a)->vl, (b)->v, (b)->vl))
-
-/* --- @mp_cmp@ --- *
- *
- * Arguments:  @const mp *a, *b@ = two numbers
- *
- * Returns:    Less than, equal to or greater than zero, according to
- *             whether @a@ is less than, equal to or greater than @b@.
- */
-
-extern int mp_cmp(const mp */*a*/, const mp */*b*/);
-
-#define MP_CMP(a, op, b) (mp_cmp((a), (b)) op 0)
-
-/* --- Other handy macros --- */
-
-#define MP_NEGP(x) ((x)->f & MP_NEG)
-#define MP_ZEROP(x) (!MP_LEN(x))
-#define MP_POSP(x) (!MP_NEGP(x) && !MP_ZEROP(x))
-#define MP_ODDP(x) (!MP_ZEROP(x) && ((x)->v[0] & 1u))
-#define MP_EVENP(x) (!MP_ODDP(x))
-
-/*----- Arithmetic operations ---------------------------------------------*/
-
-/* --- @mp_neg@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a@ = argument
- *
- * Returns:    The negation of the argument.
- *
- * Use:                Negates its argument.
- */
-
-extern mp *mp_neg(mp */*d*/, mp */*a*/);
-
-/* --- @mp_add@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a, *b@ = sources
- *
- * Returns:    Result, @a@ added to @b@.
- */
-
-extern mp *mp_add(mp */*d*/, mp */*a*/, mp */*b*/);
-
-/* --- @mp_sub@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a, *b@ = sources
- *
- * Returns:    Result, @b@ subtracted from @a@.
- */
-
-extern mp *mp_sub(mp */*d*/, mp */*a*/, mp */*b*/);
-
-/* --- @mp_mul@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a, *b@ = sources
- *
- * Returns:    Result, @a@ multiplied by @b@.
- */
-
-extern mp *mp_mul(mp */*d*/, mp */*a*/, mp */*b*/);
-
-/* --- @mp_sqr@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a@ = source
- *
- * Returns:    Result, @a@ squared.
- */
-
-extern mp *mp_sqr(mp */*d*/, mp */*a*/);
-
-/* --- @mp_div@ --- *
- *
- * Arguments:  @mp **qq, **rr@ = destination, quotient and remainder
- *             @mp *a, *b@ = sources
- *
- * Use:                Calculates the quotient and remainder when @a@ is divided by
- *             @b@.
- */
-
-extern void mp_div(mp **/*qq*/, mp **/*rr*/, mp */*a*/, mp */*b*/);
-
-/* --- @mp_exp@ --- *
- *
- * Arguments:  @mp *d@ = fake destination
- *             @mp *a@ = base
- *             @mp *e@ = exponent
- *
- * Returns:    Result, %$a^e$%.
- */
-
-extern mp *mp_exp(mp */*d*/, mp */*a*/, mp */*e*/);
-
-/* --- @mp_odd@ --- *
- *
- * Arguments:  @mp *d@ = pointer to destination integer
- *             @mp *m@ = pointer to source integer
- *             @size_t *s@ = where to store the power of 2
- *
- * Returns:    An odd integer integer %$t$% such that %$m = 2^s t$%.
- *
- * Use:                Computes a power of two and an odd integer which, when
- *             multiplied, give a specified result.  This sort of thing is
- *             useful in number theory quite often.
- */
-
-extern mp *mp_odd(mp */*d*/, mp */*m*/, size_t */*s*/);
-
-/*----- More advanced algorithms ------------------------------------------*/
-
-/* --- @mp_sqrt@ --- *
- *
- * Arguments:  @mp *d@ = pointer to destination integer
- *             @mp *a@ = (nonnegative) integer to take square root of
- *
- * Returns:    The largest integer %$x$% such that %$x^2 \le a$%.
- *
- * Use:                Computes integer square roots.
- *
- *             The current implementation isn't very good: it uses the
- *             Newton-Raphson method to find an approximation to %$a$%.  If
- *             there's any demand for a better version, I'll write one.
- */
-
-extern mp *mp_sqrt(mp */*d*/, mp */*a*/);
-
-/* --- @mp_gcd@ --- *
- *
- * Arguments:  @mp **gcd, **xx, **yy@ = where to write the results
- *             @mp *a, *b@ = sources (must be nonzero)
- *
- * Returns:    ---
- *
- * Use:                Calculates @gcd(a, b)@, and two numbers @x@ and @y@ such that
- *             @ax + by = gcd(a, b)@.  This is useful for computing modular
- *             inverses.  Neither @a@ nor @b@ may be zero.
- */
-
-extern void mp_gcd(mp **/*gcd*/, mp **/*xx*/, mp **/*yy*/,
-                  mp */*a*/, mp */*b*/);
-
-/* -- @mp_modinv@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *x@ = argument
- *             @mp *p@ = modulus
- *
- * Returns:    The inverse %$x^{-1} \bmod p$%.
- *
- * Use:                Computes a modular inverse.    An assertion fails if %$p$%
- *             has no inverse.
- */
-
-extern mp *mp_modinv(mp */*d*/, mp */*x*/, mp */*p*/);
-
-/* --- @mp_jacobi@ --- *
- *
- * Arguments:  @mp *a@ = an integer
- *             @mp *n@ = another integer
- *
- * Returns:    @-1@, @0@ or @1@ -- the Jacobi symbol %$J(a, n)$%.
- *
- * Use:                Computes the Kronecker symbol %$\jacobi{a}{n}$%.  If @n@ is
- *             prime, this is the Legendre symbol and is equal to 1 if and
- *             only if @a@ is a quadratic residue mod @n@.  The result is
- *             zero if and only if @a@ and @n@ have a common factor greater
- *             than one.
- *
- *             If @n@ is composite, then this computes the Kronecker symbol
- *
- *               %$\jacobi{a}{n}=\jacobi{a}{u}\prod_i\jacobi{a}{p_i}^{e_i}$%
- *
- *             where %$n = u p_0^{e_0} \ldots p_{n-1}^{e_{n-1}}$% is the
- *             prime factorization of %$n$%.  The missing bits are:
- *
- *               * %$\jacobi{a}{1} = 1$%;
- *               * %$\jacobi{a}{-1} = 1$% if @a@ is negative, or 1 if
- *                 positive;
- *               * %$\jacobi{a}{0} = 0$%;
- *               * %$\jacobi{a}{2}$ is 0 if @a@ is even, 1 if @a@ is
- *                 congruent to 1 or 7 (mod 8), or %$-1$% otherwise.
- *
- *             If %$n$% is positive and odd, then this is the Jacobi
- *             symbol.  (The Kronecker symbol is a consistant domain
- *             extension; the Jacobi symbol was implemented first, and the
- *             name stuck.)
- */
-
-extern int mp_jacobi(mp */*a*/, mp */*n*/);
-
-/* --- @mp_modsqrt@ --- *
- *
- * Arguments:  @mp *d@ = destination integer
- *             @mp *a@ = source integer
- *             @mp *p@ = modulus (must be prime)
- *
- * Returns:    If %$a$% is a quadratic residue, a square root of %$a$%; else
- *             a null pointer.
- *
- * Use:                Returns an integer %$x$% such that %$x^2 \equiv a \pmod{p}$%,
- *             if one exists; else a null pointer.  This function will not
- *             work if %$p$% is composite: you must factor the modulus, take
- *             a square root mod each factor, and recombine the results
- *             using the Chinese Remainder Theorem.
- *
- *             We guarantee that the square root returned is the smallest
- *             one (i.e., the `positive' square root).
- */
-
-extern mp *mp_modsqrt(mp */*d*/, mp */*a*/, mp */*p*/);
-
-/* --- @mp_modexp@ --- *
- *
- * Arguments:  @mp *d@ = fake destination
- *             @mp *x@ = base of exponentiation
- *             @mp *e@ = exponent
- *             @mp *n@ = modulus (must be positive)
- *
- * Returns:    The value %$x^e \bmod n$%.
- */
-
-extern mp *mp_modexp(mp */*d*/, mp */*x*/, mp */*e*/, mp */*n*/);
-
-/*----- Test harness support ----------------------------------------------*/
-
-#include <mLib/testrig.h>
-
-#ifndef CATACOMB_MPTEXT_H
-#  include "mptext.h"
-#endif
-
-extern const test_type type_mp;
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif