root/src/gauche/arith.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


   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 */

/* [<][>][^][v][top][bottom][index][help] */