From: Noah Misch <noah@leadboat.com>
To: pgsql-hackers@postgresql.org
Subject: Synchronize with imath upstream
Date: Sat, 2 Feb 2019 19:57:04 -0800
Message-ID: <20190203035704.GA6226@rfd.leadboat.com> (raw)
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
diff --git a/contrib/pgcrypto/imath.c b/contrib/pgcrypto/imath.cindex 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.hindex 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_ */
diff --git a/configure b/configureindex 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.inindex 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/Makefileindex 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.cindex 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.hindex 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.inindex 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@
Attachments:
[text/plain] imath1.29-raw-sync-v1.patch (117.7K, ../20190203035704.GA6226@rfd.leadboat.com/2-imath1.29-raw-sync-v1.patch)
download | inline diff:diff --git a/contrib/pgcrypto/imath.c b/contrib/pgcrypto/imath.cindex 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.hindex 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_ */
[text/plain] imath1.29-pgedits-v1.patch (6.5K, ../20190203035704.GA6226@rfd.leadboat.com/3-imath1.29-pgedits-v1.patch)
download | inline diff:diff --git a/configure b/configureindex 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.inindex 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/Makefileindex 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.cindex 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.hindex 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.inindex 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@
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-hackers@postgresql.org
Cc: noah@leadboat.com
Subject: Re: Synchronize with imath upstream
In-Reply-To: <20190203035704.GA6226@rfd.leadboat.com>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox