X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/fa16f6d37b362288e3086fbb34344bc817c09796..f09e814abfcb58c0bb5423589e2940c205106e8d:/mp.h diff --git a/mp.h b/mp.h index 71092fd..c405bca 100644 --- a/mp.h +++ b/mp.h @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: mp.h,v 1.12 2001/06/16 12:57:43 mdw Exp $ + * $Id: mp.h,v 1.13 2002/10/06 22:52:50 mdw Exp $ * * Simple multiprecision arithmetic * @@ -30,6 +30,9 @@ /*----- Revision history --------------------------------------------------* * * $Log: mp.h,v $ + * Revision 1.13 2002/10/06 22:52:50 mdw + * Pile of changes for supporting two's complement properly. + * * Revision 1.12 2001/06/16 12:57:43 mdw * Move the @mpmont_factor@ structure and rename it now that it's used for * Barrett simultaneous exponentiation too. @@ -492,6 +495,18 @@ extern void mp_rscan(mpscan */*sc*/, const mp */*m*/); 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 @@ -574,50 +589,117 @@ extern mp *mp_loadb(mp */*d*/, const void */*pv*/, size_t /*sz*/); extern void mp_storeb(const mp */*m*/, void */*pv*/, size_t /*sz*/); -/*----- Simple arithmetic -------------------------------------------------*/ - -/* --- @mp_2c@ --- * +/* --- @mp_loadl2c@ --- * * * Arguments: @mp *d@ = destination - * @mp *a@ = source + * @const void *pv@ = pointer to source data + * @size_t sz@ = size of the source data + * + * Returns: Resulting multiprecision number. * - * Returns: Result, @a@ converted to two's complement notation. + * 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_2c(mp */*d*/, mp */*a*/); +extern mp *mp_loadl2c(mp */*d*/, const void */*pv*/, size_t /*sz*/); -/* --- @mp_sm@ --- * +/* --- @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 - * @mp *a@ = source + * @const void *pv@ = pointer to source data + * @size_t sz@ = size of the source data * - * Returns: Result, @a@ converted to the native signed-magnitude - * notation. + * 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_sm(mp */*d*/, mp */*a*/); +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*/); + +/*----- Simple arithmetic -------------------------------------------------*/ -/* --- @mp_lsl@ --- * +/* --- @mp_lsl@, @mp_lsr@ --- * * * Arguments: @mp *d@ = destination * @mp *a@ = source * @size_t n@ = number of bits to move * - * Returns: Result, @a@ shifted left by @n@. + * Returns: Result, @a@ shifted left or right by @n@. */ extern mp *mp_lsl(mp */*d*/, mp */*a*/, size_t /*n*/); +extern mp *mp_lsr(mp */*d*/, mp */*a*/, size_t /*n*/); -/* --- @mp_lsr@ --- * +/* --- @mp_lsl2c@, @mp_lsr2c@ --- * * * Arguments: @mp *d@ = destination * @mp *a@ = source * @size_t n@ = number of bits to move * - * Returns: Result, @a@ shifted left by @n@. + * Returns: Result, @a@ shifted left or right by @n@. Handles the + * pretence of sign-extension for negative numbers. */ -extern mp *mp_lsr(mp */*d*/, mp */*a*/, size_t /*n*/); +extern mp *mp_lsl2c(mp */*d*/, mp */*a*/, size_t /*n*/); +extern mp *mp_lsr2c(mp */*d*/, mp */*a*/, size_t /*n*/); + +/* --- @mp_testbit@ --- * + * + * Arguments: @mp *x@ = a large integer + * @size_t n@ = which bit to test + * + * Returns: Nonzero if the bit is set, zero if not. + */ + +extern int mp_testbit(mp */*x*/, size_t /*n*/); + +/* --- @mp_testbit2c@ --- * + * + * Arguments: @mp *x@ = a large integer + * @size_t 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*/, size_t /*n*/); /* --- @mp_eq@ --- * * @@ -644,19 +726,86 @@ extern int mp_cmp(const mp */*a*/, const mp */*b*/); #define MP_CMP(a, op, b) (mp_cmp((a), (b)) op 0) -/* --- @mpx_and@, @mpx_or@, @mpx_xor@, @mpx_not@ --- * +/* --- @mp_bitop@ --- * * * Arguments: @mp *d@ = destination * @mp *a, *b@ = sources * - * Returns: The result of the obvious bitwise operation. + * 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@ */ -extern mp *mp_and(mp */*d*/, mp */*a*/, mp */*b*/); -extern mp *mp_or(mp */*d*/, mp */*a*/, mp */*b*/); -extern mp *mp_xor(mp */*d*/, mp */*a*/, mp */*b*/); +#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_not@ --- * + * + * Arguments: @mp *d@ = destination + * @mp *a@ = source + * + * Returns: The bitwise complement of the source. + */ + extern mp *mp_not(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_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_add@ --- * * * Arguments: @mp *d@ = destination