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

Contents of /trunk/js/jsnum.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 507 - (show annotations)
Sun Jan 10 07:23:34 2010 UTC (9 years, 7 months ago) by siliconforks
File MIME type: text/plain
File size: 12447 byte(s)
Update SpiderMonkey from Firefox 3.6rc1.

1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 *
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 *
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
10 *
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
15 *
16 * The Original Code is Mozilla Communicator client code, released
17 * March 31, 1998.
18 *
19 * The Initial Developer of the Original Code is
20 * Netscape Communications Corporation.
21 * Portions created by the Initial Developer are Copyright (C) 1998
22 * the Initial Developer. All Rights Reserved.
23 *
24 * Contributor(s):
25 *
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
37 *
38 * ***** END LICENSE BLOCK ***** */
39
40 #ifndef jsnum_h___
41 #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.
53 *
54 * JS numbers are optimistically stored in the top 31 bits of 32-bit integers,
55 * but floating point literals, results that overflow 31 bits, and division and
56 * modulus operands and results require a 64-bit IEEE double. These are GC'ed
57 * and pointed to by 32-bit jsvals on the stack and in object properties.
58 */
59
60 JS_BEGIN_EXTERN_C
61
62 /*
63 * The ARM architecture supports two floating point models: VFP and FPA. When
64 * targetting FPA, doubles are mixed-endian on little endian ARMs (meaning that
65 * the high and low words are in big endian order).
66 */
67 #if defined(__arm) || defined(__arm32__) || defined(__arm26__) || defined(__arm__)
68 #if !defined(__VFP_FP__)
69 #define FPU_IS_ARM_FPA
70 #endif
71 #endif
72
73 typedef union jsdpun {
74 struct {
75 #if defined(IS_LITTLE_ENDIAN) && !defined(FPU_IS_ARM_FPA)
76 uint32 lo, hi;
77 #else
78 uint32 hi, lo;
79 #endif
80 } s;
81 uint64 u64;
82 jsdouble d;
83 } jsdpun;
84
85 static inline int
86 JSDOUBLE_IS_NaN(jsdouble d)
87 {
88 #ifdef WIN32
89 return _isnan(d);
90 #else
91 return isnan(d);
92 #endif
93 }
94
95 static inline int
96 JSDOUBLE_IS_FINITE(jsdouble d)
97 {
98 #ifdef WIN32
99 return _finite(d);
100 #else
101 return finite(d);
102 #endif
103 }
104
105 static inline int
106 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 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
131 #define JSDOUBLE_HI32_EXPMASK 0x7ff00000
132 #define JSDOUBLE_HI32_MANTMASK 0x000fffff
133
134 static inline int
135 JSDOUBLE_IS_INT(jsdouble d, jsint& i)
136 {
137 if (JSDOUBLE_IS_NEGZERO(d))
138 return false;
139 return d == (i = jsint(d));
140 }
141
142 static inline int
143 JSDOUBLE_IS_NEG(jsdouble d)
144 {
145 #ifdef WIN32
146 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 JS_HASH_DOUBLE(jsdouble d)
156 {
157 jsdpun u;
158 u.d = d;
159 return u.s.lo ^ u.s.hi;
160 }
161
162 #if defined(XP_WIN)
163 #define JSDOUBLE_COMPARE(LVAL, OP, RVAL, IFNAN) \
164 ((JSDOUBLE_IS_NaN(LVAL) || JSDOUBLE_IS_NaN(RVAL)) \
165 ? (IFNAN) \
166 : (LVAL) OP (RVAL))
167 #else
168 #define JSDOUBLE_COMPARE(LVAL, OP, RVAL, IFNAN) ((LVAL) OP (RVAL))
169 #endif
170
171 extern jsdouble js_NaN;
172
173 /* Initialize number constants and runtime state for the first context. */
174 extern JSBool
175 js_InitRuntimeNumberState(JSContext *cx);
176
177 extern void
178 js_TraceRuntimeNumberState(JSTracer *trc);
179
180 extern void
181 js_FinishRuntimeNumberState(JSContext *cx);
182
183 /* Initialize the Number class, returning its prototype object. */
184 extern JSClass js_NumberClass;
185
186 extern JSObject *
187 js_InitNumberClass(JSContext *cx, JSObject *obj);
188
189 /*
190 * String constants for global function names, used in jsapi.c and jsnum.c.
191 */
192 extern const char js_Infinity_str[];
193 extern const char js_NaN_str[];
194 extern const char js_isNaN_str[];
195 extern const char js_isFinite_str[];
196 extern const char js_parseFloat_str[];
197 extern const char js_parseInt_str[];
198
199 /*
200 * vp must be a root.
201 */
202 extern JSBool
203 js_NewNumberInRootedValue(JSContext *cx, jsdouble d, jsval *vp);
204
205 /*
206 * Create a weakly rooted integer or double jsval as appropriate for the given
207 * jsdouble.
208 */
209 extern JSBool
210 js_NewWeaklyRootedNumber(JSContext *cx, jsdouble d, jsval *vp);
211
212 /* Convert a number to a GC'ed string. */
213 extern JSString * JS_FASTCALL
214 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
225 * 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
227 * for result has to be created explicitly using, for example, the
228 * js_NewNumberInRootedValue function.
229 */
230 extern jsdouble
231 js_ValueToNumber(JSContext *cx, jsval* vp);
232
233 /*
234 * Convert a value to an int32 or uint32, according to the ECMA rules for
235 * ToInt32 and ToUint32. On exit JSVAL_IS_NULL(*vp) iff there was an error. If
236 * on exit JSVAL_IS_INT(*vp), then *vp holds the jsval matching the result.
237 * Otherwise *vp is JSVAL_TRUE indicating that the jsval for result has to be
238 * created explicitly using, for example, the js_NewNumberInRootedValue
239 * function.
240 */
241 extern int32
242 js_ValueToECMAInt32(JSContext *cx, jsval *vp);
243
244 extern uint32
245 js_ValueToECMAUint32(JSContext *cx, jsval *vp);
246
247 /*
248 * Specialized ToInt32 and ToUint32 converters for doubles.
249 */
250 /*
251 * 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
355 js_DoubleToECMAUint32(jsdouble d);
356
357 /*
358 * Convert a value to a number, then to an int32 if it fits by rounding to
359 * nearest; but failing with an error report if the double is out of range
360 * or unordered. On exit JSVAL_IS_NULL(*vp) iff there was an error. If on exit
361 * JSVAL_IS_INT(*vp), then *vp holds the jsval matching the result. Otherwise
362 * *vp is JSVAL_TRUE indicating that the jsval for result has to be created
363 * explicitly using, for example, the js_NewNumberInRootedValue function.
364 */
365 extern int32
366 js_ValueToInt32(JSContext *cx, jsval *vp);
367
368 /*
369 * Convert a value to a number, then to a uint16 according to the ECMA rules
370 * for ToUint16. On exit JSVAL_IS_NULL(*vp) iff there was an error, otherwise
371 * vp is jsval matching the result.
372 */
373 extern uint16
374 js_ValueToUint16(JSContext *cx, jsval *vp);
375
376 /*
377 * 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.
379 */
380 static inline jsdouble
381 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
400 * correct sign, and underflows with zeros of the correct sign. Guaranteed to
401 * return the closest double number to the given input in dp.
402 *
403 * Also allows inputs of the form [+|-]Infinity, which produce an infinity of
404 * the appropriate sign. The case of the "Infinity" string must match exactly.
405 * If the string does not contain a number, set *ep to s and return 0.0 in dp.
406 * Return false if out of memory.
407 */
408 extern JSBool
409 js_strtod(JSContext *cx, const jschar *s, const jschar *send,
410 const jschar **ep, jsdouble *dp);
411
412 /*
413 * Similar to strtol except that it handles integers of arbitrary size.
414 * Guaranteed to return the closest double number to the given input when radix
415 * is 10 or a power of 2. Callers may see round-off errors for very large
416 * numbers of a different radix than 10 or a power of 2.
417 *
418 * If the string does not contain a number, set *ep to s and return 0.0 in dp.
419 * Return false if out of memory.
420 */
421 extern JSBool
422 js_strtointeger(JSContext *cx, const jschar *s, const jschar *send,
423 const jschar **ep, jsint radix, jsdouble *dp);
424
425 JS_END_EXTERN_C
426
427 #endif /* jsnum_h___ */

  ViewVC Help
Powered by ViewVC 1.1.24