const typename Signature<typename T::Ret, typename T::Arg0, typename T::Arg1>::IArgs& iargs) const
{
// Fast-path for common case
- if (iargs.a.isOrdinary() && iargs.b.isOrdinary())
+ if (iargs.a.isOrdinary(ctx.format.getMaxValue()) && iargs.b.isOrdinary(ctx.format.getMaxValue()))
{
Interval ret;
TCU_SET_INTERVAL_BOUNDS(ret, sum,
Interval b = iargs.b;
// Fast-path for common case
- if (a.isOrdinary() && b.isOrdinary())
+ if (a.isOrdinary(ctx.format.getMaxValue()) && b.isOrdinary(ctx.format.getMaxValue()))
{
Interval ret;
if (a.hi() < 0)
Interval doApply (const EvalContext& ctx, const typename Signature<typename T::Ret, typename T::Arg0, typename T::Arg1>::IArgs& iargs) const
{
// Fast-path for common case
- if (iargs.a.isOrdinary() && iargs.b.isOrdinary())
+ if (iargs.a.isOrdinary(ctx.format.getMaxValue()) && iargs.b.isOrdinary(ctx.format.getMaxValue()))
{
Interval ret;
ret |= ctx.format.roundOut(Interval(-DE_PI_DOUBLE, DE_PI_DOUBLE), true);
}
- if (!yi.isFinite() || !xi.isFinite())
+ if (!yi.isFinite(ctx.format.getMaxValue()) || !xi.isFinite(ctx.format.getMaxValue()))
{
// Infinities may not be supported, allow anything, including NaN
ret |= TCU_NAN;
}
protected:
- TIRet doApply (const EvalContext&, const TIArgs& iargs) const
+ TIRet doApply (const EvalContext& ctx, const TIArgs& iargs) const
{
Interval fracIV;
Interval& wholeIV = const_cast<Interval&>(iargs.b);
TCU_INTERVAL_APPLY_MONOTONE1(wholeIV, x, iargs.a, whole,
deModf(x, &intPart); whole = intPart);
- if (!iargs.a.isFinite())
+ if (!iargs.a.isFinite(ctx.format.getMaxValue()))
{
// Behavior on modf(Inf) not well-defined, allow anything as a fractional part
// See Khronos bug 13907
bool any = iargs.a.hasNaN() || iargs.b.hi() > (maxExp + 1);
Interval ret(any, ldexp(iargs.a.lo(), (int)iargs.b.lo()), ldexp(iargs.a.hi(), (int)iargs.b.hi()));
if (iargs.b.lo() < minExp) ret |= 0.0;
- if (!ret.isFinite()) ret |= TCU_NAN;
+ if (!ret.isFinite(ctx.format.getMaxValue())) ret |= TCU_NAN;
return ctx.format.convert(ret);
}
};
// Add 1ULP precision tolerance to account for differing rounding modes between the GPU and deLdExp.
ret += Interval(-ctx.format.ulp(ret.lo()), ctx.format.ulp(ret.hi()));
if (iargs.b.lo() < minExp) ret |= 0.0;
- if (!ret.isFinite()) ret |= TCU_NAN;
+ if (!ret.isFinite(ctx.format.getMaxValue())) ret |= TCU_NAN;
return ctx.format.convert(ret);
}
bool hasNaN (void) const { return m_hasNaN; }
Interval nan (void) const { return m_hasNaN ? TCU_NAN : Interval(); }
bool empty (void) const { return m_lo > m_hi; }
- bool isFinite (void) const { return m_lo > -TCU_INFINITY && m_hi < TCU_INFINITY; }
- bool isOrdinary (void) const { return !hasNaN() && !empty() && isFinite(); }
+
+ // The interval is represented in double, it can extend outside the range of smaller floating-point formats
+ // and get rounded to infinity.
+ bool isFinite (double maxValue) const { return m_lo > -maxValue && m_hi < maxValue; }
+ bool isOrdinary (double maxValue) const { return !hasNaN() && !empty() && isFinite(maxValue); }
void warning (double lo_, double hi_)
{
TCU_SET_INTERVAL(prod2, tmp, tmp = ia.hi() * ib.lo());
TCU_SET_INTERVAL(prod3, tmp, tmp = ia.hi() * ib.hi());
- prod = format.convert(format.roundOut(prod0 | prod1 | prod2 | prod3, ia.isFinite() && ib.isFinite()));
+ prod = format.convert(format.roundOut(prod0 | prod1 | prod2 | prod3, ia.isFinite(format.getMaxValue()) && ib.isFinite(format.getMaxValue())));
TCU_SET_INTERVAL_BOUNDS(res, tmp,
tmp = prod.lo() + ic.lo(),
tmp = prod.hi() + ic.hi());
- return format.convert(format.roundOut(res, prod.isFinite() && ic.isFinite()));
+ return format.convert(format.roundOut(res, prod.isFinite(format.getMaxValue()) && ic.isFinite(format.getMaxValue())));
}
bool compare (const void* const* inputs, const void* const* outputs)
const IArgs& iargs) const
{
// Fast-path for common case
- if (iargs.a.isOrdinary() && iargs.b.isOrdinary())
+ if (iargs.a.isOrdinary(ctx.format.getMaxValue()) && iargs.b.isOrdinary(ctx.format.getMaxValue()))
{
Interval ret;
TCU_SET_INTERVAL_BOUNDS(ret, sum,
Interval b = iargs.b;
// Fast-path for common case
- if (a.isOrdinary() && b.isOrdinary())
+ if (a.isOrdinary(ctx.format.getMaxValue()) && b.isOrdinary(ctx.format.getMaxValue()))
{
Interval ret;
if (a.hi() < 0)
Interval doApply (const EvalContext& ctx, const IArgs& iargs) const
{
// Fast-path for common case
- if (iargs.a.isOrdinary() && iargs.b.isOrdinary())
+ if (iargs.a.isOrdinary(ctx.format.getMaxValue()) && iargs.b.isOrdinary(ctx.format.getMaxValue()))
{
Interval ret;
ATan2 (void) : CFloatFunc2 ("atan", deAtan2) {}
protected:
- Interval innerExtrema (const EvalContext&,
+ Interval innerExtrema (const EvalContext& ctx,
const Interval& yi,
const Interval& xi) const
{
ret |= Interval(-DE_PI_DOUBLE, DE_PI_DOUBLE);
}
- if ((!yi.isFinite() || !xi.isFinite()))
+ if (!yi.isFinite(ctx.format.getMaxValue()) || !xi.isFinite(ctx.format.getMaxValue()))
{
// Infinities may not be supported, allow anything, including NaN
ret |= TCU_NAN;
}
protected:
- IRet doApply (const EvalContext&, const IArgs& iargs) const
+ IRet doApply (const EvalContext& ctx, const IArgs& iargs) const
{
Interval fracIV;
Interval& wholeIV = const_cast<Interval&>(iargs.b);
TCU_INTERVAL_APPLY_MONOTONE1(wholeIV, x, iargs.a, whole,
deModf(x, &intPart); whole = intPart);
- if (!iargs.a.isFinite())
+ if (!iargs.a.isFinite(ctx.format.getMaxValue()))
{
// Behavior on modf(Inf) not well-defined, allow anything as a fractional part
// See Khronos bug 13907