Initial import.
[u/mdw/catacomb] / mptypes.h
1 /* -*-c-*-
2 *
3 * $Id: mptypes.h,v 1.1 1999/09/03 08:41:12 mdw Exp $
4 *
5 * Types for multiprecision arithmetic
6 *
7 * (c) 1999 Straylight/Edgeware
8 */
9
10 /*----- Licensing notice --------------------------------------------------*
11 *
12 * This file is part of Catacomb.
13 *
14 * Catacomb is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU Library General Public License as
16 * published by the Free Software Foundation; either version 2 of the
17 * License, or (at your option) any later version.
18 *
19 * Catacomb is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Library General Public License for more details.
23 *
24 * You should have received a copy of the GNU Library General Public
25 * License along with Catacomb; if not, write to the Free
26 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
27 * MA 02111-1307, USA.
28 */
29
30 /*----- Revision history --------------------------------------------------*
31 *
32 * $Log: mptypes.h,v $
33 * Revision 1.1 1999/09/03 08:41:12 mdw
34 * Initial import.
35 *
36 */
37
38 #ifndef MPTYPES_H
39 #define MPTYPES_H
40
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44
45 /*----- Header files ------------------------------------------------------*/
46
47 #include <limits.h>
48 #include <stddef.h>
49
50 #include <mLib/bits.h>
51
52 /*----- Important types ---------------------------------------------------*/
53
54 /* --- Choose word and doubleword types --- *
55 *
56 * The types I need, and their properties, are as follows:
57 *
58 * * @mpw@ is the radix in which all the arithmetic is actually performed.
59 * It must be an unsigned type that is efficient on the host's hardware.
60 * @MPW_MAX@ is the largest value of type @mpw@ I'll use. (Although
61 * there may be bigger values available, I'll not use them.) @MPW_BITS@
62 * is the number of bits required to represent @MPW_MAX@.
63 *
64 * * @mpd@ must be twice as large as @mpw@: I must be able to multiply any
65 * two @mpw@ values and end up with an @mpd@ as the result. @MPD_MAX@ is
66 * the largest value of type @mpd@ I'll use, and @MPD_BITS@ is the number
67 * of bits required to represent it.
68 *
69 * The algorithm used to choose these types is:
70 *
71 * * Try to use @unsigned int@ as @mpw@ and @unsigned long@ as @mpd@. If
72 * @unsigned long@ looks to small to do this, try to use @unsigned long
73 * long@, if it exists.
74 *
75 * * If that's not good enough, then fall back to @unsigned short@ as @mpw@
76 * and choose one of @unsigned int@, @unsigned long@ or @unsigned long
77 * long@ (in decreasing order of preference) as @mpd@.
78 *
79 * * If that doesn't work either, choose @unsigned int@ as both, and use
80 * half its width only as @mpw@.
81 */
82
83 #ifndef MP_TEST
84
85 /* --- Hack for GCC until it catches up with C9X --- *
86 *
87 * GCC uses bogus names for the @long long@ minimum and maximum values in its
88 * <limits.h> file. This little hack makes the proper portable C9X names
89 * work as well.
90 */
91
92 #if defined(ULONG_LONG_MAX) && !defined(ULLONG_MAX)
93 # define LLONG_MIN LONG_LONG_MIN
94 # define LLONG_MAX LONG_LONG_MAX
95 # define ULLONG_MAX ULONG_LONG_MAX
96 #endif
97
98 /* --- Decide on the actual types to use --- *
99 *
100 * The division trick here makes sure that one type is twice another without
101 * the risk of overflowing the arithmetic provided by the preprocessor.
102 */
103
104 #if ULONG_MAX / UINT_MAX >= UINT_MAX
105 typedef unsigned int mpw;
106 typedef unsigned long mpd;
107 # define MPW_MAX UINT_MAX
108 #elif ULLONG_MAX / UINT_MAX >= UINT_MAX
109 typedef unsigned int mpw;
110 typedef unsigned long long mpd;
111 # define MPW_MAX UINT_MAX
112 #elif UINT_MAX / USHRT_MAX >= USHRT_MAX
113 typedef unsigned short mpw;
114 typedef unsigned int mpd;
115 # define MPW_MAX USHRT_MAX
116 #elif ULONG_MAX / USHRT_MAX >= USHRT_MAX
117 typedef unsigned short mpw;
118 typedef unsigned long mpd;
119 # define MPW_MAX USHRT_MAX
120 #elif ULLONG_MAX / USHRT_MAX >= USHRT_MAX
121 typedef unsigned short mpw;
122 typedef unsigned long long mpd;
123 # define MPW_MAX USHRT_MAX
124 #else
125 typedef unsigned int mpw;
126 typedef unsigned int mpd;
127 # define MPD_MAX UINT_MAX
128 #endif
129
130 /* --- Fix a value for @MPD_MAX@ --- *
131 *
132 * This will then be the target for finding the bit widths and things.
133 */
134
135 #ifdef MPW_MAX
136 # define MPD_MAX ((MPW_MAX + 1) * MPW_MAX + MW_WMAX)
137 #endif
138
139 /* --- Find the width of @MPD_MAX@ in bits --- *
140 *
141 * It must be at least 16 bits wide, because the smallest type I bother to
142 * try is @unsigned short@. I only bother testing for up to 64 bits, and in
143 * power-of-two chunks, because I don't care about efficiency on more bizarre
144 * systems.
145 */
146
147 #if MPD_MAX <= 0xfffffffff
148 # if MPD_MAX == 0xffffffff
149 # define MPD_BITS 32
150 # elif MPD_MAX >= 0x0fffffff
151 # define MPD_BITS 28
152 # elif MPD_MAX >= 0x00ffffff
153 # define MPD_BITS 24
154 # elif MPD_MAX >= 0x000fffff
155 # define MPD_BITS 20
156 # elif MPD_MAX >= 0x0000ffff
157 # define MPD_BITS 16
158 # else
159 # error "Abject failure deciding on type `mpw'"
160 #else
161 # if MPD_MAX / 0xffffffff < 0xffffffff
162 # define MPD_BITS 32
163 # else
164 # define MPD_BITS 64 /* Slightly dodgy */
165 #endif
166
167 /* --- Now sort out the other magical values --- */
168
169 #undef MPD_MAX
170 #undef MPW_MAX
171
172 #define MPW_BITS (MPD_BITS / 2)
173 #define MPD_MAX (((1 << (MPD_BITS - 1)) - 1) * 2 + 1)
174 #define MPW_MAX ((1 << MPW_BITS) - 1)
175
176 #endif
177
178 /*----- Macros for coercion and masking -----------------------------------*/
179
180 /* --- @MPW@ --- *
181 *
182 * Arguments: @x@ = an unsigned value
183 *
184 * Use: Expands to the value of @x@ masked and typecast to a
185 * multiprecision integer word.
186 */
187
188 #define MPW(x) ((mpw)((x) & MPW_MAX))
189
190 /* --- @MPWS@ --- *
191 *
192 * Arguments: @n@ = number of words
193 *
194 * Use: Expands to the number of bytes occupied by a given number of
195 * words.
196 */
197
198 #define MPWS(n) ((n) * sizeof(mpw))
199
200 /*----- That's all, folks -------------------------------------------------*/
201
202 #ifdef __cplusplus
203 }
204 #endif
205
206 #endif