Browse Source

workaround for some uclibc's lacking fmin/fmax and round

pull/1/head
Sami Vaarala 11 years ago
parent
commit
43dd685962
  1. 51
      src/duk_builtin_math.c

51
src/duk_builtin_math.c

@ -67,7 +67,11 @@ static double fmin_fixed(double x, double y) {
return +0.0;
}
}
#ifdef DUK_USE_MATH_FMIN
return fmin(x, y);
#else
return (x < y ? x : y);
#endif
}
static double fmax_fixed(double x, double y) {
@ -81,16 +85,20 @@ static double fmax_fixed(double x, double y) {
return -0.0;
}
}
#ifdef DUK_USE_MATH_FMAX
return fmax(x, y);
#else
return (x > y ? x : y);
#endif
}
static double round_fixed(double x) {
/* Numbers must be rounded towards +Infinity, e.g. -3.5 must
* be rounded to -3 (not -4). When rounded to zero, zero sign
* must be set appropriately. E5.1 Section 15.8.2.15.
/* Numbers half-way between integers must be rounded towards +Infinity,
* e.g. -3.5 must be rounded to -3 (not -4). When rounded to zero, zero
* sign must be set appropriately. E5.1 Section 15.8.2.15.
*
* Note that ANSI C round() is "round to nearest integer, away
* from zero", which is incorrect for negative values.
* Note that ANSI C round() is "round to nearest integer, away from zero",
* which is incorrect for negative values. Here we make do with floor().
*/
int c = fpclassify(x);
@ -98,22 +106,31 @@ static double round_fixed(double x) {
return x;
}
if (x >= 0.0) {
/* FIXME: rely on [0,0.5[ rounding to +0? */
if (x < 0.5) {
return +0.0;
} else {
return round(x);
}
} else {
if (x >= -0.5) {
/*
* x is finite and non-zero
*
* -1.6 -> floor(-1.1) -> -2
* -1.5 -> floor(-1.0) -> -1 (towards +Inf)
* -1.4 -> floor(-0.9) -> -1
* -0.5 -> -0.0 (special case)
* -0.1 -> -0.0 (special case)
* +0.1 -> +0.0 (special case)
* +0.5 -> floor(+1.0) -> 1 (towards +Inf)
* +1.4 -> floor(+1.9) -> 1
* +1.5 -> floor(+2.0) -> 2 (towards +Inf)
* +1.6 -> floor(+2.1) -> 2
*/
if (x >= -0.5 && x < 0.5) {
/* +0.5 is handled by floor, this is on purpose */
if (x < 0.0) {
return -0.0;
} else {
x = floor(x + 0.5);
DUK_ASSERT(x <= -1.0);
return x;
return +0.0;
}
}
return floor(x + 0.5);
}
static double pow_fixed(double x, double y) {

Loading…
Cancel
Save