xref: /minix3/crypto/external/bsd/heimdal/dist/lib/hcrypto/libtommath/mtest/mpi.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: mpi.c,v 1.1.1.3 2014/04/24 12:45:39 pettai Exp $	*/
2ebfedea0SLionel Sambuc 
3ebfedea0SLionel Sambuc /*
4ebfedea0SLionel Sambuc     mpi.c
5ebfedea0SLionel Sambuc 
6ebfedea0SLionel Sambuc     by Michael J. Fromberger <sting@linguist.dartmouth.edu>
7ebfedea0SLionel Sambuc     Copyright (C) 1998 Michael J. Fromberger, All Rights Reserved
8ebfedea0SLionel Sambuc 
9ebfedea0SLionel Sambuc     Arbitrary precision integer arithmetic library
10ebfedea0SLionel Sambuc 
11ebfedea0SLionel Sambuc     Id: mpi.c,v 1.2 2005/05/05 14:38:47 tom Exp
12ebfedea0SLionel Sambuc  */
13ebfedea0SLionel Sambuc 
14ebfedea0SLionel Sambuc #include "mpi.h"
15ebfedea0SLionel Sambuc #include <stdlib.h>
16ebfedea0SLionel Sambuc #include <string.h>
17ebfedea0SLionel Sambuc #include <ctype.h>
18ebfedea0SLionel Sambuc 
19ebfedea0SLionel Sambuc #if MP_DEBUG
20ebfedea0SLionel Sambuc #include <stdio.h>
21ebfedea0SLionel Sambuc 
22ebfedea0SLionel Sambuc #define DIAG(T,V) {fprintf(stderr,T);mp_print(V,stderr);fputc('\n',stderr);}
23ebfedea0SLionel Sambuc #else
24ebfedea0SLionel Sambuc #define DIAG(T,V)
25ebfedea0SLionel Sambuc #endif
26ebfedea0SLionel Sambuc 
27ebfedea0SLionel Sambuc /*
28ebfedea0SLionel Sambuc    If MP_LOGTAB is not defined, use the math library to compute the
29ebfedea0SLionel Sambuc    logarithms on the fly.  Otherwise, use the static table below.
30ebfedea0SLionel Sambuc    Pick which works best for your system.
31ebfedea0SLionel Sambuc  */
32ebfedea0SLionel Sambuc #if MP_LOGTAB
33ebfedea0SLionel Sambuc 
34ebfedea0SLionel Sambuc /* {{{ s_logv_2[] - log table for 2 in various bases */
35ebfedea0SLionel Sambuc 
36ebfedea0SLionel Sambuc /*
37ebfedea0SLionel Sambuc   A table of the logs of 2 for various bases (the 0 and 1 entries of
38ebfedea0SLionel Sambuc   this table are meaningless and should not be referenced).
39ebfedea0SLionel Sambuc 
40ebfedea0SLionel Sambuc   This table is used to compute output lengths for the mp_toradix()
41ebfedea0SLionel Sambuc   function.  Since a number n in radix r takes up about log_r(n)
42ebfedea0SLionel Sambuc   digits, we estimate the output size by taking the least integer
43ebfedea0SLionel Sambuc   greater than log_r(n), where:
44ebfedea0SLionel Sambuc 
45ebfedea0SLionel Sambuc   log_r(n) = log_2(n) * log_r(2)
46ebfedea0SLionel Sambuc 
47ebfedea0SLionel Sambuc   This table, therefore, is a table of log_r(2) for 2 <= r <= 36,
48ebfedea0SLionel Sambuc   which are the output bases supported.
49ebfedea0SLionel Sambuc  */
50ebfedea0SLionel Sambuc 
51ebfedea0SLionel Sambuc #include "logtab.h"
52ebfedea0SLionel Sambuc 
53ebfedea0SLionel Sambuc /* }}} */
54ebfedea0SLionel Sambuc #define LOG_V_2(R)  s_logv_2[(R)]
55ebfedea0SLionel Sambuc 
56ebfedea0SLionel Sambuc #else
57ebfedea0SLionel Sambuc 
58ebfedea0SLionel Sambuc #include <math.h>
59ebfedea0SLionel Sambuc #define LOG_V_2(R)  (log(2.0)/log(R))
60ebfedea0SLionel Sambuc 
61ebfedea0SLionel Sambuc #endif
62ebfedea0SLionel Sambuc 
63ebfedea0SLionel Sambuc /* Default precision for newly created mp_int's      */
64ebfedea0SLionel Sambuc static unsigned int s_mp_defprec = MP_DEFPREC;
65ebfedea0SLionel Sambuc 
66ebfedea0SLionel Sambuc /* {{{ Digit arithmetic macros */
67ebfedea0SLionel Sambuc 
68ebfedea0SLionel Sambuc /*
69ebfedea0SLionel Sambuc   When adding and multiplying digits, the results can be larger than
70ebfedea0SLionel Sambuc   can be contained in an mp_digit.  Thus, an mp_word is used.  These
71ebfedea0SLionel Sambuc   macros mask off the upper and lower digits of the mp_word (the
72ebfedea0SLionel Sambuc   mp_word may be more than 2 mp_digits wide, but we only concern
73ebfedea0SLionel Sambuc   ourselves with the low-order 2 mp_digits)
74ebfedea0SLionel Sambuc 
75ebfedea0SLionel Sambuc   If your mp_word DOES have more than 2 mp_digits, you need to
76ebfedea0SLionel Sambuc   uncomment the first line, and comment out the second.
77ebfedea0SLionel Sambuc  */
78ebfedea0SLionel Sambuc 
79ebfedea0SLionel Sambuc /* #define  CARRYOUT(W)  (((W)>>DIGIT_BIT)&MP_DIGIT_MAX) */
80ebfedea0SLionel Sambuc #define  CARRYOUT(W)  ((W)>>DIGIT_BIT)
81ebfedea0SLionel Sambuc #define  ACCUM(W)     ((W)&MP_DIGIT_MAX)
82ebfedea0SLionel Sambuc 
83ebfedea0SLionel Sambuc /* }}} */
84ebfedea0SLionel Sambuc 
85ebfedea0SLionel Sambuc /* {{{ Comparison constants */
86ebfedea0SLionel Sambuc 
87ebfedea0SLionel Sambuc #define  MP_LT       -1
88ebfedea0SLionel Sambuc #define  MP_EQ        0
89ebfedea0SLionel Sambuc #define  MP_GT        1
90ebfedea0SLionel Sambuc 
91ebfedea0SLionel Sambuc /* }}} */
92ebfedea0SLionel Sambuc 
93ebfedea0SLionel Sambuc /* {{{ Constant strings */
94ebfedea0SLionel Sambuc 
95ebfedea0SLionel Sambuc /* Constant strings returned by mp_strerror() */
96ebfedea0SLionel Sambuc static const char *mp_err_string[] = {
97ebfedea0SLionel Sambuc   "unknown result code",     /* say what?            */
98ebfedea0SLionel Sambuc   "boolean true",            /* MP_OKAY, MP_YES      */
99ebfedea0SLionel Sambuc   "boolean false",           /* MP_NO                */
100ebfedea0SLionel Sambuc   "out of memory",           /* MP_MEM               */
101ebfedea0SLionel Sambuc   "argument out of range",   /* MP_RANGE             */
102ebfedea0SLionel Sambuc   "invalid input parameter", /* MP_BADARG            */
103ebfedea0SLionel Sambuc   "result is undefined"      /* MP_UNDEF             */
104ebfedea0SLionel Sambuc };
105ebfedea0SLionel Sambuc 
106ebfedea0SLionel Sambuc /* Value to digit maps for radix conversion   */
107ebfedea0SLionel Sambuc 
108ebfedea0SLionel Sambuc /* s_dmap_1 - standard digits and letters */
109ebfedea0SLionel Sambuc static const char *s_dmap_1 =
110ebfedea0SLionel Sambuc   "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
111ebfedea0SLionel Sambuc 
112ebfedea0SLionel Sambuc #if 0
113ebfedea0SLionel Sambuc /* s_dmap_2 - base64 ordering for digits  */
114ebfedea0SLionel Sambuc static const char *s_dmap_2 =
115ebfedea0SLionel Sambuc   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
116ebfedea0SLionel Sambuc #endif
117ebfedea0SLionel Sambuc 
118ebfedea0SLionel Sambuc /* }}} */
119ebfedea0SLionel Sambuc 
120ebfedea0SLionel Sambuc /* {{{ Static function declarations */
121ebfedea0SLionel Sambuc 
122ebfedea0SLionel Sambuc /*
123ebfedea0SLionel Sambuc    If MP_MACRO is false, these will be defined as actual functions;
124ebfedea0SLionel Sambuc    otherwise, suitable macro definitions will be used.  This works
125ebfedea0SLionel Sambuc    around the fact that ANSI C89 doesn't support an 'inline' keyword
126ebfedea0SLionel Sambuc    (although I hear C9x will ... about bloody time).  At present, the
127ebfedea0SLionel Sambuc    macro definitions are identical to the function bodies, but they'll
128ebfedea0SLionel Sambuc    expand in place, instead of generating a function call.
129ebfedea0SLionel Sambuc 
130ebfedea0SLionel Sambuc    I chose these particular functions to be made into macros because
131ebfedea0SLionel Sambuc    some profiling showed they are called a lot on a typical workload,
132ebfedea0SLionel Sambuc    and yet they are primarily housekeeping.
133ebfedea0SLionel Sambuc  */
134ebfedea0SLionel Sambuc #if MP_MACRO == 0
135ebfedea0SLionel Sambuc  void     s_mp_setz(mp_digit *dp, mp_size count); /* zero digits           */
136ebfedea0SLionel Sambuc  void     s_mp_copy(mp_digit *sp, mp_digit *dp, mp_size count); /* copy    */
137ebfedea0SLionel Sambuc  void    *s_mp_alloc(size_t nb, size_t ni);       /* general allocator     */
138ebfedea0SLionel Sambuc  void     s_mp_free(void *ptr);                   /* general free function */
139ebfedea0SLionel Sambuc #else
140ebfedea0SLionel Sambuc 
141ebfedea0SLionel Sambuc  /* Even if these are defined as macros, we need to respect the settings
142ebfedea0SLionel Sambuc     of the MP_MEMSET and MP_MEMCPY configuration options...
143ebfedea0SLionel Sambuc   */
144ebfedea0SLionel Sambuc  #if MP_MEMSET == 0
145ebfedea0SLionel Sambuc   #define  s_mp_setz(dp, count) \
146ebfedea0SLionel Sambuc        {int ix;for(ix=0;ix<(count);ix++)(dp)[ix]=0;}
147ebfedea0SLionel Sambuc  #else
148ebfedea0SLionel Sambuc   #define  s_mp_setz(dp, count) memset(dp, 0, (count) * sizeof(mp_digit))
149ebfedea0SLionel Sambuc  #endif /* MP_MEMSET */
150ebfedea0SLionel Sambuc 
151ebfedea0SLionel Sambuc  #if MP_MEMCPY == 0
152ebfedea0SLionel Sambuc   #define  s_mp_copy(sp, dp, count) \
153ebfedea0SLionel Sambuc        {int ix;for(ix=0;ix<(count);ix++)(dp)[ix]=(sp)[ix];}
154ebfedea0SLionel Sambuc  #else
155ebfedea0SLionel Sambuc   #define  s_mp_copy(sp, dp, count) memcpy(dp, sp, (count) * sizeof(mp_digit))
156ebfedea0SLionel Sambuc  #endif /* MP_MEMCPY */
157ebfedea0SLionel Sambuc 
158ebfedea0SLionel Sambuc  #define  s_mp_alloc(nb, ni)  calloc(nb, ni)
159ebfedea0SLionel Sambuc  #define  s_mp_free(ptr) {if(ptr) free(ptr);}
160ebfedea0SLionel Sambuc #endif /* MP_MACRO */
161ebfedea0SLionel Sambuc 
162ebfedea0SLionel Sambuc mp_err   s_mp_grow(mp_int *mp, mp_size min);   /* increase allocated size */
163ebfedea0SLionel Sambuc mp_err   s_mp_pad(mp_int *mp, mp_size min);    /* left pad with zeroes    */
164ebfedea0SLionel Sambuc 
165ebfedea0SLionel Sambuc void     s_mp_clamp(mp_int *mp);               /* clip leading zeroes     */
166ebfedea0SLionel Sambuc 
167ebfedea0SLionel Sambuc void     s_mp_exch(mp_int *a, mp_int *b);      /* swap a and b in place   */
168ebfedea0SLionel Sambuc 
169ebfedea0SLionel Sambuc mp_err   s_mp_lshd(mp_int *mp, mp_size p);     /* left-shift by p digits  */
170ebfedea0SLionel Sambuc void     s_mp_rshd(mp_int *mp, mp_size p);     /* right-shift by p digits */
171ebfedea0SLionel Sambuc void     s_mp_div_2d(mp_int *mp, mp_digit d);  /* divide by 2^d in place  */
172ebfedea0SLionel Sambuc void     s_mp_mod_2d(mp_int *mp, mp_digit d);  /* modulo 2^d in place     */
173ebfedea0SLionel Sambuc mp_err   s_mp_mul_2d(mp_int *mp, mp_digit d);  /* multiply by 2^d in place*/
174ebfedea0SLionel Sambuc void     s_mp_div_2(mp_int *mp);               /* divide by 2 in place    */
175ebfedea0SLionel Sambuc mp_err   s_mp_mul_2(mp_int *mp);               /* multiply by 2 in place  */
176ebfedea0SLionel Sambuc mp_digit s_mp_norm(mp_int *a, mp_int *b);      /* normalize for division  */
177ebfedea0SLionel Sambuc mp_err   s_mp_add_d(mp_int *mp, mp_digit d);   /* unsigned digit addition */
178ebfedea0SLionel Sambuc mp_err   s_mp_sub_d(mp_int *mp, mp_digit d);   /* unsigned digit subtract */
179ebfedea0SLionel Sambuc mp_err   s_mp_mul_d(mp_int *mp, mp_digit d);   /* unsigned digit multiply */
180ebfedea0SLionel Sambuc mp_err   s_mp_div_d(mp_int *mp, mp_digit d, mp_digit *r);
181ebfedea0SLionel Sambuc 		                               /* unsigned digit divide   */
182ebfedea0SLionel Sambuc mp_err   s_mp_reduce(mp_int *x, mp_int *m, mp_int *mu);
183ebfedea0SLionel Sambuc                                                /* Barrett reduction       */
184ebfedea0SLionel Sambuc mp_err   s_mp_add(mp_int *a, mp_int *b);       /* magnitude addition      */
185ebfedea0SLionel Sambuc mp_err   s_mp_sub(mp_int *a, mp_int *b);       /* magnitude subtract      */
186ebfedea0SLionel Sambuc mp_err   s_mp_mul(mp_int *a, mp_int *b);       /* magnitude multiply      */
187ebfedea0SLionel Sambuc #if 0
188ebfedea0SLionel Sambuc void     s_mp_kmul(mp_digit *a, mp_digit *b, mp_digit *out, mp_size len);
189ebfedea0SLionel Sambuc                                                /* multiply buffers in place */
190ebfedea0SLionel Sambuc #endif
191ebfedea0SLionel Sambuc #if MP_SQUARE
192ebfedea0SLionel Sambuc mp_err   s_mp_sqr(mp_int *a);                  /* magnitude square        */
193ebfedea0SLionel Sambuc #else
194ebfedea0SLionel Sambuc #define  s_mp_sqr(a) s_mp_mul(a, a)
195ebfedea0SLionel Sambuc #endif
196ebfedea0SLionel Sambuc mp_err   s_mp_div(mp_int *a, mp_int *b);       /* magnitude divide        */
197ebfedea0SLionel Sambuc mp_err   s_mp_2expt(mp_int *a, mp_digit k);    /* a = 2^k                 */
198ebfedea0SLionel Sambuc int      s_mp_cmp(mp_int *a, mp_int *b);       /* magnitude comparison    */
199ebfedea0SLionel Sambuc int      s_mp_cmp_d(mp_int *a, mp_digit d);    /* magnitude digit compare */
200ebfedea0SLionel Sambuc int      s_mp_ispow2(mp_int *v);               /* is v a power of 2?      */
201ebfedea0SLionel Sambuc int      s_mp_ispow2d(mp_digit d);             /* is d a power of 2?      */
202ebfedea0SLionel Sambuc 
203ebfedea0SLionel Sambuc int      s_mp_tovalue(char ch, int r);          /* convert ch to value    */
204ebfedea0SLionel Sambuc char     s_mp_todigit(int val, int r, int low); /* convert val to digit   */
205ebfedea0SLionel Sambuc int      s_mp_outlen(int bits, int r);          /* output length in bytes */
206ebfedea0SLionel Sambuc 
207ebfedea0SLionel Sambuc /* }}} */
208ebfedea0SLionel Sambuc 
209ebfedea0SLionel Sambuc /* {{{ Default precision manipulation */
210ebfedea0SLionel Sambuc 
mp_get_prec(void)211ebfedea0SLionel Sambuc unsigned int mp_get_prec(void)
212ebfedea0SLionel Sambuc {
213ebfedea0SLionel Sambuc   return s_mp_defprec;
214ebfedea0SLionel Sambuc 
215ebfedea0SLionel Sambuc } /* end mp_get_prec() */
216ebfedea0SLionel Sambuc 
mp_set_prec(unsigned int prec)217ebfedea0SLionel Sambuc void         mp_set_prec(unsigned int prec)
218ebfedea0SLionel Sambuc {
219ebfedea0SLionel Sambuc   if(prec == 0)
220ebfedea0SLionel Sambuc     s_mp_defprec = MP_DEFPREC;
221ebfedea0SLionel Sambuc   else
222ebfedea0SLionel Sambuc     s_mp_defprec = prec;
223ebfedea0SLionel Sambuc 
224ebfedea0SLionel Sambuc } /* end mp_set_prec() */
225ebfedea0SLionel Sambuc 
226ebfedea0SLionel Sambuc /* }}} */
227ebfedea0SLionel Sambuc 
228ebfedea0SLionel Sambuc /*------------------------------------------------------------------------*/
229ebfedea0SLionel Sambuc /* {{{ mp_init(mp) */
230ebfedea0SLionel Sambuc 
231ebfedea0SLionel Sambuc /*
232ebfedea0SLionel Sambuc   mp_init(mp)
233ebfedea0SLionel Sambuc 
234ebfedea0SLionel Sambuc   Initialize a new zero-valued mp_int.  Returns MP_OKAY if successful,
235ebfedea0SLionel Sambuc   MP_MEM if memory could not be allocated for the structure.
236ebfedea0SLionel Sambuc  */
237ebfedea0SLionel Sambuc 
mp_init(mp_int * mp)238ebfedea0SLionel Sambuc mp_err mp_init(mp_int *mp)
239ebfedea0SLionel Sambuc {
240ebfedea0SLionel Sambuc   return mp_init_size(mp, s_mp_defprec);
241ebfedea0SLionel Sambuc 
242ebfedea0SLionel Sambuc } /* end mp_init() */
243ebfedea0SLionel Sambuc 
244ebfedea0SLionel Sambuc /* }}} */
245ebfedea0SLionel Sambuc 
246ebfedea0SLionel Sambuc /* {{{ mp_init_array(mp[], count) */
247ebfedea0SLionel Sambuc 
mp_init_array(mp_int mp[],int count)248ebfedea0SLionel Sambuc mp_err mp_init_array(mp_int mp[], int count)
249ebfedea0SLionel Sambuc {
250ebfedea0SLionel Sambuc   mp_err  res;
251ebfedea0SLionel Sambuc   int     pos;
252ebfedea0SLionel Sambuc 
253ebfedea0SLionel Sambuc   ARGCHK(mp !=NULL && count > 0, MP_BADARG);
254ebfedea0SLionel Sambuc 
255ebfedea0SLionel Sambuc   for(pos = 0; pos < count; ++pos) {
256ebfedea0SLionel Sambuc     if((res = mp_init(&mp[pos])) != MP_OKAY)
257ebfedea0SLionel Sambuc       goto CLEANUP;
258ebfedea0SLionel Sambuc   }
259ebfedea0SLionel Sambuc 
260ebfedea0SLionel Sambuc   return MP_OKAY;
261ebfedea0SLionel Sambuc 
262ebfedea0SLionel Sambuc  CLEANUP:
263ebfedea0SLionel Sambuc   while(--pos >= 0)
264ebfedea0SLionel Sambuc     mp_clear(&mp[pos]);
265ebfedea0SLionel Sambuc 
266ebfedea0SLionel Sambuc   return res;
267ebfedea0SLionel Sambuc 
268ebfedea0SLionel Sambuc } /* end mp_init_array() */
269ebfedea0SLionel Sambuc 
270ebfedea0SLionel Sambuc /* }}} */
271ebfedea0SLionel Sambuc 
272ebfedea0SLionel Sambuc /* {{{ mp_init_size(mp, prec) */
273ebfedea0SLionel Sambuc 
274ebfedea0SLionel Sambuc /*
275ebfedea0SLionel Sambuc   mp_init_size(mp, prec)
276ebfedea0SLionel Sambuc 
277ebfedea0SLionel Sambuc   Initialize a new zero-valued mp_int with at least the given
278ebfedea0SLionel Sambuc   precision; returns MP_OKAY if successful, or MP_MEM if memory could
279ebfedea0SLionel Sambuc   not be allocated for the structure.
280ebfedea0SLionel Sambuc  */
281ebfedea0SLionel Sambuc 
mp_init_size(mp_int * mp,mp_size prec)282ebfedea0SLionel Sambuc mp_err mp_init_size(mp_int *mp, mp_size prec)
283ebfedea0SLionel Sambuc {
284ebfedea0SLionel Sambuc   ARGCHK(mp != NULL && prec > 0, MP_BADARG);
285ebfedea0SLionel Sambuc 
286ebfedea0SLionel Sambuc   if((DIGITS(mp) = s_mp_alloc(prec, sizeof(mp_digit))) == NULL)
287ebfedea0SLionel Sambuc     return MP_MEM;
288ebfedea0SLionel Sambuc 
289ebfedea0SLionel Sambuc   SIGN(mp) = MP_ZPOS;
290ebfedea0SLionel Sambuc   USED(mp) = 1;
291ebfedea0SLionel Sambuc   ALLOC(mp) = prec;
292ebfedea0SLionel Sambuc 
293ebfedea0SLionel Sambuc   return MP_OKAY;
294ebfedea0SLionel Sambuc 
295ebfedea0SLionel Sambuc } /* end mp_init_size() */
296ebfedea0SLionel Sambuc 
297ebfedea0SLionel Sambuc /* }}} */
298ebfedea0SLionel Sambuc 
299ebfedea0SLionel Sambuc /* {{{ mp_init_copy(mp, from) */
300ebfedea0SLionel Sambuc 
301ebfedea0SLionel Sambuc /*
302ebfedea0SLionel Sambuc   mp_init_copy(mp, from)
303ebfedea0SLionel Sambuc 
304ebfedea0SLionel Sambuc   Initialize mp as an exact copy of from.  Returns MP_OKAY if
305ebfedea0SLionel Sambuc   successful, MP_MEM if memory could not be allocated for the new
306ebfedea0SLionel Sambuc   structure.
307ebfedea0SLionel Sambuc  */
308ebfedea0SLionel Sambuc 
mp_init_copy(mp_int * mp,mp_int * from)309ebfedea0SLionel Sambuc mp_err mp_init_copy(mp_int *mp, mp_int *from)
310ebfedea0SLionel Sambuc {
311ebfedea0SLionel Sambuc   ARGCHK(mp != NULL && from != NULL, MP_BADARG);
312ebfedea0SLionel Sambuc 
313ebfedea0SLionel Sambuc   if(mp == from)
314ebfedea0SLionel Sambuc     return MP_OKAY;
315ebfedea0SLionel Sambuc 
316ebfedea0SLionel Sambuc   if((DIGITS(mp) = s_mp_alloc(USED(from), sizeof(mp_digit))) == NULL)
317ebfedea0SLionel Sambuc     return MP_MEM;
318ebfedea0SLionel Sambuc 
319ebfedea0SLionel Sambuc   s_mp_copy(DIGITS(from), DIGITS(mp), USED(from));
320ebfedea0SLionel Sambuc   USED(mp) = USED(from);
321ebfedea0SLionel Sambuc   ALLOC(mp) = USED(from);
322ebfedea0SLionel Sambuc   SIGN(mp) = SIGN(from);
323ebfedea0SLionel Sambuc 
324ebfedea0SLionel Sambuc   return MP_OKAY;
325ebfedea0SLionel Sambuc 
326ebfedea0SLionel Sambuc } /* end mp_init_copy() */
327ebfedea0SLionel Sambuc 
328ebfedea0SLionel Sambuc /* }}} */
329ebfedea0SLionel Sambuc 
330ebfedea0SLionel Sambuc /* {{{ mp_copy(from, to) */
331ebfedea0SLionel Sambuc 
332ebfedea0SLionel Sambuc /*
333ebfedea0SLionel Sambuc   mp_copy(from, to)
334ebfedea0SLionel Sambuc 
335ebfedea0SLionel Sambuc   Copies the mp_int 'from' to the mp_int 'to'.  It is presumed that
336ebfedea0SLionel Sambuc   'to' has already been initialized (if not, use mp_init_copy()
337ebfedea0SLionel Sambuc   instead). If 'from' and 'to' are identical, nothing happens.
338ebfedea0SLionel Sambuc  */
339ebfedea0SLionel Sambuc 
mp_copy(mp_int * from,mp_int * to)340ebfedea0SLionel Sambuc mp_err mp_copy(mp_int *from, mp_int *to)
341ebfedea0SLionel Sambuc {
342ebfedea0SLionel Sambuc   ARGCHK(from != NULL && to != NULL, MP_BADARG);
343ebfedea0SLionel Sambuc 
344ebfedea0SLionel Sambuc   if(from == to)
345ebfedea0SLionel Sambuc     return MP_OKAY;
346ebfedea0SLionel Sambuc 
347ebfedea0SLionel Sambuc   { /* copy */
348ebfedea0SLionel Sambuc     mp_digit   *tmp;
349ebfedea0SLionel Sambuc 
350ebfedea0SLionel Sambuc     /*
351ebfedea0SLionel Sambuc       If the allocated buffer in 'to' already has enough space to hold
352ebfedea0SLionel Sambuc       all the used digits of 'from', we'll re-use it to avoid hitting
353ebfedea0SLionel Sambuc       the memory allocater more than necessary; otherwise, we'd have
354ebfedea0SLionel Sambuc       to grow anyway, so we just allocate a hunk and make the copy as
355ebfedea0SLionel Sambuc       usual
356ebfedea0SLionel Sambuc      */
357ebfedea0SLionel Sambuc     if(ALLOC(to) >= USED(from)) {
358ebfedea0SLionel Sambuc       s_mp_setz(DIGITS(to) + USED(from), ALLOC(to) - USED(from));
359ebfedea0SLionel Sambuc       s_mp_copy(DIGITS(from), DIGITS(to), USED(from));
360ebfedea0SLionel Sambuc 
361ebfedea0SLionel Sambuc     } else {
362ebfedea0SLionel Sambuc       if((tmp = s_mp_alloc(USED(from), sizeof(mp_digit))) == NULL)
363ebfedea0SLionel Sambuc 	return MP_MEM;
364ebfedea0SLionel Sambuc 
365ebfedea0SLionel Sambuc       s_mp_copy(DIGITS(from), tmp, USED(from));
366ebfedea0SLionel Sambuc 
367ebfedea0SLionel Sambuc       if(DIGITS(to) != NULL) {
368ebfedea0SLionel Sambuc #if MP_CRYPTO
369ebfedea0SLionel Sambuc 	s_mp_setz(DIGITS(to), ALLOC(to));
370ebfedea0SLionel Sambuc #endif
371ebfedea0SLionel Sambuc 	s_mp_free(DIGITS(to));
372ebfedea0SLionel Sambuc       }
373ebfedea0SLionel Sambuc 
374ebfedea0SLionel Sambuc       DIGITS(to) = tmp;
375ebfedea0SLionel Sambuc       ALLOC(to) = USED(from);
376ebfedea0SLionel Sambuc     }
377ebfedea0SLionel Sambuc 
378ebfedea0SLionel Sambuc     /* Copy the precision and sign from the original */
379ebfedea0SLionel Sambuc     USED(to) = USED(from);
380ebfedea0SLionel Sambuc     SIGN(to) = SIGN(from);
381ebfedea0SLionel Sambuc   } /* end copy */
382ebfedea0SLionel Sambuc 
383ebfedea0SLionel Sambuc   return MP_OKAY;
384ebfedea0SLionel Sambuc 
385ebfedea0SLionel Sambuc } /* end mp_copy() */
386ebfedea0SLionel Sambuc 
387ebfedea0SLionel Sambuc /* }}} */
388ebfedea0SLionel Sambuc 
389ebfedea0SLionel Sambuc /* {{{ mp_exch(mp1, mp2) */
390ebfedea0SLionel Sambuc 
391ebfedea0SLionel Sambuc /*
392ebfedea0SLionel Sambuc   mp_exch(mp1, mp2)
393ebfedea0SLionel Sambuc 
394ebfedea0SLionel Sambuc   Exchange mp1 and mp2 without allocating any intermediate memory
395ebfedea0SLionel Sambuc   (well, unless you count the stack space needed for this call and the
396ebfedea0SLionel Sambuc   locals it creates...).  This cannot fail.
397ebfedea0SLionel Sambuc  */
398ebfedea0SLionel Sambuc 
mp_exch(mp_int * mp1,mp_int * mp2)399ebfedea0SLionel Sambuc void mp_exch(mp_int *mp1, mp_int *mp2)
400ebfedea0SLionel Sambuc {
401ebfedea0SLionel Sambuc #if MP_ARGCHK == 2
402ebfedea0SLionel Sambuc   assert(mp1 != NULL && mp2 != NULL);
403ebfedea0SLionel Sambuc #else
404ebfedea0SLionel Sambuc   if(mp1 == NULL || mp2 == NULL)
405ebfedea0SLionel Sambuc     return;
406ebfedea0SLionel Sambuc #endif
407ebfedea0SLionel Sambuc 
408ebfedea0SLionel Sambuc   s_mp_exch(mp1, mp2);
409ebfedea0SLionel Sambuc 
410ebfedea0SLionel Sambuc } /* end mp_exch() */
411ebfedea0SLionel Sambuc 
412ebfedea0SLionel Sambuc /* }}} */
413ebfedea0SLionel Sambuc 
414ebfedea0SLionel Sambuc /* {{{ mp_clear(mp) */
415ebfedea0SLionel Sambuc 
416ebfedea0SLionel Sambuc /*
417ebfedea0SLionel Sambuc   mp_clear(mp)
418ebfedea0SLionel Sambuc 
419ebfedea0SLionel Sambuc   Release the storage used by an mp_int, and void its fields so that
420ebfedea0SLionel Sambuc   if someone calls mp_clear() again for the same int later, we won't
421ebfedea0SLionel Sambuc   get tollchocked.
422ebfedea0SLionel Sambuc  */
423ebfedea0SLionel Sambuc 
mp_clear(mp_int * mp)424ebfedea0SLionel Sambuc void   mp_clear(mp_int *mp)
425ebfedea0SLionel Sambuc {
426ebfedea0SLionel Sambuc   if(mp == NULL)
427ebfedea0SLionel Sambuc     return;
428ebfedea0SLionel Sambuc 
429ebfedea0SLionel Sambuc   if(DIGITS(mp) != NULL) {
430ebfedea0SLionel Sambuc #if MP_CRYPTO
431ebfedea0SLionel Sambuc     s_mp_setz(DIGITS(mp), ALLOC(mp));
432ebfedea0SLionel Sambuc #endif
433ebfedea0SLionel Sambuc     s_mp_free(DIGITS(mp));
434ebfedea0SLionel Sambuc     DIGITS(mp) = NULL;
435ebfedea0SLionel Sambuc   }
436ebfedea0SLionel Sambuc 
437ebfedea0SLionel Sambuc   USED(mp) = 0;
438ebfedea0SLionel Sambuc   ALLOC(mp) = 0;
439ebfedea0SLionel Sambuc 
440ebfedea0SLionel Sambuc } /* end mp_clear() */
441ebfedea0SLionel Sambuc 
442ebfedea0SLionel Sambuc /* }}} */
443ebfedea0SLionel Sambuc 
444ebfedea0SLionel Sambuc /* {{{ mp_clear_array(mp[], count) */
445ebfedea0SLionel Sambuc 
mp_clear_array(mp_int mp[],int count)446ebfedea0SLionel Sambuc void   mp_clear_array(mp_int mp[], int count)
447ebfedea0SLionel Sambuc {
448ebfedea0SLionel Sambuc   ARGCHK(mp != NULL && count > 0, MP_BADARG);
449ebfedea0SLionel Sambuc 
450ebfedea0SLionel Sambuc   while(--count >= 0)
451ebfedea0SLionel Sambuc     mp_clear(&mp[count]);
452ebfedea0SLionel Sambuc 
453ebfedea0SLionel Sambuc } /* end mp_clear_array() */
454ebfedea0SLionel Sambuc 
455ebfedea0SLionel Sambuc /* }}} */
456ebfedea0SLionel Sambuc 
457ebfedea0SLionel Sambuc /* {{{ mp_zero(mp) */
458ebfedea0SLionel Sambuc 
459ebfedea0SLionel Sambuc /*
460ebfedea0SLionel Sambuc   mp_zero(mp)
461ebfedea0SLionel Sambuc 
462ebfedea0SLionel Sambuc   Set mp to zero.  Does not change the allocated size of the structure,
463ebfedea0SLionel Sambuc   and therefore cannot fail (except on a bad argument, which we ignore)
464ebfedea0SLionel Sambuc  */
mp_zero(mp_int * mp)465ebfedea0SLionel Sambuc void   mp_zero(mp_int *mp)
466ebfedea0SLionel Sambuc {
467ebfedea0SLionel Sambuc   if(mp == NULL)
468ebfedea0SLionel Sambuc     return;
469ebfedea0SLionel Sambuc 
470ebfedea0SLionel Sambuc   s_mp_setz(DIGITS(mp), ALLOC(mp));
471ebfedea0SLionel Sambuc   USED(mp) = 1;
472ebfedea0SLionel Sambuc   SIGN(mp) = MP_ZPOS;
473ebfedea0SLionel Sambuc 
474ebfedea0SLionel Sambuc } /* end mp_zero() */
475ebfedea0SLionel Sambuc 
476ebfedea0SLionel Sambuc /* }}} */
477ebfedea0SLionel Sambuc 
478ebfedea0SLionel Sambuc /* {{{ mp_set(mp, d) */
479ebfedea0SLionel Sambuc 
mp_set(mp_int * mp,mp_digit d)480ebfedea0SLionel Sambuc void   mp_set(mp_int *mp, mp_digit d)
481ebfedea0SLionel Sambuc {
482ebfedea0SLionel Sambuc   if(mp == NULL)
483ebfedea0SLionel Sambuc     return;
484ebfedea0SLionel Sambuc 
485ebfedea0SLionel Sambuc   mp_zero(mp);
486ebfedea0SLionel Sambuc   DIGIT(mp, 0) = d;
487ebfedea0SLionel Sambuc 
488ebfedea0SLionel Sambuc } /* end mp_set() */
489ebfedea0SLionel Sambuc 
490ebfedea0SLionel Sambuc /* }}} */
491ebfedea0SLionel Sambuc 
492ebfedea0SLionel Sambuc /* {{{ mp_set_int(mp, z) */
493ebfedea0SLionel Sambuc 
mp_set_int(mp_int * mp,long z)494ebfedea0SLionel Sambuc mp_err mp_set_int(mp_int *mp, long z)
495ebfedea0SLionel Sambuc {
496ebfedea0SLionel Sambuc   int            ix;
497ebfedea0SLionel Sambuc   unsigned long  v = abs(z);
498ebfedea0SLionel Sambuc   mp_err         res;
499ebfedea0SLionel Sambuc 
500ebfedea0SLionel Sambuc   ARGCHK(mp != NULL, MP_BADARG);
501ebfedea0SLionel Sambuc 
502ebfedea0SLionel Sambuc   mp_zero(mp);
503ebfedea0SLionel Sambuc   if(z == 0)
504ebfedea0SLionel Sambuc     return MP_OKAY;  /* shortcut for zero */
505ebfedea0SLionel Sambuc 
506ebfedea0SLionel Sambuc   for(ix = sizeof(long) - 1; ix >= 0; ix--) {
507ebfedea0SLionel Sambuc 
508ebfedea0SLionel Sambuc     if((res = s_mp_mul_2d(mp, CHAR_BIT)) != MP_OKAY)
509ebfedea0SLionel Sambuc       return res;
510ebfedea0SLionel Sambuc 
511ebfedea0SLionel Sambuc     res = s_mp_add_d(mp,
512ebfedea0SLionel Sambuc 		     (mp_digit)((v >> (ix * CHAR_BIT)) & UCHAR_MAX));
513ebfedea0SLionel Sambuc     if(res != MP_OKAY)
514ebfedea0SLionel Sambuc       return res;
515ebfedea0SLionel Sambuc 
516ebfedea0SLionel Sambuc   }
517ebfedea0SLionel Sambuc 
518ebfedea0SLionel Sambuc   if(z < 0)
519ebfedea0SLionel Sambuc     SIGN(mp) = MP_NEG;
520ebfedea0SLionel Sambuc 
521ebfedea0SLionel Sambuc   return MP_OKAY;
522ebfedea0SLionel Sambuc 
523ebfedea0SLionel Sambuc } /* end mp_set_int() */
524ebfedea0SLionel Sambuc 
525ebfedea0SLionel Sambuc /* }}} */
526ebfedea0SLionel Sambuc 
527ebfedea0SLionel Sambuc /*------------------------------------------------------------------------*/
528ebfedea0SLionel Sambuc /* {{{ Digit arithmetic */
529ebfedea0SLionel Sambuc 
530ebfedea0SLionel Sambuc /* {{{ mp_add_d(a, d, b) */
531ebfedea0SLionel Sambuc 
532ebfedea0SLionel Sambuc /*
533ebfedea0SLionel Sambuc   mp_add_d(a, d, b)
534ebfedea0SLionel Sambuc 
535ebfedea0SLionel Sambuc   Compute the sum b = a + d, for a single digit d.  Respects the sign of
536ebfedea0SLionel Sambuc   its primary addend (single digits are unsigned anyway).
537ebfedea0SLionel Sambuc  */
538ebfedea0SLionel Sambuc 
mp_add_d(mp_int * a,mp_digit d,mp_int * b)539ebfedea0SLionel Sambuc mp_err mp_add_d(mp_int *a, mp_digit d, mp_int *b)
540ebfedea0SLionel Sambuc {
541ebfedea0SLionel Sambuc   mp_err   res = MP_OKAY;
542ebfedea0SLionel Sambuc 
543ebfedea0SLionel Sambuc   ARGCHK(a != NULL && b != NULL, MP_BADARG);
544ebfedea0SLionel Sambuc 
545ebfedea0SLionel Sambuc   if((res = mp_copy(a, b)) != MP_OKAY)
546ebfedea0SLionel Sambuc     return res;
547ebfedea0SLionel Sambuc 
548ebfedea0SLionel Sambuc   if(SIGN(b) == MP_ZPOS) {
549ebfedea0SLionel Sambuc     res = s_mp_add_d(b, d);
550ebfedea0SLionel Sambuc   } else if(s_mp_cmp_d(b, d) >= 0) {
551ebfedea0SLionel Sambuc     res = s_mp_sub_d(b, d);
552ebfedea0SLionel Sambuc   } else {
553ebfedea0SLionel Sambuc     SIGN(b) = MP_ZPOS;
554ebfedea0SLionel Sambuc 
555ebfedea0SLionel Sambuc     DIGIT(b, 0) = d - DIGIT(b, 0);
556ebfedea0SLionel Sambuc   }
557ebfedea0SLionel Sambuc 
558ebfedea0SLionel Sambuc   return res;
559ebfedea0SLionel Sambuc 
560ebfedea0SLionel Sambuc } /* end mp_add_d() */
561ebfedea0SLionel Sambuc 
562ebfedea0SLionel Sambuc /* }}} */
563ebfedea0SLionel Sambuc 
564ebfedea0SLionel Sambuc /* {{{ mp_sub_d(a, d, b) */
565ebfedea0SLionel Sambuc 
566ebfedea0SLionel Sambuc /*
567ebfedea0SLionel Sambuc   mp_sub_d(a, d, b)
568ebfedea0SLionel Sambuc 
569ebfedea0SLionel Sambuc   Compute the difference b = a - d, for a single digit d.  Respects the
570ebfedea0SLionel Sambuc   sign of its subtrahend (single digits are unsigned anyway).
571ebfedea0SLionel Sambuc  */
572ebfedea0SLionel Sambuc 
mp_sub_d(mp_int * a,mp_digit d,mp_int * b)573ebfedea0SLionel Sambuc mp_err mp_sub_d(mp_int *a, mp_digit d, mp_int *b)
574ebfedea0SLionel Sambuc {
575ebfedea0SLionel Sambuc   mp_err   res;
576ebfedea0SLionel Sambuc 
577ebfedea0SLionel Sambuc   ARGCHK(a != NULL && b != NULL, MP_BADARG);
578ebfedea0SLionel Sambuc 
579ebfedea0SLionel Sambuc   if((res = mp_copy(a, b)) != MP_OKAY)
580ebfedea0SLionel Sambuc     return res;
581ebfedea0SLionel Sambuc 
582ebfedea0SLionel Sambuc   if(SIGN(b) == MP_NEG) {
583ebfedea0SLionel Sambuc     if((res = s_mp_add_d(b, d)) != MP_OKAY)
584ebfedea0SLionel Sambuc       return res;
585ebfedea0SLionel Sambuc 
586ebfedea0SLionel Sambuc   } else if(s_mp_cmp_d(b, d) >= 0) {
587ebfedea0SLionel Sambuc     if((res = s_mp_sub_d(b, d)) != MP_OKAY)
588ebfedea0SLionel Sambuc       return res;
589ebfedea0SLionel Sambuc 
590ebfedea0SLionel Sambuc   } else {
591ebfedea0SLionel Sambuc     mp_neg(b, b);
592ebfedea0SLionel Sambuc 
593ebfedea0SLionel Sambuc     DIGIT(b, 0) = d - DIGIT(b, 0);
594ebfedea0SLionel Sambuc     SIGN(b) = MP_NEG;
595ebfedea0SLionel Sambuc   }
596ebfedea0SLionel Sambuc 
597ebfedea0SLionel Sambuc   if(s_mp_cmp_d(b, 0) == 0)
598ebfedea0SLionel Sambuc     SIGN(b) = MP_ZPOS;
599ebfedea0SLionel Sambuc 
600ebfedea0SLionel Sambuc   return MP_OKAY;
601ebfedea0SLionel Sambuc 
602ebfedea0SLionel Sambuc } /* end mp_sub_d() */
603ebfedea0SLionel Sambuc 
604ebfedea0SLionel Sambuc /* }}} */
605ebfedea0SLionel Sambuc 
606ebfedea0SLionel Sambuc /* {{{ mp_mul_d(a, d, b) */
607ebfedea0SLionel Sambuc 
608ebfedea0SLionel Sambuc /*
609ebfedea0SLionel Sambuc   mp_mul_d(a, d, b)
610ebfedea0SLionel Sambuc 
611ebfedea0SLionel Sambuc   Compute the product b = a * d, for a single digit d.  Respects the sign
612ebfedea0SLionel Sambuc   of its multiplicand (single digits are unsigned anyway)
613ebfedea0SLionel Sambuc  */
614ebfedea0SLionel Sambuc 
mp_mul_d(mp_int * a,mp_digit d,mp_int * b)615ebfedea0SLionel Sambuc mp_err mp_mul_d(mp_int *a, mp_digit d, mp_int *b)
616ebfedea0SLionel Sambuc {
617ebfedea0SLionel Sambuc   mp_err  res;
618ebfedea0SLionel Sambuc 
619ebfedea0SLionel Sambuc   ARGCHK(a != NULL && b != NULL, MP_BADARG);
620ebfedea0SLionel Sambuc 
621ebfedea0SLionel Sambuc   if(d == 0) {
622ebfedea0SLionel Sambuc     mp_zero(b);
623ebfedea0SLionel Sambuc     return MP_OKAY;
624ebfedea0SLionel Sambuc   }
625ebfedea0SLionel Sambuc 
626ebfedea0SLionel Sambuc   if((res = mp_copy(a, b)) != MP_OKAY)
627ebfedea0SLionel Sambuc     return res;
628ebfedea0SLionel Sambuc 
629ebfedea0SLionel Sambuc   res = s_mp_mul_d(b, d);
630ebfedea0SLionel Sambuc 
631ebfedea0SLionel Sambuc   return res;
632ebfedea0SLionel Sambuc 
633ebfedea0SLionel Sambuc } /* end mp_mul_d() */
634ebfedea0SLionel Sambuc 
635ebfedea0SLionel Sambuc /* }}} */
636ebfedea0SLionel Sambuc 
637ebfedea0SLionel Sambuc /* {{{ mp_mul_2(a, c) */
638ebfedea0SLionel Sambuc 
mp_mul_2(mp_int * a,mp_int * c)639ebfedea0SLionel Sambuc mp_err mp_mul_2(mp_int *a, mp_int *c)
640ebfedea0SLionel Sambuc {
641ebfedea0SLionel Sambuc   mp_err  res;
642ebfedea0SLionel Sambuc 
643ebfedea0SLionel Sambuc   ARGCHK(a != NULL && c != NULL, MP_BADARG);
644ebfedea0SLionel Sambuc 
645ebfedea0SLionel Sambuc   if((res = mp_copy(a, c)) != MP_OKAY)
646ebfedea0SLionel Sambuc     return res;
647ebfedea0SLionel Sambuc 
648ebfedea0SLionel Sambuc   return s_mp_mul_2(c);
649ebfedea0SLionel Sambuc 
650ebfedea0SLionel Sambuc } /* end mp_mul_2() */
651ebfedea0SLionel Sambuc 
652ebfedea0SLionel Sambuc /* }}} */
653ebfedea0SLionel Sambuc 
654ebfedea0SLionel Sambuc /* {{{ mp_div_d(a, d, q, r) */
655ebfedea0SLionel Sambuc 
656ebfedea0SLionel Sambuc /*
657ebfedea0SLionel Sambuc   mp_div_d(a, d, q, r)
658ebfedea0SLionel Sambuc 
659ebfedea0SLionel Sambuc   Compute the quotient q = a / d and remainder r = a mod d, for a
660ebfedea0SLionel Sambuc   single digit d.  Respects the sign of its divisor (single digits are
661ebfedea0SLionel Sambuc   unsigned anyway).
662ebfedea0SLionel Sambuc  */
663ebfedea0SLionel Sambuc 
mp_div_d(mp_int * a,mp_digit d,mp_int * q,mp_digit * r)664ebfedea0SLionel Sambuc mp_err mp_div_d(mp_int *a, mp_digit d, mp_int *q, mp_digit *r)
665ebfedea0SLionel Sambuc {
666ebfedea0SLionel Sambuc   mp_err   res;
667ebfedea0SLionel Sambuc   mp_digit rem;
668ebfedea0SLionel Sambuc   int      pow;
669ebfedea0SLionel Sambuc 
670ebfedea0SLionel Sambuc   ARGCHK(a != NULL, MP_BADARG);
671ebfedea0SLionel Sambuc 
672ebfedea0SLionel Sambuc   if(d == 0)
673ebfedea0SLionel Sambuc     return MP_RANGE;
674ebfedea0SLionel Sambuc 
675ebfedea0SLionel Sambuc   /* Shortcut for powers of two ... */
676ebfedea0SLionel Sambuc   if((pow = s_mp_ispow2d(d)) >= 0) {
677ebfedea0SLionel Sambuc     mp_digit  mask;
678ebfedea0SLionel Sambuc 
679ebfedea0SLionel Sambuc     mask = (1 << pow) - 1;
680ebfedea0SLionel Sambuc     rem = DIGIT(a, 0) & mask;
681ebfedea0SLionel Sambuc 
682ebfedea0SLionel Sambuc     if(q) {
683ebfedea0SLionel Sambuc       mp_copy(a, q);
684ebfedea0SLionel Sambuc       s_mp_div_2d(q, pow);
685ebfedea0SLionel Sambuc     }
686ebfedea0SLionel Sambuc 
687ebfedea0SLionel Sambuc     if(r)
688ebfedea0SLionel Sambuc       *r = rem;
689ebfedea0SLionel Sambuc 
690ebfedea0SLionel Sambuc     return MP_OKAY;
691ebfedea0SLionel Sambuc   }
692ebfedea0SLionel Sambuc 
693ebfedea0SLionel Sambuc   /*
694ebfedea0SLionel Sambuc     If the quotient is actually going to be returned, we'll try to
695ebfedea0SLionel Sambuc     avoid hitting the memory allocator by copying the dividend into it
696ebfedea0SLionel Sambuc     and doing the division there.  This can't be any _worse_ than
697ebfedea0SLionel Sambuc     always copying, and will sometimes be better (since it won't make
698ebfedea0SLionel Sambuc     another copy)
699ebfedea0SLionel Sambuc 
700ebfedea0SLionel Sambuc     If it's not going to be returned, we need to allocate a temporary
701ebfedea0SLionel Sambuc     to hold the quotient, which will just be discarded.
702ebfedea0SLionel Sambuc    */
703ebfedea0SLionel Sambuc   if(q) {
704ebfedea0SLionel Sambuc     if((res = mp_copy(a, q)) != MP_OKAY)
705ebfedea0SLionel Sambuc       return res;
706ebfedea0SLionel Sambuc 
707ebfedea0SLionel Sambuc     res = s_mp_div_d(q, d, &rem);
708ebfedea0SLionel Sambuc     if(s_mp_cmp_d(q, 0) == MP_EQ)
709ebfedea0SLionel Sambuc       SIGN(q) = MP_ZPOS;
710ebfedea0SLionel Sambuc 
711ebfedea0SLionel Sambuc   } else {
712ebfedea0SLionel Sambuc     mp_int  qp;
713ebfedea0SLionel Sambuc 
714ebfedea0SLionel Sambuc     if((res = mp_init_copy(&qp, a)) != MP_OKAY)
715ebfedea0SLionel Sambuc       return res;
716ebfedea0SLionel Sambuc 
717ebfedea0SLionel Sambuc     res = s_mp_div_d(&qp, d, &rem);
718ebfedea0SLionel Sambuc     if(s_mp_cmp_d(&qp, 0) == 0)
719ebfedea0SLionel Sambuc       SIGN(&qp) = MP_ZPOS;
720ebfedea0SLionel Sambuc 
721ebfedea0SLionel Sambuc     mp_clear(&qp);
722ebfedea0SLionel Sambuc   }
723ebfedea0SLionel Sambuc 
724ebfedea0SLionel Sambuc   if(r)
725ebfedea0SLionel Sambuc     *r = rem;
726ebfedea0SLionel Sambuc 
727ebfedea0SLionel Sambuc   return res;
728ebfedea0SLionel Sambuc 
729ebfedea0SLionel Sambuc } /* end mp_div_d() */
730ebfedea0SLionel Sambuc 
731ebfedea0SLionel Sambuc /* }}} */
732ebfedea0SLionel Sambuc 
733ebfedea0SLionel Sambuc /* {{{ mp_div_2(a, c) */
734ebfedea0SLionel Sambuc 
735ebfedea0SLionel Sambuc /*
736ebfedea0SLionel Sambuc   mp_div_2(a, c)
737ebfedea0SLionel Sambuc 
738ebfedea0SLionel Sambuc   Compute c = a / 2, disregarding the remainder.
739ebfedea0SLionel Sambuc  */
740ebfedea0SLionel Sambuc 
mp_div_2(mp_int * a,mp_int * c)741ebfedea0SLionel Sambuc mp_err mp_div_2(mp_int *a, mp_int *c)
742ebfedea0SLionel Sambuc {
743ebfedea0SLionel Sambuc   mp_err  res;
744ebfedea0SLionel Sambuc 
745ebfedea0SLionel Sambuc   ARGCHK(a != NULL && c != NULL, MP_BADARG);
746ebfedea0SLionel Sambuc 
747ebfedea0SLionel Sambuc   if((res = mp_copy(a, c)) != MP_OKAY)
748ebfedea0SLionel Sambuc     return res;
749ebfedea0SLionel Sambuc 
750ebfedea0SLionel Sambuc   s_mp_div_2(c);
751ebfedea0SLionel Sambuc 
752ebfedea0SLionel Sambuc   return MP_OKAY;
753ebfedea0SLionel Sambuc 
754ebfedea0SLionel Sambuc } /* end mp_div_2() */
755ebfedea0SLionel Sambuc 
756ebfedea0SLionel Sambuc /* }}} */
757ebfedea0SLionel Sambuc 
758ebfedea0SLionel Sambuc /* {{{ mp_expt_d(a, d, b) */
759ebfedea0SLionel Sambuc 
mp_expt_d(mp_int * a,mp_digit d,mp_int * c)760ebfedea0SLionel Sambuc mp_err mp_expt_d(mp_int *a, mp_digit d, mp_int *c)
761ebfedea0SLionel Sambuc {
762ebfedea0SLionel Sambuc   mp_int   s, x;
763ebfedea0SLionel Sambuc   mp_err   res;
764ebfedea0SLionel Sambuc 
765ebfedea0SLionel Sambuc   ARGCHK(a != NULL && c != NULL, MP_BADARG);
766ebfedea0SLionel Sambuc 
767ebfedea0SLionel Sambuc   if((res = mp_init(&s)) != MP_OKAY)
768ebfedea0SLionel Sambuc     return res;
769ebfedea0SLionel Sambuc   if((res = mp_init_copy(&x, a)) != MP_OKAY)
770ebfedea0SLionel Sambuc     goto X;
771ebfedea0SLionel Sambuc 
772ebfedea0SLionel Sambuc   DIGIT(&s, 0) = 1;
773ebfedea0SLionel Sambuc 
774ebfedea0SLionel Sambuc   while(d != 0) {
775ebfedea0SLionel Sambuc     if(d & 1) {
776ebfedea0SLionel Sambuc       if((res = s_mp_mul(&s, &x)) != MP_OKAY)
777ebfedea0SLionel Sambuc 	goto CLEANUP;
778ebfedea0SLionel Sambuc     }
779ebfedea0SLionel Sambuc 
780ebfedea0SLionel Sambuc     d >>= 1;
781ebfedea0SLionel Sambuc 
782ebfedea0SLionel Sambuc     if((res = s_mp_sqr(&x)) != MP_OKAY)
783ebfedea0SLionel Sambuc       goto CLEANUP;
784ebfedea0SLionel Sambuc   }
785ebfedea0SLionel Sambuc 
786ebfedea0SLionel Sambuc   s_mp_exch(&s, c);
787ebfedea0SLionel Sambuc 
788ebfedea0SLionel Sambuc CLEANUP:
789ebfedea0SLionel Sambuc   mp_clear(&x);
790ebfedea0SLionel Sambuc X:
791ebfedea0SLionel Sambuc   mp_clear(&s);
792ebfedea0SLionel Sambuc 
793ebfedea0SLionel Sambuc   return res;
794ebfedea0SLionel Sambuc 
795ebfedea0SLionel Sambuc } /* end mp_expt_d() */
796ebfedea0SLionel Sambuc 
797ebfedea0SLionel Sambuc /* }}} */
798ebfedea0SLionel Sambuc 
799ebfedea0SLionel Sambuc /* }}} */
800ebfedea0SLionel Sambuc 
801ebfedea0SLionel Sambuc /*------------------------------------------------------------------------*/
802ebfedea0SLionel Sambuc /* {{{ Full arithmetic */
803ebfedea0SLionel Sambuc 
804ebfedea0SLionel Sambuc /* {{{ mp_abs(a, b) */
805ebfedea0SLionel Sambuc 
806ebfedea0SLionel Sambuc /*
807ebfedea0SLionel Sambuc   mp_abs(a, b)
808ebfedea0SLionel Sambuc 
809ebfedea0SLionel Sambuc   Compute b = |a|.  'a' and 'b' may be identical.
810ebfedea0SLionel Sambuc  */
811ebfedea0SLionel Sambuc 
mp_abs(mp_int * a,mp_int * b)812ebfedea0SLionel Sambuc mp_err mp_abs(mp_int *a, mp_int *b)
813ebfedea0SLionel Sambuc {
814ebfedea0SLionel Sambuc   mp_err   res;
815ebfedea0SLionel Sambuc 
816ebfedea0SLionel Sambuc   ARGCHK(a != NULL && b != NULL, MP_BADARG);
817ebfedea0SLionel Sambuc 
818ebfedea0SLionel Sambuc   if((res = mp_copy(a, b)) != MP_OKAY)
819ebfedea0SLionel Sambuc     return res;
820ebfedea0SLionel Sambuc 
821ebfedea0SLionel Sambuc   SIGN(b) = MP_ZPOS;
822ebfedea0SLionel Sambuc 
823ebfedea0SLionel Sambuc   return MP_OKAY;
824ebfedea0SLionel Sambuc 
825ebfedea0SLionel Sambuc } /* end mp_abs() */
826ebfedea0SLionel Sambuc 
827ebfedea0SLionel Sambuc /* }}} */
828ebfedea0SLionel Sambuc 
829ebfedea0SLionel Sambuc /* {{{ mp_neg(a, b) */
830ebfedea0SLionel Sambuc 
831ebfedea0SLionel Sambuc /*
832ebfedea0SLionel Sambuc   mp_neg(a, b)
833ebfedea0SLionel Sambuc 
834ebfedea0SLionel Sambuc   Compute b = -a.  'a' and 'b' may be identical.
835ebfedea0SLionel Sambuc  */
836ebfedea0SLionel Sambuc 
mp_neg(mp_int * a,mp_int * b)837ebfedea0SLionel Sambuc mp_err mp_neg(mp_int *a, mp_int *b)
838ebfedea0SLionel Sambuc {
839ebfedea0SLionel Sambuc   mp_err   res;
840ebfedea0SLionel Sambuc 
841ebfedea0SLionel Sambuc   ARGCHK(a != NULL && b != NULL, MP_BADARG);
842ebfedea0SLionel Sambuc 
843ebfedea0SLionel Sambuc   if((res = mp_copy(a, b)) != MP_OKAY)
844ebfedea0SLionel Sambuc     return res;
845ebfedea0SLionel Sambuc 
846ebfedea0SLionel Sambuc   if(s_mp_cmp_d(b, 0) == MP_EQ)
847ebfedea0SLionel Sambuc     SIGN(b) = MP_ZPOS;
848ebfedea0SLionel Sambuc   else
849ebfedea0SLionel Sambuc     SIGN(b) = (SIGN(b) == MP_NEG) ? MP_ZPOS : MP_NEG;
850ebfedea0SLionel Sambuc 
851ebfedea0SLionel Sambuc   return MP_OKAY;
852ebfedea0SLionel Sambuc 
853ebfedea0SLionel Sambuc } /* end mp_neg() */
854ebfedea0SLionel Sambuc 
855ebfedea0SLionel Sambuc /* }}} */
856ebfedea0SLionel Sambuc 
857ebfedea0SLionel Sambuc /* {{{ mp_add(a, b, c) */
858ebfedea0SLionel Sambuc 
859ebfedea0SLionel Sambuc /*
860ebfedea0SLionel Sambuc   mp_add(a, b, c)
861ebfedea0SLionel Sambuc 
862ebfedea0SLionel Sambuc   Compute c = a + b.  All parameters may be identical.
863ebfedea0SLionel Sambuc  */
864ebfedea0SLionel Sambuc 
mp_add(mp_int * a,mp_int * b,mp_int * c)865ebfedea0SLionel Sambuc mp_err mp_add(mp_int *a, mp_int *b, mp_int *c)
866ebfedea0SLionel Sambuc {
867ebfedea0SLionel Sambuc   mp_err  res;
868ebfedea0SLionel Sambuc   int     cmp;
869ebfedea0SLionel Sambuc 
870ebfedea0SLionel Sambuc   ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
871ebfedea0SLionel Sambuc 
872ebfedea0SLionel Sambuc   if(SIGN(a) == SIGN(b)) { /* same sign:  add values, keep sign */
873ebfedea0SLionel Sambuc 
874ebfedea0SLionel Sambuc     /* Commutativity of addition lets us do this in either order,
875ebfedea0SLionel Sambuc        so we avoid having to use a temporary even if the result
876ebfedea0SLionel Sambuc        is supposed to replace the output
877ebfedea0SLionel Sambuc      */
878ebfedea0SLionel Sambuc     if(c == b) {
879ebfedea0SLionel Sambuc       if((res = s_mp_add(c, a)) != MP_OKAY)
880ebfedea0SLionel Sambuc 	return res;
881ebfedea0SLionel Sambuc     } else {
882ebfedea0SLionel Sambuc       if(c != a && (res = mp_copy(a, c)) != MP_OKAY)
883ebfedea0SLionel Sambuc 	return res;
884ebfedea0SLionel Sambuc 
885ebfedea0SLionel Sambuc       if((res = s_mp_add(c, b)) != MP_OKAY)
886ebfedea0SLionel Sambuc 	return res;
887ebfedea0SLionel Sambuc     }
888ebfedea0SLionel Sambuc 
889ebfedea0SLionel Sambuc   } else if((cmp = s_mp_cmp(a, b)) > 0) {  /* different sign: a > b   */
890ebfedea0SLionel Sambuc 
891ebfedea0SLionel Sambuc     /* If the output is going to be clobbered, we will use a temporary
892ebfedea0SLionel Sambuc        variable; otherwise, we'll do it without touching the memory
893ebfedea0SLionel Sambuc        allocator at all, if possible
894ebfedea0SLionel Sambuc      */
895ebfedea0SLionel Sambuc     if(c == b) {
896ebfedea0SLionel Sambuc       mp_int  tmp;
897ebfedea0SLionel Sambuc 
898ebfedea0SLionel Sambuc       if((res = mp_init_copy(&tmp, a)) != MP_OKAY)
899ebfedea0SLionel Sambuc 	return res;
900ebfedea0SLionel Sambuc       if((res = s_mp_sub(&tmp, b)) != MP_OKAY) {
901ebfedea0SLionel Sambuc 	mp_clear(&tmp);
902ebfedea0SLionel Sambuc 	return res;
903ebfedea0SLionel Sambuc       }
904ebfedea0SLionel Sambuc 
905ebfedea0SLionel Sambuc       s_mp_exch(&tmp, c);
906ebfedea0SLionel Sambuc       mp_clear(&tmp);
907ebfedea0SLionel Sambuc 
908ebfedea0SLionel Sambuc     } else {
909ebfedea0SLionel Sambuc 
910ebfedea0SLionel Sambuc       if(c != a && (res = mp_copy(a, c)) != MP_OKAY)
911ebfedea0SLionel Sambuc 	return res;
912ebfedea0SLionel Sambuc       if((res = s_mp_sub(c, b)) != MP_OKAY)
913ebfedea0SLionel Sambuc 	return res;
914ebfedea0SLionel Sambuc 
915ebfedea0SLionel Sambuc     }
916ebfedea0SLionel Sambuc 
917ebfedea0SLionel Sambuc   } else if(cmp == 0) {             /* different sign, a == b   */
918ebfedea0SLionel Sambuc 
919ebfedea0SLionel Sambuc     mp_zero(c);
920ebfedea0SLionel Sambuc     return MP_OKAY;
921ebfedea0SLionel Sambuc 
922ebfedea0SLionel Sambuc   } else {                          /* different sign: a < b    */
923ebfedea0SLionel Sambuc 
924ebfedea0SLionel Sambuc     /* See above... */
925ebfedea0SLionel Sambuc     if(c == a) {
926ebfedea0SLionel Sambuc       mp_int  tmp;
927ebfedea0SLionel Sambuc 
928ebfedea0SLionel Sambuc       if((res = mp_init_copy(&tmp, b)) != MP_OKAY)
929ebfedea0SLionel Sambuc 	return res;
930ebfedea0SLionel Sambuc       if((res = s_mp_sub(&tmp, a)) != MP_OKAY) {
931ebfedea0SLionel Sambuc 	mp_clear(&tmp);
932ebfedea0SLionel Sambuc 	return res;
933ebfedea0SLionel Sambuc       }
934ebfedea0SLionel Sambuc 
935ebfedea0SLionel Sambuc       s_mp_exch(&tmp, c);
936ebfedea0SLionel Sambuc       mp_clear(&tmp);
937ebfedea0SLionel Sambuc 
938ebfedea0SLionel Sambuc     } else {
939ebfedea0SLionel Sambuc 
940ebfedea0SLionel Sambuc       if(c != b && (res = mp_copy(b, c)) != MP_OKAY)
941ebfedea0SLionel Sambuc 	return res;
942ebfedea0SLionel Sambuc       if((res = s_mp_sub(c, a)) != MP_OKAY)
943ebfedea0SLionel Sambuc 	return res;
944ebfedea0SLionel Sambuc 
945ebfedea0SLionel Sambuc     }
946ebfedea0SLionel Sambuc   }
947ebfedea0SLionel Sambuc 
948ebfedea0SLionel Sambuc   if(USED(c) == 1 && DIGIT(c, 0) == 0)
949ebfedea0SLionel Sambuc     SIGN(c) = MP_ZPOS;
950ebfedea0SLionel Sambuc 
951ebfedea0SLionel Sambuc   return MP_OKAY;
952ebfedea0SLionel Sambuc 
953ebfedea0SLionel Sambuc } /* end mp_add() */
954ebfedea0SLionel Sambuc 
955ebfedea0SLionel Sambuc /* }}} */
956ebfedea0SLionel Sambuc 
957ebfedea0SLionel Sambuc /* {{{ mp_sub(a, b, c) */
958ebfedea0SLionel Sambuc 
959ebfedea0SLionel Sambuc /*
960ebfedea0SLionel Sambuc   mp_sub(a, b, c)
961ebfedea0SLionel Sambuc 
962ebfedea0SLionel Sambuc   Compute c = a - b.  All parameters may be identical.
963ebfedea0SLionel Sambuc  */
964ebfedea0SLionel Sambuc 
mp_sub(mp_int * a,mp_int * b,mp_int * c)965ebfedea0SLionel Sambuc mp_err mp_sub(mp_int *a, mp_int *b, mp_int *c)
966ebfedea0SLionel Sambuc {
967ebfedea0SLionel Sambuc   mp_err  res;
968ebfedea0SLionel Sambuc   int     cmp;
969ebfedea0SLionel Sambuc 
970ebfedea0SLionel Sambuc   ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
971ebfedea0SLionel Sambuc 
972ebfedea0SLionel Sambuc   if(SIGN(a) != SIGN(b)) {
973ebfedea0SLionel Sambuc     if(c == a) {
974ebfedea0SLionel Sambuc       if((res = s_mp_add(c, b)) != MP_OKAY)
975ebfedea0SLionel Sambuc 	return res;
976ebfedea0SLionel Sambuc     } else {
977ebfedea0SLionel Sambuc       if(c != b && ((res = mp_copy(b, c)) != MP_OKAY))
978ebfedea0SLionel Sambuc 	return res;
979ebfedea0SLionel Sambuc       if((res = s_mp_add(c, a)) != MP_OKAY)
980ebfedea0SLionel Sambuc 	return res;
981ebfedea0SLionel Sambuc       SIGN(c) = SIGN(a);
982ebfedea0SLionel Sambuc     }
983ebfedea0SLionel Sambuc 
984ebfedea0SLionel Sambuc   } else if((cmp = s_mp_cmp(a, b)) > 0) { /* Same sign, a > b */
985ebfedea0SLionel Sambuc     if(c == b) {
986ebfedea0SLionel Sambuc       mp_int  tmp;
987ebfedea0SLionel Sambuc 
988ebfedea0SLionel Sambuc       if((res = mp_init_copy(&tmp, a)) != MP_OKAY)
989ebfedea0SLionel Sambuc 	return res;
990ebfedea0SLionel Sambuc       if((res = s_mp_sub(&tmp, b)) != MP_OKAY) {
991ebfedea0SLionel Sambuc 	mp_clear(&tmp);
992ebfedea0SLionel Sambuc 	return res;
993ebfedea0SLionel Sambuc       }
994ebfedea0SLionel Sambuc       s_mp_exch(&tmp, c);
995ebfedea0SLionel Sambuc       mp_clear(&tmp);
996ebfedea0SLionel Sambuc 
997ebfedea0SLionel Sambuc     } else {
998ebfedea0SLionel Sambuc       if(c != a && ((res = mp_copy(a, c)) != MP_OKAY))
999ebfedea0SLionel Sambuc 	return res;
1000ebfedea0SLionel Sambuc 
1001ebfedea0SLionel Sambuc       if((res = s_mp_sub(c, b)) != MP_OKAY)
1002ebfedea0SLionel Sambuc 	return res;
1003ebfedea0SLionel Sambuc     }
1004ebfedea0SLionel Sambuc 
1005ebfedea0SLionel Sambuc   } else if(cmp == 0) {  /* Same sign, equal magnitude */
1006ebfedea0SLionel Sambuc     mp_zero(c);
1007ebfedea0SLionel Sambuc     return MP_OKAY;
1008ebfedea0SLionel Sambuc 
1009ebfedea0SLionel Sambuc   } else {               /* Same sign, b > a */
1010ebfedea0SLionel Sambuc     if(c == a) {
1011ebfedea0SLionel Sambuc       mp_int  tmp;
1012ebfedea0SLionel Sambuc 
1013ebfedea0SLionel Sambuc       if((res = mp_init_copy(&tmp, b)) != MP_OKAY)
1014ebfedea0SLionel Sambuc 	return res;
1015ebfedea0SLionel Sambuc 
1016ebfedea0SLionel Sambuc       if((res = s_mp_sub(&tmp, a)) != MP_OKAY) {
1017ebfedea0SLionel Sambuc 	mp_clear(&tmp);
1018ebfedea0SLionel Sambuc 	return res;
1019ebfedea0SLionel Sambuc       }
1020ebfedea0SLionel Sambuc       s_mp_exch(&tmp, c);
1021ebfedea0SLionel Sambuc       mp_clear(&tmp);
1022ebfedea0SLionel Sambuc 
1023ebfedea0SLionel Sambuc     } else {
1024ebfedea0SLionel Sambuc       if(c != b && ((res = mp_copy(b, c)) != MP_OKAY))
1025ebfedea0SLionel Sambuc 	return res;
1026ebfedea0SLionel Sambuc 
1027ebfedea0SLionel Sambuc       if((res = s_mp_sub(c, a)) != MP_OKAY)
1028ebfedea0SLionel Sambuc 	return res;
1029ebfedea0SLionel Sambuc     }
1030ebfedea0SLionel Sambuc 
1031ebfedea0SLionel Sambuc     SIGN(c) = !SIGN(b);
1032ebfedea0SLionel Sambuc   }
1033ebfedea0SLionel Sambuc 
1034ebfedea0SLionel Sambuc   if(USED(c) == 1 && DIGIT(c, 0) == 0)
1035ebfedea0SLionel Sambuc     SIGN(c) = MP_ZPOS;
1036ebfedea0SLionel Sambuc 
1037ebfedea0SLionel Sambuc   return MP_OKAY;
1038ebfedea0SLionel Sambuc 
1039ebfedea0SLionel Sambuc } /* end mp_sub() */
1040ebfedea0SLionel Sambuc 
1041ebfedea0SLionel Sambuc /* }}} */
1042ebfedea0SLionel Sambuc 
1043ebfedea0SLionel Sambuc /* {{{ mp_mul(a, b, c) */
1044ebfedea0SLionel Sambuc 
1045ebfedea0SLionel Sambuc /*
1046ebfedea0SLionel Sambuc   mp_mul(a, b, c)
1047ebfedea0SLionel Sambuc 
1048ebfedea0SLionel Sambuc   Compute c = a * b.  All parameters may be identical.
1049ebfedea0SLionel Sambuc  */
1050ebfedea0SLionel Sambuc 
mp_mul(mp_int * a,mp_int * b,mp_int * c)1051ebfedea0SLionel Sambuc mp_err mp_mul(mp_int *a, mp_int *b, mp_int *c)
1052ebfedea0SLionel Sambuc {
1053ebfedea0SLionel Sambuc   mp_err   res;
1054ebfedea0SLionel Sambuc   mp_sign  sgn;
1055ebfedea0SLionel Sambuc 
1056ebfedea0SLionel Sambuc   ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
1057ebfedea0SLionel Sambuc 
1058ebfedea0SLionel Sambuc   sgn = (SIGN(a) == SIGN(b)) ? MP_ZPOS : MP_NEG;
1059ebfedea0SLionel Sambuc 
1060ebfedea0SLionel Sambuc   if(c == b) {
1061ebfedea0SLionel Sambuc     if((res = s_mp_mul(c, a)) != MP_OKAY)
1062ebfedea0SLionel Sambuc       return res;
1063ebfedea0SLionel Sambuc 
1064ebfedea0SLionel Sambuc   } else {
1065ebfedea0SLionel Sambuc     if((res = mp_copy(a, c)) != MP_OKAY)
1066ebfedea0SLionel Sambuc       return res;
1067ebfedea0SLionel Sambuc 
1068ebfedea0SLionel Sambuc     if((res = s_mp_mul(c, b)) != MP_OKAY)
1069ebfedea0SLionel Sambuc       return res;
1070ebfedea0SLionel Sambuc   }
1071ebfedea0SLionel Sambuc 
1072ebfedea0SLionel Sambuc   if(sgn == MP_ZPOS || s_mp_cmp_d(c, 0) == MP_EQ)
1073ebfedea0SLionel Sambuc     SIGN(c) = MP_ZPOS;
1074ebfedea0SLionel Sambuc   else
1075ebfedea0SLionel Sambuc     SIGN(c) = sgn;
1076ebfedea0SLionel Sambuc 
1077ebfedea0SLionel Sambuc   return MP_OKAY;
1078ebfedea0SLionel Sambuc 
1079ebfedea0SLionel Sambuc } /* end mp_mul() */
1080ebfedea0SLionel Sambuc 
1081ebfedea0SLionel Sambuc /* }}} */
1082ebfedea0SLionel Sambuc 
1083ebfedea0SLionel Sambuc /* {{{ mp_mul_2d(a, d, c) */
1084ebfedea0SLionel Sambuc 
1085ebfedea0SLionel Sambuc /*
1086ebfedea0SLionel Sambuc   mp_mul_2d(a, d, c)
1087ebfedea0SLionel Sambuc 
1088ebfedea0SLionel Sambuc   Compute c = a * 2^d.  a may be the same as c.
1089ebfedea0SLionel Sambuc  */
1090ebfedea0SLionel Sambuc 
mp_mul_2d(mp_int * a,mp_digit d,mp_int * c)1091ebfedea0SLionel Sambuc mp_err mp_mul_2d(mp_int *a, mp_digit d, mp_int *c)
1092ebfedea0SLionel Sambuc {
1093ebfedea0SLionel Sambuc   mp_err   res;
1094ebfedea0SLionel Sambuc 
1095ebfedea0SLionel Sambuc   ARGCHK(a != NULL && c != NULL, MP_BADARG);
1096ebfedea0SLionel Sambuc 
1097ebfedea0SLionel Sambuc   if((res = mp_copy(a, c)) != MP_OKAY)
1098ebfedea0SLionel Sambuc     return res;
1099ebfedea0SLionel Sambuc 
1100ebfedea0SLionel Sambuc   if(d == 0)
1101ebfedea0SLionel Sambuc     return MP_OKAY;
1102ebfedea0SLionel Sambuc 
1103ebfedea0SLionel Sambuc   return s_mp_mul_2d(c, d);
1104ebfedea0SLionel Sambuc 
1105ebfedea0SLionel Sambuc } /* end mp_mul() */
1106ebfedea0SLionel Sambuc 
1107ebfedea0SLionel Sambuc /* }}} */
1108ebfedea0SLionel Sambuc 
1109ebfedea0SLionel Sambuc /* {{{ mp_sqr(a, b) */
1110ebfedea0SLionel Sambuc 
1111ebfedea0SLionel Sambuc #if MP_SQUARE
mp_sqr(mp_int * a,mp_int * b)1112ebfedea0SLionel Sambuc mp_err mp_sqr(mp_int *a, mp_int *b)
1113ebfedea0SLionel Sambuc {
1114ebfedea0SLionel Sambuc   mp_err   res;
1115ebfedea0SLionel Sambuc 
1116ebfedea0SLionel Sambuc   ARGCHK(a != NULL && b != NULL, MP_BADARG);
1117ebfedea0SLionel Sambuc 
1118ebfedea0SLionel Sambuc   if((res = mp_copy(a, b)) != MP_OKAY)
1119ebfedea0SLionel Sambuc     return res;
1120ebfedea0SLionel Sambuc 
1121ebfedea0SLionel Sambuc   if((res = s_mp_sqr(b)) != MP_OKAY)
1122ebfedea0SLionel Sambuc     return res;
1123ebfedea0SLionel Sambuc 
1124ebfedea0SLionel Sambuc   SIGN(b) = MP_ZPOS;
1125ebfedea0SLionel Sambuc 
1126ebfedea0SLionel Sambuc   return MP_OKAY;
1127ebfedea0SLionel Sambuc 
1128ebfedea0SLionel Sambuc } /* end mp_sqr() */
1129ebfedea0SLionel Sambuc #endif
1130ebfedea0SLionel Sambuc 
1131ebfedea0SLionel Sambuc /* }}} */
1132ebfedea0SLionel Sambuc 
1133ebfedea0SLionel Sambuc /* {{{ mp_div(a, b, q, r) */
1134ebfedea0SLionel Sambuc 
1135ebfedea0SLionel Sambuc /*
1136ebfedea0SLionel Sambuc   mp_div(a, b, q, r)
1137ebfedea0SLionel Sambuc 
1138ebfedea0SLionel Sambuc   Compute q = a / b and r = a mod b.  Input parameters may be re-used
1139ebfedea0SLionel Sambuc   as output parameters.  If q or r is NULL, that portion of the
1140ebfedea0SLionel Sambuc   computation will be discarded (although it will still be computed)
1141ebfedea0SLionel Sambuc 
1142ebfedea0SLionel Sambuc   Pay no attention to the hacker behind the curtain.
1143ebfedea0SLionel Sambuc  */
1144ebfedea0SLionel Sambuc 
mp_div(mp_int * a,mp_int * b,mp_int * q,mp_int * r)1145ebfedea0SLionel Sambuc mp_err mp_div(mp_int *a, mp_int *b, mp_int *q, mp_int *r)
1146ebfedea0SLionel Sambuc {
1147ebfedea0SLionel Sambuc   mp_err   res;
1148ebfedea0SLionel Sambuc   mp_int   qtmp, rtmp;
1149ebfedea0SLionel Sambuc   int      cmp;
1150ebfedea0SLionel Sambuc 
1151ebfedea0SLionel Sambuc   ARGCHK(a != NULL && b != NULL, MP_BADARG);
1152ebfedea0SLionel Sambuc 
1153ebfedea0SLionel Sambuc   if(mp_cmp_z(b) == MP_EQ)
1154ebfedea0SLionel Sambuc     return MP_RANGE;
1155ebfedea0SLionel Sambuc 
1156ebfedea0SLionel Sambuc   /* If a <= b, we can compute the solution without division, and
1157ebfedea0SLionel Sambuc      avoid any memory allocation
1158ebfedea0SLionel Sambuc    */
1159ebfedea0SLionel Sambuc   if((cmp = s_mp_cmp(a, b)) < 0) {
1160ebfedea0SLionel Sambuc     if(r) {
1161ebfedea0SLionel Sambuc       if((res = mp_copy(a, r)) != MP_OKAY)
1162ebfedea0SLionel Sambuc 	return res;
1163ebfedea0SLionel Sambuc     }
1164ebfedea0SLionel Sambuc 
1165ebfedea0SLionel Sambuc     if(q)
1166ebfedea0SLionel Sambuc       mp_zero(q);
1167ebfedea0SLionel Sambuc 
1168ebfedea0SLionel Sambuc     return MP_OKAY;
1169ebfedea0SLionel Sambuc 
1170ebfedea0SLionel Sambuc   } else if(cmp == 0) {
1171ebfedea0SLionel Sambuc 
1172ebfedea0SLionel Sambuc     /* Set quotient to 1, with appropriate sign */
1173ebfedea0SLionel Sambuc     if(q) {
1174ebfedea0SLionel Sambuc       int qneg = (SIGN(a) != SIGN(b));
1175ebfedea0SLionel Sambuc 
1176ebfedea0SLionel Sambuc       mp_set(q, 1);
1177ebfedea0SLionel Sambuc       if(qneg)
1178ebfedea0SLionel Sambuc 	SIGN(q) = MP_NEG;
1179ebfedea0SLionel Sambuc     }
1180ebfedea0SLionel Sambuc 
1181ebfedea0SLionel Sambuc     if(r)
1182ebfedea0SLionel Sambuc       mp_zero(r);
1183ebfedea0SLionel Sambuc 
1184ebfedea0SLionel Sambuc     return MP_OKAY;
1185ebfedea0SLionel Sambuc   }
1186ebfedea0SLionel Sambuc 
1187ebfedea0SLionel Sambuc   /* If we get here, it means we actually have to do some division */
1188ebfedea0SLionel Sambuc 
1189ebfedea0SLionel Sambuc   /* Set up some temporaries... */
1190ebfedea0SLionel Sambuc   if((res = mp_init_copy(&qtmp, a)) != MP_OKAY)
1191ebfedea0SLionel Sambuc     return res;
1192ebfedea0SLionel Sambuc   if((res = mp_init_copy(&rtmp, b)) != MP_OKAY)
1193ebfedea0SLionel Sambuc     goto CLEANUP;
1194ebfedea0SLionel Sambuc 
1195ebfedea0SLionel Sambuc   if((res = s_mp_div(&qtmp, &rtmp)) != MP_OKAY)
1196ebfedea0SLionel Sambuc     goto CLEANUP;
1197ebfedea0SLionel Sambuc 
1198ebfedea0SLionel Sambuc   /* Compute the signs for the output  */
1199ebfedea0SLionel Sambuc   SIGN(&rtmp) = SIGN(a); /* Sr = Sa              */
1200ebfedea0SLionel Sambuc   if(SIGN(a) == SIGN(b))
1201ebfedea0SLionel Sambuc     SIGN(&qtmp) = MP_ZPOS;  /* Sq = MP_ZPOS if Sa = Sb */
1202ebfedea0SLionel Sambuc   else
1203ebfedea0SLionel Sambuc     SIGN(&qtmp) = MP_NEG;   /* Sq = MP_NEG if Sa != Sb */
1204ebfedea0SLionel Sambuc 
1205ebfedea0SLionel Sambuc   if(s_mp_cmp_d(&qtmp, 0) == MP_EQ)
1206ebfedea0SLionel Sambuc     SIGN(&qtmp) = MP_ZPOS;
1207ebfedea0SLionel Sambuc   if(s_mp_cmp_d(&rtmp, 0) == MP_EQ)
1208ebfedea0SLionel Sambuc     SIGN(&rtmp) = MP_ZPOS;
1209ebfedea0SLionel Sambuc 
1210ebfedea0SLionel Sambuc   /* Copy output, if it is needed      */
1211ebfedea0SLionel Sambuc   if(q)
1212ebfedea0SLionel Sambuc     s_mp_exch(&qtmp, q);
1213ebfedea0SLionel Sambuc 
1214ebfedea0SLionel Sambuc   if(r)
1215ebfedea0SLionel Sambuc     s_mp_exch(&rtmp, r);
1216ebfedea0SLionel Sambuc 
1217ebfedea0SLionel Sambuc CLEANUP:
1218ebfedea0SLionel Sambuc   mp_clear(&rtmp);
1219ebfedea0SLionel Sambuc   mp_clear(&qtmp);
1220ebfedea0SLionel Sambuc 
1221ebfedea0SLionel Sambuc   return res;
1222ebfedea0SLionel Sambuc 
1223ebfedea0SLionel Sambuc } /* end mp_div() */
1224ebfedea0SLionel Sambuc 
1225ebfedea0SLionel Sambuc /* }}} */
1226ebfedea0SLionel Sambuc 
1227ebfedea0SLionel Sambuc /* {{{ mp_div_2d(a, d, q, r) */
1228ebfedea0SLionel Sambuc 
mp_div_2d(mp_int * a,mp_digit d,mp_int * q,mp_int * r)1229ebfedea0SLionel Sambuc mp_err mp_div_2d(mp_int *a, mp_digit d, mp_int *q, mp_int *r)
1230ebfedea0SLionel Sambuc {
1231ebfedea0SLionel Sambuc   mp_err  res;
1232ebfedea0SLionel Sambuc 
1233ebfedea0SLionel Sambuc   ARGCHK(a != NULL, MP_BADARG);
1234ebfedea0SLionel Sambuc 
1235ebfedea0SLionel Sambuc   if(q) {
1236ebfedea0SLionel Sambuc     if((res = mp_copy(a, q)) != MP_OKAY)
1237ebfedea0SLionel Sambuc       return res;
1238ebfedea0SLionel Sambuc 
1239ebfedea0SLionel Sambuc     s_mp_div_2d(q, d);
1240ebfedea0SLionel Sambuc   }
1241ebfedea0SLionel Sambuc 
1242ebfedea0SLionel Sambuc   if(r) {
1243ebfedea0SLionel Sambuc     if((res = mp_copy(a, r)) != MP_OKAY)
1244ebfedea0SLionel Sambuc       return res;
1245ebfedea0SLionel Sambuc 
1246ebfedea0SLionel Sambuc     s_mp_mod_2d(r, d);
1247ebfedea0SLionel Sambuc   }
1248ebfedea0SLionel Sambuc 
1249ebfedea0SLionel Sambuc   return MP_OKAY;
1250ebfedea0SLionel Sambuc 
1251ebfedea0SLionel Sambuc } /* end mp_div_2d() */
1252ebfedea0SLionel Sambuc 
1253ebfedea0SLionel Sambuc /* }}} */
1254ebfedea0SLionel Sambuc 
1255ebfedea0SLionel Sambuc /* {{{ mp_expt(a, b, c) */
1256ebfedea0SLionel Sambuc 
1257ebfedea0SLionel Sambuc /*
1258ebfedea0SLionel Sambuc   mp_expt(a, b, c)
1259ebfedea0SLionel Sambuc 
1260ebfedea0SLionel Sambuc   Compute c = a ** b, that is, raise a to the b power.  Uses a
1261ebfedea0SLionel Sambuc   standard iterative square-and-multiply technique.
1262ebfedea0SLionel Sambuc  */
1263ebfedea0SLionel Sambuc 
mp_expt(mp_int * a,mp_int * b,mp_int * c)1264ebfedea0SLionel Sambuc mp_err mp_expt(mp_int *a, mp_int *b, mp_int *c)
1265ebfedea0SLionel Sambuc {
1266ebfedea0SLionel Sambuc   mp_int   s, x;
1267ebfedea0SLionel Sambuc   mp_err   res;
1268ebfedea0SLionel Sambuc   mp_digit d;
1269ebfedea0SLionel Sambuc   int      dig, bit;
1270ebfedea0SLionel Sambuc 
1271ebfedea0SLionel Sambuc   ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
1272ebfedea0SLionel Sambuc 
1273ebfedea0SLionel Sambuc   if(mp_cmp_z(b) < 0)
1274ebfedea0SLionel Sambuc     return MP_RANGE;
1275ebfedea0SLionel Sambuc 
1276ebfedea0SLionel Sambuc   if((res = mp_init(&s)) != MP_OKAY)
1277ebfedea0SLionel Sambuc     return res;
1278ebfedea0SLionel Sambuc 
1279ebfedea0SLionel Sambuc   mp_set(&s, 1);
1280ebfedea0SLionel Sambuc 
1281ebfedea0SLionel Sambuc   if((res = mp_init_copy(&x, a)) != MP_OKAY)
1282ebfedea0SLionel Sambuc     goto X;
1283ebfedea0SLionel Sambuc 
1284ebfedea0SLionel Sambuc   /* Loop over low-order digits in ascending order */
1285ebfedea0SLionel Sambuc   for(dig = 0; dig < (USED(b) - 1); dig++) {
1286ebfedea0SLionel Sambuc     d = DIGIT(b, dig);
1287ebfedea0SLionel Sambuc 
1288ebfedea0SLionel Sambuc     /* Loop over bits of each non-maximal digit */
1289ebfedea0SLionel Sambuc     for(bit = 0; bit < DIGIT_BIT; bit++) {
1290ebfedea0SLionel Sambuc       if(d & 1) {
1291ebfedea0SLionel Sambuc 	if((res = s_mp_mul(&s, &x)) != MP_OKAY)
1292ebfedea0SLionel Sambuc 	  goto CLEANUP;
1293ebfedea0SLionel Sambuc       }
1294ebfedea0SLionel Sambuc 
1295ebfedea0SLionel Sambuc       d >>= 1;
1296ebfedea0SLionel Sambuc 
1297ebfedea0SLionel Sambuc       if((res = s_mp_sqr(&x)) != MP_OKAY)
1298ebfedea0SLionel Sambuc 	goto CLEANUP;
1299ebfedea0SLionel Sambuc     }
1300ebfedea0SLionel Sambuc   }
1301ebfedea0SLionel Sambuc 
1302ebfedea0SLionel Sambuc   /* Consider now the last digit... */
1303ebfedea0SLionel Sambuc   d = DIGIT(b, dig);
1304ebfedea0SLionel Sambuc 
1305ebfedea0SLionel Sambuc   while(d) {
1306ebfedea0SLionel Sambuc     if(d & 1) {
1307ebfedea0SLionel Sambuc       if((res = s_mp_mul(&s, &x)) != MP_OKAY)
1308ebfedea0SLionel Sambuc 	goto CLEANUP;
1309ebfedea0SLionel Sambuc     }
1310ebfedea0SLionel Sambuc 
1311ebfedea0SLionel Sambuc     d >>= 1;
1312ebfedea0SLionel Sambuc 
1313ebfedea0SLionel Sambuc     if((res = s_mp_sqr(&x)) != MP_OKAY)
1314ebfedea0SLionel Sambuc       goto CLEANUP;
1315ebfedea0SLionel Sambuc   }
1316ebfedea0SLionel Sambuc 
1317ebfedea0SLionel Sambuc   if(mp_iseven(b))
1318ebfedea0SLionel Sambuc     SIGN(&s) = SIGN(a);
1319ebfedea0SLionel Sambuc 
1320ebfedea0SLionel Sambuc   res = mp_copy(&s, c);
1321ebfedea0SLionel Sambuc 
1322ebfedea0SLionel Sambuc CLEANUP:
1323ebfedea0SLionel Sambuc   mp_clear(&x);
1324ebfedea0SLionel Sambuc X:
1325ebfedea0SLionel Sambuc   mp_clear(&s);
1326ebfedea0SLionel Sambuc 
1327ebfedea0SLionel Sambuc   return res;
1328ebfedea0SLionel Sambuc 
1329ebfedea0SLionel Sambuc } /* end mp_expt() */
1330ebfedea0SLionel Sambuc 
1331ebfedea0SLionel Sambuc /* }}} */
1332ebfedea0SLionel Sambuc 
1333ebfedea0SLionel Sambuc /* {{{ mp_2expt(a, k) */
1334ebfedea0SLionel Sambuc 
1335ebfedea0SLionel Sambuc /* Compute a = 2^k */
1336ebfedea0SLionel Sambuc 
mp_2expt(mp_int * a,mp_digit k)1337ebfedea0SLionel Sambuc mp_err mp_2expt(mp_int *a, mp_digit k)
1338ebfedea0SLionel Sambuc {
1339ebfedea0SLionel Sambuc   ARGCHK(a != NULL, MP_BADARG);
1340ebfedea0SLionel Sambuc 
1341ebfedea0SLionel Sambuc   return s_mp_2expt(a, k);
1342ebfedea0SLionel Sambuc 
1343ebfedea0SLionel Sambuc } /* end mp_2expt() */
1344ebfedea0SLionel Sambuc 
1345ebfedea0SLionel Sambuc /* }}} */
1346ebfedea0SLionel Sambuc 
1347ebfedea0SLionel Sambuc /* {{{ mp_mod(a, m, c) */
1348ebfedea0SLionel Sambuc 
1349ebfedea0SLionel Sambuc /*
1350ebfedea0SLionel Sambuc   mp_mod(a, m, c)
1351ebfedea0SLionel Sambuc 
1352ebfedea0SLionel Sambuc   Compute c = a (mod m).  Result will always be 0 <= c < m.
1353ebfedea0SLionel Sambuc  */
1354ebfedea0SLionel Sambuc 
mp_mod(mp_int * a,mp_int * m,mp_int * c)1355ebfedea0SLionel Sambuc mp_err mp_mod(mp_int *a, mp_int *m, mp_int *c)
1356ebfedea0SLionel Sambuc {
1357ebfedea0SLionel Sambuc   mp_err  res;
1358ebfedea0SLionel Sambuc   int     mag;
1359ebfedea0SLionel Sambuc 
1360ebfedea0SLionel Sambuc   ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);
1361ebfedea0SLionel Sambuc 
1362ebfedea0SLionel Sambuc   if(SIGN(m) == MP_NEG)
1363ebfedea0SLionel Sambuc     return MP_RANGE;
1364ebfedea0SLionel Sambuc 
1365ebfedea0SLionel Sambuc   /*
1366ebfedea0SLionel Sambuc      If |a| > m, we need to divide to get the remainder and take the
1367ebfedea0SLionel Sambuc      absolute value.
1368ebfedea0SLionel Sambuc 
1369ebfedea0SLionel Sambuc      If |a| < m, we don't need to do any division, just copy and adjust
1370ebfedea0SLionel Sambuc      the sign (if a is negative).
1371ebfedea0SLionel Sambuc 
1372ebfedea0SLionel Sambuc      If |a| == m, we can simply set the result to zero.
1373ebfedea0SLionel Sambuc 
1374ebfedea0SLionel Sambuc      This order is intended to minimize the average path length of the
1375ebfedea0SLionel Sambuc      comparison chain on common workloads -- the most frequent cases are
1376ebfedea0SLionel Sambuc      that |a| != m, so we do those first.
1377ebfedea0SLionel Sambuc    */
1378ebfedea0SLionel Sambuc   if((mag = s_mp_cmp(a, m)) > 0) {
1379ebfedea0SLionel Sambuc     if((res = mp_div(a, m, NULL, c)) != MP_OKAY)
1380ebfedea0SLionel Sambuc       return res;
1381ebfedea0SLionel Sambuc 
1382ebfedea0SLionel Sambuc     if(SIGN(c) == MP_NEG) {
1383ebfedea0SLionel Sambuc       if((res = mp_add(c, m, c)) != MP_OKAY)
1384ebfedea0SLionel Sambuc 	return res;
1385ebfedea0SLionel Sambuc     }
1386ebfedea0SLionel Sambuc 
1387ebfedea0SLionel Sambuc   } else if(mag < 0) {
1388ebfedea0SLionel Sambuc     if((res = mp_copy(a, c)) != MP_OKAY)
1389ebfedea0SLionel Sambuc       return res;
1390ebfedea0SLionel Sambuc 
1391ebfedea0SLionel Sambuc     if(mp_cmp_z(a) < 0) {
1392ebfedea0SLionel Sambuc       if((res = mp_add(c, m, c)) != MP_OKAY)
1393ebfedea0SLionel Sambuc 	return res;
1394ebfedea0SLionel Sambuc 
1395ebfedea0SLionel Sambuc     }
1396ebfedea0SLionel Sambuc 
1397ebfedea0SLionel Sambuc   } else {
1398ebfedea0SLionel Sambuc     mp_zero(c);
1399ebfedea0SLionel Sambuc 
1400ebfedea0SLionel Sambuc   }
1401ebfedea0SLionel Sambuc 
1402ebfedea0SLionel Sambuc   return MP_OKAY;
1403ebfedea0SLionel Sambuc 
1404ebfedea0SLionel Sambuc } /* end mp_mod() */
1405ebfedea0SLionel Sambuc 
1406ebfedea0SLionel Sambuc /* }}} */
1407ebfedea0SLionel Sambuc 
1408ebfedea0SLionel Sambuc /* {{{ mp_mod_d(a, d, c) */
1409ebfedea0SLionel Sambuc 
1410ebfedea0SLionel Sambuc /*
1411ebfedea0SLionel Sambuc   mp_mod_d(a, d, c)
1412ebfedea0SLionel Sambuc 
1413ebfedea0SLionel Sambuc   Compute c = a (mod d).  Result will always be 0 <= c < d
1414ebfedea0SLionel Sambuc  */
mp_mod_d(mp_int * a,mp_digit d,mp_digit * c)1415ebfedea0SLionel Sambuc mp_err mp_mod_d(mp_int *a, mp_digit d, mp_digit *c)
1416ebfedea0SLionel Sambuc {
1417ebfedea0SLionel Sambuc   mp_err   res;
1418ebfedea0SLionel Sambuc   mp_digit rem;
1419ebfedea0SLionel Sambuc 
1420ebfedea0SLionel Sambuc   ARGCHK(a != NULL && c != NULL, MP_BADARG);
1421ebfedea0SLionel Sambuc 
1422ebfedea0SLionel Sambuc   if(s_mp_cmp_d(a, d) > 0) {
1423ebfedea0SLionel Sambuc     if((res = mp_div_d(a, d, NULL, &rem)) != MP_OKAY)
1424ebfedea0SLionel Sambuc       return res;
1425ebfedea0SLionel Sambuc 
1426ebfedea0SLionel Sambuc   } else {
1427ebfedea0SLionel Sambuc     if(SIGN(a) == MP_NEG)
1428ebfedea0SLionel Sambuc       rem = d - DIGIT(a, 0);
1429ebfedea0SLionel Sambuc     else
1430ebfedea0SLionel Sambuc       rem = DIGIT(a, 0);
1431ebfedea0SLionel Sambuc   }
1432ebfedea0SLionel Sambuc 
1433ebfedea0SLionel Sambuc   if(c)
1434ebfedea0SLionel Sambuc     *c = rem;
1435ebfedea0SLionel Sambuc 
1436ebfedea0SLionel Sambuc   return MP_OKAY;
1437ebfedea0SLionel Sambuc 
1438ebfedea0SLionel Sambuc } /* end mp_mod_d() */
1439ebfedea0SLionel Sambuc 
1440ebfedea0SLionel Sambuc /* }}} */
1441ebfedea0SLionel Sambuc 
1442ebfedea0SLionel Sambuc /* {{{ mp_sqrt(a, b) */
1443ebfedea0SLionel Sambuc 
1444ebfedea0SLionel Sambuc /*
1445ebfedea0SLionel Sambuc   mp_sqrt(a, b)
1446ebfedea0SLionel Sambuc 
1447ebfedea0SLionel Sambuc   Compute the integer square root of a, and store the result in b.
1448ebfedea0SLionel Sambuc   Uses an integer-arithmetic version of Newton's iterative linear
1449ebfedea0SLionel Sambuc   approximation technique to determine this value; the result has the
1450ebfedea0SLionel Sambuc   following two properties:
1451ebfedea0SLionel Sambuc 
1452ebfedea0SLionel Sambuc      b^2 <= a
1453ebfedea0SLionel Sambuc      (b+1)^2 >= a
1454ebfedea0SLionel Sambuc 
1455ebfedea0SLionel Sambuc   It is a range error to pass a negative value.
1456ebfedea0SLionel Sambuc  */
mp_sqrt(mp_int * a,mp_int * b)1457ebfedea0SLionel Sambuc mp_err mp_sqrt(mp_int *a, mp_int *b)
1458ebfedea0SLionel Sambuc {
1459ebfedea0SLionel Sambuc   mp_int   x, t;
1460ebfedea0SLionel Sambuc   mp_err   res;
1461ebfedea0SLionel Sambuc 
1462ebfedea0SLionel Sambuc   ARGCHK(a != NULL && b != NULL, MP_BADARG);
1463ebfedea0SLionel Sambuc 
1464ebfedea0SLionel Sambuc   /* Cannot take square root of a negative value */
1465ebfedea0SLionel Sambuc   if(SIGN(a) == MP_NEG)
1466ebfedea0SLionel Sambuc     return MP_RANGE;
1467ebfedea0SLionel Sambuc 
1468ebfedea0SLionel Sambuc   /* Special cases for zero and one, trivial     */
1469ebfedea0SLionel Sambuc   if(mp_cmp_d(a, 0) == MP_EQ || mp_cmp_d(a, 1) == MP_EQ)
1470ebfedea0SLionel Sambuc     return mp_copy(a, b);
1471ebfedea0SLionel Sambuc 
1472ebfedea0SLionel Sambuc   /* Initialize the temporaries we'll use below  */
1473ebfedea0SLionel Sambuc   if((res = mp_init_size(&t, USED(a))) != MP_OKAY)
1474ebfedea0SLionel Sambuc     return res;
1475ebfedea0SLionel Sambuc 
1476ebfedea0SLionel Sambuc   /* Compute an initial guess for the iteration as a itself */
1477ebfedea0SLionel Sambuc   if((res = mp_init_copy(&x, a)) != MP_OKAY)
1478ebfedea0SLionel Sambuc     goto X;
1479ebfedea0SLionel Sambuc 
1480ebfedea0SLionel Sambuc s_mp_rshd(&x, (USED(&x)/2)+1);
1481ebfedea0SLionel Sambuc mp_add_d(&x, 1, &x);
1482ebfedea0SLionel Sambuc 
1483ebfedea0SLionel Sambuc   for(;;) {
1484ebfedea0SLionel Sambuc     /* t = (x * x) - a */
1485ebfedea0SLionel Sambuc     mp_copy(&x, &t);      /* can't fail, t is big enough for original x */
1486ebfedea0SLionel Sambuc     if((res = mp_sqr(&t, &t)) != MP_OKAY ||
1487ebfedea0SLionel Sambuc        (res = mp_sub(&t, a, &t)) != MP_OKAY)
1488ebfedea0SLionel Sambuc       goto CLEANUP;
1489ebfedea0SLionel Sambuc 
1490ebfedea0SLionel Sambuc     /* t = t / 2x       */
1491ebfedea0SLionel Sambuc     s_mp_mul_2(&x);
1492ebfedea0SLionel Sambuc     if((res = mp_div(&t, &x, &t, NULL)) != MP_OKAY)
1493ebfedea0SLionel Sambuc       goto CLEANUP;
1494ebfedea0SLionel Sambuc     s_mp_div_2(&x);
1495ebfedea0SLionel Sambuc 
1496ebfedea0SLionel Sambuc     /* Terminate the loop, if the quotient is zero */
1497ebfedea0SLionel Sambuc     if(mp_cmp_z(&t) == MP_EQ)
1498ebfedea0SLionel Sambuc       break;
1499ebfedea0SLionel Sambuc 
1500ebfedea0SLionel Sambuc     /* x = x - t       */
1501ebfedea0SLionel Sambuc     if((res = mp_sub(&x, &t, &x)) != MP_OKAY)
1502ebfedea0SLionel Sambuc       goto CLEANUP;
1503ebfedea0SLionel Sambuc 
1504ebfedea0SLionel Sambuc   }
1505ebfedea0SLionel Sambuc 
1506ebfedea0SLionel Sambuc   /* Copy result to output parameter */
1507ebfedea0SLionel Sambuc   mp_sub_d(&x, 1, &x);
1508ebfedea0SLionel Sambuc   s_mp_exch(&x, b);
1509ebfedea0SLionel Sambuc 
1510ebfedea0SLionel Sambuc  CLEANUP:
1511ebfedea0SLionel Sambuc   mp_clear(&x);
1512ebfedea0SLionel Sambuc  X:
1513ebfedea0SLionel Sambuc   mp_clear(&t);
1514ebfedea0SLionel Sambuc 
1515ebfedea0SLionel Sambuc   return res;
1516ebfedea0SLionel Sambuc 
1517ebfedea0SLionel Sambuc } /* end mp_sqrt() */
1518ebfedea0SLionel Sambuc 
1519ebfedea0SLionel Sambuc /* }}} */
1520ebfedea0SLionel Sambuc 
1521ebfedea0SLionel Sambuc /* }}} */
1522ebfedea0SLionel Sambuc 
1523ebfedea0SLionel Sambuc /*------------------------------------------------------------------------*/
1524ebfedea0SLionel Sambuc /* {{{ Modular arithmetic */
1525ebfedea0SLionel Sambuc 
1526ebfedea0SLionel Sambuc #if MP_MODARITH
1527ebfedea0SLionel Sambuc /* {{{ mp_addmod(a, b, m, c) */
1528ebfedea0SLionel Sambuc 
1529ebfedea0SLionel Sambuc /*
1530ebfedea0SLionel Sambuc   mp_addmod(a, b, m, c)
1531ebfedea0SLionel Sambuc 
1532ebfedea0SLionel Sambuc   Compute c = (a + b) mod m
1533ebfedea0SLionel Sambuc  */
1534ebfedea0SLionel Sambuc 
mp_addmod(mp_int * a,mp_int * b,mp_int * m,mp_int * c)1535ebfedea0SLionel Sambuc mp_err mp_addmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c)
1536ebfedea0SLionel Sambuc {
1537ebfedea0SLionel Sambuc   mp_err  res;
1538ebfedea0SLionel Sambuc 
1539ebfedea0SLionel Sambuc   ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);
1540ebfedea0SLionel Sambuc 
1541ebfedea0SLionel Sambuc   if((res = mp_add(a, b, c)) != MP_OKAY)
1542ebfedea0SLionel Sambuc     return res;
1543ebfedea0SLionel Sambuc   if((res = mp_mod(c, m, c)) != MP_OKAY)
1544ebfedea0SLionel Sambuc     return res;
1545ebfedea0SLionel Sambuc 
1546ebfedea0SLionel Sambuc   return MP_OKAY;
1547ebfedea0SLionel Sambuc 
1548ebfedea0SLionel Sambuc }
1549ebfedea0SLionel Sambuc 
1550ebfedea0SLionel Sambuc /* }}} */
1551ebfedea0SLionel Sambuc 
1552ebfedea0SLionel Sambuc /* {{{ mp_submod(a, b, m, c) */
1553ebfedea0SLionel Sambuc 
1554ebfedea0SLionel Sambuc /*
1555ebfedea0SLionel Sambuc   mp_submod(a, b, m, c)
1556ebfedea0SLionel Sambuc 
1557ebfedea0SLionel Sambuc   Compute c = (a - b) mod m
1558ebfedea0SLionel Sambuc  */
1559ebfedea0SLionel Sambuc 
mp_submod(mp_int * a,mp_int * b,mp_int * m,mp_int * c)1560ebfedea0SLionel Sambuc mp_err mp_submod(mp_int *a, mp_int *b, mp_int *m, mp_int *c)
1561ebfedea0SLionel Sambuc {
1562ebfedea0SLionel Sambuc   mp_err  res;
1563ebfedea0SLionel Sambuc 
1564ebfedea0SLionel Sambuc   ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);
1565ebfedea0SLionel Sambuc 
1566ebfedea0SLionel Sambuc   if((res = mp_sub(a, b, c)) != MP_OKAY)
1567ebfedea0SLionel Sambuc     return res;
1568ebfedea0SLionel Sambuc   if((res = mp_mod(c, m, c)) != MP_OKAY)
1569ebfedea0SLionel Sambuc     return res;
1570ebfedea0SLionel Sambuc 
1571ebfedea0SLionel Sambuc   return MP_OKAY;
1572ebfedea0SLionel Sambuc 
1573ebfedea0SLionel Sambuc }
1574ebfedea0SLionel Sambuc 
1575ebfedea0SLionel Sambuc /* }}} */
1576ebfedea0SLionel Sambuc 
1577ebfedea0SLionel Sambuc /* {{{ mp_mulmod(a, b, m, c) */
1578ebfedea0SLionel Sambuc 
1579ebfedea0SLionel Sambuc /*
1580ebfedea0SLionel Sambuc   mp_mulmod(a, b, m, c)
1581ebfedea0SLionel Sambuc 
1582ebfedea0SLionel Sambuc   Compute c = (a * b) mod m
1583ebfedea0SLionel Sambuc  */
1584ebfedea0SLionel Sambuc 
mp_mulmod(mp_int * a,mp_int * b,mp_int * m,mp_int * c)1585ebfedea0SLionel Sambuc mp_err mp_mulmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c)
1586ebfedea0SLionel Sambuc {
1587ebfedea0SLionel Sambuc   mp_err  res;
1588ebfedea0SLionel Sambuc 
1589ebfedea0SLionel Sambuc   ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);
1590ebfedea0SLionel Sambuc 
1591ebfedea0SLionel Sambuc   if((res = mp_mul(a, b, c)) != MP_OKAY)
1592ebfedea0SLionel Sambuc     return res;
1593ebfedea0SLionel Sambuc   if((res = mp_mod(c, m, c)) != MP_OKAY)
1594ebfedea0SLionel Sambuc     return res;
1595ebfedea0SLionel Sambuc 
1596ebfedea0SLionel Sambuc   return MP_OKAY;
1597ebfedea0SLionel Sambuc 
1598ebfedea0SLionel Sambuc }
1599ebfedea0SLionel Sambuc 
1600ebfedea0SLionel Sambuc /* }}} */
1601ebfedea0SLionel Sambuc 
1602ebfedea0SLionel Sambuc /* {{{ mp_sqrmod(a, m, c) */
1603ebfedea0SLionel Sambuc 
1604ebfedea0SLionel Sambuc #if MP_SQUARE
mp_sqrmod(mp_int * a,mp_int * m,mp_int * c)1605ebfedea0SLionel Sambuc mp_err mp_sqrmod(mp_int *a, mp_int *m, mp_int *c)
1606ebfedea0SLionel Sambuc {
1607ebfedea0SLionel Sambuc   mp_err  res;
1608ebfedea0SLionel Sambuc 
1609ebfedea0SLionel Sambuc   ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);
1610ebfedea0SLionel Sambuc 
1611ebfedea0SLionel Sambuc   if((res = mp_sqr(a, c)) != MP_OKAY)
1612ebfedea0SLionel Sambuc     return res;
1613ebfedea0SLionel Sambuc   if((res = mp_mod(c, m, c)) != MP_OKAY)
1614ebfedea0SLionel Sambuc     return res;
1615ebfedea0SLionel Sambuc 
1616ebfedea0SLionel Sambuc   return MP_OKAY;
1617ebfedea0SLionel Sambuc 
1618ebfedea0SLionel Sambuc } /* end mp_sqrmod() */
1619ebfedea0SLionel Sambuc #endif
1620ebfedea0SLionel Sambuc 
1621ebfedea0SLionel Sambuc /* }}} */
1622ebfedea0SLionel Sambuc 
1623ebfedea0SLionel Sambuc /* {{{ mp_exptmod(a, b, m, c) */
1624ebfedea0SLionel Sambuc 
1625ebfedea0SLionel Sambuc /*
1626ebfedea0SLionel Sambuc   mp_exptmod(a, b, m, c)
1627ebfedea0SLionel Sambuc 
1628ebfedea0SLionel Sambuc   Compute c = (a ** b) mod m.  Uses a standard square-and-multiply
1629ebfedea0SLionel Sambuc   method with modular reductions at each step. (This is basically the
1630ebfedea0SLionel Sambuc   same code as mp_expt(), except for the addition of the reductions)
1631ebfedea0SLionel Sambuc 
1632ebfedea0SLionel Sambuc   The modular reductions are done using Barrett's algorithm (see
1633ebfedea0SLionel Sambuc   s_mp_reduce() below for details)
1634ebfedea0SLionel Sambuc  */
1635ebfedea0SLionel Sambuc 
mp_exptmod(mp_int * a,mp_int * b,mp_int * m,mp_int * c)1636ebfedea0SLionel Sambuc mp_err mp_exptmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c)
1637ebfedea0SLionel Sambuc {
1638ebfedea0SLionel Sambuc   mp_int   s, x, mu;
1639ebfedea0SLionel Sambuc   mp_err   res;
1640ebfedea0SLionel Sambuc   mp_digit d, *db = DIGITS(b);
1641ebfedea0SLionel Sambuc   mp_size  ub = USED(b);
1642ebfedea0SLionel Sambuc   int      dig, bit;
1643ebfedea0SLionel Sambuc 
1644ebfedea0SLionel Sambuc   ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
1645ebfedea0SLionel Sambuc 
1646ebfedea0SLionel Sambuc   if(mp_cmp_z(b) < 0 || mp_cmp_z(m) <= 0)
1647ebfedea0SLionel Sambuc     return MP_RANGE;
1648ebfedea0SLionel Sambuc 
1649ebfedea0SLionel Sambuc   if((res = mp_init(&s)) != MP_OKAY)
1650ebfedea0SLionel Sambuc     return res;
1651ebfedea0SLionel Sambuc   if((res = mp_init_copy(&x, a)) != MP_OKAY)
1652ebfedea0SLionel Sambuc     goto X;
1653ebfedea0SLionel Sambuc   if((res = mp_mod(&x, m, &x)) != MP_OKAY ||
1654ebfedea0SLionel Sambuc      (res = mp_init(&mu)) != MP_OKAY)
1655ebfedea0SLionel Sambuc     goto MU;
1656ebfedea0SLionel Sambuc 
1657ebfedea0SLionel Sambuc   mp_set(&s, 1);
1658ebfedea0SLionel Sambuc 
1659ebfedea0SLionel Sambuc   /* mu = b^2k / m */
1660ebfedea0SLionel Sambuc   s_mp_add_d(&mu, 1);
1661ebfedea0SLionel Sambuc   s_mp_lshd(&mu, 2 * USED(m));
1662ebfedea0SLionel Sambuc   if((res = mp_div(&mu, m, &mu, NULL)) != MP_OKAY)
1663ebfedea0SLionel Sambuc     goto CLEANUP;
1664ebfedea0SLionel Sambuc 
1665ebfedea0SLionel Sambuc   /* Loop over digits of b in ascending order, except highest order */
1666ebfedea0SLionel Sambuc   for(dig = 0; dig < (ub - 1); dig++) {
1667ebfedea0SLionel Sambuc     d = *db++;
1668ebfedea0SLionel Sambuc 
1669ebfedea0SLionel Sambuc     /* Loop over the bits of the lower-order digits */
1670ebfedea0SLionel Sambuc     for(bit = 0; bit < DIGIT_BIT; bit++) {
1671ebfedea0SLionel Sambuc       if(d & 1) {
1672ebfedea0SLionel Sambuc 	if((res = s_mp_mul(&s, &x)) != MP_OKAY)
1673ebfedea0SLionel Sambuc 	  goto CLEANUP;
1674ebfedea0SLionel Sambuc 	if((res = s_mp_reduce(&s, m, &mu)) != MP_OKAY)
1675ebfedea0SLionel Sambuc 	  goto CLEANUP;
1676ebfedea0SLionel Sambuc       }
1677ebfedea0SLionel Sambuc 
1678ebfedea0SLionel Sambuc       d >>= 1;
1679ebfedea0SLionel Sambuc 
1680ebfedea0SLionel Sambuc       if((res = s_mp_sqr(&x)) != MP_OKAY)
1681ebfedea0SLionel Sambuc 	goto CLEANUP;
1682ebfedea0SLionel Sambuc       if((res = s_mp_reduce(&x, m, &mu)) != MP_OKAY)
1683ebfedea0SLionel Sambuc 	goto CLEANUP;
1684ebfedea0SLionel Sambuc     }
1685ebfedea0SLionel Sambuc   }
1686ebfedea0SLionel Sambuc 
1687ebfedea0SLionel Sambuc   /* Now do the last digit... */
1688ebfedea0SLionel Sambuc   d = *db;
1689ebfedea0SLionel Sambuc 
1690ebfedea0SLionel Sambuc   while(d) {
1691ebfedea0SLionel Sambuc     if(d & 1) {
1692ebfedea0SLionel Sambuc       if((res = s_mp_mul(&s, &x)) != MP_OKAY)
1693ebfedea0SLionel Sambuc 	goto CLEANUP;
1694ebfedea0SLionel Sambuc       if((res = s_mp_reduce(&s, m, &mu)) != MP_OKAY)
1695ebfedea0SLionel Sambuc 	goto CLEANUP;
1696ebfedea0SLionel Sambuc     }
1697ebfedea0SLionel Sambuc 
1698ebfedea0SLionel Sambuc     d >>= 1;
1699ebfedea0SLionel Sambuc 
1700ebfedea0SLionel Sambuc     if((res = s_mp_sqr(&x)) != MP_OKAY)
1701ebfedea0SLionel Sambuc       goto CLEANUP;
1702ebfedea0SLionel Sambuc     if((res = s_mp_reduce(&x, m, &mu)) != MP_OKAY)
1703ebfedea0SLionel Sambuc       goto CLEANUP;
1704ebfedea0SLionel Sambuc   }
1705ebfedea0SLionel Sambuc 
1706ebfedea0SLionel Sambuc   s_mp_exch(&s, c);
1707ebfedea0SLionel Sambuc 
1708ebfedea0SLionel Sambuc  CLEANUP:
1709ebfedea0SLionel Sambuc   mp_clear(&mu);
1710ebfedea0SLionel Sambuc  MU:
1711ebfedea0SLionel Sambuc   mp_clear(&x);
1712ebfedea0SLionel Sambuc  X:
1713ebfedea0SLionel Sambuc   mp_clear(&s);
1714ebfedea0SLionel Sambuc 
1715ebfedea0SLionel Sambuc   return res;
1716ebfedea0SLionel Sambuc 
1717ebfedea0SLionel Sambuc } /* end mp_exptmod() */
1718ebfedea0SLionel Sambuc 
1719ebfedea0SLionel Sambuc /* }}} */
1720ebfedea0SLionel Sambuc 
1721ebfedea0SLionel Sambuc /* {{{ mp_exptmod_d(a, d, m, c) */
1722ebfedea0SLionel Sambuc 
mp_exptmod_d(mp_int * a,mp_digit d,mp_int * m,mp_int * c)1723ebfedea0SLionel Sambuc mp_err mp_exptmod_d(mp_int *a, mp_digit d, mp_int *m, mp_int *c)
1724ebfedea0SLionel Sambuc {
1725ebfedea0SLionel Sambuc   mp_int   s, x;
1726ebfedea0SLionel Sambuc   mp_err   res;
1727ebfedea0SLionel Sambuc 
1728ebfedea0SLionel Sambuc   ARGCHK(a != NULL && c != NULL, MP_BADARG);
1729ebfedea0SLionel Sambuc 
1730ebfedea0SLionel Sambuc   if((res = mp_init(&s)) != MP_OKAY)
1731ebfedea0SLionel Sambuc     return res;
1732ebfedea0SLionel Sambuc   if((res = mp_init_copy(&x, a)) != MP_OKAY)
1733ebfedea0SLionel Sambuc     goto X;
1734ebfedea0SLionel Sambuc 
1735ebfedea0SLionel Sambuc   mp_set(&s, 1);
1736ebfedea0SLionel Sambuc 
1737ebfedea0SLionel Sambuc   while(d != 0) {
1738ebfedea0SLionel Sambuc     if(d & 1) {
1739ebfedea0SLionel Sambuc       if((res = s_mp_mul(&s, &x)) != MP_OKAY ||
1740ebfedea0SLionel Sambuc 	 (res = mp_mod(&s, m, &s)) != MP_OKAY)
1741ebfedea0SLionel Sambuc 	goto CLEANUP;
1742ebfedea0SLionel Sambuc     }
1743ebfedea0SLionel Sambuc 
1744ebfedea0SLionel Sambuc     d /= 2;
1745ebfedea0SLionel Sambuc 
1746ebfedea0SLionel Sambuc     if((res = s_mp_sqr(&x)) != MP_OKAY ||
1747ebfedea0SLionel Sambuc        (res = mp_mod(&x, m, &x)) != MP_OKAY)
1748ebfedea0SLionel Sambuc       goto CLEANUP;
1749ebfedea0SLionel Sambuc   }
1750ebfedea0SLionel Sambuc 
1751ebfedea0SLionel Sambuc   s_mp_exch(&s, c);
1752ebfedea0SLionel Sambuc 
1753ebfedea0SLionel Sambuc CLEANUP:
1754ebfedea0SLionel Sambuc   mp_clear(&x);
1755ebfedea0SLionel Sambuc X:
1756ebfedea0SLionel Sambuc   mp_clear(&s);
1757ebfedea0SLionel Sambuc 
1758ebfedea0SLionel Sambuc   return res;
1759ebfedea0SLionel Sambuc 
1760ebfedea0SLionel Sambuc } /* end mp_exptmod_d() */
1761ebfedea0SLionel Sambuc 
1762ebfedea0SLionel Sambuc /* }}} */
1763ebfedea0SLionel Sambuc #endif /* if MP_MODARITH */
1764ebfedea0SLionel Sambuc 
1765ebfedea0SLionel Sambuc /* }}} */
1766ebfedea0SLionel Sambuc 
1767ebfedea0SLionel Sambuc /*------------------------------------------------------------------------*/
1768ebfedea0SLionel Sambuc /* {{{ Comparison functions */
1769ebfedea0SLionel Sambuc 
1770ebfedea0SLionel Sambuc /* {{{ mp_cmp_z(a) */
1771ebfedea0SLionel Sambuc 
1772ebfedea0SLionel Sambuc /*
1773ebfedea0SLionel Sambuc   mp_cmp_z(a)
1774ebfedea0SLionel Sambuc 
1775ebfedea0SLionel Sambuc   Compare a <=> 0.  Returns <0 if a<0, 0 if a=0, >0 if a>0.
1776ebfedea0SLionel Sambuc  */
1777ebfedea0SLionel Sambuc 
mp_cmp_z(mp_int * a)1778ebfedea0SLionel Sambuc int    mp_cmp_z(mp_int *a)
1779ebfedea0SLionel Sambuc {
1780ebfedea0SLionel Sambuc   if(SIGN(a) == MP_NEG)
1781ebfedea0SLionel Sambuc     return MP_LT;
1782ebfedea0SLionel Sambuc   else if(USED(a) == 1 && DIGIT(a, 0) == 0)
1783ebfedea0SLionel Sambuc     return MP_EQ;
1784ebfedea0SLionel Sambuc   else
1785ebfedea0SLionel Sambuc     return MP_GT;
1786ebfedea0SLionel Sambuc 
1787ebfedea0SLionel Sambuc } /* end mp_cmp_z() */
1788ebfedea0SLionel Sambuc 
1789ebfedea0SLionel Sambuc /* }}} */
1790ebfedea0SLionel Sambuc 
1791ebfedea0SLionel Sambuc /* {{{ mp_cmp_d(a, d) */
1792ebfedea0SLionel Sambuc 
1793ebfedea0SLionel Sambuc /*
1794ebfedea0SLionel Sambuc   mp_cmp_d(a, d)
1795ebfedea0SLionel Sambuc 
1796ebfedea0SLionel Sambuc   Compare a <=> d.  Returns <0 if a<d, 0 if a=d, >0 if a>d
1797ebfedea0SLionel Sambuc  */
1798ebfedea0SLionel Sambuc 
mp_cmp_d(mp_int * a,mp_digit d)1799ebfedea0SLionel Sambuc int    mp_cmp_d(mp_int *a, mp_digit d)
1800ebfedea0SLionel Sambuc {
1801ebfedea0SLionel Sambuc   ARGCHK(a != NULL, MP_EQ);
1802ebfedea0SLionel Sambuc 
1803ebfedea0SLionel Sambuc   if(SIGN(a) == MP_NEG)
1804ebfedea0SLionel Sambuc     return MP_LT;
1805ebfedea0SLionel Sambuc 
1806ebfedea0SLionel Sambuc   return s_mp_cmp_d(a, d);
1807ebfedea0SLionel Sambuc 
1808ebfedea0SLionel Sambuc } /* end mp_cmp_d() */
1809ebfedea0SLionel Sambuc 
1810ebfedea0SLionel Sambuc /* }}} */
1811ebfedea0SLionel Sambuc 
1812ebfedea0SLionel Sambuc /* {{{ mp_cmp(a, b) */
1813ebfedea0SLionel Sambuc 
mp_cmp(mp_int * a,mp_int * b)1814ebfedea0SLionel Sambuc int    mp_cmp(mp_int *a, mp_int *b)
1815ebfedea0SLionel Sambuc {
1816ebfedea0SLionel Sambuc   ARGCHK(a != NULL && b != NULL, MP_EQ);
1817ebfedea0SLionel Sambuc 
1818ebfedea0SLionel Sambuc   if(SIGN(a) == SIGN(b)) {
1819ebfedea0SLionel Sambuc     int  mag;
1820ebfedea0SLionel Sambuc 
1821ebfedea0SLionel Sambuc     if((mag = s_mp_cmp(a, b)) == MP_EQ)
1822ebfedea0SLionel Sambuc       return MP_EQ;
1823ebfedea0SLionel Sambuc 
1824ebfedea0SLionel Sambuc     if(SIGN(a) == MP_ZPOS)
1825ebfedea0SLionel Sambuc       return mag;
1826ebfedea0SLionel Sambuc     else
1827ebfedea0SLionel Sambuc       return -mag;
1828ebfedea0SLionel Sambuc 
1829ebfedea0SLionel Sambuc   } else if(SIGN(a) == MP_ZPOS) {
1830ebfedea0SLionel Sambuc     return MP_GT;
1831ebfedea0SLionel Sambuc   } else {
1832ebfedea0SLionel Sambuc     return MP_LT;
1833ebfedea0SLionel Sambuc   }
1834ebfedea0SLionel Sambuc 
1835ebfedea0SLionel Sambuc } /* end mp_cmp() */
1836ebfedea0SLionel Sambuc 
1837ebfedea0SLionel Sambuc /* }}} */
1838ebfedea0SLionel Sambuc 
1839ebfedea0SLionel Sambuc /* {{{ mp_cmp_mag(a, b) */
1840ebfedea0SLionel Sambuc 
1841ebfedea0SLionel Sambuc /*
1842ebfedea0SLionel Sambuc   mp_cmp_mag(a, b)
1843ebfedea0SLionel Sambuc 
1844ebfedea0SLionel Sambuc   Compares |a| <=> |b|, and returns an appropriate comparison result
1845ebfedea0SLionel Sambuc  */
1846ebfedea0SLionel Sambuc 
mp_cmp_mag(mp_int * a,mp_int * b)1847ebfedea0SLionel Sambuc int    mp_cmp_mag(mp_int *a, mp_int *b)
1848ebfedea0SLionel Sambuc {
1849ebfedea0SLionel Sambuc   ARGCHK(a != NULL && b != NULL, MP_EQ);
1850ebfedea0SLionel Sambuc 
1851ebfedea0SLionel Sambuc   return s_mp_cmp(a, b);
1852ebfedea0SLionel Sambuc 
1853ebfedea0SLionel Sambuc } /* end mp_cmp_mag() */
1854ebfedea0SLionel Sambuc 
1855ebfedea0SLionel Sambuc /* }}} */
1856ebfedea0SLionel Sambuc 
1857ebfedea0SLionel Sambuc /* {{{ mp_cmp_int(a, z) */
1858ebfedea0SLionel Sambuc 
1859ebfedea0SLionel Sambuc /*
1860ebfedea0SLionel Sambuc   This just converts z to an mp_int, and uses the existing comparison
1861ebfedea0SLionel Sambuc   routines.  This is sort of inefficient, but it's not clear to me how
1862ebfedea0SLionel Sambuc   frequently this wil get used anyway.  For small positive constants,
1863ebfedea0SLionel Sambuc   you can always use mp_cmp_d(), and for zero, there is mp_cmp_z().
1864ebfedea0SLionel Sambuc  */
mp_cmp_int(mp_int * a,long z)1865ebfedea0SLionel Sambuc int    mp_cmp_int(mp_int *a, long z)
1866ebfedea0SLionel Sambuc {
1867ebfedea0SLionel Sambuc   mp_int  tmp;
1868ebfedea0SLionel Sambuc   int     out;
1869ebfedea0SLionel Sambuc 
1870ebfedea0SLionel Sambuc   ARGCHK(a != NULL, MP_EQ);
1871ebfedea0SLionel Sambuc 
1872ebfedea0SLionel Sambuc   mp_init(&tmp); mp_set_int(&tmp, z);
1873ebfedea0SLionel Sambuc   out = mp_cmp(a, &tmp);
1874ebfedea0SLionel Sambuc   mp_clear(&tmp);
1875ebfedea0SLionel Sambuc 
1876ebfedea0SLionel Sambuc   return out;
1877ebfedea0SLionel Sambuc 
1878ebfedea0SLionel Sambuc } /* end mp_cmp_int() */
1879ebfedea0SLionel Sambuc 
1880ebfedea0SLionel Sambuc /* }}} */
1881ebfedea0SLionel Sambuc 
1882ebfedea0SLionel Sambuc /* {{{ mp_isodd(a) */
1883ebfedea0SLionel Sambuc 
1884ebfedea0SLionel Sambuc /*
1885ebfedea0SLionel Sambuc   mp_isodd(a)
1886ebfedea0SLionel Sambuc 
1887ebfedea0SLionel Sambuc   Returns a true (non-zero) value if a is odd, false (zero) otherwise.
1888ebfedea0SLionel Sambuc  */
mp_isodd(mp_int * a)1889ebfedea0SLionel Sambuc int    mp_isodd(mp_int *a)
1890ebfedea0SLionel Sambuc {
1891ebfedea0SLionel Sambuc   ARGCHK(a != NULL, 0);
1892ebfedea0SLionel Sambuc 
1893ebfedea0SLionel Sambuc   return (DIGIT(a, 0) & 1);
1894ebfedea0SLionel Sambuc 
1895ebfedea0SLionel Sambuc } /* end mp_isodd() */
1896ebfedea0SLionel Sambuc 
1897ebfedea0SLionel Sambuc /* }}} */
1898ebfedea0SLionel Sambuc 
1899ebfedea0SLionel Sambuc /* {{{ mp_iseven(a) */
1900ebfedea0SLionel Sambuc 
mp_iseven(mp_int * a)1901ebfedea0SLionel Sambuc int    mp_iseven(mp_int *a)
1902ebfedea0SLionel Sambuc {
1903ebfedea0SLionel Sambuc   return !mp_isodd(a);
1904ebfedea0SLionel Sambuc 
1905ebfedea0SLionel Sambuc } /* end mp_iseven() */
1906ebfedea0SLionel Sambuc 
1907ebfedea0SLionel Sambuc /* }}} */
1908ebfedea0SLionel Sambuc 
1909ebfedea0SLionel Sambuc /* }}} */
1910ebfedea0SLionel Sambuc 
1911ebfedea0SLionel Sambuc /*------------------------------------------------------------------------*/
1912ebfedea0SLionel Sambuc /* {{{ Number theoretic functions */
1913ebfedea0SLionel Sambuc 
1914ebfedea0SLionel Sambuc #if MP_NUMTH
1915ebfedea0SLionel Sambuc /* {{{ mp_gcd(a, b, c) */
1916ebfedea0SLionel Sambuc 
1917ebfedea0SLionel Sambuc /*
1918ebfedea0SLionel Sambuc   Like the old mp_gcd() function, except computes the GCD using the
1919ebfedea0SLionel Sambuc   binary algorithm due to Josef Stein in 1961 (via Knuth).
1920ebfedea0SLionel Sambuc  */
mp_gcd(mp_int * a,mp_int * b,mp_int * c)1921ebfedea0SLionel Sambuc mp_err mp_gcd(mp_int *a, mp_int *b, mp_int *c)
1922ebfedea0SLionel Sambuc {
1923ebfedea0SLionel Sambuc   mp_err   res;
1924ebfedea0SLionel Sambuc   mp_int   u, v, t;
1925ebfedea0SLionel Sambuc   mp_size  k = 0;
1926ebfedea0SLionel Sambuc 
1927ebfedea0SLionel Sambuc   ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
1928ebfedea0SLionel Sambuc 
1929ebfedea0SLionel Sambuc   if(mp_cmp_z(a) == MP_EQ && mp_cmp_z(b) == MP_EQ)
1930ebfedea0SLionel Sambuc       return MP_RANGE;
1931ebfedea0SLionel Sambuc   if(mp_cmp_z(a) == MP_EQ) {
1932ebfedea0SLionel Sambuc     return mp_copy(b, c);
1933ebfedea0SLionel Sambuc   } else if(mp_cmp_z(b) == MP_EQ) {
1934ebfedea0SLionel Sambuc     return mp_copy(a, c);
1935ebfedea0SLionel Sambuc   }
1936ebfedea0SLionel Sambuc 
1937ebfedea0SLionel Sambuc   if((res = mp_init(&t)) != MP_OKAY)
1938ebfedea0SLionel Sambuc     return res;
1939ebfedea0SLionel Sambuc   if((res = mp_init_copy(&u, a)) != MP_OKAY)
1940ebfedea0SLionel Sambuc     goto U;
1941ebfedea0SLionel Sambuc   if((res = mp_init_copy(&v, b)) != MP_OKAY)
1942ebfedea0SLionel Sambuc     goto V;
1943ebfedea0SLionel Sambuc 
1944ebfedea0SLionel Sambuc   SIGN(&u) = MP_ZPOS;
1945ebfedea0SLionel Sambuc   SIGN(&v) = MP_ZPOS;
1946ebfedea0SLionel Sambuc 
1947ebfedea0SLionel Sambuc   /* Divide out common factors of 2 until at least 1 of a, b is even */
1948ebfedea0SLionel Sambuc   while(mp_iseven(&u) && mp_iseven(&v)) {
1949ebfedea0SLionel Sambuc     s_mp_div_2(&u);
1950ebfedea0SLionel Sambuc     s_mp_div_2(&v);
1951ebfedea0SLionel Sambuc     ++k;
1952ebfedea0SLionel Sambuc   }
1953ebfedea0SLionel Sambuc 
1954ebfedea0SLionel Sambuc   /* Initialize t */
1955ebfedea0SLionel Sambuc   if(mp_isodd(&u)) {
1956ebfedea0SLionel Sambuc     if((res = mp_copy(&v, &t)) != MP_OKAY)
1957ebfedea0SLionel Sambuc       goto CLEANUP;
1958ebfedea0SLionel Sambuc 
1959ebfedea0SLionel Sambuc     /* t = -v */
1960ebfedea0SLionel Sambuc     if(SIGN(&v) == MP_ZPOS)
1961ebfedea0SLionel Sambuc       SIGN(&t) = MP_NEG;
1962ebfedea0SLionel Sambuc     else
1963ebfedea0SLionel Sambuc       SIGN(&t) = MP_ZPOS;
1964ebfedea0SLionel Sambuc 
1965ebfedea0SLionel Sambuc   } else {
1966ebfedea0SLionel Sambuc     if((res = mp_copy(&u, &t)) != MP_OKAY)
1967ebfedea0SLionel Sambuc       goto CLEANUP;
1968ebfedea0SLionel Sambuc 
1969ebfedea0SLionel Sambuc   }
1970ebfedea0SLionel Sambuc 
1971ebfedea0SLionel Sambuc   for(;;) {
1972ebfedea0SLionel Sambuc     while(mp_iseven(&t)) {
1973ebfedea0SLionel Sambuc       s_mp_div_2(&t);
1974ebfedea0SLionel Sambuc     }
1975ebfedea0SLionel Sambuc 
1976ebfedea0SLionel Sambuc     if(mp_cmp_z(&t) == MP_GT) {
1977ebfedea0SLionel Sambuc       if((res = mp_copy(&t, &u)) != MP_OKAY)
1978ebfedea0SLionel Sambuc 	goto CLEANUP;
1979ebfedea0SLionel Sambuc 
1980ebfedea0SLionel Sambuc     } else {
1981ebfedea0SLionel Sambuc       if((res = mp_copy(&t, &v)) != MP_OKAY)
1982ebfedea0SLionel Sambuc 	goto CLEANUP;
1983ebfedea0SLionel Sambuc 
1984ebfedea0SLionel Sambuc       /* v = -t */
1985ebfedea0SLionel Sambuc       if(SIGN(&t) == MP_ZPOS)
1986ebfedea0SLionel Sambuc 	SIGN(&v) = MP_NEG;
1987ebfedea0SLionel Sambuc       else
1988ebfedea0SLionel Sambuc 	SIGN(&v) = MP_ZPOS;
1989ebfedea0SLionel Sambuc     }
1990ebfedea0SLionel Sambuc 
1991ebfedea0SLionel Sambuc     if((res = mp_sub(&u, &v, &t)) != MP_OKAY)
1992ebfedea0SLionel Sambuc       goto CLEANUP;
1993ebfedea0SLionel Sambuc 
1994ebfedea0SLionel Sambuc     if(s_mp_cmp_d(&t, 0) == MP_EQ)
1995ebfedea0SLionel Sambuc       break;
1996ebfedea0SLionel Sambuc   }
1997ebfedea0SLionel Sambuc 
1998ebfedea0SLionel Sambuc   s_mp_2expt(&v, k);       /* v = 2^k   */
1999ebfedea0SLionel Sambuc   res = mp_mul(&u, &v, c); /* c = u * v */
2000ebfedea0SLionel Sambuc 
2001ebfedea0SLionel Sambuc  CLEANUP:
2002ebfedea0SLionel Sambuc   mp_clear(&v);
2003ebfedea0SLionel Sambuc  V:
2004ebfedea0SLionel Sambuc   mp_clear(&u);
2005ebfedea0SLionel Sambuc  U:
2006ebfedea0SLionel Sambuc   mp_clear(&t);
2007ebfedea0SLionel Sambuc 
2008ebfedea0SLionel Sambuc   return res;
2009ebfedea0SLionel Sambuc 
2010ebfedea0SLionel Sambuc } /* end mp_bgcd() */
2011ebfedea0SLionel Sambuc 
2012ebfedea0SLionel Sambuc /* }}} */
2013ebfedea0SLionel Sambuc 
2014ebfedea0SLionel Sambuc /* {{{ mp_lcm(a, b, c) */
2015ebfedea0SLionel Sambuc 
2016ebfedea0SLionel Sambuc /* We compute the least common multiple using the rule:
2017ebfedea0SLionel Sambuc 
2018ebfedea0SLionel Sambuc    ab = [a, b](a, b)
2019ebfedea0SLionel Sambuc 
2020ebfedea0SLionel Sambuc    ... by computing the product, and dividing out the gcd.
2021ebfedea0SLionel Sambuc  */
2022ebfedea0SLionel Sambuc 
mp_lcm(mp_int * a,mp_int * b,mp_int * c)2023ebfedea0SLionel Sambuc mp_err mp_lcm(mp_int *a, mp_int *b, mp_int *c)
2024ebfedea0SLionel Sambuc {
2025ebfedea0SLionel Sambuc   mp_int  gcd, prod;
2026ebfedea0SLionel Sambuc   mp_err  res;
2027ebfedea0SLionel Sambuc 
2028ebfedea0SLionel Sambuc   ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
2029ebfedea0SLionel Sambuc 
2030ebfedea0SLionel Sambuc   /* Set up temporaries */
2031ebfedea0SLionel Sambuc   if((res = mp_init(&gcd)) != MP_OKAY)
2032ebfedea0SLionel Sambuc     return res;
2033ebfedea0SLionel Sambuc   if((res = mp_init(&prod)) != MP_OKAY)
2034ebfedea0SLionel Sambuc     goto GCD;
2035ebfedea0SLionel Sambuc 
2036ebfedea0SLionel Sambuc   if((res = mp_mul(a, b, &prod)) != MP_OKAY)
2037ebfedea0SLionel Sambuc     goto CLEANUP;
2038ebfedea0SLionel Sambuc   if((res = mp_gcd(a, b, &gcd)) != MP_OKAY)
2039ebfedea0SLionel Sambuc     goto CLEANUP;
2040ebfedea0SLionel Sambuc 
2041ebfedea0SLionel Sambuc   res = mp_div(&prod, &gcd, c, NULL);
2042ebfedea0SLionel Sambuc 
2043ebfedea0SLionel Sambuc  CLEANUP:
2044ebfedea0SLionel Sambuc   mp_clear(&prod);
2045ebfedea0SLionel Sambuc  GCD:
2046ebfedea0SLionel Sambuc   mp_clear(&gcd);
2047ebfedea0SLionel Sambuc 
2048ebfedea0SLionel Sambuc   return res;
2049ebfedea0SLionel Sambuc 
2050ebfedea0SLionel Sambuc } /* end mp_lcm() */
2051ebfedea0SLionel Sambuc 
2052ebfedea0SLionel Sambuc /* }}} */
2053ebfedea0SLionel Sambuc 
2054ebfedea0SLionel Sambuc /* {{{ mp_xgcd(a, b, g, x, y) */
2055ebfedea0SLionel Sambuc 
2056ebfedea0SLionel Sambuc /*
2057ebfedea0SLionel Sambuc   mp_xgcd(a, b, g, x, y)
2058ebfedea0SLionel Sambuc 
2059ebfedea0SLionel Sambuc   Compute g = (a, b) and values x and y satisfying Bezout's identity
2060ebfedea0SLionel Sambuc   (that is, ax + by = g).  This uses the extended binary GCD algorithm
2061ebfedea0SLionel Sambuc   based on the Stein algorithm used for mp_gcd()
2062ebfedea0SLionel Sambuc  */
2063ebfedea0SLionel Sambuc 
mp_xgcd(mp_int * a,mp_int * b,mp_int * g,mp_int * x,mp_int * y)2064ebfedea0SLionel Sambuc mp_err mp_xgcd(mp_int *a, mp_int *b, mp_int *g, mp_int *x, mp_int *y)
2065ebfedea0SLionel Sambuc {
2066ebfedea0SLionel Sambuc   mp_int   gx, xc, yc, u, v, A, B, C, D;
2067ebfedea0SLionel Sambuc   mp_int  *clean[9];
2068ebfedea0SLionel Sambuc   mp_err   res;
2069ebfedea0SLionel Sambuc   int      last = -1;
2070ebfedea0SLionel Sambuc 
2071ebfedea0SLionel Sambuc   if(mp_cmp_z(b) == 0)
2072ebfedea0SLionel Sambuc     return MP_RANGE;
2073ebfedea0SLionel Sambuc 
2074ebfedea0SLionel Sambuc   /* Initialize all these variables we need */
2075ebfedea0SLionel Sambuc   if((res = mp_init(&u)) != MP_OKAY) goto CLEANUP;
2076ebfedea0SLionel Sambuc   clean[++last] = &u;
2077ebfedea0SLionel Sambuc   if((res = mp_init(&v)) != MP_OKAY) goto CLEANUP;
2078ebfedea0SLionel Sambuc   clean[++last] = &v;
2079ebfedea0SLionel Sambuc   if((res = mp_init(&gx)) != MP_OKAY) goto CLEANUP;
2080ebfedea0SLionel Sambuc   clean[++last] = &gx;
2081ebfedea0SLionel Sambuc   if((res = mp_init(&A)) != MP_OKAY) goto CLEANUP;
2082ebfedea0SLionel Sambuc   clean[++last] = &A;
2083ebfedea0SLionel Sambuc   if((res = mp_init(&B)) != MP_OKAY) goto CLEANUP;
2084ebfedea0SLionel Sambuc   clean[++last] = &B;
2085ebfedea0SLionel Sambuc   if((res = mp_init(&C)) != MP_OKAY) goto CLEANUP;
2086ebfedea0SLionel Sambuc   clean[++last] = &C;
2087ebfedea0SLionel Sambuc   if((res = mp_init(&D)) != MP_OKAY) goto CLEANUP;
2088ebfedea0SLionel Sambuc   clean[++last] = &D;
2089ebfedea0SLionel Sambuc   if((res = mp_init_copy(&xc, a)) != MP_OKAY) goto CLEANUP;
2090ebfedea0SLionel Sambuc   clean[++last] = &xc;
2091ebfedea0SLionel Sambuc   mp_abs(&xc, &xc);
2092ebfedea0SLionel Sambuc   if((res = mp_init_copy(&yc, b)) != MP_OKAY) goto CLEANUP;
2093ebfedea0SLionel Sambuc   clean[++last] = &yc;
2094ebfedea0SLionel Sambuc   mp_abs(&yc, &yc);
2095ebfedea0SLionel Sambuc 
2096ebfedea0SLionel Sambuc   mp_set(&gx, 1);
2097ebfedea0SLionel Sambuc 
2098ebfedea0SLionel Sambuc   /* Divide by two until at least one of them is even */
2099ebfedea0SLionel Sambuc   while(mp_iseven(&xc) && mp_iseven(&yc)) {
2100ebfedea0SLionel Sambuc     s_mp_div_2(&xc);
2101ebfedea0SLionel Sambuc     s_mp_div_2(&yc);
2102ebfedea0SLionel Sambuc     if((res = s_mp_mul_2(&gx)) != MP_OKAY)
2103ebfedea0SLionel Sambuc       goto CLEANUP;
2104ebfedea0SLionel Sambuc   }
2105ebfedea0SLionel Sambuc 
2106ebfedea0SLionel Sambuc   mp_copy(&xc, &u);
2107ebfedea0SLionel Sambuc   mp_copy(&yc, &v);
2108ebfedea0SLionel Sambuc   mp_set(&A, 1); mp_set(&D, 1);
2109ebfedea0SLionel Sambuc 
2110ebfedea0SLionel Sambuc   /* Loop through binary GCD algorithm */
2111ebfedea0SLionel Sambuc   for(;;) {
2112ebfedea0SLionel Sambuc     while(mp_iseven(&u)) {
2113ebfedea0SLionel Sambuc       s_mp_div_2(&u);
2114ebfedea0SLionel Sambuc 
2115ebfedea0SLionel Sambuc       if(mp_iseven(&A) && mp_iseven(&B)) {
2116ebfedea0SLionel Sambuc 	s_mp_div_2(&A); s_mp_div_2(&B);
2117ebfedea0SLionel Sambuc       } else {
2118ebfedea0SLionel Sambuc 	if((res = mp_add(&A, &yc, &A)) != MP_OKAY) goto CLEANUP;
2119ebfedea0SLionel Sambuc 	s_mp_div_2(&A);
2120ebfedea0SLionel Sambuc 	if((res = mp_sub(&B, &xc, &B)) != MP_OKAY) goto CLEANUP;
2121ebfedea0SLionel Sambuc 	s_mp_div_2(&B);
2122ebfedea0SLionel Sambuc       }
2123ebfedea0SLionel Sambuc     }
2124ebfedea0SLionel Sambuc 
2125ebfedea0SLionel Sambuc     while(mp_iseven(&v)) {
2126ebfedea0SLionel Sambuc       s_mp_div_2(&v);
2127ebfedea0SLionel Sambuc 
2128ebfedea0SLionel Sambuc       if(mp_iseven(&C) && mp_iseven(&D)) {
2129ebfedea0SLionel Sambuc 	s_mp_div_2(&C); s_mp_div_2(&D);
2130ebfedea0SLionel Sambuc       } else {
2131ebfedea0SLionel Sambuc 	if((res = mp_add(&C, &yc, &C)) != MP_OKAY) goto CLEANUP;
2132ebfedea0SLionel Sambuc 	s_mp_div_2(&C);
2133ebfedea0SLionel Sambuc 	if((res = mp_sub(&D, &xc, &D)) != MP_OKAY) goto CLEANUP;
2134ebfedea0SLionel Sambuc 	s_mp_div_2(&D);
2135ebfedea0SLionel Sambuc       }
2136ebfedea0SLionel Sambuc     }
2137ebfedea0SLionel Sambuc 
2138ebfedea0SLionel Sambuc     if(mp_cmp(&u, &v) >= 0) {
2139ebfedea0SLionel Sambuc       if((res = mp_sub(&u, &v, &u)) != MP_OKAY) goto CLEANUP;
2140ebfedea0SLionel Sambuc       if((res = mp_sub(&A, &C, &A)) != MP_OKAY) goto CLEANUP;
2141ebfedea0SLionel Sambuc       if((res = mp_sub(&B, &D, &B)) != MP_OKAY) goto CLEANUP;
2142ebfedea0SLionel Sambuc 
2143ebfedea0SLionel Sambuc     } else {
2144ebfedea0SLionel Sambuc       if((res = mp_sub(&v, &u, &v)) != MP_OKAY) goto CLEANUP;
2145ebfedea0SLionel Sambuc       if((res = mp_sub(&C, &A, &C)) != MP_OKAY) goto CLEANUP;
2146ebfedea0SLionel Sambuc       if((res = mp_sub(&D, &B, &D)) != MP_OKAY) goto CLEANUP;
2147ebfedea0SLionel Sambuc 
2148ebfedea0SLionel Sambuc     }
2149ebfedea0SLionel Sambuc 
2150ebfedea0SLionel Sambuc     /* If we're done, copy results to output */
2151ebfedea0SLionel Sambuc     if(mp_cmp_z(&u) == 0) {
2152ebfedea0SLionel Sambuc       if(x)
2153ebfedea0SLionel Sambuc 	if((res = mp_copy(&C, x)) != MP_OKAY) goto CLEANUP;
2154ebfedea0SLionel Sambuc 
2155ebfedea0SLionel Sambuc       if(y)
2156ebfedea0SLionel Sambuc 	if((res = mp_copy(&D, y)) != MP_OKAY) goto CLEANUP;
2157ebfedea0SLionel Sambuc 
2158ebfedea0SLionel Sambuc       if(g)
2159ebfedea0SLionel Sambuc 	if((res = mp_mul(&gx, &v, g)) != MP_OKAY) goto CLEANUP;
2160ebfedea0SLionel Sambuc 
2161ebfedea0SLionel Sambuc       break;
2162ebfedea0SLionel Sambuc     }
2163ebfedea0SLionel Sambuc   }
2164ebfedea0SLionel Sambuc 
2165ebfedea0SLionel Sambuc  CLEANUP:
2166ebfedea0SLionel Sambuc   while(last >= 0)
2167ebfedea0SLionel Sambuc     mp_clear(clean[last--]);
2168ebfedea0SLionel Sambuc 
2169ebfedea0SLionel Sambuc   return res;
2170ebfedea0SLionel Sambuc 
2171ebfedea0SLionel Sambuc } /* end mp_xgcd() */
2172ebfedea0SLionel Sambuc 
2173ebfedea0SLionel Sambuc /* }}} */
2174ebfedea0SLionel Sambuc 
2175ebfedea0SLionel Sambuc /* {{{ mp_invmod(a, m, c) */
2176ebfedea0SLionel Sambuc 
2177ebfedea0SLionel Sambuc /*
2178ebfedea0SLionel Sambuc   mp_invmod(a, m, c)
2179ebfedea0SLionel Sambuc 
2180ebfedea0SLionel Sambuc   Compute c = a^-1 (mod m), if there is an inverse for a (mod m).
2181ebfedea0SLionel Sambuc   This is equivalent to the question of whether (a, m) = 1.  If not,
2182ebfedea0SLionel Sambuc   MP_UNDEF is returned, and there is no inverse.
2183ebfedea0SLionel Sambuc  */
2184ebfedea0SLionel Sambuc 
mp_invmod(mp_int * a,mp_int * m,mp_int * c)2185ebfedea0SLionel Sambuc mp_err mp_invmod(mp_int *a, mp_int *m, mp_int *c)
2186ebfedea0SLionel Sambuc {
2187ebfedea0SLionel Sambuc   mp_int  g, x;
2188ebfedea0SLionel Sambuc   mp_err  res;
2189ebfedea0SLionel Sambuc 
2190ebfedea0SLionel Sambuc   ARGCHK(a && m && c, MP_BADARG);
2191ebfedea0SLionel Sambuc 
2192ebfedea0SLionel Sambuc   if(mp_cmp_z(a) == 0 || mp_cmp_z(m) == 0)
2193ebfedea0SLionel Sambuc     return MP_RANGE;
2194ebfedea0SLionel Sambuc 
2195ebfedea0SLionel Sambuc   if((res = mp_init(&g)) != MP_OKAY)
2196ebfedea0SLionel Sambuc     return res;
2197ebfedea0SLionel Sambuc   if((res = mp_init(&x)) != MP_OKAY)
2198ebfedea0SLionel Sambuc     goto X;
2199ebfedea0SLionel Sambuc 
2200ebfedea0SLionel Sambuc   if((res = mp_xgcd(a, m, &g, &x, NULL)) != MP_OKAY)
2201ebfedea0SLionel Sambuc     goto CLEANUP;
2202ebfedea0SLionel Sambuc 
2203ebfedea0SLionel Sambuc   if(mp_cmp_d(&g, 1) != MP_EQ) {
2204ebfedea0SLionel Sambuc     res = MP_UNDEF;
2205ebfedea0SLionel Sambuc     goto CLEANUP;
2206ebfedea0SLionel Sambuc   }
2207ebfedea0SLionel Sambuc 
2208ebfedea0SLionel Sambuc   res = mp_mod(&x, m, c);
2209ebfedea0SLionel Sambuc   SIGN(c) = SIGN(a);
2210ebfedea0SLionel Sambuc 
2211ebfedea0SLionel Sambuc CLEANUP:
2212ebfedea0SLionel Sambuc   mp_clear(&x);
2213ebfedea0SLionel Sambuc X:
2214ebfedea0SLionel Sambuc   mp_clear(&g);
2215ebfedea0SLionel Sambuc 
2216ebfedea0SLionel Sambuc   return res;
2217ebfedea0SLionel Sambuc 
2218ebfedea0SLionel Sambuc } /* end mp_invmod() */
2219ebfedea0SLionel Sambuc 
2220ebfedea0SLionel Sambuc /* }}} */
2221ebfedea0SLionel Sambuc #endif /* if MP_NUMTH */
2222ebfedea0SLionel Sambuc 
2223ebfedea0SLionel Sambuc /* }}} */
2224ebfedea0SLionel Sambuc 
2225ebfedea0SLionel Sambuc /*------------------------------------------------------------------------*/
2226ebfedea0SLionel Sambuc /* {{{ mp_print(mp, ofp) */
2227ebfedea0SLionel Sambuc 
2228ebfedea0SLionel Sambuc #if MP_IOFUNC
2229ebfedea0SLionel Sambuc /*
2230ebfedea0SLionel Sambuc   mp_print(mp, ofp)
2231ebfedea0SLionel Sambuc 
2232ebfedea0SLionel Sambuc   Print a textual representation of the given mp_int on the output
2233ebfedea0SLionel Sambuc   stream 'ofp'.  Output is generated using the internal radix.
2234ebfedea0SLionel Sambuc  */
2235ebfedea0SLionel Sambuc 
mp_print(mp_int * mp,FILE * ofp)2236ebfedea0SLionel Sambuc void   mp_print(mp_int *mp, FILE *ofp)
2237ebfedea0SLionel Sambuc {
2238ebfedea0SLionel Sambuc   int   ix;
2239ebfedea0SLionel Sambuc 
2240ebfedea0SLionel Sambuc   if(mp == NULL || ofp == NULL)
2241ebfedea0SLionel Sambuc     return;
2242ebfedea0SLionel Sambuc 
2243ebfedea0SLionel Sambuc   fputc((SIGN(mp) == MP_NEG) ? '-' : '+', ofp);
2244ebfedea0SLionel Sambuc 
2245ebfedea0SLionel Sambuc   for(ix = USED(mp) - 1; ix >= 0; ix--) {
2246ebfedea0SLionel Sambuc     fprintf(ofp, DIGIT_FMT, DIGIT(mp, ix));
2247ebfedea0SLionel Sambuc   }
2248ebfedea0SLionel Sambuc 
2249ebfedea0SLionel Sambuc } /* end mp_print() */
2250ebfedea0SLionel Sambuc 
2251ebfedea0SLionel Sambuc #endif /* if MP_IOFUNC */
2252ebfedea0SLionel Sambuc 
2253ebfedea0SLionel Sambuc /* }}} */
2254ebfedea0SLionel Sambuc 
2255ebfedea0SLionel Sambuc /*------------------------------------------------------------------------*/
2256ebfedea0SLionel Sambuc /* {{{ More I/O Functions */
2257ebfedea0SLionel Sambuc 
2258ebfedea0SLionel Sambuc /* {{{ mp_read_signed_bin(mp, str, len) */
2259ebfedea0SLionel Sambuc 
2260ebfedea0SLionel Sambuc /*
2261ebfedea0SLionel Sambuc    mp_read_signed_bin(mp, str, len)
2262ebfedea0SLionel Sambuc 
2263ebfedea0SLionel Sambuc    Read in a raw value (base 256) into the given mp_int
2264ebfedea0SLionel Sambuc  */
2265ebfedea0SLionel Sambuc 
mp_read_signed_bin(mp_int * mp,unsigned char * str,int len)2266ebfedea0SLionel Sambuc mp_err  mp_read_signed_bin(mp_int *mp, unsigned char *str, int len)
2267ebfedea0SLionel Sambuc {
2268ebfedea0SLionel Sambuc   mp_err         res;
2269ebfedea0SLionel Sambuc 
2270ebfedea0SLionel Sambuc   ARGCHK(mp != NULL && str != NULL && len > 0, MP_BADARG);
2271ebfedea0SLionel Sambuc 
2272ebfedea0SLionel Sambuc   if((res = mp_read_unsigned_bin(mp, str + 1, len - 1)) == MP_OKAY) {
2273ebfedea0SLionel Sambuc     /* Get sign from first byte */
2274ebfedea0SLionel Sambuc     if(str[0])
2275ebfedea0SLionel Sambuc       SIGN(mp) = MP_NEG;
2276ebfedea0SLionel Sambuc     else
2277ebfedea0SLionel Sambuc       SIGN(mp) = MP_ZPOS;
2278ebfedea0SLionel Sambuc   }
2279ebfedea0SLionel Sambuc 
2280ebfedea0SLionel Sambuc   return res;
2281ebfedea0SLionel Sambuc 
2282ebfedea0SLionel Sambuc } /* end mp_read_signed_bin() */
2283ebfedea0SLionel Sambuc 
2284ebfedea0SLionel Sambuc /* }}} */
2285ebfedea0SLionel Sambuc 
2286ebfedea0SLionel Sambuc /* {{{ mp_signed_bin_size(mp) */
2287ebfedea0SLionel Sambuc 
mp_signed_bin_size(mp_int * mp)2288ebfedea0SLionel Sambuc int    mp_signed_bin_size(mp_int *mp)
2289ebfedea0SLionel Sambuc {
2290ebfedea0SLionel Sambuc   ARGCHK(mp != NULL, 0);
2291ebfedea0SLionel Sambuc 
2292ebfedea0SLionel Sambuc   return mp_unsigned_bin_size(mp) + 1;
2293ebfedea0SLionel Sambuc 
2294ebfedea0SLionel Sambuc } /* end mp_signed_bin_size() */
2295ebfedea0SLionel Sambuc 
2296ebfedea0SLionel Sambuc /* }}} */
2297ebfedea0SLionel Sambuc 
2298ebfedea0SLionel Sambuc /* {{{ mp_to_signed_bin(mp, str) */
2299ebfedea0SLionel Sambuc 
mp_to_signed_bin(mp_int * mp,unsigned char * str)2300ebfedea0SLionel Sambuc mp_err mp_to_signed_bin(mp_int *mp, unsigned char *str)
2301ebfedea0SLionel Sambuc {
2302ebfedea0SLionel Sambuc   ARGCHK(mp != NULL && str != NULL, MP_BADARG);
2303ebfedea0SLionel Sambuc 
2304ebfedea0SLionel Sambuc   /* Caller responsible for allocating enough memory (use mp_raw_size(mp)) */
2305ebfedea0SLionel Sambuc   str[0] = (char)SIGN(mp);
2306ebfedea0SLionel Sambuc 
2307ebfedea0SLionel Sambuc   return mp_to_unsigned_bin(mp, str + 1);
2308ebfedea0SLionel Sambuc 
2309ebfedea0SLionel Sambuc } /* end mp_to_signed_bin() */
2310ebfedea0SLionel Sambuc 
2311ebfedea0SLionel Sambuc /* }}} */
2312ebfedea0SLionel Sambuc 
2313ebfedea0SLionel Sambuc /* {{{ mp_read_unsigned_bin(mp, str, len) */
2314ebfedea0SLionel Sambuc 
2315ebfedea0SLionel Sambuc /*
2316ebfedea0SLionel Sambuc   mp_read_unsigned_bin(mp, str, len)
2317ebfedea0SLionel Sambuc 
2318ebfedea0SLionel Sambuc   Read in an unsigned value (base 256) into the given mp_int
2319ebfedea0SLionel Sambuc  */
2320ebfedea0SLionel Sambuc 
mp_read_unsigned_bin(mp_int * mp,unsigned char * str,int len)2321ebfedea0SLionel Sambuc mp_err  mp_read_unsigned_bin(mp_int *mp, unsigned char *str, int len)
2322ebfedea0SLionel Sambuc {
2323ebfedea0SLionel Sambuc   int     ix;
2324ebfedea0SLionel Sambuc   mp_err  res;
2325ebfedea0SLionel Sambuc 
2326ebfedea0SLionel Sambuc   ARGCHK(mp != NULL && str != NULL && len > 0, MP_BADARG);
2327ebfedea0SLionel Sambuc 
2328ebfedea0SLionel Sambuc   mp_zero(mp);
2329ebfedea0SLionel Sambuc 
2330ebfedea0SLionel Sambuc   for(ix = 0; ix < len; ix++) {
2331ebfedea0SLionel Sambuc     if((res = s_mp_mul_2d(mp, CHAR_BIT)) != MP_OKAY)
2332ebfedea0SLionel Sambuc       return res;
2333ebfedea0SLionel Sambuc 
2334ebfedea0SLionel Sambuc     if((res = mp_add_d(mp, str[ix], mp)) != MP_OKAY)
2335ebfedea0SLionel Sambuc       return res;
2336ebfedea0SLionel Sambuc   }
2337ebfedea0SLionel Sambuc 
2338ebfedea0SLionel Sambuc   return MP_OKAY;
2339ebfedea0SLionel Sambuc 
2340ebfedea0SLionel Sambuc } /* end mp_read_unsigned_bin() */
2341ebfedea0SLionel Sambuc 
2342ebfedea0SLionel Sambuc /* }}} */
2343ebfedea0SLionel Sambuc 
2344ebfedea0SLionel Sambuc /* {{{ mp_unsigned_bin_size(mp) */
2345ebfedea0SLionel Sambuc 
mp_unsigned_bin_size(mp_int * mp)2346ebfedea0SLionel Sambuc int     mp_unsigned_bin_size(mp_int *mp)
2347ebfedea0SLionel Sambuc {
2348ebfedea0SLionel Sambuc   mp_digit   topdig;
2349ebfedea0SLionel Sambuc   int        count;
2350ebfedea0SLionel Sambuc 
2351ebfedea0SLionel Sambuc   ARGCHK(mp != NULL, 0);
2352ebfedea0SLionel Sambuc 
2353ebfedea0SLionel Sambuc   /* Special case for the value zero */
2354ebfedea0SLionel Sambuc   if(USED(mp) == 1 && DIGIT(mp, 0) == 0)
2355ebfedea0SLionel Sambuc     return 1;
2356ebfedea0SLionel Sambuc 
2357ebfedea0SLionel Sambuc   count = (USED(mp) - 1) * sizeof(mp_digit);
2358ebfedea0SLionel Sambuc   topdig = DIGIT(mp, USED(mp) - 1);
2359ebfedea0SLionel Sambuc 
2360ebfedea0SLionel Sambuc   while(topdig != 0) {
2361ebfedea0SLionel Sambuc     ++count;
2362ebfedea0SLionel Sambuc     topdig >>= CHAR_BIT;
2363ebfedea0SLionel Sambuc   }
2364ebfedea0SLionel Sambuc 
2365ebfedea0SLionel Sambuc   return count;
2366ebfedea0SLionel Sambuc 
2367ebfedea0SLionel Sambuc } /* end mp_unsigned_bin_size() */
2368ebfedea0SLionel Sambuc 
2369ebfedea0SLionel Sambuc /* }}} */
2370ebfedea0SLionel Sambuc 
2371ebfedea0SLionel Sambuc /* {{{ mp_to_unsigned_bin(mp, str) */
2372ebfedea0SLionel Sambuc 
mp_to_unsigned_bin(mp_int * mp,unsigned char * str)2373ebfedea0SLionel Sambuc mp_err mp_to_unsigned_bin(mp_int *mp, unsigned char *str)
2374ebfedea0SLionel Sambuc {
2375ebfedea0SLionel Sambuc   mp_digit      *dp, *end, d;
2376ebfedea0SLionel Sambuc   unsigned char *spos;
2377ebfedea0SLionel Sambuc 
2378ebfedea0SLionel Sambuc   ARGCHK(mp != NULL && str != NULL, MP_BADARG);
2379ebfedea0SLionel Sambuc 
2380ebfedea0SLionel Sambuc   dp = DIGITS(mp);
2381ebfedea0SLionel Sambuc   end = dp + USED(mp) - 1;
2382ebfedea0SLionel Sambuc   spos = str;
2383ebfedea0SLionel Sambuc 
2384ebfedea0SLionel Sambuc   /* Special case for zero, quick test */
2385ebfedea0SLionel Sambuc   if(dp == end && *dp == 0) {
2386ebfedea0SLionel Sambuc     *str = '\0';
2387ebfedea0SLionel Sambuc     return MP_OKAY;
2388ebfedea0SLionel Sambuc   }
2389ebfedea0SLionel Sambuc 
2390ebfedea0SLionel Sambuc   /* Generate digits in reverse order */
2391ebfedea0SLionel Sambuc   while(dp < end) {
2392ebfedea0SLionel Sambuc     int      ix;
2393ebfedea0SLionel Sambuc 
2394ebfedea0SLionel Sambuc     d = *dp;
2395ebfedea0SLionel Sambuc     for(ix = 0; ix < sizeof(mp_digit); ++ix) {
2396ebfedea0SLionel Sambuc       *spos = d & UCHAR_MAX;
2397ebfedea0SLionel Sambuc       d >>= CHAR_BIT;
2398ebfedea0SLionel Sambuc       ++spos;
2399ebfedea0SLionel Sambuc     }
2400ebfedea0SLionel Sambuc 
2401ebfedea0SLionel Sambuc     ++dp;
2402ebfedea0SLionel Sambuc   }
2403ebfedea0SLionel Sambuc 
2404ebfedea0SLionel Sambuc   /* Now handle last digit specially, high order zeroes are not written */
2405ebfedea0SLionel Sambuc   d = *end;
2406ebfedea0SLionel Sambuc   while(d != 0) {
2407ebfedea0SLionel Sambuc     *spos = d & UCHAR_MAX;
2408ebfedea0SLionel Sambuc     d >>= CHAR_BIT;
2409ebfedea0SLionel Sambuc     ++spos;
2410ebfedea0SLionel Sambuc   }
2411ebfedea0SLionel Sambuc 
2412ebfedea0SLionel Sambuc   /* Reverse everything to get digits in the correct order */
2413ebfedea0SLionel Sambuc   while(--spos > str) {
2414ebfedea0SLionel Sambuc     unsigned char t = *str;
2415ebfedea0SLionel Sambuc     *str = *spos;
2416ebfedea0SLionel Sambuc     *spos = t;
2417ebfedea0SLionel Sambuc 
2418ebfedea0SLionel Sambuc     ++str;
2419ebfedea0SLionel Sambuc   }
2420ebfedea0SLionel Sambuc 
2421ebfedea0SLionel Sambuc   return MP_OKAY;
2422ebfedea0SLionel Sambuc 
2423ebfedea0SLionel Sambuc } /* end mp_to_unsigned_bin() */
2424ebfedea0SLionel Sambuc 
2425ebfedea0SLionel Sambuc /* }}} */
2426ebfedea0SLionel Sambuc 
2427ebfedea0SLionel Sambuc /* {{{ mp_count_bits(mp) */
2428ebfedea0SLionel Sambuc 
mp_count_bits(mp_int * mp)2429ebfedea0SLionel Sambuc int    mp_count_bits(mp_int *mp)
2430ebfedea0SLionel Sambuc {
2431ebfedea0SLionel Sambuc   int      len;
2432ebfedea0SLionel Sambuc   mp_digit d;
2433ebfedea0SLionel Sambuc 
2434ebfedea0SLionel Sambuc   ARGCHK(mp != NULL, MP_BADARG);
2435ebfedea0SLionel Sambuc 
2436ebfedea0SLionel Sambuc   len = DIGIT_BIT * (USED(mp) - 1);
2437ebfedea0SLionel Sambuc   d = DIGIT(mp, USED(mp) - 1);
2438ebfedea0SLionel Sambuc 
2439ebfedea0SLionel Sambuc   while(d != 0) {
2440ebfedea0SLionel Sambuc     ++len;
2441ebfedea0SLionel Sambuc     d >>= 1;
2442ebfedea0SLionel Sambuc   }
2443ebfedea0SLionel Sambuc 
2444ebfedea0SLionel Sambuc   return len;
2445ebfedea0SLionel Sambuc 
2446ebfedea0SLionel Sambuc } /* end mp_count_bits() */
2447ebfedea0SLionel Sambuc 
2448ebfedea0SLionel Sambuc /* }}} */
2449ebfedea0SLionel Sambuc 
2450ebfedea0SLionel Sambuc /* {{{ mp_read_radix(mp, str, radix) */
2451ebfedea0SLionel Sambuc 
2452ebfedea0SLionel Sambuc /*
2453ebfedea0SLionel Sambuc   mp_read_radix(mp, str, radix)
2454ebfedea0SLionel Sambuc 
2455ebfedea0SLionel Sambuc   Read an integer from the given string, and set mp to the resulting
2456ebfedea0SLionel Sambuc   value.  The input is presumed to be in base 10.  Leading non-digit
2457ebfedea0SLionel Sambuc   characters are ignored, and the function reads until a non-digit
2458ebfedea0SLionel Sambuc   character or the end of the string.
2459ebfedea0SLionel Sambuc  */
2460ebfedea0SLionel Sambuc 
mp_read_radix(mp_int * mp,unsigned char * str,int radix)2461ebfedea0SLionel Sambuc mp_err  mp_read_radix(mp_int *mp, unsigned char *str, int radix)
2462ebfedea0SLionel Sambuc {
2463ebfedea0SLionel Sambuc   int     ix = 0, val = 0;
2464ebfedea0SLionel Sambuc   mp_err  res;
2465ebfedea0SLionel Sambuc   mp_sign sig = MP_ZPOS;
2466ebfedea0SLionel Sambuc 
2467ebfedea0SLionel Sambuc   ARGCHK(mp != NULL && str != NULL && radix >= 2 && radix <= MAX_RADIX,
2468ebfedea0SLionel Sambuc 	 MP_BADARG);
2469ebfedea0SLionel Sambuc 
2470ebfedea0SLionel Sambuc   mp_zero(mp);
2471ebfedea0SLionel Sambuc 
2472ebfedea0SLionel Sambuc   /* Skip leading non-digit characters until a digit or '-' or '+' */
2473ebfedea0SLionel Sambuc   while(str[ix] &&
2474ebfedea0SLionel Sambuc 	(s_mp_tovalue(str[ix], radix) < 0) &&
2475ebfedea0SLionel Sambuc 	str[ix] != '-' &&
2476ebfedea0SLionel Sambuc 	str[ix] != '+') {
2477ebfedea0SLionel Sambuc     ++ix;
2478ebfedea0SLionel Sambuc   }
2479ebfedea0SLionel Sambuc 
2480ebfedea0SLionel Sambuc   if(str[ix] == '-') {
2481ebfedea0SLionel Sambuc     sig = MP_NEG;
2482ebfedea0SLionel Sambuc     ++ix;
2483ebfedea0SLionel Sambuc   } else if(str[ix] == '+') {
2484ebfedea0SLionel Sambuc     sig = MP_ZPOS; /* this is the default anyway... */
2485ebfedea0SLionel Sambuc     ++ix;
2486ebfedea0SLionel Sambuc   }
2487ebfedea0SLionel Sambuc 
2488ebfedea0SLionel Sambuc   while((val = s_mp_tovalue(str[ix], radix)) >= 0) {
2489ebfedea0SLionel Sambuc     if((res = s_mp_mul_d(mp, radix)) != MP_OKAY)
2490ebfedea0SLionel Sambuc       return res;
2491ebfedea0SLionel Sambuc     if((res = s_mp_add_d(mp, val)) != MP_OKAY)
2492ebfedea0SLionel Sambuc       return res;
2493ebfedea0SLionel Sambuc     ++ix;
2494ebfedea0SLionel Sambuc   }
2495ebfedea0SLionel Sambuc 
2496ebfedea0SLionel Sambuc   if(s_mp_cmp_d(mp, 0) == MP_EQ)
2497ebfedea0SLionel Sambuc     SIGN(mp) = MP_ZPOS;
2498ebfedea0SLionel Sambuc   else
2499ebfedea0SLionel Sambuc     SIGN(mp) = sig;
2500ebfedea0SLionel Sambuc 
2501ebfedea0SLionel Sambuc   return MP_OKAY;
2502ebfedea0SLionel Sambuc 
2503ebfedea0SLionel Sambuc } /* end mp_read_radix() */
2504ebfedea0SLionel Sambuc 
2505ebfedea0SLionel Sambuc /* }}} */
2506ebfedea0SLionel Sambuc 
2507ebfedea0SLionel Sambuc /* {{{ mp_radix_size(mp, radix) */
2508ebfedea0SLionel Sambuc 
mp_radix_size(mp_int * mp,int radix)2509ebfedea0SLionel Sambuc int    mp_radix_size(mp_int *mp, int radix)
2510ebfedea0SLionel Sambuc {
2511ebfedea0SLionel Sambuc   int  len;
2512ebfedea0SLionel Sambuc   ARGCHK(mp != NULL, 0);
2513ebfedea0SLionel Sambuc 
2514ebfedea0SLionel Sambuc   len = s_mp_outlen(mp_count_bits(mp), radix) + 1; /* for NUL terminator */
2515ebfedea0SLionel Sambuc 
2516ebfedea0SLionel Sambuc   if(mp_cmp_z(mp) < 0)
2517ebfedea0SLionel Sambuc     ++len; /* for sign */
2518ebfedea0SLionel Sambuc 
2519ebfedea0SLionel Sambuc   return len;
2520ebfedea0SLionel Sambuc 
2521ebfedea0SLionel Sambuc } /* end mp_radix_size() */
2522ebfedea0SLionel Sambuc 
2523ebfedea0SLionel Sambuc /* }}} */
2524ebfedea0SLionel Sambuc 
2525ebfedea0SLionel Sambuc /* {{{ mp_value_radix_size(num, qty, radix) */
2526ebfedea0SLionel Sambuc 
2527ebfedea0SLionel Sambuc /* num = number of digits
2528ebfedea0SLionel Sambuc    qty = number of bits per digit
2529ebfedea0SLionel Sambuc    radix = target base
2530ebfedea0SLionel Sambuc 
2531ebfedea0SLionel Sambuc    Return the number of digits in the specified radix that would be
2532ebfedea0SLionel Sambuc    needed to express 'num' digits of 'qty' bits each.
2533ebfedea0SLionel Sambuc  */
mp_value_radix_size(int num,int qty,int radix)2534ebfedea0SLionel Sambuc int    mp_value_radix_size(int num, int qty, int radix)
2535ebfedea0SLionel Sambuc {
2536ebfedea0SLionel Sambuc   ARGCHK(num >= 0 && qty > 0 && radix >= 2 && radix <= MAX_RADIX, 0);
2537ebfedea0SLionel Sambuc 
2538ebfedea0SLionel Sambuc   return s_mp_outlen(num * qty, radix);
2539ebfedea0SLionel Sambuc 
2540ebfedea0SLionel Sambuc } /* end mp_value_radix_size() */
2541ebfedea0SLionel Sambuc 
2542ebfedea0SLionel Sambuc /* }}} */
2543ebfedea0SLionel Sambuc 
2544ebfedea0SLionel Sambuc /* {{{ mp_toradix(mp, str, radix) */
2545ebfedea0SLionel Sambuc 
mp_toradix(mp_int * mp,unsigned char * str,int radix)2546ebfedea0SLionel Sambuc mp_err mp_toradix(mp_int *mp, unsigned char *str, int radix)
2547ebfedea0SLionel Sambuc {
2548ebfedea0SLionel Sambuc   int  ix, pos = 0;
2549ebfedea0SLionel Sambuc 
2550ebfedea0SLionel Sambuc   ARGCHK(mp != NULL && str != NULL, MP_BADARG);
2551ebfedea0SLionel Sambuc   ARGCHK(radix > 1 && radix <= MAX_RADIX, MP_RANGE);
2552ebfedea0SLionel Sambuc 
2553ebfedea0SLionel Sambuc   if(mp_cmp_z(mp) == MP_EQ) {
2554ebfedea0SLionel Sambuc     str[0] = '0';
2555ebfedea0SLionel Sambuc     str[1] = '\0';
2556ebfedea0SLionel Sambuc   } else {
2557ebfedea0SLionel Sambuc     mp_err   res;
2558ebfedea0SLionel Sambuc     mp_int   tmp;
2559ebfedea0SLionel Sambuc     mp_sign  sgn;
2560ebfedea0SLionel Sambuc     mp_digit rem, rdx = (mp_digit)radix;
2561ebfedea0SLionel Sambuc     char     ch;
2562ebfedea0SLionel Sambuc 
2563ebfedea0SLionel Sambuc     if((res = mp_init_copy(&tmp, mp)) != MP_OKAY)
2564ebfedea0SLionel Sambuc       return res;
2565ebfedea0SLionel Sambuc 
2566ebfedea0SLionel Sambuc     /* Save sign for later, and take absolute value */
2567ebfedea0SLionel Sambuc     sgn = SIGN(&tmp); SIGN(&tmp) = MP_ZPOS;
2568ebfedea0SLionel Sambuc 
2569ebfedea0SLionel Sambuc     /* Generate output digits in reverse order      */
2570ebfedea0SLionel Sambuc     while(mp_cmp_z(&tmp) != 0) {
2571ebfedea0SLionel Sambuc       if((res = s_mp_div_d(&tmp, rdx, &rem)) != MP_OKAY) {
2572ebfedea0SLionel Sambuc 	mp_clear(&tmp);
2573ebfedea0SLionel Sambuc 	return res;
2574ebfedea0SLionel Sambuc       }
2575ebfedea0SLionel Sambuc 
2576ebfedea0SLionel Sambuc       /* Generate digits, use capital letters */
2577ebfedea0SLionel Sambuc       ch = s_mp_todigit(rem, radix, 0);
2578ebfedea0SLionel Sambuc 
2579ebfedea0SLionel Sambuc       str[pos++] = ch;
2580ebfedea0SLionel Sambuc     }
2581ebfedea0SLionel Sambuc 
2582ebfedea0SLionel Sambuc     /* Add - sign if original value was negative */
2583ebfedea0SLionel Sambuc     if(sgn == MP_NEG)
2584ebfedea0SLionel Sambuc       str[pos++] = '-';
2585ebfedea0SLionel Sambuc 
2586ebfedea0SLionel Sambuc     /* Add trailing NUL to end the string        */
2587ebfedea0SLionel Sambuc     str[pos--] = '\0';
2588ebfedea0SLionel Sambuc 
2589ebfedea0SLionel Sambuc     /* Reverse the digits and sign indicator     */
2590ebfedea0SLionel Sambuc     ix = 0;
2591ebfedea0SLionel Sambuc     while(ix < pos) {
2592ebfedea0SLionel Sambuc       char tmp = str[ix];
2593ebfedea0SLionel Sambuc 
2594ebfedea0SLionel Sambuc       str[ix] = str[pos];
2595ebfedea0SLionel Sambuc       str[pos] = tmp;
2596ebfedea0SLionel Sambuc       ++ix;
2597ebfedea0SLionel Sambuc       --pos;
2598ebfedea0SLionel Sambuc     }
2599ebfedea0SLionel Sambuc 
2600ebfedea0SLionel Sambuc     mp_clear(&tmp);
2601ebfedea0SLionel Sambuc   }
2602ebfedea0SLionel Sambuc 
2603ebfedea0SLionel Sambuc   return MP_OKAY;
2604ebfedea0SLionel Sambuc 
2605ebfedea0SLionel Sambuc } /* end mp_toradix() */
2606ebfedea0SLionel Sambuc 
2607ebfedea0SLionel Sambuc /* }}} */
2608ebfedea0SLionel Sambuc 
2609ebfedea0SLionel Sambuc /* {{{ mp_char2value(ch, r) */
2610ebfedea0SLionel Sambuc 
mp_char2value(char ch,int r)2611ebfedea0SLionel Sambuc int    mp_char2value(char ch, int r)
2612ebfedea0SLionel Sambuc {
2613ebfedea0SLionel Sambuc   return s_mp_tovalue(ch, r);
2614ebfedea0SLionel Sambuc 
2615ebfedea0SLionel Sambuc } /* end mp_tovalue() */
2616ebfedea0SLionel Sambuc 
2617ebfedea0SLionel Sambuc /* }}} */
2618ebfedea0SLionel Sambuc 
2619ebfedea0SLionel Sambuc /* }}} */
2620ebfedea0SLionel Sambuc 
2621ebfedea0SLionel Sambuc /* {{{ mp_strerror(ec) */
2622ebfedea0SLionel Sambuc 
2623ebfedea0SLionel Sambuc /*
2624ebfedea0SLionel Sambuc   mp_strerror(ec)
2625ebfedea0SLionel Sambuc 
2626ebfedea0SLionel Sambuc   Return a string describing the meaning of error code 'ec'.  The
2627ebfedea0SLionel Sambuc   string returned is allocated in static memory, so the caller should
2628ebfedea0SLionel Sambuc   not attempt to modify or free the memory associated with this
2629ebfedea0SLionel Sambuc   string.
2630ebfedea0SLionel Sambuc  */
mp_strerror(mp_err ec)2631ebfedea0SLionel Sambuc const char  *mp_strerror(mp_err ec)
2632ebfedea0SLionel Sambuc {
2633ebfedea0SLionel Sambuc   int   aec = (ec < 0) ? -ec : ec;
2634ebfedea0SLionel Sambuc 
2635ebfedea0SLionel Sambuc   /* Code values are negative, so the senses of these comparisons
2636ebfedea0SLionel Sambuc      are accurate */
2637ebfedea0SLionel Sambuc   if(ec < MP_LAST_CODE || ec > MP_OKAY) {
2638ebfedea0SLionel Sambuc     return mp_err_string[0];  /* unknown error code */
2639ebfedea0SLionel Sambuc   } else {
2640ebfedea0SLionel Sambuc     return mp_err_string[aec + 1];
2641ebfedea0SLionel Sambuc   }
2642ebfedea0SLionel Sambuc 
2643ebfedea0SLionel Sambuc } /* end mp_strerror() */
2644ebfedea0SLionel Sambuc 
2645ebfedea0SLionel Sambuc /* }}} */
2646ebfedea0SLionel Sambuc 
2647ebfedea0SLionel Sambuc /*========================================================================*/
2648ebfedea0SLionel Sambuc /*------------------------------------------------------------------------*/
2649ebfedea0SLionel Sambuc /* Static function definitions (internal use only)                        */
2650ebfedea0SLionel Sambuc 
2651ebfedea0SLionel Sambuc /* {{{ Memory management */
2652ebfedea0SLionel Sambuc 
2653ebfedea0SLionel Sambuc /* {{{ s_mp_grow(mp, min) */
2654ebfedea0SLionel Sambuc 
2655ebfedea0SLionel Sambuc /* Make sure there are at least 'min' digits allocated to mp              */
s_mp_grow(mp_int * mp,mp_size min)2656ebfedea0SLionel Sambuc mp_err   s_mp_grow(mp_int *mp, mp_size min)
2657ebfedea0SLionel Sambuc {
2658ebfedea0SLionel Sambuc   if(min > ALLOC(mp)) {
2659ebfedea0SLionel Sambuc     mp_digit   *tmp;
2660ebfedea0SLionel Sambuc 
2661ebfedea0SLionel Sambuc     /* Set min to next nearest default precision block size */
2662ebfedea0SLionel Sambuc     min = ((min + (s_mp_defprec - 1)) / s_mp_defprec) * s_mp_defprec;
2663ebfedea0SLionel Sambuc 
2664ebfedea0SLionel Sambuc     if((tmp = s_mp_alloc(min, sizeof(mp_digit))) == NULL)
2665ebfedea0SLionel Sambuc       return MP_MEM;
2666ebfedea0SLionel Sambuc 
2667ebfedea0SLionel Sambuc     s_mp_copy(DIGITS(mp), tmp, USED(mp));
2668ebfedea0SLionel Sambuc 
2669ebfedea0SLionel Sambuc #if MP_CRYPTO
2670ebfedea0SLionel Sambuc     s_mp_setz(DIGITS(mp), ALLOC(mp));
2671ebfedea0SLionel Sambuc #endif
2672ebfedea0SLionel Sambuc     s_mp_free(DIGITS(mp));
2673ebfedea0SLionel Sambuc     DIGITS(mp) = tmp;
2674ebfedea0SLionel Sambuc     ALLOC(mp) = min;
2675ebfedea0SLionel Sambuc   }
2676ebfedea0SLionel Sambuc 
2677ebfedea0SLionel Sambuc   return MP_OKAY;
2678ebfedea0SLionel Sambuc 
2679ebfedea0SLionel Sambuc } /* end s_mp_grow() */
2680ebfedea0SLionel Sambuc 
2681ebfedea0SLionel Sambuc /* }}} */
2682ebfedea0SLionel Sambuc 
2683ebfedea0SLionel Sambuc /* {{{ s_mp_pad(mp, min) */
2684ebfedea0SLionel Sambuc 
2685ebfedea0SLionel Sambuc /* Make sure the used size of mp is at least 'min', growing if needed     */
s_mp_pad(mp_int * mp,mp_size min)2686ebfedea0SLionel Sambuc mp_err   s_mp_pad(mp_int *mp, mp_size min)
2687ebfedea0SLionel Sambuc {
2688ebfedea0SLionel Sambuc   if(min > USED(mp)) {
2689ebfedea0SLionel Sambuc     mp_err  res;
2690ebfedea0SLionel Sambuc 
2691ebfedea0SLionel Sambuc     /* Make sure there is room to increase precision  */
2692ebfedea0SLionel Sambuc     if(min > ALLOC(mp) && (res = s_mp_grow(mp, min)) != MP_OKAY)
2693ebfedea0SLionel Sambuc       return res;
2694ebfedea0SLionel Sambuc 
2695ebfedea0SLionel Sambuc     /* Increase precision; should already be 0-filled */
2696ebfedea0SLionel Sambuc     USED(mp) = min;
2697ebfedea0SLionel Sambuc   }
2698ebfedea0SLionel Sambuc 
2699ebfedea0SLionel Sambuc   return MP_OKAY;
2700ebfedea0SLionel Sambuc 
2701ebfedea0SLionel Sambuc } /* end s_mp_pad() */
2702ebfedea0SLionel Sambuc 
2703ebfedea0SLionel Sambuc /* }}} */
2704ebfedea0SLionel Sambuc 
2705ebfedea0SLionel Sambuc /* {{{ s_mp_setz(dp, count) */
2706ebfedea0SLionel Sambuc 
2707ebfedea0SLionel Sambuc #if MP_MACRO == 0
2708ebfedea0SLionel Sambuc /* Set 'count' digits pointed to by dp to be zeroes                       */
s_mp_setz(mp_digit * dp,mp_size count)2709ebfedea0SLionel Sambuc void s_mp_setz(mp_digit *dp, mp_size count)
2710ebfedea0SLionel Sambuc {
2711ebfedea0SLionel Sambuc #if MP_MEMSET == 0
2712ebfedea0SLionel Sambuc   int  ix;
2713ebfedea0SLionel Sambuc 
2714ebfedea0SLionel Sambuc   for(ix = 0; ix < count; ix++)
2715ebfedea0SLionel Sambuc     dp[ix] = 0;
2716ebfedea0SLionel Sambuc #else
2717ebfedea0SLionel Sambuc   memset(dp, 0, count * sizeof(mp_digit));
2718ebfedea0SLionel Sambuc #endif
2719ebfedea0SLionel Sambuc 
2720ebfedea0SLionel Sambuc } /* end s_mp_setz() */
2721ebfedea0SLionel Sambuc #endif
2722ebfedea0SLionel Sambuc 
2723ebfedea0SLionel Sambuc /* }}} */
2724ebfedea0SLionel Sambuc 
2725ebfedea0SLionel Sambuc /* {{{ s_mp_copy(sp, dp, count) */
2726ebfedea0SLionel Sambuc 
2727ebfedea0SLionel Sambuc #if MP_MACRO == 0
2728ebfedea0SLionel Sambuc /* Copy 'count' digits from sp to dp                                      */
s_mp_copy(mp_digit * sp,mp_digit * dp,mp_size count)2729ebfedea0SLionel Sambuc void s_mp_copy(mp_digit *sp, mp_digit *dp, mp_size count)
2730ebfedea0SLionel Sambuc {
2731ebfedea0SLionel Sambuc #if MP_MEMCPY == 0
2732ebfedea0SLionel Sambuc   int  ix;
2733ebfedea0SLionel Sambuc 
2734ebfedea0SLionel Sambuc   for(ix = 0; ix < count; ix++)
2735ebfedea0SLionel Sambuc     dp[ix] = sp[ix];
2736ebfedea0SLionel Sambuc #else
2737ebfedea0SLionel Sambuc   memcpy(dp, sp, count * sizeof(mp_digit));
2738ebfedea0SLionel Sambuc #endif
2739ebfedea0SLionel Sambuc 
2740ebfedea0SLionel Sambuc } /* end s_mp_copy() */
2741ebfedea0SLionel Sambuc #endif
2742ebfedea0SLionel Sambuc 
2743ebfedea0SLionel Sambuc /* }}} */
2744ebfedea0SLionel Sambuc 
2745ebfedea0SLionel Sambuc /* {{{ s_mp_alloc(nb, ni) */
2746ebfedea0SLionel Sambuc 
2747ebfedea0SLionel Sambuc #if MP_MACRO == 0
2748ebfedea0SLionel Sambuc /* Allocate ni records of nb bytes each, and return a pointer to that     */
s_mp_alloc(size_t nb,size_t ni)2749ebfedea0SLionel Sambuc void    *s_mp_alloc(size_t nb, size_t ni)
2750ebfedea0SLionel Sambuc {
2751ebfedea0SLionel Sambuc   return calloc(nb, ni);
2752ebfedea0SLionel Sambuc 
2753ebfedea0SLionel Sambuc } /* end s_mp_alloc() */
2754ebfedea0SLionel Sambuc #endif
2755ebfedea0SLionel Sambuc 
2756ebfedea0SLionel Sambuc /* }}} */
2757ebfedea0SLionel Sambuc 
2758ebfedea0SLionel Sambuc /* {{{ s_mp_free(ptr) */
2759ebfedea0SLionel Sambuc 
2760ebfedea0SLionel Sambuc #if MP_MACRO == 0
2761ebfedea0SLionel Sambuc /* Free the memory pointed to by ptr                                      */
s_mp_free(void * ptr)2762ebfedea0SLionel Sambuc void     s_mp_free(void *ptr)
2763ebfedea0SLionel Sambuc {
2764ebfedea0SLionel Sambuc   if(ptr)
2765ebfedea0SLionel Sambuc     free(ptr);
2766ebfedea0SLionel Sambuc 
2767ebfedea0SLionel Sambuc } /* end s_mp_free() */
2768ebfedea0SLionel Sambuc #endif
2769ebfedea0SLionel Sambuc 
2770ebfedea0SLionel Sambuc /* }}} */
2771ebfedea0SLionel Sambuc 
2772ebfedea0SLionel Sambuc /* {{{ s_mp_clamp(mp) */
2773ebfedea0SLionel Sambuc 
2774ebfedea0SLionel Sambuc /* Remove leading zeroes from the given value                             */
s_mp_clamp(mp_int * mp)2775ebfedea0SLionel Sambuc void     s_mp_clamp(mp_int *mp)
2776ebfedea0SLionel Sambuc {
2777ebfedea0SLionel Sambuc   mp_size   du = USED(mp);
2778ebfedea0SLionel Sambuc   mp_digit *zp = DIGITS(mp) + du - 1;
2779ebfedea0SLionel Sambuc 
2780ebfedea0SLionel Sambuc   while(du > 1 && !*zp--)
2781ebfedea0SLionel Sambuc     --du;
2782ebfedea0SLionel Sambuc 
2783ebfedea0SLionel Sambuc   USED(mp) = du;
2784ebfedea0SLionel Sambuc 
2785ebfedea0SLionel Sambuc } /* end s_mp_clamp() */
2786ebfedea0SLionel Sambuc 
2787ebfedea0SLionel Sambuc 
2788ebfedea0SLionel Sambuc /* }}} */
2789ebfedea0SLionel Sambuc 
2790ebfedea0SLionel Sambuc /* {{{ s_mp_exch(a, b) */
2791ebfedea0SLionel Sambuc 
2792ebfedea0SLionel Sambuc /* Exchange the data for a and b; (b, a) = (a, b)                         */
s_mp_exch(mp_int * a,mp_int * b)2793ebfedea0SLionel Sambuc void     s_mp_exch(mp_int *a, mp_int *b)
2794ebfedea0SLionel Sambuc {
2795ebfedea0SLionel Sambuc   mp_int   tmp;
2796ebfedea0SLionel Sambuc 
2797ebfedea0SLionel Sambuc   tmp = *a;
2798ebfedea0SLionel Sambuc   *a = *b;
2799ebfedea0SLionel Sambuc   *b = tmp;
2800ebfedea0SLionel Sambuc 
2801ebfedea0SLionel Sambuc } /* end s_mp_exch() */
2802ebfedea0SLionel Sambuc 
2803ebfedea0SLionel Sambuc /* }}} */
2804ebfedea0SLionel Sambuc 
2805ebfedea0SLionel Sambuc /* }}} */
2806ebfedea0SLionel Sambuc 
2807ebfedea0SLionel Sambuc /* {{{ Arithmetic helpers */
2808ebfedea0SLionel Sambuc 
2809ebfedea0SLionel Sambuc /* {{{ s_mp_lshd(mp, p) */
2810ebfedea0SLionel Sambuc 
2811ebfedea0SLionel Sambuc /*
2812ebfedea0SLionel Sambuc    Shift mp leftward by p digits, growing if needed, and zero-filling
2813ebfedea0SLionel Sambuc    the in-shifted digits at the right end.  This is a convenient
2814ebfedea0SLionel Sambuc    alternative to multiplication by powers of the radix
2815ebfedea0SLionel Sambuc  */
2816ebfedea0SLionel Sambuc 
s_mp_lshd(mp_int * mp,mp_size p)2817ebfedea0SLionel Sambuc mp_err   s_mp_lshd(mp_int *mp, mp_size p)
2818ebfedea0SLionel Sambuc {
2819ebfedea0SLionel Sambuc   mp_err   res;
2820ebfedea0SLionel Sambuc   mp_size  pos;
2821ebfedea0SLionel Sambuc   mp_digit *dp;
2822ebfedea0SLionel Sambuc   int     ix;
2823ebfedea0SLionel Sambuc 
2824ebfedea0SLionel Sambuc   if(p == 0)
2825ebfedea0SLionel Sambuc     return MP_OKAY;
2826ebfedea0SLionel Sambuc 
2827ebfedea0SLionel Sambuc   if((res = s_mp_pad(mp, USED(mp) + p)) != MP_OKAY)
2828ebfedea0SLionel Sambuc     return res;
2829ebfedea0SLionel Sambuc 
2830ebfedea0SLionel Sambuc   pos = USED(mp) - 1;
2831ebfedea0SLionel Sambuc   dp = DIGITS(mp);
2832ebfedea0SLionel Sambuc 
2833ebfedea0SLionel Sambuc   /* Shift all the significant figures over as needed */
2834ebfedea0SLionel Sambuc   for(ix = pos - p; ix >= 0; ix--)
2835ebfedea0SLionel Sambuc     dp[ix + p] = dp[ix];
2836ebfedea0SLionel Sambuc 
2837ebfedea0SLionel Sambuc   /* Fill the bottom digits with zeroes */
2838ebfedea0SLionel Sambuc   for(ix = 0; ix < p; ix++)
2839ebfedea0SLionel Sambuc     dp[ix] = 0;
2840ebfedea0SLionel Sambuc 
2841ebfedea0SLionel Sambuc   return MP_OKAY;
2842ebfedea0SLionel Sambuc 
2843ebfedea0SLionel Sambuc } /* end s_mp_lshd() */
2844ebfedea0SLionel Sambuc 
2845ebfedea0SLionel Sambuc /* }}} */
2846ebfedea0SLionel Sambuc 
2847ebfedea0SLionel Sambuc /* {{{ s_mp_rshd(mp, p) */
2848ebfedea0SLionel Sambuc 
2849ebfedea0SLionel Sambuc /*
2850ebfedea0SLionel Sambuc    Shift mp rightward by p digits.  Maintains the invariant that
2851ebfedea0SLionel Sambuc    digits above the precision are all zero.  Digits shifted off the
2852ebfedea0SLionel Sambuc    end are lost.  Cannot fail.
2853ebfedea0SLionel Sambuc  */
2854ebfedea0SLionel Sambuc 
s_mp_rshd(mp_int * mp,mp_size p)2855ebfedea0SLionel Sambuc void     s_mp_rshd(mp_int *mp, mp_size p)
2856ebfedea0SLionel Sambuc {
2857ebfedea0SLionel Sambuc   mp_size  ix;
2858ebfedea0SLionel Sambuc   mp_digit *dp;
2859ebfedea0SLionel Sambuc 
2860ebfedea0SLionel Sambuc   if(p == 0)
2861ebfedea0SLionel Sambuc     return;
2862ebfedea0SLionel Sambuc 
2863ebfedea0SLionel Sambuc   /* Shortcut when all digits are to be shifted off */
2864ebfedea0SLionel Sambuc   if(p >= USED(mp)) {
2865ebfedea0SLionel Sambuc     s_mp_setz(DIGITS(mp), ALLOC(mp));
2866ebfedea0SLionel Sambuc     USED(mp) = 1;
2867ebfedea0SLionel Sambuc     SIGN(mp) = MP_ZPOS;
2868ebfedea0SLionel Sambuc     return;
2869ebfedea0SLionel Sambuc   }
2870ebfedea0SLionel Sambuc 
2871ebfedea0SLionel Sambuc   /* Shift all the significant figures over as needed */
2872ebfedea0SLionel Sambuc   dp = DIGITS(mp);
2873ebfedea0SLionel Sambuc   for(ix = p; ix < USED(mp); ix++)
2874ebfedea0SLionel Sambuc     dp[ix - p] = dp[ix];
2875ebfedea0SLionel Sambuc 
2876ebfedea0SLionel Sambuc   /* Fill the top digits with zeroes */
2877ebfedea0SLionel Sambuc   ix -= p;
2878ebfedea0SLionel Sambuc   while(ix < USED(mp))
2879ebfedea0SLionel Sambuc     dp[ix++] = 0;
2880ebfedea0SLionel Sambuc 
2881ebfedea0SLionel Sambuc   /* Strip off any leading zeroes    */
2882ebfedea0SLionel Sambuc   s_mp_clamp(mp);
2883ebfedea0SLionel Sambuc 
2884ebfedea0SLionel Sambuc } /* end s_mp_rshd() */
2885ebfedea0SLionel Sambuc 
2886ebfedea0SLionel Sambuc /* }}} */
2887ebfedea0SLionel Sambuc 
2888ebfedea0SLionel Sambuc /* {{{ s_mp_div_2(mp) */
2889ebfedea0SLionel Sambuc 
2890ebfedea0SLionel Sambuc /* Divide by two -- take advantage of radix properties to do it fast      */
s_mp_div_2(mp_int * mp)2891ebfedea0SLionel Sambuc void     s_mp_div_2(mp_int *mp)
2892ebfedea0SLionel Sambuc {
2893ebfedea0SLionel Sambuc   s_mp_div_2d(mp, 1);
2894ebfedea0SLionel Sambuc 
2895ebfedea0SLionel Sambuc } /* end s_mp_div_2() */
2896ebfedea0SLionel Sambuc 
2897ebfedea0SLionel Sambuc /* }}} */
2898ebfedea0SLionel Sambuc 
2899ebfedea0SLionel Sambuc /* {{{ s_mp_mul_2(mp) */
2900ebfedea0SLionel Sambuc 
s_mp_mul_2(mp_int * mp)2901ebfedea0SLionel Sambuc mp_err s_mp_mul_2(mp_int *mp)
2902ebfedea0SLionel Sambuc {
2903ebfedea0SLionel Sambuc   int      ix;
2904ebfedea0SLionel Sambuc   mp_digit kin = 0, kout, *dp = DIGITS(mp);
2905ebfedea0SLionel Sambuc   mp_err   res;
2906ebfedea0SLionel Sambuc 
2907ebfedea0SLionel Sambuc   /* Shift digits leftward by 1 bit */
2908ebfedea0SLionel Sambuc   for(ix = 0; ix < USED(mp); ix++) {
2909ebfedea0SLionel Sambuc     kout = (dp[ix] >> (DIGIT_BIT - 1)) & 1;
2910ebfedea0SLionel Sambuc     dp[ix] = (dp[ix] << 1) | kin;
2911ebfedea0SLionel Sambuc 
2912ebfedea0SLionel Sambuc     kin = kout;
2913ebfedea0SLionel Sambuc   }
2914ebfedea0SLionel Sambuc 
2915ebfedea0SLionel Sambuc   /* Deal with rollover from last digit */
2916ebfedea0SLionel Sambuc   if(kin) {
2917ebfedea0SLionel Sambuc     if(ix >= ALLOC(mp)) {
2918ebfedea0SLionel Sambuc       if((res = s_mp_grow(mp, ALLOC(mp) + 1)) != MP_OKAY)
2919ebfedea0SLionel Sambuc 	return res;
2920ebfedea0SLionel Sambuc       dp = DIGITS(mp);
2921ebfedea0SLionel Sambuc     }
2922ebfedea0SLionel Sambuc 
2923ebfedea0SLionel Sambuc     dp[ix] = kin;
2924ebfedea0SLionel Sambuc     USED(mp) += 1;
2925ebfedea0SLionel Sambuc   }
2926ebfedea0SLionel Sambuc 
2927ebfedea0SLionel Sambuc   return MP_OKAY;
2928ebfedea0SLionel Sambuc 
2929ebfedea0SLionel Sambuc } /* end s_mp_mul_2() */
2930ebfedea0SLionel Sambuc 
2931ebfedea0SLionel Sambuc /* }}} */
2932ebfedea0SLionel Sambuc 
2933ebfedea0SLionel Sambuc /* {{{ s_mp_mod_2d(mp, d) */
2934ebfedea0SLionel Sambuc 
2935ebfedea0SLionel Sambuc /*
2936ebfedea0SLionel Sambuc   Remainder the integer by 2^d, where d is a number of bits.  This
2937ebfedea0SLionel Sambuc   amounts to a bitwise AND of the value, and does not require the full
2938ebfedea0SLionel Sambuc   division code
2939ebfedea0SLionel Sambuc  */
s_mp_mod_2d(mp_int * mp,mp_digit d)2940ebfedea0SLionel Sambuc void     s_mp_mod_2d(mp_int *mp, mp_digit d)
2941ebfedea0SLionel Sambuc {
2942ebfedea0SLionel Sambuc   unsigned int  ndig = (d / DIGIT_BIT), nbit = (d % DIGIT_BIT);
2943ebfedea0SLionel Sambuc   unsigned int  ix;
2944ebfedea0SLionel Sambuc   mp_digit      dmask, *dp = DIGITS(mp);
2945ebfedea0SLionel Sambuc 
2946ebfedea0SLionel Sambuc   if(ndig >= USED(mp))
2947ebfedea0SLionel Sambuc     return;
2948ebfedea0SLionel Sambuc 
2949ebfedea0SLionel Sambuc   /* Flush all the bits above 2^d in its digit */
2950ebfedea0SLionel Sambuc   dmask = (1 << nbit) - 1;
2951ebfedea0SLionel Sambuc   dp[ndig] &= dmask;
2952ebfedea0SLionel Sambuc 
2953ebfedea0SLionel Sambuc   /* Flush all digits above the one with 2^d in it */
2954ebfedea0SLionel Sambuc   for(ix = ndig + 1; ix < USED(mp); ix++)
2955ebfedea0SLionel Sambuc     dp[ix] = 0;
2956ebfedea0SLionel Sambuc 
2957ebfedea0SLionel Sambuc   s_mp_clamp(mp);
2958ebfedea0SLionel Sambuc 
2959ebfedea0SLionel Sambuc } /* end s_mp_mod_2d() */
2960ebfedea0SLionel Sambuc 
2961ebfedea0SLionel Sambuc /* }}} */
2962ebfedea0SLionel Sambuc 
2963ebfedea0SLionel Sambuc /* {{{ s_mp_mul_2d(mp, d) */
2964ebfedea0SLionel Sambuc 
2965ebfedea0SLionel Sambuc /*
2966ebfedea0SLionel Sambuc   Multiply by the integer 2^d, where d is a number of bits.  This
2967ebfedea0SLionel Sambuc   amounts to a bitwise shift of the value, and does not require the
2968ebfedea0SLionel Sambuc   full multiplication code.
2969ebfedea0SLionel Sambuc  */
s_mp_mul_2d(mp_int * mp,mp_digit d)2970ebfedea0SLionel Sambuc mp_err    s_mp_mul_2d(mp_int *mp, mp_digit d)
2971ebfedea0SLionel Sambuc {
2972ebfedea0SLionel Sambuc   mp_err   res;
2973ebfedea0SLionel Sambuc   mp_digit save, next, mask, *dp;
2974ebfedea0SLionel Sambuc   mp_size  used;
2975ebfedea0SLionel Sambuc   int      ix;
2976ebfedea0SLionel Sambuc 
2977ebfedea0SLionel Sambuc   if((res = s_mp_lshd(mp, d / DIGIT_BIT)) != MP_OKAY)
2978ebfedea0SLionel Sambuc     return res;
2979ebfedea0SLionel Sambuc 
2980ebfedea0SLionel Sambuc   dp = DIGITS(mp); used = USED(mp);
2981ebfedea0SLionel Sambuc   d %= DIGIT_BIT;
2982ebfedea0SLionel Sambuc 
2983ebfedea0SLionel Sambuc   mask = (1 << d) - 1;
2984ebfedea0SLionel Sambuc 
2985ebfedea0SLionel Sambuc   /* If the shift requires another digit, make sure we've got one to
2986ebfedea0SLionel Sambuc      work with */
2987ebfedea0SLionel Sambuc   if((dp[used - 1] >> (DIGIT_BIT - d)) & mask) {
2988ebfedea0SLionel Sambuc     if((res = s_mp_grow(mp, used + 1)) != MP_OKAY)
2989ebfedea0SLionel Sambuc       return res;
2990ebfedea0SLionel Sambuc     dp = DIGITS(mp);
2991ebfedea0SLionel Sambuc   }
2992ebfedea0SLionel Sambuc 
2993ebfedea0SLionel Sambuc   /* Do the shifting... */
2994ebfedea0SLionel Sambuc   save = 0;
2995ebfedea0SLionel Sambuc   for(ix = 0; ix < used; ix++) {
2996ebfedea0SLionel Sambuc     next = (dp[ix] >> (DIGIT_BIT - d)) & mask;
2997ebfedea0SLionel Sambuc     dp[ix] = (dp[ix] << d) | save;
2998ebfedea0SLionel Sambuc     save = next;
2999ebfedea0SLionel Sambuc   }
3000ebfedea0SLionel Sambuc 
3001ebfedea0SLionel Sambuc   /* If, at this point, we have a nonzero carryout into the next
3002ebfedea0SLionel Sambuc      digit, we'll increase the size by one digit, and store it...
3003ebfedea0SLionel Sambuc    */
3004ebfedea0SLionel Sambuc   if(save) {
3005ebfedea0SLionel Sambuc     dp[used] = save;
3006ebfedea0SLionel Sambuc     USED(mp) += 1;
3007ebfedea0SLionel Sambuc   }
3008ebfedea0SLionel Sambuc 
3009ebfedea0SLionel Sambuc   s_mp_clamp(mp);
3010ebfedea0SLionel Sambuc   return MP_OKAY;
3011ebfedea0SLionel Sambuc 
3012ebfedea0SLionel Sambuc } /* end s_mp_mul_2d() */
3013ebfedea0SLionel Sambuc 
3014ebfedea0SLionel Sambuc /* }}} */
3015ebfedea0SLionel Sambuc 
3016ebfedea0SLionel Sambuc /* {{{ s_mp_div_2d(mp, d) */
3017ebfedea0SLionel Sambuc 
3018ebfedea0SLionel Sambuc /*
3019ebfedea0SLionel Sambuc   Divide the integer by 2^d, where d is a number of bits.  This
3020ebfedea0SLionel Sambuc   amounts to a bitwise shift of the value, and does not require the
3021ebfedea0SLionel Sambuc   full division code (used in Barrett reduction, see below)
3022ebfedea0SLionel Sambuc  */
s_mp_div_2d(mp_int * mp,mp_digit d)3023ebfedea0SLionel Sambuc void     s_mp_div_2d(mp_int *mp, mp_digit d)
3024ebfedea0SLionel Sambuc {
3025ebfedea0SLionel Sambuc   int       ix;
3026ebfedea0SLionel Sambuc   mp_digit  save, next, mask, *dp = DIGITS(mp);
3027ebfedea0SLionel Sambuc 
3028ebfedea0SLionel Sambuc   s_mp_rshd(mp, d / DIGIT_BIT);
3029ebfedea0SLionel Sambuc   d %= DIGIT_BIT;
3030ebfedea0SLionel Sambuc 
3031ebfedea0SLionel Sambuc   mask = (1 << d) - 1;
3032ebfedea0SLionel Sambuc 
3033ebfedea0SLionel Sambuc   save = 0;
3034ebfedea0SLionel Sambuc   for(ix = USED(mp) - 1; ix >= 0; ix--) {
3035ebfedea0SLionel Sambuc     next = dp[ix] & mask;
3036ebfedea0SLionel Sambuc     dp[ix] = (dp[ix] >> d) | (save << (DIGIT_BIT - d));
3037ebfedea0SLionel Sambuc     save = next;
3038ebfedea0SLionel Sambuc   }
3039ebfedea0SLionel Sambuc 
3040ebfedea0SLionel Sambuc   s_mp_clamp(mp);
3041ebfedea0SLionel Sambuc 
3042ebfedea0SLionel Sambuc } /* end s_mp_div_2d() */
3043ebfedea0SLionel Sambuc 
3044ebfedea0SLionel Sambuc /* }}} */
3045ebfedea0SLionel Sambuc 
3046ebfedea0SLionel Sambuc /* {{{ s_mp_norm(a, b) */
3047ebfedea0SLionel Sambuc 
3048ebfedea0SLionel Sambuc /*
3049ebfedea0SLionel Sambuc   s_mp_norm(a, b)
3050ebfedea0SLionel Sambuc 
3051ebfedea0SLionel Sambuc   Normalize a and b for division, where b is the divisor.  In order
3052ebfedea0SLionel Sambuc   that we might make good guesses for quotient digits, we want the
3053ebfedea0SLionel Sambuc   leading digit of b to be at least half the radix, which we
3054ebfedea0SLionel Sambuc   accomplish by multiplying a and b by a constant.  This constant is
3055ebfedea0SLionel Sambuc   returned (so that it can be divided back out of the remainder at the
3056ebfedea0SLionel Sambuc   end of the division process).
3057ebfedea0SLionel Sambuc 
3058ebfedea0SLionel Sambuc   We multiply by the smallest power of 2 that gives us a leading digit
3059ebfedea0SLionel Sambuc   at least half the radix.  By choosing a power of 2, we simplify the
3060ebfedea0SLionel Sambuc   multiplication and division steps to simple shifts.
3061ebfedea0SLionel Sambuc  */
s_mp_norm(mp_int * a,mp_int * b)3062ebfedea0SLionel Sambuc mp_digit s_mp_norm(mp_int *a, mp_int *b)
3063ebfedea0SLionel Sambuc {
3064ebfedea0SLionel Sambuc   mp_digit  t, d = 0;
3065ebfedea0SLionel Sambuc 
3066ebfedea0SLionel Sambuc   t = DIGIT(b, USED(b) - 1);
3067ebfedea0SLionel Sambuc   while(t < (RADIX / 2)) {
3068ebfedea0SLionel Sambuc     t <<= 1;
3069ebfedea0SLionel Sambuc     ++d;
3070ebfedea0SLionel Sambuc   }
3071ebfedea0SLionel Sambuc 
3072ebfedea0SLionel Sambuc   if(d != 0) {
3073ebfedea0SLionel Sambuc     s_mp_mul_2d(a, d);
3074ebfedea0SLionel Sambuc     s_mp_mul_2d(b, d);
3075ebfedea0SLionel Sambuc   }
3076ebfedea0SLionel Sambuc 
3077ebfedea0SLionel Sambuc   return d;
3078ebfedea0SLionel Sambuc 
3079ebfedea0SLionel Sambuc } /* end s_mp_norm() */
3080ebfedea0SLionel Sambuc 
3081ebfedea0SLionel Sambuc /* }}} */
3082ebfedea0SLionel Sambuc 
3083ebfedea0SLionel Sambuc /* }}} */
3084ebfedea0SLionel Sambuc 
3085ebfedea0SLionel Sambuc /* {{{ Primitive digit arithmetic */
3086ebfedea0SLionel Sambuc 
3087ebfedea0SLionel Sambuc /* {{{ s_mp_add_d(mp, d) */
3088ebfedea0SLionel Sambuc 
3089ebfedea0SLionel Sambuc /* Add d to |mp| in place                                                 */
s_mp_add_d(mp_int * mp,mp_digit d)3090ebfedea0SLionel Sambuc mp_err   s_mp_add_d(mp_int *mp, mp_digit d)    /* unsigned digit addition */
3091ebfedea0SLionel Sambuc {
3092ebfedea0SLionel Sambuc   mp_word   w, k = 0;
3093ebfedea0SLionel Sambuc   mp_size   ix = 1, used = USED(mp);
3094ebfedea0SLionel Sambuc   mp_digit *dp = DIGITS(mp);
3095ebfedea0SLionel Sambuc 
3096ebfedea0SLionel Sambuc   w = dp[0] + d;
3097ebfedea0SLionel Sambuc   dp[0] = ACCUM(w);
3098ebfedea0SLionel Sambuc   k = CARRYOUT(w);
3099ebfedea0SLionel Sambuc 
3100ebfedea0SLionel Sambuc   while(ix < used && k) {
3101ebfedea0SLionel Sambuc     w = dp[ix] + k;
3102ebfedea0SLionel Sambuc     dp[ix] = ACCUM(w);
3103ebfedea0SLionel Sambuc     k = CARRYOUT(w);
3104ebfedea0SLionel Sambuc     ++ix;
3105ebfedea0SLionel Sambuc   }
3106ebfedea0SLionel Sambuc 
3107ebfedea0SLionel Sambuc   if(k != 0) {
3108ebfedea0SLionel Sambuc     mp_err  res;
3109ebfedea0SLionel Sambuc 
3110ebfedea0SLionel Sambuc     if((res = s_mp_pad(mp, USED(mp) + 1)) != MP_OKAY)
3111ebfedea0SLionel Sambuc       return res;
3112ebfedea0SLionel Sambuc 
3113ebfedea0SLionel Sambuc     DIGIT(mp, ix) = k;
3114ebfedea0SLionel Sambuc   }
3115ebfedea0SLionel Sambuc 
3116ebfedea0SLionel Sambuc   return MP_OKAY;
3117ebfedea0SLionel Sambuc 
3118ebfedea0SLionel Sambuc } /* end s_mp_add_d() */
3119ebfedea0SLionel Sambuc 
3120ebfedea0SLionel Sambuc /* }}} */
3121ebfedea0SLionel Sambuc 
3122ebfedea0SLionel Sambuc /* {{{ s_mp_sub_d(mp, d) */
3123ebfedea0SLionel Sambuc 
3124ebfedea0SLionel Sambuc /* Subtract d from |mp| in place, assumes |mp| > d                        */
s_mp_sub_d(mp_int * mp,mp_digit d)3125ebfedea0SLionel Sambuc mp_err   s_mp_sub_d(mp_int *mp, mp_digit d)    /* unsigned digit subtract */
3126ebfedea0SLionel Sambuc {
3127ebfedea0SLionel Sambuc   mp_word   w, b = 0;
3128ebfedea0SLionel Sambuc   mp_size   ix = 1, used = USED(mp);
3129ebfedea0SLionel Sambuc   mp_digit *dp = DIGITS(mp);
3130ebfedea0SLionel Sambuc 
3131ebfedea0SLionel Sambuc   /* Compute initial subtraction    */
3132ebfedea0SLionel Sambuc   w = (RADIX + dp[0]) - d;
3133ebfedea0SLionel Sambuc   b = CARRYOUT(w) ? 0 : 1;
3134ebfedea0SLionel Sambuc   dp[0] = ACCUM(w);
3135ebfedea0SLionel Sambuc 
3136ebfedea0SLionel Sambuc   /* Propagate borrows leftward     */
3137ebfedea0SLionel Sambuc   while(b && ix < used) {
3138ebfedea0SLionel Sambuc     w = (RADIX + dp[ix]) - b;
3139ebfedea0SLionel Sambuc     b = CARRYOUT(w) ? 0 : 1;
3140ebfedea0SLionel Sambuc     dp[ix] = ACCUM(w);
3141ebfedea0SLionel Sambuc     ++ix;
3142ebfedea0SLionel Sambuc   }
3143ebfedea0SLionel Sambuc 
3144ebfedea0SLionel Sambuc   /* Remove leading zeroes          */
3145ebfedea0SLionel Sambuc   s_mp_clamp(mp);
3146ebfedea0SLionel Sambuc 
3147ebfedea0SLionel Sambuc   /* If we have a borrow out, it's a violation of the input invariant */
3148ebfedea0SLionel Sambuc   if(b)
3149ebfedea0SLionel Sambuc     return MP_RANGE;
3150ebfedea0SLionel Sambuc   else
3151ebfedea0SLionel Sambuc     return MP_OKAY;
3152ebfedea0SLionel Sambuc 
3153ebfedea0SLionel Sambuc } /* end s_mp_sub_d() */
3154ebfedea0SLionel Sambuc 
3155ebfedea0SLionel Sambuc /* }}} */
3156ebfedea0SLionel Sambuc 
3157ebfedea0SLionel Sambuc /* {{{ s_mp_mul_d(a, d) */
3158ebfedea0SLionel Sambuc 
3159ebfedea0SLionel Sambuc /* Compute a = a * d, single digit multiplication                         */
s_mp_mul_d(mp_int * a,mp_digit d)3160ebfedea0SLionel Sambuc mp_err   s_mp_mul_d(mp_int *a, mp_digit d)
3161ebfedea0SLionel Sambuc {
3162ebfedea0SLionel Sambuc   mp_word w, k = 0;
3163ebfedea0SLionel Sambuc   mp_size ix, max;
3164ebfedea0SLionel Sambuc   mp_err  res;
3165ebfedea0SLionel Sambuc   mp_digit *dp = DIGITS(a);
3166ebfedea0SLionel Sambuc 
3167ebfedea0SLionel Sambuc   /*
3168ebfedea0SLionel Sambuc     Single-digit multiplication will increase the precision of the
3169ebfedea0SLionel Sambuc     output by at most one digit.  However, we can detect when this
3170ebfedea0SLionel Sambuc     will happen -- if the high-order digit of a, times d, gives a
3171ebfedea0SLionel Sambuc     two-digit result, then the precision of the result will increase;
3172ebfedea0SLionel Sambuc     otherwise it won't.  We use this fact to avoid calling s_mp_pad()
3173ebfedea0SLionel Sambuc     unless absolutely necessary.
3174ebfedea0SLionel Sambuc    */
3175ebfedea0SLionel Sambuc   max = USED(a);
3176ebfedea0SLionel Sambuc   w = dp[max - 1] * d;
3177ebfedea0SLionel Sambuc   if(CARRYOUT(w) != 0) {
3178ebfedea0SLionel Sambuc     if((res = s_mp_pad(a, max + 1)) != MP_OKAY)
3179ebfedea0SLionel Sambuc       return res;
3180ebfedea0SLionel Sambuc     dp = DIGITS(a);
3181ebfedea0SLionel Sambuc   }
3182ebfedea0SLionel Sambuc 
3183ebfedea0SLionel Sambuc   for(ix = 0; ix < max; ix++) {
3184ebfedea0SLionel Sambuc     w = (dp[ix] * d) + k;
3185ebfedea0SLionel Sambuc     dp[ix] = ACCUM(w);
3186ebfedea0SLionel Sambuc     k = CARRYOUT(w);
3187ebfedea0SLionel Sambuc   }
3188ebfedea0SLionel Sambuc 
3189ebfedea0SLionel Sambuc   /* If there is a precision increase, take care of it here; the above
3190ebfedea0SLionel Sambuc      test guarantees we have enough storage to do this safely.
3191ebfedea0SLionel Sambuc    */
3192ebfedea0SLionel Sambuc   if(k) {
3193ebfedea0SLionel Sambuc     dp[max] = k;
3194ebfedea0SLionel Sambuc     USED(a) = max + 1;
3195ebfedea0SLionel Sambuc   }
3196ebfedea0SLionel Sambuc 
3197ebfedea0SLionel Sambuc   s_mp_clamp(a);
3198ebfedea0SLionel Sambuc 
3199ebfedea0SLionel Sambuc   return MP_OKAY;
3200ebfedea0SLionel Sambuc 
3201ebfedea0SLionel Sambuc } /* end s_mp_mul_d() */
3202ebfedea0SLionel Sambuc 
3203ebfedea0SLionel Sambuc /* }}} */
3204ebfedea0SLionel Sambuc 
3205ebfedea0SLionel Sambuc /* {{{ s_mp_div_d(mp, d, r) */
3206ebfedea0SLionel Sambuc 
3207ebfedea0SLionel Sambuc /*
3208ebfedea0SLionel Sambuc   s_mp_div_d(mp, d, r)
3209ebfedea0SLionel Sambuc 
3210ebfedea0SLionel Sambuc   Compute the quotient mp = mp / d and remainder r = mp mod d, for a
3211ebfedea0SLionel Sambuc   single digit d.  If r is null, the remainder will be discarded.
3212ebfedea0SLionel Sambuc  */
3213ebfedea0SLionel Sambuc 
s_mp_div_d(mp_int * mp,mp_digit d,mp_digit * r)3214ebfedea0SLionel Sambuc mp_err   s_mp_div_d(mp_int *mp, mp_digit d, mp_digit *r)
3215ebfedea0SLionel Sambuc {
3216ebfedea0SLionel Sambuc   mp_word   w = 0, t;
3217ebfedea0SLionel Sambuc   mp_int    quot;
3218ebfedea0SLionel Sambuc   mp_err    res;
3219ebfedea0SLionel Sambuc   mp_digit *dp = DIGITS(mp), *qp;
3220ebfedea0SLionel Sambuc   int       ix;
3221ebfedea0SLionel Sambuc 
3222ebfedea0SLionel Sambuc   if(d == 0)
3223ebfedea0SLionel Sambuc     return MP_RANGE;
3224ebfedea0SLionel Sambuc 
3225ebfedea0SLionel Sambuc   /* Make room for the quotient */
3226ebfedea0SLionel Sambuc   if((res = mp_init_size(&quot, USED(mp))) != MP_OKAY)
3227ebfedea0SLionel Sambuc     return res;
3228ebfedea0SLionel Sambuc 
3229ebfedea0SLionel Sambuc   USED(&quot) = USED(mp); /* so clamping will work below */
3230ebfedea0SLionel Sambuc   qp = DIGITS(&quot);
3231ebfedea0SLionel Sambuc 
3232ebfedea0SLionel Sambuc   /* Divide without subtraction */
3233ebfedea0SLionel Sambuc   for(ix = USED(mp) - 1; ix >= 0; ix--) {
3234ebfedea0SLionel Sambuc     w = (w << DIGIT_BIT) | dp[ix];
3235ebfedea0SLionel Sambuc 
3236ebfedea0SLionel Sambuc     if(w >= d) {
3237ebfedea0SLionel Sambuc       t = w / d;
3238ebfedea0SLionel Sambuc       w = w % d;
3239ebfedea0SLionel Sambuc     } else {
3240ebfedea0SLionel Sambuc       t = 0;
3241ebfedea0SLionel Sambuc     }
3242ebfedea0SLionel Sambuc 
3243ebfedea0SLionel Sambuc     qp[ix] = t;
3244ebfedea0SLionel Sambuc   }
3245ebfedea0SLionel Sambuc 
3246ebfedea0SLionel Sambuc   /* Deliver the remainder, if desired */
3247ebfedea0SLionel Sambuc   if(r)
3248ebfedea0SLionel Sambuc     *r = w;
3249ebfedea0SLionel Sambuc 
3250ebfedea0SLionel Sambuc   s_mp_clamp(&quot);
3251ebfedea0SLionel Sambuc   mp_exch(&quot, mp);
3252ebfedea0SLionel Sambuc   mp_clear(&quot);
3253ebfedea0SLionel Sambuc 
3254ebfedea0SLionel Sambuc   return MP_OKAY;
3255ebfedea0SLionel Sambuc 
3256ebfedea0SLionel Sambuc } /* end s_mp_div_d() */
3257ebfedea0SLionel Sambuc 
3258ebfedea0SLionel Sambuc /* }}} */
3259ebfedea0SLionel Sambuc 
3260ebfedea0SLionel Sambuc /* }}} */
3261ebfedea0SLionel Sambuc 
3262ebfedea0SLionel Sambuc /* {{{ Primitive full arithmetic */
3263ebfedea0SLionel Sambuc 
3264ebfedea0SLionel Sambuc /* {{{ s_mp_add(a, b) */
3265ebfedea0SLionel Sambuc 
3266ebfedea0SLionel Sambuc /* Compute a = |a| + |b|                                                  */
s_mp_add(mp_int * a,mp_int * b)3267ebfedea0SLionel Sambuc mp_err   s_mp_add(mp_int *a, mp_int *b)        /* magnitude addition      */
3268ebfedea0SLionel Sambuc {
3269ebfedea0SLionel Sambuc   mp_word   w = 0;
3270ebfedea0SLionel Sambuc   mp_digit *pa, *pb;
3271ebfedea0SLionel Sambuc   mp_size   ix, used = USED(b);
3272ebfedea0SLionel Sambuc   mp_err    res;
3273ebfedea0SLionel Sambuc 
3274ebfedea0SLionel Sambuc   /* Make sure a has enough precision for the output value */
3275ebfedea0SLionel Sambuc   if((used > USED(a)) && (res = s_mp_pad(a, used)) != MP_OKAY)
3276ebfedea0SLionel Sambuc     return res;
3277ebfedea0SLionel Sambuc 
3278ebfedea0SLionel Sambuc   /*
3279ebfedea0SLionel Sambuc     Add up all digits up to the precision of b.  If b had initially
3280ebfedea0SLionel Sambuc     the same precision as a, or greater, we took care of it by the
3281ebfedea0SLionel Sambuc     padding step above, so there is no problem.  If b had initially
3282ebfedea0SLionel Sambuc     less precision, we'll have to make sure the carry out is duly
3283ebfedea0SLionel Sambuc     propagated upward among the higher-order digits of the sum.
3284ebfedea0SLionel Sambuc    */
3285ebfedea0SLionel Sambuc   pa = DIGITS(a);
3286ebfedea0SLionel Sambuc   pb = DIGITS(b);
3287ebfedea0SLionel Sambuc   for(ix = 0; ix < used; ++ix) {
3288ebfedea0SLionel Sambuc     w += *pa + *pb++;
3289ebfedea0SLionel Sambuc     *pa++ = ACCUM(w);
3290ebfedea0SLionel Sambuc     w = CARRYOUT(w);
3291ebfedea0SLionel Sambuc   }
3292ebfedea0SLionel Sambuc 
3293ebfedea0SLionel Sambuc   /* If we run out of 'b' digits before we're actually done, make
3294ebfedea0SLionel Sambuc      sure the carries get propagated upward...
3295ebfedea0SLionel Sambuc    */
3296ebfedea0SLionel Sambuc   used = USED(a);
3297ebfedea0SLionel Sambuc   while(w && ix < used) {
3298ebfedea0SLionel Sambuc     w += *pa;
3299ebfedea0SLionel Sambuc     *pa++ = ACCUM(w);
3300ebfedea0SLionel Sambuc     w = CARRYOUT(w);
3301ebfedea0SLionel Sambuc     ++ix;
3302ebfedea0SLionel Sambuc   }
3303ebfedea0SLionel Sambuc 
3304ebfedea0SLionel Sambuc   /* If there's an overall carry out, increase precision and include
3305ebfedea0SLionel Sambuc      it.  We could have done this initially, but why touch the memory
3306ebfedea0SLionel Sambuc      allocator unless we're sure we have to?
3307ebfedea0SLionel Sambuc    */
3308ebfedea0SLionel Sambuc   if(w) {
3309ebfedea0SLionel Sambuc     if((res = s_mp_pad(a, used + 1)) != MP_OKAY)
3310ebfedea0SLionel Sambuc       return res;
3311ebfedea0SLionel Sambuc 
3312ebfedea0SLionel Sambuc     DIGIT(a, ix) = w;  /* pa may not be valid after s_mp_pad() call */
3313ebfedea0SLionel Sambuc   }
3314ebfedea0SLionel Sambuc 
3315ebfedea0SLionel Sambuc   return MP_OKAY;
3316ebfedea0SLionel Sambuc 
3317ebfedea0SLionel Sambuc } /* end s_mp_add() */
3318ebfedea0SLionel Sambuc 
3319ebfedea0SLionel Sambuc /* }}} */
3320ebfedea0SLionel Sambuc 
3321ebfedea0SLionel Sambuc /* {{{ s_mp_sub(a, b) */
3322ebfedea0SLionel Sambuc 
3323ebfedea0SLionel Sambuc /* Compute a = |a| - |b|, assumes |a| >= |b|                              */
s_mp_sub(mp_int * a,mp_int * b)3324ebfedea0SLionel Sambuc mp_err   s_mp_sub(mp_int *a, mp_int *b)        /* magnitude subtract      */
3325ebfedea0SLionel Sambuc {
3326ebfedea0SLionel Sambuc   mp_word   w = 0;
3327ebfedea0SLionel Sambuc   mp_digit *pa, *pb;
3328ebfedea0SLionel Sambuc   mp_size   ix, used = USED(b);
3329ebfedea0SLionel Sambuc 
3330ebfedea0SLionel Sambuc   /*
3331ebfedea0SLionel Sambuc     Subtract and propagate borrow.  Up to the precision of b, this
3332ebfedea0SLionel Sambuc     accounts for the digits of b; after that, we just make sure the
3333ebfedea0SLionel Sambuc     carries get to the right place.  This saves having to pad b out to
3334ebfedea0SLionel Sambuc     the precision of a just to make the loops work right...
3335ebfedea0SLionel Sambuc    */
3336ebfedea0SLionel Sambuc   pa = DIGITS(a);
3337ebfedea0SLionel Sambuc   pb = DIGITS(b);
3338ebfedea0SLionel Sambuc 
3339ebfedea0SLionel Sambuc   for(ix = 0; ix < used; ++ix) {
3340ebfedea0SLionel Sambuc     w = (RADIX + *pa) - w - *pb++;
3341ebfedea0SLionel Sambuc     *pa++ = ACCUM(w);
3342ebfedea0SLionel Sambuc     w = CARRYOUT(w) ? 0 : 1;
3343ebfedea0SLionel Sambuc   }
3344ebfedea0SLionel Sambuc 
3345ebfedea0SLionel Sambuc   used = USED(a);
3346ebfedea0SLionel Sambuc   while(ix < used) {
3347ebfedea0SLionel Sambuc     w = RADIX + *pa - w;
3348ebfedea0SLionel Sambuc     *pa++ = ACCUM(w);
3349ebfedea0SLionel Sambuc     w = CARRYOUT(w) ? 0 : 1;
3350ebfedea0SLionel Sambuc     ++ix;
3351ebfedea0SLionel Sambuc   }
3352ebfedea0SLionel Sambuc 
3353ebfedea0SLionel Sambuc   /* Clobber any leading zeroes we created    */
3354ebfedea0SLionel Sambuc   s_mp_clamp(a);
3355ebfedea0SLionel Sambuc 
3356ebfedea0SLionel Sambuc   /*
3357ebfedea0SLionel Sambuc      If there was a borrow out, then |b| > |a| in violation
3358ebfedea0SLionel Sambuc      of our input invariant.  We've already done the work,
3359ebfedea0SLionel Sambuc      but we'll at least complain about it...
3360ebfedea0SLionel Sambuc    */
3361ebfedea0SLionel Sambuc   if(w)
3362ebfedea0SLionel Sambuc     return MP_RANGE;
3363ebfedea0SLionel Sambuc   else
3364ebfedea0SLionel Sambuc     return MP_OKAY;
3365ebfedea0SLionel Sambuc 
3366ebfedea0SLionel Sambuc } /* end s_mp_sub() */
3367ebfedea0SLionel Sambuc 
3368ebfedea0SLionel Sambuc /* }}} */
3369ebfedea0SLionel Sambuc 
s_mp_reduce(mp_int * x,mp_int * m,mp_int * mu)3370ebfedea0SLionel Sambuc mp_err   s_mp_reduce(mp_int *x, mp_int *m, mp_int *mu)
3371ebfedea0SLionel Sambuc {
3372ebfedea0SLionel Sambuc   mp_int   q;
3373ebfedea0SLionel Sambuc   mp_err   res;
3374ebfedea0SLionel Sambuc   mp_size  um = USED(m);
3375ebfedea0SLionel Sambuc 
3376ebfedea0SLionel Sambuc   if((res = mp_init_copy(&q, x)) != MP_OKAY)
3377ebfedea0SLionel Sambuc     return res;
3378ebfedea0SLionel Sambuc 
3379ebfedea0SLionel Sambuc   s_mp_rshd(&q, um - 1);       /* q1 = x / b^(k-1)  */
3380ebfedea0SLionel Sambuc   s_mp_mul(&q, mu);            /* q2 = q1 * mu      */
3381ebfedea0SLionel Sambuc   s_mp_rshd(&q, um + 1);       /* q3 = q2 / b^(k+1) */
3382ebfedea0SLionel Sambuc 
3383ebfedea0SLionel Sambuc   /* x = x mod b^(k+1), quick (no division) */
3384ebfedea0SLionel Sambuc   s_mp_mod_2d(x, (mp_digit)(DIGIT_BIT * (um + 1)));
3385ebfedea0SLionel Sambuc 
3386ebfedea0SLionel Sambuc   /* q = q * m mod b^(k+1), quick (no division), uses the short multiplier */
3387ebfedea0SLionel Sambuc #ifndef SHRT_MUL
3388ebfedea0SLionel Sambuc   s_mp_mul(&q, m);
3389ebfedea0SLionel Sambuc   s_mp_mod_2d(&q, (mp_digit)(DIGIT_BIT * (um + 1)));
3390ebfedea0SLionel Sambuc #else
3391ebfedea0SLionel Sambuc   s_mp_mul_dig(&q, m, um + 1);
3392ebfedea0SLionel Sambuc #endif
3393ebfedea0SLionel Sambuc 
3394ebfedea0SLionel Sambuc   /* x = x - q */
3395ebfedea0SLionel Sambuc   if((res = mp_sub(x, &q, x)) != MP_OKAY)
3396ebfedea0SLionel Sambuc     goto CLEANUP;
3397ebfedea0SLionel Sambuc 
3398ebfedea0SLionel Sambuc   /* If x < 0, add b^(k+1) to it */
3399ebfedea0SLionel Sambuc   if(mp_cmp_z(x) < 0) {
3400ebfedea0SLionel Sambuc     mp_set(&q, 1);
3401ebfedea0SLionel Sambuc     if((res = s_mp_lshd(&q, um + 1)) != MP_OKAY)
3402ebfedea0SLionel Sambuc       goto CLEANUP;
3403ebfedea0SLionel Sambuc     if((res = mp_add(x, &q, x)) != MP_OKAY)
3404ebfedea0SLionel Sambuc       goto CLEANUP;
3405ebfedea0SLionel Sambuc   }
3406ebfedea0SLionel Sambuc 
3407ebfedea0SLionel Sambuc   /* Back off if it's too big */
3408ebfedea0SLionel Sambuc   while(mp_cmp(x, m) >= 0) {
3409ebfedea0SLionel Sambuc     if((res = s_mp_sub(x, m)) != MP_OKAY)
3410ebfedea0SLionel Sambuc       break;
3411ebfedea0SLionel Sambuc   }
3412ebfedea0SLionel Sambuc 
3413ebfedea0SLionel Sambuc  CLEANUP:
3414ebfedea0SLionel Sambuc   mp_clear(&q);
3415ebfedea0SLionel Sambuc 
3416ebfedea0SLionel Sambuc   return res;
3417ebfedea0SLionel Sambuc 
3418ebfedea0SLionel Sambuc } /* end s_mp_reduce() */
3419ebfedea0SLionel Sambuc 
3420ebfedea0SLionel Sambuc 
3421ebfedea0SLionel Sambuc 
3422ebfedea0SLionel Sambuc /* {{{ s_mp_mul(a, b) */
3423ebfedea0SLionel Sambuc 
3424ebfedea0SLionel Sambuc /* Compute a = |a| * |b|                                                  */
s_mp_mul(mp_int * a,mp_int * b)3425ebfedea0SLionel Sambuc mp_err   s_mp_mul(mp_int *a, mp_int *b)
3426ebfedea0SLionel Sambuc {
3427ebfedea0SLionel Sambuc   mp_word   w, k = 0;
3428ebfedea0SLionel Sambuc   mp_int    tmp;
3429ebfedea0SLionel Sambuc   mp_err    res;
3430ebfedea0SLionel Sambuc   mp_size   ix, jx, ua = USED(a), ub = USED(b);
3431ebfedea0SLionel Sambuc   mp_digit *pa, *pb, *pt, *pbt;
3432ebfedea0SLionel Sambuc 
3433ebfedea0SLionel Sambuc   if((res = mp_init_size(&tmp, ua + ub)) != MP_OKAY)
3434ebfedea0SLionel Sambuc     return res;
3435ebfedea0SLionel Sambuc 
3436ebfedea0SLionel Sambuc   /* This has the effect of left-padding with zeroes... */
3437ebfedea0SLionel Sambuc   USED(&tmp) = ua + ub;
3438ebfedea0SLionel Sambuc 
3439ebfedea0SLionel Sambuc   /* We're going to need the base value each iteration */
3440ebfedea0SLionel Sambuc   pbt = DIGITS(&tmp);
3441ebfedea0SLionel Sambuc 
3442ebfedea0SLionel Sambuc   /* Outer loop:  Digits of b */
3443ebfedea0SLionel Sambuc 
3444ebfedea0SLionel Sambuc   pb = DIGITS(b);
3445ebfedea0SLionel Sambuc   for(ix = 0; ix < ub; ++ix, ++pb) {
3446ebfedea0SLionel Sambuc     if(*pb == 0)
3447ebfedea0SLionel Sambuc       continue;
3448ebfedea0SLionel Sambuc 
3449ebfedea0SLionel Sambuc     /* Inner product:  Digits of a */
3450ebfedea0SLionel Sambuc     pa = DIGITS(a);
3451ebfedea0SLionel Sambuc     for(jx = 0; jx < ua; ++jx, ++pa) {
3452ebfedea0SLionel Sambuc       pt = pbt + ix + jx;
3453ebfedea0SLionel Sambuc       w = *pb * *pa + k + *pt;
3454ebfedea0SLionel Sambuc       *pt = ACCUM(w);
3455ebfedea0SLionel Sambuc       k = CARRYOUT(w);
3456ebfedea0SLionel Sambuc     }
3457ebfedea0SLionel Sambuc 
3458ebfedea0SLionel Sambuc     pbt[ix + jx] = k;
3459ebfedea0SLionel Sambuc     k = 0;
3460ebfedea0SLionel Sambuc   }
3461ebfedea0SLionel Sambuc 
3462ebfedea0SLionel Sambuc   s_mp_clamp(&tmp);
3463ebfedea0SLionel Sambuc   s_mp_exch(&tmp, a);
3464ebfedea0SLionel Sambuc 
3465ebfedea0SLionel Sambuc   mp_clear(&tmp);
3466ebfedea0SLionel Sambuc 
3467ebfedea0SLionel Sambuc   return MP_OKAY;
3468ebfedea0SLionel Sambuc 
3469ebfedea0SLionel Sambuc } /* end s_mp_mul() */
3470ebfedea0SLionel Sambuc 
3471ebfedea0SLionel Sambuc /* }}} */
3472ebfedea0SLionel Sambuc 
3473ebfedea0SLionel Sambuc /* {{{ s_mp_kmul(a, b, out, len) */
3474ebfedea0SLionel Sambuc 
3475ebfedea0SLionel Sambuc #if 0
3476ebfedea0SLionel Sambuc void   s_mp_kmul(mp_digit *a, mp_digit *b, mp_digit *out, mp_size len)
3477ebfedea0SLionel Sambuc {
3478ebfedea0SLionel Sambuc   mp_word   w, k = 0;
3479ebfedea0SLionel Sambuc   mp_size   ix, jx;
3480ebfedea0SLionel Sambuc   mp_digit *pa, *pt;
3481ebfedea0SLionel Sambuc 
3482ebfedea0SLionel Sambuc   for(ix = 0; ix < len; ++ix, ++b) {
3483ebfedea0SLionel Sambuc     if(*b == 0)
3484ebfedea0SLionel Sambuc       continue;
3485ebfedea0SLionel Sambuc 
3486ebfedea0SLionel Sambuc     pa = a;
3487ebfedea0SLionel Sambuc     for(jx = 0; jx < len; ++jx, ++pa) {
3488ebfedea0SLionel Sambuc       pt = out + ix + jx;
3489ebfedea0SLionel Sambuc       w = *b * *pa + k + *pt;
3490ebfedea0SLionel Sambuc       *pt = ACCUM(w);
3491ebfedea0SLionel Sambuc       k = CARRYOUT(w);
3492ebfedea0SLionel Sambuc     }
3493ebfedea0SLionel Sambuc 
3494ebfedea0SLionel Sambuc     out[ix + jx] = k;
3495ebfedea0SLionel Sambuc     k = 0;
3496ebfedea0SLionel Sambuc   }
3497ebfedea0SLionel Sambuc 
3498ebfedea0SLionel Sambuc } /* end s_mp_kmul() */
3499ebfedea0SLionel Sambuc #endif
3500ebfedea0SLionel Sambuc 
3501ebfedea0SLionel Sambuc /* }}} */
3502ebfedea0SLionel Sambuc 
3503ebfedea0SLionel Sambuc /* {{{ s_mp_sqr(a) */
3504ebfedea0SLionel Sambuc 
3505ebfedea0SLionel Sambuc /*
3506ebfedea0SLionel Sambuc   Computes the square of a, in place.  This can be done more
3507ebfedea0SLionel Sambuc   efficiently than a general multiplication, because many of the
3508ebfedea0SLionel Sambuc   computation steps are redundant when squaring.  The inner product
3509ebfedea0SLionel Sambuc   step is a bit more complicated, but we save a fair number of
3510ebfedea0SLionel Sambuc   iterations of the multiplication loop.
3511ebfedea0SLionel Sambuc  */
3512ebfedea0SLionel Sambuc #if MP_SQUARE
s_mp_sqr(mp_int * a)3513ebfedea0SLionel Sambuc mp_err   s_mp_sqr(mp_int *a)
3514ebfedea0SLionel Sambuc {
3515ebfedea0SLionel Sambuc   mp_word  w, k = 0;
3516ebfedea0SLionel Sambuc   mp_int   tmp;
3517ebfedea0SLionel Sambuc   mp_err   res;
3518ebfedea0SLionel Sambuc   mp_size  ix, jx, kx, used = USED(a);
3519ebfedea0SLionel Sambuc   mp_digit *pa1, *pa2, *pt, *pbt;
3520ebfedea0SLionel Sambuc 
3521ebfedea0SLionel Sambuc   if((res = mp_init_size(&tmp, 2 * used)) != MP_OKAY)
3522ebfedea0SLionel Sambuc     return res;
3523ebfedea0SLionel Sambuc 
3524ebfedea0SLionel Sambuc   /* Left-pad with zeroes */
3525ebfedea0SLionel Sambuc   USED(&tmp) = 2 * used;
3526ebfedea0SLionel Sambuc 
3527ebfedea0SLionel Sambuc   /* We need the base value each time through the loop */
3528ebfedea0SLionel Sambuc   pbt = DIGITS(&tmp);
3529ebfedea0SLionel Sambuc 
3530ebfedea0SLionel Sambuc   pa1 = DIGITS(a);
3531ebfedea0SLionel Sambuc   for(ix = 0; ix < used; ++ix, ++pa1) {
3532ebfedea0SLionel Sambuc     if(*pa1 == 0)
3533ebfedea0SLionel Sambuc       continue;
3534ebfedea0SLionel Sambuc 
3535ebfedea0SLionel Sambuc     w = DIGIT(&tmp, ix + ix) + (*pa1 * *pa1);
3536ebfedea0SLionel Sambuc 
3537ebfedea0SLionel Sambuc     pbt[ix + ix] = ACCUM(w);
3538ebfedea0SLionel Sambuc     k = CARRYOUT(w);
3539ebfedea0SLionel Sambuc 
3540ebfedea0SLionel Sambuc     /*
3541ebfedea0SLionel Sambuc       The inner product is computed as:
3542ebfedea0SLionel Sambuc 
3543ebfedea0SLionel Sambuc          (C, S) = t[i,j] + 2 a[i] a[j] + C
3544ebfedea0SLionel Sambuc 
3545ebfedea0SLionel Sambuc       This can overflow what can be represented in an mp_word, and
3546ebfedea0SLionel Sambuc       since C arithmetic does not provide any way to check for
3547ebfedea0SLionel Sambuc       overflow, we have to check explicitly for overflow conditions
3548ebfedea0SLionel Sambuc       before they happen.
3549ebfedea0SLionel Sambuc      */
3550ebfedea0SLionel Sambuc     for(jx = ix + 1, pa2 = DIGITS(a) + jx; jx < used; ++jx, ++pa2) {
3551ebfedea0SLionel Sambuc       mp_word  u = 0, v;
3552ebfedea0SLionel Sambuc 
3553ebfedea0SLionel Sambuc       /* Store this in a temporary to avoid indirections later */
3554ebfedea0SLionel Sambuc       pt = pbt + ix + jx;
3555ebfedea0SLionel Sambuc 
3556ebfedea0SLionel Sambuc       /* Compute the multiplicative step */
3557ebfedea0SLionel Sambuc       w = *pa1 * *pa2;
3558ebfedea0SLionel Sambuc 
3559ebfedea0SLionel Sambuc       /* If w is more than half MP_WORD_MAX, the doubling will
3560ebfedea0SLionel Sambuc 	 overflow, and we need to record a carry out into the next
3561ebfedea0SLionel Sambuc 	 word */
3562ebfedea0SLionel Sambuc       u = (w >> (MP_WORD_BIT - 1)) & 1;
3563ebfedea0SLionel Sambuc 
3564ebfedea0SLionel Sambuc       /* Double what we've got, overflow will be ignored as defined
3565ebfedea0SLionel Sambuc 	 for C arithmetic (we've already noted if it is to occur)
3566ebfedea0SLionel Sambuc        */
3567ebfedea0SLionel Sambuc       w *= 2;
3568ebfedea0SLionel Sambuc 
3569ebfedea0SLionel Sambuc       /* Compute the additive step */
3570ebfedea0SLionel Sambuc       v = *pt + k;
3571ebfedea0SLionel Sambuc 
3572ebfedea0SLionel Sambuc       /* If we do not already have an overflow carry, check to see
3573ebfedea0SLionel Sambuc 	 if the addition will cause one, and set the carry out if so
3574ebfedea0SLionel Sambuc        */
3575ebfedea0SLionel Sambuc       u |= ((MP_WORD_MAX - v) < w);
3576ebfedea0SLionel Sambuc 
3577ebfedea0SLionel Sambuc       /* Add in the rest, again ignoring overflow */
3578ebfedea0SLionel Sambuc       w += v;
3579ebfedea0SLionel Sambuc 
3580ebfedea0SLionel Sambuc       /* Set the i,j digit of the output */
3581ebfedea0SLionel Sambuc       *pt = ACCUM(w);
3582ebfedea0SLionel Sambuc 
3583ebfedea0SLionel Sambuc       /* Save carry information for the next iteration of the loop.
3584ebfedea0SLionel Sambuc 	 This is why k must be an mp_word, instead of an mp_digit */
3585ebfedea0SLionel Sambuc       k = CARRYOUT(w) | (u << DIGIT_BIT);
3586ebfedea0SLionel Sambuc 
3587ebfedea0SLionel Sambuc     } /* for(jx ...) */
3588ebfedea0SLionel Sambuc 
3589ebfedea0SLionel Sambuc     /* Set the last digit in the cycle and reset the carry */
3590ebfedea0SLionel Sambuc     k = DIGIT(&tmp, ix + jx) + k;
3591ebfedea0SLionel Sambuc     pbt[ix + jx] = ACCUM(k);
3592ebfedea0SLionel Sambuc     k = CARRYOUT(k);
3593ebfedea0SLionel Sambuc 
3594ebfedea0SLionel Sambuc     /* If we are carrying out, propagate the carry to the next digit
3595ebfedea0SLionel Sambuc        in the output.  This may cascade, so we have to be somewhat
3596ebfedea0SLionel Sambuc        circumspect -- but we will have enough precision in the output
3597ebfedea0SLionel Sambuc        that we won't overflow
3598ebfedea0SLionel Sambuc      */
3599ebfedea0SLionel Sambuc     kx = 1;
3600ebfedea0SLionel Sambuc     while(k) {
3601ebfedea0SLionel Sambuc       k = pbt[ix + jx + kx] + 1;
3602ebfedea0SLionel Sambuc       pbt[ix + jx + kx] = ACCUM(k);
3603ebfedea0SLionel Sambuc       k = CARRYOUT(k);
3604ebfedea0SLionel Sambuc       ++kx;
3605ebfedea0SLionel Sambuc     }
3606ebfedea0SLionel Sambuc   } /* for(ix ...) */
3607ebfedea0SLionel Sambuc 
3608ebfedea0SLionel Sambuc   s_mp_clamp(&tmp);
3609ebfedea0SLionel Sambuc   s_mp_exch(&tmp, a);
3610ebfedea0SLionel Sambuc 
3611ebfedea0SLionel Sambuc   mp_clear(&tmp);
3612ebfedea0SLionel Sambuc 
3613ebfedea0SLionel Sambuc   return MP_OKAY;
3614ebfedea0SLionel Sambuc 
3615ebfedea0SLionel Sambuc } /* end s_mp_sqr() */
3616ebfedea0SLionel Sambuc #endif
3617ebfedea0SLionel Sambuc 
3618ebfedea0SLionel Sambuc /* }}} */
3619ebfedea0SLionel Sambuc 
3620ebfedea0SLionel Sambuc /* {{{ s_mp_div(a, b) */
3621ebfedea0SLionel Sambuc 
3622ebfedea0SLionel Sambuc /*
3623ebfedea0SLionel Sambuc   s_mp_div(a, b)
3624ebfedea0SLionel Sambuc 
3625ebfedea0SLionel Sambuc   Compute a = a / b and b = a mod b.  Assumes b > a.
3626ebfedea0SLionel Sambuc  */
3627ebfedea0SLionel Sambuc 
s_mp_div(mp_int * a,mp_int * b)3628ebfedea0SLionel Sambuc mp_err   s_mp_div(mp_int *a, mp_int *b)
3629ebfedea0SLionel Sambuc {
3630ebfedea0SLionel Sambuc   mp_int   quot, rem, t;
3631ebfedea0SLionel Sambuc   mp_word  q;
3632ebfedea0SLionel Sambuc   mp_err   res;
3633ebfedea0SLionel Sambuc   mp_digit d;
3634ebfedea0SLionel Sambuc   int      ix;
3635ebfedea0SLionel Sambuc 
3636ebfedea0SLionel Sambuc   if(mp_cmp_z(b) == 0)
3637ebfedea0SLionel Sambuc     return MP_RANGE;
3638ebfedea0SLionel Sambuc 
3639ebfedea0SLionel Sambuc   /* Shortcut if b is power of two */
3640ebfedea0SLionel Sambuc   if((ix = s_mp_ispow2(b)) >= 0) {
3641ebfedea0SLionel Sambuc     mp_copy(a, b);  /* need this for remainder */
3642ebfedea0SLionel Sambuc     s_mp_div_2d(a, (mp_digit)ix);
3643ebfedea0SLionel Sambuc     s_mp_mod_2d(b, (mp_digit)ix);
3644ebfedea0SLionel Sambuc 
3645ebfedea0SLionel Sambuc     return MP_OKAY;
3646ebfedea0SLionel Sambuc   }
3647ebfedea0SLionel Sambuc 
3648ebfedea0SLionel Sambuc   /* Allocate space to store the quotient */
3649ebfedea0SLionel Sambuc   if((res = mp_init_size(&quot, USED(a))) != MP_OKAY)
3650ebfedea0SLionel Sambuc     return res;
3651ebfedea0SLionel Sambuc 
3652ebfedea0SLionel Sambuc   /* A working temporary for division     */
3653ebfedea0SLionel Sambuc   if((res = mp_init_size(&t, USED(a))) != MP_OKAY)
3654ebfedea0SLionel Sambuc     goto T;
3655ebfedea0SLionel Sambuc 
3656ebfedea0SLionel Sambuc   /* Allocate space for the remainder     */
3657ebfedea0SLionel Sambuc   if((res = mp_init_size(&rem, USED(a))) != MP_OKAY)
3658ebfedea0SLionel Sambuc     goto REM;
3659ebfedea0SLionel Sambuc 
3660ebfedea0SLionel Sambuc   /* Normalize to optimize guessing       */
3661ebfedea0SLionel Sambuc   d = s_mp_norm(a, b);
3662ebfedea0SLionel Sambuc 
3663ebfedea0SLionel Sambuc   /* Perform the division itself...woo!   */
3664ebfedea0SLionel Sambuc   ix = USED(a) - 1;
3665ebfedea0SLionel Sambuc 
3666ebfedea0SLionel Sambuc   while(ix >= 0) {
3667ebfedea0SLionel Sambuc     /* Find a partial substring of a which is at least b */
3668ebfedea0SLionel Sambuc     while(s_mp_cmp(&rem, b) < 0 && ix >= 0) {
3669ebfedea0SLionel Sambuc       if((res = s_mp_lshd(&rem, 1)) != MP_OKAY)
3670ebfedea0SLionel Sambuc 	goto CLEANUP;
3671ebfedea0SLionel Sambuc 
3672ebfedea0SLionel Sambuc       if((res = s_mp_lshd(&quot, 1)) != MP_OKAY)
3673ebfedea0SLionel Sambuc 	goto CLEANUP;
3674ebfedea0SLionel Sambuc 
3675ebfedea0SLionel Sambuc       DIGIT(&rem, 0) = DIGIT(a, ix);
3676ebfedea0SLionel Sambuc       s_mp_clamp(&rem);
3677ebfedea0SLionel Sambuc       --ix;
3678ebfedea0SLionel Sambuc     }
3679ebfedea0SLionel Sambuc 
3680ebfedea0SLionel Sambuc     /* If we didn't find one, we're finished dividing    */
3681ebfedea0SLionel Sambuc     if(s_mp_cmp(&rem, b) < 0)
3682ebfedea0SLionel Sambuc       break;
3683ebfedea0SLionel Sambuc 
3684ebfedea0SLionel Sambuc     /* Compute a guess for the next quotient digit       */
3685ebfedea0SLionel Sambuc     q = DIGIT(&rem, USED(&rem) - 1);
3686ebfedea0SLionel Sambuc     if(q <= DIGIT(b, USED(b) - 1) && USED(&rem) > 1)
3687ebfedea0SLionel Sambuc       q = (q << DIGIT_BIT) | DIGIT(&rem, USED(&rem) - 2);
3688ebfedea0SLionel Sambuc 
3689ebfedea0SLionel Sambuc     q /= DIGIT(b, USED(b) - 1);
3690ebfedea0SLionel Sambuc 
3691ebfedea0SLionel Sambuc     /* The guess can be as much as RADIX + 1 */
3692ebfedea0SLionel Sambuc     if(q >= RADIX)
3693ebfedea0SLionel Sambuc       q = RADIX - 1;
3694ebfedea0SLionel Sambuc 
3695ebfedea0SLionel Sambuc     /* See what that multiplies out to                   */
3696ebfedea0SLionel Sambuc     mp_copy(b, &t);
3697ebfedea0SLionel Sambuc     if((res = s_mp_mul_d(&t, q)) != MP_OKAY)
3698ebfedea0SLionel Sambuc       goto CLEANUP;
3699ebfedea0SLionel Sambuc 
3700ebfedea0SLionel Sambuc     /*
3701ebfedea0SLionel Sambuc        If it's too big, back it off.  We should not have to do this
3702ebfedea0SLionel Sambuc        more than once, or, in rare cases, twice.  Knuth describes a
3703ebfedea0SLionel Sambuc        method by which this could be reduced to a maximum of once, but
3704ebfedea0SLionel Sambuc        I didn't implement that here.
3705ebfedea0SLionel Sambuc      */
3706ebfedea0SLionel Sambuc     while(s_mp_cmp(&t, &rem) > 0) {
3707ebfedea0SLionel Sambuc       --q;
3708ebfedea0SLionel Sambuc       s_mp_sub(&t, b);
3709ebfedea0SLionel Sambuc     }
3710ebfedea0SLionel Sambuc 
3711ebfedea0SLionel Sambuc     /* At this point, q should be the right next digit   */
3712ebfedea0SLionel Sambuc     if((res = s_mp_sub(&rem, &t)) != MP_OKAY)
3713ebfedea0SLionel Sambuc       goto CLEANUP;
3714ebfedea0SLionel Sambuc 
3715ebfedea0SLionel Sambuc     /*
3716ebfedea0SLionel Sambuc       Include the digit in the quotient.  We allocated enough memory
3717ebfedea0SLionel Sambuc       for any quotient we could ever possibly get, so we should not
3718ebfedea0SLionel Sambuc       have to check for failures here
3719ebfedea0SLionel Sambuc      */
3720ebfedea0SLionel Sambuc     DIGIT(&quot, 0) = q;
3721ebfedea0SLionel Sambuc   }
3722ebfedea0SLionel Sambuc 
3723ebfedea0SLionel Sambuc   /* Denormalize remainder                */
3724ebfedea0SLionel Sambuc   if(d != 0)
3725ebfedea0SLionel Sambuc     s_mp_div_2d(&rem, d);
3726ebfedea0SLionel Sambuc 
3727ebfedea0SLionel Sambuc   s_mp_clamp(&quot);
3728ebfedea0SLionel Sambuc   s_mp_clamp(&rem);
3729ebfedea0SLionel Sambuc 
3730ebfedea0SLionel Sambuc   /* Copy quotient back to output         */
3731ebfedea0SLionel Sambuc   s_mp_exch(&quot, a);
3732ebfedea0SLionel Sambuc 
3733ebfedea0SLionel Sambuc   /* Copy remainder back to output        */
3734ebfedea0SLionel Sambuc   s_mp_exch(&rem, b);
3735ebfedea0SLionel Sambuc 
3736ebfedea0SLionel Sambuc CLEANUP:
3737ebfedea0SLionel Sambuc   mp_clear(&rem);
3738ebfedea0SLionel Sambuc REM:
3739ebfedea0SLionel Sambuc   mp_clear(&t);
3740ebfedea0SLionel Sambuc T:
3741ebfedea0SLionel Sambuc   mp_clear(&quot);
3742ebfedea0SLionel Sambuc 
3743ebfedea0SLionel Sambuc   return res;
3744ebfedea0SLionel Sambuc 
3745ebfedea0SLionel Sambuc } /* end s_mp_div() */
3746ebfedea0SLionel Sambuc 
3747ebfedea0SLionel Sambuc /* }}} */
3748ebfedea0SLionel Sambuc 
3749ebfedea0SLionel Sambuc /* {{{ s_mp_2expt(a, k) */
3750ebfedea0SLionel Sambuc 
s_mp_2expt(mp_int * a,mp_digit k)3751ebfedea0SLionel Sambuc mp_err   s_mp_2expt(mp_int *a, mp_digit k)
3752ebfedea0SLionel Sambuc {
3753ebfedea0SLionel Sambuc   mp_err    res;
3754ebfedea0SLionel Sambuc   mp_size   dig, bit;
3755ebfedea0SLionel Sambuc 
3756ebfedea0SLionel Sambuc   dig = k / DIGIT_BIT;
3757ebfedea0SLionel Sambuc   bit = k % DIGIT_BIT;
3758ebfedea0SLionel Sambuc 
3759ebfedea0SLionel Sambuc   mp_zero(a);
3760ebfedea0SLionel Sambuc   if((res = s_mp_pad(a, dig + 1)) != MP_OKAY)
3761ebfedea0SLionel Sambuc     return res;
3762ebfedea0SLionel Sambuc 
3763ebfedea0SLionel Sambuc   DIGIT(a, dig) |= (1 << bit);
3764ebfedea0SLionel Sambuc 
3765ebfedea0SLionel Sambuc   return MP_OKAY;
3766ebfedea0SLionel Sambuc 
3767ebfedea0SLionel Sambuc } /* end s_mp_2expt() */
3768ebfedea0SLionel Sambuc 
3769ebfedea0SLionel Sambuc /* }}} */
3770ebfedea0SLionel Sambuc 
3771ebfedea0SLionel Sambuc 
3772ebfedea0SLionel Sambuc /* }}} */
3773ebfedea0SLionel Sambuc 
3774ebfedea0SLionel Sambuc /* }}} */
3775ebfedea0SLionel Sambuc 
3776ebfedea0SLionel Sambuc /* {{{ Primitive comparisons */
3777ebfedea0SLionel Sambuc 
3778ebfedea0SLionel Sambuc /* {{{ s_mp_cmp(a, b) */
3779ebfedea0SLionel Sambuc 
3780ebfedea0SLionel Sambuc /* Compare |a| <=> |b|, return 0 if equal, <0 if a<b, >0 if a>b           */
s_mp_cmp(mp_int * a,mp_int * b)3781ebfedea0SLionel Sambuc int      s_mp_cmp(mp_int *a, mp_int *b)
3782ebfedea0SLionel Sambuc {
3783ebfedea0SLionel Sambuc   mp_size   ua = USED(a), ub = USED(b);
3784ebfedea0SLionel Sambuc 
3785ebfedea0SLionel Sambuc   if(ua > ub)
3786ebfedea0SLionel Sambuc     return MP_GT;
3787ebfedea0SLionel Sambuc   else if(ua < ub)
3788ebfedea0SLionel Sambuc     return MP_LT;
3789ebfedea0SLionel Sambuc   else {
3790ebfedea0SLionel Sambuc     int      ix = ua - 1;
3791ebfedea0SLionel Sambuc     mp_digit *ap = DIGITS(a) + ix, *bp = DIGITS(b) + ix;
3792ebfedea0SLionel Sambuc 
3793ebfedea0SLionel Sambuc     while(ix >= 0) {
3794ebfedea0SLionel Sambuc       if(*ap > *bp)
3795ebfedea0SLionel Sambuc 	return MP_GT;
3796ebfedea0SLionel Sambuc       else if(*ap < *bp)
3797ebfedea0SLionel Sambuc 	return MP_LT;
3798ebfedea0SLionel Sambuc 
3799ebfedea0SLionel Sambuc       --ap; --bp; --ix;
3800ebfedea0SLionel Sambuc     }
3801ebfedea0SLionel Sambuc 
3802ebfedea0SLionel Sambuc     return MP_EQ;
3803ebfedea0SLionel Sambuc   }
3804ebfedea0SLionel Sambuc 
3805ebfedea0SLionel Sambuc } /* end s_mp_cmp() */
3806ebfedea0SLionel Sambuc 
3807ebfedea0SLionel Sambuc /* }}} */
3808ebfedea0SLionel Sambuc 
3809ebfedea0SLionel Sambuc /* {{{ s_mp_cmp_d(a, d) */
3810ebfedea0SLionel Sambuc 
3811ebfedea0SLionel Sambuc /* Compare |a| <=> d, return 0 if equal, <0 if a<d, >0 if a>d             */
s_mp_cmp_d(mp_int * a,mp_digit d)3812ebfedea0SLionel Sambuc int      s_mp_cmp_d(mp_int *a, mp_digit d)
3813ebfedea0SLionel Sambuc {
3814ebfedea0SLionel Sambuc   mp_size  ua = USED(a);
3815ebfedea0SLionel Sambuc   mp_digit *ap = DIGITS(a);
3816ebfedea0SLionel Sambuc 
3817ebfedea0SLionel Sambuc   if(ua > 1)
3818ebfedea0SLionel Sambuc     return MP_GT;
3819ebfedea0SLionel Sambuc 
3820ebfedea0SLionel Sambuc   if(*ap < d)
3821ebfedea0SLionel Sambuc     return MP_LT;
3822ebfedea0SLionel Sambuc   else if(*ap > d)
3823ebfedea0SLionel Sambuc     return MP_GT;
3824ebfedea0SLionel Sambuc   else
3825ebfedea0SLionel Sambuc     return MP_EQ;
3826ebfedea0SLionel Sambuc 
3827ebfedea0SLionel Sambuc } /* end s_mp_cmp_d() */
3828ebfedea0SLionel Sambuc 
3829ebfedea0SLionel Sambuc /* }}} */
3830ebfedea0SLionel Sambuc 
3831ebfedea0SLionel Sambuc /* {{{ s_mp_ispow2(v) */
3832ebfedea0SLionel Sambuc 
3833ebfedea0SLionel Sambuc /*
3834ebfedea0SLionel Sambuc   Returns -1 if the value is not a power of two; otherwise, it returns
3835ebfedea0SLionel Sambuc   k such that v = 2^k, i.e. lg(v).
3836ebfedea0SLionel Sambuc  */
s_mp_ispow2(mp_int * v)3837ebfedea0SLionel Sambuc int      s_mp_ispow2(mp_int *v)
3838ebfedea0SLionel Sambuc {
3839ebfedea0SLionel Sambuc   mp_digit d, *dp;
3840ebfedea0SLionel Sambuc   mp_size  uv = USED(v);
3841ebfedea0SLionel Sambuc   int      extra = 0, ix;
3842ebfedea0SLionel Sambuc 
3843ebfedea0SLionel Sambuc   d = DIGIT(v, uv - 1); /* most significant digit of v */
3844ebfedea0SLionel Sambuc 
3845ebfedea0SLionel Sambuc   while(d && ((d & 1) == 0)) {
3846ebfedea0SLionel Sambuc     d >>= 1;
3847ebfedea0SLionel Sambuc     ++extra;
3848ebfedea0SLionel Sambuc   }
3849ebfedea0SLionel Sambuc 
3850ebfedea0SLionel Sambuc   if(d == 1) {
3851ebfedea0SLionel Sambuc     ix = uv - 2;
3852ebfedea0SLionel Sambuc     dp = DIGITS(v) + ix;
3853ebfedea0SLionel Sambuc 
3854ebfedea0SLionel Sambuc     while(ix >= 0) {
3855ebfedea0SLionel Sambuc       if(*dp)
3856ebfedea0SLionel Sambuc 	return -1; /* not a power of two */
3857ebfedea0SLionel Sambuc 
3858ebfedea0SLionel Sambuc       --dp; --ix;
3859ebfedea0SLionel Sambuc     }
3860ebfedea0SLionel Sambuc 
3861ebfedea0SLionel Sambuc     return ((uv - 1) * DIGIT_BIT) + extra;
3862ebfedea0SLionel Sambuc   }
3863ebfedea0SLionel Sambuc 
3864ebfedea0SLionel Sambuc   return -1;
3865ebfedea0SLionel Sambuc 
3866ebfedea0SLionel Sambuc } /* end s_mp_ispow2() */
3867ebfedea0SLionel Sambuc 
3868ebfedea0SLionel Sambuc /* }}} */
3869ebfedea0SLionel Sambuc 
3870ebfedea0SLionel Sambuc /* {{{ s_mp_ispow2d(d) */
3871ebfedea0SLionel Sambuc 
s_mp_ispow2d(mp_digit d)3872ebfedea0SLionel Sambuc int      s_mp_ispow2d(mp_digit d)
3873ebfedea0SLionel Sambuc {
3874ebfedea0SLionel Sambuc   int   pow = 0;
3875ebfedea0SLionel Sambuc 
3876ebfedea0SLionel Sambuc   while((d & 1) == 0) {
3877ebfedea0SLionel Sambuc     ++pow; d >>= 1;
3878ebfedea0SLionel Sambuc   }
3879ebfedea0SLionel Sambuc 
3880ebfedea0SLionel Sambuc   if(d == 1)
3881ebfedea0SLionel Sambuc     return pow;
3882ebfedea0SLionel Sambuc 
3883ebfedea0SLionel Sambuc   return -1;
3884ebfedea0SLionel Sambuc 
3885ebfedea0SLionel Sambuc } /* end s_mp_ispow2d() */
3886ebfedea0SLionel Sambuc 
3887ebfedea0SLionel Sambuc /* }}} */
3888ebfedea0SLionel Sambuc 
3889ebfedea0SLionel Sambuc /* }}} */
3890ebfedea0SLionel Sambuc 
3891ebfedea0SLionel Sambuc /* {{{ Primitive I/O helpers */
3892ebfedea0SLionel Sambuc 
3893ebfedea0SLionel Sambuc /* {{{ s_mp_tovalue(ch, r) */
3894ebfedea0SLionel Sambuc 
3895ebfedea0SLionel Sambuc /*
3896ebfedea0SLionel Sambuc   Convert the given character to its digit value, in the given radix.
3897ebfedea0SLionel Sambuc   If the given character is not understood in the given radix, -1 is
3898ebfedea0SLionel Sambuc   returned.  Otherwise the digit's numeric value is returned.
3899ebfedea0SLionel Sambuc 
3900ebfedea0SLionel Sambuc   The results will be odd if you use a radix < 2 or > 62, you are
3901ebfedea0SLionel Sambuc   expected to know what you're up to.
3902ebfedea0SLionel Sambuc  */
s_mp_tovalue(char ch,int r)3903ebfedea0SLionel Sambuc int      s_mp_tovalue(char ch, int r)
3904ebfedea0SLionel Sambuc {
3905ebfedea0SLionel Sambuc   int    val, xch;
3906ebfedea0SLionel Sambuc 
3907ebfedea0SLionel Sambuc   if(r > 36)
3908ebfedea0SLionel Sambuc     xch = ch;
3909ebfedea0SLionel Sambuc   else
3910ebfedea0SLionel Sambuc     xch = toupper(ch);
3911ebfedea0SLionel Sambuc 
3912ebfedea0SLionel Sambuc   if(isdigit(xch))
3913ebfedea0SLionel Sambuc     val = xch - '0';
3914ebfedea0SLionel Sambuc   else if(isupper(xch))
3915ebfedea0SLionel Sambuc     val = xch - 'A' + 10;
3916ebfedea0SLionel Sambuc   else if(islower(xch))
3917ebfedea0SLionel Sambuc     val = xch - 'a' + 36;
3918ebfedea0SLionel Sambuc   else if(xch == '+')
3919ebfedea0SLionel Sambuc     val = 62;
3920ebfedea0SLionel Sambuc   else if(xch == '/')
3921ebfedea0SLionel Sambuc     val = 63;
3922ebfedea0SLionel Sambuc   else
3923ebfedea0SLionel Sambuc     return -1;
3924ebfedea0SLionel Sambuc 
3925ebfedea0SLionel Sambuc   if(val < 0 || val >= r)
3926ebfedea0SLionel Sambuc     return -1;
3927ebfedea0SLionel Sambuc 
3928ebfedea0SLionel Sambuc   return val;
3929ebfedea0SLionel Sambuc 
3930ebfedea0SLionel Sambuc } /* end s_mp_tovalue() */
3931ebfedea0SLionel Sambuc 
3932ebfedea0SLionel Sambuc /* }}} */
3933ebfedea0SLionel Sambuc 
3934ebfedea0SLionel Sambuc /* {{{ s_mp_todigit(val, r, low) */
3935ebfedea0SLionel Sambuc 
3936ebfedea0SLionel Sambuc /*
3937ebfedea0SLionel Sambuc   Convert val to a radix-r digit, if possible.  If val is out of range
3938ebfedea0SLionel Sambuc   for r, returns zero.  Otherwise, returns an ASCII character denoting
3939ebfedea0SLionel Sambuc   the value in the given radix.
3940ebfedea0SLionel Sambuc 
3941ebfedea0SLionel Sambuc   The results may be odd if you use a radix < 2 or > 64, you are
3942ebfedea0SLionel Sambuc   expected to know what you're doing.
3943ebfedea0SLionel Sambuc  */
3944ebfedea0SLionel Sambuc 
s_mp_todigit(int val,int r,int low)3945ebfedea0SLionel Sambuc char     s_mp_todigit(int val, int r, int low)
3946ebfedea0SLionel Sambuc {
3947ebfedea0SLionel Sambuc   char   ch;
3948ebfedea0SLionel Sambuc 
3949ebfedea0SLionel Sambuc   if(val < 0 || val >= r)
3950ebfedea0SLionel Sambuc     return 0;
3951ebfedea0SLionel Sambuc 
3952ebfedea0SLionel Sambuc   ch = s_dmap_1[val];
3953ebfedea0SLionel Sambuc 
3954ebfedea0SLionel Sambuc   if(r <= 36 && low)
3955ebfedea0SLionel Sambuc     ch = tolower(ch);
3956ebfedea0SLionel Sambuc 
3957ebfedea0SLionel Sambuc   return ch;
3958ebfedea0SLionel Sambuc 
3959ebfedea0SLionel Sambuc } /* end s_mp_todigit() */
3960ebfedea0SLionel Sambuc 
3961ebfedea0SLionel Sambuc /* }}} */
3962ebfedea0SLionel Sambuc 
3963ebfedea0SLionel Sambuc /* {{{ s_mp_outlen(bits, radix) */
3964ebfedea0SLionel Sambuc 
3965ebfedea0SLionel Sambuc /*
3966ebfedea0SLionel Sambuc    Return an estimate for how long a string is needed to hold a radix
3967ebfedea0SLionel Sambuc    r representation of a number with 'bits' significant bits.
3968ebfedea0SLionel Sambuc 
3969ebfedea0SLionel Sambuc    Does not include space for a sign or a NUL terminator.
3970ebfedea0SLionel Sambuc  */
s_mp_outlen(int bits,int r)3971ebfedea0SLionel Sambuc int      s_mp_outlen(int bits, int r)
3972ebfedea0SLionel Sambuc {
3973ebfedea0SLionel Sambuc   return (int)((double)bits * LOG_V_2(r));
3974ebfedea0SLionel Sambuc 
3975ebfedea0SLionel Sambuc } /* end s_mp_outlen() */
3976ebfedea0SLionel Sambuc 
3977ebfedea0SLionel Sambuc /* }}} */
3978ebfedea0SLionel Sambuc 
3979ebfedea0SLionel Sambuc /* }}} */
3980ebfedea0SLionel Sambuc 
3981ebfedea0SLionel Sambuc /*------------------------------------------------------------------------*/
3982ebfedea0SLionel Sambuc /* HERE THERE BE DRAGONS                                                  */
3983ebfedea0SLionel Sambuc /* crc==4242132123, version==2, Sat Feb 02 06:43:52 2002 */
3984ebfedea0SLionel Sambuc 
3985ebfedea0SLionel Sambuc /* Source: /cvs/libtom/libtommath/mtest/mpi.c,v  */
3986ebfedea0SLionel Sambuc /* Revision: 1.2  */
3987ebfedea0SLionel Sambuc /* Date: 2005/05/05 14:38:47  */
3988