X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/ba6e6b64033b1f9de49feccb5c9cd438354481f7..0f00dc4c8eb47e67bc0f148c2dd109f73a451e0a:/mp.h diff --git a/mp.h b/mp.h deleted file mode 100644 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 -#include - -#include - -#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 - -#ifndef CATACOMB_MPTEXT_H -# include "mptext.h" -#endif - -extern const test_type type_mp; - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif