Pile of changes for supporting two's complement properly.
[u/mdw/catacomb] / mp.h
diff --git a/mp.h b/mp.h
index 71092fd..c405bca 100644 (file)
--- 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