1 /* 2 * Integer arithmetic evaluation, header file. 3 * 4 * (c) Thomas Pornin 2002 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 4. The name of the authors may not be used to endorse or promote 15 * products derived from this software without specific prior written 16 * permission. 17 * 18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 24 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 25 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 27 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 28 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 */ 31 32 /* 33 * This arithmetic evaluator uses two files: this header file (arith.h) 34 * and the source file (arith.c). To use this code, the source file should 35 * be included from another .c file which defines some macros (see below). 36 * Then the functions defined in the arith.c file become available to the 37 * including source file. If those functions are defined with external 38 * linkage (that is, `ARITH_FUNCTION_HEADER' does not contain `static'), 39 * it is possible for other source files to use the arithmetic functions 40 * by including the arith.h header only. The source file which includes 41 * arith.c should *not* include arith.h. 42 * 43 * If the #include is for arith.h, the following macros should be 44 * defined: 45 * 46 * -- If the evaluator is supposed to use a native type: 47 * NATIVE_SIGNED the native signed integer type 48 * NATIVE_UNSIGNED the native unsigned integer type 49 * 50 * -- If the evaluator is supposed to use an emulated type: 51 * SIMUL_ARITH_SUBTYPE the native unsigned type used for the simulation 52 * SIMUL_SUBTYPE_BITS the native unsigned type size 53 * SIMUL_NUMBITS the emulated type size 54 * 55 * -- For both cases: 56 * ARITH_TYPENAME the central arithmetic type name 57 * ARITH_FUNCTION_HEADER the qualifiers to add to function definitions 58 * 59 * The presence (respectively absence) of the NATIVE_SIGNED macro triggers 60 * the use of the native type evaluator (respectively simulated type 61 * evaluator). 62 * 63 * If the #include is for arith.c, the macros for arith.h should be defined, 64 * and the following should be defined as well: 65 * 66 * -- If the evaluator is supposed to use a native type: 67 * NATIVE_UNSIGNED_BITS the native unsigned type size 68 * NATIVE_SIGNED_MIN the native signed minimum value 69 * NATIVE_SIGNED_MAX the native signed maximum value 70 * (the last two macros must evaluate to signed constant expressions) 71 * 72 * -- For both cases: 73 * ARITH_WARNING(type) code to perform on warning 74 * ARITH_ERROR(type) code to perform on error 75 * 76 * The macro ARITH_WARNING() and ARITH_ERROR() are invoked with a 77 * numerical argument which is one of the enumeration constants 78 * defined below (ARITH_EXCEP_*) that identifies the specific problem. 79 * 80 * If the #include is for arith.c, the macro ARITHMETIC_CHECKS may be 81 * defined. When this macro is defined, checks are performed so that all 82 * operation which would lead to undefined or implementation-defined 83 * behaviour are first reported through ARITH_WARNING(). Code is smaller 84 * and faster without these checks, of course. Regardless of the status 85 * of that macro, divisions by 0 and overflows on signed division are 86 * reported as errors through ARITH_ERROR(). 87 * 88 */ 89 90 #ifndef ARITH_H__ 91 #define ARITH_H__ 92 93 enum { 94 /* Warnings */ 95 ARITH_EXCEP_CONV_O, /* overflow on conversion */ 96 ARITH_EXCEP_NEG_O, /* overflow on unary minus */ 97 ARITH_EXCEP_NOT_T, /* trap representation on bitwise inversion */ 98 ARITH_EXCEP_PLUS_O, /* overflow on addition */ 99 ARITH_EXCEP_PLUS_U, /* underflow on addition */ 100 ARITH_EXCEP_MINUS_O, /* overflow on subtraction */ 101 ARITH_EXCEP_MINUS_U, /* underflow on subtraction */ 102 ARITH_EXCEP_AND_T, /* trap representation on bitwise and */ 103 ARITH_EXCEP_XOR_T, /* trap representation on bitwise xor */ 104 ARITH_EXCEP_OR_T, /* trap representation on bitwise or */ 105 ARITH_EXCEP_LSH_W, /* left shift by type width or more */ 106 ARITH_EXCEP_LSH_C, /* left shift by negative count */ 107 ARITH_EXCEP_LSH_O, /* overflow on left shift */ 108 ARITH_EXCEP_LSH_U, /* underflow on left shift */ 109 ARITH_EXCEP_RSH_W, /* right shift by type width or more */ 110 ARITH_EXCEP_RSH_C, /* right shift by negative count */ 111 ARITH_EXCEP_RSH_N, /* right shift of negative value */ 112 ARITH_EXCEP_STAR_O, /* overflow on multiplication */ 113 ARITH_EXCEP_STAR_U, /* underflow on multiplication */ 114 115 /* Errors */ 116 ARITH_EXCEP_SLASH_D, /* division by 0 */ 117 ARITH_EXCEP_SLASH_O, /* overflow on division */ 118 ARITH_EXCEP_PCT_D, /* division by 0 on modulus operator */ 119 ARITH_EXCEP_CONST_O /* constant too large */ 120 }; 121 122 #if !(defined pARI && defined aARI) 123 124 #define pARI void 125 #define pARI_ 126 #define aARI 127 #define aARI_ 128 129 #define useARI ((void) 0) 130 131 #else 132 133 #define pARI_ pARI, 134 #define aARI_ aARI, 135 136 #define useARI ((void) aARI) 137 138 #endif 139 140 #define arith_strc_(x, y) x ## y 141 #define arith_strc(x, y) arith_strc_(x, y) 142 143 #define arith_u arith_strc(u_, ARITH_TYPENAME) 144 #define arith_s arith_strc(s_, ARITH_TYPENAME) 145 #define arith_op_u(op) arith_strc(ARITH_TYPENAME, arith_strc(_u_, op)) 146 #define arith_op_s(op) arith_strc(ARITH_TYPENAME, arith_strc(_s_, op)) 147 148 #define ARITH_DECL_MONO_U_U(op) ARITH_FUNCTION_HEADER arith_u \ 149 arith_op_u(op)(pARI_ arith_u x) 150 #define ARITH_DECL_MONO_U_S(op) ARITH_FUNCTION_HEADER arith_s \ 151 arith_op_u(op)(pARI_ arith_u x) 152 #define ARITH_DECL_MONO_U_I(op) ARITH_FUNCTION_HEADER int \ 153 arith_op_u(op)(pARI_ arith_u x) 154 #define ARITH_DECL_MONO_U_L(op) ARITH_FUNCTION_HEADER unsigned long \ 155 arith_op_u(op)(pARI_ arith_u x) 156 #define ARITH_DECL_MONO_S_U(op) ARITH_FUNCTION_HEADER arith_u \ 157 arith_op_s(op)(pARI_ arith_s x) 158 #define ARITH_DECL_MONO_S_S(op) ARITH_FUNCTION_HEADER arith_s \ 159 arith_op_s(op)(pARI_ arith_s x) 160 #define ARITH_DECL_MONO_S_I(op) ARITH_FUNCTION_HEADER int \ 161 arith_op_s(op)(pARI_ arith_s x) 162 #define ARITH_DECL_MONO_S_L(op) ARITH_FUNCTION_HEADER long \ 163 arith_op_s(op)(pARI_ arith_s x) 164 #define ARITH_DECL_MONO_I_U(op) ARITH_FUNCTION_HEADER arith_u \ 165 arith_op_u(op)(pARI_ int x) 166 #define ARITH_DECL_MONO_L_U(op) ARITH_FUNCTION_HEADER arith_u \ 167 arith_op_u(op)(pARI_ unsigned long x) 168 #define ARITH_DECL_MONO_I_S(op) ARITH_FUNCTION_HEADER arith_s \ 169 arith_op_s(op)(pARI_ int x) 170 #define ARITH_DECL_MONO_L_S(op) ARITH_FUNCTION_HEADER arith_s \ 171 arith_op_s(op)(pARI_ long x) 172 #define ARITH_DECL_MONO_ST_US(op) ARITH_FUNCTION_HEADER char *arith_op_u(op) \ 173 (pARI_ char *c, arith_u *ru, arith_s *rs, int *sp) 174 175 #define ARITH_DECL_BI_UU_U(op) ARITH_FUNCTION_HEADER arith_u \ 176 arith_op_u(op)(pARI_ arith_u x, arith_u y) 177 #define ARITH_DECL_BI_UI_U(op) ARITH_FUNCTION_HEADER arith_u \ 178 arith_op_u(op)(pARI_ arith_u x, int y) 179 #define ARITH_DECL_BI_UU_I(op) ARITH_FUNCTION_HEADER int \ 180 arith_op_u(op)(pARI_ arith_u x, arith_u y) 181 #define ARITH_DECL_BI_SS_S(op) ARITH_FUNCTION_HEADER arith_s \ 182 arith_op_s(op)(pARI_ arith_s x, arith_s y) 183 #define ARITH_DECL_BI_SI_S(op) ARITH_FUNCTION_HEADER arith_s \ 184 arith_op_s(op)(pARI_ arith_s x, int y) 185 #define ARITH_DECL_BI_SS_I(op) ARITH_FUNCTION_HEADER int \ 186 arith_op_s(op)(pARI_ arith_s x, arith_s y) 187 188 #endif 189 190 #ifdef NATIVE_SIGNED 191 192 typedef NATIVE_SIGNED arith_s; 193 typedef NATIVE_UNSIGNED arith_u; 194 195 #else 196 197 #if SIMUL_NUMBITS > (2 * SIMUL_SUBTYPE_BITS) 198 #error Native subtype too small for arithmetic simulation. 199 #endif 200 201 #define SIMUL_MSW_WIDTH (SIMUL_NUMBITS / 2) 202 #define SIMUL_LSW_WIDTH ((SIMUL_NUMBITS + 1) / 2) 203 204 typedef struct { 205 SIMUL_ARITH_SUBTYPE msw, lsw; 206 } arith_u, arith_s; 207 208 #endif 209 210 /* functions with the unsigned type */ 211 212 ARITH_DECL_MONO_S_U(to_u); 213 ARITH_DECL_MONO_I_U(fromint); 214 ARITH_DECL_MONO_L_U(fromulong); 215 ARITH_DECL_MONO_U_I(toint); 216 ARITH_DECL_MONO_U_L(toulong); 217 218 ARITH_DECL_MONO_U_U(neg); 219 ARITH_DECL_MONO_U_U(not); 220 ARITH_DECL_MONO_U_I(lnot); 221 ARITH_DECL_MONO_U_I(lval); 222 223 ARITH_DECL_BI_UU_U(plus); 224 ARITH_DECL_BI_UU_U(minus); 225 ARITH_DECL_BI_UI_U(lsh); 226 ARITH_DECL_BI_UI_U(rsh); 227 ARITH_DECL_BI_UU_I(lt); 228 ARITH_DECL_BI_UU_I(leq); 229 ARITH_DECL_BI_UU_I(gt); 230 ARITH_DECL_BI_UU_I(geq); 231 ARITH_DECL_BI_UU_I(same); 232 ARITH_DECL_BI_UU_I(neq); 233 ARITH_DECL_BI_UU_U(and); 234 ARITH_DECL_BI_UU_U(xor); 235 ARITH_DECL_BI_UU_U(or); 236 ARITH_DECL_BI_UU_U(star); 237 ARITH_DECL_BI_UU_U(slash); 238 ARITH_DECL_BI_UU_U(pct); 239 240 /* functions with the signed type */ 241 242 ARITH_DECL_MONO_U_S(to_s); 243 ARITH_DECL_MONO_I_S(fromint); 244 ARITH_DECL_MONO_L_S(fromlong); 245 ARITH_DECL_MONO_S_I(toint); 246 ARITH_DECL_MONO_S_L(tolong); 247 248 ARITH_DECL_MONO_S_S(neg); 249 ARITH_DECL_MONO_S_S(not); 250 ARITH_DECL_MONO_S_I(lnot); 251 ARITH_DECL_MONO_S_I(lval); 252 253 ARITH_DECL_BI_SS_S(plus); 254 ARITH_DECL_BI_SS_S(minus); 255 ARITH_DECL_BI_SI_S(lsh); 256 ARITH_DECL_BI_SI_S(rsh); 257 ARITH_DECL_BI_SS_I(lt); 258 ARITH_DECL_BI_SS_I(leq); 259 ARITH_DECL_BI_SS_I(gt); 260 ARITH_DECL_BI_SS_I(geq); 261 ARITH_DECL_BI_SS_I(same); 262 ARITH_DECL_BI_SS_I(neq); 263 ARITH_DECL_BI_SS_S(and); 264 ARITH_DECL_BI_SS_S(xor); 265 ARITH_DECL_BI_SS_S(or); 266 ARITH_DECL_BI_SS_S(star); 267 ARITH_DECL_BI_SS_S(slash); 268 ARITH_DECL_BI_SS_S(pct); 269 270 /* conversions from string */ 271 ARITH_DECL_MONO_ST_US(octconst); 272 ARITH_DECL_MONO_ST_US(hexconst); 273 ARITH_DECL_MONO_ST_US(decconst); 274