// -*-C++-*- #include "vecmathlib.h" #include #include #include #include #include #include #include #include using namespace std; int num_errors = 0; template struct vecmathlib_test { typedef typename realvec_t::boolvec_t boolvec_t; typedef typename realvec_t::intvec_t intvec_t; typedef typename realvec_t::int_t int_t; typedef typename realvec_t::uint_t uint_t; typedef typename realvec_t::real_t real_t; // Short names for type casts typedef real_t R; typedef int_t I; typedef uint_t U; typedef realvec_t RV; typedef intvec_t IV; typedef boolvec_t BV; typedef vecmathlib::floatprops FP; typedef vecmathlib::mathfuncs MF; // Test each function with this many random values static const int imax = 10000; // Require (arbitrarily) that 3/4 of the digits are correct static real_t accuracy() { return pow(realvec_t::epsilon(), R(0.75)); } static realvec_t random(const real_t xmin, const real_t xmax) { realvec_t x; for (int i=0; i static string hex(const T x) { unsigned char cs[sizeof x]; memcpy(cs, &x, sizeof x); ostringstream buf; buf << "0x"; const char* const hexdigits = "0123456789abcdef"; const int n0 = is_big_endian() ? 0 : sizeof x - 1; const int dn = is_big_endian() ? +1 : -1; const int n1 = n0 + sizeof x * dn; for (int n=n0; n!=n1; n+=dn) { buf << hexdigits[cs[n]>>4] << hexdigits[cs[n]&15]; } return buf.str(); } static boolvec_t supported(realvec_t x) { return x==RV(0.0) || MF::vml_ieee_isnormal(x) #ifdef VML_HAVE_DENORMALS || MF::vml_ieee_isfinite(x) #endif #ifdef VML_HAVE_INF || MF::vml_ieee_isinf(x) #endif #ifdef VML_HAVE_NAN || MF::vml_ieee_isnan(x) #endif ; } static boolvec_t supported(intvec_t x) { return true; } static boolvec_t supported(boolvec_t x) { return true; } // Check load memory access static void check_mem(const char* const func, const realvec_t x, const real_t* const p, const realvec_t xold, const int mval) { realvec_t xwant; for (int i=0; i static void check_bool(const char* const func, const bool rstd, const bool rvml, const A x) { const bool dr = rstd ^ rvml; const bool isbad = dr; if (isbad) { ++ num_errors; cout << "Error in " << func << ":\n" << " x=" << x << " [" << hex(x) << "]\n" << " fstd(x)=" << rstd << " [" << hex(rstd) << "]\n" << " fvml(x)=" << rvml << " [" << hex(rvml) << "]\n" << " isbad(x)=" << isbad << "\n" << flush; } } template static void check_bool(const char* const func, const boolvec_t rstd, const boolvec_t rvml, const A x) { boolvec_t dr; bool isbad = false; for (int i=0; i static void check_bool(const char* const func, const boolvec_t rstd, const boolvec_t rvml, const A x, const B y) { boolvec_t dr; bool isbad = false; for (int i=0; i static void check_bool(const char* const func, bool fstd(typename A::scalar_t x), boolvec_t fvml(A x), const A x) { boolvec_t rstd; for (int i=0; i static void check_bool(const char* const func, bool fstd(typename A::scalar_t x, typename B::scalar_t y), boolvec_t fvml(A x, B y), const A x, const B y) { boolvec_t rstd; for (int i=0; i static void check_int(const char* const func, int_t fstd(typename A::scalar_t x), intvec_t fvml(A x), const A x) { intvec_t rstd; for (int i=0; i static void check_int(const char* const func, int_t fstd(typename A::scalar_t x, B y), intvec_t fvml(A x, B y), const A x, const B y) { intvec_t rstd; for (int i=0; i static void check_int(const char* const func, int_t fstd(typename A::scalar_t x, typename B::scalar_t y), intvec_t fvml(A x, B y), const A x, const B y) { intvec_t rstd; for (int i=0; i static void check_int(const char* const func, int_t fstd(typename A::scalar_t x, typename B::scalar_t y, typename C::scalar_t z), intvec_t fvml(A x, B y, C z), const A x, const B y, const C z) { intvec_t rstd; for (int i=0; i static void check_real(const char* const func, real_t fstd(typename A::scalar_t x), realvec_t fvml(A x), const A x, const real_t accuracy) { realvec_t rstd; for (int i=0; i realvec_t(accuracy) * scale; if (any(isbad)) { ++ num_errors; cout << setprecision(realvec_t::digits10+2) << "Error in " << func << "(" << x << " " << "[" << hex(x) << "]):\n" << " fstd(x)=" << rstd << " [" << hex(rstd) << "]\n" << " fvml(x)=" << rvml << " [" << hex(rvml) << "]\n" << " abs-error(x)=" << fabs(dr) << "\n" << " rel-error(x)=" << fabs(dr) / scale << "\n" << " isbad(x)=" << isbad << "\n" << " accuracy=" << accuracy << "\n" << flush; } } template static void check_real(const char* const func, real_t fstd(typename A::scalar_t x, B y), realvec_t fvml(A x, B y), const A x, const B y, const real_t accuracy) { realvec_t rstd; for (int i=0; i realvec_t(accuracy) * scale; if (any(isbad)) { ++ num_errors; cout << setprecision(realvec_t::digits10+2) << "Error in " << func << "(" << x << "," << y << " " << "[" << hex(x) << "],[" << hex(y) << "]):\n" << " fstd(x,y)=" << rstd << " [" << hex(rstd) << "]\n" << " fvml(x,y)=" << rvml << " [" << hex(rvml) << "]\n" << " abs-error(x,y)=" << fabs(dr) << "\n" << " rel-error(x,y)=" << fabs(dr) / scale << "\n" << " isbad(x,y)=" << isbad << "\n" << " accuracy=" << accuracy << "\n" << flush; } } template static void check_real(const char* const func, real_t fstd(typename A::scalar_t x, typename B::scalar_t y), realvec_t fvml(A x, B y), const A x, const B y, const real_t accuracy, const realvec_t offset = RV(0.0)) { realvec_t rstd; for (int i=0; ifabs(offset/RV(2.0)), rvml + copysign(offset, rstd-rvml), rvml); const realvec_t dr = rstd - rvml; const realvec_t scale = fabs(rstd) + fabs(rvml) + realvec_t(1.0); const boolvec_t isbad = supported(x) && supported(y) && supported(rstd) && fabs(dr) > realvec_t(accuracy) * scale; if (any(isbad)) { ++ num_errors; cout << setprecision(realvec_t::digits10+2) << "Error in " << func << "(" << x << "," << y << " " << "[" << hex(x) << "],[" << hex(y) << "]):\n" << " fstd(x,y)=" << rstd << " [" << hex(rstd) << "]\n" << " fvml(x,y)=" << rvml << " [" << hex(rvml) << "]\n" << " abs-error(x,y)=" << fabs(dr) << "\n" << " rel-error(x,y)=" << fabs(dr) / scale << "\n" << " isbad(x,y)=" << isbad << "\n" << " accuracy=" << accuracy << "\n" << flush; } } template static void check_real(const char* const func, real_t fstd(typename A::scalar_t x, typename B::scalar_t y, typename C::scalar_t z), realvec_t fvml(A x, B y, C z), const A x, const B y, C const z, const real_t accuracy) { realvec_t rstd; for (int i=0; i realvec_t(accuracy) * scale; if (any(isbad)) { ++ num_errors; cout << setprecision(realvec_t::digits10+2) << "Error in " << func << "(" << x << "," << y<< "," << z << " " << "[" << hex(x) << "," << hex(y) << "," << hex(z) << "]):\n" << " fstd(x,y,z)=" << rstd << " [" << hex(rstd) << "]\n" << " fvml(x,y,z)=" << rvml << " [" << hex(rvml) << "]\n" << " abs-error(x,y,z)=" << fabs(dr) << "\n" << " rel-error(x,y,z)=" << fabs(dr) / scale << "\n" << " isbad(x,y,z)=" << isbad << "\n" << " accuracy=" << accuracy << "\n" << flush; } } static real_t* align_mem(real_t* p) { const ptrdiff_t alignment = sizeof(realvec_t); p = (real_t*)((intptr_t(p) + alignment-1) & -alignment); assert(intptr_t(p) % alignment == 0); return p; } static string add_suffix(const char* str, int i) { ostringstream buf; buf << str << "." << i; return buf.str(); } static void test_mem() { cout << " testing loada loadu storea storeu (errors may lead to segfaults)...\n" << flush; const int n = 4; const int sz = realvec_t::size; const int nbytes = n*sz*sizeof(real_t); real_t* const x = align_mem(new real_t[(n+1)*sz]); real_t* const xnew = align_mem(new real_t[(n+1)*sz]); for (int i=0; i static T local_ifthen(bool b, T x, T y) { return b ? x : y; } static void test_bool() { cout << " testing boolean operations...\n" << flush; const boolvec_t bf = boolvec_t(false); const boolvec_t bt = boolvec_t(true); for (int i=0; i, (intvec_t(*)(boolvec_t,intvec_t,intvec_t))vecmathlib::ifthen, x, IV(I(1)), IV(I(2))); check_real("ifthen(real)", local_ifthen, ((realvec_t(*)(boolvec_t,realvec_t,realvec_t)) vecmathlib::ifthen), x, RV(1.0), RV(2.0), R(0.0)); } for (int n=0; n<(1<::min(); const int_t int_max = std::numeric_limits::max(); const int_t values[] = { 0, 1, 2, 3, -1, -2, -3, int_min, int_min+1, int_min+2, int_min+3, int_max, int_max-1, int_max-2, int_max-3, }; const int nvalues = sizeof values / sizeof *values; for (int i=0; i("convert_bool(int)", local_convert_bool, vecmathlib::convert_bool, x); check_int("convert_int(bool)", local_convert_int, vecmathlib::convert_int, b); check_int("+", local_pos, local_pos, x); check_int("-", local_neg, local_neg, x); check_int("~", local_not, local_not, x); check_int("+", local_add, local_add, x, y); check_int("-", local_sub, local_sub, x, y); check_int("&", local_and, local_and, x, y); check_int("|", local_or, local_or, x, y); check_int("^", local_xor, local_xor, x, y); const int_t bits = 8*sizeof(int_t); check_int("lsr", local_lsr, vecmathlib::lsr, x, y[0] & (bits-1)); check_int(">>", local_sr, local_srs, x, y[0] & (bits-1)); check_int("<<", local_sl, local_sls, x, y[0] & (bits-1)); check_int("lsr", local_lsr, vecmathlib::lsr, x, y & IV(bits-1)); check_int(">>", local_sr, local_sr, x, y & IV(bits-1)); check_int("<<", local_sl, local_sl, x, y & IV(bits-1)); check_bool("==", local_eq, local_veq, x, y); check_bool("!=", local_ne, local_vne, x, y); check_bool("<", local_lt, local_vlt, x, y); check_bool("<=", local_le, local_vle, x, y); check_bool(">", local_gt, local_vgt, x, y); check_bool(">=", local_ge, local_vge, x, y); } } static void test_real() { cout << " testing real operations...\n" << flush; realvec_t r0 = realvec_t(0.0); realvec_t r1 = realvec_t(1.0); for (int i=0; i "int_t" static int_t local_ilogb(real_t x) { int r = std::ilogb(x); if (r==FP_ILOGB0) return std::numeric_limits::min(); if (r==FP_ILOGBNAN) return std::numeric_limits::max(); return r; } static real_t local_ldexp(real_t x, int_t n) { return ldexp(x, n); } static void test_fabs() { cout << " testing + - + - * == != < <= > >= copysign fabs fdim fma fmax fmin ilogb isfinite isinf isnan isnormal ldexp signbit...\n" << flush; const real_t eps = FP::epsilon(); const real_t int_min = R(std::numeric_limits::min()); const real_t int_max = R(std::numeric_limits::max()); const real_t uint_min = R(std::numeric_limits::min()); const real_t uint_max = R(std::numeric_limits::max()); const real_t values[] = { R(+0.0), R(+0.1), R(+0.9), R(+1.0), R(+1.1), R(-0.0), R(-0.1), R(-0.9), R(-1.0), R(-1.1), R(+0.0)+eps, R(+0.1)+eps, R(+0.9)+eps, R(+1.0)+eps, R(+1.1)+eps, R(-0.0)+eps, R(-0.1)+eps, R(-0.9)+eps, R(-1.0)+eps, R(-1.1)+eps, R(+0.0)-eps, R(+0.1)-eps, R(+0.9)-eps, R(+1.0)-eps, R(+1.1)-eps, R(-0.0)-eps, R(-0.1)-eps, R(-0.9)-eps, R(-1.0)-eps, R(-1.1)-eps, #ifdef VML_HAVE_DENORMALS +FP::min(), +FP::min()*(R(1.0)+eps), +FP::min()*R(2.0), -FP::min(), -FP::min()*(R(1.0)+eps), -FP::min()*R(2.0), #endif +FP::max(), +FP::max()*(R(1.0)-eps), +FP::max()*(R(1.0)-R(2.0)*eps), -FP::max(), -FP::max()*(R(1.0)-eps), -FP::max()*(R(1.0)-R(2.0)*eps), +R(0.5)*FP::max(), +R(0.5)*FP::max()*(R(1.0)+eps), -R(0.5)*FP::max(), -R(0.5)*FP::max()*(R(1.0)+eps), #ifdef VML_HAVE_INF +R(1.0/0.0), // +FP::infinity() -R(1.0/0.0), // -FP::infinity() #endif #ifdef VML_HAVE_NAN R(0.0/0.0), // FP::quite_NaN() #endif +int_min, +int_max, +uint_min, +uint_max, -int_min, -int_max, -uint_min, -uint_max, +int_min+R(0.1), +int_max+R(0.1), +uint_min+R(0.1), +uint_max+R(0.1), -int_min+R(0.1), -int_max+R(0.1), -uint_min+R(0.1), -uint_max+R(0.1), +int_min-R(0.1), +int_max-R(0.1), +uint_min-R(0.1), +uint_max-R(0.1), -int_min-R(0.1), -int_max-R(0.1), -uint_min-R(0.1), -uint_max-R(0.1), +int_min+R(1.0), +int_max+R(1.0), +uint_min+R(1.0), +uint_max+R(1.0), -int_min+R(1.0), -int_max+R(1.0), -uint_min+R(1.0), -uint_max+R(1.0), +int_min-R(1.0), +int_max-R(1.0), +uint_min-R(1.0), +uint_max-R(1.0), -int_min-R(1.0), -int_max-R(1.0), -uint_min-R(1.0), -uint_max-R(1.0), -R(443.9999425), }; const int nvalues = sizeof values / sizeof *values; for (int i=0; i<8*nvalues+imax; ++i) { const realvec_t x = i<8*nvalues && i&1 ? RV(values[i/8]) : random(R(-10.0), R(+10.0)); const realvec_t y = i<8*nvalues && i&2 ? RV(values[i/8]) : random(R(-10.0), R(+10.0)); const realvec_t z = i<8*nvalues && i&4 ? RV(values[i/8]) : random(R(-10.0), R(+10.0)); const intvec_t n = random(int_t(-10), int_t(+10)); check_real("+", local_pos, local_pos, x, R(0.0)); check_real("-", local_neg, local_neg, x, R(0.0)); check_real("+", local_add, local_add, x, y, R(0.0)); check_real("-", local_sub, local_sub, x, y, R(0.0)); check_real("*", local_mul, local_mul, x, y, R(0.0)); check_bool("==", local_eq, local_veq, x, y); check_bool("!=", local_ne, local_vne, x, y); check_bool("<", local_lt, local_vlt, x, y); check_bool("<=", local_le, local_vle, x, y); check_bool(">", local_gt, local_vgt, x, y); check_bool(">=", local_ge, local_vge, x, y); check_real("copysign", std::copysign, vecmathlib::copysign, x, y, 0.0); check_real("fabs", std::fabs, vecmathlib::fabs, x, 0.0); check_real("fdim", std::fdim, vecmathlib::fdim, x, y, accuracy()); check_real("fma", std::fma, vecmathlib::fma, x, y, z, R(2.0)*accuracy()); check_real("fmax", std::fmax, vecmathlib::fmax, x, y, 0.0); check_real("fmin", std::fmin, vecmathlib::fmin, x, y, 0.0); check_int("ilogb", local_ilogb, (intvec_t(*)(realvec_t))vecmathlib::ilogb, x); #if defined VML_HAVE_INF && defined VML_HAVE_NAN check_bool("isfinite", std::isfinite, vecmathlib::isfinite, x); #endif #ifdef VML_HAVE_INF check_bool("isinf", std::isinf, vecmathlib::isinf, x); #endif #ifdef VML_HAVE_NAN check_bool("isnan", std::isnan, vecmathlib::isnan, x); #endif #ifdef VML_HAVE_DENORMALS check_bool("isnormal", std::isnormal, vecmathlib::isnormal, x); #endif check_real("ldexp", local_ldexp, vecmathlib::ldexp, x, n[0], 0.0); check_real("ldexp", local_ldexp, vecmathlib::ldexp, x, n, 0.0); check_bool("signbit", std::signbit, vecmathlib::signbit, x); } } static void test_convert() { cout << " testing ceil convert_float convert_int floor rint round trunc...\n" << flush; const real_t eps = FP::epsilon(); const real_t int_min = R(std::numeric_limits::min()); const real_t int_max = R(std::numeric_limits::max()); const real_t uint_min = R(std::numeric_limits::min()); const real_t uint_max = R(std::numeric_limits::max()); const real_t mantissa_max = (U(1) << (FP::mantissa_bits+1)) - U(1); const real_t real_max = (((U(1) << (FP::mantissa_bits+1)) - U(1)) << (FP::exponent_bits-1)) + (U(1) << (FP::exponent_bits-1)) - U(1); const real_t values[] = { R(+0.0), R(+0.1), R(+0.9), R(+1.0), R(+1.1), R(-0.0), R(-0.1), R(-0.9), R(-1.0), R(-1.1), R(+0.0)+eps, R(+0.1)+eps, R(+0.9)+eps, R(+1.0)+eps, R(+1.1)+eps, R(-0.0)+eps, R(-0.1)+eps, R(-0.9)+eps, R(-1.0)+eps, R(-1.1)+eps, R(+0.0)-eps, R(+0.1)-eps, R(+0.9)-eps, R(+1.0)-eps, R(+1.1)-eps, R(-0.0)-eps, R(-0.1)-eps, R(-0.9)-eps, R(-1.0)-eps, R(-1.1)-eps, #ifdef VML_HAVE_DENORMALS +FP::min(), +FP::min()*(R(1.0)+eps), +FP::min()*R(2.0), -FP::min(), -FP::min()*(R(1.0)+eps), -FP::min()*R(2.0), #endif +FP::max(), +FP::max()*(R(1.0)-eps), +FP::max()*(R(1.0)-R(2.0)*eps), -FP::max(), -FP::max()*(R(1.0)-eps), -FP::max()*(R(1.0)-R(2.0)*eps), +R(0.5)*FP::max(), +R(0.5)*FP::max()*(R(1.0)+eps), -R(0.5)*FP::max(), -R(0.5)*FP::max()*(R(1.0)+eps), #ifdef VML_HAVE_INF +R(1.0/0.0), // +FP::infinity() -R(1.0/0.0), // -FP::infinity() #endif #ifdef VML_HAVE_NAN R(0.0/0.0), // FP::quite_NaN() #endif +int_min, +int_max, +uint_min, +uint_max, -int_min, -int_max, -uint_min, -uint_max, +int_min+R(0.1), +int_max+R(0.1), +uint_min+R(0.1), +uint_max+R(0.1), -int_min+R(0.1), -int_max+R(0.1), -uint_min+R(0.1), -uint_max+R(0.1), +int_min-R(0.1), +int_max-R(0.1), +uint_min-R(0.1), +uint_max-R(0.1), -int_min-R(0.1), -int_max-R(0.1), -uint_min-R(0.1), -uint_max-R(0.1), +int_min+R(1.0), +int_max+R(1.0), +uint_min+R(1.0), +uint_max+R(1.0), -int_min+R(1.0), -int_max+R(1.0), -uint_min+R(1.0), -uint_max+R(1.0), +int_min-R(1.0), +int_max-R(1.0), +uint_min-R(1.0), +uint_max-R(1.0), -int_min-R(1.0), -int_max-R(1.0), -uint_min-R(1.0), -uint_max-R(1.0), +mantissa_max, +mantissa_max-R(1.0), +mantissa_max+R(1.0), -mantissa_max, -mantissa_max-R(1.0), -mantissa_max+R(1.0), +real_max, +real_max-R(1.0), +real_max+R(1.0), -real_max, -real_max-R(1.0), -real_max+R(1.0), -R(443.9999425), }; const int nvalues = sizeof values / sizeof *values; for (int i=0; i::min() / 2, // avoid overflow std::numeric_limits::max() / 2); const realvec_t fn1 = vecmathlib::convert_float(n1); const realvec_t fn2 = vecmathlib::convert_float(n2); const realvec_t fn1h = vecmathlib::convert_float(n1) * RV(0.25); const realvec_t fn2h = vecmathlib::convert_float(n2) * RV(0.25); check_real("convert_float", FP::convert_float, vecmathlib::convert_float, n1, accuracy()); check_real("convert_float", FP::convert_float, vecmathlib::convert_float, n2, accuracy()); // Note: RV(int_max) > int_max due to rounding if (all(x >= RV(int_min) && x < RV(int_max))) { check_int("convert_int", FP::convert_int, vecmathlib::convert_int, x); } check_real("ceil", std::ceil, vecmathlib::ceil, x, accuracy()); check_real("ceil", std::ceil, vecmathlib::ceil, fn1, accuracy()); check_real("ceil", std::ceil, vecmathlib::ceil, fn2, accuracy()); check_real("ceil", std::ceil, vecmathlib::ceil, fn1h, accuracy()); check_real("ceil", std::ceil, vecmathlib::ceil, fn2h, accuracy()); check_real("floor", std::floor, vecmathlib::floor, x, accuracy()); check_real("floor", std::floor, vecmathlib::floor, fn1, accuracy()); check_real("floor", std::floor, vecmathlib::floor, fn2, accuracy()); check_real("floor", std::floor, vecmathlib::floor, fn1h, accuracy()); check_real("floor", std::floor, vecmathlib::floor, fn2h, accuracy()); check_real("rint", std::rint, vecmathlib::rint, x, accuracy()); check_real("rint", std::rint, vecmathlib::rint, fn1, accuracy()); check_real("rint", std::rint, vecmathlib::rint, fn2, accuracy()); check_real("rint", std::rint, vecmathlib::rint, fn1h, accuracy()); check_real("rint", std::rint, vecmathlib::rint, fn2h, accuracy()); check_real("round", std::round, vecmathlib::round, x, accuracy()); check_real("round", std::round, vecmathlib::round, fn1, accuracy()); check_real("round", std::round, vecmathlib::round, fn2, accuracy()); check_real("round", std::round, vecmathlib::round, fn1h, accuracy()); check_real("round", std::round, vecmathlib::round, fn2h, accuracy()); check_real("trunc", std::trunc, vecmathlib::trunc, x, accuracy()); check_real("trunc", std::trunc, vecmathlib::trunc, fn1, accuracy()); check_real("trunc", std::trunc, vecmathlib::trunc, fn2, accuracy()); check_real("trunc", std::trunc, vecmathlib::trunc, fn1h, accuracy()); check_real("trunc", std::trunc, vecmathlib::trunc, fn2h, accuracy()); } } static void test_asin() { cout << " testing asin acos atan atan2...\n" << flush; for (int i=0; i("asin", std::asin, vecmathlib::asin, x, accuracy()); check_real("acos", std::acos, vecmathlib::acos, x, accuracy()); } for (int i=0; i("atan", std::atan, vecmathlib::atan, x, accuracy()); check_real("atan2", std::atan2, vecmathlib::atan2, x, y, accuracy()); } } static void test_asinh() { cout << " testing asinh acosh atanh...\n" << flush; for (int i=0; i("asinh", std::asinh, vecmathlib::asinh, x, accuracy()); } for (int i=0; i("acosh", std::acosh, vecmathlib::acosh, x, accuracy()); } for (int i=0; i("atanh", std::atanh, vecmathlib::atanh, x, accuracy()); } } static real_t local_exp10(real_t x) { return pow(R(10.0), x); } static void test_exp() { cout << " testing exp exp10 exp2 expm1...\n" << flush; for (int i=0; i("exp", std::exp, vecmathlib::exp, x, accuracy()); check_real("exp10", local_exp10, vecmathlib::exp10, x, accuracy()); check_real("exp2", std::exp2, vecmathlib::exp2, x, accuracy()); check_real("expm1", std::expm1, vecmathlib::expm1, x, accuracy()); } } static void test_log() { cout << " testing log log10 log1p log2...\n" << flush; for (int i=0; i("log", std::log, vecmathlib::log, x, accuracy()); check_real("log10", std::log10, vecmathlib::log10, x, accuracy()); check_real("log1p", std::log1p, vecmathlib::log1p, x, accuracy()); check_real("log2", std::log2, vecmathlib::log2, x, accuracy()); } } static void test_pow() { cout << " testing pow...\n" << flush; for (int i=0; i("pow(0,y)", std::pow, vecmathlib::pow, RV(0.0), ya, accuracy()); check_real("pow(x,0)", std::pow, vecmathlib::pow, x, RV(0.0), accuracy()); // just to check check_real("log(x)", std::log, vecmathlib::log, x, accuracy()); check_real("pow(x,y)", std::pow, vecmathlib::pow, x, y, accuracy()); check_real("pow(-x,n)", std::pow, vecmathlib::pow, -x, fn, accuracy()); } } static real_t local_rcp(real_t x) { return R(1.0)/x; } static void test_rcp() { cout << " testing / fmod rcp remainder...\n" << flush; for (int i=0; i("/", local_div, local_div, x, y, accuracy()); check_real("rcp", local_rcp, vecmathlib::rcp, x, accuracy()); check_real("fmod(x,y)", std::fmod, vecmathlib::fmod, x, y, 2.0*accuracy()); check_real("fmod(x,m)", std::fmod, vecmathlib::fmod, x, fm, 2.0*accuracy()); check_real("fmod(n,y)", std::fmod, vecmathlib::fmod, fn, y, 2.0*accuracy()); check_real("remainder(x,y)", std::remainder, vecmathlib::remainder, x, y, R(2.0)*accuracy()); check_real("remainder(x,m)", std::remainder, vecmathlib::remainder, x, fm, R(2.0)*accuracy(), fm); check_real("remainder(n,y)", std::remainder, vecmathlib::remainder, fn, y, R(2.0)*accuracy()); } } static void test_sin() { cout << " testing cos sin tan...\n" << flush; for (int i=0; i("sin", std::sin, vecmathlib::sin, x, accuracy()); check_real("cos", std::cos, vecmathlib::cos, x, accuracy()); } for (int i=0; i("tan", std::tan, vecmathlib::tan, x, R(100.0)*accuracy()); } } static void test_sinh() { cout << " testing cosh sinh tanh...\n" << flush; for (int i=0; i("sinh", std::sinh, vecmathlib::sinh, x, accuracy()); check_real("cosh", std::cosh, vecmathlib::cosh, x, accuracy()); check_real("tanh", std::tanh, vecmathlib::tanh, x, accuracy()); } } static real_t local_rsqrt(real_t x) { return R(1.0)/sqrt(x); } static void test_sqrt() { cout << " testing cbrt hypot rsqrt sqrt...\n" << flush; for (int i=0; i("cbrt", std::cbrt, vecmathlib::cbrt, x, accuracy()); check_real("hypot", std::hypot, vecmathlib::hypot, y, z, accuracy()); check_real("rsqrt", local_rsqrt, vecmathlib::rsqrt, x, accuracy()); check_real("sqrt", std::sqrt, vecmathlib::sqrt, x, accuracy()); } } static void test() { cout << "\n" << "Testing math functions for type " << realvec_t::name() << ":\n"; test_bool(); test_int(); test_real(); test_mem(); // Test "basic" functions first test_fabs(); test_convert(); #warning "TODO" // test_rcp(); // test_sqrt(); // test_exp(); // test_log(); // test_pow(); // test_sin(); // test_sinh(); // test_asin(); // test_asinh(); } }; int main(int argc, char** argv) { using namespace vecmathlib; cout << "Testing math functions:\n" << flush; cout << "Vecmathlib configuration: [conf" #ifdef VML_DEBUG "-DEBUG" #endif #ifdef __ALTIVEC__ "-Altivec" #endif #ifdef __VSX__ "-VSX" #endif #if defined __bgq__ && defined __VECTOR4DOUBLE__ "-QPX" #endif #ifdef __SSE2__ "-SSE2" #endif #ifdef __SSE3__ "-SSE3" #endif #ifdef __SSE4_1__ "-SSE4.1" #endif #ifdef __SSE4a__ "-SSE4a" #endif #ifdef __AVX__ "-AVX" #endif "]\n"; #warning "TODO" // vecmathlib_test>::test(); // // vecmathlib_test>::test(); // vecmathlib_test>::test(); // #ifdef VECMATHLIB_HAVE_VEC_FLOAT_1 // vecmathlib_test>::test(); // #endif // vecmathlib_test>::test(); // // vecmathlib_test>::test(); // vecmathlib_test>::test(); // #ifdef VECMATHLIB_HAVE_VEC_FLOAT_4 // vecmathlib_test>::test(); // #endif // #ifdef VECMATHLIB_HAVE_VEC_FLOAT_8 // vecmathlib_test>::test(); // // vecmathlib_test>::test(); // vecmathlib_test>::test(); // vecmathlib_test>::test(); // #endif // // vecmathlib_test>::test(); // // vecmathlib_test>::test(); // vecmathlib_test>::test(); // #ifdef VECMATHLIB_HAVE_VEC_DOUBLE_1 // vecmathlib_test>::test(); // #endif // vecmathlib_test>::test(); // // vecmathlib_test>::test(); // vecmathlib_test>::test(); // #ifdef VECMATHLIB_HAVE_VEC_DOUBLE_2 // vecmathlib_test>::test(); // #endif #ifdef VECMATHLIB_HAVE_VEC_DOUBLE_4 // vecmathlib_test>::test(); // // vecmathlib_test>::test(); // vecmathlib_test>::test(); vecmathlib_test>::test(); #endif cout << "\n"; if (num_errors == 0) { cout << "SUCCESS"; } else { cout << "FAILURE"; } cout << ": " << num_errors << " errors found\n" << flush; return num_errors == 0 ? 0 : 1; }