chiark / gitweb /
Rearrange the file tree.
[catacomb] / math / mpint.h
1 /* -*-c-*-
2  *
3  * Conversion between MPs and standard C integers
4  *
5  * (c) 1999 Straylight/Edgeware
6  */
7
8 /*----- Licensing notice --------------------------------------------------*
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.
16  *
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.
21  *
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
28 #ifndef CATACOMB_MPINT_H
29 #define CATACOMB_MPINT_H
30
31 #ifdef __cplusplus
32   extern "C" {
33 #endif
34
35 /*----- Header files ------------------------------------------------------*/
36
37 #include <limits.h>
38
39 #ifndef CATACOMB_MP_H
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                                                                         \
61   MP_DEST(_d, _sz, 0);                                                  \
62   _d->f &= ~(MP_NEG | MP_UNDEF);                                        \
63                                                                         \
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);                                            \
71       if (_i <= MPW_MAX)                                                \
72         break;                                                          \
73       else                                                              \
74         _i /= (type)MPW_MAX + 1;                                        \
75     }                                                                   \
76   } else {                                                              \
77     _d->f |= MP_NEG;                                                    \
78     while (_i) {                                                        \
79       if (_o == _sz) {                                                  \
80         _sz <<= 1;                                                      \
81         MP_ENSURE(_d, _sz);                                             \
82       }                                                                 \
83       _d->v[_o++] = MPW(-_i);                                           \
84       if (_i >= -MPW_MAX)                                               \
85         break;                                                          \
86       else                                                              \
87         _i /= (type)MPW_MAX + 1;                                        \
88     }                                                                   \
89   }                                                                     \
90                                                                         \
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   }                                                                     \
128   if (!MP_NEGP(_m))                                                     \
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);
152 mp_fromINT(uint32, uint32);
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)                                            \
172   extern type mp_to##name(const mp */*m*/)
173
174 mp_toINT(short, short);
175 mp_toINT(ushort, unsigned short);
176 mp_toINT(int, int);
177 mp_toINT(uint, unsigned);
178 mp_toINT(uint32, uint32);
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