static int eqish_floating_p(double x, double y,
const struct tvec_floatinfo *fi)
{
- double t;
+ double t, u;
+ /* NaNs and infinities are equal only to each other. */
if (NANP(x)) return (NANP(y)); else if (NANP(y)) return (0);
if (INFP(x)) return (x == y); else if (INFP(y)) return (0);
+ /* Compare finite values. */
switch (fi ? fi->f&TVFF_EQMASK : TVFF_EXACT) {
case TVFF_EXACT:
return (x == y && NEGP(x) == NEGP(y));
case TVFF_ABSDELTA:
- t = x - y; if (t < 0) t = -t; return (t < fi->delta);
+ t = fabs(y - x); return (t < fi->delta);
case TVFF_RELDELTA:
- t = 1.0 - x/y; if (t < 0) t = -t; return (t < fi->delta);
+ t = fabs(y - x); u = fabs(y*fi->delta); if (u < DBL_MIN) u = DBL_MIN;
+ return (t <= u);
default:
abort();
}
/* Predefined floating-point ranges. */
const struct tvec_floatinfo
- tvflt_float = { TVFF_EXACT | TVFF_INFOK | TVFF_NANOK,
- -FLT_MAX, FLT_MAX, 0.0 },
+ tvflt_float = { TVFF_RELDELTA | TVFF_INFOK | TVFF_NANOK,
+ -FLT_MAX, FLT_MAX, FLT_EPSILON/2 },
tvflt_double = { TVFF_EXACT | TVFF_INFOK | TVFF_NANOK,
-DBL_MAX, DBL_MAX, 0.0 },
tvflt_finite = { TVFF_EXACT, -DBL_MAX, DBL_MAX, 0.0 },