Пример #1
0
gmx_simd4_real_t
setSimd4RealFrom3R(real r0, real r1, real r2)
{
    std::vector<real> v(3);
    v[0] = r0;
    v[1] = r1;
    v[2] = r2;
    return vector2Simd4Real(v);
}
Пример #2
0
gmx_simd4_real_t
setSimd4RealFrom1R(real value)
{
    std::vector<real> v(GMX_SIMD4_WIDTH);
    for (int i = 0; i < GMX_SIMD4_WIDTH; i++)
    {
        v[i] = value;
    }
    return vector2Simd4Real(v);
}
Пример #3
0
/*! \brief Implementation routine to compare SIMD4 vs reference functions.
 *
 * \param refFuncExpr    Description of reference function expression
 * \param simd4FuncExpr  Description of SIMD function expression
 * \param refFunc        Reference math function pointer
 * \param simd4Func      SIMD math function pointer
 *
 * The function will be tested with the range and tolerances specified in
 * the SimdBaseTest class. You should not never call this function directly,
 * but use the macro GMX_EXPECT_SIMD4_FUNC_NEAR(refFunc,tstFunc) instead.
 */
::testing::AssertionResult
Simd4MathTest::compareSimd4MathFunction(const char * refFuncExpr, const char *simd4FuncExpr,
                                        real refFunc(real x),     gmx_simd4_real_t gmx_simdcall simd4Func(gmx_simd4_real_t x))
{
    std::vector<real>            vx(GMX_SIMD4_WIDTH);
    std::vector<real>            vref(GMX_SIMD4_WIDTH);
    std::vector<real>            vtst(GMX_SIMD4_WIDTH);
    real                         dx;
    gmx_int64_t                  ulpDiff, maxUlpDiff;
    real                         maxUlpDiffPos;
    real                         refValMaxUlpDiff, simdValMaxUlpDiff;
    bool                         eq, signOk;
    int                          i, iter;
    int                          niter   = s_nPoints/GMX_SIMD4_WIDTH;
    int                          npoints = niter*GMX_SIMD4_WIDTH;
#    ifdef GMX_DOUBLE
    union {
        double r; gmx_int64_t i;
    } conv0, conv1;
#    else
    union {
        float  r; gmx_int32_t i;
    } conv0, conv1;
#    endif

    maxUlpDiff = 0;
    dx         = (range_.second-range_.first)/npoints;

    for (iter = 0; iter < niter; iter++)
    {
        for (i = 0; i < GMX_SIMD4_WIDTH; i++)
        {
            vx[i]   = range_.first+dx*(iter*GMX_SIMD4_WIDTH+i);
            vref[i] = refFunc(vx[i]);
        }
        vtst  = simd4Real2Vector(simd4Func(vector2Simd4Real(vx)));

        for (i = 0, eq = true, signOk = true; i < GMX_SIMD4_WIDTH && eq == true; i++)
        {
            eq     = eq && ( fabs(vref[i]-vtst[i]) < absTol_ );
            signOk = signOk && ( vref[i]*vtst[i] >= 0 );
        }
        if (eq == true)
        {
            // Go to next point if everything within absolute tolerance
            continue;
        }
        else if (signOk == false)
        {
            return ::testing::AssertionFailure()
                   << "Failing SIMD4 math function comparison due to sign differences." << std::endl
                   << "Reference function: " << refFuncExpr << std::endl
                   << "Simd function:      " << simd4FuncExpr << std::endl
                   << "Test range is ( " << range_.first << " , " << range_.second << " ) " << std::endl
                   << "First sign difference around x=" << std::setprecision(20) << ::testing::PrintToString(vx) << std::endl
                   << "Ref values:   " << std::setprecision(20) << ::testing::PrintToString(vref) << std::endl
                   << "SIMD4 values: " << std::setprecision(20) << ::testing::PrintToString(vtst) << std::endl;
        }
        /* We replicate the trivial ulp differences comparison here rather than
         * calling the lower-level routine for comparing them, since this enables
         * us to run through the entire test range and report the largest deviation
         * without lots of extra glue routines.
         */
        for (i = 0; i < GMX_SIMD4_WIDTH; i++)
        {
            conv0.r = vref[i];
            conv1.r = vtst[i];
            ulpDiff = llabs(conv0.i-conv1.i);
            if (ulpDiff > maxUlpDiff)
            {
                maxUlpDiff        = ulpDiff;
                maxUlpDiffPos     = vx[i];
                refValMaxUlpDiff  = vref[i];
                simdValMaxUlpDiff = vtst[i];
            }
        }
    }

    if (maxUlpDiff <= ulpTol_)
    {
        return ::testing::AssertionSuccess();
    }
    else
    {
        return ::testing::AssertionFailure()
               << "Failing SIMD4 math function ulp comparison between " << refFuncExpr << " and " << simd4FuncExpr << std::endl
               << "Requested ulp tolerance: " << ulpTol_ << std::endl
               << "Requested abs tolerance: " << absTol_ << std::endl
               << "Largest Ulp difference occurs for x=" << std::setprecision(20) << maxUlpDiffPos << std::endl
               << "Ref  values:  " << std::setprecision(20) << refValMaxUlpDiff << std::endl
               << "SIMD4 values: " << std::setprecision(20) << simdValMaxUlpDiff << std::endl
               << "Ulp diff.:   " << std::setprecision(20) << maxUlpDiff << std::endl;
    }
}