Home | History | Annotate | Download | only in nspr
      1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /*
      3  * The contents of this file are subject to the Mozilla Public
      4  * License Version 1.1 (the "License"); you may not use this file
      5  * except in compliance with the License. You may obtain a copy of
      6  * the License at http://www.mozilla.org/MPL/
      7  *
      8  * Software distributed under the License is distributed on an "AS
      9  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
     10  * implied. See the License for the specific language governing
     11  * rights and limitations under the License.
     12  *
     13  * The Original Code is the Netscape Portable Runtime (NSPR).
     14  *
     15  * The Initial Developer of the Original Code is Netscape
     16  * Communications Corporation.  Portions created by Netscape are
     17  * Copyright (C) 1998-2000 Netscape Communications Corporation.  All
     18  * Rights Reserved.
     19  *
     20  * Contributor(s):
     21  *
     22  * Alternatively, the contents of this file may be used under the
     23  * terms of the GNU General Public License Version 2 or later (the
     24  * "GPL"), in which case the provisions of the GPL are applicable
     25  * instead of those above.  If you wish to allow use of your
     26  * version of this file only under the terms of the GPL and not to
     27  * allow others to use your version of this file under the MPL,
     28  * indicate your decision by deleting the provisions above and
     29  * replace them with the notice and other provisions required by
     30  * the GPL.  If you do not delete the provisions above, a recipient
     31  * may use your version of this file under either the MPL or the
     32  * GPL.
     33  */
     34 
     35 /*
     36 ** File:                prlong.h
     37 ** Description: Portable access to 64 bit numerics
     38 **
     39 ** Long-long (64-bit signed integer type) support. Some C compilers
     40 ** don't support 64 bit integers yet, so we use these macros to
     41 ** support both machines that do and don't.
     42 **/
     43 #ifndef prlong_h___
     44 #define prlong_h___
     45 
     46 #include "prtypes.h"
     47 
     48 PR_BEGIN_EXTERN_C
     49 
     50 /***********************************************************************
     51 ** DEFINES:     LL_MaxInt
     52 **              LL_MinInt
     53 **              LL_Zero
     54 **              LL_MaxUint
     55 ** DESCRIPTION:
     56 **      Various interesting constants and static variable
     57 **      initializer
     58 ***********************************************************************/
     59 #if defined(HAVE_WATCOM_BUG_2)
     60 PRInt64 __pascal __loadds __export
     61     LL_MaxInt(void);
     62 PRInt64 __pascal __loadds __export
     63     LL_MinInt(void);
     64 PRInt64 __pascal __loadds __export
     65     LL_Zero(void);
     66 PRUint64 __pascal __loadds __export
     67     LL_MaxUint(void);
     68 #else
     69 NSPR_API(PRInt64) LL_MaxInt(void);
     70 NSPR_API(PRInt64) LL_MinInt(void);
     71 NSPR_API(PRInt64) LL_Zero(void);
     72 NSPR_API(PRUint64) LL_MaxUint(void);
     73 #endif
     74 
     75 #define LL_MAXINT   LL_MaxInt()
     76 #define LL_MININT   LL_MinInt()
     77 #define LL_ZERO     LL_Zero()
     78 #define LL_MAXUINT  LL_MaxUint()
     79 
     80 #if defined(HAVE_LONG_LONG)
     81 
     82 #if PR_BYTES_PER_LONG == 8
     83 #define LL_INIT(hi, lo)  ((hi ## L << 32) + lo ## L)
     84 #elif (defined(WIN32) || defined(WIN16)) && !defined(__GNUC__)
     85 #define LL_INIT(hi, lo)  ((hi ## i64 << 32) + lo ## i64)
     86 #else
     87 #define LL_INIT(hi, lo)  ((hi ## LL << 32) + lo ## LL)
     88 #endif
     89 
     90 /***********************************************************************
     91 ** MACROS:      LL_*
     92 ** DESCRIPTION:
     93 **      The following macros define portable access to the 64 bit
     94 **      math facilities.
     95 **
     96 ***********************************************************************/
     97 
     98 /***********************************************************************
     99 ** MACROS:      LL_<relational operators>
    100 **
    101 **  LL_IS_ZERO        Test for zero
    102 **  LL_EQ             Test for equality
    103 **  LL_NE             Test for inequality
    104 **  LL_GE_ZERO        Test for zero or positive
    105 **  LL_CMP            Compare two values
    106 ***********************************************************************/
    107 #define LL_IS_ZERO(a)       ((a) == 0)
    108 #define LL_EQ(a, b)         ((a) == (b))
    109 #define LL_NE(a, b)         ((a) != (b))
    110 #define LL_GE_ZERO(a)       ((a) >= 0)
    111 #define LL_CMP(a, op, b)    ((PRInt64)(a) op (PRInt64)(b))
    112 #define LL_UCMP(a, op, b)   ((PRUint64)(a) op (PRUint64)(b))
    113 
    114 /***********************************************************************
    115 ** MACROS:      LL_<logical operators>
    116 **
    117 **  LL_AND            Logical and
    118 **  LL_OR             Logical or
    119 **  LL_XOR            Logical exclusion
    120 **  LL_OR2            A disgusting deviation
    121 **  LL_NOT            Negation (one's complement)
    122 ***********************************************************************/
    123 #define LL_AND(r, a, b)        ((r) = (a) & (b))
    124 #define LL_OR(r, a, b)        ((r) = (a) | (b))
    125 #define LL_XOR(r, a, b)        ((r) = (a) ^ (b))
    126 #define LL_OR2(r, a)        ((r) = (r) | (a))
    127 #define LL_NOT(r, a)        ((r) = ~(a))
    128 
    129 /***********************************************************************
    130 ** MACROS:      LL_<mathematical operators>
    131 **
    132 **  LL_NEG            Negation (two's complement)
    133 **  LL_ADD            Summation (two's complement)
    134 **  LL_SUB            Difference (two's complement)
    135 ***********************************************************************/
    136 #define LL_NEG(r, a)        ((r) = -(a))
    137 #define LL_ADD(r, a, b)     ((r) = (a) + (b))
    138 #define LL_SUB(r, a, b)     ((r) = (a) - (b))
    139 
    140 /***********************************************************************
    141 ** MACROS:      LL_<mathematical operators>
    142 **
    143 **  LL_MUL            Product (two's complement)
    144 **  LL_DIV            Quotient (two's complement)
    145 **  LL_MOD            Modulus (two's complement)
    146 ***********************************************************************/
    147 #define LL_MUL(r, a, b)        ((r) = (a) * (b))
    148 #define LL_DIV(r, a, b)        ((r) = (a) / (b))
    149 #define LL_MOD(r, a, b)        ((r) = (a) % (b))
    150 
    151 /***********************************************************************
    152 ** MACROS:      LL_<shifting operators>
    153 **
    154 **  LL_SHL            Shift left [0..64] bits
    155 **  LL_SHR            Shift right [0..64] bits with sign extension
    156 **  LL_USHR           Unsigned shift right [0..64] bits
    157 **  LL_ISHL           Signed shift left [0..64] bits
    158 ***********************************************************************/
    159 #define LL_SHL(r, a, b)     ((r) = (PRInt64)(a) << (b))
    160 #define LL_SHR(r, a, b)     ((r) = (PRInt64)(a) >> (b))
    161 #define LL_USHR(r, a, b)    ((r) = (PRUint64)(a) >> (b))
    162 #define LL_ISHL(r, a, b)    ((r) = (PRInt64)(a) << (b))
    163 
    164 /***********************************************************************
    165 ** MACROS:      LL_<conversion operators>
    166 **
    167 **  LL_L2I            Convert to signed 32 bit
    168 **  LL_L2UI           Convert to unsigned 32 bit
    169 **  LL_L2F            Convert to floating point
    170 **  LL_L2D            Convert to floating point
    171 **  LL_I2L            Convert signed to 64 bit
    172 **  LL_UI2L           Convert unsigned to 64 bit
    173 **  LL_F2L            Convert float to 64 bit
    174 **  LL_D2L            Convert float to 64 bit
    175 ***********************************************************************/
    176 #define LL_L2I(i, l)        ((i) = (PRInt32)(l))
    177 #define LL_L2UI(ui, l)        ((ui) = (PRUint32)(l))
    178 #define LL_L2F(f, l)        ((f) = (PRFloat64)(l))
    179 #define LL_L2D(d, l)        ((d) = (PRFloat64)(l))
    180 
    181 #define LL_I2L(l, i)        ((l) = (PRInt64)(i))
    182 #define LL_UI2L(l, ui)        ((l) = (PRInt64)(ui))
    183 #define LL_F2L(l, f)        ((l) = (PRInt64)(f))
    184 #define LL_D2L(l, d)        ((l) = (PRInt64)(d))
    185 
    186 /***********************************************************************
    187 ** MACROS:      LL_UDIVMOD
    188 ** DESCRIPTION:
    189 **  Produce both a quotient and a remainder given an unsigned
    190 ** INPUTS:      PRUint64 a: The dividend of the operation
    191 **              PRUint64 b: The quotient of the operation
    192 ** OUTPUTS:     PRUint64 *qp: pointer to quotient
    193 **              PRUint64 *rp: pointer to remainder
    194 ***********************************************************************/
    195 #define LL_UDIVMOD(qp, rp, a, b) \
    196     (*(qp) = ((PRUint64)(a) / (b)), \
    197      *(rp) = ((PRUint64)(a) % (b)))
    198 
    199 #else  /* !HAVE_LONG_LONG */
    200 
    201 #ifdef IS_LITTLE_ENDIAN
    202 #define LL_INIT(hi, lo) {PR_INT32(lo), PR_INT32(hi)}
    203 #else
    204 #define LL_INIT(hi, lo) {PR_INT32(hi), PR_INT32(lo)}
    205 #endif
    206 
    207 #define LL_IS_ZERO(a)        (((a).hi == 0) && ((a).lo == 0))
    208 #define LL_EQ(a, b)        (((a).hi == (b).hi) && ((a).lo == (b).lo))
    209 #define LL_NE(a, b)        (((a).hi != (b).hi) || ((a).lo != (b).lo))
    210 #define LL_GE_ZERO(a)        (((a).hi >> 31) == 0)
    211 
    212 #define LL_CMP(a, op, b)    (((a).hi == (b).hi) ? ((a).lo op (b).lo) : \
    213                  ((PRInt32)(a).hi op (PRInt32)(b).hi))
    214 #define LL_UCMP(a, op, b)    (((a).hi == (b).hi) ? ((a).lo op (b).lo) : \
    215                  ((a).hi op (b).hi))
    216 
    217 #define LL_AND(r, a, b)        ((r).lo = (a).lo & (b).lo, \
    218                  (r).hi = (a).hi & (b).hi)
    219 #define LL_OR(r, a, b)        ((r).lo = (a).lo | (b).lo, \
    220                  (r).hi = (a).hi | (b).hi)
    221 #define LL_XOR(r, a, b)        ((r).lo = (a).lo ^ (b).lo, \
    222                  (r).hi = (a).hi ^ (b).hi)
    223 #define LL_OR2(r, a)        ((r).lo = (r).lo | (a).lo, \
    224                  (r).hi = (r).hi | (a).hi)
    225 #define LL_NOT(r, a)        ((r).lo = ~(a).lo, \
    226                  (r).hi = ~(a).hi)
    227 
    228 #define LL_NEG(r, a)        ((r).lo = -(PRInt32)(a).lo, \
    229                  (r).hi = -(PRInt32)(a).hi - ((r).lo != 0))
    230 #define LL_ADD(r, a, b) { \
    231     PRInt64 _a, _b; \
    232     _a = a; _b = b; \
    233     (r).lo = _a.lo + _b.lo; \
    234     (r).hi = _a.hi + _b.hi + ((r).lo < _b.lo); \
    235 }
    236 
    237 #define LL_SUB(r, a, b) { \
    238     PRInt64 _a, _b; \
    239     _a = a; _b = b; \
    240     (r).lo = _a.lo - _b.lo; \
    241     (r).hi = _a.hi - _b.hi - (_a.lo < _b.lo); \
    242 }
    243 
    244 #define LL_MUL(r, a, b) { \
    245     PRInt64 _a, _b; \
    246     _a = a; _b = b; \
    247     LL_MUL32(r, _a.lo, _b.lo); \
    248     (r).hi += _a.hi * _b.lo + _a.lo * _b.hi; \
    249 }
    250 
    251 #define _lo16(a)        ((a) & PR_BITMASK(16))
    252 #define _hi16(a)        ((a) >> 16)
    253 
    254 #define LL_MUL32(r, a, b) { \
    255      PRUint32 _a1, _a0, _b1, _b0, _y0, _y1, _y2, _y3; \
    256      _a1 = _hi16(a), _a0 = _lo16(a); \
    257      _b1 = _hi16(b), _b0 = _lo16(b); \
    258      _y0 = _a0 * _b0; \
    259      _y1 = _a0 * _b1; \
    260      _y2 = _a1 * _b0; \
    261      _y3 = _a1 * _b1; \
    262      _y1 += _hi16(_y0);                         /* can't carry */ \
    263      _y1 += _y2;                                /* might carry */ \
    264      if (_y1 < _y2)    \
    265         _y3 += (PRUint32)(PR_BIT(16));  /* propagate */ \
    266      (r).lo = (_lo16(_y1) << 16) + _lo16(_y0); \
    267      (r).hi = _y3 + _hi16(_y1); \
    268 }
    269 
    270 #define LL_UDIVMOD(qp, rp, a, b)    ll_udivmod(qp, rp, a, b)
    271 
    272 NSPR_API(void) ll_udivmod(PRUint64 *qp, PRUint64 *rp, PRUint64 a, PRUint64 b);
    273 
    274 #define LL_DIV(r, a, b) { \
    275     PRInt64 _a, _b; \
    276     PRUint32 _negative = (PRInt32)(a).hi < 0; \
    277     if (_negative) { \
    278     LL_NEG(_a, a); \
    279     } else { \
    280     _a = a; \
    281     } \
    282     if ((PRInt32)(b).hi < 0) { \
    283     _negative ^= 1; \
    284     LL_NEG(_b, b); \
    285     } else { \
    286     _b = b; \
    287     } \
    288     LL_UDIVMOD(&(r), 0, _a, _b); \
    289     if (_negative) \
    290     LL_NEG(r, r); \
    291 }
    292 
    293 #define LL_MOD(r, a, b) { \
    294     PRInt64 _a, _b; \
    295     PRUint32 _negative = (PRInt32)(a).hi < 0; \
    296     if (_negative) { \
    297     LL_NEG(_a, a); \
    298     } else { \
    299     _a = a; \
    300     } \
    301     if ((PRInt32)(b).hi < 0) { \
    302     LL_NEG(_b, b); \
    303     } else { \
    304     _b = b; \
    305     } \
    306     LL_UDIVMOD(0, &(r), _a, _b); \
    307     if (_negative) \
    308     LL_NEG(r, r); \
    309 }
    310 
    311 #define LL_SHL(r, a, b) { \
    312     if (b) { \
    313     PRInt64 _a; \
    314         _a = a; \
    315         if ((b) < 32) { \
    316         (r).lo = _a.lo << ((b) & 31); \
    317         (r).hi = (_a.hi << ((b) & 31)) | (_a.lo >> (32 - (b))); \
    318     } else { \
    319         (r).lo = 0; \
    320         (r).hi = _a.lo << ((b) & 31); \
    321     } \
    322     } else { \
    323     (r) = (a); \
    324     } \
    325 }
    326 
    327 /* a is an PRInt32, b is PRInt32, r is PRInt64 */
    328 #define LL_ISHL(r, a, b) { \
    329     if (b) { \
    330     PRInt64 _a; \
    331     _a.lo = (a); \
    332     _a.hi = 0; \
    333         if ((b) < 32) { \
    334         (r).lo = (a) << ((b) & 31); \
    335         (r).hi = ((a) >> (32 - (b))); \
    336     } else { \
    337         (r).lo = 0; \
    338         (r).hi = (a) << ((b) & 31); \
    339     } \
    340     } else { \
    341     (r).lo = (a); \
    342     (r).hi = 0; \
    343     } \
    344 }
    345 
    346 #define LL_SHR(r, a, b) { \
    347     if (b) { \
    348     PRInt64 _a; \
    349         _a = a; \
    350     if ((b) < 32) { \
    351         (r).lo = (_a.hi << (32 - (b))) | (_a.lo >> ((b) & 31)); \
    352         (r).hi = (PRInt32)_a.hi >> ((b) & 31); \
    353     } else { \
    354         (r).lo = (PRInt32)_a.hi >> ((b) & 31); \
    355         (r).hi = (PRInt32)_a.hi >> 31; \
    356     } \
    357     } else { \
    358     (r) = (a); \
    359     } \
    360 }
    361 
    362 #define LL_USHR(r, a, b) { \
    363     if (b) { \
    364     PRInt64 _a; \
    365         _a = a; \
    366     if ((b) < 32) { \
    367         (r).lo = (_a.hi << (32 - (b))) | (_a.lo >> ((b) & 31)); \
    368         (r).hi = _a.hi >> ((b) & 31); \
    369     } else { \
    370         (r).lo = _a.hi >> ((b) & 31); \
    371         (r).hi = 0; \
    372     } \
    373     } else { \
    374     (r) = (a); \
    375     } \
    376 }
    377 
    378 #define LL_L2I(i, l)        ((i) = (l).lo)
    379 #define LL_L2UI(ui, l)        ((ui) = (l).lo)
    380 #define LL_L2F(f, l)        { double _d; LL_L2D(_d, l); (f) = (PRFloat64)_d; }
    381 
    382 #define LL_L2D(d, l) { \
    383     int _negative; \
    384     PRInt64 _absval; \
    385  \
    386     _negative = (l).hi >> 31; \
    387     if (_negative) { \
    388     LL_NEG(_absval, l); \
    389     } else { \
    390     _absval = l; \
    391     } \
    392     (d) = (double)_absval.hi * 4.294967296e9 + _absval.lo; \
    393     if (_negative) \
    394     (d) = -(d); \
    395 }
    396 
    397 #define LL_I2L(l, i)        { PRInt32 _i = ((PRInt32)(i)) >> 31; (l).lo = (i); (l).hi = _i; }
    398 #define LL_UI2L(l, ui)      ((l).lo = (ui), (l).hi = 0)
    399 #define LL_F2L(l, f)        { double _d = (double)f; LL_D2L(l, _d); }
    400 
    401 #define LL_D2L(l, d) { \
    402     int _negative; \
    403     double _absval, _d_hi; \
    404     PRInt64 _lo_d; \
    405  \
    406     _negative = ((d) < 0); \
    407     _absval = _negative ? -(d) : (d); \
    408  \
    409     (l).hi = _absval / 4.294967296e9; \
    410     (l).lo = 0; \
    411     LL_L2D(_d_hi, l); \
    412     _absval -= _d_hi; \
    413     _lo_d.hi = 0; \
    414     if (_absval < 0) { \
    415     _lo_d.lo = -_absval; \
    416     LL_SUB(l, l, _lo_d); \
    417     } else { \
    418     _lo_d.lo = _absval; \
    419     LL_ADD(l, l, _lo_d); \
    420     } \
    421  \
    422     if (_negative) \
    423     LL_NEG(l, l); \
    424 }
    425 
    426 #endif /* !HAVE_LONG_LONG */
    427 
    428 PR_END_EXTERN_C
    429 
    430 #endif /* prlong_h___ */
    431