am e5fc2a80: Relax fma() verification in builtin_functions.common.fma
authorPyry Haulos <phaulos@google.com>
Fri, 20 Feb 2015 23:30:50 +0000 (23:30 +0000)
committerAndroid Git Automerger <android-git-automerger@android.com>
Fri, 20 Feb 2015 23:30:50 +0000 (23:30 +0000)
* commit 'e5fc2a804322422a6d50270e9e00fb1c193b6f90':
  Relax fma() verification in builtin_functions.common.fma

1  2 
modules/gles31/functional/es31fShaderCommonFunctionTests.cpp

@@@ -27,6 -27,8 +27,8 @@@
  #include "tcuTestLog.hpp"
  #include "tcuFormatUtil.hpp"
  #include "tcuFloat.hpp"
+ #include "tcuInterval.hpp"
+ #include "tcuFloatFormat.hpp"
  #include "deRandom.hpp"
  #include "deMath.h"
  #include "deString.h"
@@@ -1877,6 -1879,7 +1879,6 @@@ public
                const glu::DataType             type                    = m_spec.inputs[0].varType.getBasicType();
                const glu::Precision    precision               = m_spec.inputs[0].varType.getPrecision();
                const int                               scalarSize              = glu::getDataTypeScalarSize(type);
 -              const bool                              signedZero              = supportsSignedZero(precision);
  
                const int                               mantissaBits    = getMinMantissaBits(precision);
                const deUint32                  maxUlpDiff              = getMaxUlpDiffFromBits(mantissaBits);
                        const int               in1                     = ((const int*)inputs[1])[compNdx];
                        const float             out0            = ((const float*)outputs[0])[compNdx];
                        const float             refOut0         = ldexp(in0, in1);
 -                      const deUint32  ulpDiff         = signedZero ? getUlpDiff(out0, refOut0) : getUlpDiffIgnoreZeroSign(out0, refOut0);
 +                      const deUint32  ulpDiff         = getUlpDiffIgnoreZeroSign(out0, refOut0);
  
                        const int               inExp           = tcu::Float32(in0).exponent();
  
@@@ -2019,32 -2022,57 +2021,57 @@@ public
                }
        }
  
+       static tcu::Interval fma (glu::Precision precision, float a, float b, float c)
+       {
+               const tcu::FloatFormat formats[] =
+               {
+                       //                               minExp         maxExp          mantissa        exact,          subnormals      infinities      NaN
+                       tcu::FloatFormat(0,                     0,                      7,                      false,          tcu::YES,       tcu::MAYBE,     tcu::MAYBE),
+                       tcu::FloatFormat(-13,           13,                     9,                      false,          tcu::MAYBE,     tcu::MAYBE,     tcu::MAYBE),
+                       tcu::FloatFormat(-126,          127,            23,                     true,           tcu::MAYBE, tcu::YES,   tcu::MAYBE)
+               };
+               const tcu::FloatFormat& format  = de::getSizedArrayElement<glu::PRECISION_LAST>(formats, precision);
+               const tcu::Interval             ia              = format.convert(a);
+               const tcu::Interval             ib              = format.convert(b);
+               const tcu::Interval             ic              = format.convert(c);
+               tcu::Interval                   prod0;
+               tcu::Interval                   prod1;
+               tcu::Interval                   prod2;
+               tcu::Interval                   prod3;
+               tcu::Interval                   prod;
+               tcu::Interval                   res;
+               TCU_SET_INTERVAL(prod0, tmp, tmp = ia.lo() * ib.lo());
+               TCU_SET_INTERVAL(prod1, tmp, tmp = ia.lo() * ib.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()));
+               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()));
+       }
        bool compare (const void* const* inputs, const void* const* outputs)
        {
                const glu::DataType             type                    = m_spec.inputs[0].varType.getBasicType();
                const glu::Precision    precision               = m_spec.inputs[0].varType.getPrecision();
                const int                               scalarSize              = glu::getDataTypeScalarSize(type);
-               const bool                              signedZero              = supportsSignedZero(precision);
-               const int                               mantissaBits    = getMinMantissaBits(precision);
  
                for (int compNdx = 0; compNdx < scalarSize; compNdx++)
                {
-                       const float             a                       = ((const float*)inputs[0])[compNdx];
-                       const float             b                       = ((const float*)inputs[1])[compNdx];
-                       const float             c                       = ((const float*)inputs[2])[compNdx];
-                       const float             res                     = ((const float*)outputs[0])[compNdx];
-                       const float             ref                     = a*b + c;
-                       const int               numBitsLost     = 1; // allow last bit to vary
-                       const deUint32  maxUlpDiff      = getMaxUlpDiffFromBits(de::max(0, mantissaBits-numBitsLost));
+                       const float                     a                       = ((const float*)inputs[0])[compNdx];
+                       const float                     b                       = ((const float*)inputs[1])[compNdx];
+                       const float                     c                       = ((const float*)inputs[2])[compNdx];
+                       const float                     res                     = ((const float*)outputs[0])[compNdx];
+                       const tcu::Interval     ref                     = fma(precision, a, b, c);
  
-                       const deUint32  ulpDiff         = signedZero ? getUlpDiff(res, ref) : getUlpDiffIgnoreZeroSign(res, ref);
-                       if (ulpDiff > maxUlpDiff)
+                       if (!ref.contains(res))
                        {
-                               m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << " with ULP threshold "
-                                                 << tcu::toHex(maxUlpDiff) << ", got ULP diff " << tcu::toHex(ulpDiff);
+                               m_failMsg << "Expected [" << compNdx << "] = " << ref;
                                return false;
                        }
                }