/[jscoverage]/trunk/js/jsnum.h
ViewVC logotype

Diff of /trunk/js/jsnum.h

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 460 by siliconforks, Sat Sep 26 23:15:22 2009 UTC revision 507 by siliconforks, Sun Jan 10 07:23:34 2010 UTC
# Line 40  Line 40 
40  #ifndef jsnum_h___  #ifndef jsnum_h___
41  #define jsnum_h___  #define jsnum_h___
42    
43    #include <math.h>
44    #if defined(XP_WIN) || defined(XP_OS2)
45    #include <float.h>
46    #endif
47    #ifdef SOLARIS
48    #include <ieeefp.h>
49    #endif
50    
51  /*  /*
52   * JS number (IEEE double) interface.   * JS number (IEEE double) interface.
53   *   *
# Line 74  Line 82 
82      jsdouble d;      jsdouble d;
83  } jsdpun;  } jsdpun;
84    
85  #if (__GNUC__ == 2 && __GNUC_MINOR__ > 95) || __GNUC__ > 2  static inline int
86  /*  JSDOUBLE_IS_NaN(jsdouble d)
87   * This version of the macros is safe for the alias optimizations that gcc  {
88   * does, but uses gcc-specific extensions.  #ifdef WIN32
89   */      return _isnan(d);
90    #else
91  #define JSDOUBLE_HI32(x) (__extension__ ({ jsdpun u; u.d = (x); u.s.hi; }))      return isnan(d);
92  #define JSDOUBLE_LO32(x) (__extension__ ({ jsdpun u; u.d = (x); u.s.lo; }))  #endif
93  #define JSDOUBLE_SET_HI32(x, y) \  }
     (__extension__ ({ jsdpun u; u.d = (x); u.s.hi = (y); (x) = u.d; }))  
 #define JSDOUBLE_SET_LO32(x, y) \  
     (__extension__ ({ jsdpun u; u.d = (x); u.s.lo = (y); (x) = u.d; }))  
   
 #else /* not or old GNUC */  
   
 /*  
  * We don't know of any non-gcc compilers that perform alias optimization,  
  * so this code should work.  
  */  
94    
95  #if defined(IS_LITTLE_ENDIAN) && !defined(FPU_IS_ARM_FPA)  static inline int
96  #define JSDOUBLE_HI32(x)        (((uint32 *)&(x))[1])  JSDOUBLE_IS_FINITE(jsdouble d)
97  #define JSDOUBLE_LO32(x)        (((uint32 *)&(x))[0])  {
98    #ifdef WIN32
99        return _finite(d);
100  #else  #else
101  #define JSDOUBLE_HI32(x)        (((uint32 *)&(x))[0])      return finite(d);
 #define JSDOUBLE_LO32(x)        (((uint32 *)&(x))[1])  
102  #endif  #endif
103    }
104    
105  #define JSDOUBLE_SET_HI32(x, y) (JSDOUBLE_HI32(x)=(y))  static inline int
106  #define JSDOUBLE_SET_LO32(x, y) (JSDOUBLE_LO32(x)=(y))  JSDOUBLE_IS_INFINITE(jsdouble d)
107    {
108    #ifdef WIN32
109        int c = _fpclass(d);
110        return c == _FPCLASS_NINF || c == _FPCLASS_PINF;
111    #elif defined(SOLARIS)
112        return !finite(d) && !isnan(d);
113    #else
114        return isinf(d);
115    #endif
116    }
117    
118  #endif /* not or old GNUC */  static inline int
119    JSDOUBLE_IS_NEGZERO(jsdouble d)
120    {
121    #ifdef WIN32
122        return (d == 0 && (_fpclass(d) & _FPCLASS_NZ));
123    #elif defined(SOLARIS)
124        return (d == 0 && copysign(1, d) < 0);
125    #else
126        return (d == 0 && signbit(d));
127    #endif
128    }
129    
130  #define JSDOUBLE_HI32_SIGNBIT   0x80000000  #define JSDOUBLE_HI32_SIGNBIT   0x80000000
131  #define JSDOUBLE_HI32_EXPMASK   0x7ff00000  #define JSDOUBLE_HI32_EXPMASK   0x7ff00000
132  #define JSDOUBLE_HI32_MANTMASK  0x000fffff  #define JSDOUBLE_HI32_MANTMASK  0x000fffff
133    
134  #define JSDOUBLE_IS_NaN(x)                                                    \  static inline int
135      ((JSDOUBLE_HI32(x) & JSDOUBLE_HI32_EXPMASK) == JSDOUBLE_HI32_EXPMASK &&   \  JSDOUBLE_IS_INT(jsdouble d, jsint& i)
136       (JSDOUBLE_LO32(x) || (JSDOUBLE_HI32(x) & JSDOUBLE_HI32_MANTMASK)))  {
137        if (JSDOUBLE_IS_NEGZERO(d))
138  #define JSDOUBLE_IS_INFINITE(x)                                               \          return false;
139      ((JSDOUBLE_HI32(x) & ~JSDOUBLE_HI32_SIGNBIT) == JSDOUBLE_HI32_EXPMASK &&  \      return d == (i = jsint(d));
140       !JSDOUBLE_LO32(x))  }
141    
142  #define JSDOUBLE_IS_FINITE(x)                                                 \  static inline int
143      ((JSDOUBLE_HI32(x) & JSDOUBLE_HI32_EXPMASK) != JSDOUBLE_HI32_EXPMASK)  JSDOUBLE_IS_NEG(jsdouble d)
144    {
145  #define JSDOUBLE_IS_NEGZERO(d)  (JSDOUBLE_HI32(d) == JSDOUBLE_HI32_SIGNBIT && \  #ifdef WIN32
146                                   JSDOUBLE_LO32(d) == 0)      return JSDOUBLE_IS_NEGZERO(d) || d < 0;
147    #elif defined(SOLARIS)
148        return copysign(1, d) < 0;
149    #else
150        return signbit(d);
151    #endif
152    }
153    
154  /*  static inline uint32
155   * JSDOUBLE_IS_INT first checks that d is neither NaN nor infinite, to avoid  JS_HASH_DOUBLE(jsdouble d)
156   * raising SIGFPE on platforms such as Alpha Linux, then (only if the cast is  {
157   * safe) leaves i as (jsint)d.  This also avoid anomalous NaN floating point      jsdpun u;
158   * comparisons under MSVC.      u.d = d;
159   */      return u.s.lo ^ u.s.hi;
160  #define JSDOUBLE_IS_INT(d, i) (JSDOUBLE_IS_FINITE(d)                          \  }
                                && !JSDOUBLE_IS_NEGZERO(d)                     \  
                                && ((d) == (i = (jsint)(d))))  
161    
162  #if defined(XP_WIN)  #if defined(XP_WIN)
163  #define JSDOUBLE_COMPARE(LVAL, OP, RVAL, IFNAN)                               \  #define JSDOUBLE_COMPARE(LVAL, OP, RVAL, IFNAN)                               \
# Line 190  Line 214 
214  js_NumberToString(JSContext *cx, jsdouble d);  js_NumberToString(JSContext *cx, jsdouble d);
215    
216  /*  /*
217     * Convert an integer or double (contained in the given jsval) to a string and
218     * append to the given buffer.
219     */
220    extern JSBool JS_FASTCALL
221    js_NumberValueToCharBuffer(JSContext *cx, jsval v, JSCharBuffer &cb);
222    
223    /*
224   * Convert a value to a number. On exit JSVAL_IS_NULL(*vp) iff there was an   * Convert a value to a number. On exit JSVAL_IS_NULL(*vp) iff there was an
225   * error. If on exit JSVAL_IS_NUMBER(*vp), then *vp holds the jsval that   * error. If on exit JSVAL_IS_NUMBER(*vp), then *vp holds the jsval that
226   * matches the result. Otherwise *vp is JSVAL_TRUE indicating that the jsval   * matches the result. Otherwise *vp is JSVAL_TRUE indicating that the jsval
# Line 216  Line 247 
247  /*  /*
248   * Specialized ToInt32 and ToUint32 converters for doubles.   * Specialized ToInt32 and ToUint32 converters for doubles.
249   */   */
250  extern int32  /*
251  js_DoubleToECMAInt32(jsdouble d);   * From the ES3 spec, 9.5
252     *  2.  If Result(1) is NaN, +0, -0, +Inf, or -Inf, return +0.
253     *  3.  Compute sign(Result(1)) * floor(abs(Result(1))).
254     *  4.  Compute Result(3) modulo 2^32; that is, a finite integer value k of Number
255     *      type with positive sign and less than 2^32 in magnitude such the mathematical
256     *      difference of Result(3) and k is mathematically an integer multiple of 2^32.
257     *  5.  If Result(4) is greater than or equal to 2^31, return Result(4)- 2^32,
258     *  otherwise return Result(4).
259     */
260    static inline int32
261    js_DoubleToECMAInt32(jsdouble d)
262    {
263    #ifdef __i386__
264        jsdpun du, duh, two32;
265        uint32 di_h, u_tmp, expon, shift_amount;
266        int32 mask32;
267    
268        /*
269         * Algorithm Outline
270         *  Step 1. If d is NaN, +/-Inf or |d|>=2^84 or |d|<1, then return 0
271         *          All of this is implemented based on an exponent comparison.
272         *  Step 2. If |d|<2^31, then return (int)d
273         *          The cast to integer (conversion in RZ mode) returns the correct result.
274         *  Step 3. If |d|>=2^32, d:=fmod(d, 2^32) is taken  -- but without a call
275         *  Step 4. If |d|>=2^31, then the fractional bits are cleared before
276         *          applying the correction by 2^32:  d - sign(d)*2^32
277         *  Step 5. Return (int)d
278         */
279    
280        du.d = d;
281        di_h = du.s.hi;
282    
283        u_tmp = (di_h & 0x7ff00000) - 0x3ff00000;
284        if (u_tmp >= (0x45300000-0x3ff00000)) {
285            // d is Nan, +/-Inf or +/-0, or |d|>=2^(32+52) or |d|<1, in which case result=0
286            return 0;
287        }
288    
289        if (u_tmp < 0x01f00000) {
290            // |d|<2^31
291            return int32_t(d);
292        }
293    
294        if (u_tmp > 0x01f00000) {
295            // |d|>=2^32
296            expon = u_tmp >> 20;
297            shift_amount = expon - 21;
298            duh.u64 = du.u64;
299            mask32 = 0x80000000;
300            if (shift_amount < 32) {
301                mask32 >>= shift_amount;
302                duh.s.hi = du.s.hi & mask32;
303                duh.s.lo = 0;
304            } else {
305                mask32 >>= (shift_amount-32);
306                duh.s.hi = du.s.hi;
307                duh.s.lo = du.s.lo & mask32;
308            }
309            du.d -= duh.d;
310        }
311    
312        di_h = du.s.hi;
313    
314        // eliminate fractional bits
315        u_tmp = (di_h & 0x7ff00000);
316        if (u_tmp >= 0x41e00000) {
317            // |d|>=2^31
318            expon = u_tmp >> 20;
319            shift_amount = expon - (0x3ff - 11);
320            mask32 = 0x80000000;
321            if (shift_amount < 32) {
322                mask32 >>= shift_amount;
323                du.s.hi &= mask32;
324                du.s.lo = 0;
325            } else {
326                mask32 >>= (shift_amount-32);
327                du.s.lo &= mask32;
328            }
329            two32.s.hi = 0x41f00000 ^ (du.s.hi & 0x80000000);
330            two32.s.lo = 0;
331            du.d -= two32.d;
332        }
333    
334        return int32(du.d);
335    #else
336        int32 i;
337        jsdouble two32, two31;
338    
339        if (!JSDOUBLE_IS_FINITE(d))
340            return 0;
341    
342        i = (int32) d;
343        if ((jsdouble) i == d)
344            return i;
345    
346        two32 = 4294967296.0;
347        two31 = 2147483648.0;
348        d = fmod(d, two32);
349        d = (d >= 0) ? floor(d) : ceil(d) + two32;
350        return (int32) (d >= two31 ? d - two32 : d);
351    #endif
352    }
353    
354  extern uint32  extern uint32
355  js_DoubleToECMAUint32(jsdouble d);  js_DoubleToECMAUint32(jsdouble d);
# Line 245  Line 377 
377   * Convert a jsdouble to an integral number, stored in a jsdouble.   * Convert a jsdouble to an integral number, stored in a jsdouble.
378   * If d is NaN, return 0.  If d is an infinity, return it without conversion.   * If d is NaN, return 0.  If d is an infinity, return it without conversion.
379   */   */
380  extern jsdouble  static inline jsdouble
381  js_DoubleToInteger(jsdouble d);  js_DoubleToInteger(jsdouble d)
382    {
383        if (d == 0)
384            return d;
385    
386        if (!JSDOUBLE_IS_FINITE(d)) {
387            if (JSDOUBLE_IS_NaN(d))
388                return 0;
389            return d;
390        }
391    
392        JSBool neg = (d < 0);
393        d = floor(neg ? -d : d);
394    
395        return neg ? -d : d;
396    }
397    
398  /*  /*
399   * Similar to strtod except that it replaces overflows with infinities of the   * Similar to strtod except that it replaces overflows with infinities of the

Legend:
Removed from v.460  
changed lines
  Added in v.507

  ViewVC Help
Powered by ViewVC 1.1.24