Synchronize with imath upstream

Started by Noah Mischalmost 7 years ago22 messages
#1Noah Misch
noah@leadboat.com
2 attachment(s)

pgcrypto bundles a copy of the imath library for arbitrary-precision integer
arithmetic in non-SSL builds. Upstream fixed buffer overflows through the
years, and commit 8b59672 brought those fixes into PostgreSQL. In master, I
would like to fully resynchronize with fresh imath 1.29. We're better off
naively tracking upstream than reactively maintaining a twelve-year-old
snapshot of upstream.

imath1.29-raw-sync-v1.patch is the result of copying new imath.c and imath.h
into place, removing "#ifdef __cplusplus" blocks that upset pgindent, running
pgindent, and filtering through "unexpand -t4 --first-only".
imath1.29-pgedits-v1.patch then restores PostgreSQL-specific changes. I would
squash these together for eventual commit, since the intermediate state is
broken, but it should ease review to see them separately. I did not keep the
INVERT_COMPARE_RESULT() change from c87cb5f; the domain of the comparisons in
question is {-1,0,1}, controlled entirely by code in imath.c.

Upstream has fixed bugs over the years, but I am not specifically aware of any
represented fix here that affects pgcrypto. Most suspicious to me are the
division fixes, which could affect our pgp_elgamal_{en,de}crypt(). You can
examine https://github.com/creachadair/imath/blob/master/ChangeLog for all
changes between imath-1.3 and imath-1.29.

Like PostgreSQL, imath now assumes C99. Unlike PostgreSQL, it has adopted
mixed declarations and code; our -Wdeclaration-after-statement would add
sixty-two warnings. If the compiler supports -Wdeclaration-after-statement, I
add -Wno-declaration-after-statement for imath.c.

Thanks,
nm

Attachments:

imath1.29-raw-sync-v1.patchtext/plain; charset=us-asciiDownload
diff --git a/contrib/pgcrypto/imath.c b/contrib/pgcrypto/imath.c
index b94a51b..96be668 100644
--- a/contrib/pgcrypto/imath.c
+++ b/contrib/pgcrypto/imath.c
@@ -1,90 +1,69 @@
-/* imath version 1.3 */
 /*
-  Name:		imath.c
-  Purpose:	Arbitrary precision integer arithmetic routines.
-  Author:	M. J. Fromberger <http://spinning-yarns.org/michael/sw/>
-  Info:		Id: imath.c 21 2006-04-02 18:58:36Z sting
-
-  Copyright (C) 2002 Michael J. Fromberger, All Rights Reserved.
-
-  Permission is hereby granted, free of charge, to any person
-  obtaining a copy of this software and associated documentation files
-  (the "Software"), to deal in the Software without restriction,
-  including without limitation the rights to use, copy, modify, merge,
-  publish, distribute, sublicense, and/or sell copies of the Software,
-  and to permit persons to whom the Software is furnished to do so,
-  subject to the following conditions:
-
-  The above copyright notice and this permission notice shall be
-  included in all copies or substantial portions of the Software.
-
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-  NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+  Name:     imath.c
+  Purpose:  Arbitrary precision integer arithmetic routines.
+  Author:   M. J. Fromberger
+
+  Copyright (C) 2002-2007 Michael J. Fromberger, All Rights Reserved.
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy
+  of this software and associated documentation files (the "Software"), to deal
+  in the Software without restriction, including without limitation the rights
+  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the Software is
+  furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in
+  all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   SOFTWARE.
  */
-/* contrib/pgcrypto/imath.c */
 
-#include "postgres.h"
-#include "px.h"
 #include "imath.h"
 
-#undef assert
-#define assert(TEST) Assert(TEST)
-#define TRACEABLE_CLAMP 0
-#define TRACEABLE_FREE 0
-
-/* {{{ Constants */
+#include <assert.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
 
 const mp_result MP_OK = 0;		/* no error, all is well  */
-const mp_result MP_FALSE = 0;	/* boolean false		  */
-const mp_result MP_TRUE = -1;	/* boolean true			  */
-const mp_result MP_MEMORY = -2; /* out of memory		  */
+const mp_result MP_FALSE = 0;	/* boolean false          */
+const mp_result MP_TRUE = -1;	/* boolean true           */
+const mp_result MP_MEMORY = -2; /* out of memory          */
 const mp_result MP_RANGE = -3;	/* argument out of range  */
-const mp_result MP_UNDEF = -4;	/* result undefined		  */
-const mp_result MP_TRUNC = -5;	/* output truncated		  */
+const mp_result MP_UNDEF = -4;	/* result undefined       */
+const mp_result MP_TRUNC = -5;	/* output truncated       */
 const mp_result MP_BADARG = -6; /* invalid null argument  */
+const mp_result MP_MINERR = -6;
 
 const mp_sign MP_NEG = 1;		/* value is strictly negative */
-const mp_sign MP_ZPOS = 0;		/* value is non-negative	  */
+const mp_sign MP_ZPOS = 0;		/* value is non-negative      */
 
 static const char *s_unknown_err = "unknown result code";
-static const char *s_error_msg[] = {
-	"error code 0",
-	"boolean true",
-	"out of memory",
-	"argument out of range",
-	"result undefined",
-	"output truncated",
-	"invalid null argument",
-	NULL
-};
-
-/* }}} */
-
-/* Optional library flags */
-#define MP_CAP_DIGITS	1		/* flag bit to capitalize letter digits */
-
-/* Argument checking macros
-   Use CHECK() where a return value is required; NRCHECK() elsewhere */
-#define CHECK(TEST)   assert(TEST)
-#define NRCHECK(TEST) assert(TEST)
-
-/* {{{ Logarithm table for computing output sizes */
+static const char *s_error_msg[] = {"error code 0", "boolean true",
+	"out of memory", "argument out of range",
+	"result undefined", "output truncated",
+"invalid argument", NULL};
 
 /* The ith entry of this table gives the value of log_i(2).
 
    An integer value n requires ceil(log_i(n)) digits to be represented
    in base i.  Since it is easy to compute lg(n), by counting bits, we
    can compute log_i(n) = lg(n) * log_i(2).
+
+   The use of this table eliminates a dependency upon linkage against
+   the standard math libraries.
+
+   If MP_MAX_RADIX is increased, this table should be expanded too.
  */
 static const double s_log2[] = {
-	0.000000000, 0.000000000, 1.000000000, 0.630929754, /* 0  1  2	3 */
-	0.500000000, 0.430676558, 0.386852807, 0.356207187, /* 4  5  6	7 */
+	0.000000000, 0.000000000, 1.000000000, 0.630929754, /* (D)(D) 2  3 */
+	0.500000000, 0.430676558, 0.386852807, 0.356207187, /* 4  5  6  7 */
 	0.333333333, 0.315464877, 0.301029996, 0.289064826, /* 8  9 10 11 */
 	0.278942946, 0.270238154, 0.262649535, 0.255958025, /* 12 13 14 15 */
 	0.250000000, 0.244650542, 0.239812467, 0.235408913, /* 16 17 18 19 */
@@ -92,136 +71,240 @@ static const double s_log2[] = {
 	0.218104292, 0.215338279, 0.212746054, 0.210309918, /* 24 25 26 27 */
 	0.208014598, 0.205846832, 0.203795047, 0.201849087, /* 28 29 30 31 */
 	0.200000000, 0.198239863, 0.196561632, 0.194959022, /* 32 33 34 35 */
-	0.193426404, 0.191958720, 0.190551412, 0.189200360, /* 36 37 38 39 */
-	0.187901825, 0.186652411, 0.185449023, 0.184288833, /* 40 41 42 43 */
-	0.183169251, 0.182087900, 0.181042597, 0.180031327, /* 44 45 46 47 */
-	0.179052232, 0.178103594, 0.177183820, 0.176291434, /* 48 49 50 51 */
-	0.175425064, 0.174583430, 0.173765343, 0.172969690, /* 52 53 54 55 */
-	0.172195434, 0.171441601, 0.170707280, 0.169991616, /* 56 57 58 59 */
-	0.169293808, 0.168613099, 0.167948779, 0.167300179, /* 60 61 62 63 */
-	0.166666667
+	0.193426404,				/* 36          */
 };
 
-/* }}} */
-/* {{{ Various macros */
-
 /* Return the number of digits needed to represent a static value */
 #define MP_VALUE_DIGITS(V) \
-((sizeof(V)+(sizeof(mp_digit)-1))/sizeof(mp_digit))
+  ((sizeof(V) + (sizeof(mp_digit) - 1)) / sizeof(mp_digit))
 
 /* Round precision P to nearest word boundary */
-#define ROUND_PREC(P) ((mp_size)(2*(((P)+1)/2)))
+static inline mp_size
+s_round_prec(mp_size P)
+{
+	return 2 * ((P + 1) / 2);
+}
 
 /* Set array P of S digits to zero */
-#define ZERO(P, S) \
-do{mp_size i__=(S)*sizeof(mp_digit);mp_digit *p__=(P);memset(p__,0,i__);}while(0)
+static inline void
+ZERO(mp_digit *P, mp_size S)
+{
+	mp_size		i__ = S * sizeof(mp_digit);
+	mp_digit   *p__ = P;
+
+	memset(p__, 0, i__);
+}
 
 /* Copy S digits from array P to array Q */
-#define COPY(P, Q, S) \
-do{mp_size i__=(S)*sizeof(mp_digit);mp_digit *p__=(P),*q__=(Q);\
-memcpy(q__,p__,i__);}while(0)
+static inline void
+COPY(mp_digit *P, mp_digit *Q, mp_size S)
+{
+	mp_size		i__ = S * sizeof(mp_digit);
+	mp_digit   *p__ = P;
+	mp_digit   *q__ = Q;
 
-/* Reverse N elements of type T in array A */
-#define REV(T, A, N) \
-do{T *u_=(A),*v_=u_+(N)-1;while(u_<v_){T xch=*u_;*u_++=*v_;*v_--=xch;}}while(0)
+	memcpy(q__, p__, i__);
+}
 
-#if TRACEABLE_CLAMP
-#define CLAMP(Z) s_clamp(Z)
-#else
-#define CLAMP(Z) \
-do{mp_int z_=(Z);mp_size uz_=MP_USED(z_);mp_digit *dz_=MP_DIGITS(z_)+uz_-1;\
-while(uz_ > 1 && (*dz_-- == 0)) --uz_;MP_USED(z_)=uz_;}while(0)
-#endif
+/* Reverse N elements of unsigned char in A. */
+static inline void
+REV(unsigned char *A, int N)
+{
+	unsigned char *u_ = A;
+	unsigned char *v_ = u_ + N - 1;
 
-#undef MIN
-#undef MAX
-#define MIN(A, B) ((B)<(A)?(B):(A))
-#define MAX(A, B) ((B)>(A)?(B):(A))
-#define SWAP(T, A, B) do{T t_=(A);A=(B);B=t_;}while(0)
+	while (u_ < v_)
+	{
+		unsigned char xch = *u_;
 
-#define TEMP(K) (temp + (K))
-#define SETUP(E, C) \
-do{if((res = (E)) != MP_OK) goto CLEANUP; ++(C);}while(0)
+		*u_++ = *v_;
+		*v_-- = xch;
+	}
+}
 
-#define CMPZ(Z) \
-(((Z)->used==1&&(Z)->digits[0]==0)?0:((Z)->sign==MP_NEG)?-1:1)
+/* Strip leading zeroes from z_ in-place. */
+static inline void
+CLAMP(mp_int z_)
+{
+	mp_size		uz_ = MP_USED(z_);
+	mp_digit   *dz_ = MP_DIGITS(z_) + uz_ - 1;
 
-#define UMUL(X, Y, Z) \
-do{mp_size ua_=MP_USED(X),ub_=MP_USED(Y);mp_size o_=ua_+ub_;\
-ZERO(MP_DIGITS(Z),o_);\
-(void) s_kmul(MP_DIGITS(X),MP_DIGITS(Y),MP_DIGITS(Z),ua_,ub_);\
-MP_USED(Z)=o_;CLAMP(Z);}while(0)
+	while (uz_ > 1 && (*dz_-- == 0))
+		--uz_;
+	z_->used = uz_;
+}
 
-#define USQR(X, Z) \
-do{mp_size ua_=MP_USED(X),o_=ua_+ua_;ZERO(MP_DIGITS(Z),o_);\
-(void) s_ksqr(MP_DIGITS(X),MP_DIGITS(Z),ua_);MP_USED(Z)=o_;CLAMP(Z);}while(0)
+/* Select min/max. */
+static inline int
+MIN(int A, int B)
+{
+	return (B < A ? B : A);
+}
+static inline mp_size
+MAX(mp_size A, mp_size B)
+{
+	return (B > A ? B : A);
+}
 
-#define UPPER_HALF(W)			((mp_word)((W) >> MP_DIGIT_BIT))
-#define LOWER_HALF(W)			((mp_digit)(W))
-#define HIGH_BIT_SET(W)			((W) >> (MP_WORD_BIT - 1))
-#define ADD_WILL_OVERFLOW(W, V) ((MP_WORD_MAX - (V)) < (W))
+/* Exchange lvalues A and B of type T, e.g.
+   SWAP(int, x, y) where x and y are variables of type int. */
+#define SWAP(T, A, B) \
+  do {                \
+	T t_ = (A);       \
+	A = (B);          \
+	B = t_;           \
+  } while (0)
 
-/* }}} */
+/* Declare a block of N temporary mpz_t values.
+   These values are initialized to zero.
+   You must add CLEANUP_TEMP() at the end of the function.
+   Use TEMP(i) to access a pointer to the ith value.
+ */
+#define DECLARE_TEMP(N)                   \
+  struct {                                \
+	mpz_t value[(N)];                     \
+	int len;                              \
+	mp_result err;                        \
+  } temp_ = {                             \
+	  .len = (N),                         \
+	  .err = MP_OK,                       \
+  };                                      \
+  do {                                    \
+	for (int i = 0; i < temp_.len; i++) { \
+	  mp_int_init(TEMP(i));               \
+	}                                     \
+  } while (0)
+
+/* Clear all allocated temp values. */
+#define CLEANUP_TEMP()                    \
+  CLEANUP:                                \
+  do {                                    \
+	for (int i = 0; i < temp_.len; i++) { \
+	  mp_int_clear(TEMP(i));              \
+	}                                     \
+	if (temp_.err != MP_OK) {             \
+	  return temp_.err;                   \
+	}                                     \
+  } while (0)
+
+/* A pointer to the kth temp value. */
+#define TEMP(K) (temp_.value + (K))
+
+/* Evaluate E, an expression of type mp_result expected to return MP_OK.  If
+   the value is not MP_OK, the error is cached and control resumes at the
+   cleanup handler, which returns it.
+*/
+#define REQUIRE(E)                        \
+  do {                                    \
+	temp_.err = (E);                      \
+	if (temp_.err != MP_OK) goto CLEANUP; \
+  } while (0)
+
+/* Compare value to zero. */
+static inline int
+CMPZ(mp_int Z)
+{
+	if (Z->used == 1 && Z->digits[0] == 0)
+		return 0;
+	return (Z->sign == MP_NEG) ? -1 : 1;
+}
+
+static inline mp_word
+UPPER_HALF(mp_word W)
+{
+	return (W >> MP_DIGIT_BIT);
+}
+static inline mp_digit
+LOWER_HALF(mp_word W)
+{
+	return (mp_digit) (W);
+}
+
+/* Report whether the highest-order bit of W is 1. */
+static inline bool
+HIGH_BIT_SET(mp_word W)
+{
+	return (W >> (MP_WORD_BIT - 1)) != 0;
+}
+
+/* Report whether adding W + V will carry out. */
+static inline bool
+ADD_WILL_OVERFLOW(mp_word W, mp_word V)
+{
+	return ((MP_WORD_MAX - V) < W);
+}
 
 /* Default number of digits allocated to a new mp_int */
-static mp_size default_precision = 64;
+static mp_size default_precision = 8;
+
+void
+mp_int_default_precision(mp_size size)
+{
+	assert(size > 0);
+	default_precision = size;
+}
 
 /* Minimum number of digits to invoke recursive multiply */
 static mp_size multiply_threshold = 32;
 
-/* Default library configuration flags */
-static mp_word mp_flags = MP_CAP_DIGITS;
+void
+mp_int_multiply_threshold(mp_size thresh)
+{
+	assert(thresh >= sizeof(mp_word));
+	multiply_threshold = thresh;
+}
 
 /* Allocate a buffer of (at least) num digits, or return
    NULL if that couldn't be done.  */
 static mp_digit *s_alloc(mp_size num);
 
-#if TRACEABLE_FREE
+/* Release a buffer of digits allocated by s_alloc(). */
 static void s_free(void *ptr);
-#else
-#define s_free(P) px_free(P)
-#endif
 
 /* Insure that z has at least min digits allocated, resizing if
    necessary.  Returns true if successful, false if out of memory. */
-static int	s_pad(mp_int z, mp_size min);
+static bool s_pad(mp_int z, mp_size min);
 
-/* Normalize by removing leading zeroes (except when z = 0) */
-#if TRACEABLE_CLAMP
-static void s_clamp(mp_int z);
-#endif
+/* Ensure Z has at least N digits allocated. */
+static inline mp_result
+GROW(mp_int Z, mp_size N)
+{
+	return s_pad(Z, N) ? MP_OK : MP_MEMORY;
+}
 
 /* Fill in a "fake" mp_int on the stack with a given value */
-static void s_fake(mp_int z, int value, mp_digit vbuf[]);
+static void s_fake(mp_int z, mp_small value, mp_digit vbuf[]);
+static void s_ufake(mp_int z, mp_usmall value, mp_digit vbuf[]);
 
 /* Compare two runs of digits of given length, returns <0, 0, >0 */
 static int	s_cdig(mp_digit *da, mp_digit *db, mp_size len);
 
 /* Pack the unsigned digits of v into array t */
-static int	s_vpack(int v, mp_digit t[]);
+static int	s_uvpack(mp_usmall v, mp_digit t[]);
 
 /* Compare magnitudes of a and b, returns <0, 0, >0 */
 static int	s_ucmp(mp_int a, mp_int b);
 
 /* Compare magnitudes of a and v, returns <0, 0, >0 */
-static int	s_vcmp(mp_int a, int v);
+static int	s_vcmp(mp_int a, mp_small v);
+static int	s_uvcmp(mp_int a, mp_usmall uv);
 
 /* Unsigned magnitude addition; assumes dc is big enough.
    Carry out is returned (no memory allocated). */
-static mp_digit s_uadd(mp_digit *da, mp_digit *db, mp_digit *dc,
-	   mp_size size_a, mp_size size_b);
+static mp_digit s_uadd(mp_digit *da, mp_digit *db, mp_digit *dc, mp_size size_a,
+	   mp_size size_b);
 
 /* Unsigned magnitude subtraction.  Assumes dc is big enough. */
-static void s_usub(mp_digit *da, mp_digit *db, mp_digit *dc,
-	   mp_size size_a, mp_size size_b);
+static void s_usub(mp_digit *da, mp_digit *db, mp_digit *dc, mp_size size_a,
+	   mp_size size_b);
 
 /* Unsigned recursive multiplication.  Assumes dc is big enough. */
-static int s_kmul(mp_digit *da, mp_digit *db, mp_digit *dc,
-	   mp_size size_a, mp_size size_b);
+static int s_kmul(mp_digit *da, mp_digit *db, mp_digit *dc, mp_size size_a,
+	   mp_size size_b);
 
 /* Unsigned magnitude multiplication.  Assumes dc is big enough. */
-static void s_umul(mp_digit *da, mp_digit *db, mp_digit *dc,
-	   mp_size size_a, mp_size size_b);
+static void s_umul(mp_digit *da, mp_digit *db, mp_digit *dc, mp_size size_a,
+	   mp_size size_b);
 
 /* Unsigned recursive squaring.  Assumes dc is big enough. */
 static int	s_ksqr(mp_digit *da, mp_digit *dc, mp_size size_a);
@@ -236,8 +319,7 @@ static void s_dadd(mp_int a, mp_digit b);
 static void s_dmul(mp_int a, mp_digit b);
 
 /* Single digit multiplication on buffers; assumes dc is big enough. */
-static void s_dbmul(mp_digit *da, mp_digit b, mp_digit *dc,
-		mp_size size_a);
+static void s_dbmul(mp_digit *da, mp_digit b, mp_digit *dc, mp_size size_a);
 
 /* Single digit division.  Replaces a with the quotient,
    returns the remainder.  */
@@ -264,7 +346,7 @@ static int	s_dp2k(mp_int z);
 static int	s_isp2(mp_int z);
 
 /* Set z to 2^k.  May allocate; returns false in case this fails. */
-static int	s_2expt(mp_int z, int k);
+static int	s_2expt(mp_int z, mp_small k);
 
 /* Normalize a and b for division, returns normalization constant */
 static int	s_norm(mp_int a, mp_int b);
@@ -279,17 +361,17 @@ static int	s_reduce(mp_int x, mp_int m, mp_int mu, mp_int q1, mp_int q2);
 /* Modular exponentiation, using Barrett reduction */
 static mp_result s_embar(mp_int a, mp_int b, mp_int m, mp_int mu, mp_int c);
 
-/* Unsigned magnitude division.  Assumes |a| > |b|.  Allocates
-   temporaries; overwrites a with quotient, b with remainder. */
-static mp_result s_udiv(mp_int a, mp_int b);
+/* Unsigned magnitude division.  Assumes |a| > |b|.  Allocates temporaries;
+   overwrites a with quotient, b with remainder. */
+static mp_result s_udiv_knuth(mp_int a, mp_int b);
 
-/* Compute the number of digits in radix r required to represent the
-   given value.  Does not account for sign flags, terminators, etc. */
+/* Compute the number of digits in radix r required to represent the given
+   value.  Does not account for sign flags, terminators, etc. */
 static int	s_outlen(mp_int z, mp_size r);
 
-/* Guess how many digits of precision will be needed to represent a
-   radix r value of the specified number of digits.  Returns a value
-   guaranteed to be no smaller than the actual number required. */
+/* Guess how many digits of precision will be needed to represent a radix r
+   value of the specified number of digits.  Returns a value guaranteed to be
+   no smaller than the actual number required. */
 static mp_size s_inlen(int len, mp_size r);
 
 /* Convert a character to a digit value in radix r, or
@@ -302,177 +384,161 @@ static char s_val2ch(int v, int caps);
 /* Take 2's complement of a buffer in place */
 static void s_2comp(unsigned char *buf, int len);
 
-/* Convert a value to binary, ignoring sign.  On input, *limpos is the
-   bound on how many bytes should be written to buf; on output, *limpos
-   is set to the number of bytes actually written. */
+/* Convert a value to binary, ignoring sign.  On input, *limpos is the bound on
+   how many bytes should be written to buf; on output, *limpos is set to the
+   number of bytes actually written. */
 static mp_result s_tobin(mp_int z, unsigned char *buf, int *limpos, int pad);
 
-#if 0
-/* Dump a representation of the mp_int to standard output */
-void		s_print(char *tag, mp_int z);
-void		s_print_buf(char *tag, mp_digit *buf, mp_size num);
-#endif
-
-/* {{{ get_default_precision() */
-
-mp_size
-mp_get_default_precision(void)
-{
-	return default_precision;
-}
-
-/* }}} */
-
-/* {{{ mp_set_default_precision(s) */
-
-void
-mp_set_default_precision(mp_size s)
+/* Multiply X by Y into Z, ignoring signs.  Requires that Z have enough storage
+   preallocated to hold the result. */
+static inline void
+UMUL(mp_int X, mp_int Y, mp_int Z)
 {
-	NRCHECK(s > 0);
+	mp_size		ua_ = MP_USED(X);
+	mp_size		ub_ = MP_USED(Y);
+	mp_size		o_ = ua_ + ub_;
 
-	default_precision = (mp_size) ROUND_PREC(s);
+	ZERO(MP_DIGITS(Z), o_);
+	(void) s_kmul(MP_DIGITS(X), MP_DIGITS(Y), MP_DIGITS(Z), ua_, ub_);
+	Z->used = o_;
+	CLAMP(Z);
 }
 
-/* }}} */
-
-/* {{{ mp_get_multiply_threshold() */
-
-mp_size
-mp_get_multiply_threshold(void)
+/* Square X into Z.  Requires that Z have enough storage to hold the result. */
+static inline void
+USQR(mp_int X, mp_int Z)
 {
-	return multiply_threshold;
-}
-
-/* }}} */
+	mp_size		ua_ = MP_USED(X);
+	mp_size		o_ = ua_ + ua_;
 
-/* {{{ mp_set_multiply_threshold(s) */
-
-void
-mp_set_multiply_threshold(mp_size s)
-{
-	multiply_threshold = s;
+	ZERO(MP_DIGITS(Z), o_);
+	(void) s_ksqr(MP_DIGITS(X), MP_DIGITS(Z), ua_);
+	Z->used = o_;
+	CLAMP(Z);
 }
 
-/* }}} */
-
-/* {{{ mp_int_init(z) */
-
 mp_result
 mp_int_init(mp_int z)
 {
-	return mp_int_init_size(z, default_precision);
-}
+	if (z == NULL)
+		return MP_BADARG;
 
-/* }}} */
+	z->single = 0;
+	z->digits = &(z->single);
+	z->alloc = 1;
+	z->used = 1;
+	z->sign = MP_ZPOS;
 
-/* {{{ mp_int_alloc() */
+	return MP_OK;
+}
 
 mp_int
 mp_int_alloc(void)
 {
-	mp_int		out = px_alloc(sizeof(mpz_t));
+	mp_int		out = malloc(sizeof(mpz_t));
 
-	assert(out != NULL);
-	out->digits = NULL;
-	out->used = 0;
-	out->alloc = 0;
-	out->sign = 0;
+	if (out != NULL)
+		mp_int_init(out);
 
 	return out;
 }
 
-/* }}} */
-
-/* {{{ mp_int_init_size(z, prec) */
-
 mp_result
 mp_int_init_size(mp_int z, mp_size prec)
 {
-	CHECK(z != NULL);
+	assert(z != NULL);
 
-	prec = (mp_size) ROUND_PREC(prec);
-	prec = MAX(prec, default_precision);
+	if (prec == 0)
+	{
+		prec = default_precision;
+	}
+	else if (prec == 1)
+	{
+		return mp_int_init(z);
+	}
+	else
+	{
+		prec = s_round_prec(prec);
+	}
 
-	if ((MP_DIGITS(z) = s_alloc(prec)) == NULL)
+	z->digits = s_alloc(prec);
+	if (MP_DIGITS(z) == NULL)
 		return MP_MEMORY;
 
 	z->digits[0] = 0;
-	MP_USED(z) = 1;
-	MP_ALLOC(z) = prec;
-	MP_SIGN(z) = MP_ZPOS;
+	z->used = 1;
+	z->alloc = prec;
+	z->sign = MP_ZPOS;
 
 	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_init_copy(z, old) */
-
 mp_result
 mp_int_init_copy(mp_int z, mp_int old)
 {
-	mp_result	res;
-	mp_size		uold,
-				target;
+	assert(z != NULL && old != NULL);
 
-	CHECK(z != NULL && old != NULL);
+	mp_size		uold = MP_USED(old);
 
-	uold = MP_USED(old);
-	target = MAX(uold, default_precision);
+	if (uold == 1)
+	{
+		mp_int_init(z);
+	}
+	else
+	{
+		mp_size		target = MAX(uold, default_precision);
+		mp_result	res = mp_int_init_size(z, target);
 
-	if ((res = mp_int_init_size(z, target)) != MP_OK)
-		return res;
+		if (res != MP_OK)
+			return res;
+	}
 
-	MP_USED(z) = uold;
-	MP_SIGN(z) = MP_SIGN(old);
+	z->used = uold;
+	z->sign = old->sign;
 	COPY(MP_DIGITS(old), MP_DIGITS(z), uold);
 
 	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_init_value(z, value) */
-
 mp_result
-mp_int_init_value(mp_int z, int value)
+mp_int_init_value(mp_int z, mp_small value)
 {
-	mp_result	res;
-
-	CHECK(z != NULL);
-
-	if ((res = mp_int_init(z)) != MP_OK)
-		return res;
+	mpz_t		vtmp;
+	mp_digit	vbuf[MP_VALUE_DIGITS(value)];
 
-	return mp_int_set_value(z, value);
+	s_fake(&vtmp, value, vbuf);
+	return mp_int_init_copy(z, &vtmp);
 }
 
-/* }}} */
-
-/* {{{ mp_int_set_value(z, value) */
-
 mp_result
-mp_int_set_value(mp_int z, int value)
+mp_int_init_uvalue(mp_int z, mp_usmall uvalue)
 {
-	mp_size		ndig;
-
-	CHECK(z != NULL);
-
-	/* How many digits to copy */
-	ndig = (mp_size) MP_VALUE_DIGITS(value);
+	mpz_t		vtmp;
+	mp_digit	vbuf[MP_VALUE_DIGITS(uvalue)];
 
-	if (!s_pad(z, ndig))
-		return MP_MEMORY;
+	s_ufake(&vtmp, uvalue, vbuf);
+	return mp_int_init_copy(z, &vtmp);
+}
 
-	MP_USED(z) = (mp_size) s_vpack(value, MP_DIGITS(z));
-	MP_SIGN(z) = (value < 0) ? MP_NEG : MP_ZPOS;
+mp_result
+mp_int_set_value(mp_int z, mp_small value)
+{
+	mpz_t		vtmp;
+	mp_digit	vbuf[MP_VALUE_DIGITS(value)];
 
-	return MP_OK;
+	s_fake(&vtmp, value, vbuf);
+	return mp_int_copy(&vtmp, z);
 }
 
-/* }}} */
+mp_result
+mp_int_set_uvalue(mp_int z, mp_usmall uvalue)
+{
+	mpz_t		vtmp;
+	mp_digit	vbuf[MP_VALUE_DIGITS(uvalue)];
 
-/* {{{ mp_int_clear(z) */
+	s_ufake(&vtmp, uvalue, vbuf);
+	return mp_int_copy(&vtmp, z);
+}
 
 void
 mp_int_clear(mp_int z)
@@ -482,34 +548,26 @@ mp_int_clear(mp_int z)
 
 	if (MP_DIGITS(z) != NULL)
 	{
-		s_free(MP_DIGITS(z));
-		MP_DIGITS(z) = NULL;
+		if (MP_DIGITS(z) != &(z->single))
+			s_free(MP_DIGITS(z));
+
+		z->digits = NULL;
 	}
 }
 
-/* }}} */
-
-/* {{{ mp_int_free(z) */
-
 void
 mp_int_free(mp_int z)
 {
-	NRCHECK(z != NULL);
+	assert(z != NULL);
 
-	if (z->digits != NULL)
-		mp_int_clear(z);
-
-	px_free(z);
+	mp_int_clear(z);
+	free(z);					/* note: NOT s_free() */
 }
 
-/* }}} */
-
-/* {{{ mp_int_copy(a, c) */
-
 mp_result
 mp_int_copy(mp_int a, mp_int c)
 {
-	CHECK(a != NULL && c != NULL);
+	assert(a != NULL && c != NULL);
 
 	if (a != c)
 	{
@@ -524,17 +582,13 @@ mp_int_copy(mp_int a, mp_int c)
 		dc = MP_DIGITS(c);
 		COPY(da, dc, ua);
 
-		MP_USED(c) = ua;
-		MP_SIGN(c) = MP_SIGN(a);
+		c->used = ua;
+		c->sign = a->sign;
 	}
 
 	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_swap(a, c) */
-
 void
 mp_int_swap(mp_int a, mp_int c)
 {
@@ -544,90 +598,71 @@ mp_int_swap(mp_int a, mp_int c)
 
 		*a = *c;
 		*c = tmp;
+
+		if (MP_DIGITS(a) == &(c->single))
+			a->digits = &(a->single);
+		if (MP_DIGITS(c) == &(a->single))
+			c->digits = &(c->single);
 	}
 }
 
-/* }}} */
-
-/* {{{ mp_int_zero(z) */
-
 void
 mp_int_zero(mp_int z)
 {
-	NRCHECK(z != NULL);
+	assert(z != NULL);
 
 	z->digits[0] = 0;
-	MP_USED(z) = 1;
-	MP_SIGN(z) = MP_ZPOS;
+	z->used = 1;
+	z->sign = MP_ZPOS;
 }
 
-/* }}} */
-
-/* {{{ mp_int_abs(a, c) */
-
 mp_result
 mp_int_abs(mp_int a, mp_int c)
 {
-	mp_result	res;
+	assert(a != NULL && c != NULL);
 
-	CHECK(a != NULL && c != NULL);
+	mp_result	res;
 
 	if ((res = mp_int_copy(a, c)) != MP_OK)
 		return res;
 
-	MP_SIGN(c) = MP_ZPOS;
+	c->sign = MP_ZPOS;
 	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_neg(a, c) */
-
 mp_result
 mp_int_neg(mp_int a, mp_int c)
 {
-	mp_result	res;
+	assert(a != NULL && c != NULL);
 
-	CHECK(a != NULL && c != NULL);
+	mp_result	res;
 
 	if ((res = mp_int_copy(a, c)) != MP_OK)
 		return res;
 
 	if (CMPZ(c) != 0)
-		MP_SIGN(c) = 1 - MP_SIGN(a);
+		c->sign = 1 - MP_SIGN(a);
 
 	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_add(a, b, c) */
-
 mp_result
 mp_int_add(mp_int a, mp_int b, mp_int c)
 {
-	mp_size		ua,
-				ub,
-				uc,
-				max;
+	assert(a != NULL && b != NULL && c != NULL);
 
-	CHECK(a != NULL && b != NULL && c != NULL);
-
-	ua = MP_USED(a);
-	ub = MP_USED(b);
-	uc = MP_USED(c);
-	max = MAX(ua, ub);
+	mp_size		ua = MP_USED(a);
+	mp_size		ub = MP_USED(b);
+	mp_size		max = MAX(ua, ub);
 
 	if (MP_SIGN(a) == MP_SIGN(b))
 	{
 		/* Same sign -- add magnitudes, preserve sign of addends */
-		mp_digit	carry;
-
 		if (!s_pad(c, max))
 			return MP_MEMORY;
 
-		carry = s_uadd(MP_DIGITS(a), MP_DIGITS(b), MP_DIGITS(c), ua, ub);
-		uc = max;
+		mp_digit	carry = s_uadd(MP_DIGITS(a), MP_DIGITS(b), MP_DIGITS(c), ua, ub);
+		mp_size		uc = max;
 
 		if (carry)
 		{
@@ -638,50 +673,55 @@ mp_int_add(mp_int a, mp_int b, mp_int c)
 			++uc;
 		}
 
-		MP_USED(c) = uc;
-		MP_SIGN(c) = MP_SIGN(a);
+		c->used = uc;
+		c->sign = a->sign;
 
 	}
 	else
 	{
 		/* Different signs -- subtract magnitudes, preserve sign of greater */
+		int			cmp = s_ucmp(a, b); /* magnitude comparision, sign ignored */
+
+		/*
+		 * Set x to max(a, b), y to min(a, b) to simplify later code. A
+		 * special case yields zero for equal magnitudes.
+		 */
 		mp_int		x,
 					y;
-		int			cmp = s_ucmp(a, b); /* magnitude comparison, sign ignored */
 
-		/* Set x to max(a, b), y to min(a, b) to simplify later code */
-		if (cmp >= 0)
+		if (cmp == 0)
 		{
-			x = a;
-			y = b;
+			mp_int_zero(c);
+			return MP_OK;
 		}
-		else
+		else if (cmp < 0)
 		{
 			x = b;
 			y = a;
 		}
+		else
+		{
+			x = a;
+			y = b;
+		}
 
 		if (!s_pad(c, MP_USED(x)))
 			return MP_MEMORY;
 
 		/* Subtract smaller from larger */
 		s_usub(MP_DIGITS(x), MP_DIGITS(y), MP_DIGITS(c), MP_USED(x), MP_USED(y));
-		MP_USED(c) = MP_USED(x);
+		c->used = x->used;
 		CLAMP(c);
 
 		/* Give result the sign of the larger */
-		MP_SIGN(c) = MP_SIGN(x);
+		c->sign = x->sign;
 	}
 
 	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_add_value(a, value, c) */
-
 mp_result
-mp_int_add_value(mp_int a, int value, mp_int c)
+mp_int_add_value(mp_int a, mp_small value, mp_int c)
 {
 	mpz_t		vtmp;
 	mp_digit	vbuf[MP_VALUE_DIGITS(value)];
@@ -691,35 +731,23 @@ mp_int_add_value(mp_int a, int value, mp_int c)
 	return mp_int_add(a, &vtmp, c);
 }
 
-/* }}} */
-
-/* {{{ mp_int_sub(a, b, c) */
-
 mp_result
 mp_int_sub(mp_int a, mp_int b, mp_int c)
 {
-	mp_size		ua,
-				ub,
-				uc,
-				max;
-
-	CHECK(a != NULL && b != NULL && c != NULL);
+	assert(a != NULL && b != NULL && c != NULL);
 
-	ua = MP_USED(a);
-	ub = MP_USED(b);
-	uc = MP_USED(c);
-	max = MAX(ua, ub);
+	mp_size		ua = MP_USED(a);
+	mp_size		ub = MP_USED(b);
+	mp_size		max = MAX(ua, ub);
 
 	if (MP_SIGN(a) != MP_SIGN(b))
 	{
 		/* Different signs -- add magnitudes and keep sign of a */
-		mp_digit	carry;
-
 		if (!s_pad(c, max))
 			return MP_MEMORY;
 
-		carry = s_uadd(MP_DIGITS(a), MP_DIGITS(b), MP_DIGITS(c), ua, ub);
-		uc = max;
+		mp_digit	carry = s_uadd(MP_DIGITS(a), MP_DIGITS(b), MP_DIGITS(c), ua, ub);
+		mp_size		uc = max;
 
 		if (carry)
 		{
@@ -730,20 +758,20 @@ mp_int_sub(mp_int a, mp_int b, mp_int c)
 			++uc;
 		}
 
-		MP_USED(c) = uc;
-		MP_SIGN(c) = MP_SIGN(a);
+		c->used = uc;
+		c->sign = a->sign;
 
 	}
 	else
 	{
 		/* Same signs -- subtract magnitudes */
+		if (!s_pad(c, max))
+			return MP_MEMORY;
 		mp_int		x,
 					y;
 		mp_sign		osign;
-		int			cmp = s_ucmp(a, b);
 
-		if (!s_pad(c, max))
-			return MP_MEMORY;
+		int			cmp = s_ucmp(a, b);
 
 		if (cmp >= 0)
 		{
@@ -762,21 +790,17 @@ mp_int_sub(mp_int a, mp_int b, mp_int c)
 			osign = 1 - osign;
 
 		s_usub(MP_DIGITS(x), MP_DIGITS(y), MP_DIGITS(c), MP_USED(x), MP_USED(y));
-		MP_USED(c) = MP_USED(x);
+		c->used = x->used;
 		CLAMP(c);
 
-		MP_SIGN(c) = osign;
+		c->sign = osign;
 	}
 
 	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_sub_value(a, value, c) */
-
 mp_result
-mp_int_sub_value(mp_int a, int value, mp_int c)
+mp_int_sub_value(mp_int a, mp_small value, mp_int c)
 {
 	mpz_t		vtmp;
 	mp_digit	vbuf[MP_VALUE_DIGITS(value)];
@@ -786,21 +810,10 @@ mp_int_sub_value(mp_int a, int value, mp_int c)
 	return mp_int_sub(a, &vtmp, c);
 }
 
-/* }}} */
-
-/* {{{ mp_int_mul(a, b, c) */
-
 mp_result
 mp_int_mul(mp_int a, mp_int b, mp_int c)
 {
-	mp_digit   *out;
-	mp_size		osize,
-				ua,
-				ub,
-				p = 0;
-	mp_sign		osign;
-
-	CHECK(a != NULL && b != NULL && c != NULL);
+	assert(a != NULL && b != NULL && c != NULL);
 
 	/* If either input is zero, we can shortcut multiplication */
 	if (mp_int_compare_zero(a) == 0 || mp_int_compare_zero(b) == 0)
@@ -810,21 +823,24 @@ mp_int_mul(mp_int a, mp_int b, mp_int c)
 	}
 
 	/* Output is positive if inputs have same sign, otherwise negative */
-	osign = (MP_SIGN(a) == MP_SIGN(b)) ? MP_ZPOS : MP_NEG;
+	mp_sign		osign = (MP_SIGN(a) == MP_SIGN(b)) ? MP_ZPOS : MP_NEG;
 
 	/*
-	 * If the output is not equal to any of the inputs, we'll write the
-	 * results there directly; otherwise, allocate a temporary space.
+	 * If the output is not identical to any of the inputs, we'll write the
+	 * results directly; otherwise, allocate a temporary space.
 	 */
-	ua = MP_USED(a);
-	ub = MP_USED(b);
-	osize = MAX(ua, ub);
+	mp_size		ua = MP_USED(a);
+	mp_size		ub = MP_USED(b);
+	mp_size		osize = MAX(ua, ub);
+
 	osize = 4 * ((osize + 1) / 2);
 
+	mp_digit   *out;
+	mp_size		p = 0;
+
 	if (c == a || c == b)
 	{
-		p = ROUND_PREC(osize);
-		p = MAX(p, default_precision);
+		p = MAX(s_round_prec(osize), default_precision);
 
 		if ((out = s_alloc(p)) == NULL)
 			return MP_MEMORY;
@@ -847,24 +863,21 @@ mp_int_mul(mp_int a, mp_int b, mp_int c)
 	 */
 	if (out != MP_DIGITS(c))
 	{
-		s_free(MP_DIGITS(c));
-		MP_DIGITS(c) = out;
-		MP_ALLOC(c) = p;
+		if ((void *) MP_DIGITS(c) != (void *) c)
+			s_free(MP_DIGITS(c));
+		c->digits = out;
+		c->alloc = p;
 	}
 
-	MP_USED(c) = osize;			/* might not be true, but we'll fix it ... */
+	c->used = osize;			/* might not be true, but we'll fix it ... */
 	CLAMP(c);					/* ... right here */
-	MP_SIGN(c) = osign;
+	c->sign = osign;
 
 	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_mul_value(a, value, c) */
-
 mp_result
-mp_int_mul_value(mp_int a, int value, mp_int c)
+mp_int_mul_value(mp_int a, mp_small value, mp_int c)
 {
 	mpz_t		vtmp;
 	mp_digit	vbuf[MP_VALUE_DIGITS(value)];
@@ -874,45 +887,39 @@ mp_int_mul_value(mp_int a, int value, mp_int c)
 	return mp_int_mul(a, &vtmp, c);
 }
 
-/* }}} */
-
-/* {{{ mp_int_mul_pow2(a, p2, c) */
-
 mp_result
-mp_int_mul_pow2(mp_int a, int p2, mp_int c)
+mp_int_mul_pow2(mp_int a, mp_small p2, mp_int c)
 {
-	mp_result	res;
+	assert(a != NULL && c != NULL && p2 >= 0);
 
-	CHECK(a != NULL && c != NULL && p2 >= 0);
+	mp_result	res = mp_int_copy(a, c);
 
-	if ((res = mp_int_copy(a, c)) != MP_OK)
+	if (res != MP_OK)
 		return res;
 
 	if (s_qmul(c, (mp_size) p2))
+	{
 		return MP_OK;
+	}
 	else
+	{
 		return MP_MEMORY;
+	}
 }
 
-/* }}} */
-
-/* {{{ mp_int_sqr(a, c) */
-
 mp_result
 mp_int_sqr(mp_int a, mp_int c)
 {
-	mp_digit   *out;
-	mp_size		osize,
-				p = 0;
-
-	CHECK(a != NULL && c != NULL);
+	assert(a != NULL && c != NULL);
 
 	/* Get a temporary buffer big enough to hold the result */
-	osize = (mp_size) 4 * ((MP_USED(a) + 1) / 2);
+	mp_size		osize = (mp_size) 4 * ((MP_USED(a) + 1) / 2);
+	mp_size		p = 0;
+	mp_digit   *out;
 
 	if (a == c)
 	{
-		p = ROUND_PREC(osize);
+		p = s_round_prec(osize);
 		p = MAX(p, default_precision);
 
 		if ((out = s_alloc(p)) == NULL)
@@ -935,39 +942,35 @@ mp_int_sqr(mp_int a, mp_int c)
 	 */
 	if (out != MP_DIGITS(c))
 	{
-		s_free(MP_DIGITS(c));
-		MP_DIGITS(c) = out;
-		MP_ALLOC(c) = p;
+		if ((void *) MP_DIGITS(c) != (void *) c)
+			s_free(MP_DIGITS(c));
+		c->digits = out;
+		c->alloc = p;
 	}
 
-	MP_USED(c) = osize;			/* might not be true, but we'll fix it ... */
+	c->used = osize;			/* might not be true, but we'll fix it ... */
 	CLAMP(c);					/* ... right here */
-	MP_SIGN(c) = MP_ZPOS;
+	c->sign = MP_ZPOS;
 
 	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_div(a, b, q, r) */
-
 mp_result
 mp_int_div(mp_int a, mp_int b, mp_int q, mp_int r)
 {
-	int			cmp,
-				last = 0,
-				lg;
+	assert(a != NULL && b != NULL && q != r);
+
+	int			cmp;
 	mp_result	res = MP_OK;
-	mpz_t		temp[2];
 	mp_int		qout,
 				rout;
-	mp_sign		sa = MP_SIGN(a),
-				sb = MP_SIGN(b);
-
-	CHECK(a != NULL && b != NULL && q != r);
+	mp_sign		sa = MP_SIGN(a);
+	mp_sign		sb = MP_SIGN(b);
 
 	if (CMPZ(b) == 0)
+	{
 		return MP_UNDEF;
+	}
 	else if ((cmp = s_ucmp(a, b)) < 0)
 	{
 		/*
@@ -995,7 +998,7 @@ mp_int_div(mp_int a, mp_int b, mp_int q, mp_int r)
 			q->digits[0] = 1;
 
 			if (sa != sb)
-				MP_SIGN(q) = MP_NEG;
+				q->sign = MP_NEG;
 		}
 
 		return MP_OK;
@@ -1006,37 +1009,41 @@ mp_int_div(mp_int a, mp_int b, mp_int q, mp_int r)
 	 * quotient and remainder, but q and r are allowed to be NULL or to
 	 * overlap with the inputs.
 	 */
+	DECLARE_TEMP(2);
+	int			lg;
+
 	if ((lg = s_isp2(b)) < 0)
 	{
-		if (q && b != q && (res = mp_int_copy(a, q)) == MP_OK)
+		if (q && b != q)
 		{
+			REQUIRE(mp_int_copy(a, q));
 			qout = q;
 		}
 		else
 		{
-			qout = TEMP(last);
-			SETUP(mp_int_init_copy(TEMP(last), a), last);
+			REQUIRE(mp_int_copy(a, TEMP(0)));
+			qout = TEMP(0);
 		}
 
-		if (r && a != r && (res = mp_int_copy(b, r)) == MP_OK)
+		if (r && a != r)
 		{
+			REQUIRE(mp_int_copy(b, r));
 			rout = r;
 		}
 		else
 		{
-			rout = TEMP(last);
-			SETUP(mp_int_init_copy(TEMP(last), b), last);
+			REQUIRE(mp_int_copy(b, TEMP(1)));
+			rout = TEMP(1);
 		}
 
-		if ((res = s_udiv(qout, rout)) != MP_OK)
-			goto CLEANUP;
+		REQUIRE(s_udiv_knuth(qout, rout));
 	}
 	else
 	{
-		if (q && (res = mp_int_copy(a, q)) != MP_OK)
-			goto CLEANUP;
-		if (r && (res = mp_int_copy(a, r)) != MP_OK)
-			goto CLEANUP;
+		if (q)
+			REQUIRE(mp_int_copy(a, q));
+		if (r)
+			REQUIRE(mp_int_copy(a, r));
 
 		if (q)
 			s_qdiv(q, (mp_size) lg);
@@ -1049,203 +1056,184 @@ mp_int_div(mp_int a, mp_int b, mp_int q, mp_int r)
 	/* Recompute signs for output */
 	if (rout)
 	{
-		MP_SIGN(rout) = sa;
+		rout->sign = sa;
 		if (CMPZ(rout) == 0)
-			MP_SIGN(rout) = MP_ZPOS;
+			rout->sign = MP_ZPOS;
 	}
 	if (qout)
 	{
-		MP_SIGN(qout) = (sa == sb) ? MP_ZPOS : MP_NEG;
+		qout->sign = (sa == sb) ? MP_ZPOS : MP_NEG;
 		if (CMPZ(qout) == 0)
-			MP_SIGN(qout) = MP_ZPOS;
+			qout->sign = MP_ZPOS;
 	}
 
-	if (q && (res = mp_int_copy(qout, q)) != MP_OK)
-		goto CLEANUP;
-	if (r && (res = mp_int_copy(rout, r)) != MP_OK)
-		goto CLEANUP;
-
-CLEANUP:
-	while (--last >= 0)
-		mp_int_clear(TEMP(last));
-
+	if (q)
+		REQUIRE(mp_int_copy(qout, q));
+	if (r)
+		REQUIRE(mp_int_copy(rout, r));
+	CLEANUP_TEMP();
 	return res;
 }
 
-/* }}} */
-
-/* {{{ mp_int_mod(a, m, c) */
-
 mp_result
 mp_int_mod(mp_int a, mp_int m, mp_int c)
 {
-	mp_result	res;
-	mpz_t		tmp;
-	mp_int		out;
+	DECLARE_TEMP(1);
+	mp_int		out = (m == c) ? TEMP(0) : c;
 
-	if (m == c)
+	REQUIRE(mp_int_div(a, m, NULL, out));
+	if (CMPZ(out) < 0)
 	{
-		if ((res = mp_int_init(&tmp)) != MP_OK)
-			return res;
-
-		out = &tmp;
+		REQUIRE(mp_int_add(out, m, c));
 	}
 	else
 	{
-		out = c;
+		REQUIRE(mp_int_copy(out, c));
 	}
-
-	if ((res = mp_int_div(a, m, NULL, out)) != MP_OK)
-		goto CLEANUP;
-
-	if (CMPZ(out) < 0)
-		res = mp_int_add(out, m, c);
-	else
-		res = mp_int_copy(out, c);
-
-CLEANUP:
-	if (out != c)
-		mp_int_clear(&tmp);
-
-	return res;
+	CLEANUP_TEMP();
+	return MP_OK;
 }
 
-/* }}} */
-
-
-/* {{{ mp_int_div_value(a, value, q, r) */
-
 mp_result
-mp_int_div_value(mp_int a, int value, mp_int q, int *r)
+mp_int_div_value(mp_int a, mp_small value, mp_int q, mp_small * r)
 {
-	mpz_t		vtmp,
-				rtmp;
+	mpz_t		vtmp;
 	mp_digit	vbuf[MP_VALUE_DIGITS(value)];
-	mp_result	res;
 
-	if ((res = mp_int_init(&rtmp)) != MP_OK)
-		return res;
 	s_fake(&vtmp, value, vbuf);
 
-	if ((res = mp_int_div(a, &vtmp, q, &rtmp)) != MP_OK)
-		goto CLEANUP;
+	DECLARE_TEMP(1);
+	REQUIRE(mp_int_div(a, &vtmp, q, TEMP(0)));
 
 	if (r)
-		(void) mp_int_to_int(&rtmp, r); /* can't fail */
+		(void) mp_int_to_int(TEMP(0), r);	/* can't fail */
 
-CLEANUP:
-	mp_int_clear(&rtmp);
-	return res;
+	CLEANUP_TEMP();
+	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_div_pow2(a, p2, q, r) */
-
 mp_result
-mp_int_div_pow2(mp_int a, int p2, mp_int q, mp_int r)
+mp_int_div_pow2(mp_int a, mp_small p2, mp_int q, mp_int r)
 {
-	mp_result	res = MP_OK;
+	assert(a != NULL && p2 >= 0 && q != r);
 
-	CHECK(a != NULL && p2 >= 0 && q != r);
+	mp_result	res = MP_OK;
 
 	if (q != NULL && (res = mp_int_copy(a, q)) == MP_OK)
+	{
 		s_qdiv(q, (mp_size) p2);
+	}
 
 	if (res == MP_OK && r != NULL && (res = mp_int_copy(a, r)) == MP_OK)
+	{
 		s_qmod(r, (mp_size) p2);
+	}
 
 	return res;
 }
 
-/* }}} */
-
-/* {{{ mp_int_expt(a, b, c) */
-
 mp_result
-mp_int_expt(mp_int a, int b, mp_int c)
+mp_int_expt(mp_int a, mp_small b, mp_int c)
 {
-	mpz_t		t;
-	mp_result	res;
-	unsigned int v = abs(b);
+	assert(c != NULL);
+	if (b < 0)
+		return MP_RANGE;
 
-	CHECK(b >= 0 && c != NULL);
-
-	if ((res = mp_int_init_copy(&t, a)) != MP_OK)
-		return res;
+	DECLARE_TEMP(1);
+	REQUIRE(mp_int_copy(a, TEMP(0)));
 
 	(void) mp_int_set_value(c, 1);
+	unsigned int v = labs(b);
+
 	while (v != 0)
 	{
 		if (v & 1)
 		{
-			if ((res = mp_int_mul(c, &t, c)) != MP_OK)
-				goto CLEANUP;
+			REQUIRE(mp_int_mul(c, TEMP(0), c));
 		}
 
 		v >>= 1;
 		if (v == 0)
 			break;
 
-		if ((res = mp_int_sqr(&t, &t)) != MP_OK)
-			goto CLEANUP;
+		REQUIRE(mp_int_sqr(TEMP(0), TEMP(0)));
 	}
 
-CLEANUP:
-	mp_int_clear(&t);
-	return res;
+	CLEANUP_TEMP();
+	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_expt_value(a, b, c) */
-
 mp_result
-mp_int_expt_value(int a, int b, mp_int c)
+mp_int_expt_value(mp_small a, mp_small b, mp_int c)
 {
-	mpz_t		t;
-	mp_result	res;
-	unsigned int v = abs(b);
-
-	CHECK(b >= 0 && c != NULL);
+	assert(c != NULL);
+	if (b < 0)
+		return MP_RANGE;
 
-	if ((res = mp_int_init_value(&t, a)) != MP_OK)
-		return res;
+	DECLARE_TEMP(1);
+	REQUIRE(mp_int_set_value(TEMP(0), a));
 
 	(void) mp_int_set_value(c, 1);
+	unsigned int v = labs(b);
+
 	while (v != 0)
 	{
 		if (v & 1)
 		{
-			if ((res = mp_int_mul(c, &t, c)) != MP_OK)
-				goto CLEANUP;
+			REQUIRE(mp_int_mul(c, TEMP(0), c));
 		}
 
 		v >>= 1;
 		if (v == 0)
 			break;
 
-		if ((res = mp_int_sqr(&t, &t)) != MP_OK)
-			goto CLEANUP;
+		REQUIRE(mp_int_sqr(TEMP(0), TEMP(0)));
 	}
 
-CLEANUP:
-	mp_int_clear(&t);
-	return res;
+	CLEANUP_TEMP();
+	return MP_OK;
 }
 
-/* }}} */
+mp_result
+mp_int_expt_full(mp_int a, mp_int b, mp_int c)
+{
+	assert(a != NULL && b != NULL && c != NULL);
+	if (MP_SIGN(b) == MP_NEG)
+		return MP_RANGE;
+
+	DECLARE_TEMP(1);
+	REQUIRE(mp_int_copy(a, TEMP(0)));
+
+	(void) mp_int_set_value(c, 1);
+	for (unsigned ix = 0; ix < MP_USED(b); ++ix)
+	{
+		mp_digit	d = b->digits[ix];
+
+		for (unsigned jx = 0; jx < MP_DIGIT_BIT; ++jx)
+		{
+			if (d & 1)
+			{
+				REQUIRE(mp_int_mul(c, TEMP(0), c));
+			}
+
+			d >>= 1;
+			if (d == 0 && ix + 1 == MP_USED(b))
+				break;
+			REQUIRE(mp_int_sqr(TEMP(0), TEMP(0)));
+		}
+	}
 
-/* {{{ mp_int_compare(a, b) */
+	CLEANUP_TEMP();
+	return MP_OK;
+}
 
 int
 mp_int_compare(mp_int a, mp_int b)
 {
-	mp_sign		sa;
+	assert(a != NULL && b != NULL);
 
-	CHECK(a != NULL && b != NULL);
+	mp_sign		sa = MP_SIGN(a);
 
-	sa = MP_SIGN(a);
 	if (sa == MP_SIGN(b))
 	{
 		int			cmp = s_ucmp(a, b);
@@ -1254,91 +1242,90 @@ mp_int_compare(mp_int a, mp_int b)
 		 * If they're both zero or positive, the normal comparison applies; if
 		 * both negative, the sense is reversed.
 		 */
-		if (sa != MP_ZPOS)
-			INVERT_COMPARE_RESULT(cmp);
-		return cmp;
+		if (sa == MP_ZPOS)
+		{
+			return cmp;
+		}
+		else
+		{
+			return -cmp;
+		}
+	}
+	else if (sa == MP_ZPOS)
+	{
+		return 1;
 	}
 	else
 	{
-		if (sa == MP_ZPOS)
-			return 1;
-		else
-			return -1;
+		return -1;
 	}
 }
 
-/* }}} */
-
-/* {{{ mp_int_compare_unsigned(a, b) */
-
 int
 mp_int_compare_unsigned(mp_int a, mp_int b)
 {
-	NRCHECK(a != NULL && b != NULL);
+	assert(a != NULL && b != NULL);
 
 	return s_ucmp(a, b);
 }
 
-/* }}} */
-
-/* {{{ mp_int_compare_zero(z) */
-
 int
 mp_int_compare_zero(mp_int z)
 {
-	NRCHECK(z != NULL);
+	assert(z != NULL);
 
 	if (MP_USED(z) == 1 && z->digits[0] == 0)
+	{
 		return 0;
+	}
 	else if (MP_SIGN(z) == MP_ZPOS)
+	{
 		return 1;
+	}
 	else
+	{
 		return -1;
+	}
 }
 
-/* }}} */
-
-/* {{{ mp_int_compare_value(z, value) */
-
 int
-mp_int_compare_value(mp_int z, int value)
+mp_int_compare_value(mp_int z, mp_small value)
 {
-	mp_sign		vsign = (value < 0) ? MP_NEG : MP_ZPOS;
-	int			cmp;
+	assert(z != NULL);
 
-	CHECK(z != NULL);
+	mp_sign		vsign = (value < 0) ? MP_NEG : MP_ZPOS;
 
 	if (vsign == MP_SIGN(z))
 	{
-		cmp = s_vcmp(z, value);
+		int			cmp = s_vcmp(z, value);
 
-		if (vsign != MP_ZPOS)
-			INVERT_COMPARE_RESULT(cmp);
-		return cmp;
+		return (vsign == MP_ZPOS) ? cmp : -cmp;
 	}
 	else
 	{
-		if (value < 0)
-			return 1;
-		else
-			return -1;
+		return (value < 0) ? 1 : -1;
 	}
 }
 
-/* }}} */
+int
+mp_int_compare_uvalue(mp_int z, mp_usmall uv)
+{
+	assert(z != NULL);
 
-/* {{{ mp_int_exptmod(a, b, m, c) */
+	if (MP_SIGN(z) == MP_NEG)
+	{
+		return -1;
+	}
+	else
+	{
+		return s_uvcmp(z, uv);
+	}
+}
 
 mp_result
 mp_int_exptmod(mp_int a, mp_int b, mp_int m, mp_int c)
 {
-	mp_result	res;
-	mp_size		um;
-	mpz_t		temp[3];
-	mp_int		s;
-	int			last = 0;
-
-	CHECK(a != NULL && b != NULL && c != NULL && m != NULL);
+	assert(a != NULL && b != NULL && c != NULL && m != NULL);
 
 	/* Zero moduli and negative exponents are not considered. */
 	if (CMPZ(m) == 0)
@@ -1346,13 +1333,17 @@ mp_int_exptmod(mp_int a, mp_int b, mp_int m, mp_int c)
 	if (CMPZ(b) < 0)
 		return MP_RANGE;
 
-	um = MP_USED(m);
-	SETUP(mp_int_init_size(TEMP(0), 2 * um), last);
-	SETUP(mp_int_init_size(TEMP(1), 2 * um), last);
+	mp_size		um = MP_USED(m);
+
+	DECLARE_TEMP(3);
+	REQUIRE(GROW(TEMP(0), 2 * um));
+	REQUIRE(GROW(TEMP(1), 2 * um));
+
+	mp_int		s;
 
 	if (c == b || c == m)
 	{
-		SETUP(mp_int_init_size(TEMP(2), 2 * um), last);
+		REQUIRE(GROW(TEMP(2), 2 * um));
 		s = TEMP(2);
 	}
 	else
@@ -1360,30 +1351,17 @@ mp_int_exptmod(mp_int a, mp_int b, mp_int m, mp_int c)
 		s = c;
 	}
 
-	if ((res = mp_int_mod(a, m, TEMP(0))) != MP_OK)
-		goto CLEANUP;
-
-	if ((res = s_brmu(TEMP(1), m)) != MP_OK)
-		goto CLEANUP;
-
-	if ((res = s_embar(TEMP(0), b, m, TEMP(1), s)) != MP_OK)
-		goto CLEANUP;
-
-	res = mp_int_copy(s, c);
+	REQUIRE(mp_int_mod(a, m, TEMP(0)));
+	REQUIRE(s_brmu(TEMP(1), m));
+	REQUIRE(s_embar(TEMP(0), b, m, TEMP(1), s));
+	REQUIRE(mp_int_copy(s, c));
 
-CLEANUP:
-	while (--last >= 0)
-		mp_int_clear(TEMP(last));
-
-	return res;
+	CLEANUP_TEMP();
+	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_exptmod_evalue(a, value, m, c) */
-
 mp_result
-mp_int_exptmod_evalue(mp_int a, int value, mp_int m, mp_int c)
+mp_int_exptmod_evalue(mp_int a, mp_small value, mp_int m, mp_int c)
 {
 	mpz_t		vtmp;
 	mp_digit	vbuf[MP_VALUE_DIGITS(value)];
@@ -1393,13 +1371,8 @@ mp_int_exptmod_evalue(mp_int a, int value, mp_int m, mp_int c)
 	return mp_int_exptmod(a, &vtmp, m, c);
 }
 
-/* }}} */
-
-/* {{{ mp_int_exptmod_bvalue(v, b, m, c) */
-
 mp_result
-mp_int_exptmod_bvalue(int value, mp_int b,
-					  mp_int m, mp_int c)
+mp_int_exptmod_bvalue(mp_small value, mp_int b, mp_int m, mp_int c)
 {
 	mpz_t		vtmp;
 	mp_digit	vbuf[MP_VALUE_DIGITS(value)];
@@ -1409,20 +1382,11 @@ mp_int_exptmod_bvalue(int value, mp_int b,
 	return mp_int_exptmod(&vtmp, b, m, c);
 }
 
-/* }}} */
-
-/* {{{ mp_int_exptmod_known(a, b, m, mu, c) */
-
 mp_result
-mp_int_exptmod_known(mp_int a, mp_int b, mp_int m, mp_int mu, mp_int c)
+mp_int_exptmod_known(mp_int a, mp_int b, mp_int m, mp_int mu,
+					 mp_int c)
 {
-	mp_result	res;
-	mp_size		um;
-	mpz_t		temp[2];
-	mp_int		s;
-	int			last = 0;
-
-	CHECK(a && b && m && c);
+	assert(a && b && m && c);
 
 	/* Zero moduli and negative exponents are not considered. */
 	if (CMPZ(m) == 0)
@@ -1430,12 +1394,16 @@ mp_int_exptmod_known(mp_int a, mp_int b, mp_int m, mp_int mu, mp_int c)
 	if (CMPZ(b) < 0)
 		return MP_RANGE;
 
-	um = MP_USED(m);
-	SETUP(mp_int_init_size(TEMP(0), 2 * um), last);
+	DECLARE_TEMP(2);
+	mp_size		um = MP_USED(m);
+
+	REQUIRE(GROW(TEMP(0), 2 * um));
+
+	mp_int		s;
 
 	if (c == b || c == m)
 	{
-		SETUP(mp_int_init_size(TEMP(1), 2 * um), last);
+		REQUIRE(GROW(TEMP(1), 2 * um));
 		s = TEMP(1);
 	}
 	else
@@ -1443,68 +1411,41 @@ mp_int_exptmod_known(mp_int a, mp_int b, mp_int m, mp_int mu, mp_int c)
 		s = c;
 	}
 
-	if ((res = mp_int_mod(a, m, TEMP(0))) != MP_OK)
-		goto CLEANUP;
-
-	if ((res = s_embar(TEMP(0), b, m, mu, s)) != MP_OK)
-		goto CLEANUP;
+	REQUIRE(mp_int_mod(a, m, TEMP(0)));
+	REQUIRE(s_embar(TEMP(0), b, m, mu, s));
+	REQUIRE(mp_int_copy(s, c));
 
-	res = mp_int_copy(s, c);
-
-CLEANUP:
-	while (--last >= 0)
-		mp_int_clear(TEMP(last));
-
-	return res;
+	CLEANUP_TEMP();
+	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_redux_const(m, c) */
-
 mp_result
 mp_int_redux_const(mp_int m, mp_int c)
 {
-	CHECK(m != NULL && c != NULL && m != c);
+	assert(m != NULL && c != NULL && m != c);
 
 	return s_brmu(c, m);
 }
 
-/* }}} */
-
-/* {{{ mp_int_invmod(a, m, c) */
-
 mp_result
 mp_int_invmod(mp_int a, mp_int m, mp_int c)
 {
-	mp_result	res;
-	mp_sign		sa;
-	int			last = 0;
-	mpz_t		temp[2];
-
-	CHECK(a != NULL && m != NULL && c != NULL);
+	assert(a != NULL && m != NULL && c != NULL);
 
 	if (CMPZ(a) == 0 || CMPZ(m) <= 0)
 		return MP_RANGE;
 
-	sa = MP_SIGN(a);			/* need this for the result later */
+	DECLARE_TEMP(2);
 
-	for (last = 0; last < 2; ++last)
-		if ((res = mp_int_init(TEMP(last))) != MP_OK)
-			goto CLEANUP;
-
-	if ((res = mp_int_egcd(a, m, TEMP(0), TEMP(1), NULL)) != MP_OK)
-		goto CLEANUP;
+	REQUIRE(mp_int_egcd(a, m, TEMP(0), TEMP(1), NULL));
 
 	if (mp_int_compare_value(TEMP(0), 1) != 0)
 	{
-		res = MP_UNDEF;
-		goto CLEANUP;
+		REQUIRE(MP_UNDEF);
 	}
 
 	/* It is first necessary to constrain the value to the proper range */
-	if ((res = mp_int_mod(TEMP(1), m, TEMP(1))) != MP_OK)
-		goto CLEANUP;
+	REQUIRE(mp_int_mod(TEMP(1), m, TEMP(1)));
 
 	/*
 	 * Now, if 'a' was originally negative, the value we have is actually the
@@ -1512,136 +1453,112 @@ mp_int_invmod(mp_int a, mp_int m, mp_int c)
 	 * have to subtract from the modulus.  Otherwise, the value is okay as it
 	 * stands.
 	 */
-	if (sa == MP_NEG)
-		res = mp_int_sub(m, TEMP(1), c);
+	if (MP_SIGN(a) == MP_NEG)
+	{
+		REQUIRE(mp_int_sub(m, TEMP(1), c));
+	}
 	else
-		res = mp_int_copy(TEMP(1), c);
-
-CLEANUP:
-	while (--last >= 0)
-		mp_int_clear(TEMP(last));
+	{
+		REQUIRE(mp_int_copy(TEMP(1), c));
+	}
 
-	return res;
+	CLEANUP_TEMP();
+	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_gcd(a, b, c) */
-
 /* Binary GCD algorithm due to Josef Stein, 1961 */
 mp_result
 mp_int_gcd(mp_int a, mp_int b, mp_int c)
 {
-	int			ca,
-				cb,
-				k = 0;
-	mpz_t		u,
-				v,
-				t;
-	mp_result	res;
+	assert(a != NULL && b != NULL && c != NULL);
 
-	CHECK(a != NULL && b != NULL && c != NULL);
+	int			ca = CMPZ(a);
+	int			cb = CMPZ(b);
 
-	ca = CMPZ(a);
-	cb = CMPZ(b);
 	if (ca == 0 && cb == 0)
+	{
 		return MP_UNDEF;
+	}
 	else if (ca == 0)
+	{
 		return mp_int_abs(b, c);
+	}
 	else if (cb == 0)
+	{
 		return mp_int_abs(a, c);
+	}
 
-	if ((res = mp_int_init(&t)) != MP_OK)
-		return res;
-	if ((res = mp_int_init_copy(&u, a)) != MP_OK)
-		goto U;
-	if ((res = mp_int_init_copy(&v, b)) != MP_OK)
-		goto V;
+	DECLARE_TEMP(3);
+	REQUIRE(mp_int_copy(a, TEMP(0)));
+	REQUIRE(mp_int_copy(b, TEMP(1)));
 
-	MP_SIGN(&u) = MP_ZPOS;
-	MP_SIGN(&v) = MP_ZPOS;
+	TEMP(0)->sign = MP_ZPOS;
+	TEMP(1)->sign = MP_ZPOS;
+
+	int			k = 0;
 
 	{							/* Divide out common factors of 2 from u and v */
-		int			div2_u = s_dp2k(&u),
-					div2_v = s_dp2k(&v);
+		int			div2_u = s_dp2k(TEMP(0));
+		int			div2_v = s_dp2k(TEMP(1));
 
 		k = MIN(div2_u, div2_v);
-		s_qdiv(&u, (mp_size) k);
-		s_qdiv(&v, (mp_size) k);
+		s_qdiv(TEMP(0), (mp_size) k);
+		s_qdiv(TEMP(1), (mp_size) k);
 	}
 
-	if (mp_int_is_odd(&u))
+	if (mp_int_is_odd(TEMP(0)))
 	{
-		if ((res = mp_int_neg(&v, &t)) != MP_OK)
-			goto CLEANUP;
+		REQUIRE(mp_int_neg(TEMP(1), TEMP(2)));
 	}
 	else
 	{
-		if ((res = mp_int_copy(&u, &t)) != MP_OK)
-			goto CLEANUP;
+		REQUIRE(mp_int_copy(TEMP(0), TEMP(2)));
 	}
 
 	for (;;)
 	{
-		s_qdiv(&t, s_dp2k(&t));
+		s_qdiv(TEMP(2), s_dp2k(TEMP(2)));
 
-		if (CMPZ(&t) > 0)
+		if (CMPZ(TEMP(2)) > 0)
 		{
-			if ((res = mp_int_copy(&t, &u)) != MP_OK)
-				goto CLEANUP;
+			REQUIRE(mp_int_copy(TEMP(2), TEMP(0)));
 		}
 		else
 		{
-			if ((res = mp_int_neg(&t, &v)) != MP_OK)
-				goto CLEANUP;
+			REQUIRE(mp_int_neg(TEMP(2), TEMP(1)));
 		}
 
-		if ((res = mp_int_sub(&u, &v, &t)) != MP_OK)
-			goto CLEANUP;
+		REQUIRE(mp_int_sub(TEMP(0), TEMP(1), TEMP(2)));
 
-		if (CMPZ(&t) == 0)
+		if (CMPZ(TEMP(2)) == 0)
 			break;
 	}
 
-	if ((res = mp_int_abs(&u, c)) != MP_OK)
-		goto CLEANUP;
+	REQUIRE(mp_int_abs(TEMP(0), c));
 	if (!s_qmul(c, (mp_size) k))
-		res = MP_MEMORY;
-
-CLEANUP:
-	mp_int_clear(&v);
-V:	mp_int_clear(&u);
-U:	mp_int_clear(&t);
+		REQUIRE(MP_MEMORY);
 
-	return res;
+	CLEANUP_TEMP();
+	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_egcd(a, b, c, x, y) */
-
-/* This is the binary GCD algorithm again, but this time we keep track
-   of the elementary matrix operations as we go, so we can get values
-   x and y satisfying c = ax + by.
+/* This is the binary GCD algorithm again, but this time we keep track of the
+   elementary matrix operations as we go, so we can get values x and y
+   satisfying c = ax + by.
  */
 mp_result
-mp_int_egcd(mp_int a, mp_int b, mp_int c,
-			mp_int x, mp_int y)
-{
-	int			k,
-				last = 0,
-				ca,
-				cb;
-	mpz_t		temp[8];
-	mp_result	res;
+mp_int_egcd(mp_int a, mp_int b, mp_int c, mp_int x, mp_int y)
+{
+	assert(a != NULL && b != NULL && c != NULL && (x != NULL || y != NULL));
 
-	CHECK(a != NULL && b != NULL && c != NULL &&
-		  (x != NULL || y != NULL));
+	mp_result	res = MP_OK;
+	int			ca = CMPZ(a);
+	int			cb = CMPZ(b);
 
-	ca = CMPZ(a);
-	cb = CMPZ(b);
 	if (ca == 0 && cb == 0)
+	{
 		return MP_UNDEF;
+	}
 	else if (ca == 0)
 	{
 		if ((res = mp_int_abs(b, c)) != MP_OK)
@@ -1662,20 +1579,17 @@ mp_int_egcd(mp_int a, mp_int b, mp_int c,
 	/*
 	 * Initialize temporaries: A:0, B:1, C:2, D:3, u:4, v:5, ou:6, ov:7
 	 */
-	for (last = 0; last < 4; ++last)
-	{
-		if ((res = mp_int_init(TEMP(last))) != MP_OK)
-			goto CLEANUP;
-	}
-	TEMP(0)->digits[0] = 1;
-	TEMP(3)->digits[0] = 1;
-
-	SETUP(mp_int_init_copy(TEMP(4), a), last);
-	SETUP(mp_int_init_copy(TEMP(5), b), last);
+	DECLARE_TEMP(8);
+	REQUIRE(mp_int_set_value(TEMP(0), 1));
+	REQUIRE(mp_int_set_value(TEMP(3), 1));
+	REQUIRE(mp_int_copy(a, TEMP(4)));
+	REQUIRE(mp_int_copy(b, TEMP(5)));
 
 	/* We will work with absolute values here */
-	MP_SIGN(TEMP(4)) = MP_ZPOS;
-	MP_SIGN(TEMP(5)) = MP_ZPOS;
+	TEMP(4)->sign = MP_ZPOS;
+	TEMP(5)->sign = MP_ZPOS;
+
+	int			k = 0;
 
 	{							/* Divide out common factors of 2 from u and v */
 		int			div2_u = s_dp2k(TEMP(4)),
@@ -1686,8 +1600,8 @@ mp_int_egcd(mp_int a, mp_int b, mp_int c,
 		s_qdiv(TEMP(5), k);
 	}
 
-	SETUP(mp_int_init_copy(TEMP(6), TEMP(4)), last);
-	SETUP(mp_int_init_copy(TEMP(7), TEMP(5)), last);
+	REQUIRE(mp_int_copy(TEMP(4), TEMP(6)));
+	REQUIRE(mp_int_copy(TEMP(5), TEMP(7)));
 
 	for (;;)
 	{
@@ -1697,10 +1611,8 @@ mp_int_egcd(mp_int a, mp_int b, mp_int c,
 
 			if (mp_int_is_odd(TEMP(0)) || mp_int_is_odd(TEMP(1)))
 			{
-				if ((res = mp_int_add(TEMP(0), TEMP(7), TEMP(0))) != MP_OK)
-					goto CLEANUP;
-				if ((res = mp_int_sub(TEMP(1), TEMP(6), TEMP(1))) != MP_OK)
-					goto CLEANUP;
+				REQUIRE(mp_int_add(TEMP(0), TEMP(7), TEMP(0)));
+				REQUIRE(mp_int_sub(TEMP(1), TEMP(6), TEMP(1)));
 			}
 
 			s_qdiv(TEMP(0), 1);
@@ -1713,10 +1625,8 @@ mp_int_egcd(mp_int a, mp_int b, mp_int c,
 
 			if (mp_int_is_odd(TEMP(2)) || mp_int_is_odd(TEMP(3)))
 			{
-				if ((res = mp_int_add(TEMP(2), TEMP(7), TEMP(2))) != MP_OK)
-					goto CLEANUP;
-				if ((res = mp_int_sub(TEMP(3), TEMP(6), TEMP(3))) != MP_OK)
-					goto CLEANUP;
+				REQUIRE(mp_int_add(TEMP(2), TEMP(7), TEMP(2)));
+				REQUIRE(mp_int_sub(TEMP(3), TEMP(6), TEMP(3)));
 			}
 
 			s_qdiv(TEMP(2), 1);
@@ -1725,157 +1635,163 @@ mp_int_egcd(mp_int a, mp_int b, mp_int c,
 
 		if (mp_int_compare(TEMP(4), TEMP(5)) >= 0)
 		{
-			if ((res = mp_int_sub(TEMP(4), TEMP(5), TEMP(4))) != MP_OK)
-				goto CLEANUP;
-			if ((res = mp_int_sub(TEMP(0), TEMP(2), TEMP(0))) != MP_OK)
-				goto CLEANUP;
-			if ((res = mp_int_sub(TEMP(1), TEMP(3), TEMP(1))) != MP_OK)
-				goto CLEANUP;
+			REQUIRE(mp_int_sub(TEMP(4), TEMP(5), TEMP(4)));
+			REQUIRE(mp_int_sub(TEMP(0), TEMP(2), TEMP(0)));
+			REQUIRE(mp_int_sub(TEMP(1), TEMP(3), TEMP(1)));
 		}
 		else
 		{
-			if ((res = mp_int_sub(TEMP(5), TEMP(4), TEMP(5))) != MP_OK)
-				goto CLEANUP;
-			if ((res = mp_int_sub(TEMP(2), TEMP(0), TEMP(2))) != MP_OK)
-				goto CLEANUP;
-			if ((res = mp_int_sub(TEMP(3), TEMP(1), TEMP(3))) != MP_OK)
-				goto CLEANUP;
+			REQUIRE(mp_int_sub(TEMP(5), TEMP(4), TEMP(5)));
+			REQUIRE(mp_int_sub(TEMP(2), TEMP(0), TEMP(2)));
+			REQUIRE(mp_int_sub(TEMP(3), TEMP(1), TEMP(3)));
 		}
 
 		if (CMPZ(TEMP(4)) == 0)
 		{
-			if (x && (res = mp_int_copy(TEMP(2), x)) != MP_OK)
-				goto CLEANUP;
-			if (y && (res = mp_int_copy(TEMP(3), y)) != MP_OK)
-				goto CLEANUP;
+			if (x)
+				REQUIRE(mp_int_copy(TEMP(2), x));
+			if (y)
+				REQUIRE(mp_int_copy(TEMP(3), y));
 			if (c)
 			{
 				if (!s_qmul(TEMP(5), k))
 				{
-					res = MP_MEMORY;
-					goto CLEANUP;
+					REQUIRE(MP_MEMORY);
 				}
-
-				res = mp_int_copy(TEMP(5), c);
+				REQUIRE(mp_int_copy(TEMP(5), c));
 			}
 
 			break;
 		}
 	}
 
-CLEANUP:
-	while (--last >= 0)
-		mp_int_clear(TEMP(last));
-
-	return res;
+	CLEANUP_TEMP();
+	return MP_OK;
 }
 
-/* }}} */
+mp_result
+mp_int_lcm(mp_int a, mp_int b, mp_int c)
+{
+	assert(a != NULL && b != NULL && c != NULL);
+
+	/*
+	 * Since a * b = gcd(a, b) * lcm(a, b), we can compute lcm(a, b) = (a /
+	 * gcd(a, b)) * b.
+	 *
+	 * This formulation insures everything works even if the input variables
+	 * share space.
+	 */
+	DECLARE_TEMP(1);
+	REQUIRE(mp_int_gcd(a, b, TEMP(0)));
+	REQUIRE(mp_int_div(a, TEMP(0), TEMP(0), NULL));
+	REQUIRE(mp_int_mul(TEMP(0), b, TEMP(0)));
+	REQUIRE(mp_int_copy(TEMP(0), c));
 
-/* {{{ mp_int_divisible_value(a, v) */
+	CLEANUP_TEMP();
+	return MP_OK;
+}
 
-int
-mp_int_divisible_value(mp_int a, int v)
+bool
+mp_int_divisible_value(mp_int a, mp_small v)
 {
-	int			rem = 0;
+	mp_small	rem = 0;
 
 	if (mp_int_div_value(a, v, NULL, &rem) != MP_OK)
-		return 0;
-
+	{
+		return false;
+	}
 	return rem == 0;
 }
 
-/* }}} */
-
-/* {{{ mp_int_is_pow2(z) */
-
 int
 mp_int_is_pow2(mp_int z)
 {
-	CHECK(z != NULL);
+	assert(z != NULL);
 
 	return s_isp2(z);
 }
 
-/* }}} */
-
-/* {{{ mp_int_sqrt(a, c) */
-
+/* Implementation of Newton's root finding method, based loosely on a patch
+   contributed by Hal Finkel <half@halssoftware.com>
+   modified by M. J. Fromberger.
+ */
 mp_result
-mp_int_sqrt(mp_int a, mp_int c)
+mp_int_root(mp_int a, mp_small b, mp_int c)
 {
-	mp_result	res = MP_OK;
-	mpz_t		temp[2];
-	int			last = 0;
+	assert(a != NULL && c != NULL && b > 0);
 
-	CHECK(a != NULL && c != NULL);
+	if (b == 1)
+	{
+		return mp_int_copy(a, c);
+	}
+	bool		flips = false;
 
-	/* The square root of a negative value does not exist in the integers. */
 	if (MP_SIGN(a) == MP_NEG)
-		return MP_UNDEF;
+	{
+		if (b % 2 == 0)
+		{
+			return MP_UNDEF;	/* root does not exist for negative a with
+								 * even b */
+		}
+		else
+		{
+			flips = true;
+		}
+	}
 
-	SETUP(mp_int_init_copy(TEMP(last), a), last);
-	SETUP(mp_int_init(TEMP(last)), last);
+	DECLARE_TEMP(5);
+	REQUIRE(mp_int_copy(a, TEMP(0)));
+	REQUIRE(mp_int_copy(a, TEMP(1)));
+	TEMP(0)->sign = MP_ZPOS;
+	TEMP(1)->sign = MP_ZPOS;
 
 	for (;;)
 	{
-		if ((res = mp_int_sqr(TEMP(0), TEMP(1))) != MP_OK)
-			goto CLEANUP;
+		REQUIRE(mp_int_expt(TEMP(1), b, TEMP(2)));
 
-		if (mp_int_compare_unsigned(a, TEMP(1)) == 0)
+		if (mp_int_compare_unsigned(TEMP(2), TEMP(0)) <= 0)
 			break;
 
-		if ((res = mp_int_copy(a, TEMP(1))) != MP_OK)
-			goto CLEANUP;
-		if ((res = mp_int_div(TEMP(1), TEMP(0), TEMP(1), NULL)) != MP_OK)
-			goto CLEANUP;
-		if ((res = mp_int_add(TEMP(0), TEMP(1), TEMP(1))) != MP_OK)
-			goto CLEANUP;
-		if ((res = mp_int_div_pow2(TEMP(1), 1, TEMP(1), NULL)) != MP_OK)
-			goto CLEANUP;
+		REQUIRE(mp_int_sub(TEMP(2), TEMP(0), TEMP(2)));
+		REQUIRE(mp_int_expt(TEMP(1), b - 1, TEMP(3)));
+		REQUIRE(mp_int_mul_value(TEMP(3), b, TEMP(3)));
+		REQUIRE(mp_int_div(TEMP(2), TEMP(3), TEMP(4), NULL));
+		REQUIRE(mp_int_sub(TEMP(1), TEMP(4), TEMP(4)));
 
-		if (mp_int_compare_unsigned(TEMP(0), TEMP(1)) == 0)
-			break;
-		if ((res = mp_int_sub_value(TEMP(0), 1, TEMP(0))) != MP_OK)
-			goto CLEANUP;
-		if (mp_int_compare_unsigned(TEMP(0), TEMP(1)) == 0)
-			break;
-
-		if ((res = mp_int_copy(TEMP(1), TEMP(0))) != MP_OK)
-			goto CLEANUP;
+		if (mp_int_compare_unsigned(TEMP(1), TEMP(4)) == 0)
+		{
+			REQUIRE(mp_int_sub_value(TEMP(4), 1, TEMP(4)));
+		}
+		REQUIRE(mp_int_copy(TEMP(4), TEMP(1)));
 	}
 
-	res = mp_int_copy(TEMP(0), c);
+	REQUIRE(mp_int_copy(TEMP(1), c));
 
-CLEANUP:
-	while (--last >= 0)
-		mp_int_clear(TEMP(last));
+	/* If the original value of a was negative, flip the output sign. */
+	if (flips)
+		(void) mp_int_neg(c, c);	/* cannot fail */
 
-	return res;
+	CLEANUP_TEMP();
+	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_to_int(z, out) */
-
 mp_result
-mp_int_to_int(mp_int z, int *out)
+mp_int_to_int(mp_int z, mp_small * out)
 {
-	unsigned int uv = 0;
-	mp_size		uz;
-	mp_digit   *dz;
-	mp_sign		sz;
+	assert(z != NULL);
 
-	CHECK(z != NULL);
+	/* Make sure the value is representable as a small integer */
+	mp_sign		sz = MP_SIGN(z);
 
-	/* Make sure the value is representable as an int */
-	sz = MP_SIGN(z);
-	if ((sz == MP_ZPOS && mp_int_compare_value(z, INT_MAX) > 0) ||
-		mp_int_compare_value(z, INT_MIN) < 0)
+	if ((sz == MP_ZPOS && mp_int_compare_value(z, MP_SMALL_MAX) > 0) ||
+		mp_int_compare_value(z, MP_SMALL_MIN) < 0)
+	{
 		return MP_RANGE;
+	}
 
-	uz = MP_USED(z);
-	dz = MP_DIGITS(z) + uz - 1;
+	mp_usmall	uz = MP_USED(z);
+	mp_digit   *dz = MP_DIGITS(z) + uz - 1;
+	mp_small	uv = 0;
 
 	while (uz > 0)
 	{
@@ -1885,33 +1801,56 @@ mp_int_to_int(mp_int z, int *out)
 	}
 
 	if (out)
-		*out = (sz == MP_NEG) ? -(int) uv : (int) uv;
+		*out = (mp_small) ((sz == MP_NEG) ? -uv : uv);
 
 	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_to_string(z, radix, str, limit) */
-
 mp_result
-mp_int_to_string(mp_int z, mp_size radix,
-				 char *str, int limit)
+mp_int_to_uint(mp_int z, mp_usmall * out)
 {
-	mp_result	res;
-	int			cmp = 0;
+	assert(z != NULL);
 
-	CHECK(z != NULL && str != NULL && limit >= 2);
+	/* Make sure the value is representable as an unsigned small integer */
+	mp_size		sz = MP_SIGN(z);
 
-	if (radix < MP_MIN_RADIX || radix > MP_MAX_RADIX)
+	if (sz == MP_NEG || mp_int_compare_uvalue(z, MP_USMALL_MAX) > 0)
+	{
 		return MP_RANGE;
+	}
+
+	mp_size		uz = MP_USED(z);
+	mp_digit   *dz = MP_DIGITS(z) + uz - 1;
+	mp_usmall	uv = 0;
+
+	while (uz > 0)
+	{
+		uv <<= MP_DIGIT_BIT / 2;
+		uv = (uv << (MP_DIGIT_BIT / 2)) | *dz--;
+		--uz;
+	}
+
+	if (out)
+		*out = uv;
+
+	return MP_OK;
+}
+
+mp_result
+mp_int_to_string(mp_int z, mp_size radix, char *str, int limit)
+{
+	assert(z != NULL && str != NULL && limit >= 2);
+	assert(radix >= MP_MIN_RADIX && radix <= MP_MAX_RADIX);
+
+	int			cmp = 0;
 
 	if (CMPZ(z) == 0)
 	{
-		*str++ = s_val2ch(0, mp_flags & MP_CAP_DIGITS);
+		*str++ = s_val2ch(0, 1);
 	}
 	else
 	{
+		mp_result	res;
 		mpz_t		tmp;
 		char	   *h,
 				   *t;
@@ -1935,7 +1874,7 @@ mp_int_to_string(mp_int z, mp_size radix,
 				break;
 
 			d = s_ddiv(&tmp, (mp_digit) radix);
-			*str++ = s_val2ch(d, mp_flags & MP_CAP_DIGITS);
+			*str++ = s_val2ch(d, 1);
 		}
 		t = str - 1;
 
@@ -1953,26 +1892,22 @@ mp_int_to_string(mp_int z, mp_size radix,
 
 	*str = '\0';
 	if (cmp == 0)
+	{
 		return MP_OK;
+	}
 	else
+	{
 		return MP_TRUNC;
+	}
 }
 
-/* }}} */
-
-/* {{{ mp_int_string_len(z, radix) */
-
 mp_result
 mp_int_string_len(mp_int z, mp_size radix)
 {
-	int			len;
-
-	CHECK(z != NULL);
-
-	if (radix < MP_MIN_RADIX || radix > MP_MAX_RADIX)
-		return MP_RANGE;
+	assert(z != NULL);
+	assert(radix >= MP_MIN_RADIX && radix <= MP_MAX_RADIX);
 
-	len = s_outlen(z, radix) + 1;	/* for terminator */
+	int			len = s_outlen(z, radix) + 1;	/* for terminator */
 
 	/* Allow for sign marker on negatives */
 	if (MP_SIGN(z) == MP_NEG)
@@ -1981,31 +1916,19 @@ mp_int_string_len(mp_int z, mp_size radix)
 	return len;
 }
 
-/* }}} */
-
-/* {{{ mp_int_read_string(z, radix, *str) */
-
 /* Read zero-terminated string into z */
 mp_result
 mp_int_read_string(mp_int z, mp_size radix, const char *str)
 {
 	return mp_int_read_cstring(z, radix, str, NULL);
-
 }
 
-/* }}} */
-
-/* {{{ mp_int_read_cstring(z, radix, *str, **end) */
-
 mp_result
-mp_int_read_cstring(mp_int z, mp_size radix, const char *str, char **end)
+mp_int_read_cstring(mp_int z, mp_size radix, const char *str,
+					char **end)
 {
-	int			ch;
-
-	CHECK(z != NULL && str != NULL);
-
-	if (radix < MP_MIN_RADIX || radix > MP_MAX_RADIX)
-		return MP_RANGE;
+	assert(z != NULL && str != NULL);
+	assert(radix >= MP_MIN_RADIX && radix <= MP_MAX_RADIX);
 
 	/* Skip leading whitespace */
 	while (isspace((unsigned char) *str))
@@ -2015,17 +1938,19 @@ mp_int_read_cstring(mp_int z, mp_size radix, const char *str, char **end)
 	switch (*str)
 	{
 		case '-':
-			MP_SIGN(z) = MP_NEG;
+			z->sign = MP_NEG;
 			++str;
 			break;
 		case '+':
 			++str;				/* fallthrough */
 		default:
-			MP_SIGN(z) = MP_ZPOS;
+			z->sign = MP_ZPOS;
 			break;
 	}
 
 	/* Skip leading zeroes */
+	int			ch;
+
 	while ((ch = s_ch2val(*str, radix)) == 0)
 		++str;
 
@@ -2033,7 +1958,7 @@ mp_int_read_cstring(mp_int z, mp_size radix, const char *str, char **end)
 	if (!s_pad(z, s_inlen(strlen(str), radix)))
 		return MP_MEMORY;
 
-	MP_USED(z) = 1;
+	z->used = 1;
 	z->digits[0] = 0;
 
 	while (*str != '\0' && ((ch = s_ch2val(*str, radix)) >= 0))
@@ -2047,7 +1972,7 @@ mp_int_read_cstring(mp_int z, mp_size radix, const char *str, char **end)
 
 	/* Override sign for zero, even if negative specified. */
 	if (CMPZ(z) == 0)
-		MP_SIGN(z) = MP_ZPOS;
+		z->sign = MP_ZPOS;
 
 	if (end != NULL)
 		*end = (char *) str;
@@ -2057,31 +1982,28 @@ mp_int_read_cstring(mp_int z, mp_size radix, const char *str, char **end)
 	 * remaining, so the caller can tell if the whole string was done
 	 */
 	if (*str != '\0')
+	{
 		return MP_TRUNC;
+	}
 	else
+	{
 		return MP_OK;
+	}
 }
 
-/* }}} */
-
-/* {{{ mp_int_count_bits(z) */
-
 mp_result
 mp_int_count_bits(mp_int z)
 {
-	mp_size		nbits = 0,
-				uz;
-	mp_digit	d;
+	assert(z != NULL);
 
-	CHECK(z != NULL);
+	mp_size		uz = MP_USED(z);
 
-	uz = MP_USED(z);
 	if (uz == 1 && z->digits[0] == 0)
 		return 1;
 
 	--uz;
-	nbits = uz * MP_DIGIT_BIT;
-	d = z->digits[uz];
+	mp_size		nbits = uz * MP_DIGIT_BIT;
+	mp_digit	d = z->digits[uz];
 
 	while (d != 0)
 	{
@@ -2092,21 +2014,15 @@ mp_int_count_bits(mp_int z)
 	return nbits;
 }
 
-/* }}} */
-
-/* {{{ mp_int_to_binary(z, buf, limit) */
-
 mp_result
 mp_int_to_binary(mp_int z, unsigned char *buf, int limit)
 {
 	static const int PAD_FOR_2C = 1;
 
-	mp_result	res;
-	int			limpos = limit;
+	assert(z != NULL && buf != NULL);
 
-	CHECK(z != NULL && buf != NULL);
-
-	res = s_tobin(z, buf, &limpos, PAD_FOR_2C);
+	int			limpos = limit;
+	mp_result	res = s_tobin(z, buf, &limpos, PAD_FOR_2C);
 
 	if (MP_SIGN(z) == MP_NEG)
 		s_2comp(buf, limpos);
@@ -2114,22 +2030,14 @@ mp_int_to_binary(mp_int z, unsigned char *buf, int limit)
 	return res;
 }
 
-/* }}} */
-
-/* {{{ mp_int_read_binary(z, buf, len) */
-
 mp_result
 mp_int_read_binary(mp_int z, unsigned char *buf, int len)
 {
-	mp_size		need,
-				i;
-	unsigned char *tmp;
-	mp_digit   *dz;
-
-	CHECK(z != NULL && buf != NULL && len > 0);
+	assert(z != NULL && buf != NULL && len > 0);
 
 	/* Figure out how many digits are needed to represent this value */
-	need = ((len * CHAR_BIT) + (MP_DIGIT_BIT - 1)) / MP_DIGIT_BIT;
+	mp_size		need = ((len * CHAR_BIT) + (MP_DIGIT_BIT - 1)) / MP_DIGIT_BIT;
+
 	if (!s_pad(z, need))
 		return MP_MEMORY;
 
@@ -2141,12 +2049,14 @@ mp_int_read_binary(mp_int z, unsigned char *buf, int len)
 	 */
 	if (buf[0] >> (CHAR_BIT - 1))
 	{
-		MP_SIGN(z) = MP_NEG;
+		z->sign = MP_NEG;
 		s_2comp(buf, len);
 	}
 
-	dz = MP_DIGITS(z);
-	for (tmp = buf, i = len; i > 0; --i, ++tmp)
+	mp_digit   *dz = MP_DIGITS(z);
+	unsigned char *tmp = buf;
+
+	for (int i = len; i > 0; --i, ++tmp)
 	{
 		s_qmul(z, (mp_size) CHAR_BIT);
 		*dz |= *tmp;
@@ -2159,20 +2069,15 @@ mp_int_read_binary(mp_int z, unsigned char *buf, int len)
 	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_binary_len(z) */
-
 mp_result
 mp_int_binary_len(mp_int z)
 {
 	mp_result	res = mp_int_count_bits(z);
-	int			bytes = mp_int_unsigned_len(z);
 
 	if (res <= 0)
 		return res;
 
-	bytes = (res + (CHAR_BIT - 1)) / CHAR_BIT;
+	int			bytes = mp_int_unsigned_len(z);
 
 	/*
 	 * If the highest-order bit falls exactly on a byte boundary, we need to
@@ -2185,193 +2090,170 @@ mp_int_binary_len(mp_int z)
 	return bytes;
 }
 
-/* }}} */
-
-/* {{{ mp_int_to_unsigned(z, buf, limit) */
-
 mp_result
 mp_int_to_unsigned(mp_int z, unsigned char *buf, int limit)
 {
 	static const int NO_PADDING = 0;
 
-	CHECK(z != NULL && buf != NULL);
+	assert(z != NULL && buf != NULL);
 
 	return s_tobin(z, buf, &limit, NO_PADDING);
 }
 
-/* }}} */
-
-/* {{{ mp_int_read_unsigned(z, buf, len) */
-
 mp_result
 mp_int_read_unsigned(mp_int z, unsigned char *buf, int len)
 {
-	mp_size		need,
-				i;
-	unsigned char *tmp;
-	mp_digit   *dz;
-
-	CHECK(z != NULL && buf != NULL && len > 0);
+	assert(z != NULL && buf != NULL && len > 0);
 
 	/* Figure out how many digits are needed to represent this value */
-	need = ((len * CHAR_BIT) + (MP_DIGIT_BIT - 1)) / MP_DIGIT_BIT;
+	mp_size		need = ((len * CHAR_BIT) + (MP_DIGIT_BIT - 1)) / MP_DIGIT_BIT;
+
 	if (!s_pad(z, need))
 		return MP_MEMORY;
 
 	mp_int_zero(z);
 
-	dz = MP_DIGITS(z);
-	for (tmp = buf, i = len; i > 0; --i, ++tmp)
+	unsigned char *tmp = buf;
+
+	for (int i = len; i > 0; --i, ++tmp)
 	{
 		(void) s_qmul(z, CHAR_BIT);
-		*dz |= *tmp;
+		*MP_DIGITS(z) |= *tmp;
 	}
 
 	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_unsigned_len(z) */
-
 mp_result
 mp_int_unsigned_len(mp_int z)
 {
 	mp_result	res = mp_int_count_bits(z);
-	int			bytes;
 
 	if (res <= 0)
 		return res;
 
-	bytes = (res + (CHAR_BIT - 1)) / CHAR_BIT;
+	int			bytes = (res + (CHAR_BIT - 1)) / CHAR_BIT;
 
 	return bytes;
 }
 
-/* }}} */
-
-/* {{{ mp_error_string(res) */
-
 const char *
 mp_error_string(mp_result res)
 {
-	int			ix;
-
 	if (res > 0)
 		return s_unknown_err;
 
 	res = -res;
+	int			ix;
+
 	for (ix = 0; ix < res && s_error_msg[ix] != NULL; ++ix)
 		;
 
 	if (s_error_msg[ix] != NULL)
+	{
 		return s_error_msg[ix];
+	}
 	else
+	{
 		return s_unknown_err;
+	}
 }
 
-/* }}} */
-
 /*------------------------------------------------------------------------*/
 /* Private functions for internal use.  These make assumptions.           */
 
-/* {{{ s_alloc(num) */
+#if DEBUG
+static const mp_digit fill = (mp_digit) 0xdeadbeefabad1dea;
+#endif
 
 static mp_digit *
 s_alloc(mp_size num)
 {
-	mp_digit   *out = px_alloc(num * sizeof(mp_digit));
+	mp_digit   *out = malloc(num * sizeof(mp_digit));
 
-	assert(out != NULL);		/* for debugging */
+	assert(out != NULL);
 
+#if DEBUG
+	for (mp_size ix = 0; ix < num; ++ix)
+		out[ix] = fill;
+#endif
 	return out;
 }
 
-/* }}} */
-
-/* {{{ s_realloc(old, num) */
-
 static mp_digit *
-s_realloc(mp_digit *old, mp_size num)
+s_realloc(mp_digit *old, mp_size osize, mp_size nsize)
 {
-	mp_digit   *new = px_realloc(old, num * sizeof(mp_digit));
+#if DEBUG
+	mp_digit   *new = s_alloc(nsize);
 
-	assert(new != NULL);		/* for debugging */
+	assert(new != NULL);
 
-	return new;
-}
+	for (mp_size ix = 0; ix < nsize; ++ix)
+		new[ix] = fill;
+	memcpy(new, old, osize * sizeof(mp_digit));
+#else
+	mp_digit   *new = realloc(old, nsize * sizeof(mp_digit));
 
-/* }}} */
+	assert(new != NULL);
+#endif
 
-/* {{{ s_free(ptr) */
+	return new;
+}
 
-#if TRACEABLE_FREE
 static void
 s_free(void *ptr)
 {
-	px_free(ptr);
+	free(ptr);
 }
-#endif
-
-/* }}} */
 
-/* {{{ s_pad(z, min) */
-
-static int
+static bool
 s_pad(mp_int z, mp_size min)
 {
 	if (MP_ALLOC(z) < min)
 	{
-		mp_size		nsize = ROUND_PREC(min);
-		mp_digit   *tmp = s_realloc(MP_DIGITS(z), nsize);
+		mp_size		nsize = s_round_prec(min);
+		mp_digit   *tmp;
 
-		if (tmp == NULL)
-			return 0;
+		if (z->digits == &(z->single))
+		{
+			if ((tmp = s_alloc(nsize)) == NULL)
+				return false;
+			tmp[0] = z->single;
+		}
+		else if ((tmp = s_realloc(MP_DIGITS(z), MP_ALLOC(z), nsize)) == NULL)
+		{
+			return false;
+		}
 
-		MP_DIGITS(z) = tmp;
-		MP_ALLOC(z) = nsize;
+		z->digits = tmp;
+		z->alloc = nsize;
 	}
 
-	return 1;
+	return true;
 }
 
-/* }}} */
-
-/* {{{ s_clamp(z) */
-
-#if TRACEABLE_CLAMP
+/* Note: This will not work correctly when value == MP_SMALL_MIN */
 static void
-s_clamp(mp_int z)
+s_fake(mp_int z, mp_small value, mp_digit vbuf[])
 {
-	mp_size		uz = MP_USED(z);
-	mp_digit   *zd = MP_DIGITS(z) + uz - 1;
-
-	while (uz > 1 && (*zd-- == 0))
-		--uz;
+	mp_usmall	uv = (mp_usmall) (value < 0) ? -value : value;
 
-	MP_USED(z) = uz;
+	s_ufake(z, uv, vbuf);
+	if (value < 0)
+		z->sign = MP_NEG;
 }
-#endif
-
-/* }}} */
-
-/* {{{ s_fake(z, value, vbuf) */
 
 static void
-s_fake(mp_int z, int value, mp_digit vbuf[])
+s_ufake(mp_int z, mp_usmall value, mp_digit vbuf[])
 {
-	mp_size		uv = (mp_size) s_vpack(value, vbuf);
+	mp_size		ndig = (mp_size) s_uvpack(value, vbuf);
 
-	z->used = uv;
+	z->used = ndig;
 	z->alloc = MP_VALUE_DIGITS(value);
-	z->sign = (value < 0) ? MP_NEG : MP_ZPOS;
+	z->sign = MP_ZPOS;
 	z->digits = vbuf;
 }
 
-/* }}} */
-
-/* {{{ s_cdig(da, db, len) */
-
 static int
 s_cdig(mp_digit *da, mp_digit *db, mp_size len)
 {
@@ -2381,22 +2263,21 @@ s_cdig(mp_digit *da, mp_digit *db, mp_size len)
 	for ( /* */ ; len != 0; --len, --dat, --dbt)
 	{
 		if (*dat > *dbt)
+		{
 			return 1;
+		}
 		else if (*dat < *dbt)
+		{
 			return -1;
+		}
 	}
 
 	return 0;
 }
 
-/* }}} */
-
-/* {{{ s_vpack(v, t[]) */
-
 static int
-s_vpack(int v, mp_digit t[])
+s_uvpack(mp_usmall uv, mp_digit t[])
 {
-	unsigned int uv = (unsigned int) ((v < 0) ? -v : v);
 	int			ndig = 0;
 
 	if (uv == 0)
@@ -2414,10 +2295,6 @@ s_vpack(int v, mp_digit t[])
 	return ndig;
 }
 
-/* }}} */
-
-/* {{{ s_ucmp(a, b) */
-
 static int
 s_ucmp(mp_int a, mp_int b)
 {
@@ -2425,41 +2302,40 @@ s_ucmp(mp_int a, mp_int b)
 				ub = MP_USED(b);
 
 	if (ua > ub)
+	{
 		return 1;
+	}
 	else if (ub > ua)
+	{
 		return -1;
+	}
 	else
+	{
 		return s_cdig(MP_DIGITS(a), MP_DIGITS(b), ua);
+	}
 }
 
-/* }}} */
-
-/* {{{ s_vcmp(a, v) */
-
 static int
-s_vcmp(mp_int a, int v)
+s_vcmp(mp_int a, mp_small v)
 {
-	mp_digit	vdig[MP_VALUE_DIGITS(v)];
-	int			ndig = 0;
-	mp_size		ua = MP_USED(a);
+	mp_usmall	uv = (v < 0) ? -(mp_usmall) v : (mp_usmall) v;
 
-	ndig = s_vpack(v, vdig);
-
-	if (ua > ndig)
-		return 1;
-	else if (ua < ndig)
-		return -1;
-	else
-		return s_cdig(MP_DIGITS(a), vdig, ndig);
+	return s_uvcmp(a, uv);
 }
 
-/* }}} */
+static int
+s_uvcmp(mp_int a, mp_usmall uv)
+{
+	mpz_t		vtmp;
+	mp_digit	vdig[MP_VALUE_DIGITS(uv)];
 
-/* {{{ s_uadd(da, db, dc, size_a, size_b) */
+	s_ufake(&vtmp, uv, vdig);
+	return s_ucmp(a, &vtmp);
+}
 
 static mp_digit
-s_uadd(mp_digit *da, mp_digit *db, mp_digit *dc,
-	   mp_size size_a, mp_size size_b)
+s_uadd(mp_digit *da, mp_digit *db, mp_digit *dc, mp_size size_a,
+	   mp_size size_b)
 {
 	mp_size		pos;
 	mp_word		w = 0;
@@ -2492,13 +2368,9 @@ s_uadd(mp_digit *da, mp_digit *db, mp_digit *dc,
 	return (mp_digit) w;
 }
 
-/* }}} */
-
-/* {{{ s_usub(da, db, dc, size_a, size_b) */
-
 static void
-s_usub(mp_digit *da, mp_digit *db, mp_digit *dc,
-	   mp_size size_a, mp_size size_b)
+s_usub(mp_digit *da, mp_digit *db, mp_digit *dc, mp_size size_a,
+	   mp_size size_b)
 {
 	mp_size		pos;
 	mp_word		w = 0;
@@ -2510,7 +2382,8 @@ s_usub(mp_digit *da, mp_digit *db, mp_digit *dc,
 	for (pos = 0; pos < size_b; ++pos, ++da, ++db, ++dc)
 	{
 		w = ((mp_word) MP_DIGIT_MAX + 1 +	/* MP_RADIX */
-			 (mp_word) *da) - w - (mp_word) *db;
+			 (mp_word) *da) -
+			w - (mp_word) *db;
 
 		*dc = LOWER_HALF(w);
 		w = (UPPER_HALF(w) == 0);
@@ -2520,7 +2393,8 @@ s_usub(mp_digit *da, mp_digit *db, mp_digit *dc,
 	for ( /* */ ; pos < size_a; ++pos, ++da, ++dc)
 	{
 		w = ((mp_word) MP_DIGIT_MAX + 1 +	/* MP_RADIX */
-			 (mp_word) *da) - w;
+			 (mp_word) *da) -
+			w;
 
 		*dc = LOWER_HALF(w);
 		w = (UPPER_HALF(w) == 0);
@@ -2530,13 +2404,9 @@ s_usub(mp_digit *da, mp_digit *db, mp_digit *dc,
 	assert(w == 0);
 }
 
-/* }}} */
-
-/* {{{ s_kmul(da, db, dc, size_a, size_b) */
-
 static int
-s_kmul(mp_digit *da, mp_digit *db, mp_digit *dc,
-	   mp_size size_a, mp_size size_b)
+s_kmul(mp_digit *da, mp_digit *db, mp_digit *dc, mp_size size_a,
+	   mp_size size_b)
 {
 	mp_size		bot_size;
 
@@ -2558,11 +2428,8 @@ s_kmul(mp_digit *da, mp_digit *db, mp_digit *dc,
 	 * Karatsuba algorithm to compute the product; otherwise use the normal
 	 * multiplication algorithm
 	 */
-	if (multiply_threshold &&
-		size_a >= multiply_threshold &&
-		size_b > bot_size)
+	if (multiply_threshold && size_a >= multiply_threshold && size_b > bot_size)
 	{
-
 		mp_digit   *t1,
 				   *t2,
 				   *t3,
@@ -2614,12 +2481,11 @@ s_kmul(mp_digit *da, mp_digit *db, mp_digit *dc,
 
 		/* Assemble the output value */
 		COPY(t1, dc, buf_size);
-		carry = s_uadd(t3, dc + bot_size, dc + bot_size,
-					   buf_size + 1, buf_size);
+		carry = s_uadd(t3, dc + bot_size, dc + bot_size, buf_size + 1, buf_size);
 		assert(carry == 0);
 
-		carry = s_uadd(t2, dc + 2 * bot_size, dc + 2 * bot_size,
-					   buf_size, buf_size);
+		carry =
+			s_uadd(t2, dc + 2 * bot_size, dc + 2 * bot_size, buf_size, buf_size);
 		assert(carry == 0);
 
 		s_free(t1);				/* note t2 and t3 are just internal pointers
@@ -2633,13 +2499,9 @@ s_kmul(mp_digit *da, mp_digit *db, mp_digit *dc,
 	return 1;
 }
 
-/* }}} */
-
-/* {{{ s_umul(da, db, dc, size_a, size_b) */
-
 static void
-s_umul(mp_digit *da, mp_digit *db, mp_digit *dc,
-	   mp_size size_a, mp_size size_b)
+s_umul(mp_digit *da, mp_digit *db, mp_digit *dc, mp_size size_a,
+	   mp_size size_b)
 {
 	mp_size		a,
 				b;
@@ -2666,10 +2528,6 @@ s_umul(mp_digit *da, mp_digit *db, mp_digit *dc,
 	}
 }
 
-/* }}} */
-
-/* {{{ s_ksqr(da, dc, size_a) */
-
 static int
 s_ksqr(mp_digit *da, mp_digit *dc, mp_size size_a)
 {
@@ -2679,7 +2537,8 @@ s_ksqr(mp_digit *da, mp_digit *dc, mp_size size_a)
 		mp_digit   *a_top = da + bot_size;
 		mp_digit   *t1,
 				   *t2,
-				   *t3;
+				   *t3,
+					carry;
 		mp_size		at_size = size_a - bot_size;
 		mp_size		buf_size = 2 * bot_size;
 
@@ -2713,13 +2572,14 @@ s_ksqr(mp_digit *da, mp_digit *dc, mp_size size_a)
 
 		/* Assemble the output value */
 		COPY(t1, dc, 2 * bot_size);
-		(void) s_uadd(t3, dc + bot_size, dc + bot_size,
-					  buf_size + 1, buf_size + 1);
+		carry = s_uadd(t3, dc + bot_size, dc + bot_size, buf_size + 1, buf_size);
+		assert(carry == 0);
 
-		(void) s_uadd(t2, dc + 2 * bot_size, dc + 2 * bot_size,
-					  buf_size, buf_size);
+		carry =
+			s_uadd(t2, dc + 2 * bot_size, dc + 2 * bot_size, buf_size, buf_size);
+		assert(carry == 0);
 
-		px_free(t1);			/* note that t2 and t2 are internal pointers
+		s_free(t1);				/* note that t2 and t2 are internal pointers
 								 * only */
 
 	}
@@ -2731,10 +2591,6 @@ s_ksqr(mp_digit *da, mp_digit *dc, mp_size size_a)
 	return 1;
 }
 
-/* }}} */
-
-/* {{{ s_usqr(da, dc, size_a) */
-
 static void
 s_usqr(mp_digit *da, mp_digit *dc, mp_size size_a)
 {
@@ -2797,10 +2653,6 @@ s_usqr(mp_digit *da, mp_digit *dc, mp_size size_a)
 	}
 }
 
-/* }}} */
-
-/* {{{ s_dadd(a, b) */
-
 static void
 s_dadd(mp_int a, mp_digit b)
 {
@@ -2823,14 +2675,10 @@ s_dadd(mp_int a, mp_digit b)
 	if (w)
 	{
 		*da = (mp_digit) w;
-		MP_USED(a) += 1;
+		a->used += 1;
 	}
 }
 
-/* }}} */
-
-/* {{{ s_dmul(a, b) */
-
 static void
 s_dmul(mp_int a, mp_digit b)
 {
@@ -2849,14 +2697,10 @@ s_dmul(mp_int a, mp_digit b)
 	if (w)
 	{
 		*da = (mp_digit) w;
-		MP_USED(a) += 1;
+		a->used += 1;
 	}
 }
 
-/* }}} */
-
-/* {{{ s_dbmul(da, b, dc, size_a) */
-
 static void
 s_dbmul(mp_digit *da, mp_digit b, mp_digit *dc, mp_size size_a)
 {
@@ -2875,10 +2719,6 @@ s_dbmul(mp_digit *da, mp_digit b, mp_digit *dc, mp_size size_a)
 		*dc = LOWER_HALF(w);
 }
 
-/* }}} */
-
-/* {{{ s_ddiv(da, d, dc, size_a) */
-
 static mp_digit
 s_ddiv(mp_int a, mp_digit b)
 {
@@ -2908,10 +2748,6 @@ s_ddiv(mp_int a, mp_digit b)
 	return (mp_digit) w;
 }
 
-/* }}} */
-
-/* {{{ s_qdiv(z, p2) */
-
 static void
 s_qdiv(mp_int z, mp_size p2)
 {
@@ -2935,9 +2771,11 @@ s_qdiv(mp_int z, mp_size p2)
 		from = to + ndig;
 
 		for (mark = ndig; mark < uz; ++mark)
+		{
 			*to++ = *from++;
+		}
 
-		MP_USED(z) = uz - ndig;
+		z->used = uz - ndig;
 	}
 
 	if (nbits)
@@ -2962,33 +2800,25 @@ s_qdiv(mp_int z, mp_size p2)
 	}
 
 	if (MP_USED(z) == 1 && z->digits[0] == 0)
-		MP_SIGN(z) = MP_ZPOS;
+		z->sign = MP_ZPOS;
 }
 
-/* }}} */
-
-/* {{{ s_qmod(z, p2) */
-
 static void
 s_qmod(mp_int z, mp_size p2)
 {
 	mp_size		start = p2 / MP_DIGIT_BIT + 1,
 				rest = p2 % MP_DIGIT_BIT;
 	mp_size		uz = MP_USED(z);
-	mp_digit	mask = (1 << rest) - 1;
+	mp_digit	mask = (1u << rest) - 1;
 
 	if (start <= uz)
 	{
-		MP_USED(z) = start;
+		z->used = start;
 		z->digits[start - 1] &= mask;
 		CLAMP(z);
 	}
 }
 
-/* }}} */
-
-/* {{{ s_qmul(z, p2) */
-
 static int
 s_qmul(mp_int z, mp_size p2)
 {
@@ -3060,21 +2890,19 @@ s_qmul(mp_int z, mp_size p2)
 		}
 	}
 
-	MP_USED(z) = uz;
+	z->used = uz;
 	CLAMP(z);
 
 	return 1;
 }
 
-/* }}} */
-
-/* {{{ s_qsub(z, p2) */
-
-/* Subtract |z| from 2^p2, assuming 2^p2 > |z|, and set z to be positive */
+/* Compute z = 2^p2 - |z|; requires that 2^p2 >= |z|
+   The sign of the result is always zero/positive.
+ */
 static int
 s_qsub(mp_int z, mp_size p2)
 {
-	mp_digit	hi = (1 << (p2 % MP_DIGIT_BIT)),
+	mp_digit	hi = (1u << (p2 % MP_DIGIT_BIT)),
 			   *zp;
 	mp_size		tdig = (p2 / MP_DIGIT_BIT),
 				pos;
@@ -3096,16 +2924,12 @@ s_qsub(mp_int z, mp_size p2)
 
 	assert(UPPER_HALF(w) != 0); /* no borrow out should be possible */
 
-	MP_SIGN(z) = MP_ZPOS;
+	z->sign = MP_ZPOS;
 	CLAMP(z);
 
 	return 1;
 }
 
-/* }}} */
-
-/* {{{ s_dp2k(z) */
-
 static int
 s_dp2k(mp_int z)
 {
@@ -3132,10 +2956,6 @@ s_dp2k(mp_int z)
 	return k;
 }
 
-/* }}} */
-
-/* {{{ s_isp2(z) */
-
 static int
 s_isp2(mp_int z)
 {
@@ -3164,12 +2984,8 @@ s_isp2(mp_int z)
 	return (int) k;
 }
 
-/* }}} */
-
-/* {{{ s_2expt(z, k) */
-
 static int
-s_2expt(mp_int z, int k)
+s_2expt(mp_int z, mp_small k)
 {
 	mp_size		ndig,
 				rest;
@@ -3183,23 +2999,19 @@ s_2expt(mp_int z, int k)
 
 	dz = MP_DIGITS(z);
 	ZERO(dz, ndig);
-	*(dz + ndig - 1) = (1 << rest);
-	MP_USED(z) = ndig;
+	*(dz + ndig - 1) = (1u << rest);
+	z->used = ndig;
 
 	return 1;
 }
 
-/* }}} */
-
-/* {{{ s_norm(a, b) */
-
 static int
 s_norm(mp_int a, mp_int b)
 {
 	mp_digit	d = b->digits[MP_USED(b) - 1];
 	int			k = 0;
 
-	while (d < (mp_digit) ((mp_digit) 1 << (MP_DIGIT_BIT - 1)))
+	while (d < (1u << (mp_digit) (MP_DIGIT_BIT - 1)))
 	{							/* d < (MP_RADIX / 2) */
 		d <<= 1;
 		++k;
@@ -3215,10 +3027,6 @@ s_norm(mp_int a, mp_int b)
 	return k;
 }
 
-/* }}} */
-
-/* {{{ s_brmu(z, m) */
-
 static mp_result
 s_brmu(mp_int z, mp_int m)
 {
@@ -3231,10 +3039,6 @@ s_brmu(mp_int z, mp_int m)
 	return mp_int_div(z, m, z, NULL);
 }
 
-/* }}} */
-
-/* {{{ s_reduce(x, m, mu, q1, q2) */
-
 static int
 s_reduce(mp_int x, mp_int m, mp_int mu, mp_int q1, mp_int q2)
 {
@@ -3273,53 +3077,47 @@ s_reduce(mp_int x, mp_int m, mp_int mu, mp_int q1, mp_int q2)
 		return 0;
 
 	/*
-	 * If x > m, we need to back it off until it is in range. This will be
+	 * If x > m, we need to back it off until it is in range.  This will be
 	 * required at most twice.
 	 */
 	if (mp_int_compare(x, m) >= 0)
+	{
 		(void) mp_int_sub(x, m, x);
-	if (mp_int_compare(x, m) >= 0)
-		(void) mp_int_sub(x, m, x);
+		if (mp_int_compare(x, m) >= 0)
+		{
+			(void) mp_int_sub(x, m, x);
+		}
+	}
 
 	/* At this point, x has been properly reduced. */
 	return 1;
 }
 
-/* }}} */
-
-/* {{{ s_embar(a, b, m, mu, c) */
-
-/* Perform modular exponentiation using Barrett's method, where mu is
-   the reduction constant for m.  Assumes a < m, b > 0. */
+/* Perform modular exponentiation using Barrett's method, where mu is the
+   reduction constant for m.  Assumes a < m, b > 0. */
 static mp_result
 s_embar(mp_int a, mp_int b, mp_int m, mp_int mu, mp_int c)
 {
-	mp_digit   *db,
-			   *dbt,
-				umu,
-				d;
-	mpz_t		temp[3];
-	mp_result	res;
-	int			last = 0;
+	mp_digit	umu = MP_USED(mu);
+	mp_digit   *db = MP_DIGITS(b);
+	mp_digit   *dbt = db + MP_USED(b) - 1;
 
-	umu = MP_USED(mu);
-	db = MP_DIGITS(b);
-	dbt = db + MP_USED(b) - 1;
-
-	while (last < 3)
-	{
-		SETUP(mp_int_init_size(TEMP(last), 4 * umu), last);
-		ZERO(MP_DIGITS(TEMP(last - 1)), MP_ALLOC(TEMP(last - 1)));
-	}
+	DECLARE_TEMP(3);
+	REQUIRE(GROW(TEMP(0), 4 * umu));
+	REQUIRE(GROW(TEMP(1), 4 * umu));
+	REQUIRE(GROW(TEMP(2), 4 * umu));
+	ZERO(TEMP(0)->digits, TEMP(0)->alloc);
+	ZERO(TEMP(1)->digits, TEMP(1)->alloc);
+	ZERO(TEMP(2)->digits, TEMP(2)->alloc);
 
 	(void) mp_int_set_value(c, 1);
 
 	/* Take care of low-order digits */
 	while (db < dbt)
 	{
-		int			i;
+		mp_digit	d = *db;
 
-		for (d = *db, i = MP_DIGIT_BIT; i > 0; --i, d >>= 1)
+		for (int i = MP_DIGIT_BIT; i > 0; --i, d >>= 1)
 		{
 			if (d & 1)
 			{
@@ -3327,31 +3125,27 @@ s_embar(mp_int a, mp_int b, mp_int m, mp_int mu, mp_int c)
 				UMUL(c, a, TEMP(0));
 				if (!s_reduce(TEMP(0), m, mu, TEMP(1), TEMP(2)))
 				{
-					res = MP_MEMORY;
-					goto CLEANUP;
+					REQUIRE(MP_MEMORY);
 				}
 				mp_int_copy(TEMP(0), c);
 			}
 
-
 			USQR(a, TEMP(0));
 			assert(MP_SIGN(TEMP(0)) == MP_ZPOS);
 			if (!s_reduce(TEMP(0), m, mu, TEMP(1), TEMP(2)))
 			{
-				res = MP_MEMORY;
-				goto CLEANUP;
+				REQUIRE(MP_MEMORY);
 			}
 			assert(MP_SIGN(TEMP(0)) == MP_ZPOS);
 			mp_int_copy(TEMP(0), a);
-
-
 		}
 
 		++db;
 	}
 
 	/* Take care of highest-order digit */
-	d = *dbt;
+	mp_digit	d = *dbt;
+
 	for (;;)
 	{
 		if (d & 1)
@@ -3359,8 +3153,7 @@ s_embar(mp_int a, mp_int b, mp_int m, mp_int mu, mp_int c)
 			UMUL(c, a, TEMP(0));
 			if (!s_reduce(TEMP(0), m, mu, TEMP(1), TEMP(2)))
 			{
-				res = MP_MEMORY;
-				goto CLEANUP;
+				REQUIRE(MP_MEMORY);
 			}
 			mp_int_copy(TEMP(0), c);
 		}
@@ -3372,170 +3165,272 @@ s_embar(mp_int a, mp_int b, mp_int m, mp_int mu, mp_int c)
 		USQR(a, TEMP(0));
 		if (!s_reduce(TEMP(0), m, mu, TEMP(1), TEMP(2)))
 		{
-			res = MP_MEMORY;
-			goto CLEANUP;
+			REQUIRE(MP_MEMORY);
 		}
 		(void) mp_int_copy(TEMP(0), a);
 	}
 
-CLEANUP:
-	while (--last >= 0)
-		mp_int_clear(TEMP(last));
-
-	return res;
+	CLEANUP_TEMP();
+	return MP_OK;
 }
 
-/* }}} */
+/* Division of nonnegative integers
+
+   This function implements division algorithm for unsigned multi-precision
+   integers. The algorithm is based on Algorithm D from Knuth's "The Art of
+   Computer Programming", 3rd ed. 1998, pg 272-273.
 
-/* {{{ s_udiv(a, b) */
+   We diverge from Knuth's algorithm in that we do not perform the subtraction
+   from the remainder until we have determined that we have the correct
+   quotient digit. This makes our algorithm less efficient that Knuth because
+   we might have to perform multiple multiplication and comparison steps before
+   the subtraction. The advantage is that it is easy to implement and ensure
+   correctness without worrying about underflow from the subtraction.
 
-/* Precondition:  a >= b and b > 0
-   Postcondition: a' = a / b, b' = a % b
+   inputs: u   a n+m digit integer in base b (b is 2^MP_DIGIT_BIT)
+		   v   a n   digit integer in base b (b is 2^MP_DIGIT_BIT)
+		   n >= 1
+		   m >= 0
+  outputs: u / v stored in u
+		   u % v stored in v
  */
 static mp_result
-s_udiv(mp_int a, mp_int b)
-{
-	mpz_t		q,
-				r,
-				t;
-	mp_size		ua,
-				ub,
-				qpos = 0;
-	mp_digit   *da,
-				btop;
-	mp_result	res = MP_OK;
-	int			k,
-				skip = 0;
-
+s_udiv_knuth(mp_int u, mp_int v)
+{
 	/* Force signs to positive */
-	MP_SIGN(a) = MP_ZPOS;
-	MP_SIGN(b) = MP_ZPOS;
+	u->sign = MP_ZPOS;
+	v->sign = MP_ZPOS;
+
+	/* Use simple division algorithm when v is only one digit long */
+	if (MP_USED(v) == 1)
+	{
+		mp_digit	d,
+					rem;
 
-	/* Normalize, per Knuth */
-	k = s_norm(a, b);
+		d = v->digits[0];
+		rem = s_ddiv(u, d);
+		mp_int_set_value(v, rem);
+		return MP_OK;
+	}
 
-	ua = MP_USED(a);
-	ub = MP_USED(b);
-	btop = b->digits[ub - 1];
-	if ((res = mp_int_init_size(&q, ua)) != MP_OK)
-		return res;
-	if ((res = mp_int_init_size(&t, ua + 1)) != MP_OK)
-		goto CLEANUP;
+	/*
+	 * Algorithm D
+	 *
+	 * The n and m variables are defined as used by Knuth. u is an n digit
+	 * number with digits u_{n-1}..u_0. v is an n+m digit number with digits
+	 * from v_{m+n-1}..v_0. We require that n > 1 and m >= 0
+	 */
+	mp_size		n = MP_USED(v);
+	mp_size		m = MP_USED(u) - n;
+
+	assert(n > 1);
+	/* assert(m >= 0) follows because m is unsigned. */
+
+	/*
+	 * D1: Normalize. The normalization step provides the necessary condition
+	 * for Theorem B, which states that the quotient estimate for q_j, call it
+	 * qhat
+	 *
+	 * qhat = u_{j+n}u_{j+n-1} / v_{n-1}
+	 *
+	 * is bounded by
+	 *
+	 * qhat - 2 <= q_j <= qhat.
+	 *
+	 * That is, qhat is always greater than the actual quotient digit q, and
+	 * it is never more than two larger than the actual quotient digit.
+	 */
+	int			k = s_norm(u, v);
+
+	/*
+	 * Extend size of u by one if needed.
+	 *
+	 * The algorithm begins with a value of u that has one more digit of
+	 * input. The normalization step sets u_{m+n}..u_0 = 2^k * u_{m+n-1}..u_0.
+	 * If the multiplication did not increase the number of digits of u, we
+	 * need to add a leading zero here.
+	 */
+	if (k == 0 || MP_USED(u) != m + n + 1)
+	{
+		if (!s_pad(u, m + n + 1))
+			return MP_MEMORY;
+		u->digits[m + n] = 0;
+		u->used = m + n + 1;
+	}
 
-	da = MP_DIGITS(a);
-	r.digits = da + ua - 1;		/* The contents of r are shared with a */
-	r.used = 1;
+	/*
+	 * Add a leading 0 to v.
+	 *
+	 * The multiplication in step D4 multiplies qhat * 0v_{n-1}..v_0.  We need
+	 * to add the leading zero to v here to ensure that the multiplication
+	 * will produce the full n+1 digit result.
+	 */
+	if (!s_pad(v, n + 1))
+		return MP_MEMORY;
+	v->digits[n] = 0;
+
+	/*
+	 * Initialize temporary variables q and t. q allocates space for m+1
+	 * digits to store the quotient digits t allocates space for n+1 digits to
+	 * hold the result of q_j*v
+	 */
+	DECLARE_TEMP(2);
+	REQUIRE(GROW(TEMP(0), m + 1));
+	REQUIRE(GROW(TEMP(1), n + 1));
+
+	/* D2: Initialize j */
+	int			j = m;
+	mpz_t		r;
+
+	r.digits = MP_DIGITS(u) + j;	/* The contents of r are shared with u */
+	r.used = n + 1;
 	r.sign = MP_ZPOS;
-	r.alloc = MP_ALLOC(a);
-	ZERO(t.digits, t.alloc);
+	r.alloc = MP_ALLOC(u);
+	ZERO(TEMP(1)->digits, TEMP(1)->alloc);
 
-	/* Solve for quotient digits, store in q.digits in reverse order */
-	while (r.digits >= da)
+	/* Calculate the m+1 digits of the quotient result */
+	for (; j >= 0; j--)
 	{
-		assert(qpos <= q.alloc);
+		/* D3: Calculate q' */
+		/* r->digits is aligned to position j of the number u */
+		mp_word		pfx,
+					qhat;
 
-		if (s_ucmp(b, &r) > 0)
-		{
-			r.digits -= 1;
-			r.used += 1;
+		pfx = r.digits[n];
+		pfx <<= MP_DIGIT_BIT / 2;
+		pfx <<= MP_DIGIT_BIT / 2;
+		pfx |= r.digits[n - 1]; /* pfx = u_{j+n}{j+n-1} */
 
-			if (++skip > 1)
-				q.digits[qpos++] = 0;
+		qhat = pfx / v->digits[n - 1];
 
-			CLAMP(&r);
-		}
-		else
-		{
-			mp_word		pfx = r.digits[r.used - 1];
-			mp_word		qdigit;
+		/*
+		 * Check to see if qhat > b, and decrease qhat if so. Theorem B
+		 * guarantess that qhat is at most 2 larger than the actual value, so
+		 * it is possible that qhat is greater than the maximum value that
+		 * will fit in a digit
+		 */
+		if (qhat > MP_DIGIT_MAX)
+			qhat = MP_DIGIT_MAX;
 
-			if (r.used > 1 && (pfx < btop || r.digits[r.used - 2] == 0))
-			{
-				pfx <<= MP_DIGIT_BIT / 2;
-				pfx <<= MP_DIGIT_BIT / 2;
-				pfx |= r.digits[r.used - 2];
+		/*
+		 * D4,D5,D6: Multiply qhat * v and test for a correct value of q
+		 *
+		 * We proceed a bit different than the way described by Knuth. This
+		 * way is simpler but less efficent. Instead of doing the multiply and
+		 * subtract then checking for underflow, we first do the multiply of
+		 * qhat * v and see if it is larger than the current remainder r. If
+		 * it is larger, we decrease qhat by one and try again. We may need to
+		 * decrease qhat one more time before we get a value that is smaller
+		 * than r.
+		 *
+		 * This way is less efficent than Knuth becuase we do more multiplies,
+		 * but we do not need to worry about underflow this way.
+		 */
+		/* t = qhat * v */
+		s_dbmul(MP_DIGITS(v), (mp_digit) qhat, TEMP(1)->digits, n + 1);
+		TEMP(1)->used = n + 1;
+		CLAMP(TEMP(1));
+
+		/* Clamp r for the comparison. Comparisons do not like leading zeros. */
+		CLAMP(&r);
+		if (s_ucmp(TEMP(1), &r) > 0)
+		{						/* would the remainder be negative? */
+			qhat -= 1;			/* try a smaller q */
+			s_dbmul(MP_DIGITS(v), (mp_digit) qhat, TEMP(1)->digits, n + 1);
+			TEMP(1)->used = n + 1;
+			CLAMP(TEMP(1));
+			if (s_ucmp(TEMP(1), &r) > 0)
+			{					/* would the remainder be negative? */
+				assert(qhat > 0);
+				qhat -= 1;		/* try a smaller q */
+				s_dbmul(MP_DIGITS(v), (mp_digit) qhat, TEMP(1)->digits, n + 1);
+				TEMP(1)->used = n + 1;
+				CLAMP(TEMP(1));
 			}
+			assert(s_ucmp(TEMP(1), &r) <= 0 && "The mathematics failed us.");
+		}
 
-			qdigit = pfx / btop;
-			if (qdigit > MP_DIGIT_MAX)
-				qdigit = 1;
+		/*
+		 * Unclamp r. The D algorithm expects r = u_{j+n}..u_j to always be
+		 * n+1 digits long.
+		 */
+		r.used = n + 1;
 
-			s_dbmul(MP_DIGITS(b), (mp_digit) qdigit, t.digits, ub);
-			t.used = ub + 1;
-			CLAMP(&t);
-			while (s_ucmp(&t, &r) > 0)
-			{
-				--qdigit;
-				(void) mp_int_sub(&t, b, &t);	/* cannot fail */
-			}
+		/*
+		 * D4: Multiply and subtract
+		 *
+		 * Note: The multiply was completed above so we only need to subtract
+		 * here.
+		 */
+		s_usub(r.digits, TEMP(1)->digits, r.digits, r.used, TEMP(1)->used);
 
-			s_usub(r.digits, t.digits, r.digits, r.used, t.used);
-			CLAMP(&r);
+		/*
+		 * D5: Test remainder
+		 *
+		 * Note: Not needed because we always check that qhat is the correct
+		 * value before performing the subtract.  Value cast to mp_digit to
+		 * prevent warning, qhat has been clamped to MP_DIGIT_MAX
+		 */
+		TEMP(0)->digits[j] = (mp_digit) qhat;
 
-			q.digits[qpos++] = (mp_digit) qdigit;
-			ZERO(t.digits, t.used);
-			skip = 0;
-		}
+		/*
+		 * D6: Add back Note: Not needed because we always check that qhat is
+		 * the correct value before performing the subtract.
+		 */
+
+		/* D7: Loop on j */
+		r.digits--;
+		ZERO(TEMP(1)->digits, TEMP(1)->alloc);
 	}
 
-	/* Put quotient digits in the correct order, and discard extra zeroes */
-	q.used = qpos;
-	REV(mp_digit, q.digits, qpos);
-	CLAMP(&q);
+	/* Get rid of leading zeros in q */
+	TEMP(0)->used = m + 1;
+	CLAMP(TEMP(0));
 
 	/* Denormalize the remainder */
-	CLAMP(a);
+	CLAMP(u);					/* use u here because the r.digits pointer is
+								 * off-by-one */
 	if (k != 0)
-		s_qdiv(a, k);
+		s_qdiv(u, k);
 
-	mp_int_copy(a, b);			/* ok:	0 <= r < b */
-	mp_int_copy(&q, a);			/* ok:	q <= a	   */
+	mp_int_copy(u, v);			/* ok:  0 <= r < v */
+	mp_int_copy(TEMP(0), u);	/* ok:  q <= u     */
 
-	mp_int_clear(&t);
-CLEANUP:
-	mp_int_clear(&q);
-	return res;
+	CLEANUP_TEMP();
+	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ s_outlen(z, r) */
-
-/* Precondition:  2 <= r < 64 */
 static int
 s_outlen(mp_int z, mp_size r)
 {
-	mp_result	bits;
-	double		raw;
+	assert(r >= MP_MIN_RADIX && r <= MP_MAX_RADIX);
 
-	bits = mp_int_count_bits(z);
-	raw = (double) bits * s_log2[r];
+	mp_result	bits = mp_int_count_bits(z);
+	double		raw = (double) bits * s_log2[r];
 
 	return (int) (raw + 0.999999);
 }
 
-/* }}} */
-
-/* {{{ s_inlen(len, r) */
-
 static mp_size
 s_inlen(int len, mp_size r)
 {
 	double		raw = (double) len / s_log2[r];
 	mp_size		bits = (mp_size) (raw + 0.5);
 
-	return (mp_size) ((bits + (MP_DIGIT_BIT - 1)) / MP_DIGIT_BIT);
+	return (mp_size) ((bits + (MP_DIGIT_BIT - 1)) / MP_DIGIT_BIT) + 1;
 }
 
-/* }}} */
-
-/* {{{ s_ch2val(c, r) */
-
 static int
 s_ch2val(char c, int r)
 {
 	int			out;
 
+	/*
+	 * In some locales, isalpha() accepts characters outside the range A-Z,
+	 * producing out<0 or out>=36.  The "out >= r" check will always catch
+	 * out>=36.  Though nothing explicitly catches out<0, our caller reacts
+	 * the same way to every negative return value.
+	 */
 	if (isdigit((unsigned char) c))
 		out = c - '0';
 	else if (r > 10 && isalpha((unsigned char) c))
@@ -3546,39 +3441,36 @@ s_ch2val(char c, int r)
 	return (out >= r) ? -1 : out;
 }
 
-/* }}} */
-
-/* {{{ s_val2ch(v, caps) */
-
 static char
 s_val2ch(int v, int caps)
 {
 	assert(v >= 0);
 
 	if (v < 10)
+	{
 		return v + '0';
+	}
 	else
 	{
 		char		out = (v - 10) + 'a';
 
 		if (caps)
+		{
 			return toupper((unsigned char) out);
+		}
 		else
+		{
 			return out;
+		}
 	}
 }
 
-/* }}} */
-
-/* {{{ s_2comp(buf, len) */
-
 static void
 s_2comp(unsigned char *buf, int len)
 {
-	int			i;
 	unsigned short s = 1;
 
-	for (i = len - 1; i >= 0; --i)
+	for (int i = len - 1; i >= 0; --i)
 	{
 		unsigned char c = ~buf[i];
 
@@ -3592,20 +3484,14 @@ s_2comp(unsigned char *buf, int len)
 	/* last carry out is ignored */
 }
 
-/* }}} */
-
-/* {{{ s_tobin(z, buf, *limpos) */
-
 static mp_result
 s_tobin(mp_int z, unsigned char *buf, int *limpos, int pad)
 {
-	mp_size		uz;
-	mp_digit   *dz;
 	int			pos = 0,
 				limit = *limpos;
+	mp_size		uz = MP_USED(z);
+	mp_digit   *dz = MP_DIGITS(z);
 
-	uz = MP_USED(z);
-	dz = MP_DIGITS(z);
 	while (uz > 0 && pos < limit)
 	{
 		mp_digit	d = *dz++;
@@ -3631,13 +3517,17 @@ s_tobin(mp_int z, unsigned char *buf, int *limpos, int pad)
 	if (pad != 0 && (buf[pos - 1] >> (CHAR_BIT - 1)))
 	{
 		if (pos < limit)
+		{
 			buf[pos++] = 0;
+		}
 		else
+		{
 			uz = 1;
+		}
 	}
 
 	/* Digits are in reverse order, fix that */
-	REV(unsigned char, buf, pos);
+	REV(buf, pos);
 
 	/* Return the number of bytes actually written */
 	*limpos = pos;
@@ -3645,40 +3535,4 @@ s_tobin(mp_int z, unsigned char *buf, int *limpos, int pad)
 	return (uz == 0) ? MP_OK : MP_TRUNC;
 }
 
-/* }}} */
-
-/* {{{ s_print(tag, z) */
-
-#if 0
-void
-s_print(char *tag, mp_int z)
-{
-	int			i;
-
-	fprintf(stderr, "%s: %c ", tag,
-			(MP_SIGN(z) == MP_NEG) ? '-' : '+');
-
-	for (i = MP_USED(z) - 1; i >= 0; --i)
-		fprintf(stderr, "%0*X", (int) (MP_DIGIT_BIT / 4), z->digits[i]);
-
-	fputc('\n', stderr);
-
-}
-
-void
-s_print_buf(char *tag, mp_digit *buf, mp_size num)
-{
-	int			i;
-
-	fprintf(stderr, "%s: ", tag);
-
-	for (i = num - 1; i >= 0; --i)
-		fprintf(stderr, "%0*X", (int) (MP_DIGIT_BIT / 4), buf[i]);
-
-	fputc('\n', stderr);
-}
-#endif
-
-/* }}} */
-
-/* HERE THERE BE DRAGONS */
+/* Here there be dragons */
diff --git a/contrib/pgcrypto/imath.h b/contrib/pgcrypto/imath.h
index 2d7a526..ab9ced1 100644
--- a/contrib/pgcrypto/imath.h
+++ b/contrib/pgcrypto/imath.h
@@ -1,61 +1,59 @@
 /*
-  Name:		imath.h
-  Purpose:	Arbitrary precision integer arithmetic routines.
-  Author:	M. J. Fromberger <http://spinning-yarns.org/michael/sw/>
-  Info:		Id: imath.h 21 2006-04-02 18:58:36Z sting
-
-  Copyright (C) 2002 Michael J. Fromberger, All Rights Reserved.
-
-  Permission is hereby granted, free of charge, to any person
-  obtaining a copy of this software and associated documentation files
-  (the "Software"), to deal in the Software without restriction,
-  including without limitation the rights to use, copy, modify, merge,
-  publish, distribute, sublicense, and/or sell copies of the Software,
-  and to permit persons to whom the Software is furnished to do so,
-  subject to the following conditions:
-
-  The above copyright notice and this permission notice shall be
-  included in all copies or substantial portions of the Software.
-
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-  NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+  Name:     imath.h
+  Purpose:  Arbitrary precision integer arithmetic routines.
+  Author:   M. J. Fromberger
+
+  Copyright (C) 2002-2007 Michael J. Fromberger, All Rights Reserved.
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy
+  of this software and associated documentation files (the "Software"), to deal
+  in the Software without restriction, including without limitation the rights
+  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the Software is
+  furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in
+  all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   SOFTWARE.
  */
-/* contrib/pgcrypto/imath.h */
 
 #ifndef IMATH_H_
 #define IMATH_H_
 
-/* use always 32bit digits - should some arch use 16bit digits? */
-#define USE_LONG_LONG
-
 #include <limits.h>
+#include <stdbool.h>
+#include <stdint.h>
 
 typedef unsigned char mp_sign;
 typedef unsigned int mp_size;
 typedef int mp_result;
+typedef long mp_small;			/* must be a signed type */
+typedef unsigned long mp_usmall;	/* must be an unsigned type */
 
-#ifdef USE_LONG_LONG
-typedef uint32 mp_digit;
-typedef uint64 mp_word;
 
-#define MP_DIGIT_MAX	   0xFFFFFFFFULL
-#define MP_WORD_MAX		   0xFFFFFFFFFFFFFFFFULL
+/* Build with words as uint64_t by default. */
+#ifdef USE_32BIT_WORDS
+typedef uint16_t mp_digit;
+typedef uint32_t mp_word;
+#define MP_DIGIT_MAX  (UINT16_MAX * 1UL)
+#define MP_WORD_MAX   (UINT32_MAX * 1UL)
 #else
-typedef uint16 mp_digit;
-typedef uint32 mp_word;
-
-#define MP_DIGIT_MAX	   0xFFFFUL
-#define MP_WORD_MAX		   0xFFFFFFFFUL
+typedef uint32_t mp_digit;
+typedef uint64_t mp_word;
+#define MP_DIGIT_MAX  (UINT32_MAX * UINT64_C(1))
+#define MP_WORD_MAX   (UINT64_MAX)
 #endif
 
-typedef struct mpz
+typedef struct
 {
+	mp_digit	single;
 	mp_digit   *digits;
 	mp_size		alloc;
 	mp_size		used;
@@ -64,10 +62,26 @@ typedef struct mpz
 
 		   *mp_int;
 
-#define MP_DIGITS(Z) ((Z)->digits)
-#define MP_ALLOC(Z)  ((Z)->alloc)
-#define MP_USED(Z)	 ((Z)->used)
-#define MP_SIGN(Z)	 ((Z)->sign)
+static inline mp_digit *
+MP_DIGITS(mp_int Z)
+{
+	return Z->digits;
+}
+static inline mp_size
+MP_ALLOC(mp_int Z)
+{
+	return Z->alloc;
+}
+static inline mp_size
+MP_USED(mp_int Z)
+{
+	return Z->used;
+}
+static inline mp_sign
+MP_SIGN(mp_int Z)
+{
+	return Z->sign;
+}
 
 extern const mp_result MP_OK;
 extern const mp_result MP_FALSE;
@@ -77,134 +91,357 @@ extern const mp_result MP_RANGE;
 extern const mp_result MP_UNDEF;
 extern const mp_result MP_TRUNC;
 extern const mp_result MP_BADARG;
+extern const mp_result MP_MINERR;
+
+#define MP_DIGIT_BIT   (sizeof(mp_digit) * CHAR_BIT)
+#define MP_WORD_BIT    (sizeof(mp_word) * CHAR_BIT)
+#define MP_SMALL_MIN   LONG_MIN
+#define MP_SMALL_MAX   LONG_MAX
+#define MP_USMALL_MAX  ULONG_MAX
+
+#define MP_MIN_RADIX   2
+#define MP_MAX_RADIX   36
 
-#define MP_DIGIT_BIT	(sizeof(mp_digit) * CHAR_BIT)
-#define MP_WORD_BIT		(sizeof(mp_word) * CHAR_BIT)
+/** Sets the default number of digits allocated to an `mp_int` constructed by
+	`mp_int_init_size()` with `prec == 0`. Allocations are rounded up to
+	multiples of this value. `MP_DEFAULT_PREC` is the default value. Requires
+	`ndigits > 0`. */
+void		mp_int_default_precision(mp_size ndigits);
 
-#define MP_MIN_RADIX	2
-#define MP_MAX_RADIX	36
+/** Sets the number of digits below which multiplication will use the standard
+	quadratic "schoolbook" multiplcation algorithm rather than Karatsuba-Ofman.
+	Requires `ndigits >= sizeof(mp_word)`. */
+void		mp_int_multiply_threshold(mp_size ndigits);
 
+/** A sign indicating a (strictly) negative value. */
 extern const mp_sign MP_NEG;
+
+/** A sign indicating a zero or positive value. */
 extern const mp_sign MP_ZPOS;
 
-#define mp_int_is_odd(Z)  ((Z)->digits[0] & 1)
-#define mp_int_is_even(Z) !((Z)->digits[0] & 1)
+/** Reports whether `z` is odd, having remainder 1 when divided by 2. */
+static inline bool
+mp_int_is_odd(mp_int z)
+{
+	return (z->digits[0] & 1) != 0;
+}
 
-mp_size		mp_get_default_precision(void);
-void		mp_set_default_precision(mp_size s);
-mp_size		mp_get_multiply_threshold(void);
-void		mp_set_multiply_threshold(mp_size s);
+/** Reports whether `z` is even, having remainder 0 when divided by 2. */
+static inline bool
+mp_int_is_even(mp_int z)
+{
+	return (z->digits[0] & 1) == 0;
+}
 
+/** Initializes `z` with 1-digit precision and sets it to zero.  This function
+	cannot fail unless `z == NULL`. */
 mp_result	mp_int_init(mp_int z);
+
+/** Allocates a fresh zero-valued `mpz_t` on the heap, returning NULL in case
+	of error. The only possible error is out-of-memory. */
 mp_int		mp_int_alloc(void);
+
+/** Initializes `z` with at least `prec` digits of storage, and sets it to
+	zero. If `prec` is zero, the default precision is used. In either case the
+	size is rounded up to the nearest multiple of the word size. */
 mp_result	mp_int_init_size(mp_int z, mp_size prec);
+
+/** Initializes `z` to be a copy of an already-initialized value in `old`. The
+	new copy does not share storage with the original. */
 mp_result	mp_int_init_copy(mp_int z, mp_int old);
-mp_result	mp_int_init_value(mp_int z, int value);
-mp_result	mp_int_set_value(mp_int z, int value);
+
+/** Initializes `z` to the specified signed `value` at default precision. */
+mp_result	mp_int_init_value(mp_int z, mp_small value);
+
+/** Initializes `z` to the specified unsigned `value` at default precision. */
+mp_result	mp_int_init_uvalue(mp_int z, mp_usmall uvalue);
+
+/** Sets `z` to the value of the specified signed `value`. */
+mp_result	mp_int_set_value(mp_int z, mp_small value);
+
+/** Sets `z` to the value of the specified unsigned `value`. */
+mp_result	mp_int_set_uvalue(mp_int z, mp_usmall uvalue);
+
+/** Releases the storage used by `z`. */
 void		mp_int_clear(mp_int z);
+
+/** Releases the storage used by `z` and also `z` itself.
+	This should only be used for `z` allocated by `mp_int_alloc()`. */
 void		mp_int_free(mp_int z);
 
-mp_result	mp_int_copy(mp_int a, mp_int c);	/* c = a	 */
-void		mp_int_swap(mp_int a, mp_int c);	/* swap a, c */
-void		mp_int_zero(mp_int z);	/* z = 0	 */
-mp_result	mp_int_abs(mp_int a, mp_int c); /* c = |a|	 */
-mp_result	mp_int_neg(mp_int a, mp_int c); /* c = -a	 */
-mp_result	mp_int_add(mp_int a, mp_int b, mp_int c);	/* c = a + b */
-mp_result	mp_int_add_value(mp_int a, int value, mp_int c);
-mp_result	mp_int_sub(mp_int a, mp_int b, mp_int c);	/* c = a - b */
-mp_result	mp_int_sub_value(mp_int a, int value, mp_int c);
-mp_result	mp_int_mul(mp_int a, mp_int b, mp_int c);	/* c = a * b */
-mp_result	mp_int_mul_value(mp_int a, int value, mp_int c);
-mp_result	mp_int_mul_pow2(mp_int a, int p2, mp_int c);
-mp_result	mp_int_sqr(mp_int a, mp_int c); /* c = a * a */
-
-mp_result mp_int_div(mp_int a, mp_int b,		/* q = a / b */
-		   mp_int q, mp_int r); /* r = a % b */
-mp_result mp_int_div_value(mp_int a, int value,		/* q = a / value */
-				 mp_int q, int *r); /* r = a % value */
-mp_result mp_int_div_pow2(mp_int a, int p2,		/* q = a / 2^p2  */
-				mp_int q, mp_int r);	/* r = q % 2^p2  */
-mp_result	mp_int_mod(mp_int a, mp_int m, mp_int c);	/* c = a % m */
-
-#define   mp_int_mod_value(A, V, R) mp_int_div_value((A), (V), 0, (R))
-mp_result	mp_int_expt(mp_int a, int b, mp_int c); /* c = a^b	 */
-mp_result	mp_int_expt_value(int a, int b, mp_int c);	/* c = a^b	 */
-
-int			mp_int_compare(mp_int a, mp_int b); /* a <=> b	   */
-int			mp_int_compare_unsigned(mp_int a, mp_int b);	/* |a| <=> |b| */
-int			mp_int_compare_zero(mp_int z);	/* a <=> 0	   */
-int			mp_int_compare_value(mp_int z, int value);	/* a <=> v	   */
-
-/* Returns true if v|a, false otherwise (including errors) */
-int			mp_int_divisible_value(mp_int a, int v);
-
-/* Returns k >= 0 such that z = 2^k, if one exists; otherwise < 0 */
+/** Replaces the value of `c` with a copy of the value of `a`. No new memory is
+	allocated unless `a` has more significant digits than `c` has allocated. */
+mp_result	mp_int_copy(mp_int a, mp_int c);
+
+/** Swaps the values and storage between `a` and `c`. */
+void		mp_int_swap(mp_int a, mp_int c);
+
+/** Sets `z` to zero. The allocated storage of `z` is not changed. */
+void		mp_int_zero(mp_int z);
+
+/** Sets `c` to the absolute value of `a`. */
+mp_result	mp_int_abs(mp_int a, mp_int c);
+
+/** Sets `c` to the additive inverse (negation) of `a`. */
+mp_result	mp_int_neg(mp_int a, mp_int c);
+
+/** Sets `c` to the sum of `a` and `b`. */
+mp_result	mp_int_add(mp_int a, mp_int b, mp_int c);
+
+/** Sets `c` to the sum of `a` and `value`. */
+mp_result	mp_int_add_value(mp_int a, mp_small value, mp_int c);
+
+/** Sets `c` to the difference of `a` less `b`. */
+mp_result	mp_int_sub(mp_int a, mp_int b, mp_int c);
+
+/** Sets `c` to the difference of `a` less `value`. */
+mp_result	mp_int_sub_value(mp_int a, mp_small value, mp_int c);
+
+/** Sets `c` to the product of `a` and `b`. */
+mp_result	mp_int_mul(mp_int a, mp_int b, mp_int c);
+
+/** Sets `c` to the product of `a` and `value`. */
+mp_result	mp_int_mul_value(mp_int a, mp_small value, mp_int c);
+
+/** Sets `c` to the product of `a` and `2^p2`. Requires `p2 >= 0`. */
+mp_result	mp_int_mul_pow2(mp_int a, mp_small p2, mp_int c);
+
+/** Sets `c` to the square of `a`. */
+mp_result	mp_int_sqr(mp_int a, mp_int c);
+
+/** Sets `q` and `r` to the quotent and remainder of `a / b`. Division by
+	powers of 2 is detected and handled efficiently.  The remainder is pinned
+	to `0 <= r < b`.
+
+	Either of `q` or `r` may be NULL, but not both, and `q` and `r` may not
+	point to the same value. */
+mp_result	mp_int_div(mp_int a, mp_int b, mp_int q, mp_int r);
+
+/** Sets `q` and `*r` to the quotent and remainder of `a / value`. Division by
+	powers of 2 is detected and handled efficiently. The remainder is pinned to
+	`0 <= *r < b`. Either of `q` or `r` may be NULL. */
+mp_result	mp_int_div_value(mp_int a, mp_small value, mp_int q, mp_small * r);
+
+/** Sets `q` and `r` to the quotient and remainder of `a / 2^p2`. This is a
+	special case for division by powers of two that is more efficient than
+	using ordinary division. Note that `mp_int_div()` will automatically handle
+	this case, this function is for cases where you have only the exponent. */
+mp_result	mp_int_div_pow2(mp_int a, mp_small p2, mp_int q, mp_int r);
+
+/** Sets `c` to the remainder of `a / m`.
+	The remainder is pinned to `0 <= c < m`. */
+mp_result	mp_int_mod(mp_int a, mp_int m, mp_int c);
+
+/** Sets `c` to the value of `a` raised to the `b` power.
+	It returns `MP_RANGE` if `b < 0`. */
+mp_result	mp_int_expt(mp_int a, mp_small b, mp_int c);
+
+/** Sets `c` to the value of `a` raised to the `b` power.
+	It returns `MP_RANGE` if `b < 0`. */
+mp_result	mp_int_expt_value(mp_small a, mp_small b, mp_int c);
+
+/** Sets `c` to the value of `a` raised to the `b` power.
+	It returns `MP_RANGE`) if `b < 0`. */
+mp_result	mp_int_expt_full(mp_int a, mp_int b, mp_int c);
+
+/** Sets `*r` to the remainder of `a / value`.
+	The remainder is pinned to `0 <= r < value`. */
+static inline
+mp_result
+mp_int_mod_value(mp_int a, mp_small value, mp_small * r)
+{
+	return mp_int_div_value(a, value, 0, r);
+}
+
+/** Returns the comparator of `a` and `b`. */
+int			mp_int_compare(mp_int a, mp_int b);
+
+/** Returns the comparator of the magnitudes of `a` and `b`, disregarding their
+	signs. Neither `a` nor `b` is modified by the comparison. */
+int			mp_int_compare_unsigned(mp_int a, mp_int b);
+
+/** Returns the comparator of `z` and zero. */
+int			mp_int_compare_zero(mp_int z);
+
+/** Returns the comparator of `z` and the signed value `v`. */
+int			mp_int_compare_value(mp_int z, mp_small v);
+
+/** Returns the comparator of `z` and the unsigned value `uv`. */
+int			mp_int_compare_uvalue(mp_int z, mp_usmall uv);
+
+/** Reports whether `a` is divisible by `v`. */
+bool		mp_int_divisible_value(mp_int a, mp_small v);
+
+/** Returns `k >= 0` such that `z` is `2^k`, if such a `k` exists. If no such
+	`k` exists, the function returns -1. */
 int			mp_int_is_pow2(mp_int z);
 
-mp_result mp_int_exptmod(mp_int a, mp_int b, mp_int m,
-			   mp_int c);		/* c = a^b (mod m) */
-mp_result mp_int_exptmod_evalue(mp_int a, int value,
-					  mp_int m, mp_int c);	/* c = a^v (mod m) */
-mp_result mp_int_exptmod_bvalue(int value, mp_int b,
-					  mp_int m, mp_int c);	/* c = v^b (mod m) */
-mp_result mp_int_exptmod_known(mp_int a, mp_int b,
-					 mp_int m, mp_int mu,
-					 mp_int c); /* c = a^b (mod m) */
+/** Sets `c` to the value of `a` raised to the `b` power, reduced modulo `m`.
+	It returns `MP_RANGE` if `b < 0` or `MP_UNDEF` if `m == 0`. */
+mp_result	mp_int_exptmod(mp_int a, mp_int b, mp_int m, mp_int c);
+
+/** Sets `c` to the value of `a` raised to the `value` power, modulo `m`.
+	It returns `MP_RANGE` if `value < 0` or `MP_UNDEF` if `m == 0`. */
+mp_result	mp_int_exptmod_evalue(mp_int a, mp_small value, mp_int m, mp_int c);
+
+/** Sets `c` to the value of `value` raised to the `b` power, modulo `m`.
+	It returns `MP_RANGE` if `b < 0` or `MP_UNDEF` if `m == 0`. */
+mp_result	mp_int_exptmod_bvalue(mp_small value, mp_int b, mp_int m, mp_int c);
+
+/** Sets `c` to the value of `a` raised to the `b` power, reduced modulo `m`,
+	given a precomputed reduction constant `mu` defined for Barrett's modular
+	reduction algorithm.
+
+	It returns `MP_RANGE` if `b < 0` or `MP_UNDEF` if `m == 0`. */
+mp_result	mp_int_exptmod_known(mp_int a, mp_int b, mp_int m, mp_int mu, mp_int c);
+
+/** Sets `c` to the reduction constant for Barrett reduction by modulus `m`.
+	Requires that `c` and `m` point to distinct locations. */
 mp_result	mp_int_redux_const(mp_int m, mp_int c);
 
-mp_result	mp_int_invmod(mp_int a, mp_int m, mp_int c);	/* c = 1/a (mod m) */
+/** Sets `c` to the multiplicative inverse of `a` modulo `m`, if it exists.
+	The least non-negative representative of the congruence class is computed.
+
+	It returns `MP_UNDEF` if the inverse does not exist, or `MP_RANGE` if `a ==
+	0` or `m <= 0`. */
+mp_result	mp_int_invmod(mp_int a, mp_int m, mp_int c);
+
+/** Sets `c` to the greatest common divisor of `a` and `b`.
+
+	It returns `MP_UNDEF` if the GCD is undefined, such as for example if `a`
+	and `b` are both zero. */
+mp_result	mp_int_gcd(mp_int a, mp_int b, mp_int c);
 
-mp_result	mp_int_gcd(mp_int a, mp_int b, mp_int c);	/* c = gcd(a, b)   */
+/** Sets `c` to the greatest common divisor of `a` and `b`, and sets `x` and
+	`y` to values satisfying Bezout's identity `gcd(a, b) = ax + by`.
 
-mp_result mp_int_egcd(mp_int a, mp_int b, mp_int c,		/* c = gcd(a, b)   */
-			mp_int x, mp_int y);	/* c = ax + by	   */
+	It returns `MP_UNDEF` if the GCD is undefined, such as for example if `a`
+	and `b` are both zero. */
+mp_result	mp_int_egcd(mp_int a, mp_int b, mp_int c, mp_int x, mp_int y);
 
-mp_result	mp_int_sqrt(mp_int a, mp_int c);	/* c = floor(sqrt(q)) */
+/** Sets `c` to the least common multiple of `a` and `b`.
 
-/* Convert to an int, if representable (returns MP_RANGE if not). */
-mp_result	mp_int_to_int(mp_int z, int *out);
+	It returns `MP_UNDEF` if the LCM is undefined, such as for example if `a`
+	and `b` are both zero. */
+mp_result	mp_int_lcm(mp_int a, mp_int b, mp_int c);
 
-/* Convert to nul-terminated string with the specified radix, writing at
-   most limit characters including the nul terminator  */
-mp_result mp_int_to_string(mp_int z, mp_size radix,
-				 char *str, int limit);
+/** Sets `c` to the greatest integer not less than the `b`th root of `a`,
+	using Newton's root-finding algorithm.
+	It returns `MP_UNDEF` if `a < 0` and `b` is even. */
+mp_result	mp_int_root(mp_int a, mp_small b, mp_int c);
 
-/* Return the number of characters required to represent
-   z in the given radix.  May over-estimate. */
+/** Sets `c` to the greatest integer not less than the square root of `a`.
+	This is a special case of `mp_int_root()`. */
+static inline
+mp_result
+mp_int_sqrt(mp_int a, mp_int c)
+{
+	return mp_int_root(a, 2, c);
+}
+
+/** Returns `MP_OK` if `z` is representable as `mp_small`, else `MP_RANGE`.
+	If `out` is not NULL, `*out` is set to the value of `z` when `MP_OK`. */
+mp_result	mp_int_to_int(mp_int z, mp_small * out);
+
+/** Returns `MP_OK` if `z` is representable as `mp_usmall`, or `MP_RANGE`.
+	If `out` is not NULL, `*out` is set to the value of `z` when `MP_OK`. */
+mp_result	mp_int_to_uint(mp_int z, mp_usmall * out);
+
+/** Converts `z` to a zero-terminated string of characters in the specified
+	`radix`, writing at most `limit` characters to `str` including the
+	terminating NUL value. A leading `-` is used to indicate a negative value.
+
+	Returns `MP_TRUNC` if `limit` was to small to write all of `z`.
+	Requires `MP_MIN_RADIX <= radix <= MP_MAX_RADIX`. */
+mp_result	mp_int_to_string(mp_int z, mp_size radix, char *str, int limit);
+
+/** Reports the minimum number of characters required to represent `z` as a
+	zero-terminated string in the given `radix`.
+	Requires `MP_MIN_RADIX <= radix <= MP_MAX_RADIX`. */
 mp_result	mp_int_string_len(mp_int z, mp_size radix);
 
-/* Read zero-terminated string into z */
+/** Reads a string of ASCII digits in the specified `radix` from the zero
+	terminated `str` provided into `z`. For values of `radix > 10`, the letters
+	`A`..`Z` or `a`..`z` are accepted. Letters are interpreted without respect
+	to case.
+
+	Leading whitespace is ignored, and a leading `+` or `-` is interpreted as a
+	sign flag. Processing stops when a NUL or any other character out of range
+	for a digit in the given radix is encountered.
+
+	If the whole string was consumed, `MP_OK` is returned; otherwise
+	`MP_TRUNC`. is returned.
+
+	Requires `MP_MIN_RADIX <= radix <= MP_MAX_RADIX`. */
 mp_result	mp_int_read_string(mp_int z, mp_size radix, const char *str);
-mp_result mp_int_read_cstring(mp_int z, mp_size radix, const char *str,
-					char **end);
 
-/* Return the number of significant bits in z */
+/** Reads a string of ASCII digits in the specified `radix` from the zero
+	terminated `str` provided into `z`. For values of `radix > 10`, the letters
+	`A`..`Z` or `a`..`z` are accepted. Letters are interpreted without respect
+	to case.
+
+	Leading whitespace is ignored, and a leading `+` or `-` is interpreted as a
+	sign flag. Processing stops when a NUL or any other character out of range
+	for a digit in the given radix is encountered.
+
+	If the whole string was consumed, `MP_OK` is returned; otherwise
+	`MP_TRUNC`. is returned. If `end` is not NULL, `*end` is set to point to
+	the first unconsumed byte of the input string (the NUL byte if the whole
+	string was consumed). This emulates the behavior of the standard C
+	`strtol()` function.
+
+	Requires `MP_MIN_RADIX <= radix <= MP_MAX_RADIX`. */
+mp_result	mp_int_read_cstring(mp_int z, mp_size radix, const char *str, char **end);
+
+/** Returns the number of significant bits in `z`. */
 mp_result	mp_int_count_bits(mp_int z);
 
-/* Convert z to two's complement binary, writing at most limit bytes */
+/** Converts `z` to 2's complement binary, writing at most `limit` bytes into
+	the given `buf`.  Returns `MP_TRUNC` if the buffer limit was too small to
+	contain the whole value.  If this occurs, the contents of buf will be
+	effectively garbage, as the function uses the buffer as scratch space.
+
+	The binary representation of `z` is in base-256 with digits ordered from
+	most significant to least significant (network byte ordering).  The
+	high-order bit of the first byte is set for negative values, clear for
+	non-negative values.
+
+	As a result, non-negative values will be padded with a leading zero byte if
+	the high-order byte of the base-256 magnitude is set.  This extra byte is
+	accounted for by the `mp_int_binary_len()` function. */
 mp_result	mp_int_to_binary(mp_int z, unsigned char *buf, int limit);
 
-/* Read a two's complement binary value into z from the given buffer */
+/** Reads a 2's complement binary value from `buf` into `z`, where `len` is the
+	length of the buffer.  The contents of `buf` may be overwritten during
+	processing, although they will be restored when the function returns. */
 mp_result	mp_int_read_binary(mp_int z, unsigned char *buf, int len);
 
-/* Return the number of bytes required to represent z in binary. */
+/** Returns the number of bytes to represent `z` in 2's complement binary. */
 mp_result	mp_int_binary_len(mp_int z);
 
-/* Convert z to unsigned binary, writing at most limit bytes */
+/** Converts the magnitude of `z` to unsigned binary, writing at most `limit`
+	bytes into the given `buf`.  The sign of `z` is ignored, but `z` is not
+	modified.  Returns `MP_TRUNC` if the buffer limit was too small to contain
+	the whole value.  If this occurs, the contents of `buf` will be effectively
+	garbage, as the function uses the buffer as scratch space during
+	conversion.
+
+	The binary representation of `z` is in base-256 with digits ordered from
+	most significant to least significant (network byte ordering). */
 mp_result	mp_int_to_unsigned(mp_int z, unsigned char *buf, int limit);
 
-/* Read an unsigned binary value into z from the given buffer */
+/** Reads an unsigned binary value from `buf` into `z`, where `len` is the
+	length of the buffer. The contents of `buf` are not modified during
+	processing. */
 mp_result	mp_int_read_unsigned(mp_int z, unsigned char *buf, int len);
 
-/* Return the number of bytes required to represent z as unsigned output */
+/** Returns the number of bytes required to represent `z` as an unsigned binary
+	value in base 256. */
 mp_result	mp_int_unsigned_len(mp_int z);
 
-/* Return a statically allocated string describing error code res */
+/** Returns a pointer to a brief, human-readable, zero-terminated string
+	describing `res`. The returned string is statically allocated and must not
+	be freed by the caller. */
 const char *mp_error_string(mp_result res);
 
-#if 0
-void		s_print(char *tag, mp_int z);
-void		s_print_buf(char *tag, mp_digit *buf, mp_size num);
-#endif
-
 #endif							/* end IMATH_H_ */
imath1.29-pgedits-v1.patchtext/plain; charset=us-asciiDownload
diff --git a/configure b/configure
index d5ace62..60b0d90 100755
--- a/configure
+++ b/configure
@@ -732,6 +732,7 @@ CPP
 BITCODE_CXXFLAGS
 BITCODE_CFLAGS
 CFLAGS_VECTOR
+PERMIT_DECLARATION_AFTER_STATEMENT
 LLVM_BINPATH
 LLVM_CXXFLAGS
 LLVM_CFLAGS
@@ -5252,6 +5253,7 @@ if test "$GCC" = yes -a "$ICC" = no; then
   CFLAGS="-Wall -Wmissing-prototypes -Wpointer-arith"
   CXXFLAGS="-Wall -Wpointer-arith"
   # These work in some but not all gcc versions
+  save_CFLAGS=$CFLAGS
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC} supports -Wdeclaration-after-statement, for CFLAGS" >&5
 $as_echo_n "checking whether ${CC} supports -Wdeclaration-after-statement, for CFLAGS... " >&6; }
@@ -5292,7 +5294,13 @@ if test x"$pgac_cv_prog_CC_cflags__Wdeclaration_after_statement" = x"yes"; then
 fi
 
 
-  # -Wdeclaration-after-statement isn't applicable for C++
+  # -Wdeclaration-after-statement isn't applicable for C++.  Specific C files
+  # disable it, so AC_SUBST the negative form.
+  PERMIT_DECLARATION_AFTER_STATEMENT=
+  if test x"$save_CFLAGS" != "$CFLAGS"; then
+    PERMIT_DECLARATION_AFTER_STATEMENT=-Wno-declaration-after-statement
+  fi
+
   # Really don't want VLAs to be used in our dialect of C
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC} supports -Werror=vla, for CFLAGS" >&5
diff --git a/configure.in b/configure.in
index 4efb912..c1edc8c 100644
--- a/configure.in
+++ b/configure.in
@@ -476,8 +476,15 @@ if test "$GCC" = yes -a "$ICC" = no; then
   CFLAGS="-Wall -Wmissing-prototypes -Wpointer-arith"
   CXXFLAGS="-Wall -Wpointer-arith"
   # These work in some but not all gcc versions
+  save_CFLAGS=$CFLAGS
   PGAC_PROG_CC_CFLAGS_OPT([-Wdeclaration-after-statement])
-  # -Wdeclaration-after-statement isn't applicable for C++
+  # -Wdeclaration-after-statement isn't applicable for C++.  Specific C files
+  # disable it, so AC_SUBST the negative form.
+  PERMIT_DECLARATION_AFTER_STATEMENT=
+  if test x"$save_CFLAGS" != "$CFLAGS"; then
+    PERMIT_DECLARATION_AFTER_STATEMENT=-Wno-declaration-after-statement
+  fi
+  AC_SUBST(PERMIT_DECLARATION_AFTER_STATEMENT)
   # Really don't want VLAs to be used in our dialect of C
   PGAC_PROG_CC_CFLAGS_OPT([-Werror=vla])
   # -Wvla is not applicable for C++
diff --git a/contrib/pgcrypto/Makefile b/contrib/pgcrypto/Makefile
index 573bc6d..1313b66 100644
--- a/contrib/pgcrypto/Makefile
+++ b/contrib/pgcrypto/Makefile
@@ -59,6 +59,9 @@ SHLIB_LINK += $(filter -leay32, $(LIBS))
 SHLIB_LINK += -lws2_32
 endif
 
+# Upstream uses a larger subset of C99.
+imath.o: CFLAGS+=$(PERMIT_DECLARATION_AFTER_STATEMENT)
+
 rijndael.o: rijndael.tbl
 
 rijndael.tbl:
diff --git a/contrib/pgcrypto/imath.c b/contrib/pgcrypto/imath.c
index 96be668..c72f965 100644
--- a/contrib/pgcrypto/imath.c
+++ b/contrib/pgcrypto/imath.c
@@ -1,6 +1,27 @@
+/*-------------------------------------------------------------------------
+ *
+ * imath.c
+ *
+ * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
+ *
+ *
+ * IDENTIFICATION
+ *	  contrib/pgcrypto/imath.c
+ *
+ * Changes versus https://github.com/creachadair/imath are:
+ * - replace malloc(), realloc() and free() with px_ versions
+ * - redirect assert() to Assert()
+ * - #undef MIN, #undef MAX before defining them
+ * - remove includes covered by c.h
+ * - rename DEBUG to IMATH_DEBUG
+ *
+ * Last synchronized from version 1.29.  Upstream copyright terms follow.
+ *-------------------------------------------------------------------------
+ */
+
 /*
-  Name:     imath.c
-  Purpose:  Arbitrary precision integer arithmetic routines.
+  Name:		imath.c
+  Purpose:	Arbitrary precision integer arithmetic routines.
   Author:   M. J. Fromberger
 
   Copyright (C) 2002-2007 Michael J. Fromberger, All Rights Reserved.
@@ -24,12 +45,13 @@
   SOFTWARE.
  */
 
+#include "postgres.h"
+
 #include "imath.h"
+#include "px.h"
 
-#include <assert.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
+#undef assert
+#define assert(TEST) Assert(TEST)
 
 const mp_result MP_OK = 0;		/* no error, all is well  */
 const mp_result MP_FALSE = 0;	/* boolean false          */
@@ -135,6 +157,8 @@ CLAMP(mp_int z_)
 }
 
 /* Select min/max. */
+#undef MIN
+#undef MAX
 static inline int
 MIN(int A, int B)
 {
@@ -435,7 +459,7 @@ mp_int_init(mp_int z)
 mp_int
 mp_int_alloc(void)
 {
-	mp_int		out = malloc(sizeof(mpz_t));
+	mp_int		out = px_alloc(sizeof(mpz_t));
 
 	if (out != NULL)
 		mp_int_init(out);
@@ -561,7 +585,7 @@ mp_int_free(mp_int z)
 	assert(z != NULL);
 
 	mp_int_clear(z);
-	free(z);					/* note: NOT s_free() */
+	px_free(z);					/* note: NOT s_free() */
 }
 
 mp_result
@@ -2162,18 +2186,18 @@ mp_error_string(mp_result res)
 /*------------------------------------------------------------------------*/
 /* Private functions for internal use.  These make assumptions.           */
 
-#if DEBUG
+#if IMATH_DEBUG
 static const mp_digit fill = (mp_digit) 0xdeadbeefabad1dea;
 #endif
 
 static mp_digit *
 s_alloc(mp_size num)
 {
-	mp_digit   *out = malloc(num * sizeof(mp_digit));
+	mp_digit   *out = px_alloc(num * sizeof(mp_digit));
 
 	assert(out != NULL);
 
-#if DEBUG
+#if IMATH_DEBUG
 	for (mp_size ix = 0; ix < num; ++ix)
 		out[ix] = fill;
 #endif
@@ -2183,7 +2207,7 @@ s_alloc(mp_size num)
 static mp_digit *
 s_realloc(mp_digit *old, mp_size osize, mp_size nsize)
 {
-#if DEBUG
+#if IMATH_DEBUG
 	mp_digit   *new = s_alloc(nsize);
 
 	assert(new != NULL);
@@ -2192,7 +2216,7 @@ s_realloc(mp_digit *old, mp_size osize, mp_size nsize)
 		new[ix] = fill;
 	memcpy(new, old, osize * sizeof(mp_digit));
 #else
-	mp_digit   *new = realloc(old, nsize * sizeof(mp_digit));
+	mp_digit   *new = px_realloc(old, nsize * sizeof(mp_digit));
 
 	assert(new != NULL);
 #endif
@@ -2203,7 +2227,7 @@ s_realloc(mp_digit *old, mp_size osize, mp_size nsize)
 static void
 s_free(void *ptr)
 {
-	free(ptr);
+	px_free(ptr);
 }
 
 static bool
diff --git a/contrib/pgcrypto/imath.h b/contrib/pgcrypto/imath.h
index ab9ced1..65be748 100644
--- a/contrib/pgcrypto/imath.h
+++ b/contrib/pgcrypto/imath.h
@@ -28,8 +28,6 @@
 #define IMATH_H_
 
 #include <limits.h>
-#include <stdbool.h>
-#include <stdint.h>
 
 typedef unsigned char mp_sign;
 typedef unsigned int mp_size;
diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index 758ea43..93ab893 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -261,6 +261,7 @@ CFLAGS = @CFLAGS@
 CFLAGS_VECTOR = @CFLAGS_VECTOR@
 CFLAGS_SSE42 = @CFLAGS_SSE42@
 CFLAGS_ARMV8_CRC32C = @CFLAGS_ARMV8_CRC32C@
+PERMIT_DECLARATION_AFTER_STATEMENT = @PERMIT_DECLARATION_AFTER_STATEMENT@
 CXXFLAGS = @CXXFLAGS@
 
 LLVM_CPPFLAGS = @LLVM_CPPFLAGS@
#2Andrew Gierth
andrew@tao11.riddles.org.uk
In reply to: Noah Misch (#1)
Re: Synchronize with imath upstream

"Noah" == Noah Misch <noah@leadboat.com> writes:

Noah> If the compiler supports -Wdeclaration-after-statement, I add
Noah> -Wno-declaration-after-statement for imath.c.

I found it much simpler to strip out -Wdeclaration-after-statement
instead:

$(RYU_OBJS): override CFLAGS := $(filter-out -Wdeclaration-after-statement,$(CFLAGS))

--
Andrew (irc:RhodiumToad)

#3Noah Misch
noah@leadboat.com
In reply to: Andrew Gierth (#2)
Re: Synchronize with imath upstream

On Sun, Feb 03, 2019 at 06:01:51AM +0000, Andrew Gierth wrote:

"Noah" == Noah Misch <noah@leadboat.com> writes:

Noah> If the compiler supports -Wdeclaration-after-statement, I add
Noah> -Wno-declaration-after-statement for imath.c.

I found it much simpler to strip out -Wdeclaration-after-statement
instead:

$(RYU_OBJS): override CFLAGS := $(filter-out -Wdeclaration-after-statement,$(CFLAGS))

The -Wno-declaration-after-statement approach takes eight lines of code, and
the filter-out approach takes one. On the other hand, using $(filter-out)
changes any runs of whitespace to single spaces ("$(filter-out foo,a b c)"
yields "a b c"). We do risk that with CPPFLAGS and LDFLAGS in a few places.
I don't want to proliferate that practice, because it changes semantics of
CFLAGS containing -DFOO="arbitrary text".

#4Andrew Gierth
andrew@tao11.riddles.org.uk
In reply to: Noah Misch (#3)
Re: Synchronize with imath upstream

"Noah" == Noah Misch <noah@leadboat.com> writes:

I found it much simpler to strip out -Wdeclaration-after-statement
instead:

$(RYU_OBJS): override CFLAGS := $(filter-out -Wdeclaration-after-statement,$(CFLAGS))

Noah> The -Wno-declaration-after-statement approach takes eight lines
Noah> of code, and the filter-out approach takes one. On the other
Noah> hand, using $(filter-out) changes any runs of whitespace to
Noah> single spaces ("$(filter-out foo,a b c)" yields "a b c"). We do
Noah> risk that with CPPFLAGS and LDFLAGS in a few places. I don't want
Noah> to proliferate that practice, because it changes semantics of
Noah> CFLAGS containing -DFOO="arbitrary text".

In that case I propose that we avoid the whole issue by removing
-Wdeclaration-after-statement entirely.

So far, expressed opinions have run about 4:2 in favour of allowing
mixed declarations and code.

--
Andrew (irc:RhodiumToad)

#5Andrew Gierth
andrew@tao11.riddles.org.uk
In reply to: Noah Misch (#1)
Re: Synchronize with imath upstream

"Noah" == Noah Misch <noah@leadboat.com> writes:

Noah> - # -Wdeclaration-after-statement isn't applicable for C++
Noah> + # -Wdeclaration-after-statement isn't applicable for C++. Specific C files
Noah> + # disable it, so AC_SUBST the negative form.
Noah> + PERMIT_DECLARATION_AFTER_STATEMENT=
Noah> + if test x"$save_CFLAGS" != "$CFLAGS"; then

Missing "x" here?

+ if test x"$save_CFLAGS" != x"$CFLAGS"; then

--
Andrew (irc:RhodiumToad)

#6Noah Misch
noah@leadboat.com
In reply to: Andrew Gierth (#5)
Re: Synchronize with imath upstream

On Sun, Feb 03, 2019 at 07:07:36AM +0000, Andrew Gierth wrote:

In that case I propose that we avoid the whole issue by removing
-Wdeclaration-after-statement entirely.

Some folks who skip $SUBJECT will be interested in your proposal. If you wish
to pursue that proposal, please start a new thread.

On Sun, Feb 03, 2019 at 07:14:13AM +0000, Andrew Gierth wrote:

"Noah" == Noah Misch <noah@leadboat.com> writes:

Noah> - # -Wdeclaration-after-statement isn't applicable for C++
Noah> + # -Wdeclaration-after-statement isn't applicable for C++. Specific C files
Noah> + # disable it, so AC_SUBST the negative form.
Noah> + PERMIT_DECLARATION_AFTER_STATEMENT=
Noah> + if test x"$save_CFLAGS" != "$CFLAGS"; then

Missing "x" here?

+ if test x"$save_CFLAGS" != x"$CFLAGS"; then

I'll incorporate your fix. Thanks.

#7Tom Lane
tgl@sss.pgh.pa.us
In reply to: Noah Misch (#3)
Re: Synchronize with imath upstream

Noah Misch <noah@leadboat.com> writes:

The -Wno-declaration-after-statement approach takes eight lines of code, and
the filter-out approach takes one. On the other hand, using $(filter-out)
changes any runs of whitespace to single spaces ("$(filter-out foo,a b c)"
yields "a b c"). We do risk that with CPPFLAGS and LDFLAGS in a few places.
I don't want to proliferate that practice, because it changes semantics of
CFLAGS containing -DFOO="arbitrary text".

I don't particularly buy that argument, because CPPFLAGS is where any -D
switches ought to be put. So we've already exposed ourselves to this
risk, in the unlikely scenario where it's not hypothetical.

regards, tom lane

#8David Fetter
david@fetter.org
In reply to: Andrew Gierth (#4)
Re: Synchronize with imath upstream

On Sun, Feb 03, 2019 at 07:07:36AM +0000, Andrew Gierth wrote:

"Noah" == Noah Misch <noah@leadboat.com> writes:

I found it much simpler to strip out -Wdeclaration-after-statement
instead:

$(RYU_OBJS): override CFLAGS := $(filter-out -Wdeclaration-after-statement,$(CFLAGS))

Noah> The -Wno-declaration-after-statement approach takes eight lines
Noah> of code, and the filter-out approach takes one. On the other
Noah> hand, using $(filter-out) changes any runs of whitespace to
Noah> single spaces ("$(filter-out foo,a b c)" yields "a b c"). We do
Noah> risk that with CPPFLAGS and LDFLAGS in a few places. I don't want
Noah> to proliferate that practice, because it changes semantics of
Noah> CFLAGS containing -DFOO="arbitrary text".

In that case I propose that we avoid the whole issue by removing
-Wdeclaration-after-statement entirely.

So far, expressed opinions have run about 4:2 in favour of allowing
mixed declarations and code.

+1 for this.

Best,
David.
--
David Fetter <david(at)fetter(dot)org> http://fetter.org/
Phone: +1 415 235 3778

Remember to vote!
Consider donating to Postgres: http://www.postgresql.org/about/donate

#9Noah Misch
noah@leadboat.com
In reply to: Tom Lane (#7)
Re: Synchronize with imath upstream

On Sun, Feb 03, 2019 at 10:31:26AM -0500, Tom Lane wrote:

Noah Misch <noah@leadboat.com> writes:

The -Wno-declaration-after-statement approach takes eight lines of code, and
the filter-out approach takes one. On the other hand, using $(filter-out)
changes any runs of whitespace to single spaces ("$(filter-out foo,a b c)"
yields "a b c"). We do risk that with CPPFLAGS and LDFLAGS in a few places.
I don't want to proliferate that practice, because it changes semantics of
CFLAGS containing -DFOO="arbitrary text".

I don't particularly buy that argument, because CPPFLAGS is where any -D
switches ought to be put. So we've already exposed ourselves to this
risk, in the unlikely scenario where it's not hypothetical.

The $(filter-out) corruption is unlikely to matter, indeed. The question is
whether to use eight lines of code to inject -Wno-declaration-after-statement
or one line to remove -Wdeclaration-after-statement using $(filter-out). I
see negligible drawbacks on either side; both approaches are tolerable. The
above-described hypothetical problem tips the scale in favor of
-Wno-declaration-after-statement.

#10Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: David Fetter (#8)
Re: Synchronize with imath upstream

On 2019-Feb-03, David Fetter wrote:

On Sun, Feb 03, 2019 at 07:07:36AM +0000, Andrew Gierth wrote:

"Noah" == Noah Misch <noah@leadboat.com> writes:

So far, expressed opinions have run about 4:2 in favour of allowing
mixed declarations and code.

+1 for this.

Just curious, why do you care? If you want to use such constructs in
extension code, you can add it in your makefiles.

I'm -1 for this myself. I think there are a few places that could
benefit from it, but my fear is that many *more* places would get worse.

--
�lvaro Herrera https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

#11Andres Freund
andres@anarazel.de
In reply to: Alvaro Herrera (#10)
Re: Synchronize with imath upstream

On February 6, 2019 5:17:50 AM GMT+05:30, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:

On 2019-Feb-03, David Fetter wrote:

On Sun, Feb 03, 2019 at 07:07:36AM +0000, Andrew Gierth wrote:

"Noah" == Noah Misch <noah@leadboat.com> writes:

So far, expressed opinions have run about 4:2 in favour of allowing
mixed declarations and code.

+1 for this.

Just curious, why do you care? If you want to use such constructs in
extension code, you can add it in your makefiles.

I'm -1 for this myself. I think there are a few places that could
benefit from it, but my fear is that many *more* places would get
worse.

Because of imported code like ryu and imath? And because it can make code considerably better when used judiciously.

Andres
--
Sent from my Android device with K-9 Mail. Please excuse my brevity.

#12Tom Lane
tgl@sss.pgh.pa.us
In reply to: Andres Freund (#11)
Re: Synchronize with imath upstream

Andres Freund <andres@anarazel.de> writes:

On February 6, 2019 5:17:50 AM GMT+05:30, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:

I'm -1 for this myself. I think there are a few places that could
benefit from it, but my fear is that many *more* places would get
worse.

Because of imported code like ryu and imath? And because it can make code considerably better when used judiciously.

I don't object to keeping imported code in a form that matches upstream
as best we can. (Should we also exclude such files from pgindent'ing?)

But changing conventions for our own code is an entirely different matter.
In this case, I think that having some places use it while the bulk of
the code doesn't is just a bad idea from a stylistic-consistency
standpoint. It's pretty much the same reason why we still aren't allowing
// comments --- there's no toolchain-based reason not to, but a mishmash of
comment styles would be ugly and hard to read.

regards, tom lane

#13Andres Freund
andres@anarazel.de
In reply to: Tom Lane (#12)
Re: Synchronize with imath upstream

Hi,

On 2019-02-06 10:15:24 -0500, Tom Lane wrote:

Andres Freund <andres@anarazel.de> writes:

On February 6, 2019 5:17:50 AM GMT+05:30, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:

I'm -1 for this myself. I think there are a few places that could
benefit from it, but my fear is that many *more* places would get
worse.

Because of imported code like ryu and imath? And because it can make code considerably better when used judiciously.

I don't object to keeping imported code in a form that matches upstream
as best we can. (Should we also exclude such files from pgindent'ing?)

I think pgindenting doesn't matter as much, as that's an automated
change. But as pgindent doesn't fix the position of declarations, that's
a significant manual process.

But changing conventions for our own code is an entirely different matter.
In this case, I think that having some places use it while the bulk of
the code doesn't is just a bad idea from a stylistic-consistency
standpoint. It's pretty much the same reason why we still aren't allowing
// comments --- there's no toolchain-based reason not to, but a mishmash of
comment styles would be ugly and hard to read.

Consistency surely has value, but it shouldn't block making use of new
things that become available. I don't feel extremely strongly about
allowing declarations after statements in C (while it's obviously
crucial for C++), but I do think it can be a noticably easier to reason
about the values of variables if they're declared closer to use, and
it's easier to make sure that a variable hasn't been used elsewhere that
way.

Greetings,

Andres Freund

#14Noah Misch
noah@leadboat.com
In reply to: Tom Lane (#12)
Re: Synchronize with imath upstream

On Wed, Feb 06, 2019 at 10:15:24AM -0500, Tom Lane wrote:

Andres Freund <andres@anarazel.de> writes:

On February 6, 2019 5:17:50 AM GMT+05:30, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:

I'm -1 for this myself. I think there are a few places that could
benefit from it, but my fear is that many *more* places would get
worse.

Because of imported code like ryu and imath? And because it can make code considerably better when used judiciously.

I don't object to keeping imported code in a form that matches upstream
as best we can. (Should we also exclude such files from pgindent'ing?)

I think it depends on how much time one spends merging upstream changes versus
making PostgreSQL-specific edits. For IMath, both amounts are too small to
get excited about. Does pgindent materially complicate src/timezone merges?

But changing conventions for our own code is an entirely different matter.
In this case, I think that having some places use it while the bulk of
the code doesn't is just a bad idea from a stylistic-consistency
standpoint. It's pretty much the same reason why we still aren't allowing
// comments --- there's no toolchain-based reason not to, but a mishmash of
comment styles would be ugly and hard to read.

(This debate never belonged in this thread, but it's too late now.) I find
code easiest to follow when the declaration appears as late as possible. I
would welcome mixed declarations and code, and I would not mourn the loss of
consistency. In terms of consistency damage, this is similar to adding
psprintf() without exterminating palloc()+snprintf(). I'm glad we introduce
ways to write new, cleaner code despite the inconsistency with older code.

#15Tom Lane
tgl@sss.pgh.pa.us
In reply to: Noah Misch (#14)
Re: Synchronize with imath upstream

Noah Misch <noah@leadboat.com> writes:

On Wed, Feb 06, 2019 at 10:15:24AM -0500, Tom Lane wrote:

I don't object to keeping imported code in a form that matches upstream
as best we can. (Should we also exclude such files from pgindent'ing?)

I think it depends on how much time one spends merging upstream changes versus
making PostgreSQL-specific edits. For IMath, both amounts are too small to
get excited about. Does pgindent materially complicate src/timezone merges?

My practice with src/timezone is to pgindent the upstream code and then
diff it; given that extra step, it's not really any more complex (and
maybe less so, as this hides minor whitespace changes for instance).
There are some other deltas to worry about as well, see
src/timezone/README.

I have no particular opinion on whether pgindent should be part of the
mix for imath, but I do strongly recommend setting up and documenting a
reproducible import process, as I did for src/timezone.

regards, tom lane

#16Daniel Gustafsson
daniel@yesql.se
In reply to: Tom Lane (#15)
Re: Synchronize with imath upstream

On 7 Feb 2019, at 16:12, Tom Lane <tgl@sss.pgh.pa.us> wrote:

.. I do strongly recommend setting up and documenting a
reproducible import process, as I did for src/timezone.

Strong +1 on this.

cheers ./daniel

#17Michael Paquier
michael@paquier.xyz
In reply to: Daniel Gustafsson (#16)
Re: Synchronize with imath upstream

On Thu, Feb 07, 2019 at 09:23:43PM +0100, Daniel Gustafsson wrote:

On 7 Feb 2019, at 16:12, Tom Lane <tgl@sss.pgh.pa.us> wrote:

.. I do strongly recommend setting up and documenting a
reproducible import process, as I did for src/timezone.

Strong +1 on this.

+1.
--
Michael
#18Noah Misch
noah@leadboat.com
In reply to: Tom Lane (#15)
2 attachment(s)
Re: Synchronize with imath upstream

On Thu, Feb 07, 2019 at 10:12:05AM -0500, Tom Lane wrote:

Noah Misch <noah@leadboat.com> writes:

On Wed, Feb 06, 2019 at 10:15:24AM -0500, Tom Lane wrote:

I don't object to keeping imported code in a form that matches upstream
as best we can. (Should we also exclude such files from pgindent'ing?)

I think it depends on how much time one spends merging upstream changes versus
making PostgreSQL-specific edits. For IMath, both amounts are too small to
get excited about. Does pgindent materially complicate src/timezone merges?

My practice with src/timezone is to pgindent the upstream code and then
diff it; given that extra step, it's not really any more complex (and
maybe less so, as this hides minor whitespace changes for instance).

Let's continue to pgindent src/timezone and IMath, then.

There are some other deltas to worry about as well, see
src/timezone/README.

I have no particular opinion on whether pgindent should be part of the
mix for imath, but I do strongly recommend setting up and documenting a
reproducible import process, as I did for src/timezone.

Good idea. I've modified the imath.c header comment to take the form of an
import process; see attached imath1.29-pgedits-v2.patch.

Attachments:

imath1.29-raw-sync-v1.patchtext/plain; charset=us-asciiDownload
diff --git a/contrib/pgcrypto/imath.c b/contrib/pgcrypto/imath.c
index b94a51b..96be668 100644
--- a/contrib/pgcrypto/imath.c
+++ b/contrib/pgcrypto/imath.c
@@ -1,90 +1,69 @@
-/* imath version 1.3 */
 /*
-  Name:		imath.c
-  Purpose:	Arbitrary precision integer arithmetic routines.
-  Author:	M. J. Fromberger <http://spinning-yarns.org/michael/sw/>
-  Info:		Id: imath.c 21 2006-04-02 18:58:36Z sting
-
-  Copyright (C) 2002 Michael J. Fromberger, All Rights Reserved.
-
-  Permission is hereby granted, free of charge, to any person
-  obtaining a copy of this software and associated documentation files
-  (the "Software"), to deal in the Software without restriction,
-  including without limitation the rights to use, copy, modify, merge,
-  publish, distribute, sublicense, and/or sell copies of the Software,
-  and to permit persons to whom the Software is furnished to do so,
-  subject to the following conditions:
-
-  The above copyright notice and this permission notice shall be
-  included in all copies or substantial portions of the Software.
-
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-  NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+  Name:     imath.c
+  Purpose:  Arbitrary precision integer arithmetic routines.
+  Author:   M. J. Fromberger
+
+  Copyright (C) 2002-2007 Michael J. Fromberger, All Rights Reserved.
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy
+  of this software and associated documentation files (the "Software"), to deal
+  in the Software without restriction, including without limitation the rights
+  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the Software is
+  furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in
+  all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   SOFTWARE.
  */
-/* contrib/pgcrypto/imath.c */
 
-#include "postgres.h"
-#include "px.h"
 #include "imath.h"
 
-#undef assert
-#define assert(TEST) Assert(TEST)
-#define TRACEABLE_CLAMP 0
-#define TRACEABLE_FREE 0
-
-/* {{{ Constants */
+#include <assert.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
 
 const mp_result MP_OK = 0;		/* no error, all is well  */
-const mp_result MP_FALSE = 0;	/* boolean false		  */
-const mp_result MP_TRUE = -1;	/* boolean true			  */
-const mp_result MP_MEMORY = -2; /* out of memory		  */
+const mp_result MP_FALSE = 0;	/* boolean false          */
+const mp_result MP_TRUE = -1;	/* boolean true           */
+const mp_result MP_MEMORY = -2; /* out of memory          */
 const mp_result MP_RANGE = -3;	/* argument out of range  */
-const mp_result MP_UNDEF = -4;	/* result undefined		  */
-const mp_result MP_TRUNC = -5;	/* output truncated		  */
+const mp_result MP_UNDEF = -4;	/* result undefined       */
+const mp_result MP_TRUNC = -5;	/* output truncated       */
 const mp_result MP_BADARG = -6; /* invalid null argument  */
+const mp_result MP_MINERR = -6;
 
 const mp_sign MP_NEG = 1;		/* value is strictly negative */
-const mp_sign MP_ZPOS = 0;		/* value is non-negative	  */
+const mp_sign MP_ZPOS = 0;		/* value is non-negative      */
 
 static const char *s_unknown_err = "unknown result code";
-static const char *s_error_msg[] = {
-	"error code 0",
-	"boolean true",
-	"out of memory",
-	"argument out of range",
-	"result undefined",
-	"output truncated",
-	"invalid null argument",
-	NULL
-};
-
-/* }}} */
-
-/* Optional library flags */
-#define MP_CAP_DIGITS	1		/* flag bit to capitalize letter digits */
-
-/* Argument checking macros
-   Use CHECK() where a return value is required; NRCHECK() elsewhere */
-#define CHECK(TEST)   assert(TEST)
-#define NRCHECK(TEST) assert(TEST)
-
-/* {{{ Logarithm table for computing output sizes */
+static const char *s_error_msg[] = {"error code 0", "boolean true",
+	"out of memory", "argument out of range",
+	"result undefined", "output truncated",
+"invalid argument", NULL};
 
 /* The ith entry of this table gives the value of log_i(2).
 
    An integer value n requires ceil(log_i(n)) digits to be represented
    in base i.  Since it is easy to compute lg(n), by counting bits, we
    can compute log_i(n) = lg(n) * log_i(2).
+
+   The use of this table eliminates a dependency upon linkage against
+   the standard math libraries.
+
+   If MP_MAX_RADIX is increased, this table should be expanded too.
  */
 static const double s_log2[] = {
-	0.000000000, 0.000000000, 1.000000000, 0.630929754, /* 0  1  2	3 */
-	0.500000000, 0.430676558, 0.386852807, 0.356207187, /* 4  5  6	7 */
+	0.000000000, 0.000000000, 1.000000000, 0.630929754, /* (D)(D) 2  3 */
+	0.500000000, 0.430676558, 0.386852807, 0.356207187, /* 4  5  6  7 */
 	0.333333333, 0.315464877, 0.301029996, 0.289064826, /* 8  9 10 11 */
 	0.278942946, 0.270238154, 0.262649535, 0.255958025, /* 12 13 14 15 */
 	0.250000000, 0.244650542, 0.239812467, 0.235408913, /* 16 17 18 19 */
@@ -92,136 +71,240 @@ static const double s_log2[] = {
 	0.218104292, 0.215338279, 0.212746054, 0.210309918, /* 24 25 26 27 */
 	0.208014598, 0.205846832, 0.203795047, 0.201849087, /* 28 29 30 31 */
 	0.200000000, 0.198239863, 0.196561632, 0.194959022, /* 32 33 34 35 */
-	0.193426404, 0.191958720, 0.190551412, 0.189200360, /* 36 37 38 39 */
-	0.187901825, 0.186652411, 0.185449023, 0.184288833, /* 40 41 42 43 */
-	0.183169251, 0.182087900, 0.181042597, 0.180031327, /* 44 45 46 47 */
-	0.179052232, 0.178103594, 0.177183820, 0.176291434, /* 48 49 50 51 */
-	0.175425064, 0.174583430, 0.173765343, 0.172969690, /* 52 53 54 55 */
-	0.172195434, 0.171441601, 0.170707280, 0.169991616, /* 56 57 58 59 */
-	0.169293808, 0.168613099, 0.167948779, 0.167300179, /* 60 61 62 63 */
-	0.166666667
+	0.193426404,				/* 36          */
 };
 
-/* }}} */
-/* {{{ Various macros */
-
 /* Return the number of digits needed to represent a static value */
 #define MP_VALUE_DIGITS(V) \
-((sizeof(V)+(sizeof(mp_digit)-1))/sizeof(mp_digit))
+  ((sizeof(V) + (sizeof(mp_digit) - 1)) / sizeof(mp_digit))
 
 /* Round precision P to nearest word boundary */
-#define ROUND_PREC(P) ((mp_size)(2*(((P)+1)/2)))
+static inline mp_size
+s_round_prec(mp_size P)
+{
+	return 2 * ((P + 1) / 2);
+}
 
 /* Set array P of S digits to zero */
-#define ZERO(P, S) \
-do{mp_size i__=(S)*sizeof(mp_digit);mp_digit *p__=(P);memset(p__,0,i__);}while(0)
+static inline void
+ZERO(mp_digit *P, mp_size S)
+{
+	mp_size		i__ = S * sizeof(mp_digit);
+	mp_digit   *p__ = P;
+
+	memset(p__, 0, i__);
+}
 
 /* Copy S digits from array P to array Q */
-#define COPY(P, Q, S) \
-do{mp_size i__=(S)*sizeof(mp_digit);mp_digit *p__=(P),*q__=(Q);\
-memcpy(q__,p__,i__);}while(0)
+static inline void
+COPY(mp_digit *P, mp_digit *Q, mp_size S)
+{
+	mp_size		i__ = S * sizeof(mp_digit);
+	mp_digit   *p__ = P;
+	mp_digit   *q__ = Q;
 
-/* Reverse N elements of type T in array A */
-#define REV(T, A, N) \
-do{T *u_=(A),*v_=u_+(N)-1;while(u_<v_){T xch=*u_;*u_++=*v_;*v_--=xch;}}while(0)
+	memcpy(q__, p__, i__);
+}
 
-#if TRACEABLE_CLAMP
-#define CLAMP(Z) s_clamp(Z)
-#else
-#define CLAMP(Z) \
-do{mp_int z_=(Z);mp_size uz_=MP_USED(z_);mp_digit *dz_=MP_DIGITS(z_)+uz_-1;\
-while(uz_ > 1 && (*dz_-- == 0)) --uz_;MP_USED(z_)=uz_;}while(0)
-#endif
+/* Reverse N elements of unsigned char in A. */
+static inline void
+REV(unsigned char *A, int N)
+{
+	unsigned char *u_ = A;
+	unsigned char *v_ = u_ + N - 1;
 
-#undef MIN
-#undef MAX
-#define MIN(A, B) ((B)<(A)?(B):(A))
-#define MAX(A, B) ((B)>(A)?(B):(A))
-#define SWAP(T, A, B) do{T t_=(A);A=(B);B=t_;}while(0)
+	while (u_ < v_)
+	{
+		unsigned char xch = *u_;
 
-#define TEMP(K) (temp + (K))
-#define SETUP(E, C) \
-do{if((res = (E)) != MP_OK) goto CLEANUP; ++(C);}while(0)
+		*u_++ = *v_;
+		*v_-- = xch;
+	}
+}
 
-#define CMPZ(Z) \
-(((Z)->used==1&&(Z)->digits[0]==0)?0:((Z)->sign==MP_NEG)?-1:1)
+/* Strip leading zeroes from z_ in-place. */
+static inline void
+CLAMP(mp_int z_)
+{
+	mp_size		uz_ = MP_USED(z_);
+	mp_digit   *dz_ = MP_DIGITS(z_) + uz_ - 1;
 
-#define UMUL(X, Y, Z) \
-do{mp_size ua_=MP_USED(X),ub_=MP_USED(Y);mp_size o_=ua_+ub_;\
-ZERO(MP_DIGITS(Z),o_);\
-(void) s_kmul(MP_DIGITS(X),MP_DIGITS(Y),MP_DIGITS(Z),ua_,ub_);\
-MP_USED(Z)=o_;CLAMP(Z);}while(0)
+	while (uz_ > 1 && (*dz_-- == 0))
+		--uz_;
+	z_->used = uz_;
+}
 
-#define USQR(X, Z) \
-do{mp_size ua_=MP_USED(X),o_=ua_+ua_;ZERO(MP_DIGITS(Z),o_);\
-(void) s_ksqr(MP_DIGITS(X),MP_DIGITS(Z),ua_);MP_USED(Z)=o_;CLAMP(Z);}while(0)
+/* Select min/max. */
+static inline int
+MIN(int A, int B)
+{
+	return (B < A ? B : A);
+}
+static inline mp_size
+MAX(mp_size A, mp_size B)
+{
+	return (B > A ? B : A);
+}
 
-#define UPPER_HALF(W)			((mp_word)((W) >> MP_DIGIT_BIT))
-#define LOWER_HALF(W)			((mp_digit)(W))
-#define HIGH_BIT_SET(W)			((W) >> (MP_WORD_BIT - 1))
-#define ADD_WILL_OVERFLOW(W, V) ((MP_WORD_MAX - (V)) < (W))
+/* Exchange lvalues A and B of type T, e.g.
+   SWAP(int, x, y) where x and y are variables of type int. */
+#define SWAP(T, A, B) \
+  do {                \
+	T t_ = (A);       \
+	A = (B);          \
+	B = t_;           \
+  } while (0)
 
-/* }}} */
+/* Declare a block of N temporary mpz_t values.
+   These values are initialized to zero.
+   You must add CLEANUP_TEMP() at the end of the function.
+   Use TEMP(i) to access a pointer to the ith value.
+ */
+#define DECLARE_TEMP(N)                   \
+  struct {                                \
+	mpz_t value[(N)];                     \
+	int len;                              \
+	mp_result err;                        \
+  } temp_ = {                             \
+	  .len = (N),                         \
+	  .err = MP_OK,                       \
+  };                                      \
+  do {                                    \
+	for (int i = 0; i < temp_.len; i++) { \
+	  mp_int_init(TEMP(i));               \
+	}                                     \
+  } while (0)
+
+/* Clear all allocated temp values. */
+#define CLEANUP_TEMP()                    \
+  CLEANUP:                                \
+  do {                                    \
+	for (int i = 0; i < temp_.len; i++) { \
+	  mp_int_clear(TEMP(i));              \
+	}                                     \
+	if (temp_.err != MP_OK) {             \
+	  return temp_.err;                   \
+	}                                     \
+  } while (0)
+
+/* A pointer to the kth temp value. */
+#define TEMP(K) (temp_.value + (K))
+
+/* Evaluate E, an expression of type mp_result expected to return MP_OK.  If
+   the value is not MP_OK, the error is cached and control resumes at the
+   cleanup handler, which returns it.
+*/
+#define REQUIRE(E)                        \
+  do {                                    \
+	temp_.err = (E);                      \
+	if (temp_.err != MP_OK) goto CLEANUP; \
+  } while (0)
+
+/* Compare value to zero. */
+static inline int
+CMPZ(mp_int Z)
+{
+	if (Z->used == 1 && Z->digits[0] == 0)
+		return 0;
+	return (Z->sign == MP_NEG) ? -1 : 1;
+}
+
+static inline mp_word
+UPPER_HALF(mp_word W)
+{
+	return (W >> MP_DIGIT_BIT);
+}
+static inline mp_digit
+LOWER_HALF(mp_word W)
+{
+	return (mp_digit) (W);
+}
+
+/* Report whether the highest-order bit of W is 1. */
+static inline bool
+HIGH_BIT_SET(mp_word W)
+{
+	return (W >> (MP_WORD_BIT - 1)) != 0;
+}
+
+/* Report whether adding W + V will carry out. */
+static inline bool
+ADD_WILL_OVERFLOW(mp_word W, mp_word V)
+{
+	return ((MP_WORD_MAX - V) < W);
+}
 
 /* Default number of digits allocated to a new mp_int */
-static mp_size default_precision = 64;
+static mp_size default_precision = 8;
+
+void
+mp_int_default_precision(mp_size size)
+{
+	assert(size > 0);
+	default_precision = size;
+}
 
 /* Minimum number of digits to invoke recursive multiply */
 static mp_size multiply_threshold = 32;
 
-/* Default library configuration flags */
-static mp_word mp_flags = MP_CAP_DIGITS;
+void
+mp_int_multiply_threshold(mp_size thresh)
+{
+	assert(thresh >= sizeof(mp_word));
+	multiply_threshold = thresh;
+}
 
 /* Allocate a buffer of (at least) num digits, or return
    NULL if that couldn't be done.  */
 static mp_digit *s_alloc(mp_size num);
 
-#if TRACEABLE_FREE
+/* Release a buffer of digits allocated by s_alloc(). */
 static void s_free(void *ptr);
-#else
-#define s_free(P) px_free(P)
-#endif
 
 /* Insure that z has at least min digits allocated, resizing if
    necessary.  Returns true if successful, false if out of memory. */
-static int	s_pad(mp_int z, mp_size min);
+static bool s_pad(mp_int z, mp_size min);
 
-/* Normalize by removing leading zeroes (except when z = 0) */
-#if TRACEABLE_CLAMP
-static void s_clamp(mp_int z);
-#endif
+/* Ensure Z has at least N digits allocated. */
+static inline mp_result
+GROW(mp_int Z, mp_size N)
+{
+	return s_pad(Z, N) ? MP_OK : MP_MEMORY;
+}
 
 /* Fill in a "fake" mp_int on the stack with a given value */
-static void s_fake(mp_int z, int value, mp_digit vbuf[]);
+static void s_fake(mp_int z, mp_small value, mp_digit vbuf[]);
+static void s_ufake(mp_int z, mp_usmall value, mp_digit vbuf[]);
 
 /* Compare two runs of digits of given length, returns <0, 0, >0 */
 static int	s_cdig(mp_digit *da, mp_digit *db, mp_size len);
 
 /* Pack the unsigned digits of v into array t */
-static int	s_vpack(int v, mp_digit t[]);
+static int	s_uvpack(mp_usmall v, mp_digit t[]);
 
 /* Compare magnitudes of a and b, returns <0, 0, >0 */
 static int	s_ucmp(mp_int a, mp_int b);
 
 /* Compare magnitudes of a and v, returns <0, 0, >0 */
-static int	s_vcmp(mp_int a, int v);
+static int	s_vcmp(mp_int a, mp_small v);
+static int	s_uvcmp(mp_int a, mp_usmall uv);
 
 /* Unsigned magnitude addition; assumes dc is big enough.
    Carry out is returned (no memory allocated). */
-static mp_digit s_uadd(mp_digit *da, mp_digit *db, mp_digit *dc,
-	   mp_size size_a, mp_size size_b);
+static mp_digit s_uadd(mp_digit *da, mp_digit *db, mp_digit *dc, mp_size size_a,
+	   mp_size size_b);
 
 /* Unsigned magnitude subtraction.  Assumes dc is big enough. */
-static void s_usub(mp_digit *da, mp_digit *db, mp_digit *dc,
-	   mp_size size_a, mp_size size_b);
+static void s_usub(mp_digit *da, mp_digit *db, mp_digit *dc, mp_size size_a,
+	   mp_size size_b);
 
 /* Unsigned recursive multiplication.  Assumes dc is big enough. */
-static int s_kmul(mp_digit *da, mp_digit *db, mp_digit *dc,
-	   mp_size size_a, mp_size size_b);
+static int s_kmul(mp_digit *da, mp_digit *db, mp_digit *dc, mp_size size_a,
+	   mp_size size_b);
 
 /* Unsigned magnitude multiplication.  Assumes dc is big enough. */
-static void s_umul(mp_digit *da, mp_digit *db, mp_digit *dc,
-	   mp_size size_a, mp_size size_b);
+static void s_umul(mp_digit *da, mp_digit *db, mp_digit *dc, mp_size size_a,
+	   mp_size size_b);
 
 /* Unsigned recursive squaring.  Assumes dc is big enough. */
 static int	s_ksqr(mp_digit *da, mp_digit *dc, mp_size size_a);
@@ -236,8 +319,7 @@ static void s_dadd(mp_int a, mp_digit b);
 static void s_dmul(mp_int a, mp_digit b);
 
 /* Single digit multiplication on buffers; assumes dc is big enough. */
-static void s_dbmul(mp_digit *da, mp_digit b, mp_digit *dc,
-		mp_size size_a);
+static void s_dbmul(mp_digit *da, mp_digit b, mp_digit *dc, mp_size size_a);
 
 /* Single digit division.  Replaces a with the quotient,
    returns the remainder.  */
@@ -264,7 +346,7 @@ static int	s_dp2k(mp_int z);
 static int	s_isp2(mp_int z);
 
 /* Set z to 2^k.  May allocate; returns false in case this fails. */
-static int	s_2expt(mp_int z, int k);
+static int	s_2expt(mp_int z, mp_small k);
 
 /* Normalize a and b for division, returns normalization constant */
 static int	s_norm(mp_int a, mp_int b);
@@ -279,17 +361,17 @@ static int	s_reduce(mp_int x, mp_int m, mp_int mu, mp_int q1, mp_int q2);
 /* Modular exponentiation, using Barrett reduction */
 static mp_result s_embar(mp_int a, mp_int b, mp_int m, mp_int mu, mp_int c);
 
-/* Unsigned magnitude division.  Assumes |a| > |b|.  Allocates
-   temporaries; overwrites a with quotient, b with remainder. */
-static mp_result s_udiv(mp_int a, mp_int b);
+/* Unsigned magnitude division.  Assumes |a| > |b|.  Allocates temporaries;
+   overwrites a with quotient, b with remainder. */
+static mp_result s_udiv_knuth(mp_int a, mp_int b);
 
-/* Compute the number of digits in radix r required to represent the
-   given value.  Does not account for sign flags, terminators, etc. */
+/* Compute the number of digits in radix r required to represent the given
+   value.  Does not account for sign flags, terminators, etc. */
 static int	s_outlen(mp_int z, mp_size r);
 
-/* Guess how many digits of precision will be needed to represent a
-   radix r value of the specified number of digits.  Returns a value
-   guaranteed to be no smaller than the actual number required. */
+/* Guess how many digits of precision will be needed to represent a radix r
+   value of the specified number of digits.  Returns a value guaranteed to be
+   no smaller than the actual number required. */
 static mp_size s_inlen(int len, mp_size r);
 
 /* Convert a character to a digit value in radix r, or
@@ -302,177 +384,161 @@ static char s_val2ch(int v, int caps);
 /* Take 2's complement of a buffer in place */
 static void s_2comp(unsigned char *buf, int len);
 
-/* Convert a value to binary, ignoring sign.  On input, *limpos is the
-   bound on how many bytes should be written to buf; on output, *limpos
-   is set to the number of bytes actually written. */
+/* Convert a value to binary, ignoring sign.  On input, *limpos is the bound on
+   how many bytes should be written to buf; on output, *limpos is set to the
+   number of bytes actually written. */
 static mp_result s_tobin(mp_int z, unsigned char *buf, int *limpos, int pad);
 
-#if 0
-/* Dump a representation of the mp_int to standard output */
-void		s_print(char *tag, mp_int z);
-void		s_print_buf(char *tag, mp_digit *buf, mp_size num);
-#endif
-
-/* {{{ get_default_precision() */
-
-mp_size
-mp_get_default_precision(void)
-{
-	return default_precision;
-}
-
-/* }}} */
-
-/* {{{ mp_set_default_precision(s) */
-
-void
-mp_set_default_precision(mp_size s)
+/* Multiply X by Y into Z, ignoring signs.  Requires that Z have enough storage
+   preallocated to hold the result. */
+static inline void
+UMUL(mp_int X, mp_int Y, mp_int Z)
 {
-	NRCHECK(s > 0);
+	mp_size		ua_ = MP_USED(X);
+	mp_size		ub_ = MP_USED(Y);
+	mp_size		o_ = ua_ + ub_;
 
-	default_precision = (mp_size) ROUND_PREC(s);
+	ZERO(MP_DIGITS(Z), o_);
+	(void) s_kmul(MP_DIGITS(X), MP_DIGITS(Y), MP_DIGITS(Z), ua_, ub_);
+	Z->used = o_;
+	CLAMP(Z);
 }
 
-/* }}} */
-
-/* {{{ mp_get_multiply_threshold() */
-
-mp_size
-mp_get_multiply_threshold(void)
+/* Square X into Z.  Requires that Z have enough storage to hold the result. */
+static inline void
+USQR(mp_int X, mp_int Z)
 {
-	return multiply_threshold;
-}
-
-/* }}} */
+	mp_size		ua_ = MP_USED(X);
+	mp_size		o_ = ua_ + ua_;
 
-/* {{{ mp_set_multiply_threshold(s) */
-
-void
-mp_set_multiply_threshold(mp_size s)
-{
-	multiply_threshold = s;
+	ZERO(MP_DIGITS(Z), o_);
+	(void) s_ksqr(MP_DIGITS(X), MP_DIGITS(Z), ua_);
+	Z->used = o_;
+	CLAMP(Z);
 }
 
-/* }}} */
-
-/* {{{ mp_int_init(z) */
-
 mp_result
 mp_int_init(mp_int z)
 {
-	return mp_int_init_size(z, default_precision);
-}
+	if (z == NULL)
+		return MP_BADARG;
 
-/* }}} */
+	z->single = 0;
+	z->digits = &(z->single);
+	z->alloc = 1;
+	z->used = 1;
+	z->sign = MP_ZPOS;
 
-/* {{{ mp_int_alloc() */
+	return MP_OK;
+}
 
 mp_int
 mp_int_alloc(void)
 {
-	mp_int		out = px_alloc(sizeof(mpz_t));
+	mp_int		out = malloc(sizeof(mpz_t));
 
-	assert(out != NULL);
-	out->digits = NULL;
-	out->used = 0;
-	out->alloc = 0;
-	out->sign = 0;
+	if (out != NULL)
+		mp_int_init(out);
 
 	return out;
 }
 
-/* }}} */
-
-/* {{{ mp_int_init_size(z, prec) */
-
 mp_result
 mp_int_init_size(mp_int z, mp_size prec)
 {
-	CHECK(z != NULL);
+	assert(z != NULL);
 
-	prec = (mp_size) ROUND_PREC(prec);
-	prec = MAX(prec, default_precision);
+	if (prec == 0)
+	{
+		prec = default_precision;
+	}
+	else if (prec == 1)
+	{
+		return mp_int_init(z);
+	}
+	else
+	{
+		prec = s_round_prec(prec);
+	}
 
-	if ((MP_DIGITS(z) = s_alloc(prec)) == NULL)
+	z->digits = s_alloc(prec);
+	if (MP_DIGITS(z) == NULL)
 		return MP_MEMORY;
 
 	z->digits[0] = 0;
-	MP_USED(z) = 1;
-	MP_ALLOC(z) = prec;
-	MP_SIGN(z) = MP_ZPOS;
+	z->used = 1;
+	z->alloc = prec;
+	z->sign = MP_ZPOS;
 
 	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_init_copy(z, old) */
-
 mp_result
 mp_int_init_copy(mp_int z, mp_int old)
 {
-	mp_result	res;
-	mp_size		uold,
-				target;
+	assert(z != NULL && old != NULL);
 
-	CHECK(z != NULL && old != NULL);
+	mp_size		uold = MP_USED(old);
 
-	uold = MP_USED(old);
-	target = MAX(uold, default_precision);
+	if (uold == 1)
+	{
+		mp_int_init(z);
+	}
+	else
+	{
+		mp_size		target = MAX(uold, default_precision);
+		mp_result	res = mp_int_init_size(z, target);
 
-	if ((res = mp_int_init_size(z, target)) != MP_OK)
-		return res;
+		if (res != MP_OK)
+			return res;
+	}
 
-	MP_USED(z) = uold;
-	MP_SIGN(z) = MP_SIGN(old);
+	z->used = uold;
+	z->sign = old->sign;
 	COPY(MP_DIGITS(old), MP_DIGITS(z), uold);
 
 	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_init_value(z, value) */
-
 mp_result
-mp_int_init_value(mp_int z, int value)
+mp_int_init_value(mp_int z, mp_small value)
 {
-	mp_result	res;
-
-	CHECK(z != NULL);
-
-	if ((res = mp_int_init(z)) != MP_OK)
-		return res;
+	mpz_t		vtmp;
+	mp_digit	vbuf[MP_VALUE_DIGITS(value)];
 
-	return mp_int_set_value(z, value);
+	s_fake(&vtmp, value, vbuf);
+	return mp_int_init_copy(z, &vtmp);
 }
 
-/* }}} */
-
-/* {{{ mp_int_set_value(z, value) */
-
 mp_result
-mp_int_set_value(mp_int z, int value)
+mp_int_init_uvalue(mp_int z, mp_usmall uvalue)
 {
-	mp_size		ndig;
-
-	CHECK(z != NULL);
-
-	/* How many digits to copy */
-	ndig = (mp_size) MP_VALUE_DIGITS(value);
+	mpz_t		vtmp;
+	mp_digit	vbuf[MP_VALUE_DIGITS(uvalue)];
 
-	if (!s_pad(z, ndig))
-		return MP_MEMORY;
+	s_ufake(&vtmp, uvalue, vbuf);
+	return mp_int_init_copy(z, &vtmp);
+}
 
-	MP_USED(z) = (mp_size) s_vpack(value, MP_DIGITS(z));
-	MP_SIGN(z) = (value < 0) ? MP_NEG : MP_ZPOS;
+mp_result
+mp_int_set_value(mp_int z, mp_small value)
+{
+	mpz_t		vtmp;
+	mp_digit	vbuf[MP_VALUE_DIGITS(value)];
 
-	return MP_OK;
+	s_fake(&vtmp, value, vbuf);
+	return mp_int_copy(&vtmp, z);
 }
 
-/* }}} */
+mp_result
+mp_int_set_uvalue(mp_int z, mp_usmall uvalue)
+{
+	mpz_t		vtmp;
+	mp_digit	vbuf[MP_VALUE_DIGITS(uvalue)];
 
-/* {{{ mp_int_clear(z) */
+	s_ufake(&vtmp, uvalue, vbuf);
+	return mp_int_copy(&vtmp, z);
+}
 
 void
 mp_int_clear(mp_int z)
@@ -482,34 +548,26 @@ mp_int_clear(mp_int z)
 
 	if (MP_DIGITS(z) != NULL)
 	{
-		s_free(MP_DIGITS(z));
-		MP_DIGITS(z) = NULL;
+		if (MP_DIGITS(z) != &(z->single))
+			s_free(MP_DIGITS(z));
+
+		z->digits = NULL;
 	}
 }
 
-/* }}} */
-
-/* {{{ mp_int_free(z) */
-
 void
 mp_int_free(mp_int z)
 {
-	NRCHECK(z != NULL);
+	assert(z != NULL);
 
-	if (z->digits != NULL)
-		mp_int_clear(z);
-
-	px_free(z);
+	mp_int_clear(z);
+	free(z);					/* note: NOT s_free() */
 }
 
-/* }}} */
-
-/* {{{ mp_int_copy(a, c) */
-
 mp_result
 mp_int_copy(mp_int a, mp_int c)
 {
-	CHECK(a != NULL && c != NULL);
+	assert(a != NULL && c != NULL);
 
 	if (a != c)
 	{
@@ -524,17 +582,13 @@ mp_int_copy(mp_int a, mp_int c)
 		dc = MP_DIGITS(c);
 		COPY(da, dc, ua);
 
-		MP_USED(c) = ua;
-		MP_SIGN(c) = MP_SIGN(a);
+		c->used = ua;
+		c->sign = a->sign;
 	}
 
 	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_swap(a, c) */
-
 void
 mp_int_swap(mp_int a, mp_int c)
 {
@@ -544,90 +598,71 @@ mp_int_swap(mp_int a, mp_int c)
 
 		*a = *c;
 		*c = tmp;
+
+		if (MP_DIGITS(a) == &(c->single))
+			a->digits = &(a->single);
+		if (MP_DIGITS(c) == &(a->single))
+			c->digits = &(c->single);
 	}
 }
 
-/* }}} */
-
-/* {{{ mp_int_zero(z) */
-
 void
 mp_int_zero(mp_int z)
 {
-	NRCHECK(z != NULL);
+	assert(z != NULL);
 
 	z->digits[0] = 0;
-	MP_USED(z) = 1;
-	MP_SIGN(z) = MP_ZPOS;
+	z->used = 1;
+	z->sign = MP_ZPOS;
 }
 
-/* }}} */
-
-/* {{{ mp_int_abs(a, c) */
-
 mp_result
 mp_int_abs(mp_int a, mp_int c)
 {
-	mp_result	res;
+	assert(a != NULL && c != NULL);
 
-	CHECK(a != NULL && c != NULL);
+	mp_result	res;
 
 	if ((res = mp_int_copy(a, c)) != MP_OK)
 		return res;
 
-	MP_SIGN(c) = MP_ZPOS;
+	c->sign = MP_ZPOS;
 	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_neg(a, c) */
-
 mp_result
 mp_int_neg(mp_int a, mp_int c)
 {
-	mp_result	res;
+	assert(a != NULL && c != NULL);
 
-	CHECK(a != NULL && c != NULL);
+	mp_result	res;
 
 	if ((res = mp_int_copy(a, c)) != MP_OK)
 		return res;
 
 	if (CMPZ(c) != 0)
-		MP_SIGN(c) = 1 - MP_SIGN(a);
+		c->sign = 1 - MP_SIGN(a);
 
 	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_add(a, b, c) */
-
 mp_result
 mp_int_add(mp_int a, mp_int b, mp_int c)
 {
-	mp_size		ua,
-				ub,
-				uc,
-				max;
+	assert(a != NULL && b != NULL && c != NULL);
 
-	CHECK(a != NULL && b != NULL && c != NULL);
-
-	ua = MP_USED(a);
-	ub = MP_USED(b);
-	uc = MP_USED(c);
-	max = MAX(ua, ub);
+	mp_size		ua = MP_USED(a);
+	mp_size		ub = MP_USED(b);
+	mp_size		max = MAX(ua, ub);
 
 	if (MP_SIGN(a) == MP_SIGN(b))
 	{
 		/* Same sign -- add magnitudes, preserve sign of addends */
-		mp_digit	carry;
-
 		if (!s_pad(c, max))
 			return MP_MEMORY;
 
-		carry = s_uadd(MP_DIGITS(a), MP_DIGITS(b), MP_DIGITS(c), ua, ub);
-		uc = max;
+		mp_digit	carry = s_uadd(MP_DIGITS(a), MP_DIGITS(b), MP_DIGITS(c), ua, ub);
+		mp_size		uc = max;
 
 		if (carry)
 		{
@@ -638,50 +673,55 @@ mp_int_add(mp_int a, mp_int b, mp_int c)
 			++uc;
 		}
 
-		MP_USED(c) = uc;
-		MP_SIGN(c) = MP_SIGN(a);
+		c->used = uc;
+		c->sign = a->sign;
 
 	}
 	else
 	{
 		/* Different signs -- subtract magnitudes, preserve sign of greater */
+		int			cmp = s_ucmp(a, b); /* magnitude comparision, sign ignored */
+
+		/*
+		 * Set x to max(a, b), y to min(a, b) to simplify later code. A
+		 * special case yields zero for equal magnitudes.
+		 */
 		mp_int		x,
 					y;
-		int			cmp = s_ucmp(a, b); /* magnitude comparison, sign ignored */
 
-		/* Set x to max(a, b), y to min(a, b) to simplify later code */
-		if (cmp >= 0)
+		if (cmp == 0)
 		{
-			x = a;
-			y = b;
+			mp_int_zero(c);
+			return MP_OK;
 		}
-		else
+		else if (cmp < 0)
 		{
 			x = b;
 			y = a;
 		}
+		else
+		{
+			x = a;
+			y = b;
+		}
 
 		if (!s_pad(c, MP_USED(x)))
 			return MP_MEMORY;
 
 		/* Subtract smaller from larger */
 		s_usub(MP_DIGITS(x), MP_DIGITS(y), MP_DIGITS(c), MP_USED(x), MP_USED(y));
-		MP_USED(c) = MP_USED(x);
+		c->used = x->used;
 		CLAMP(c);
 
 		/* Give result the sign of the larger */
-		MP_SIGN(c) = MP_SIGN(x);
+		c->sign = x->sign;
 	}
 
 	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_add_value(a, value, c) */
-
 mp_result
-mp_int_add_value(mp_int a, int value, mp_int c)
+mp_int_add_value(mp_int a, mp_small value, mp_int c)
 {
 	mpz_t		vtmp;
 	mp_digit	vbuf[MP_VALUE_DIGITS(value)];
@@ -691,35 +731,23 @@ mp_int_add_value(mp_int a, int value, mp_int c)
 	return mp_int_add(a, &vtmp, c);
 }
 
-/* }}} */
-
-/* {{{ mp_int_sub(a, b, c) */
-
 mp_result
 mp_int_sub(mp_int a, mp_int b, mp_int c)
 {
-	mp_size		ua,
-				ub,
-				uc,
-				max;
-
-	CHECK(a != NULL && b != NULL && c != NULL);
+	assert(a != NULL && b != NULL && c != NULL);
 
-	ua = MP_USED(a);
-	ub = MP_USED(b);
-	uc = MP_USED(c);
-	max = MAX(ua, ub);
+	mp_size		ua = MP_USED(a);
+	mp_size		ub = MP_USED(b);
+	mp_size		max = MAX(ua, ub);
 
 	if (MP_SIGN(a) != MP_SIGN(b))
 	{
 		/* Different signs -- add magnitudes and keep sign of a */
-		mp_digit	carry;
-
 		if (!s_pad(c, max))
 			return MP_MEMORY;
 
-		carry = s_uadd(MP_DIGITS(a), MP_DIGITS(b), MP_DIGITS(c), ua, ub);
-		uc = max;
+		mp_digit	carry = s_uadd(MP_DIGITS(a), MP_DIGITS(b), MP_DIGITS(c), ua, ub);
+		mp_size		uc = max;
 
 		if (carry)
 		{
@@ -730,20 +758,20 @@ mp_int_sub(mp_int a, mp_int b, mp_int c)
 			++uc;
 		}
 
-		MP_USED(c) = uc;
-		MP_SIGN(c) = MP_SIGN(a);
+		c->used = uc;
+		c->sign = a->sign;
 
 	}
 	else
 	{
 		/* Same signs -- subtract magnitudes */
+		if (!s_pad(c, max))
+			return MP_MEMORY;
 		mp_int		x,
 					y;
 		mp_sign		osign;
-		int			cmp = s_ucmp(a, b);
 
-		if (!s_pad(c, max))
-			return MP_MEMORY;
+		int			cmp = s_ucmp(a, b);
 
 		if (cmp >= 0)
 		{
@@ -762,21 +790,17 @@ mp_int_sub(mp_int a, mp_int b, mp_int c)
 			osign = 1 - osign;
 
 		s_usub(MP_DIGITS(x), MP_DIGITS(y), MP_DIGITS(c), MP_USED(x), MP_USED(y));
-		MP_USED(c) = MP_USED(x);
+		c->used = x->used;
 		CLAMP(c);
 
-		MP_SIGN(c) = osign;
+		c->sign = osign;
 	}
 
 	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_sub_value(a, value, c) */
-
 mp_result
-mp_int_sub_value(mp_int a, int value, mp_int c)
+mp_int_sub_value(mp_int a, mp_small value, mp_int c)
 {
 	mpz_t		vtmp;
 	mp_digit	vbuf[MP_VALUE_DIGITS(value)];
@@ -786,21 +810,10 @@ mp_int_sub_value(mp_int a, int value, mp_int c)
 	return mp_int_sub(a, &vtmp, c);
 }
 
-/* }}} */
-
-/* {{{ mp_int_mul(a, b, c) */
-
 mp_result
 mp_int_mul(mp_int a, mp_int b, mp_int c)
 {
-	mp_digit   *out;
-	mp_size		osize,
-				ua,
-				ub,
-				p = 0;
-	mp_sign		osign;
-
-	CHECK(a != NULL && b != NULL && c != NULL);
+	assert(a != NULL && b != NULL && c != NULL);
 
 	/* If either input is zero, we can shortcut multiplication */
 	if (mp_int_compare_zero(a) == 0 || mp_int_compare_zero(b) == 0)
@@ -810,21 +823,24 @@ mp_int_mul(mp_int a, mp_int b, mp_int c)
 	}
 
 	/* Output is positive if inputs have same sign, otherwise negative */
-	osign = (MP_SIGN(a) == MP_SIGN(b)) ? MP_ZPOS : MP_NEG;
+	mp_sign		osign = (MP_SIGN(a) == MP_SIGN(b)) ? MP_ZPOS : MP_NEG;
 
 	/*
-	 * If the output is not equal to any of the inputs, we'll write the
-	 * results there directly; otherwise, allocate a temporary space.
+	 * If the output is not identical to any of the inputs, we'll write the
+	 * results directly; otherwise, allocate a temporary space.
 	 */
-	ua = MP_USED(a);
-	ub = MP_USED(b);
-	osize = MAX(ua, ub);
+	mp_size		ua = MP_USED(a);
+	mp_size		ub = MP_USED(b);
+	mp_size		osize = MAX(ua, ub);
+
 	osize = 4 * ((osize + 1) / 2);
 
+	mp_digit   *out;
+	mp_size		p = 0;
+
 	if (c == a || c == b)
 	{
-		p = ROUND_PREC(osize);
-		p = MAX(p, default_precision);
+		p = MAX(s_round_prec(osize), default_precision);
 
 		if ((out = s_alloc(p)) == NULL)
 			return MP_MEMORY;
@@ -847,24 +863,21 @@ mp_int_mul(mp_int a, mp_int b, mp_int c)
 	 */
 	if (out != MP_DIGITS(c))
 	{
-		s_free(MP_DIGITS(c));
-		MP_DIGITS(c) = out;
-		MP_ALLOC(c) = p;
+		if ((void *) MP_DIGITS(c) != (void *) c)
+			s_free(MP_DIGITS(c));
+		c->digits = out;
+		c->alloc = p;
 	}
 
-	MP_USED(c) = osize;			/* might not be true, but we'll fix it ... */
+	c->used = osize;			/* might not be true, but we'll fix it ... */
 	CLAMP(c);					/* ... right here */
-	MP_SIGN(c) = osign;
+	c->sign = osign;
 
 	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_mul_value(a, value, c) */
-
 mp_result
-mp_int_mul_value(mp_int a, int value, mp_int c)
+mp_int_mul_value(mp_int a, mp_small value, mp_int c)
 {
 	mpz_t		vtmp;
 	mp_digit	vbuf[MP_VALUE_DIGITS(value)];
@@ -874,45 +887,39 @@ mp_int_mul_value(mp_int a, int value, mp_int c)
 	return mp_int_mul(a, &vtmp, c);
 }
 
-/* }}} */
-
-/* {{{ mp_int_mul_pow2(a, p2, c) */
-
 mp_result
-mp_int_mul_pow2(mp_int a, int p2, mp_int c)
+mp_int_mul_pow2(mp_int a, mp_small p2, mp_int c)
 {
-	mp_result	res;
+	assert(a != NULL && c != NULL && p2 >= 0);
 
-	CHECK(a != NULL && c != NULL && p2 >= 0);
+	mp_result	res = mp_int_copy(a, c);
 
-	if ((res = mp_int_copy(a, c)) != MP_OK)
+	if (res != MP_OK)
 		return res;
 
 	if (s_qmul(c, (mp_size) p2))
+	{
 		return MP_OK;
+	}
 	else
+	{
 		return MP_MEMORY;
+	}
 }
 
-/* }}} */
-
-/* {{{ mp_int_sqr(a, c) */
-
 mp_result
 mp_int_sqr(mp_int a, mp_int c)
 {
-	mp_digit   *out;
-	mp_size		osize,
-				p = 0;
-
-	CHECK(a != NULL && c != NULL);
+	assert(a != NULL && c != NULL);
 
 	/* Get a temporary buffer big enough to hold the result */
-	osize = (mp_size) 4 * ((MP_USED(a) + 1) / 2);
+	mp_size		osize = (mp_size) 4 * ((MP_USED(a) + 1) / 2);
+	mp_size		p = 0;
+	mp_digit   *out;
 
 	if (a == c)
 	{
-		p = ROUND_PREC(osize);
+		p = s_round_prec(osize);
 		p = MAX(p, default_precision);
 
 		if ((out = s_alloc(p)) == NULL)
@@ -935,39 +942,35 @@ mp_int_sqr(mp_int a, mp_int c)
 	 */
 	if (out != MP_DIGITS(c))
 	{
-		s_free(MP_DIGITS(c));
-		MP_DIGITS(c) = out;
-		MP_ALLOC(c) = p;
+		if ((void *) MP_DIGITS(c) != (void *) c)
+			s_free(MP_DIGITS(c));
+		c->digits = out;
+		c->alloc = p;
 	}
 
-	MP_USED(c) = osize;			/* might not be true, but we'll fix it ... */
+	c->used = osize;			/* might not be true, but we'll fix it ... */
 	CLAMP(c);					/* ... right here */
-	MP_SIGN(c) = MP_ZPOS;
+	c->sign = MP_ZPOS;
 
 	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_div(a, b, q, r) */
-
 mp_result
 mp_int_div(mp_int a, mp_int b, mp_int q, mp_int r)
 {
-	int			cmp,
-				last = 0,
-				lg;
+	assert(a != NULL && b != NULL && q != r);
+
+	int			cmp;
 	mp_result	res = MP_OK;
-	mpz_t		temp[2];
 	mp_int		qout,
 				rout;
-	mp_sign		sa = MP_SIGN(a),
-				sb = MP_SIGN(b);
-
-	CHECK(a != NULL && b != NULL && q != r);
+	mp_sign		sa = MP_SIGN(a);
+	mp_sign		sb = MP_SIGN(b);
 
 	if (CMPZ(b) == 0)
+	{
 		return MP_UNDEF;
+	}
 	else if ((cmp = s_ucmp(a, b)) < 0)
 	{
 		/*
@@ -995,7 +998,7 @@ mp_int_div(mp_int a, mp_int b, mp_int q, mp_int r)
 			q->digits[0] = 1;
 
 			if (sa != sb)
-				MP_SIGN(q) = MP_NEG;
+				q->sign = MP_NEG;
 		}
 
 		return MP_OK;
@@ -1006,37 +1009,41 @@ mp_int_div(mp_int a, mp_int b, mp_int q, mp_int r)
 	 * quotient and remainder, but q and r are allowed to be NULL or to
 	 * overlap with the inputs.
 	 */
+	DECLARE_TEMP(2);
+	int			lg;
+
 	if ((lg = s_isp2(b)) < 0)
 	{
-		if (q && b != q && (res = mp_int_copy(a, q)) == MP_OK)
+		if (q && b != q)
 		{
+			REQUIRE(mp_int_copy(a, q));
 			qout = q;
 		}
 		else
 		{
-			qout = TEMP(last);
-			SETUP(mp_int_init_copy(TEMP(last), a), last);
+			REQUIRE(mp_int_copy(a, TEMP(0)));
+			qout = TEMP(0);
 		}
 
-		if (r && a != r && (res = mp_int_copy(b, r)) == MP_OK)
+		if (r && a != r)
 		{
+			REQUIRE(mp_int_copy(b, r));
 			rout = r;
 		}
 		else
 		{
-			rout = TEMP(last);
-			SETUP(mp_int_init_copy(TEMP(last), b), last);
+			REQUIRE(mp_int_copy(b, TEMP(1)));
+			rout = TEMP(1);
 		}
 
-		if ((res = s_udiv(qout, rout)) != MP_OK)
-			goto CLEANUP;
+		REQUIRE(s_udiv_knuth(qout, rout));
 	}
 	else
 	{
-		if (q && (res = mp_int_copy(a, q)) != MP_OK)
-			goto CLEANUP;
-		if (r && (res = mp_int_copy(a, r)) != MP_OK)
-			goto CLEANUP;
+		if (q)
+			REQUIRE(mp_int_copy(a, q));
+		if (r)
+			REQUIRE(mp_int_copy(a, r));
 
 		if (q)
 			s_qdiv(q, (mp_size) lg);
@@ -1049,203 +1056,184 @@ mp_int_div(mp_int a, mp_int b, mp_int q, mp_int r)
 	/* Recompute signs for output */
 	if (rout)
 	{
-		MP_SIGN(rout) = sa;
+		rout->sign = sa;
 		if (CMPZ(rout) == 0)
-			MP_SIGN(rout) = MP_ZPOS;
+			rout->sign = MP_ZPOS;
 	}
 	if (qout)
 	{
-		MP_SIGN(qout) = (sa == sb) ? MP_ZPOS : MP_NEG;
+		qout->sign = (sa == sb) ? MP_ZPOS : MP_NEG;
 		if (CMPZ(qout) == 0)
-			MP_SIGN(qout) = MP_ZPOS;
+			qout->sign = MP_ZPOS;
 	}
 
-	if (q && (res = mp_int_copy(qout, q)) != MP_OK)
-		goto CLEANUP;
-	if (r && (res = mp_int_copy(rout, r)) != MP_OK)
-		goto CLEANUP;
-
-CLEANUP:
-	while (--last >= 0)
-		mp_int_clear(TEMP(last));
-
+	if (q)
+		REQUIRE(mp_int_copy(qout, q));
+	if (r)
+		REQUIRE(mp_int_copy(rout, r));
+	CLEANUP_TEMP();
 	return res;
 }
 
-/* }}} */
-
-/* {{{ mp_int_mod(a, m, c) */
-
 mp_result
 mp_int_mod(mp_int a, mp_int m, mp_int c)
 {
-	mp_result	res;
-	mpz_t		tmp;
-	mp_int		out;
+	DECLARE_TEMP(1);
+	mp_int		out = (m == c) ? TEMP(0) : c;
 
-	if (m == c)
+	REQUIRE(mp_int_div(a, m, NULL, out));
+	if (CMPZ(out) < 0)
 	{
-		if ((res = mp_int_init(&tmp)) != MP_OK)
-			return res;
-
-		out = &tmp;
+		REQUIRE(mp_int_add(out, m, c));
 	}
 	else
 	{
-		out = c;
+		REQUIRE(mp_int_copy(out, c));
 	}
-
-	if ((res = mp_int_div(a, m, NULL, out)) != MP_OK)
-		goto CLEANUP;
-
-	if (CMPZ(out) < 0)
-		res = mp_int_add(out, m, c);
-	else
-		res = mp_int_copy(out, c);
-
-CLEANUP:
-	if (out != c)
-		mp_int_clear(&tmp);
-
-	return res;
+	CLEANUP_TEMP();
+	return MP_OK;
 }
 
-/* }}} */
-
-
-/* {{{ mp_int_div_value(a, value, q, r) */
-
 mp_result
-mp_int_div_value(mp_int a, int value, mp_int q, int *r)
+mp_int_div_value(mp_int a, mp_small value, mp_int q, mp_small * r)
 {
-	mpz_t		vtmp,
-				rtmp;
+	mpz_t		vtmp;
 	mp_digit	vbuf[MP_VALUE_DIGITS(value)];
-	mp_result	res;
 
-	if ((res = mp_int_init(&rtmp)) != MP_OK)
-		return res;
 	s_fake(&vtmp, value, vbuf);
 
-	if ((res = mp_int_div(a, &vtmp, q, &rtmp)) != MP_OK)
-		goto CLEANUP;
+	DECLARE_TEMP(1);
+	REQUIRE(mp_int_div(a, &vtmp, q, TEMP(0)));
 
 	if (r)
-		(void) mp_int_to_int(&rtmp, r); /* can't fail */
+		(void) mp_int_to_int(TEMP(0), r);	/* can't fail */
 
-CLEANUP:
-	mp_int_clear(&rtmp);
-	return res;
+	CLEANUP_TEMP();
+	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_div_pow2(a, p2, q, r) */
-
 mp_result
-mp_int_div_pow2(mp_int a, int p2, mp_int q, mp_int r)
+mp_int_div_pow2(mp_int a, mp_small p2, mp_int q, mp_int r)
 {
-	mp_result	res = MP_OK;
+	assert(a != NULL && p2 >= 0 && q != r);
 
-	CHECK(a != NULL && p2 >= 0 && q != r);
+	mp_result	res = MP_OK;
 
 	if (q != NULL && (res = mp_int_copy(a, q)) == MP_OK)
+	{
 		s_qdiv(q, (mp_size) p2);
+	}
 
 	if (res == MP_OK && r != NULL && (res = mp_int_copy(a, r)) == MP_OK)
+	{
 		s_qmod(r, (mp_size) p2);
+	}
 
 	return res;
 }
 
-/* }}} */
-
-/* {{{ mp_int_expt(a, b, c) */
-
 mp_result
-mp_int_expt(mp_int a, int b, mp_int c)
+mp_int_expt(mp_int a, mp_small b, mp_int c)
 {
-	mpz_t		t;
-	mp_result	res;
-	unsigned int v = abs(b);
+	assert(c != NULL);
+	if (b < 0)
+		return MP_RANGE;
 
-	CHECK(b >= 0 && c != NULL);
-
-	if ((res = mp_int_init_copy(&t, a)) != MP_OK)
-		return res;
+	DECLARE_TEMP(1);
+	REQUIRE(mp_int_copy(a, TEMP(0)));
 
 	(void) mp_int_set_value(c, 1);
+	unsigned int v = labs(b);
+
 	while (v != 0)
 	{
 		if (v & 1)
 		{
-			if ((res = mp_int_mul(c, &t, c)) != MP_OK)
-				goto CLEANUP;
+			REQUIRE(mp_int_mul(c, TEMP(0), c));
 		}
 
 		v >>= 1;
 		if (v == 0)
 			break;
 
-		if ((res = mp_int_sqr(&t, &t)) != MP_OK)
-			goto CLEANUP;
+		REQUIRE(mp_int_sqr(TEMP(0), TEMP(0)));
 	}
 
-CLEANUP:
-	mp_int_clear(&t);
-	return res;
+	CLEANUP_TEMP();
+	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_expt_value(a, b, c) */
-
 mp_result
-mp_int_expt_value(int a, int b, mp_int c)
+mp_int_expt_value(mp_small a, mp_small b, mp_int c)
 {
-	mpz_t		t;
-	mp_result	res;
-	unsigned int v = abs(b);
-
-	CHECK(b >= 0 && c != NULL);
+	assert(c != NULL);
+	if (b < 0)
+		return MP_RANGE;
 
-	if ((res = mp_int_init_value(&t, a)) != MP_OK)
-		return res;
+	DECLARE_TEMP(1);
+	REQUIRE(mp_int_set_value(TEMP(0), a));
 
 	(void) mp_int_set_value(c, 1);
+	unsigned int v = labs(b);
+
 	while (v != 0)
 	{
 		if (v & 1)
 		{
-			if ((res = mp_int_mul(c, &t, c)) != MP_OK)
-				goto CLEANUP;
+			REQUIRE(mp_int_mul(c, TEMP(0), c));
 		}
 
 		v >>= 1;
 		if (v == 0)
 			break;
 
-		if ((res = mp_int_sqr(&t, &t)) != MP_OK)
-			goto CLEANUP;
+		REQUIRE(mp_int_sqr(TEMP(0), TEMP(0)));
 	}
 
-CLEANUP:
-	mp_int_clear(&t);
-	return res;
+	CLEANUP_TEMP();
+	return MP_OK;
 }
 
-/* }}} */
+mp_result
+mp_int_expt_full(mp_int a, mp_int b, mp_int c)
+{
+	assert(a != NULL && b != NULL && c != NULL);
+	if (MP_SIGN(b) == MP_NEG)
+		return MP_RANGE;
+
+	DECLARE_TEMP(1);
+	REQUIRE(mp_int_copy(a, TEMP(0)));
+
+	(void) mp_int_set_value(c, 1);
+	for (unsigned ix = 0; ix < MP_USED(b); ++ix)
+	{
+		mp_digit	d = b->digits[ix];
+
+		for (unsigned jx = 0; jx < MP_DIGIT_BIT; ++jx)
+		{
+			if (d & 1)
+			{
+				REQUIRE(mp_int_mul(c, TEMP(0), c));
+			}
+
+			d >>= 1;
+			if (d == 0 && ix + 1 == MP_USED(b))
+				break;
+			REQUIRE(mp_int_sqr(TEMP(0), TEMP(0)));
+		}
+	}
 
-/* {{{ mp_int_compare(a, b) */
+	CLEANUP_TEMP();
+	return MP_OK;
+}
 
 int
 mp_int_compare(mp_int a, mp_int b)
 {
-	mp_sign		sa;
+	assert(a != NULL && b != NULL);
 
-	CHECK(a != NULL && b != NULL);
+	mp_sign		sa = MP_SIGN(a);
 
-	sa = MP_SIGN(a);
 	if (sa == MP_SIGN(b))
 	{
 		int			cmp = s_ucmp(a, b);
@@ -1254,91 +1242,90 @@ mp_int_compare(mp_int a, mp_int b)
 		 * If they're both zero or positive, the normal comparison applies; if
 		 * both negative, the sense is reversed.
 		 */
-		if (sa != MP_ZPOS)
-			INVERT_COMPARE_RESULT(cmp);
-		return cmp;
+		if (sa == MP_ZPOS)
+		{
+			return cmp;
+		}
+		else
+		{
+			return -cmp;
+		}
+	}
+	else if (sa == MP_ZPOS)
+	{
+		return 1;
 	}
 	else
 	{
-		if (sa == MP_ZPOS)
-			return 1;
-		else
-			return -1;
+		return -1;
 	}
 }
 
-/* }}} */
-
-/* {{{ mp_int_compare_unsigned(a, b) */
-
 int
 mp_int_compare_unsigned(mp_int a, mp_int b)
 {
-	NRCHECK(a != NULL && b != NULL);
+	assert(a != NULL && b != NULL);
 
 	return s_ucmp(a, b);
 }
 
-/* }}} */
-
-/* {{{ mp_int_compare_zero(z) */
-
 int
 mp_int_compare_zero(mp_int z)
 {
-	NRCHECK(z != NULL);
+	assert(z != NULL);
 
 	if (MP_USED(z) == 1 && z->digits[0] == 0)
+	{
 		return 0;
+	}
 	else if (MP_SIGN(z) == MP_ZPOS)
+	{
 		return 1;
+	}
 	else
+	{
 		return -1;
+	}
 }
 
-/* }}} */
-
-/* {{{ mp_int_compare_value(z, value) */
-
 int
-mp_int_compare_value(mp_int z, int value)
+mp_int_compare_value(mp_int z, mp_small value)
 {
-	mp_sign		vsign = (value < 0) ? MP_NEG : MP_ZPOS;
-	int			cmp;
+	assert(z != NULL);
 
-	CHECK(z != NULL);
+	mp_sign		vsign = (value < 0) ? MP_NEG : MP_ZPOS;
 
 	if (vsign == MP_SIGN(z))
 	{
-		cmp = s_vcmp(z, value);
+		int			cmp = s_vcmp(z, value);
 
-		if (vsign != MP_ZPOS)
-			INVERT_COMPARE_RESULT(cmp);
-		return cmp;
+		return (vsign == MP_ZPOS) ? cmp : -cmp;
 	}
 	else
 	{
-		if (value < 0)
-			return 1;
-		else
-			return -1;
+		return (value < 0) ? 1 : -1;
 	}
 }
 
-/* }}} */
+int
+mp_int_compare_uvalue(mp_int z, mp_usmall uv)
+{
+	assert(z != NULL);
 
-/* {{{ mp_int_exptmod(a, b, m, c) */
+	if (MP_SIGN(z) == MP_NEG)
+	{
+		return -1;
+	}
+	else
+	{
+		return s_uvcmp(z, uv);
+	}
+}
 
 mp_result
 mp_int_exptmod(mp_int a, mp_int b, mp_int m, mp_int c)
 {
-	mp_result	res;
-	mp_size		um;
-	mpz_t		temp[3];
-	mp_int		s;
-	int			last = 0;
-
-	CHECK(a != NULL && b != NULL && c != NULL && m != NULL);
+	assert(a != NULL && b != NULL && c != NULL && m != NULL);
 
 	/* Zero moduli and negative exponents are not considered. */
 	if (CMPZ(m) == 0)
@@ -1346,13 +1333,17 @@ mp_int_exptmod(mp_int a, mp_int b, mp_int m, mp_int c)
 	if (CMPZ(b) < 0)
 		return MP_RANGE;
 
-	um = MP_USED(m);
-	SETUP(mp_int_init_size(TEMP(0), 2 * um), last);
-	SETUP(mp_int_init_size(TEMP(1), 2 * um), last);
+	mp_size		um = MP_USED(m);
+
+	DECLARE_TEMP(3);
+	REQUIRE(GROW(TEMP(0), 2 * um));
+	REQUIRE(GROW(TEMP(1), 2 * um));
+
+	mp_int		s;
 
 	if (c == b || c == m)
 	{
-		SETUP(mp_int_init_size(TEMP(2), 2 * um), last);
+		REQUIRE(GROW(TEMP(2), 2 * um));
 		s = TEMP(2);
 	}
 	else
@@ -1360,30 +1351,17 @@ mp_int_exptmod(mp_int a, mp_int b, mp_int m, mp_int c)
 		s = c;
 	}
 
-	if ((res = mp_int_mod(a, m, TEMP(0))) != MP_OK)
-		goto CLEANUP;
-
-	if ((res = s_brmu(TEMP(1), m)) != MP_OK)
-		goto CLEANUP;
-
-	if ((res = s_embar(TEMP(0), b, m, TEMP(1), s)) != MP_OK)
-		goto CLEANUP;
-
-	res = mp_int_copy(s, c);
+	REQUIRE(mp_int_mod(a, m, TEMP(0)));
+	REQUIRE(s_brmu(TEMP(1), m));
+	REQUIRE(s_embar(TEMP(0), b, m, TEMP(1), s));
+	REQUIRE(mp_int_copy(s, c));
 
-CLEANUP:
-	while (--last >= 0)
-		mp_int_clear(TEMP(last));
-
-	return res;
+	CLEANUP_TEMP();
+	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_exptmod_evalue(a, value, m, c) */
-
 mp_result
-mp_int_exptmod_evalue(mp_int a, int value, mp_int m, mp_int c)
+mp_int_exptmod_evalue(mp_int a, mp_small value, mp_int m, mp_int c)
 {
 	mpz_t		vtmp;
 	mp_digit	vbuf[MP_VALUE_DIGITS(value)];
@@ -1393,13 +1371,8 @@ mp_int_exptmod_evalue(mp_int a, int value, mp_int m, mp_int c)
 	return mp_int_exptmod(a, &vtmp, m, c);
 }
 
-/* }}} */
-
-/* {{{ mp_int_exptmod_bvalue(v, b, m, c) */
-
 mp_result
-mp_int_exptmod_bvalue(int value, mp_int b,
-					  mp_int m, mp_int c)
+mp_int_exptmod_bvalue(mp_small value, mp_int b, mp_int m, mp_int c)
 {
 	mpz_t		vtmp;
 	mp_digit	vbuf[MP_VALUE_DIGITS(value)];
@@ -1409,20 +1382,11 @@ mp_int_exptmod_bvalue(int value, mp_int b,
 	return mp_int_exptmod(&vtmp, b, m, c);
 }
 
-/* }}} */
-
-/* {{{ mp_int_exptmod_known(a, b, m, mu, c) */
-
 mp_result
-mp_int_exptmod_known(mp_int a, mp_int b, mp_int m, mp_int mu, mp_int c)
+mp_int_exptmod_known(mp_int a, mp_int b, mp_int m, mp_int mu,
+					 mp_int c)
 {
-	mp_result	res;
-	mp_size		um;
-	mpz_t		temp[2];
-	mp_int		s;
-	int			last = 0;
-
-	CHECK(a && b && m && c);
+	assert(a && b && m && c);
 
 	/* Zero moduli and negative exponents are not considered. */
 	if (CMPZ(m) == 0)
@@ -1430,12 +1394,16 @@ mp_int_exptmod_known(mp_int a, mp_int b, mp_int m, mp_int mu, mp_int c)
 	if (CMPZ(b) < 0)
 		return MP_RANGE;
 
-	um = MP_USED(m);
-	SETUP(mp_int_init_size(TEMP(0), 2 * um), last);
+	DECLARE_TEMP(2);
+	mp_size		um = MP_USED(m);
+
+	REQUIRE(GROW(TEMP(0), 2 * um));
+
+	mp_int		s;
 
 	if (c == b || c == m)
 	{
-		SETUP(mp_int_init_size(TEMP(1), 2 * um), last);
+		REQUIRE(GROW(TEMP(1), 2 * um));
 		s = TEMP(1);
 	}
 	else
@@ -1443,68 +1411,41 @@ mp_int_exptmod_known(mp_int a, mp_int b, mp_int m, mp_int mu, mp_int c)
 		s = c;
 	}
 
-	if ((res = mp_int_mod(a, m, TEMP(0))) != MP_OK)
-		goto CLEANUP;
-
-	if ((res = s_embar(TEMP(0), b, m, mu, s)) != MP_OK)
-		goto CLEANUP;
+	REQUIRE(mp_int_mod(a, m, TEMP(0)));
+	REQUIRE(s_embar(TEMP(0), b, m, mu, s));
+	REQUIRE(mp_int_copy(s, c));
 
-	res = mp_int_copy(s, c);
-
-CLEANUP:
-	while (--last >= 0)
-		mp_int_clear(TEMP(last));
-
-	return res;
+	CLEANUP_TEMP();
+	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_redux_const(m, c) */
-
 mp_result
 mp_int_redux_const(mp_int m, mp_int c)
 {
-	CHECK(m != NULL && c != NULL && m != c);
+	assert(m != NULL && c != NULL && m != c);
 
 	return s_brmu(c, m);
 }
 
-/* }}} */
-
-/* {{{ mp_int_invmod(a, m, c) */
-
 mp_result
 mp_int_invmod(mp_int a, mp_int m, mp_int c)
 {
-	mp_result	res;
-	mp_sign		sa;
-	int			last = 0;
-	mpz_t		temp[2];
-
-	CHECK(a != NULL && m != NULL && c != NULL);
+	assert(a != NULL && m != NULL && c != NULL);
 
 	if (CMPZ(a) == 0 || CMPZ(m) <= 0)
 		return MP_RANGE;
 
-	sa = MP_SIGN(a);			/* need this for the result later */
+	DECLARE_TEMP(2);
 
-	for (last = 0; last < 2; ++last)
-		if ((res = mp_int_init(TEMP(last))) != MP_OK)
-			goto CLEANUP;
-
-	if ((res = mp_int_egcd(a, m, TEMP(0), TEMP(1), NULL)) != MP_OK)
-		goto CLEANUP;
+	REQUIRE(mp_int_egcd(a, m, TEMP(0), TEMP(1), NULL));
 
 	if (mp_int_compare_value(TEMP(0), 1) != 0)
 	{
-		res = MP_UNDEF;
-		goto CLEANUP;
+		REQUIRE(MP_UNDEF);
 	}
 
 	/* It is first necessary to constrain the value to the proper range */
-	if ((res = mp_int_mod(TEMP(1), m, TEMP(1))) != MP_OK)
-		goto CLEANUP;
+	REQUIRE(mp_int_mod(TEMP(1), m, TEMP(1)));
 
 	/*
 	 * Now, if 'a' was originally negative, the value we have is actually the
@@ -1512,136 +1453,112 @@ mp_int_invmod(mp_int a, mp_int m, mp_int c)
 	 * have to subtract from the modulus.  Otherwise, the value is okay as it
 	 * stands.
 	 */
-	if (sa == MP_NEG)
-		res = mp_int_sub(m, TEMP(1), c);
+	if (MP_SIGN(a) == MP_NEG)
+	{
+		REQUIRE(mp_int_sub(m, TEMP(1), c));
+	}
 	else
-		res = mp_int_copy(TEMP(1), c);
-
-CLEANUP:
-	while (--last >= 0)
-		mp_int_clear(TEMP(last));
+	{
+		REQUIRE(mp_int_copy(TEMP(1), c));
+	}
 
-	return res;
+	CLEANUP_TEMP();
+	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_gcd(a, b, c) */
-
 /* Binary GCD algorithm due to Josef Stein, 1961 */
 mp_result
 mp_int_gcd(mp_int a, mp_int b, mp_int c)
 {
-	int			ca,
-				cb,
-				k = 0;
-	mpz_t		u,
-				v,
-				t;
-	mp_result	res;
+	assert(a != NULL && b != NULL && c != NULL);
 
-	CHECK(a != NULL && b != NULL && c != NULL);
+	int			ca = CMPZ(a);
+	int			cb = CMPZ(b);
 
-	ca = CMPZ(a);
-	cb = CMPZ(b);
 	if (ca == 0 && cb == 0)
+	{
 		return MP_UNDEF;
+	}
 	else if (ca == 0)
+	{
 		return mp_int_abs(b, c);
+	}
 	else if (cb == 0)
+	{
 		return mp_int_abs(a, c);
+	}
 
-	if ((res = mp_int_init(&t)) != MP_OK)
-		return res;
-	if ((res = mp_int_init_copy(&u, a)) != MP_OK)
-		goto U;
-	if ((res = mp_int_init_copy(&v, b)) != MP_OK)
-		goto V;
+	DECLARE_TEMP(3);
+	REQUIRE(mp_int_copy(a, TEMP(0)));
+	REQUIRE(mp_int_copy(b, TEMP(1)));
 
-	MP_SIGN(&u) = MP_ZPOS;
-	MP_SIGN(&v) = MP_ZPOS;
+	TEMP(0)->sign = MP_ZPOS;
+	TEMP(1)->sign = MP_ZPOS;
+
+	int			k = 0;
 
 	{							/* Divide out common factors of 2 from u and v */
-		int			div2_u = s_dp2k(&u),
-					div2_v = s_dp2k(&v);
+		int			div2_u = s_dp2k(TEMP(0));
+		int			div2_v = s_dp2k(TEMP(1));
 
 		k = MIN(div2_u, div2_v);
-		s_qdiv(&u, (mp_size) k);
-		s_qdiv(&v, (mp_size) k);
+		s_qdiv(TEMP(0), (mp_size) k);
+		s_qdiv(TEMP(1), (mp_size) k);
 	}
 
-	if (mp_int_is_odd(&u))
+	if (mp_int_is_odd(TEMP(0)))
 	{
-		if ((res = mp_int_neg(&v, &t)) != MP_OK)
-			goto CLEANUP;
+		REQUIRE(mp_int_neg(TEMP(1), TEMP(2)));
 	}
 	else
 	{
-		if ((res = mp_int_copy(&u, &t)) != MP_OK)
-			goto CLEANUP;
+		REQUIRE(mp_int_copy(TEMP(0), TEMP(2)));
 	}
 
 	for (;;)
 	{
-		s_qdiv(&t, s_dp2k(&t));
+		s_qdiv(TEMP(2), s_dp2k(TEMP(2)));
 
-		if (CMPZ(&t) > 0)
+		if (CMPZ(TEMP(2)) > 0)
 		{
-			if ((res = mp_int_copy(&t, &u)) != MP_OK)
-				goto CLEANUP;
+			REQUIRE(mp_int_copy(TEMP(2), TEMP(0)));
 		}
 		else
 		{
-			if ((res = mp_int_neg(&t, &v)) != MP_OK)
-				goto CLEANUP;
+			REQUIRE(mp_int_neg(TEMP(2), TEMP(1)));
 		}
 
-		if ((res = mp_int_sub(&u, &v, &t)) != MP_OK)
-			goto CLEANUP;
+		REQUIRE(mp_int_sub(TEMP(0), TEMP(1), TEMP(2)));
 
-		if (CMPZ(&t) == 0)
+		if (CMPZ(TEMP(2)) == 0)
 			break;
 	}
 
-	if ((res = mp_int_abs(&u, c)) != MP_OK)
-		goto CLEANUP;
+	REQUIRE(mp_int_abs(TEMP(0), c));
 	if (!s_qmul(c, (mp_size) k))
-		res = MP_MEMORY;
-
-CLEANUP:
-	mp_int_clear(&v);
-V:	mp_int_clear(&u);
-U:	mp_int_clear(&t);
+		REQUIRE(MP_MEMORY);
 
-	return res;
+	CLEANUP_TEMP();
+	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_egcd(a, b, c, x, y) */
-
-/* This is the binary GCD algorithm again, but this time we keep track
-   of the elementary matrix operations as we go, so we can get values
-   x and y satisfying c = ax + by.
+/* This is the binary GCD algorithm again, but this time we keep track of the
+   elementary matrix operations as we go, so we can get values x and y
+   satisfying c = ax + by.
  */
 mp_result
-mp_int_egcd(mp_int a, mp_int b, mp_int c,
-			mp_int x, mp_int y)
-{
-	int			k,
-				last = 0,
-				ca,
-				cb;
-	mpz_t		temp[8];
-	mp_result	res;
+mp_int_egcd(mp_int a, mp_int b, mp_int c, mp_int x, mp_int y)
+{
+	assert(a != NULL && b != NULL && c != NULL && (x != NULL || y != NULL));
 
-	CHECK(a != NULL && b != NULL && c != NULL &&
-		  (x != NULL || y != NULL));
+	mp_result	res = MP_OK;
+	int			ca = CMPZ(a);
+	int			cb = CMPZ(b);
 
-	ca = CMPZ(a);
-	cb = CMPZ(b);
 	if (ca == 0 && cb == 0)
+	{
 		return MP_UNDEF;
+	}
 	else if (ca == 0)
 	{
 		if ((res = mp_int_abs(b, c)) != MP_OK)
@@ -1662,20 +1579,17 @@ mp_int_egcd(mp_int a, mp_int b, mp_int c,
 	/*
 	 * Initialize temporaries: A:0, B:1, C:2, D:3, u:4, v:5, ou:6, ov:7
 	 */
-	for (last = 0; last < 4; ++last)
-	{
-		if ((res = mp_int_init(TEMP(last))) != MP_OK)
-			goto CLEANUP;
-	}
-	TEMP(0)->digits[0] = 1;
-	TEMP(3)->digits[0] = 1;
-
-	SETUP(mp_int_init_copy(TEMP(4), a), last);
-	SETUP(mp_int_init_copy(TEMP(5), b), last);
+	DECLARE_TEMP(8);
+	REQUIRE(mp_int_set_value(TEMP(0), 1));
+	REQUIRE(mp_int_set_value(TEMP(3), 1));
+	REQUIRE(mp_int_copy(a, TEMP(4)));
+	REQUIRE(mp_int_copy(b, TEMP(5)));
 
 	/* We will work with absolute values here */
-	MP_SIGN(TEMP(4)) = MP_ZPOS;
-	MP_SIGN(TEMP(5)) = MP_ZPOS;
+	TEMP(4)->sign = MP_ZPOS;
+	TEMP(5)->sign = MP_ZPOS;
+
+	int			k = 0;
 
 	{							/* Divide out common factors of 2 from u and v */
 		int			div2_u = s_dp2k(TEMP(4)),
@@ -1686,8 +1600,8 @@ mp_int_egcd(mp_int a, mp_int b, mp_int c,
 		s_qdiv(TEMP(5), k);
 	}
 
-	SETUP(mp_int_init_copy(TEMP(6), TEMP(4)), last);
-	SETUP(mp_int_init_copy(TEMP(7), TEMP(5)), last);
+	REQUIRE(mp_int_copy(TEMP(4), TEMP(6)));
+	REQUIRE(mp_int_copy(TEMP(5), TEMP(7)));
 
 	for (;;)
 	{
@@ -1697,10 +1611,8 @@ mp_int_egcd(mp_int a, mp_int b, mp_int c,
 
 			if (mp_int_is_odd(TEMP(0)) || mp_int_is_odd(TEMP(1)))
 			{
-				if ((res = mp_int_add(TEMP(0), TEMP(7), TEMP(0))) != MP_OK)
-					goto CLEANUP;
-				if ((res = mp_int_sub(TEMP(1), TEMP(6), TEMP(1))) != MP_OK)
-					goto CLEANUP;
+				REQUIRE(mp_int_add(TEMP(0), TEMP(7), TEMP(0)));
+				REQUIRE(mp_int_sub(TEMP(1), TEMP(6), TEMP(1)));
 			}
 
 			s_qdiv(TEMP(0), 1);
@@ -1713,10 +1625,8 @@ mp_int_egcd(mp_int a, mp_int b, mp_int c,
 
 			if (mp_int_is_odd(TEMP(2)) || mp_int_is_odd(TEMP(3)))
 			{
-				if ((res = mp_int_add(TEMP(2), TEMP(7), TEMP(2))) != MP_OK)
-					goto CLEANUP;
-				if ((res = mp_int_sub(TEMP(3), TEMP(6), TEMP(3))) != MP_OK)
-					goto CLEANUP;
+				REQUIRE(mp_int_add(TEMP(2), TEMP(7), TEMP(2)));
+				REQUIRE(mp_int_sub(TEMP(3), TEMP(6), TEMP(3)));
 			}
 
 			s_qdiv(TEMP(2), 1);
@@ -1725,157 +1635,163 @@ mp_int_egcd(mp_int a, mp_int b, mp_int c,
 
 		if (mp_int_compare(TEMP(4), TEMP(5)) >= 0)
 		{
-			if ((res = mp_int_sub(TEMP(4), TEMP(5), TEMP(4))) != MP_OK)
-				goto CLEANUP;
-			if ((res = mp_int_sub(TEMP(0), TEMP(2), TEMP(0))) != MP_OK)
-				goto CLEANUP;
-			if ((res = mp_int_sub(TEMP(1), TEMP(3), TEMP(1))) != MP_OK)
-				goto CLEANUP;
+			REQUIRE(mp_int_sub(TEMP(4), TEMP(5), TEMP(4)));
+			REQUIRE(mp_int_sub(TEMP(0), TEMP(2), TEMP(0)));
+			REQUIRE(mp_int_sub(TEMP(1), TEMP(3), TEMP(1)));
 		}
 		else
 		{
-			if ((res = mp_int_sub(TEMP(5), TEMP(4), TEMP(5))) != MP_OK)
-				goto CLEANUP;
-			if ((res = mp_int_sub(TEMP(2), TEMP(0), TEMP(2))) != MP_OK)
-				goto CLEANUP;
-			if ((res = mp_int_sub(TEMP(3), TEMP(1), TEMP(3))) != MP_OK)
-				goto CLEANUP;
+			REQUIRE(mp_int_sub(TEMP(5), TEMP(4), TEMP(5)));
+			REQUIRE(mp_int_sub(TEMP(2), TEMP(0), TEMP(2)));
+			REQUIRE(mp_int_sub(TEMP(3), TEMP(1), TEMP(3)));
 		}
 
 		if (CMPZ(TEMP(4)) == 0)
 		{
-			if (x && (res = mp_int_copy(TEMP(2), x)) != MP_OK)
-				goto CLEANUP;
-			if (y && (res = mp_int_copy(TEMP(3), y)) != MP_OK)
-				goto CLEANUP;
+			if (x)
+				REQUIRE(mp_int_copy(TEMP(2), x));
+			if (y)
+				REQUIRE(mp_int_copy(TEMP(3), y));
 			if (c)
 			{
 				if (!s_qmul(TEMP(5), k))
 				{
-					res = MP_MEMORY;
-					goto CLEANUP;
+					REQUIRE(MP_MEMORY);
 				}
-
-				res = mp_int_copy(TEMP(5), c);
+				REQUIRE(mp_int_copy(TEMP(5), c));
 			}
 
 			break;
 		}
 	}
 
-CLEANUP:
-	while (--last >= 0)
-		mp_int_clear(TEMP(last));
-
-	return res;
+	CLEANUP_TEMP();
+	return MP_OK;
 }
 
-/* }}} */
+mp_result
+mp_int_lcm(mp_int a, mp_int b, mp_int c)
+{
+	assert(a != NULL && b != NULL && c != NULL);
+
+	/*
+	 * Since a * b = gcd(a, b) * lcm(a, b), we can compute lcm(a, b) = (a /
+	 * gcd(a, b)) * b.
+	 *
+	 * This formulation insures everything works even if the input variables
+	 * share space.
+	 */
+	DECLARE_TEMP(1);
+	REQUIRE(mp_int_gcd(a, b, TEMP(0)));
+	REQUIRE(mp_int_div(a, TEMP(0), TEMP(0), NULL));
+	REQUIRE(mp_int_mul(TEMP(0), b, TEMP(0)));
+	REQUIRE(mp_int_copy(TEMP(0), c));
 
-/* {{{ mp_int_divisible_value(a, v) */
+	CLEANUP_TEMP();
+	return MP_OK;
+}
 
-int
-mp_int_divisible_value(mp_int a, int v)
+bool
+mp_int_divisible_value(mp_int a, mp_small v)
 {
-	int			rem = 0;
+	mp_small	rem = 0;
 
 	if (mp_int_div_value(a, v, NULL, &rem) != MP_OK)
-		return 0;
-
+	{
+		return false;
+	}
 	return rem == 0;
 }
 
-/* }}} */
-
-/* {{{ mp_int_is_pow2(z) */
-
 int
 mp_int_is_pow2(mp_int z)
 {
-	CHECK(z != NULL);
+	assert(z != NULL);
 
 	return s_isp2(z);
 }
 
-/* }}} */
-
-/* {{{ mp_int_sqrt(a, c) */
-
+/* Implementation of Newton's root finding method, based loosely on a patch
+   contributed by Hal Finkel <half@halssoftware.com>
+   modified by M. J. Fromberger.
+ */
 mp_result
-mp_int_sqrt(mp_int a, mp_int c)
+mp_int_root(mp_int a, mp_small b, mp_int c)
 {
-	mp_result	res = MP_OK;
-	mpz_t		temp[2];
-	int			last = 0;
+	assert(a != NULL && c != NULL && b > 0);
 
-	CHECK(a != NULL && c != NULL);
+	if (b == 1)
+	{
+		return mp_int_copy(a, c);
+	}
+	bool		flips = false;
 
-	/* The square root of a negative value does not exist in the integers. */
 	if (MP_SIGN(a) == MP_NEG)
-		return MP_UNDEF;
+	{
+		if (b % 2 == 0)
+		{
+			return MP_UNDEF;	/* root does not exist for negative a with
+								 * even b */
+		}
+		else
+		{
+			flips = true;
+		}
+	}
 
-	SETUP(mp_int_init_copy(TEMP(last), a), last);
-	SETUP(mp_int_init(TEMP(last)), last);
+	DECLARE_TEMP(5);
+	REQUIRE(mp_int_copy(a, TEMP(0)));
+	REQUIRE(mp_int_copy(a, TEMP(1)));
+	TEMP(0)->sign = MP_ZPOS;
+	TEMP(1)->sign = MP_ZPOS;
 
 	for (;;)
 	{
-		if ((res = mp_int_sqr(TEMP(0), TEMP(1))) != MP_OK)
-			goto CLEANUP;
+		REQUIRE(mp_int_expt(TEMP(1), b, TEMP(2)));
 
-		if (mp_int_compare_unsigned(a, TEMP(1)) == 0)
+		if (mp_int_compare_unsigned(TEMP(2), TEMP(0)) <= 0)
 			break;
 
-		if ((res = mp_int_copy(a, TEMP(1))) != MP_OK)
-			goto CLEANUP;
-		if ((res = mp_int_div(TEMP(1), TEMP(0), TEMP(1), NULL)) != MP_OK)
-			goto CLEANUP;
-		if ((res = mp_int_add(TEMP(0), TEMP(1), TEMP(1))) != MP_OK)
-			goto CLEANUP;
-		if ((res = mp_int_div_pow2(TEMP(1), 1, TEMP(1), NULL)) != MP_OK)
-			goto CLEANUP;
+		REQUIRE(mp_int_sub(TEMP(2), TEMP(0), TEMP(2)));
+		REQUIRE(mp_int_expt(TEMP(1), b - 1, TEMP(3)));
+		REQUIRE(mp_int_mul_value(TEMP(3), b, TEMP(3)));
+		REQUIRE(mp_int_div(TEMP(2), TEMP(3), TEMP(4), NULL));
+		REQUIRE(mp_int_sub(TEMP(1), TEMP(4), TEMP(4)));
 
-		if (mp_int_compare_unsigned(TEMP(0), TEMP(1)) == 0)
-			break;
-		if ((res = mp_int_sub_value(TEMP(0), 1, TEMP(0))) != MP_OK)
-			goto CLEANUP;
-		if (mp_int_compare_unsigned(TEMP(0), TEMP(1)) == 0)
-			break;
-
-		if ((res = mp_int_copy(TEMP(1), TEMP(0))) != MP_OK)
-			goto CLEANUP;
+		if (mp_int_compare_unsigned(TEMP(1), TEMP(4)) == 0)
+		{
+			REQUIRE(mp_int_sub_value(TEMP(4), 1, TEMP(4)));
+		}
+		REQUIRE(mp_int_copy(TEMP(4), TEMP(1)));
 	}
 
-	res = mp_int_copy(TEMP(0), c);
+	REQUIRE(mp_int_copy(TEMP(1), c));
 
-CLEANUP:
-	while (--last >= 0)
-		mp_int_clear(TEMP(last));
+	/* If the original value of a was negative, flip the output sign. */
+	if (flips)
+		(void) mp_int_neg(c, c);	/* cannot fail */
 
-	return res;
+	CLEANUP_TEMP();
+	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_to_int(z, out) */
-
 mp_result
-mp_int_to_int(mp_int z, int *out)
+mp_int_to_int(mp_int z, mp_small * out)
 {
-	unsigned int uv = 0;
-	mp_size		uz;
-	mp_digit   *dz;
-	mp_sign		sz;
+	assert(z != NULL);
 
-	CHECK(z != NULL);
+	/* Make sure the value is representable as a small integer */
+	mp_sign		sz = MP_SIGN(z);
 
-	/* Make sure the value is representable as an int */
-	sz = MP_SIGN(z);
-	if ((sz == MP_ZPOS && mp_int_compare_value(z, INT_MAX) > 0) ||
-		mp_int_compare_value(z, INT_MIN) < 0)
+	if ((sz == MP_ZPOS && mp_int_compare_value(z, MP_SMALL_MAX) > 0) ||
+		mp_int_compare_value(z, MP_SMALL_MIN) < 0)
+	{
 		return MP_RANGE;
+	}
 
-	uz = MP_USED(z);
-	dz = MP_DIGITS(z) + uz - 1;
+	mp_usmall	uz = MP_USED(z);
+	mp_digit   *dz = MP_DIGITS(z) + uz - 1;
+	mp_small	uv = 0;
 
 	while (uz > 0)
 	{
@@ -1885,33 +1801,56 @@ mp_int_to_int(mp_int z, int *out)
 	}
 
 	if (out)
-		*out = (sz == MP_NEG) ? -(int) uv : (int) uv;
+		*out = (mp_small) ((sz == MP_NEG) ? -uv : uv);
 
 	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_to_string(z, radix, str, limit) */
-
 mp_result
-mp_int_to_string(mp_int z, mp_size radix,
-				 char *str, int limit)
+mp_int_to_uint(mp_int z, mp_usmall * out)
 {
-	mp_result	res;
-	int			cmp = 0;
+	assert(z != NULL);
 
-	CHECK(z != NULL && str != NULL && limit >= 2);
+	/* Make sure the value is representable as an unsigned small integer */
+	mp_size		sz = MP_SIGN(z);
 
-	if (radix < MP_MIN_RADIX || radix > MP_MAX_RADIX)
+	if (sz == MP_NEG || mp_int_compare_uvalue(z, MP_USMALL_MAX) > 0)
+	{
 		return MP_RANGE;
+	}
+
+	mp_size		uz = MP_USED(z);
+	mp_digit   *dz = MP_DIGITS(z) + uz - 1;
+	mp_usmall	uv = 0;
+
+	while (uz > 0)
+	{
+		uv <<= MP_DIGIT_BIT / 2;
+		uv = (uv << (MP_DIGIT_BIT / 2)) | *dz--;
+		--uz;
+	}
+
+	if (out)
+		*out = uv;
+
+	return MP_OK;
+}
+
+mp_result
+mp_int_to_string(mp_int z, mp_size radix, char *str, int limit)
+{
+	assert(z != NULL && str != NULL && limit >= 2);
+	assert(radix >= MP_MIN_RADIX && radix <= MP_MAX_RADIX);
+
+	int			cmp = 0;
 
 	if (CMPZ(z) == 0)
 	{
-		*str++ = s_val2ch(0, mp_flags & MP_CAP_DIGITS);
+		*str++ = s_val2ch(0, 1);
 	}
 	else
 	{
+		mp_result	res;
 		mpz_t		tmp;
 		char	   *h,
 				   *t;
@@ -1935,7 +1874,7 @@ mp_int_to_string(mp_int z, mp_size radix,
 				break;
 
 			d = s_ddiv(&tmp, (mp_digit) radix);
-			*str++ = s_val2ch(d, mp_flags & MP_CAP_DIGITS);
+			*str++ = s_val2ch(d, 1);
 		}
 		t = str - 1;
 
@@ -1953,26 +1892,22 @@ mp_int_to_string(mp_int z, mp_size radix,
 
 	*str = '\0';
 	if (cmp == 0)
+	{
 		return MP_OK;
+	}
 	else
+	{
 		return MP_TRUNC;
+	}
 }
 
-/* }}} */
-
-/* {{{ mp_int_string_len(z, radix) */
-
 mp_result
 mp_int_string_len(mp_int z, mp_size radix)
 {
-	int			len;
-
-	CHECK(z != NULL);
-
-	if (radix < MP_MIN_RADIX || radix > MP_MAX_RADIX)
-		return MP_RANGE;
+	assert(z != NULL);
+	assert(radix >= MP_MIN_RADIX && radix <= MP_MAX_RADIX);
 
-	len = s_outlen(z, radix) + 1;	/* for terminator */
+	int			len = s_outlen(z, radix) + 1;	/* for terminator */
 
 	/* Allow for sign marker on negatives */
 	if (MP_SIGN(z) == MP_NEG)
@@ -1981,31 +1916,19 @@ mp_int_string_len(mp_int z, mp_size radix)
 	return len;
 }
 
-/* }}} */
-
-/* {{{ mp_int_read_string(z, radix, *str) */
-
 /* Read zero-terminated string into z */
 mp_result
 mp_int_read_string(mp_int z, mp_size radix, const char *str)
 {
 	return mp_int_read_cstring(z, radix, str, NULL);
-
 }
 
-/* }}} */
-
-/* {{{ mp_int_read_cstring(z, radix, *str, **end) */
-
 mp_result
-mp_int_read_cstring(mp_int z, mp_size radix, const char *str, char **end)
+mp_int_read_cstring(mp_int z, mp_size radix, const char *str,
+					char **end)
 {
-	int			ch;
-
-	CHECK(z != NULL && str != NULL);
-
-	if (radix < MP_MIN_RADIX || radix > MP_MAX_RADIX)
-		return MP_RANGE;
+	assert(z != NULL && str != NULL);
+	assert(radix >= MP_MIN_RADIX && radix <= MP_MAX_RADIX);
 
 	/* Skip leading whitespace */
 	while (isspace((unsigned char) *str))
@@ -2015,17 +1938,19 @@ mp_int_read_cstring(mp_int z, mp_size radix, const char *str, char **end)
 	switch (*str)
 	{
 		case '-':
-			MP_SIGN(z) = MP_NEG;
+			z->sign = MP_NEG;
 			++str;
 			break;
 		case '+':
 			++str;				/* fallthrough */
 		default:
-			MP_SIGN(z) = MP_ZPOS;
+			z->sign = MP_ZPOS;
 			break;
 	}
 
 	/* Skip leading zeroes */
+	int			ch;
+
 	while ((ch = s_ch2val(*str, radix)) == 0)
 		++str;
 
@@ -2033,7 +1958,7 @@ mp_int_read_cstring(mp_int z, mp_size radix, const char *str, char **end)
 	if (!s_pad(z, s_inlen(strlen(str), radix)))
 		return MP_MEMORY;
 
-	MP_USED(z) = 1;
+	z->used = 1;
 	z->digits[0] = 0;
 
 	while (*str != '\0' && ((ch = s_ch2val(*str, radix)) >= 0))
@@ -2047,7 +1972,7 @@ mp_int_read_cstring(mp_int z, mp_size radix, const char *str, char **end)
 
 	/* Override sign for zero, even if negative specified. */
 	if (CMPZ(z) == 0)
-		MP_SIGN(z) = MP_ZPOS;
+		z->sign = MP_ZPOS;
 
 	if (end != NULL)
 		*end = (char *) str;
@@ -2057,31 +1982,28 @@ mp_int_read_cstring(mp_int z, mp_size radix, const char *str, char **end)
 	 * remaining, so the caller can tell if the whole string was done
 	 */
 	if (*str != '\0')
+	{
 		return MP_TRUNC;
+	}
 	else
+	{
 		return MP_OK;
+	}
 }
 
-/* }}} */
-
-/* {{{ mp_int_count_bits(z) */
-
 mp_result
 mp_int_count_bits(mp_int z)
 {
-	mp_size		nbits = 0,
-				uz;
-	mp_digit	d;
+	assert(z != NULL);
 
-	CHECK(z != NULL);
+	mp_size		uz = MP_USED(z);
 
-	uz = MP_USED(z);
 	if (uz == 1 && z->digits[0] == 0)
 		return 1;
 
 	--uz;
-	nbits = uz * MP_DIGIT_BIT;
-	d = z->digits[uz];
+	mp_size		nbits = uz * MP_DIGIT_BIT;
+	mp_digit	d = z->digits[uz];
 
 	while (d != 0)
 	{
@@ -2092,21 +2014,15 @@ mp_int_count_bits(mp_int z)
 	return nbits;
 }
 
-/* }}} */
-
-/* {{{ mp_int_to_binary(z, buf, limit) */
-
 mp_result
 mp_int_to_binary(mp_int z, unsigned char *buf, int limit)
 {
 	static const int PAD_FOR_2C = 1;
 
-	mp_result	res;
-	int			limpos = limit;
+	assert(z != NULL && buf != NULL);
 
-	CHECK(z != NULL && buf != NULL);
-
-	res = s_tobin(z, buf, &limpos, PAD_FOR_2C);
+	int			limpos = limit;
+	mp_result	res = s_tobin(z, buf, &limpos, PAD_FOR_2C);
 
 	if (MP_SIGN(z) == MP_NEG)
 		s_2comp(buf, limpos);
@@ -2114,22 +2030,14 @@ mp_int_to_binary(mp_int z, unsigned char *buf, int limit)
 	return res;
 }
 
-/* }}} */
-
-/* {{{ mp_int_read_binary(z, buf, len) */
-
 mp_result
 mp_int_read_binary(mp_int z, unsigned char *buf, int len)
 {
-	mp_size		need,
-				i;
-	unsigned char *tmp;
-	mp_digit   *dz;
-
-	CHECK(z != NULL && buf != NULL && len > 0);
+	assert(z != NULL && buf != NULL && len > 0);
 
 	/* Figure out how many digits are needed to represent this value */
-	need = ((len * CHAR_BIT) + (MP_DIGIT_BIT - 1)) / MP_DIGIT_BIT;
+	mp_size		need = ((len * CHAR_BIT) + (MP_DIGIT_BIT - 1)) / MP_DIGIT_BIT;
+
 	if (!s_pad(z, need))
 		return MP_MEMORY;
 
@@ -2141,12 +2049,14 @@ mp_int_read_binary(mp_int z, unsigned char *buf, int len)
 	 */
 	if (buf[0] >> (CHAR_BIT - 1))
 	{
-		MP_SIGN(z) = MP_NEG;
+		z->sign = MP_NEG;
 		s_2comp(buf, len);
 	}
 
-	dz = MP_DIGITS(z);
-	for (tmp = buf, i = len; i > 0; --i, ++tmp)
+	mp_digit   *dz = MP_DIGITS(z);
+	unsigned char *tmp = buf;
+
+	for (int i = len; i > 0; --i, ++tmp)
 	{
 		s_qmul(z, (mp_size) CHAR_BIT);
 		*dz |= *tmp;
@@ -2159,20 +2069,15 @@ mp_int_read_binary(mp_int z, unsigned char *buf, int len)
 	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_binary_len(z) */
-
 mp_result
 mp_int_binary_len(mp_int z)
 {
 	mp_result	res = mp_int_count_bits(z);
-	int			bytes = mp_int_unsigned_len(z);
 
 	if (res <= 0)
 		return res;
 
-	bytes = (res + (CHAR_BIT - 1)) / CHAR_BIT;
+	int			bytes = mp_int_unsigned_len(z);
 
 	/*
 	 * If the highest-order bit falls exactly on a byte boundary, we need to
@@ -2185,193 +2090,170 @@ mp_int_binary_len(mp_int z)
 	return bytes;
 }
 
-/* }}} */
-
-/* {{{ mp_int_to_unsigned(z, buf, limit) */
-
 mp_result
 mp_int_to_unsigned(mp_int z, unsigned char *buf, int limit)
 {
 	static const int NO_PADDING = 0;
 
-	CHECK(z != NULL && buf != NULL);
+	assert(z != NULL && buf != NULL);
 
 	return s_tobin(z, buf, &limit, NO_PADDING);
 }
 
-/* }}} */
-
-/* {{{ mp_int_read_unsigned(z, buf, len) */
-
 mp_result
 mp_int_read_unsigned(mp_int z, unsigned char *buf, int len)
 {
-	mp_size		need,
-				i;
-	unsigned char *tmp;
-	mp_digit   *dz;
-
-	CHECK(z != NULL && buf != NULL && len > 0);
+	assert(z != NULL && buf != NULL && len > 0);
 
 	/* Figure out how many digits are needed to represent this value */
-	need = ((len * CHAR_BIT) + (MP_DIGIT_BIT - 1)) / MP_DIGIT_BIT;
+	mp_size		need = ((len * CHAR_BIT) + (MP_DIGIT_BIT - 1)) / MP_DIGIT_BIT;
+
 	if (!s_pad(z, need))
 		return MP_MEMORY;
 
 	mp_int_zero(z);
 
-	dz = MP_DIGITS(z);
-	for (tmp = buf, i = len; i > 0; --i, ++tmp)
+	unsigned char *tmp = buf;
+
+	for (int i = len; i > 0; --i, ++tmp)
 	{
 		(void) s_qmul(z, CHAR_BIT);
-		*dz |= *tmp;
+		*MP_DIGITS(z) |= *tmp;
 	}
 
 	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ mp_int_unsigned_len(z) */
-
 mp_result
 mp_int_unsigned_len(mp_int z)
 {
 	mp_result	res = mp_int_count_bits(z);
-	int			bytes;
 
 	if (res <= 0)
 		return res;
 
-	bytes = (res + (CHAR_BIT - 1)) / CHAR_BIT;
+	int			bytes = (res + (CHAR_BIT - 1)) / CHAR_BIT;
 
 	return bytes;
 }
 
-/* }}} */
-
-/* {{{ mp_error_string(res) */
-
 const char *
 mp_error_string(mp_result res)
 {
-	int			ix;
-
 	if (res > 0)
 		return s_unknown_err;
 
 	res = -res;
+	int			ix;
+
 	for (ix = 0; ix < res && s_error_msg[ix] != NULL; ++ix)
 		;
 
 	if (s_error_msg[ix] != NULL)
+	{
 		return s_error_msg[ix];
+	}
 	else
+	{
 		return s_unknown_err;
+	}
 }
 
-/* }}} */
-
 /*------------------------------------------------------------------------*/
 /* Private functions for internal use.  These make assumptions.           */
 
-/* {{{ s_alloc(num) */
+#if DEBUG
+static const mp_digit fill = (mp_digit) 0xdeadbeefabad1dea;
+#endif
 
 static mp_digit *
 s_alloc(mp_size num)
 {
-	mp_digit   *out = px_alloc(num * sizeof(mp_digit));
+	mp_digit   *out = malloc(num * sizeof(mp_digit));
 
-	assert(out != NULL);		/* for debugging */
+	assert(out != NULL);
 
+#if DEBUG
+	for (mp_size ix = 0; ix < num; ++ix)
+		out[ix] = fill;
+#endif
 	return out;
 }
 
-/* }}} */
-
-/* {{{ s_realloc(old, num) */
-
 static mp_digit *
-s_realloc(mp_digit *old, mp_size num)
+s_realloc(mp_digit *old, mp_size osize, mp_size nsize)
 {
-	mp_digit   *new = px_realloc(old, num * sizeof(mp_digit));
+#if DEBUG
+	mp_digit   *new = s_alloc(nsize);
 
-	assert(new != NULL);		/* for debugging */
+	assert(new != NULL);
 
-	return new;
-}
+	for (mp_size ix = 0; ix < nsize; ++ix)
+		new[ix] = fill;
+	memcpy(new, old, osize * sizeof(mp_digit));
+#else
+	mp_digit   *new = realloc(old, nsize * sizeof(mp_digit));
 
-/* }}} */
+	assert(new != NULL);
+#endif
 
-/* {{{ s_free(ptr) */
+	return new;
+}
 
-#if TRACEABLE_FREE
 static void
 s_free(void *ptr)
 {
-	px_free(ptr);
+	free(ptr);
 }
-#endif
-
-/* }}} */
 
-/* {{{ s_pad(z, min) */
-
-static int
+static bool
 s_pad(mp_int z, mp_size min)
 {
 	if (MP_ALLOC(z) < min)
 	{
-		mp_size		nsize = ROUND_PREC(min);
-		mp_digit   *tmp = s_realloc(MP_DIGITS(z), nsize);
+		mp_size		nsize = s_round_prec(min);
+		mp_digit   *tmp;
 
-		if (tmp == NULL)
-			return 0;
+		if (z->digits == &(z->single))
+		{
+			if ((tmp = s_alloc(nsize)) == NULL)
+				return false;
+			tmp[0] = z->single;
+		}
+		else if ((tmp = s_realloc(MP_DIGITS(z), MP_ALLOC(z), nsize)) == NULL)
+		{
+			return false;
+		}
 
-		MP_DIGITS(z) = tmp;
-		MP_ALLOC(z) = nsize;
+		z->digits = tmp;
+		z->alloc = nsize;
 	}
 
-	return 1;
+	return true;
 }
 
-/* }}} */
-
-/* {{{ s_clamp(z) */
-
-#if TRACEABLE_CLAMP
+/* Note: This will not work correctly when value == MP_SMALL_MIN */
 static void
-s_clamp(mp_int z)
+s_fake(mp_int z, mp_small value, mp_digit vbuf[])
 {
-	mp_size		uz = MP_USED(z);
-	mp_digit   *zd = MP_DIGITS(z) + uz - 1;
-
-	while (uz > 1 && (*zd-- == 0))
-		--uz;
+	mp_usmall	uv = (mp_usmall) (value < 0) ? -value : value;
 
-	MP_USED(z) = uz;
+	s_ufake(z, uv, vbuf);
+	if (value < 0)
+		z->sign = MP_NEG;
 }
-#endif
-
-/* }}} */
-
-/* {{{ s_fake(z, value, vbuf) */
 
 static void
-s_fake(mp_int z, int value, mp_digit vbuf[])
+s_ufake(mp_int z, mp_usmall value, mp_digit vbuf[])
 {
-	mp_size		uv = (mp_size) s_vpack(value, vbuf);
+	mp_size		ndig = (mp_size) s_uvpack(value, vbuf);
 
-	z->used = uv;
+	z->used = ndig;
 	z->alloc = MP_VALUE_DIGITS(value);
-	z->sign = (value < 0) ? MP_NEG : MP_ZPOS;
+	z->sign = MP_ZPOS;
 	z->digits = vbuf;
 }
 
-/* }}} */
-
-/* {{{ s_cdig(da, db, len) */
-
 static int
 s_cdig(mp_digit *da, mp_digit *db, mp_size len)
 {
@@ -2381,22 +2263,21 @@ s_cdig(mp_digit *da, mp_digit *db, mp_size len)
 	for ( /* */ ; len != 0; --len, --dat, --dbt)
 	{
 		if (*dat > *dbt)
+		{
 			return 1;
+		}
 		else if (*dat < *dbt)
+		{
 			return -1;
+		}
 	}
 
 	return 0;
 }
 
-/* }}} */
-
-/* {{{ s_vpack(v, t[]) */
-
 static int
-s_vpack(int v, mp_digit t[])
+s_uvpack(mp_usmall uv, mp_digit t[])
 {
-	unsigned int uv = (unsigned int) ((v < 0) ? -v : v);
 	int			ndig = 0;
 
 	if (uv == 0)
@@ -2414,10 +2295,6 @@ s_vpack(int v, mp_digit t[])
 	return ndig;
 }
 
-/* }}} */
-
-/* {{{ s_ucmp(a, b) */
-
 static int
 s_ucmp(mp_int a, mp_int b)
 {
@@ -2425,41 +2302,40 @@ s_ucmp(mp_int a, mp_int b)
 				ub = MP_USED(b);
 
 	if (ua > ub)
+	{
 		return 1;
+	}
 	else if (ub > ua)
+	{
 		return -1;
+	}
 	else
+	{
 		return s_cdig(MP_DIGITS(a), MP_DIGITS(b), ua);
+	}
 }
 
-/* }}} */
-
-/* {{{ s_vcmp(a, v) */
-
 static int
-s_vcmp(mp_int a, int v)
+s_vcmp(mp_int a, mp_small v)
 {
-	mp_digit	vdig[MP_VALUE_DIGITS(v)];
-	int			ndig = 0;
-	mp_size		ua = MP_USED(a);
+	mp_usmall	uv = (v < 0) ? -(mp_usmall) v : (mp_usmall) v;
 
-	ndig = s_vpack(v, vdig);
-
-	if (ua > ndig)
-		return 1;
-	else if (ua < ndig)
-		return -1;
-	else
-		return s_cdig(MP_DIGITS(a), vdig, ndig);
+	return s_uvcmp(a, uv);
 }
 
-/* }}} */
+static int
+s_uvcmp(mp_int a, mp_usmall uv)
+{
+	mpz_t		vtmp;
+	mp_digit	vdig[MP_VALUE_DIGITS(uv)];
 
-/* {{{ s_uadd(da, db, dc, size_a, size_b) */
+	s_ufake(&vtmp, uv, vdig);
+	return s_ucmp(a, &vtmp);
+}
 
 static mp_digit
-s_uadd(mp_digit *da, mp_digit *db, mp_digit *dc,
-	   mp_size size_a, mp_size size_b)
+s_uadd(mp_digit *da, mp_digit *db, mp_digit *dc, mp_size size_a,
+	   mp_size size_b)
 {
 	mp_size		pos;
 	mp_word		w = 0;
@@ -2492,13 +2368,9 @@ s_uadd(mp_digit *da, mp_digit *db, mp_digit *dc,
 	return (mp_digit) w;
 }
 
-/* }}} */
-
-/* {{{ s_usub(da, db, dc, size_a, size_b) */
-
 static void
-s_usub(mp_digit *da, mp_digit *db, mp_digit *dc,
-	   mp_size size_a, mp_size size_b)
+s_usub(mp_digit *da, mp_digit *db, mp_digit *dc, mp_size size_a,
+	   mp_size size_b)
 {
 	mp_size		pos;
 	mp_word		w = 0;
@@ -2510,7 +2382,8 @@ s_usub(mp_digit *da, mp_digit *db, mp_digit *dc,
 	for (pos = 0; pos < size_b; ++pos, ++da, ++db, ++dc)
 	{
 		w = ((mp_word) MP_DIGIT_MAX + 1 +	/* MP_RADIX */
-			 (mp_word) *da) - w - (mp_word) *db;
+			 (mp_word) *da) -
+			w - (mp_word) *db;
 
 		*dc = LOWER_HALF(w);
 		w = (UPPER_HALF(w) == 0);
@@ -2520,7 +2393,8 @@ s_usub(mp_digit *da, mp_digit *db, mp_digit *dc,
 	for ( /* */ ; pos < size_a; ++pos, ++da, ++dc)
 	{
 		w = ((mp_word) MP_DIGIT_MAX + 1 +	/* MP_RADIX */
-			 (mp_word) *da) - w;
+			 (mp_word) *da) -
+			w;
 
 		*dc = LOWER_HALF(w);
 		w = (UPPER_HALF(w) == 0);
@@ -2530,13 +2404,9 @@ s_usub(mp_digit *da, mp_digit *db, mp_digit *dc,
 	assert(w == 0);
 }
 
-/* }}} */
-
-/* {{{ s_kmul(da, db, dc, size_a, size_b) */
-
 static int
-s_kmul(mp_digit *da, mp_digit *db, mp_digit *dc,
-	   mp_size size_a, mp_size size_b)
+s_kmul(mp_digit *da, mp_digit *db, mp_digit *dc, mp_size size_a,
+	   mp_size size_b)
 {
 	mp_size		bot_size;
 
@@ -2558,11 +2428,8 @@ s_kmul(mp_digit *da, mp_digit *db, mp_digit *dc,
 	 * Karatsuba algorithm to compute the product; otherwise use the normal
 	 * multiplication algorithm
 	 */
-	if (multiply_threshold &&
-		size_a >= multiply_threshold &&
-		size_b > bot_size)
+	if (multiply_threshold && size_a >= multiply_threshold && size_b > bot_size)
 	{
-
 		mp_digit   *t1,
 				   *t2,
 				   *t3,
@@ -2614,12 +2481,11 @@ s_kmul(mp_digit *da, mp_digit *db, mp_digit *dc,
 
 		/* Assemble the output value */
 		COPY(t1, dc, buf_size);
-		carry = s_uadd(t3, dc + bot_size, dc + bot_size,
-					   buf_size + 1, buf_size);
+		carry = s_uadd(t3, dc + bot_size, dc + bot_size, buf_size + 1, buf_size);
 		assert(carry == 0);
 
-		carry = s_uadd(t2, dc + 2 * bot_size, dc + 2 * bot_size,
-					   buf_size, buf_size);
+		carry =
+			s_uadd(t2, dc + 2 * bot_size, dc + 2 * bot_size, buf_size, buf_size);
 		assert(carry == 0);
 
 		s_free(t1);				/* note t2 and t3 are just internal pointers
@@ -2633,13 +2499,9 @@ s_kmul(mp_digit *da, mp_digit *db, mp_digit *dc,
 	return 1;
 }
 
-/* }}} */
-
-/* {{{ s_umul(da, db, dc, size_a, size_b) */
-
 static void
-s_umul(mp_digit *da, mp_digit *db, mp_digit *dc,
-	   mp_size size_a, mp_size size_b)
+s_umul(mp_digit *da, mp_digit *db, mp_digit *dc, mp_size size_a,
+	   mp_size size_b)
 {
 	mp_size		a,
 				b;
@@ -2666,10 +2528,6 @@ s_umul(mp_digit *da, mp_digit *db, mp_digit *dc,
 	}
 }
 
-/* }}} */
-
-/* {{{ s_ksqr(da, dc, size_a) */
-
 static int
 s_ksqr(mp_digit *da, mp_digit *dc, mp_size size_a)
 {
@@ -2679,7 +2537,8 @@ s_ksqr(mp_digit *da, mp_digit *dc, mp_size size_a)
 		mp_digit   *a_top = da + bot_size;
 		mp_digit   *t1,
 				   *t2,
-				   *t3;
+				   *t3,
+					carry;
 		mp_size		at_size = size_a - bot_size;
 		mp_size		buf_size = 2 * bot_size;
 
@@ -2713,13 +2572,14 @@ s_ksqr(mp_digit *da, mp_digit *dc, mp_size size_a)
 
 		/* Assemble the output value */
 		COPY(t1, dc, 2 * bot_size);
-		(void) s_uadd(t3, dc + bot_size, dc + bot_size,
-					  buf_size + 1, buf_size + 1);
+		carry = s_uadd(t3, dc + bot_size, dc + bot_size, buf_size + 1, buf_size);
+		assert(carry == 0);
 
-		(void) s_uadd(t2, dc + 2 * bot_size, dc + 2 * bot_size,
-					  buf_size, buf_size);
+		carry =
+			s_uadd(t2, dc + 2 * bot_size, dc + 2 * bot_size, buf_size, buf_size);
+		assert(carry == 0);
 
-		px_free(t1);			/* note that t2 and t2 are internal pointers
+		s_free(t1);				/* note that t2 and t2 are internal pointers
 								 * only */
 
 	}
@@ -2731,10 +2591,6 @@ s_ksqr(mp_digit *da, mp_digit *dc, mp_size size_a)
 	return 1;
 }
 
-/* }}} */
-
-/* {{{ s_usqr(da, dc, size_a) */
-
 static void
 s_usqr(mp_digit *da, mp_digit *dc, mp_size size_a)
 {
@@ -2797,10 +2653,6 @@ s_usqr(mp_digit *da, mp_digit *dc, mp_size size_a)
 	}
 }
 
-/* }}} */
-
-/* {{{ s_dadd(a, b) */
-
 static void
 s_dadd(mp_int a, mp_digit b)
 {
@@ -2823,14 +2675,10 @@ s_dadd(mp_int a, mp_digit b)
 	if (w)
 	{
 		*da = (mp_digit) w;
-		MP_USED(a) += 1;
+		a->used += 1;
 	}
 }
 
-/* }}} */
-
-/* {{{ s_dmul(a, b) */
-
 static void
 s_dmul(mp_int a, mp_digit b)
 {
@@ -2849,14 +2697,10 @@ s_dmul(mp_int a, mp_digit b)
 	if (w)
 	{
 		*da = (mp_digit) w;
-		MP_USED(a) += 1;
+		a->used += 1;
 	}
 }
 
-/* }}} */
-
-/* {{{ s_dbmul(da, b, dc, size_a) */
-
 static void
 s_dbmul(mp_digit *da, mp_digit b, mp_digit *dc, mp_size size_a)
 {
@@ -2875,10 +2719,6 @@ s_dbmul(mp_digit *da, mp_digit b, mp_digit *dc, mp_size size_a)
 		*dc = LOWER_HALF(w);
 }
 
-/* }}} */
-
-/* {{{ s_ddiv(da, d, dc, size_a) */
-
 static mp_digit
 s_ddiv(mp_int a, mp_digit b)
 {
@@ -2908,10 +2748,6 @@ s_ddiv(mp_int a, mp_digit b)
 	return (mp_digit) w;
 }
 
-/* }}} */
-
-/* {{{ s_qdiv(z, p2) */
-
 static void
 s_qdiv(mp_int z, mp_size p2)
 {
@@ -2935,9 +2771,11 @@ s_qdiv(mp_int z, mp_size p2)
 		from = to + ndig;
 
 		for (mark = ndig; mark < uz; ++mark)
+		{
 			*to++ = *from++;
+		}
 
-		MP_USED(z) = uz - ndig;
+		z->used = uz - ndig;
 	}
 
 	if (nbits)
@@ -2962,33 +2800,25 @@ s_qdiv(mp_int z, mp_size p2)
 	}
 
 	if (MP_USED(z) == 1 && z->digits[0] == 0)
-		MP_SIGN(z) = MP_ZPOS;
+		z->sign = MP_ZPOS;
 }
 
-/* }}} */
-
-/* {{{ s_qmod(z, p2) */
-
 static void
 s_qmod(mp_int z, mp_size p2)
 {
 	mp_size		start = p2 / MP_DIGIT_BIT + 1,
 				rest = p2 % MP_DIGIT_BIT;
 	mp_size		uz = MP_USED(z);
-	mp_digit	mask = (1 << rest) - 1;
+	mp_digit	mask = (1u << rest) - 1;
 
 	if (start <= uz)
 	{
-		MP_USED(z) = start;
+		z->used = start;
 		z->digits[start - 1] &= mask;
 		CLAMP(z);
 	}
 }
 
-/* }}} */
-
-/* {{{ s_qmul(z, p2) */
-
 static int
 s_qmul(mp_int z, mp_size p2)
 {
@@ -3060,21 +2890,19 @@ s_qmul(mp_int z, mp_size p2)
 		}
 	}
 
-	MP_USED(z) = uz;
+	z->used = uz;
 	CLAMP(z);
 
 	return 1;
 }
 
-/* }}} */
-
-/* {{{ s_qsub(z, p2) */
-
-/* Subtract |z| from 2^p2, assuming 2^p2 > |z|, and set z to be positive */
+/* Compute z = 2^p2 - |z|; requires that 2^p2 >= |z|
+   The sign of the result is always zero/positive.
+ */
 static int
 s_qsub(mp_int z, mp_size p2)
 {
-	mp_digit	hi = (1 << (p2 % MP_DIGIT_BIT)),
+	mp_digit	hi = (1u << (p2 % MP_DIGIT_BIT)),
 			   *zp;
 	mp_size		tdig = (p2 / MP_DIGIT_BIT),
 				pos;
@@ -3096,16 +2924,12 @@ s_qsub(mp_int z, mp_size p2)
 
 	assert(UPPER_HALF(w) != 0); /* no borrow out should be possible */
 
-	MP_SIGN(z) = MP_ZPOS;
+	z->sign = MP_ZPOS;
 	CLAMP(z);
 
 	return 1;
 }
 
-/* }}} */
-
-/* {{{ s_dp2k(z) */
-
 static int
 s_dp2k(mp_int z)
 {
@@ -3132,10 +2956,6 @@ s_dp2k(mp_int z)
 	return k;
 }
 
-/* }}} */
-
-/* {{{ s_isp2(z) */
-
 static int
 s_isp2(mp_int z)
 {
@@ -3164,12 +2984,8 @@ s_isp2(mp_int z)
 	return (int) k;
 }
 
-/* }}} */
-
-/* {{{ s_2expt(z, k) */
-
 static int
-s_2expt(mp_int z, int k)
+s_2expt(mp_int z, mp_small k)
 {
 	mp_size		ndig,
 				rest;
@@ -3183,23 +2999,19 @@ s_2expt(mp_int z, int k)
 
 	dz = MP_DIGITS(z);
 	ZERO(dz, ndig);
-	*(dz + ndig - 1) = (1 << rest);
-	MP_USED(z) = ndig;
+	*(dz + ndig - 1) = (1u << rest);
+	z->used = ndig;
 
 	return 1;
 }
 
-/* }}} */
-
-/* {{{ s_norm(a, b) */
-
 static int
 s_norm(mp_int a, mp_int b)
 {
 	mp_digit	d = b->digits[MP_USED(b) - 1];
 	int			k = 0;
 
-	while (d < (mp_digit) ((mp_digit) 1 << (MP_DIGIT_BIT - 1)))
+	while (d < (1u << (mp_digit) (MP_DIGIT_BIT - 1)))
 	{							/* d < (MP_RADIX / 2) */
 		d <<= 1;
 		++k;
@@ -3215,10 +3027,6 @@ s_norm(mp_int a, mp_int b)
 	return k;
 }
 
-/* }}} */
-
-/* {{{ s_brmu(z, m) */
-
 static mp_result
 s_brmu(mp_int z, mp_int m)
 {
@@ -3231,10 +3039,6 @@ s_brmu(mp_int z, mp_int m)
 	return mp_int_div(z, m, z, NULL);
 }
 
-/* }}} */
-
-/* {{{ s_reduce(x, m, mu, q1, q2) */
-
 static int
 s_reduce(mp_int x, mp_int m, mp_int mu, mp_int q1, mp_int q2)
 {
@@ -3273,53 +3077,47 @@ s_reduce(mp_int x, mp_int m, mp_int mu, mp_int q1, mp_int q2)
 		return 0;
 
 	/*
-	 * If x > m, we need to back it off until it is in range. This will be
+	 * If x > m, we need to back it off until it is in range.  This will be
 	 * required at most twice.
 	 */
 	if (mp_int_compare(x, m) >= 0)
+	{
 		(void) mp_int_sub(x, m, x);
-	if (mp_int_compare(x, m) >= 0)
-		(void) mp_int_sub(x, m, x);
+		if (mp_int_compare(x, m) >= 0)
+		{
+			(void) mp_int_sub(x, m, x);
+		}
+	}
 
 	/* At this point, x has been properly reduced. */
 	return 1;
 }
 
-/* }}} */
-
-/* {{{ s_embar(a, b, m, mu, c) */
-
-/* Perform modular exponentiation using Barrett's method, where mu is
-   the reduction constant for m.  Assumes a < m, b > 0. */
+/* Perform modular exponentiation using Barrett's method, where mu is the
+   reduction constant for m.  Assumes a < m, b > 0. */
 static mp_result
 s_embar(mp_int a, mp_int b, mp_int m, mp_int mu, mp_int c)
 {
-	mp_digit   *db,
-			   *dbt,
-				umu,
-				d;
-	mpz_t		temp[3];
-	mp_result	res;
-	int			last = 0;
+	mp_digit	umu = MP_USED(mu);
+	mp_digit   *db = MP_DIGITS(b);
+	mp_digit   *dbt = db + MP_USED(b) - 1;
 
-	umu = MP_USED(mu);
-	db = MP_DIGITS(b);
-	dbt = db + MP_USED(b) - 1;
-
-	while (last < 3)
-	{
-		SETUP(mp_int_init_size(TEMP(last), 4 * umu), last);
-		ZERO(MP_DIGITS(TEMP(last - 1)), MP_ALLOC(TEMP(last - 1)));
-	}
+	DECLARE_TEMP(3);
+	REQUIRE(GROW(TEMP(0), 4 * umu));
+	REQUIRE(GROW(TEMP(1), 4 * umu));
+	REQUIRE(GROW(TEMP(2), 4 * umu));
+	ZERO(TEMP(0)->digits, TEMP(0)->alloc);
+	ZERO(TEMP(1)->digits, TEMP(1)->alloc);
+	ZERO(TEMP(2)->digits, TEMP(2)->alloc);
 
 	(void) mp_int_set_value(c, 1);
 
 	/* Take care of low-order digits */
 	while (db < dbt)
 	{
-		int			i;
+		mp_digit	d = *db;
 
-		for (d = *db, i = MP_DIGIT_BIT; i > 0; --i, d >>= 1)
+		for (int i = MP_DIGIT_BIT; i > 0; --i, d >>= 1)
 		{
 			if (d & 1)
 			{
@@ -3327,31 +3125,27 @@ s_embar(mp_int a, mp_int b, mp_int m, mp_int mu, mp_int c)
 				UMUL(c, a, TEMP(0));
 				if (!s_reduce(TEMP(0), m, mu, TEMP(1), TEMP(2)))
 				{
-					res = MP_MEMORY;
-					goto CLEANUP;
+					REQUIRE(MP_MEMORY);
 				}
 				mp_int_copy(TEMP(0), c);
 			}
 
-
 			USQR(a, TEMP(0));
 			assert(MP_SIGN(TEMP(0)) == MP_ZPOS);
 			if (!s_reduce(TEMP(0), m, mu, TEMP(1), TEMP(2)))
 			{
-				res = MP_MEMORY;
-				goto CLEANUP;
+				REQUIRE(MP_MEMORY);
 			}
 			assert(MP_SIGN(TEMP(0)) == MP_ZPOS);
 			mp_int_copy(TEMP(0), a);
-
-
 		}
 
 		++db;
 	}
 
 	/* Take care of highest-order digit */
-	d = *dbt;
+	mp_digit	d = *dbt;
+
 	for (;;)
 	{
 		if (d & 1)
@@ -3359,8 +3153,7 @@ s_embar(mp_int a, mp_int b, mp_int m, mp_int mu, mp_int c)
 			UMUL(c, a, TEMP(0));
 			if (!s_reduce(TEMP(0), m, mu, TEMP(1), TEMP(2)))
 			{
-				res = MP_MEMORY;
-				goto CLEANUP;
+				REQUIRE(MP_MEMORY);
 			}
 			mp_int_copy(TEMP(0), c);
 		}
@@ -3372,170 +3165,272 @@ s_embar(mp_int a, mp_int b, mp_int m, mp_int mu, mp_int c)
 		USQR(a, TEMP(0));
 		if (!s_reduce(TEMP(0), m, mu, TEMP(1), TEMP(2)))
 		{
-			res = MP_MEMORY;
-			goto CLEANUP;
+			REQUIRE(MP_MEMORY);
 		}
 		(void) mp_int_copy(TEMP(0), a);
 	}
 
-CLEANUP:
-	while (--last >= 0)
-		mp_int_clear(TEMP(last));
-
-	return res;
+	CLEANUP_TEMP();
+	return MP_OK;
 }
 
-/* }}} */
+/* Division of nonnegative integers
+
+   This function implements division algorithm for unsigned multi-precision
+   integers. The algorithm is based on Algorithm D from Knuth's "The Art of
+   Computer Programming", 3rd ed. 1998, pg 272-273.
 
-/* {{{ s_udiv(a, b) */
+   We diverge from Knuth's algorithm in that we do not perform the subtraction
+   from the remainder until we have determined that we have the correct
+   quotient digit. This makes our algorithm less efficient that Knuth because
+   we might have to perform multiple multiplication and comparison steps before
+   the subtraction. The advantage is that it is easy to implement and ensure
+   correctness without worrying about underflow from the subtraction.
 
-/* Precondition:  a >= b and b > 0
-   Postcondition: a' = a / b, b' = a % b
+   inputs: u   a n+m digit integer in base b (b is 2^MP_DIGIT_BIT)
+		   v   a n   digit integer in base b (b is 2^MP_DIGIT_BIT)
+		   n >= 1
+		   m >= 0
+  outputs: u / v stored in u
+		   u % v stored in v
  */
 static mp_result
-s_udiv(mp_int a, mp_int b)
-{
-	mpz_t		q,
-				r,
-				t;
-	mp_size		ua,
-				ub,
-				qpos = 0;
-	mp_digit   *da,
-				btop;
-	mp_result	res = MP_OK;
-	int			k,
-				skip = 0;
-
+s_udiv_knuth(mp_int u, mp_int v)
+{
 	/* Force signs to positive */
-	MP_SIGN(a) = MP_ZPOS;
-	MP_SIGN(b) = MP_ZPOS;
+	u->sign = MP_ZPOS;
+	v->sign = MP_ZPOS;
+
+	/* Use simple division algorithm when v is only one digit long */
+	if (MP_USED(v) == 1)
+	{
+		mp_digit	d,
+					rem;
 
-	/* Normalize, per Knuth */
-	k = s_norm(a, b);
+		d = v->digits[0];
+		rem = s_ddiv(u, d);
+		mp_int_set_value(v, rem);
+		return MP_OK;
+	}
 
-	ua = MP_USED(a);
-	ub = MP_USED(b);
-	btop = b->digits[ub - 1];
-	if ((res = mp_int_init_size(&q, ua)) != MP_OK)
-		return res;
-	if ((res = mp_int_init_size(&t, ua + 1)) != MP_OK)
-		goto CLEANUP;
+	/*
+	 * Algorithm D
+	 *
+	 * The n and m variables are defined as used by Knuth. u is an n digit
+	 * number with digits u_{n-1}..u_0. v is an n+m digit number with digits
+	 * from v_{m+n-1}..v_0. We require that n > 1 and m >= 0
+	 */
+	mp_size		n = MP_USED(v);
+	mp_size		m = MP_USED(u) - n;
+
+	assert(n > 1);
+	/* assert(m >= 0) follows because m is unsigned. */
+
+	/*
+	 * D1: Normalize. The normalization step provides the necessary condition
+	 * for Theorem B, which states that the quotient estimate for q_j, call it
+	 * qhat
+	 *
+	 * qhat = u_{j+n}u_{j+n-1} / v_{n-1}
+	 *
+	 * is bounded by
+	 *
+	 * qhat - 2 <= q_j <= qhat.
+	 *
+	 * That is, qhat is always greater than the actual quotient digit q, and
+	 * it is never more than two larger than the actual quotient digit.
+	 */
+	int			k = s_norm(u, v);
+
+	/*
+	 * Extend size of u by one if needed.
+	 *
+	 * The algorithm begins with a value of u that has one more digit of
+	 * input. The normalization step sets u_{m+n}..u_0 = 2^k * u_{m+n-1}..u_0.
+	 * If the multiplication did not increase the number of digits of u, we
+	 * need to add a leading zero here.
+	 */
+	if (k == 0 || MP_USED(u) != m + n + 1)
+	{
+		if (!s_pad(u, m + n + 1))
+			return MP_MEMORY;
+		u->digits[m + n] = 0;
+		u->used = m + n + 1;
+	}
 
-	da = MP_DIGITS(a);
-	r.digits = da + ua - 1;		/* The contents of r are shared with a */
-	r.used = 1;
+	/*
+	 * Add a leading 0 to v.
+	 *
+	 * The multiplication in step D4 multiplies qhat * 0v_{n-1}..v_0.  We need
+	 * to add the leading zero to v here to ensure that the multiplication
+	 * will produce the full n+1 digit result.
+	 */
+	if (!s_pad(v, n + 1))
+		return MP_MEMORY;
+	v->digits[n] = 0;
+
+	/*
+	 * Initialize temporary variables q and t. q allocates space for m+1
+	 * digits to store the quotient digits t allocates space for n+1 digits to
+	 * hold the result of q_j*v
+	 */
+	DECLARE_TEMP(2);
+	REQUIRE(GROW(TEMP(0), m + 1));
+	REQUIRE(GROW(TEMP(1), n + 1));
+
+	/* D2: Initialize j */
+	int			j = m;
+	mpz_t		r;
+
+	r.digits = MP_DIGITS(u) + j;	/* The contents of r are shared with u */
+	r.used = n + 1;
 	r.sign = MP_ZPOS;
-	r.alloc = MP_ALLOC(a);
-	ZERO(t.digits, t.alloc);
+	r.alloc = MP_ALLOC(u);
+	ZERO(TEMP(1)->digits, TEMP(1)->alloc);
 
-	/* Solve for quotient digits, store in q.digits in reverse order */
-	while (r.digits >= da)
+	/* Calculate the m+1 digits of the quotient result */
+	for (; j >= 0; j--)
 	{
-		assert(qpos <= q.alloc);
+		/* D3: Calculate q' */
+		/* r->digits is aligned to position j of the number u */
+		mp_word		pfx,
+					qhat;
 
-		if (s_ucmp(b, &r) > 0)
-		{
-			r.digits -= 1;
-			r.used += 1;
+		pfx = r.digits[n];
+		pfx <<= MP_DIGIT_BIT / 2;
+		pfx <<= MP_DIGIT_BIT / 2;
+		pfx |= r.digits[n - 1]; /* pfx = u_{j+n}{j+n-1} */
 
-			if (++skip > 1)
-				q.digits[qpos++] = 0;
+		qhat = pfx / v->digits[n - 1];
 
-			CLAMP(&r);
-		}
-		else
-		{
-			mp_word		pfx = r.digits[r.used - 1];
-			mp_word		qdigit;
+		/*
+		 * Check to see if qhat > b, and decrease qhat if so. Theorem B
+		 * guarantess that qhat is at most 2 larger than the actual value, so
+		 * it is possible that qhat is greater than the maximum value that
+		 * will fit in a digit
+		 */
+		if (qhat > MP_DIGIT_MAX)
+			qhat = MP_DIGIT_MAX;
 
-			if (r.used > 1 && (pfx < btop || r.digits[r.used - 2] == 0))
-			{
-				pfx <<= MP_DIGIT_BIT / 2;
-				pfx <<= MP_DIGIT_BIT / 2;
-				pfx |= r.digits[r.used - 2];
+		/*
+		 * D4,D5,D6: Multiply qhat * v and test for a correct value of q
+		 *
+		 * We proceed a bit different than the way described by Knuth. This
+		 * way is simpler but less efficent. Instead of doing the multiply and
+		 * subtract then checking for underflow, we first do the multiply of
+		 * qhat * v and see if it is larger than the current remainder r. If
+		 * it is larger, we decrease qhat by one and try again. We may need to
+		 * decrease qhat one more time before we get a value that is smaller
+		 * than r.
+		 *
+		 * This way is less efficent than Knuth becuase we do more multiplies,
+		 * but we do not need to worry about underflow this way.
+		 */
+		/* t = qhat * v */
+		s_dbmul(MP_DIGITS(v), (mp_digit) qhat, TEMP(1)->digits, n + 1);
+		TEMP(1)->used = n + 1;
+		CLAMP(TEMP(1));
+
+		/* Clamp r for the comparison. Comparisons do not like leading zeros. */
+		CLAMP(&r);
+		if (s_ucmp(TEMP(1), &r) > 0)
+		{						/* would the remainder be negative? */
+			qhat -= 1;			/* try a smaller q */
+			s_dbmul(MP_DIGITS(v), (mp_digit) qhat, TEMP(1)->digits, n + 1);
+			TEMP(1)->used = n + 1;
+			CLAMP(TEMP(1));
+			if (s_ucmp(TEMP(1), &r) > 0)
+			{					/* would the remainder be negative? */
+				assert(qhat > 0);
+				qhat -= 1;		/* try a smaller q */
+				s_dbmul(MP_DIGITS(v), (mp_digit) qhat, TEMP(1)->digits, n + 1);
+				TEMP(1)->used = n + 1;
+				CLAMP(TEMP(1));
 			}
+			assert(s_ucmp(TEMP(1), &r) <= 0 && "The mathematics failed us.");
+		}
 
-			qdigit = pfx / btop;
-			if (qdigit > MP_DIGIT_MAX)
-				qdigit = 1;
+		/*
+		 * Unclamp r. The D algorithm expects r = u_{j+n}..u_j to always be
+		 * n+1 digits long.
+		 */
+		r.used = n + 1;
 
-			s_dbmul(MP_DIGITS(b), (mp_digit) qdigit, t.digits, ub);
-			t.used = ub + 1;
-			CLAMP(&t);
-			while (s_ucmp(&t, &r) > 0)
-			{
-				--qdigit;
-				(void) mp_int_sub(&t, b, &t);	/* cannot fail */
-			}
+		/*
+		 * D4: Multiply and subtract
+		 *
+		 * Note: The multiply was completed above so we only need to subtract
+		 * here.
+		 */
+		s_usub(r.digits, TEMP(1)->digits, r.digits, r.used, TEMP(1)->used);
 
-			s_usub(r.digits, t.digits, r.digits, r.used, t.used);
-			CLAMP(&r);
+		/*
+		 * D5: Test remainder
+		 *
+		 * Note: Not needed because we always check that qhat is the correct
+		 * value before performing the subtract.  Value cast to mp_digit to
+		 * prevent warning, qhat has been clamped to MP_DIGIT_MAX
+		 */
+		TEMP(0)->digits[j] = (mp_digit) qhat;
 
-			q.digits[qpos++] = (mp_digit) qdigit;
-			ZERO(t.digits, t.used);
-			skip = 0;
-		}
+		/*
+		 * D6: Add back Note: Not needed because we always check that qhat is
+		 * the correct value before performing the subtract.
+		 */
+
+		/* D7: Loop on j */
+		r.digits--;
+		ZERO(TEMP(1)->digits, TEMP(1)->alloc);
 	}
 
-	/* Put quotient digits in the correct order, and discard extra zeroes */
-	q.used = qpos;
-	REV(mp_digit, q.digits, qpos);
-	CLAMP(&q);
+	/* Get rid of leading zeros in q */
+	TEMP(0)->used = m + 1;
+	CLAMP(TEMP(0));
 
 	/* Denormalize the remainder */
-	CLAMP(a);
+	CLAMP(u);					/* use u here because the r.digits pointer is
+								 * off-by-one */
 	if (k != 0)
-		s_qdiv(a, k);
+		s_qdiv(u, k);
 
-	mp_int_copy(a, b);			/* ok:	0 <= r < b */
-	mp_int_copy(&q, a);			/* ok:	q <= a	   */
+	mp_int_copy(u, v);			/* ok:  0 <= r < v */
+	mp_int_copy(TEMP(0), u);	/* ok:  q <= u     */
 
-	mp_int_clear(&t);
-CLEANUP:
-	mp_int_clear(&q);
-	return res;
+	CLEANUP_TEMP();
+	return MP_OK;
 }
 
-/* }}} */
-
-/* {{{ s_outlen(z, r) */
-
-/* Precondition:  2 <= r < 64 */
 static int
 s_outlen(mp_int z, mp_size r)
 {
-	mp_result	bits;
-	double		raw;
+	assert(r >= MP_MIN_RADIX && r <= MP_MAX_RADIX);
 
-	bits = mp_int_count_bits(z);
-	raw = (double) bits * s_log2[r];
+	mp_result	bits = mp_int_count_bits(z);
+	double		raw = (double) bits * s_log2[r];
 
 	return (int) (raw + 0.999999);
 }
 
-/* }}} */
-
-/* {{{ s_inlen(len, r) */
-
 static mp_size
 s_inlen(int len, mp_size r)
 {
 	double		raw = (double) len / s_log2[r];
 	mp_size		bits = (mp_size) (raw + 0.5);
 
-	return (mp_size) ((bits + (MP_DIGIT_BIT - 1)) / MP_DIGIT_BIT);
+	return (mp_size) ((bits + (MP_DIGIT_BIT - 1)) / MP_DIGIT_BIT) + 1;
 }
 
-/* }}} */
-
-/* {{{ s_ch2val(c, r) */
-
 static int
 s_ch2val(char c, int r)
 {
 	int			out;
 
+	/*
+	 * In some locales, isalpha() accepts characters outside the range A-Z,
+	 * producing out<0 or out>=36.  The "out >= r" check will always catch
+	 * out>=36.  Though nothing explicitly catches out<0, our caller reacts
+	 * the same way to every negative return value.
+	 */
 	if (isdigit((unsigned char) c))
 		out = c - '0';
 	else if (r > 10 && isalpha((unsigned char) c))
@@ -3546,39 +3441,36 @@ s_ch2val(char c, int r)
 	return (out >= r) ? -1 : out;
 }
 
-/* }}} */
-
-/* {{{ s_val2ch(v, caps) */
-
 static char
 s_val2ch(int v, int caps)
 {
 	assert(v >= 0);
 
 	if (v < 10)
+	{
 		return v + '0';
+	}
 	else
 	{
 		char		out = (v - 10) + 'a';
 
 		if (caps)
+		{
 			return toupper((unsigned char) out);
+		}
 		else
+		{
 			return out;
+		}
 	}
 }
 
-/* }}} */
-
-/* {{{ s_2comp(buf, len) */
-
 static void
 s_2comp(unsigned char *buf, int len)
 {
-	int			i;
 	unsigned short s = 1;
 
-	for (i = len - 1; i >= 0; --i)
+	for (int i = len - 1; i >= 0; --i)
 	{
 		unsigned char c = ~buf[i];
 
@@ -3592,20 +3484,14 @@ s_2comp(unsigned char *buf, int len)
 	/* last carry out is ignored */
 }
 
-/* }}} */
-
-/* {{{ s_tobin(z, buf, *limpos) */
-
 static mp_result
 s_tobin(mp_int z, unsigned char *buf, int *limpos, int pad)
 {
-	mp_size		uz;
-	mp_digit   *dz;
 	int			pos = 0,
 				limit = *limpos;
+	mp_size		uz = MP_USED(z);
+	mp_digit   *dz = MP_DIGITS(z);
 
-	uz = MP_USED(z);
-	dz = MP_DIGITS(z);
 	while (uz > 0 && pos < limit)
 	{
 		mp_digit	d = *dz++;
@@ -3631,13 +3517,17 @@ s_tobin(mp_int z, unsigned char *buf, int *limpos, int pad)
 	if (pad != 0 && (buf[pos - 1] >> (CHAR_BIT - 1)))
 	{
 		if (pos < limit)
+		{
 			buf[pos++] = 0;
+		}
 		else
+		{
 			uz = 1;
+		}
 	}
 
 	/* Digits are in reverse order, fix that */
-	REV(unsigned char, buf, pos);
+	REV(buf, pos);
 
 	/* Return the number of bytes actually written */
 	*limpos = pos;
@@ -3645,40 +3535,4 @@ s_tobin(mp_int z, unsigned char *buf, int *limpos, int pad)
 	return (uz == 0) ? MP_OK : MP_TRUNC;
 }
 
-/* }}} */
-
-/* {{{ s_print(tag, z) */
-
-#if 0
-void
-s_print(char *tag, mp_int z)
-{
-	int			i;
-
-	fprintf(stderr, "%s: %c ", tag,
-			(MP_SIGN(z) == MP_NEG) ? '-' : '+');
-
-	for (i = MP_USED(z) - 1; i >= 0; --i)
-		fprintf(stderr, "%0*X", (int) (MP_DIGIT_BIT / 4), z->digits[i]);
-
-	fputc('\n', stderr);
-
-}
-
-void
-s_print_buf(char *tag, mp_digit *buf, mp_size num)
-{
-	int			i;
-
-	fprintf(stderr, "%s: ", tag);
-
-	for (i = num - 1; i >= 0; --i)
-		fprintf(stderr, "%0*X", (int) (MP_DIGIT_BIT / 4), buf[i]);
-
-	fputc('\n', stderr);
-}
-#endif
-
-/* }}} */
-
-/* HERE THERE BE DRAGONS */
+/* Here there be dragons */
diff --git a/contrib/pgcrypto/imath.h b/contrib/pgcrypto/imath.h
index 2d7a526..ab9ced1 100644
--- a/contrib/pgcrypto/imath.h
+++ b/contrib/pgcrypto/imath.h
@@ -1,61 +1,59 @@
 /*
-  Name:		imath.h
-  Purpose:	Arbitrary precision integer arithmetic routines.
-  Author:	M. J. Fromberger <http://spinning-yarns.org/michael/sw/>
-  Info:		Id: imath.h 21 2006-04-02 18:58:36Z sting
-
-  Copyright (C) 2002 Michael J. Fromberger, All Rights Reserved.
-
-  Permission is hereby granted, free of charge, to any person
-  obtaining a copy of this software and associated documentation files
-  (the "Software"), to deal in the Software without restriction,
-  including without limitation the rights to use, copy, modify, merge,
-  publish, distribute, sublicense, and/or sell copies of the Software,
-  and to permit persons to whom the Software is furnished to do so,
-  subject to the following conditions:
-
-  The above copyright notice and this permission notice shall be
-  included in all copies or substantial portions of the Software.
-
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-  NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+  Name:     imath.h
+  Purpose:  Arbitrary precision integer arithmetic routines.
+  Author:   M. J. Fromberger
+
+  Copyright (C) 2002-2007 Michael J. Fromberger, All Rights Reserved.
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy
+  of this software and associated documentation files (the "Software"), to deal
+  in the Software without restriction, including without limitation the rights
+  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the Software is
+  furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in
+  all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   SOFTWARE.
  */
-/* contrib/pgcrypto/imath.h */
 
 #ifndef IMATH_H_
 #define IMATH_H_
 
-/* use always 32bit digits - should some arch use 16bit digits? */
-#define USE_LONG_LONG
-
 #include <limits.h>
+#include <stdbool.h>
+#include <stdint.h>
 
 typedef unsigned char mp_sign;
 typedef unsigned int mp_size;
 typedef int mp_result;
+typedef long mp_small;			/* must be a signed type */
+typedef unsigned long mp_usmall;	/* must be an unsigned type */
 
-#ifdef USE_LONG_LONG
-typedef uint32 mp_digit;
-typedef uint64 mp_word;
 
-#define MP_DIGIT_MAX	   0xFFFFFFFFULL
-#define MP_WORD_MAX		   0xFFFFFFFFFFFFFFFFULL
+/* Build with words as uint64_t by default. */
+#ifdef USE_32BIT_WORDS
+typedef uint16_t mp_digit;
+typedef uint32_t mp_word;
+#define MP_DIGIT_MAX  (UINT16_MAX * 1UL)
+#define MP_WORD_MAX   (UINT32_MAX * 1UL)
 #else
-typedef uint16 mp_digit;
-typedef uint32 mp_word;
-
-#define MP_DIGIT_MAX	   0xFFFFUL
-#define MP_WORD_MAX		   0xFFFFFFFFUL
+typedef uint32_t mp_digit;
+typedef uint64_t mp_word;
+#define MP_DIGIT_MAX  (UINT32_MAX * UINT64_C(1))
+#define MP_WORD_MAX   (UINT64_MAX)
 #endif
 
-typedef struct mpz
+typedef struct
 {
+	mp_digit	single;
 	mp_digit   *digits;
 	mp_size		alloc;
 	mp_size		used;
@@ -64,10 +62,26 @@ typedef struct mpz
 
 		   *mp_int;
 
-#define MP_DIGITS(Z) ((Z)->digits)
-#define MP_ALLOC(Z)  ((Z)->alloc)
-#define MP_USED(Z)	 ((Z)->used)
-#define MP_SIGN(Z)	 ((Z)->sign)
+static inline mp_digit *
+MP_DIGITS(mp_int Z)
+{
+	return Z->digits;
+}
+static inline mp_size
+MP_ALLOC(mp_int Z)
+{
+	return Z->alloc;
+}
+static inline mp_size
+MP_USED(mp_int Z)
+{
+	return Z->used;
+}
+static inline mp_sign
+MP_SIGN(mp_int Z)
+{
+	return Z->sign;
+}
 
 extern const mp_result MP_OK;
 extern const mp_result MP_FALSE;
@@ -77,134 +91,357 @@ extern const mp_result MP_RANGE;
 extern const mp_result MP_UNDEF;
 extern const mp_result MP_TRUNC;
 extern const mp_result MP_BADARG;
+extern const mp_result MP_MINERR;
+
+#define MP_DIGIT_BIT   (sizeof(mp_digit) * CHAR_BIT)
+#define MP_WORD_BIT    (sizeof(mp_word) * CHAR_BIT)
+#define MP_SMALL_MIN   LONG_MIN
+#define MP_SMALL_MAX   LONG_MAX
+#define MP_USMALL_MAX  ULONG_MAX
+
+#define MP_MIN_RADIX   2
+#define MP_MAX_RADIX   36
 
-#define MP_DIGIT_BIT	(sizeof(mp_digit) * CHAR_BIT)
-#define MP_WORD_BIT		(sizeof(mp_word) * CHAR_BIT)
+/** Sets the default number of digits allocated to an `mp_int` constructed by
+	`mp_int_init_size()` with `prec == 0`. Allocations are rounded up to
+	multiples of this value. `MP_DEFAULT_PREC` is the default value. Requires
+	`ndigits > 0`. */
+void		mp_int_default_precision(mp_size ndigits);
 
-#define MP_MIN_RADIX	2
-#define MP_MAX_RADIX	36
+/** Sets the number of digits below which multiplication will use the standard
+	quadratic "schoolbook" multiplcation algorithm rather than Karatsuba-Ofman.
+	Requires `ndigits >= sizeof(mp_word)`. */
+void		mp_int_multiply_threshold(mp_size ndigits);
 
+/** A sign indicating a (strictly) negative value. */
 extern const mp_sign MP_NEG;
+
+/** A sign indicating a zero or positive value. */
 extern const mp_sign MP_ZPOS;
 
-#define mp_int_is_odd(Z)  ((Z)->digits[0] & 1)
-#define mp_int_is_even(Z) !((Z)->digits[0] & 1)
+/** Reports whether `z` is odd, having remainder 1 when divided by 2. */
+static inline bool
+mp_int_is_odd(mp_int z)
+{
+	return (z->digits[0] & 1) != 0;
+}
 
-mp_size		mp_get_default_precision(void);
-void		mp_set_default_precision(mp_size s);
-mp_size		mp_get_multiply_threshold(void);
-void		mp_set_multiply_threshold(mp_size s);
+/** Reports whether `z` is even, having remainder 0 when divided by 2. */
+static inline bool
+mp_int_is_even(mp_int z)
+{
+	return (z->digits[0] & 1) == 0;
+}
 
+/** Initializes `z` with 1-digit precision and sets it to zero.  This function
+	cannot fail unless `z == NULL`. */
 mp_result	mp_int_init(mp_int z);
+
+/** Allocates a fresh zero-valued `mpz_t` on the heap, returning NULL in case
+	of error. The only possible error is out-of-memory. */
 mp_int		mp_int_alloc(void);
+
+/** Initializes `z` with at least `prec` digits of storage, and sets it to
+	zero. If `prec` is zero, the default precision is used. In either case the
+	size is rounded up to the nearest multiple of the word size. */
 mp_result	mp_int_init_size(mp_int z, mp_size prec);
+
+/** Initializes `z` to be a copy of an already-initialized value in `old`. The
+	new copy does not share storage with the original. */
 mp_result	mp_int_init_copy(mp_int z, mp_int old);
-mp_result	mp_int_init_value(mp_int z, int value);
-mp_result	mp_int_set_value(mp_int z, int value);
+
+/** Initializes `z` to the specified signed `value` at default precision. */
+mp_result	mp_int_init_value(mp_int z, mp_small value);
+
+/** Initializes `z` to the specified unsigned `value` at default precision. */
+mp_result	mp_int_init_uvalue(mp_int z, mp_usmall uvalue);
+
+/** Sets `z` to the value of the specified signed `value`. */
+mp_result	mp_int_set_value(mp_int z, mp_small value);
+
+/** Sets `z` to the value of the specified unsigned `value`. */
+mp_result	mp_int_set_uvalue(mp_int z, mp_usmall uvalue);
+
+/** Releases the storage used by `z`. */
 void		mp_int_clear(mp_int z);
+
+/** Releases the storage used by `z` and also `z` itself.
+	This should only be used for `z` allocated by `mp_int_alloc()`. */
 void		mp_int_free(mp_int z);
 
-mp_result	mp_int_copy(mp_int a, mp_int c);	/* c = a	 */
-void		mp_int_swap(mp_int a, mp_int c);	/* swap a, c */
-void		mp_int_zero(mp_int z);	/* z = 0	 */
-mp_result	mp_int_abs(mp_int a, mp_int c); /* c = |a|	 */
-mp_result	mp_int_neg(mp_int a, mp_int c); /* c = -a	 */
-mp_result	mp_int_add(mp_int a, mp_int b, mp_int c);	/* c = a + b */
-mp_result	mp_int_add_value(mp_int a, int value, mp_int c);
-mp_result	mp_int_sub(mp_int a, mp_int b, mp_int c);	/* c = a - b */
-mp_result	mp_int_sub_value(mp_int a, int value, mp_int c);
-mp_result	mp_int_mul(mp_int a, mp_int b, mp_int c);	/* c = a * b */
-mp_result	mp_int_mul_value(mp_int a, int value, mp_int c);
-mp_result	mp_int_mul_pow2(mp_int a, int p2, mp_int c);
-mp_result	mp_int_sqr(mp_int a, mp_int c); /* c = a * a */
-
-mp_result mp_int_div(mp_int a, mp_int b,		/* q = a / b */
-		   mp_int q, mp_int r); /* r = a % b */
-mp_result mp_int_div_value(mp_int a, int value,		/* q = a / value */
-				 mp_int q, int *r); /* r = a % value */
-mp_result mp_int_div_pow2(mp_int a, int p2,		/* q = a / 2^p2  */
-				mp_int q, mp_int r);	/* r = q % 2^p2  */
-mp_result	mp_int_mod(mp_int a, mp_int m, mp_int c);	/* c = a % m */
-
-#define   mp_int_mod_value(A, V, R) mp_int_div_value((A), (V), 0, (R))
-mp_result	mp_int_expt(mp_int a, int b, mp_int c); /* c = a^b	 */
-mp_result	mp_int_expt_value(int a, int b, mp_int c);	/* c = a^b	 */
-
-int			mp_int_compare(mp_int a, mp_int b); /* a <=> b	   */
-int			mp_int_compare_unsigned(mp_int a, mp_int b);	/* |a| <=> |b| */
-int			mp_int_compare_zero(mp_int z);	/* a <=> 0	   */
-int			mp_int_compare_value(mp_int z, int value);	/* a <=> v	   */
-
-/* Returns true if v|a, false otherwise (including errors) */
-int			mp_int_divisible_value(mp_int a, int v);
-
-/* Returns k >= 0 such that z = 2^k, if one exists; otherwise < 0 */
+/** Replaces the value of `c` with a copy of the value of `a`. No new memory is
+	allocated unless `a` has more significant digits than `c` has allocated. */
+mp_result	mp_int_copy(mp_int a, mp_int c);
+
+/** Swaps the values and storage between `a` and `c`. */
+void		mp_int_swap(mp_int a, mp_int c);
+
+/** Sets `z` to zero. The allocated storage of `z` is not changed. */
+void		mp_int_zero(mp_int z);
+
+/** Sets `c` to the absolute value of `a`. */
+mp_result	mp_int_abs(mp_int a, mp_int c);
+
+/** Sets `c` to the additive inverse (negation) of `a`. */
+mp_result	mp_int_neg(mp_int a, mp_int c);
+
+/** Sets `c` to the sum of `a` and `b`. */
+mp_result	mp_int_add(mp_int a, mp_int b, mp_int c);
+
+/** Sets `c` to the sum of `a` and `value`. */
+mp_result	mp_int_add_value(mp_int a, mp_small value, mp_int c);
+
+/** Sets `c` to the difference of `a` less `b`. */
+mp_result	mp_int_sub(mp_int a, mp_int b, mp_int c);
+
+/** Sets `c` to the difference of `a` less `value`. */
+mp_result	mp_int_sub_value(mp_int a, mp_small value, mp_int c);
+
+/** Sets `c` to the product of `a` and `b`. */
+mp_result	mp_int_mul(mp_int a, mp_int b, mp_int c);
+
+/** Sets `c` to the product of `a` and `value`. */
+mp_result	mp_int_mul_value(mp_int a, mp_small value, mp_int c);
+
+/** Sets `c` to the product of `a` and `2^p2`. Requires `p2 >= 0`. */
+mp_result	mp_int_mul_pow2(mp_int a, mp_small p2, mp_int c);
+
+/** Sets `c` to the square of `a`. */
+mp_result	mp_int_sqr(mp_int a, mp_int c);
+
+/** Sets `q` and `r` to the quotent and remainder of `a / b`. Division by
+	powers of 2 is detected and handled efficiently.  The remainder is pinned
+	to `0 <= r < b`.
+
+	Either of `q` or `r` may be NULL, but not both, and `q` and `r` may not
+	point to the same value. */
+mp_result	mp_int_div(mp_int a, mp_int b, mp_int q, mp_int r);
+
+/** Sets `q` and `*r` to the quotent and remainder of `a / value`. Division by
+	powers of 2 is detected and handled efficiently. The remainder is pinned to
+	`0 <= *r < b`. Either of `q` or `r` may be NULL. */
+mp_result	mp_int_div_value(mp_int a, mp_small value, mp_int q, mp_small * r);
+
+/** Sets `q` and `r` to the quotient and remainder of `a / 2^p2`. This is a
+	special case for division by powers of two that is more efficient than
+	using ordinary division. Note that `mp_int_div()` will automatically handle
+	this case, this function is for cases where you have only the exponent. */
+mp_result	mp_int_div_pow2(mp_int a, mp_small p2, mp_int q, mp_int r);
+
+/** Sets `c` to the remainder of `a / m`.
+	The remainder is pinned to `0 <= c < m`. */
+mp_result	mp_int_mod(mp_int a, mp_int m, mp_int c);
+
+/** Sets `c` to the value of `a` raised to the `b` power.
+	It returns `MP_RANGE` if `b < 0`. */
+mp_result	mp_int_expt(mp_int a, mp_small b, mp_int c);
+
+/** Sets `c` to the value of `a` raised to the `b` power.
+	It returns `MP_RANGE` if `b < 0`. */
+mp_result	mp_int_expt_value(mp_small a, mp_small b, mp_int c);
+
+/** Sets `c` to the value of `a` raised to the `b` power.
+	It returns `MP_RANGE`) if `b < 0`. */
+mp_result	mp_int_expt_full(mp_int a, mp_int b, mp_int c);
+
+/** Sets `*r` to the remainder of `a / value`.
+	The remainder is pinned to `0 <= r < value`. */
+static inline
+mp_result
+mp_int_mod_value(mp_int a, mp_small value, mp_small * r)
+{
+	return mp_int_div_value(a, value, 0, r);
+}
+
+/** Returns the comparator of `a` and `b`. */
+int			mp_int_compare(mp_int a, mp_int b);
+
+/** Returns the comparator of the magnitudes of `a` and `b`, disregarding their
+	signs. Neither `a` nor `b` is modified by the comparison. */
+int			mp_int_compare_unsigned(mp_int a, mp_int b);
+
+/** Returns the comparator of `z` and zero. */
+int			mp_int_compare_zero(mp_int z);
+
+/** Returns the comparator of `z` and the signed value `v`. */
+int			mp_int_compare_value(mp_int z, mp_small v);
+
+/** Returns the comparator of `z` and the unsigned value `uv`. */
+int			mp_int_compare_uvalue(mp_int z, mp_usmall uv);
+
+/** Reports whether `a` is divisible by `v`. */
+bool		mp_int_divisible_value(mp_int a, mp_small v);
+
+/** Returns `k >= 0` such that `z` is `2^k`, if such a `k` exists. If no such
+	`k` exists, the function returns -1. */
 int			mp_int_is_pow2(mp_int z);
 
-mp_result mp_int_exptmod(mp_int a, mp_int b, mp_int m,
-			   mp_int c);		/* c = a^b (mod m) */
-mp_result mp_int_exptmod_evalue(mp_int a, int value,
-					  mp_int m, mp_int c);	/* c = a^v (mod m) */
-mp_result mp_int_exptmod_bvalue(int value, mp_int b,
-					  mp_int m, mp_int c);	/* c = v^b (mod m) */
-mp_result mp_int_exptmod_known(mp_int a, mp_int b,
-					 mp_int m, mp_int mu,
-					 mp_int c); /* c = a^b (mod m) */
+/** Sets `c` to the value of `a` raised to the `b` power, reduced modulo `m`.
+	It returns `MP_RANGE` if `b < 0` or `MP_UNDEF` if `m == 0`. */
+mp_result	mp_int_exptmod(mp_int a, mp_int b, mp_int m, mp_int c);
+
+/** Sets `c` to the value of `a` raised to the `value` power, modulo `m`.
+	It returns `MP_RANGE` if `value < 0` or `MP_UNDEF` if `m == 0`. */
+mp_result	mp_int_exptmod_evalue(mp_int a, mp_small value, mp_int m, mp_int c);
+
+/** Sets `c` to the value of `value` raised to the `b` power, modulo `m`.
+	It returns `MP_RANGE` if `b < 0` or `MP_UNDEF` if `m == 0`. */
+mp_result	mp_int_exptmod_bvalue(mp_small value, mp_int b, mp_int m, mp_int c);
+
+/** Sets `c` to the value of `a` raised to the `b` power, reduced modulo `m`,
+	given a precomputed reduction constant `mu` defined for Barrett's modular
+	reduction algorithm.
+
+	It returns `MP_RANGE` if `b < 0` or `MP_UNDEF` if `m == 0`. */
+mp_result	mp_int_exptmod_known(mp_int a, mp_int b, mp_int m, mp_int mu, mp_int c);
+
+/** Sets `c` to the reduction constant for Barrett reduction by modulus `m`.
+	Requires that `c` and `m` point to distinct locations. */
 mp_result	mp_int_redux_const(mp_int m, mp_int c);
 
-mp_result	mp_int_invmod(mp_int a, mp_int m, mp_int c);	/* c = 1/a (mod m) */
+/** Sets `c` to the multiplicative inverse of `a` modulo `m`, if it exists.
+	The least non-negative representative of the congruence class is computed.
+
+	It returns `MP_UNDEF` if the inverse does not exist, or `MP_RANGE` if `a ==
+	0` or `m <= 0`. */
+mp_result	mp_int_invmod(mp_int a, mp_int m, mp_int c);
+
+/** Sets `c` to the greatest common divisor of `a` and `b`.
+
+	It returns `MP_UNDEF` if the GCD is undefined, such as for example if `a`
+	and `b` are both zero. */
+mp_result	mp_int_gcd(mp_int a, mp_int b, mp_int c);
 
-mp_result	mp_int_gcd(mp_int a, mp_int b, mp_int c);	/* c = gcd(a, b)   */
+/** Sets `c` to the greatest common divisor of `a` and `b`, and sets `x` and
+	`y` to values satisfying Bezout's identity `gcd(a, b) = ax + by`.
 
-mp_result mp_int_egcd(mp_int a, mp_int b, mp_int c,		/* c = gcd(a, b)   */
-			mp_int x, mp_int y);	/* c = ax + by	   */
+	It returns `MP_UNDEF` if the GCD is undefined, such as for example if `a`
+	and `b` are both zero. */
+mp_result	mp_int_egcd(mp_int a, mp_int b, mp_int c, mp_int x, mp_int y);
 
-mp_result	mp_int_sqrt(mp_int a, mp_int c);	/* c = floor(sqrt(q)) */
+/** Sets `c` to the least common multiple of `a` and `b`.
 
-/* Convert to an int, if representable (returns MP_RANGE if not). */
-mp_result	mp_int_to_int(mp_int z, int *out);
+	It returns `MP_UNDEF` if the LCM is undefined, such as for example if `a`
+	and `b` are both zero. */
+mp_result	mp_int_lcm(mp_int a, mp_int b, mp_int c);
 
-/* Convert to nul-terminated string with the specified radix, writing at
-   most limit characters including the nul terminator  */
-mp_result mp_int_to_string(mp_int z, mp_size radix,
-				 char *str, int limit);
+/** Sets `c` to the greatest integer not less than the `b`th root of `a`,
+	using Newton's root-finding algorithm.
+	It returns `MP_UNDEF` if `a < 0` and `b` is even. */
+mp_result	mp_int_root(mp_int a, mp_small b, mp_int c);
 
-/* Return the number of characters required to represent
-   z in the given radix.  May over-estimate. */
+/** Sets `c` to the greatest integer not less than the square root of `a`.
+	This is a special case of `mp_int_root()`. */
+static inline
+mp_result
+mp_int_sqrt(mp_int a, mp_int c)
+{
+	return mp_int_root(a, 2, c);
+}
+
+/** Returns `MP_OK` if `z` is representable as `mp_small`, else `MP_RANGE`.
+	If `out` is not NULL, `*out` is set to the value of `z` when `MP_OK`. */
+mp_result	mp_int_to_int(mp_int z, mp_small * out);
+
+/** Returns `MP_OK` if `z` is representable as `mp_usmall`, or `MP_RANGE`.
+	If `out` is not NULL, `*out` is set to the value of `z` when `MP_OK`. */
+mp_result	mp_int_to_uint(mp_int z, mp_usmall * out);
+
+/** Converts `z` to a zero-terminated string of characters in the specified
+	`radix`, writing at most `limit` characters to `str` including the
+	terminating NUL value. A leading `-` is used to indicate a negative value.
+
+	Returns `MP_TRUNC` if `limit` was to small to write all of `z`.
+	Requires `MP_MIN_RADIX <= radix <= MP_MAX_RADIX`. */
+mp_result	mp_int_to_string(mp_int z, mp_size radix, char *str, int limit);
+
+/** Reports the minimum number of characters required to represent `z` as a
+	zero-terminated string in the given `radix`.
+	Requires `MP_MIN_RADIX <= radix <= MP_MAX_RADIX`. */
 mp_result	mp_int_string_len(mp_int z, mp_size radix);
 
-/* Read zero-terminated string into z */
+/** Reads a string of ASCII digits in the specified `radix` from the zero
+	terminated `str` provided into `z`. For values of `radix > 10`, the letters
+	`A`..`Z` or `a`..`z` are accepted. Letters are interpreted without respect
+	to case.
+
+	Leading whitespace is ignored, and a leading `+` or `-` is interpreted as a
+	sign flag. Processing stops when a NUL or any other character out of range
+	for a digit in the given radix is encountered.
+
+	If the whole string was consumed, `MP_OK` is returned; otherwise
+	`MP_TRUNC`. is returned.
+
+	Requires `MP_MIN_RADIX <= radix <= MP_MAX_RADIX`. */
 mp_result	mp_int_read_string(mp_int z, mp_size radix, const char *str);
-mp_result mp_int_read_cstring(mp_int z, mp_size radix, const char *str,
-					char **end);
 
-/* Return the number of significant bits in z */
+/** Reads a string of ASCII digits in the specified `radix` from the zero
+	terminated `str` provided into `z`. For values of `radix > 10`, the letters
+	`A`..`Z` or `a`..`z` are accepted. Letters are interpreted without respect
+	to case.
+
+	Leading whitespace is ignored, and a leading `+` or `-` is interpreted as a
+	sign flag. Processing stops when a NUL or any other character out of range
+	for a digit in the given radix is encountered.
+
+	If the whole string was consumed, `MP_OK` is returned; otherwise
+	`MP_TRUNC`. is returned. If `end` is not NULL, `*end` is set to point to
+	the first unconsumed byte of the input string (the NUL byte if the whole
+	string was consumed). This emulates the behavior of the standard C
+	`strtol()` function.
+
+	Requires `MP_MIN_RADIX <= radix <= MP_MAX_RADIX`. */
+mp_result	mp_int_read_cstring(mp_int z, mp_size radix, const char *str, char **end);
+
+/** Returns the number of significant bits in `z`. */
 mp_result	mp_int_count_bits(mp_int z);
 
-/* Convert z to two's complement binary, writing at most limit bytes */
+/** Converts `z` to 2's complement binary, writing at most `limit` bytes into
+	the given `buf`.  Returns `MP_TRUNC` if the buffer limit was too small to
+	contain the whole value.  If this occurs, the contents of buf will be
+	effectively garbage, as the function uses the buffer as scratch space.
+
+	The binary representation of `z` is in base-256 with digits ordered from
+	most significant to least significant (network byte ordering).  The
+	high-order bit of the first byte is set for negative values, clear for
+	non-negative values.
+
+	As a result, non-negative values will be padded with a leading zero byte if
+	the high-order byte of the base-256 magnitude is set.  This extra byte is
+	accounted for by the `mp_int_binary_len()` function. */
 mp_result	mp_int_to_binary(mp_int z, unsigned char *buf, int limit);
 
-/* Read a two's complement binary value into z from the given buffer */
+/** Reads a 2's complement binary value from `buf` into `z`, where `len` is the
+	length of the buffer.  The contents of `buf` may be overwritten during
+	processing, although they will be restored when the function returns. */
 mp_result	mp_int_read_binary(mp_int z, unsigned char *buf, int len);
 
-/* Return the number of bytes required to represent z in binary. */
+/** Returns the number of bytes to represent `z` in 2's complement binary. */
 mp_result	mp_int_binary_len(mp_int z);
 
-/* Convert z to unsigned binary, writing at most limit bytes */
+/** Converts the magnitude of `z` to unsigned binary, writing at most `limit`
+	bytes into the given `buf`.  The sign of `z` is ignored, but `z` is not
+	modified.  Returns `MP_TRUNC` if the buffer limit was too small to contain
+	the whole value.  If this occurs, the contents of `buf` will be effectively
+	garbage, as the function uses the buffer as scratch space during
+	conversion.
+
+	The binary representation of `z` is in base-256 with digits ordered from
+	most significant to least significant (network byte ordering). */
 mp_result	mp_int_to_unsigned(mp_int z, unsigned char *buf, int limit);
 
-/* Read an unsigned binary value into z from the given buffer */
+/** Reads an unsigned binary value from `buf` into `z`, where `len` is the
+	length of the buffer. The contents of `buf` are not modified during
+	processing. */
 mp_result	mp_int_read_unsigned(mp_int z, unsigned char *buf, int len);
 
-/* Return the number of bytes required to represent z as unsigned output */
+/** Returns the number of bytes required to represent `z` as an unsigned binary
+	value in base 256. */
 mp_result	mp_int_unsigned_len(mp_int z);
 
-/* Return a statically allocated string describing error code res */
+/** Returns a pointer to a brief, human-readable, zero-terminated string
+	describing `res`. The returned string is statically allocated and must not
+	be freed by the caller. */
 const char *mp_error_string(mp_result res);
 
-#if 0
-void		s_print(char *tag, mp_int z);
-void		s_print_buf(char *tag, mp_digit *buf, mp_size num);
-#endif
-
 #endif							/* end IMATH_H_ */
imath1.29-pgedits-v2.patchtext/plain; charset=us-asciiDownload
diff --git a/configure b/configure
index d5ace62..a280bd1 100755
--- a/configure
+++ b/configure
@@ -732,6 +732,7 @@ CPP
 BITCODE_CXXFLAGS
 BITCODE_CFLAGS
 CFLAGS_VECTOR
+PERMIT_DECLARATION_AFTER_STATEMENT
 LLVM_BINPATH
 LLVM_CXXFLAGS
 LLVM_CFLAGS
@@ -5252,6 +5253,7 @@ if test "$GCC" = yes -a "$ICC" = no; then
   CFLAGS="-Wall -Wmissing-prototypes -Wpointer-arith"
   CXXFLAGS="-Wall -Wpointer-arith"
   # These work in some but not all gcc versions
+  save_CFLAGS=$CFLAGS
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC} supports -Wdeclaration-after-statement, for CFLAGS" >&5
 $as_echo_n "checking whether ${CC} supports -Wdeclaration-after-statement, for CFLAGS... " >&6; }
@@ -5292,7 +5294,13 @@ if test x"$pgac_cv_prog_CC_cflags__Wdeclaration_after_statement" = x"yes"; then
 fi
 
 
-  # -Wdeclaration-after-statement isn't applicable for C++
+  # -Wdeclaration-after-statement isn't applicable for C++.  Specific C files
+  # disable it, so AC_SUBST the negative form.
+  PERMIT_DECLARATION_AFTER_STATEMENT=
+  if test x"$save_CFLAGS" != x"$CFLAGS"; then
+    PERMIT_DECLARATION_AFTER_STATEMENT=-Wno-declaration-after-statement
+  fi
+
   # Really don't want VLAs to be used in our dialect of C
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC} supports -Werror=vla, for CFLAGS" >&5
diff --git a/configure.in b/configure.in
index 4efb912..1c02890 100644
--- a/configure.in
+++ b/configure.in
@@ -476,8 +476,15 @@ if test "$GCC" = yes -a "$ICC" = no; then
   CFLAGS="-Wall -Wmissing-prototypes -Wpointer-arith"
   CXXFLAGS="-Wall -Wpointer-arith"
   # These work in some but not all gcc versions
+  save_CFLAGS=$CFLAGS
   PGAC_PROG_CC_CFLAGS_OPT([-Wdeclaration-after-statement])
-  # -Wdeclaration-after-statement isn't applicable for C++
+  # -Wdeclaration-after-statement isn't applicable for C++.  Specific C files
+  # disable it, so AC_SUBST the negative form.
+  PERMIT_DECLARATION_AFTER_STATEMENT=
+  if test x"$save_CFLAGS" != x"$CFLAGS"; then
+    PERMIT_DECLARATION_AFTER_STATEMENT=-Wno-declaration-after-statement
+  fi
+  AC_SUBST(PERMIT_DECLARATION_AFTER_STATEMENT)
   # Really don't want VLAs to be used in our dialect of C
   PGAC_PROG_CC_CFLAGS_OPT([-Werror=vla])
   # -Wvla is not applicable for C++
diff --git a/contrib/pgcrypto/Makefile b/contrib/pgcrypto/Makefile
index 573bc6d..1313b66 100644
--- a/contrib/pgcrypto/Makefile
+++ b/contrib/pgcrypto/Makefile
@@ -59,6 +59,9 @@ SHLIB_LINK += $(filter -leay32, $(LIBS))
 SHLIB_LINK += -lws2_32
 endif
 
+# Upstream uses a larger subset of C99.
+imath.o: CFLAGS+=$(PERMIT_DECLARATION_AFTER_STATEMENT)
+
 rijndael.o: rijndael.tbl
 
 rijndael.tbl:
diff --git a/contrib/pgcrypto/imath.c b/contrib/pgcrypto/imath.c
index 96be668..ea20ebf 100644
--- a/contrib/pgcrypto/imath.c
+++ b/contrib/pgcrypto/imath.c
@@ -1,6 +1,43 @@
+/*-------------------------------------------------------------------------
+ *
+ * imath.c
+ *
+ * Last synchronized from https://github.com/creachadair/imath/tree/v1.29,
+ * using the following procedure:
+ *
+ * 1. Download imath.c and imath.h of the last synchronized version.  Remove
+ *    "#ifdef __cplusplus" blocks, which upset pgindent.  Run pgindent on the
+ *    two files.  Filter the two files through "unexpand -t4 --first-only".
+ *    Diff the result against the PostgreSQL versions.  As of the last
+ *    synchronization, changes were as follows:
+ *
+ *    - replace malloc(), realloc() and free() with px_ versions
+ *    - redirect assert() to Assert()
+ *    - #undef MIN, #undef MAX before defining them
+ *    - remove includes covered by c.h
+ *    - rename DEBUG to IMATH_DEBUG
+ *
+ * 2. Download a newer imath.c and imath.h.  Transform them like in step 1.
+ *    Apply to these files the diff you saved in step 1.  Look for new lines
+ *    requiring the same kind of change, such as new malloc() calls.
+ *
+ * 3. Configure PostgreSQL using --without-openssl.  Run "make -C
+ *    contrib/pgcrypto check".
+ *
+ * 4. Update this header comment.
+ *
+ * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *	  contrib/pgcrypto/imath.c
+ *
+ * Upstream copyright terms follow.
+ *-------------------------------------------------------------------------
+ */
+
 /*
-  Name:     imath.c
-  Purpose:  Arbitrary precision integer arithmetic routines.
+  Name:		imath.c
+  Purpose:	Arbitrary precision integer arithmetic routines.
   Author:   M. J. Fromberger
 
   Copyright (C) 2002-2007 Michael J. Fromberger, All Rights Reserved.
@@ -24,12 +61,13 @@
   SOFTWARE.
  */
 
+#include "postgres.h"
+
 #include "imath.h"
+#include "px.h"
 
-#include <assert.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
+#undef assert
+#define assert(TEST) Assert(TEST)
 
 const mp_result MP_OK = 0;		/* no error, all is well  */
 const mp_result MP_FALSE = 0;	/* boolean false          */
@@ -135,6 +173,8 @@ CLAMP(mp_int z_)
 }
 
 /* Select min/max. */
+#undef MIN
+#undef MAX
 static inline int
 MIN(int A, int B)
 {
@@ -435,7 +475,7 @@ mp_int_init(mp_int z)
 mp_int
 mp_int_alloc(void)
 {
-	mp_int		out = malloc(sizeof(mpz_t));
+	mp_int		out = px_alloc(sizeof(mpz_t));
 
 	if (out != NULL)
 		mp_int_init(out);
@@ -561,7 +601,7 @@ mp_int_free(mp_int z)
 	assert(z != NULL);
 
 	mp_int_clear(z);
-	free(z);					/* note: NOT s_free() */
+	px_free(z);					/* note: NOT s_free() */
 }
 
 mp_result
@@ -2162,18 +2202,18 @@ mp_error_string(mp_result res)
 /*------------------------------------------------------------------------*/
 /* Private functions for internal use.  These make assumptions.           */
 
-#if DEBUG
+#if IMATH_DEBUG
 static const mp_digit fill = (mp_digit) 0xdeadbeefabad1dea;
 #endif
 
 static mp_digit *
 s_alloc(mp_size num)
 {
-	mp_digit   *out = malloc(num * sizeof(mp_digit));
+	mp_digit   *out = px_alloc(num * sizeof(mp_digit));
 
 	assert(out != NULL);
 
-#if DEBUG
+#if IMATH_DEBUG
 	for (mp_size ix = 0; ix < num; ++ix)
 		out[ix] = fill;
 #endif
@@ -2183,7 +2223,7 @@ s_alloc(mp_size num)
 static mp_digit *
 s_realloc(mp_digit *old, mp_size osize, mp_size nsize)
 {
-#if DEBUG
+#if IMATH_DEBUG
 	mp_digit   *new = s_alloc(nsize);
 
 	assert(new != NULL);
@@ -2192,7 +2232,7 @@ s_realloc(mp_digit *old, mp_size osize, mp_size nsize)
 		new[ix] = fill;
 	memcpy(new, old, osize * sizeof(mp_digit));
 #else
-	mp_digit   *new = realloc(old, nsize * sizeof(mp_digit));
+	mp_digit   *new = px_realloc(old, nsize * sizeof(mp_digit));
 
 	assert(new != NULL);
 #endif
@@ -2203,7 +2243,7 @@ s_realloc(mp_digit *old, mp_size osize, mp_size nsize)
 static void
 s_free(void *ptr)
 {
-	free(ptr);
+	px_free(ptr);
 }
 
 static bool
diff --git a/contrib/pgcrypto/imath.h b/contrib/pgcrypto/imath.h
index ab9ced1..65be748 100644
--- a/contrib/pgcrypto/imath.h
+++ b/contrib/pgcrypto/imath.h
@@ -28,8 +28,6 @@
 #define IMATH_H_
 
 #include <limits.h>
-#include <stdbool.h>
-#include <stdint.h>
 
 typedef unsigned char mp_sign;
 typedef unsigned int mp_size;
diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index 758ea43..93ab893 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -261,6 +261,7 @@ CFLAGS = @CFLAGS@
 CFLAGS_VECTOR = @CFLAGS_VECTOR@
 CFLAGS_SSE42 = @CFLAGS_SSE42@
 CFLAGS_ARMV8_CRC32C = @CFLAGS_ARMV8_CRC32C@
+PERMIT_DECLARATION_AFTER_STATEMENT = @PERMIT_DECLARATION_AFTER_STATEMENT@
 CXXFLAGS = @CXXFLAGS@
 
 LLVM_CPPFLAGS = @LLVM_CPPFLAGS@
#19Tom Lane
tgl@sss.pgh.pa.us
In reply to: Noah Misch (#18)
Re: Synchronize with imath upstream

Noah Misch <noah@leadboat.com> writes:

On Thu, Feb 07, 2019 at 10:12:05AM -0500, Tom Lane wrote:

I have no particular opinion on whether pgindent should be part of the
mix for imath, but I do strongly recommend setting up and documenting a
reproducible import process, as I did for src/timezone.

Good idea. I've modified the imath.c header comment to take the form of an
import process; see attached imath1.29-pgedits-v2.patch.

Maybe easier to keep the instructions in a separate README file?
(I don't see a need to put a PG copyright in this file, when the
mods from upstream are this small.)

Looks good otherwise.

regards, tom lane

#20Noah Misch
noah@leadboat.com
In reply to: Tom Lane (#19)
Re: Synchronize with imath upstream

On Thu, Feb 07, 2019 at 11:56:18PM -0500, Tom Lane wrote:

Noah Misch <noah@leadboat.com> writes:

On Thu, Feb 07, 2019 at 10:12:05AM -0500, Tom Lane wrote:

I have no particular opinion on whether pgindent should be part of the
mix for imath, but I do strongly recommend setting up and documenting a
reproducible import process, as I did for src/timezone.

Good idea. I've modified the imath.c header comment to take the form of an
import process; see attached imath1.29-pgedits-v2.patch.

Maybe easier to keep the instructions in a separate README file?

Most imath.c patches have cause to update those lines, and patches to other
files almost never do. Hence, I think hackers are more likely to find and
update those lines in imath.c. I would choose a README if concerns weren't
concentrated in one file.

(I don't see a need to put a PG copyright in this file, when the
mods from upstream are this small.)

The tree has been inconsistent about that, which is okay. I was mimicking
src/port/strlcpy.c. Others, e.g. src/port/crypt.c, haven't added a copyright.

#21Tom Lane
tgl@sss.pgh.pa.us
In reply to: Noah Misch (#20)
Re: Synchronize with imath upstream

Noah Misch <noah@leadboat.com> writes:

On Thu, Feb 07, 2019 at 11:56:18PM -0500, Tom Lane wrote:

Maybe easier to keep the instructions in a separate README file?

Most imath.c patches have cause to update those lines, and patches to other
files almost never do. Hence, I think hackers are more likely to find and
update those lines in imath.c. I would choose a README if concerns weren't
concentrated in one file.

Fair enough, objection withdrawn.

regards, tom lane

#22Noah Misch
noah@leadboat.com
In reply to: Tom Lane (#21)
Re: Synchronize with imath upstream

On Sat, Feb 16, 2019 at 02:12:50PM -0500, Tom Lane wrote:

Noah Misch <noah@leadboat.com> writes:

On Thu, Feb 07, 2019 at 11:56:18PM -0500, Tom Lane wrote:

Maybe easier to keep the instructions in a separate README file?

Most imath.c patches have cause to update those lines, and patches to other
files almost never do. Hence, I think hackers are more likely to find and
update those lines in imath.c. I would choose a README if concerns weren't
concentrated in one file.

Fair enough, objection withdrawn.

Pushed, but it broke dory. Will fix.