comparison mtest/mpi.c @ 1:22d5cf7d4b1a libtommath

Renaming branch
author Matt Johnston <matt@ucc.asn.au>
date Mon, 31 May 2004 18:23:46 +0000
parents
children a96ff234ff19
comparison
equal deleted inserted replaced
-1:000000000000 1:22d5cf7d4b1a
1 /*
2 mpi.c
3
4 by Michael J. Fromberger <[email protected]>
5 Copyright (C) 1998 Michael J. Fromberger, All Rights Reserved
6
7 Arbitrary precision integer arithmetic library
8
9 $Id: mpi.c,v 1.1.1.1 2003/05/19 04:01:19 matt Exp $
10 */
11
12 #include "mpi.h"
13 #include <stdlib.h>
14 #include <string.h>
15 #include <ctype.h>
16
17 #if MP_DEBUG
18 #include <stdio.h>
19
20 #define DIAG(T,V) {fprintf(stderr,T);mp_print(V,stderr);fputc('\n',stderr);}
21 #else
22 #define DIAG(T,V)
23 #endif
24
25 /*
26 If MP_LOGTAB is not defined, use the math library to compute the
27 logarithms on the fly. Otherwise, use the static table below.
28 Pick which works best for your system.
29 */
30 #if MP_LOGTAB
31
32 /* {{{ s_logv_2[] - log table for 2 in various bases */
33
34 /*
35 A table of the logs of 2 for various bases (the 0 and 1 entries of
36 this table are meaningless and should not be referenced).
37
38 This table is used to compute output lengths for the mp_toradix()
39 function. Since a number n in radix r takes up about log_r(n)
40 digits, we estimate the output size by taking the least integer
41 greater than log_r(n), where:
42
43 log_r(n) = log_2(n) * log_r(2)
44
45 This table, therefore, is a table of log_r(2) for 2 <= r <= 36,
46 which are the output bases supported.
47 */
48
49 #include "logtab.h"
50
51 /* }}} */
52 #define LOG_V_2(R) s_logv_2[(R)]
53
54 #else
55
56 #include <math.h>
57 #define LOG_V_2(R) (log(2.0)/log(R))
58
59 #endif
60
61 /* Default precision for newly created mp_int's */
62 static unsigned int s_mp_defprec = MP_DEFPREC;
63
64 /* {{{ Digit arithmetic macros */
65
66 /*
67 When adding and multiplying digits, the results can be larger than
68 can be contained in an mp_digit. Thus, an mp_word is used. These
69 macros mask off the upper and lower digits of the mp_word (the
70 mp_word may be more than 2 mp_digits wide, but we only concern
71 ourselves with the low-order 2 mp_digits)
72
73 If your mp_word DOES have more than 2 mp_digits, you need to
74 uncomment the first line, and comment out the second.
75 */
76
77 /* #define CARRYOUT(W) (((W)>>DIGIT_BIT)&MP_DIGIT_MAX) */
78 #define CARRYOUT(W) ((W)>>DIGIT_BIT)
79 #define ACCUM(W) ((W)&MP_DIGIT_MAX)
80
81 /* }}} */
82
83 /* {{{ Comparison constants */
84
85 #define MP_LT -1
86 #define MP_EQ 0
87 #define MP_GT 1
88
89 /* }}} */
90
91 /* {{{ Constant strings */
92
93 /* Constant strings returned by mp_strerror() */
94 static const char *mp_err_string[] = {
95 "unknown result code", /* say what? */
96 "boolean true", /* MP_OKAY, MP_YES */
97 "boolean false", /* MP_NO */
98 "out of memory", /* MP_MEM */
99 "argument out of range", /* MP_RANGE */
100 "invalid input parameter", /* MP_BADARG */
101 "result is undefined" /* MP_UNDEF */
102 };
103
104 /* Value to digit maps for radix conversion */
105
106 /* s_dmap_1 - standard digits and letters */
107 static const char *s_dmap_1 =
108 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
109
110 #if 0
111 /* s_dmap_2 - base64 ordering for digits */
112 static const char *s_dmap_2 =
113 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
114 #endif
115
116 /* }}} */
117
118 /* {{{ Static function declarations */
119
120 /*
121 If MP_MACRO is false, these will be defined as actual functions;
122 otherwise, suitable macro definitions will be used. This works
123 around the fact that ANSI C89 doesn't support an 'inline' keyword
124 (although I hear C9x will ... about bloody time). At present, the
125 macro definitions are identical to the function bodies, but they'll
126 expand in place, instead of generating a function call.
127
128 I chose these particular functions to be made into macros because
129 some profiling showed they are called a lot on a typical workload,
130 and yet they are primarily housekeeping.
131 */
132 #if MP_MACRO == 0
133 void s_mp_setz(mp_digit *dp, mp_size count); /* zero digits */
134 void s_mp_copy(mp_digit *sp, mp_digit *dp, mp_size count); /* copy */
135 void *s_mp_alloc(size_t nb, size_t ni); /* general allocator */
136 void s_mp_free(void *ptr); /* general free function */
137 #else
138
139 /* Even if these are defined as macros, we need to respect the settings
140 of the MP_MEMSET and MP_MEMCPY configuration options...
141 */
142 #if MP_MEMSET == 0
143 #define s_mp_setz(dp, count) \
144 {int ix;for(ix=0;ix<(count);ix++)(dp)[ix]=0;}
145 #else
146 #define s_mp_setz(dp, count) memset(dp, 0, (count) * sizeof(mp_digit))
147 #endif /* MP_MEMSET */
148
149 #if MP_MEMCPY == 0
150 #define s_mp_copy(sp, dp, count) \
151 {int ix;for(ix=0;ix<(count);ix++)(dp)[ix]=(sp)[ix];}
152 #else
153 #define s_mp_copy(sp, dp, count) memcpy(dp, sp, (count) * sizeof(mp_digit))
154 #endif /* MP_MEMCPY */
155
156 #define s_mp_alloc(nb, ni) calloc(nb, ni)
157 #define s_mp_free(ptr) {if(ptr) free(ptr);}
158 #endif /* MP_MACRO */
159
160 mp_err s_mp_grow(mp_int *mp, mp_size min); /* increase allocated size */
161 mp_err s_mp_pad(mp_int *mp, mp_size min); /* left pad with zeroes */
162
163 void s_mp_clamp(mp_int *mp); /* clip leading zeroes */
164
165 void s_mp_exch(mp_int *a, mp_int *b); /* swap a and b in place */
166
167 mp_err s_mp_lshd(mp_int *mp, mp_size p); /* left-shift by p digits */
168 void s_mp_rshd(mp_int *mp, mp_size p); /* right-shift by p digits */
169 void s_mp_div_2d(mp_int *mp, mp_digit d); /* divide by 2^d in place */
170 void s_mp_mod_2d(mp_int *mp, mp_digit d); /* modulo 2^d in place */