/* [<][>][^][v][top][bottom][index][help] */
1 /*
2 * arith.h - macros for arithmetic
3 *
4 * Copyright (c) 2000-2003 Shiro Kawai, All rights reserved.
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 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the authors nor the names of its contributors
18 * may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * $Id: arith.h,v 1.6 2003/07/05 03:29:13 shirok Exp $
34 */
35
36 #ifndef GAUCHE_ARITH_H
37 #define GAUCHE_ARITH_H
38
39 /*
40 * This file defines some basic integer arithmetic operations.
41 * Most modern CPUs have efficient way to perform those operations.
42 *
43 * Not intended for global use; i.e. only Gauche internal code uses these.
44 * Only the features needed by Gauche's guts are implemented. You see
45 * the provided macros are not symmetric.
46 */
47
48 /* some useful constants */
49 #define SCM_ULONG_MAX ((u_long)(-1L)) /* to be configured */
50 #define WORD_BITS (SIZEOF_LONG * 8)
51 #define HALF_BITS (WORD_BITS/2)
52 #define HALF_WORD (1L<<HALF_BITS)
53
54 #ifndef LONG_MIN
55 #define LONG_MIN ((long)(1L<<(WORD_BITS-1)))
56 #endif
57 #ifndef LONG_MAX
58 #define LONG_MAX (-(LONG_MIN+1))
59 #endif
60
61 #define LOMASK (HALF_WORD-1)
62 #define HIMASK (~LOMASK)
63 #define LO(word) ((word) & LOMASK)
64 #define HI(word) (((word) >> HALF_BITS)&LOMASK)
65
66 /* Include processor-specific macros */
67 #if defined(SCM_TARGET_I386)
68 #include "arith_i386.h"
69 #endif
70
71 /*-----------------------------------------------------------------
72 * UADD(r, c, x, y) unsigned word add with carry
73 * u_long : r, c, x, y;
74 * r <- x + y + c mod wordsize
75 * c <- 1 if carry, 0 otherwise
76 */
77
78 #ifndef UADD
79 /* Portable version */
80 #define UADD(r, c, x, y) \
81 do { \
82 (r) = (x) + (y) + (c); \
83 (c) = ((r)<(x) || ((r)==(x) && ((y)>0||(c)>0)))? 1 : 0; \
84 } while (0)
85 #endif /*UADD*/
86
87 /*-----------------------------------------------------------------
88 * UADDOV(r, v, x, y) unsigned word add with overflow check
89 * u_long : r, v, x, y;
90 * if x + y overflows, v = 1
91 * else r <- x + y, v = 0
92 */
93
94 #ifndef UADDOV
95 /* Portable version */
96 #define UADDOV(r, v, x, y) \
97 do { \
98 (r) = (x) + (y); \
99 (v) = ((r) < (x))? 1 : 0; \
100 } while (0)
101 #endif /*UADDOV*/
102
103 /*-----------------------------------------------------------------
104 * SADDOV(r, v, x, y) signed word addition with overflow check
105 * long : r, v, x, y;
106 * if x + y overflows, v = 1 or -1 depending on the sign of the result
107 * else r <- x + y, v = 0
108 */
109
110 #ifndef SADDOV
111 /* Portable version */
112 #define SADDOV(r, v, x, y) \
113 do { \
114 (r) = (x) + (y); \
115 if ((x) >= 0) { \
116 if ((y) >= 0 && (r) < 0) (v) = 1; \
117 else (v) = 0; \
118 } else { \
119 if ((y) < 0 && (r) >= 0) (v) = -1; \
120 else (v) = 0; \
121 } \
122 } while (0)
123 #endif /*SADDOV*/
124
125 /*-----------------------------------------------------------------
126 * USUB(r, c, x, y) unsigned word subtract with borrow
127 * u_long : r, x, c, y;
128 * r <- x - y - c mod wordsize
129 * c <- 1 if borrow, 0 otherwise
130 */
131
132 #ifndef USUB
133 /* Portable version */
134 #define USUB(r, c, x, y) \
135 do { \
136 (r) = (x) - (y) - (c); \
137 (c) = ((r)>(x) || ((r)==(x) && ((y)>0||(c)>0)))? 1 : 0; \
138 } while (0)
139 #endif /*USUB*/
140
141 /*-----------------------------------------------------------------
142 * USUBOV(r, v, x, y) unsigned word subtract with overflow check
143 * u_long : r, v, x, y;
144 * if x - y overflows, v = 1
145 * else r <- x - y, v = 0
146 */
147
148 #ifndef USUBOV
149 /* Portable version */
150 #define USUBOV(r, v, x, y) \
151 do { \
152 (r) = (x) - (y); \
153 (v) = ((r) > (x))? 1 : 0; \
154 } while (0)
155 #endif /*USUBOV*/
156
157 /*-----------------------------------------------------------------
158 * SSUBOV(r, v, x, y) signed word subtract without borrow
159 * long : r, v, x, y;
160 * if x - y overflows, c = 1 or -1 depending on the sign of the result
161 * else r <- x - y, v = 0
162 */
163
164 #ifndef SSUBOV
165 /* Portable version */
166 #define SSUBOV(r, v, x, y) \
167 do { \
168 (r) = (x) - (y); \
169 if ((x) >= 0) { \
170 if ((y) < 0 && (r) <= 0) (v) = 1; \
171 else (v) = 0; \
172 } else { \
173 if ((y) >= 0 && (r) > 0) (v) = -1; \
174 else (v) = 0; \
175 } \
176 } while (0)
177 #endif /*SSUBOV*/
178
179 /*-----------------------------------------------------------------
180 * UMUL(hi, lo, x, y) unsigned word multiply
181 * u_long : hi, lo, x, y;
182 * [hi, lo] <- x * y
183 */
184
185 #ifndef UMUL
186 /* Portable version */
187 #define UMUL(hi, lo, x, y) \
188 do { \
189 u_long xl_ = LO(x), xh_ = HI(x), yl_ = LO(y), yh_ = HI(y); \
190 u_long t1_, t2_, t3_, t4_; \
191 lo = xl_ * yl_; \
192 t1_ = xl_ * yh_; \
193 t2_ = xh_ * yl_; \
194 hi = xh_ * yh_; \
195 t3_ = t1_ + t2_; \
196 if (t3_ < t1_) hi += HALF_WORD; \
197 hi += HI(t3_); \
198 t4_ = LO(t3_) << HALF_BITS; \
199 lo += t4_; \
200 if (lo < t4_) hi++; \
201 } while (0)
202 #endif /*UMUL*/
203
204 /*-----------------------------------------------------------------
205 * UMULOV(r, v, x, y) unsigned word multiply with overflow check
206 * u_long : r, x, y
207 * int : v
208 * if x * y overflows, v = 1
209 * else r <- x * y, v = 0
210 */
211
212 #ifndef UMULOV
213 #define UMULOV(r, v, x, y) \
214 do { \
215 if ((x)==0 || (y)==0) { (v) = (r) = 0; } \
216 else { \
217 u_long t5_; \
218 UMUL(t5_, r, x, y); \
219 (v) = (t5_)? 1 : 0; \
220 } \
221 } while (0)
222 #endif /*UMULOV*/
223
224 /*-----------------------------------------------------------------
225 * SMULOV(r, v, x, y) signed word multiply with overflow check
226 * long : r, x, y
227 * int : v
228 * if x * y overflows, v = 1 or -1 depending on the sign of the result
229 * else r <- x * y, v = 0
230 */
231
232 #ifndef SMULOV
233 #define SMULOV(r, v, x, y) \
234 do { \
235 u_long t6_; \
236 if ((x) >= 0) { \
237 if ((y) >= 0) { \
238 UMULOV(t6_, v, x, y); \
239 if ((v) || t6_ > LONG_MAX) (v) = 1; \
240 else (r) = t6_; \
241 } else { \
242 UMULOV(t6_, v, x, -y); \
243 if ((v) || t6_ > LONG_MAX+1UL) (v) = -1; \
244 else (r) = -t6_; \
245 } \
246 } else { \
247 if ((y) >= 0) { \
248 UMULOV(t6_, v, -x, y); \
249 if ((v) || t6_ > LONG_MAX+1UL) (v) = -1; \
250 else (r) = -t6_; \
251 } else { \
252 UMULOV(t6_, v, -x, -y); \
253 if ((v) || t6_ > LONG_MAX) (v) = 1; \
254 else (r) = t6_; \
255 } \
256 } \
257 } while (0)
258 #endif /*SMULOV*/
259
260
261 #endif /* GAUCHE_ARITH_H */