1 /*
2  *  Replacements for missing platform functions.
3  *
4  *  Unlike the originals, fpclassify() and signbit() replacements don't
5  *  work on any floating point types, only doubles.  The C typing here
6  *  mimics the standard prototypes.
7  */
8 
9 #include "duk_internal.h"
10 
11 #if defined(DUK_USE_COMPUTED_NAN)
12 DUK_INTERNAL double duk_computed_nan;
13 #endif
14 
15 #if defined(DUK_USE_COMPUTED_INFINITY)
16 DUK_INTERNAL double duk_computed_infinity;
17 #endif
18 
19 #if defined(DUK_USE_REPL_FPCLASSIFY)
duk_repl_fpclassify(double x)20 DUK_INTERNAL int duk_repl_fpclassify(double x) {
21 	duk_double_union u;
22 	duk_uint_fast16_t expt;
23 	duk_small_int_t mzero;
24 
25 	u.d = x;
26 	expt = (duk_uint_fast16_t) (u.us[DUK_DBL_IDX_US0] & 0x7ff0UL);
27 	if (expt > 0x0000UL && expt < 0x7ff0UL) {
28 		/* expt values [0x001,0x7fe] = normal */
29 		return DUK_FP_NORMAL;
30 	}
31 
32 	mzero = (u.ui[DUK_DBL_IDX_UI1] == 0 && (u.ui[DUK_DBL_IDX_UI0] & 0x000fffffUL) == 0);
33 	if (expt == 0x0000UL) {
34 		/* expt 0x000 is zero/subnormal */
35 		if (mzero) {
36 			return DUK_FP_ZERO;
37 		} else {
38 			return DUK_FP_SUBNORMAL;
39 		}
40 	} else {
41 		/* expt 0xfff is infinite/nan */
42 		if (mzero) {
43 			return DUK_FP_INFINITE;
44 		} else {
45 			return DUK_FP_NAN;
46 		}
47 	}
48 }
49 #endif
50 
51 #if defined(DUK_USE_REPL_SIGNBIT)
duk_repl_signbit(double x)52 DUK_INTERNAL int duk_repl_signbit(double x) {
53 	duk_double_union u;
54 	u.d = x;
55 	return (int) (u.uc[DUK_DBL_IDX_UC0] & 0x80UL);
56 }
57 #endif
58 
59 #if defined(DUK_USE_REPL_ISFINITE)
duk_repl_isfinite(double x)60 DUK_INTERNAL int duk_repl_isfinite(double x) {
61 	int c = DUK_FPCLASSIFY(x);
62 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
63 		return 0;
64 	} else {
65 		return 1;
66 	}
67 }
68 #endif
69 
70 #if defined(DUK_USE_REPL_ISNAN)
duk_repl_isnan(double x)71 DUK_INTERNAL int duk_repl_isnan(double x) {
72 	int c = DUK_FPCLASSIFY(x);
73 	return (c == DUK_FP_NAN);
74 }
75 #endif
76 
77 #if defined(DUK_USE_REPL_ISINF)
duk_repl_isinf(double x)78 DUK_INTERNAL int duk_repl_isinf(double x) {
79 	int c = DUK_FPCLASSIFY(x);
80 	return (c == DUK_FP_INFINITE);
81 }
82 #endif
83