d03ab969 |
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 |