Commit | Line | Data |
---|---|---|
70b904c5 | 1 | /* -*-c-*- |
2 | * | |
70b904c5 | 3 | * Conversion between MPs and standard C integers |
4 | * | |
5 | * (c) 1999 Straylight/Edgeware | |
6 | */ | |
7 | ||
45c0fd36 | 8 | /*----- Licensing notice --------------------------------------------------* |
70b904c5 | 9 | * |
10 | * This file is part of Catacomb. | |
11 | * | |
12 | * Catacomb is free software; you can redistribute it and/or modify | |
13 | * it under the terms of the GNU Library General Public License as | |
14 | * published by the Free Software Foundation; either version 2 of the | |
15 | * License, or (at your option) any later version. | |
45c0fd36 | 16 | * |
70b904c5 | 17 | * Catacomb is distributed in the hope that it will be useful, |
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 | * GNU Library General Public License for more details. | |
45c0fd36 | 21 | * |
70b904c5 | 22 | * You should have received a copy of the GNU Library General Public |
23 | * License along with Catacomb; if not, write to the Free | |
24 | * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, | |
25 | * MA 02111-1307, USA. | |
26 | */ | |
27 | ||
92c2a290 | 28 | #ifndef CATACOMB_MPINT_H |
29 | #define CATACOMB_MPINT_H | |
70b904c5 | 30 | |
31 | #ifdef __cplusplus | |
32 | extern "C" { | |
33 | #endif | |
34 | ||
35 | /*----- Header files ------------------------------------------------------*/ | |
36 | ||
37 | #include <limits.h> | |
38 | ||
92c2a290 | 39 | #ifndef CATACOMB_MP_H |
70b904c5 | 40 | # include "mp.h" |
41 | #endif | |
42 | ||
43 | /*----- Generic translation macros ----------------------------------------*/ | |
44 | ||
45 | /* --- @MP_FROMINT@ --- * | |
46 | * | |
47 | * Arguments: @d@ = destination multiprecision integer | |
48 | * @type@ = type of integer which @i@ is | |
49 | * @i@ = a standard C integer | |
50 | * | |
51 | * Use: Stores the value of @i@ in @d@. This macro is actually | |
52 | * rather subtle in places. Be careful what you change. | |
53 | */ | |
54 | ||
55 | #define MP_FROMINT(d, type, i) do { \ | |
56 | type _i = (i); \ | |
57 | size_t _o = 0; \ | |
58 | mp *_d = (d); \ | |
59 | size_t _sz = 4; \ | |
60 | \ | |
d34decd2 | 61 | MP_DEST(_d, _sz, 0); \ |
70b904c5 | 62 | _d->f &= ~(MP_NEG | MP_UNDEF); \ |
63 | \ | |
3485fc41 MW |
64 | if (_i >= 0) { \ |
65 | while (_i) { \ | |
66 | if (_o == _sz) { \ | |
67 | _sz <<= 1; \ | |
68 | MP_ENSURE(_d, _sz); \ | |
69 | } \ | |
70 | _d->v[_o++] = MPW(_i); \ | |
7eaaecf5 | 71 | if (_i <= MPW_MAX) \ |
3485fc41 MW |
72 | break; \ |
73 | else \ | |
74 | _i /= (type)MPW_MAX + 1; \ | |
75 | } \ | |
76 | } else { \ | |
70b904c5 | 77 | _d->f |= MP_NEG; \ |
3485fc41 MW |
78 | while (_i) { \ |
79 | if (_o == _sz) { \ | |
80 | _sz <<= 1; \ | |
81 | MP_ENSURE(_d, _sz); \ | |
82 | } \ | |
83 | _d->v[_o++] = MPW(-_i); \ | |
7eaaecf5 | 84 | if (_i >= -MPW_MAX) \ |
3485fc41 MW |
85 | break; \ |
86 | else \ | |
87 | _i /= (type)MPW_MAX + 1; \ | |
70b904c5 | 88 | } \ |
70b904c5 | 89 | } \ |
3485fc41 | 90 | \ |
70b904c5 | 91 | _d->vl = _d->v + _o; \ |
92 | (d) = _d; \ | |
93 | } while (0) | |
94 | ||
95 | /* --- @MP_TOINT@ --- * | |
96 | * | |
97 | * Arguments: @m@ = a multiprecision integer | |
98 | * @type@ = the type of @i@ | |
99 | * @max@ = the largest value @i@ can represent | |
100 | * @i@ = an integer variable | |
101 | * | |
102 | * Use: Stores the value of a multiprecision integer in a standard C | |
103 | * integer. If the value won't fit, the behaviour is determined | |
104 | * by the type of @i@: if @i@ is unsigned, the value of the | |
105 | * multiprecision integer modulo @max + 1@ is stored; if @i@ is | |
106 | * signed, the behaviour is undefined. | |
107 | * | |
108 | * If you don't want to be bitten by these sorts of things, keep | |
109 | * copies of @INT_MAX@ or whatever is appropriate in | |
110 | * multiprecision form and compare before conversion. | |
111 | */ | |
112 | ||
113 | #define MP_TOINT(m, type, max, i) do { \ | |
114 | type _i = 0; \ | |
115 | type _max = (max); \ | |
116 | unsigned _s = 0; \ | |
117 | const mp *_m = (m); \ | |
118 | const mpw *_v = _m->v, *_vl = _m->vl; \ | |
119 | \ | |
120 | /* --- Do all the arithmetic in negative numbers --- */ \ | |
121 | \ | |
122 | while (_v < _vl && _max > 0) { \ | |
123 | _i -= *_v << _s; \ | |
124 | _s += MPW_BITS; \ | |
125 | _v++; \ | |
126 | _max /= (mpd)MPW_MAX + 1; \ | |
127 | } \ | |
a69a3efd | 128 | if (!MP_NEGP(_m)) \ |
70b904c5 | 129 | _i = -_i; \ |
130 | (i) = _i; \ | |
131 | } while (0) | |
132 | ||
133 | /*----- Functions provided ------------------------------------------------*/ | |
134 | ||
135 | /* --- @mp_fromINT@ --- * | |
136 | * | |
137 | * Arguments: @mp *d@ = pointer to destination multiprecision integer | |
138 | * @INT i@ = standard C integer to convert | |
139 | * | |
140 | * Returns: The resulting multiprecision integer. | |
141 | * | |
142 | * Use: Converts a standard C integer to a multiprecision integer. | |
143 | */ | |
144 | ||
145 | #define mp_fromINT(name, type) \ | |
146 | extern mp *mp_from##name(mp */*d*/, type /*i*/) | |
147 | ||
148 | mp_fromINT(short, short); | |
149 | mp_fromINT(ushort, unsigned short); | |
150 | mp_fromINT(int, int); | |
151 | mp_fromINT(uint, unsigned); | |
92c2a290 | 152 | mp_fromINT(uint32, uint32); |
70b904c5 | 153 | mp_fromINT(long, long); |
154 | mp_fromINT(ulong, unsigned long); | |
155 | ||
156 | #undef mp_fromINT | |
157 | ||
158 | /* --- @mp_toINT@ --- * | |
159 | * | |
160 | * Arguments: @const mp *m@ = pointer to a multiprecision integer | |
161 | * | |
162 | * Returns: The value of the integer @m@ as a C integer. | |
163 | * | |
164 | * Use: Converts a multiprecision integer to a standard C integer. | |
165 | * If the value of the multiprecision integer cannot be | |
166 | * represented in the return type, and the return type is | |
167 | * unsigned, it is reduced modulo @TYPE_MAX + 1@; if the return | |
168 | * type is signed, the behaviour is undefined. | |
169 | */ | |
170 | ||
171 | #define mp_toINT(name, type) \ | |
cfcaafa7 | 172 | extern type mp_to##name(const mp */*m*/) |
70b904c5 | 173 | |
174 | mp_toINT(short, short); | |
175 | mp_toINT(ushort, unsigned short); | |
176 | mp_toINT(int, int); | |
177 | mp_toINT(uint, unsigned); | |
92c2a290 | 178 | mp_toINT(uint32, uint32); |
70b904c5 | 179 | mp_toINT(long, long); |
180 | mp_toINT(ulong, unsigned long); | |
181 | ||
182 | #undef mp_toINT | |
183 | ||
184 | /*----- That's all, folks -------------------------------------------------*/ | |
185 | ||
186 | #ifdef __cplusplus | |
187 | } | |
188 | #endif | |
189 | ||
190 | #endif |