cosmopolitan/third_party/duktape/duk_replacements.c

83 lines
1.8 KiB
C

/*
* Replacements for missing platform functions.
*
* Unlike the originals, fpclassify() and signbit() replacements don't
* work on any floating point types, only doubles. The C typing here
* mimics the standard prototypes.
*/
#include "third_party/duktape/duk_internal.h"
#if defined(DUK_USE_COMPUTED_NAN)
DUK_INTERNAL double duk_computed_nan;
#endif
#if defined(DUK_USE_COMPUTED_INFINITY)
DUK_INTERNAL double duk_computed_infinity;
#endif
#if defined(DUK_USE_REPL_FPCLASSIFY)
DUK_INTERNAL int duk_repl_fpclassify(double x) {
duk_double_union u;
duk_uint_fast16_t expt;
duk_small_int_t mzero;
u.d = x;
expt = (duk_uint_fast16_t) (u.us[DUK_DBL_IDX_US0] & 0x7ff0UL);
if (expt > 0x0000UL && expt < 0x7ff0UL) {
/* expt values [0x001,0x7fe] = normal */
return DUK_FP_NORMAL;
}
mzero = (u.ui[DUK_DBL_IDX_UI1] == 0 && (u.ui[DUK_DBL_IDX_UI0] & 0x000fffffUL) == 0);
if (expt == 0x0000UL) {
/* expt 0x000 is zero/subnormal */
if (mzero) {
return DUK_FP_ZERO;
} else {
return DUK_FP_SUBNORMAL;
}
} else {
/* expt 0xfff is infinite/nan */
if (mzero) {
return DUK_FP_INFINITE;
} else {
return DUK_FP_NAN;
}
}
}
#endif
#if defined(DUK_USE_REPL_SIGNBIT)
DUK_INTERNAL int duk_repl_signbit(double x) {
duk_double_union u;
u.d = x;
return (int) (u.uc[DUK_DBL_IDX_UC0] & 0x80UL);
}
#endif
#if defined(DUK_USE_REPL_ISFINITE)
DUK_INTERNAL int duk_repl_isfinite(double x) {
int c = DUK_FPCLASSIFY(x);
if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
return 0;
} else {
return 1;
}
}
#endif
#if defined(DUK_USE_REPL_ISNAN)
DUK_INTERNAL int duk_repl_isnan(double x) {
int c = DUK_FPCLASSIFY(x);
return (c == DUK_FP_NAN);
}
#endif
#if defined(DUK_USE_REPL_ISINF)
DUK_INTERNAL int duk_repl_isinf(double x) {
int c = DUK_FPCLASSIFY(x);
return (c == DUK_FP_INFINITE);
}
#endif