From 93001e99a4f0a8648a59530d89cbc41f345321cc Mon Sep 17 00:00:00 2001 From: Jeremy Kemp Date: Mon, 10 Aug 2020 13:19:26 +0100 Subject: [PATCH] Bruteforce - embedded, relaxed ulp requirements (#839) * Add embedded profile ULP requiremnts for relaxed tests. * Fixed exp relaxed ULP for embedded. * Added a utility function, getAllowedUlpError, for determining FP32 ULP. * Collection of requested changes from PR. Re-named float_embedded_relaxed_ulps -> relaxed_embedded_error. Re-ordered Func struct members. --- .../math_brute_force/FunctionList.cpp | 354 ++++++++++++------ .../math_brute_force/FunctionList.h | 3 +- test_conformance/math_brute_force/Utility.cpp | 32 +- test_conformance/math_brute_force/Utility.h | 7 +- test_conformance/math_brute_force/binary.cpp | 3 +- .../math_brute_force/binaryOperator.cpp | 4 +- test_conformance/math_brute_force/unary.cpp | 10 +- .../math_brute_force/unary_two_results.cpp | 8 +- 8 files changed, 286 insertions(+), 135 deletions(-) diff --git a/test_conformance/math_brute_force/FunctionList.cpp b/test_conformance/math_brute_force/FunctionList.cpp index 30ee551f..0aa35508 100644 --- a/test_conformance/math_brute_force/FunctionList.cpp +++ b/test_conformance/math_brute_force/FunctionList.cpp @@ -1,6 +1,6 @@ // // Copyright (c) 2017 The Khronos Group Inc. -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -27,10 +27,30 @@ // Only use ulps information in spir test #ifdef FUNCTION_LIST_ULPS_ONLY -#define ENTRY( _name, _ulp, _embedded_ulp, _rmode, _type ) { STRINGIFY(_name), STRINGIFY(_name), {NULL}, {NULL}, {NULL}, _ulp, _ulp, _embedded_ulp, INFINITY, _rmode, RELAXED_OFF, _type } -#define ENTRY_EXT( _name, _ulp, _embedded_ulp, _relaxed_ulp, _rmode, _type ) { STRINGIFY(_name), STRINGIFY(_name), {NULL}, {NULL}, {NULL}, _ulp, _ulp, _embedded_ulp, _relaxed_ulp, _rmode, RELAXED_ON, _type } -#define HALF_ENTRY( _name, _ulp, _embedded_ulp, _rmode, _type ) { "half_" STRINGIFY(_name), "half_" STRINGIFY(_name), {NULL}, {NULL}, {NULL}, _ulp, _ulp, _embedded_ulp, INFINITY, _rmode, RELAXED_OFF, _type } -#define OPERATOR_ENTRY(_name, _operator, _ulp, _embedded_ulp, _rmode, _type) { STRINGIFY(_name), _operator, {NULL}, {NULL}, {NULL}, _ulp, _ulp, _embedded_ulp, INFINITY, _rmode, RELAXED_OFF, _type } +#define ENTRY(_name, _ulp, _embedded_ulp, _rmode, _type) \ + { \ + STRINGIFY(_name), STRINGIFY(_name), { NULL }, { NULL }, { NULL }, \ + _ulp, _ulp, _embedded_ulp, INFINITY, INFINITY, _rmode, \ + RELAXED_OFF, _type \ + } +#define ENTRY_EXT(_name, _ulp, _embedded_ulp, _relaxed_ulp, _rmode, _type, \ + _relaxed_embedded_ulp) \ + { \ + STRINGIFY(_name), STRINGIFY(_name), { NULL }, { NULL }, { NULL }, \ + _ulp, _ulp, _embedded_ulp, _relaxed_ulp, _relaxed_embedded_ulp, \ + _rmode, RELAXED_ON, _type \ + } +#define HALF_ENTRY(_name, _ulp, _embedded_ulp, _rmode, _type) \ + { \ + "half_" STRINGIFY(_name), "half_" STRINGIFY(_name), { NULL }, \ + { NULL }, { NULL }, _ulp, _ulp, _embedded_ulp, INFINITY, INFINITY, \ + _rmode, RELAXED_OFF, _type \ + } +#define OPERATOR_ENTRY(_name, _operator, _ulp, _embedded_ulp, _rmode, _type) \ + { \ + STRINGIFY(_name), _operator, { NULL }, { NULL }, { NULL }, _ulp, _ulp, \ + _embedded_ulp, INFINITY, INFINITY, _rmode, RELAXED_OFF, _type \ + } #define unaryF NULL #define i_unaryF NULL #define unaryF_u NULL @@ -54,10 +74,33 @@ #else // FUNCTION_LIST_ULPS_ONLY -#define ENTRY( _name, _ulp, _embedded_ulp, _rmode, _type ) { STRINGIFY(_name), STRINGIFY(_name), {(void*)reference_##_name}, {(void*)reference_##_name##l}, {(void*)reference_##_name}, _ulp, _ulp, _embedded_ulp, INFINITY, _rmode, RELAXED_OFF, _type } -#define ENTRY_EXT( _name, _ulp, _embedded_ulp, _relaxed_ulp, _rmode, _type ) { STRINGIFY(_name), STRINGIFY(_name), {(void*)reference_##_name}, {(void*)reference_##_name##l}, {(void*)reference_##relaxed_##_name}, _ulp, _ulp, _embedded_ulp, _relaxed_ulp, _rmode, RELAXED_ON, _type } -#define HALF_ENTRY( _name, _ulp, _embedded_ulp, _rmode, _type ) { "half_" STRINGIFY(_name), "half_" STRINGIFY(_name), {(void*)reference_##_name}, {NULL}, {NULL}, _ulp, _ulp, _embedded_ulp, INFINITY, _rmode, RELAXED_OFF, _type } -#define OPERATOR_ENTRY(_name, _operator, _ulp, _embedded_ulp, _rmode, _type) { STRINGIFY(_name), _operator, {(void*)reference_##_name}, {(void*)reference_##_name##l}, {NULL}, _ulp, _ulp, _embedded_ulp, INFINITY, _rmode, RELAXED_OFF, _type } +#define ENTRY(_name, _ulp, _embedded_ulp, _rmode, _type) \ + { \ + STRINGIFY(_name), STRINGIFY(_name), { (void*)reference_##_name }, \ + { (void*)reference_##_name##l }, { (void*)reference_##_name }, \ + _ulp, _ulp, _embedded_ulp, INFINITY, INFINITY, _rmode, \ + RELAXED_OFF, _type \ + } +#define ENTRY_EXT(_name, _ulp, _embedded_ulp, _relaxed_ulp, _rmode, _type, \ + _relaxed_embedded_ulp) \ + { \ + STRINGIFY(_name), STRINGIFY(_name), { (void*)reference_##_name }, \ + { (void*)reference_##_name##l }, \ + { (void*)reference_##relaxed_##_name }, _ulp, _ulp, _embedded_ulp, \ + _relaxed_ulp, _relaxed_embedded_ulp, _rmode, RELAXED_ON, _type \ + } +#define HALF_ENTRY(_name, _ulp, _embedded_ulp, _rmode, _type) \ + { \ + "half_" STRINGIFY(_name), "half_" STRINGIFY(_name), \ + { (void*)reference_##_name }, { NULL }, { NULL }, _ulp, _ulp, \ + _embedded_ulp, INFINITY, INFINITY, _rmode, RELAXED_OFF, _type \ + } +#define OPERATOR_ENTRY(_name, _operator, _ulp, _embedded_ulp, _rmode, _type) \ + { \ + STRINGIFY(_name), _operator, { (void*)reference_##_name }, \ + { (void*)reference_##_name##l }, { NULL }, _ulp, _ulp, \ + _embedded_ulp, INFINITY, INFINITY, _rmode, RELAXED_OFF, _type \ + } extern const vtbl _unary; // float foo( float ) extern const vtbl _unary_u; // float foo( uint ), double foo( ulong ) @@ -91,115 +134,192 @@ extern const vtbl _mad_tbl; // float mad( float, float, float ) #endif // FUNCTION_LIST_ULPS_ONLY -const Func functionList[] = { - ENTRY( acos, 4.0f, 4.0f, FTZ_OFF, unaryF), - ENTRY( acosh, 4.0f, 4.0f, FTZ_OFF, unaryF), - ENTRY( acospi, 5.0f, 5.0f, FTZ_OFF, unaryF), - ENTRY( asin, 4.0f, 4.0f, FTZ_OFF, unaryF), - ENTRY( asinh, 4.0f, 4.0f, FTZ_OFF, unaryF), - ENTRY( asinpi, 5.0f, 5.0f, FTZ_OFF, unaryF), - ENTRY( atan, 5.0f, 5.0f, FTZ_OFF, unaryF), - ENTRY( atanh, 5.0f, 5.0f, FTZ_OFF, unaryF), - ENTRY( atanpi, 5.0f, 5.0f, FTZ_OFF, unaryF), - ENTRY( atan2, 6.0f, 6.0f, FTZ_OFF, binaryF), - ENTRY( atan2pi, 6.0f, 6.0f, FTZ_OFF, binaryF), - ENTRY( cbrt, 2.0f, 4.0f, FTZ_OFF, unaryF), - ENTRY( ceil, 0.0f, 0.0f, FTZ_OFF, unaryF), - ENTRY( copysign, 0.0f, 0.0f, FTZ_OFF, binaryF), - ENTRY_EXT( cos, 4.0f, 4.0f, 0.00048828125f, FTZ_OFF, unaryF), //relaxed ulp 2^-11 - ENTRY( cosh, 4.0f, 4.0f, FTZ_OFF, unaryF), - ENTRY( cospi, 4.0f, 4.0f, FTZ_OFF, unaryF), -// ENTRY( erfc, 16.0f, 16.0f, FTZ_OFF, unaryF), //disabled for 1.0 due to lack of reference implementation -// ENTRY( erf, 16.0f, 16.0f, FTZ_OFF, unaryF), //disabled for 1.0 due to lack of reference implementation - ENTRY_EXT( exp, 3.0f, 4.0f, 3.0f, FTZ_OFF, unaryF), //relaxed error is actually overwritten in unary.c as it is 3+floor(fabs(2*x)) - ENTRY_EXT( exp2, 3.0f, 4.0f, 3.0f, FTZ_OFF, unaryF), //relaxed error is actually overwritten in unary.c as it is 3+floor(fabs(2*x)) - ENTRY_EXT( exp10, 3.0f, 4.0f, 8192.0f, FTZ_OFF, unaryF), //relaxed error is actually overwritten in unary.c as it is 3+floor(fabs(2*x)) in derived mode, - // in non-derived mode it uses the ulp error for half_exp10. - ENTRY( expm1, 3.0f, 4.0f, FTZ_OFF, unaryF), - ENTRY( fabs, 0.0f, 0.0f, FTZ_OFF, unaryF), - ENTRY( fdim, 0.0f, 0.0f, FTZ_OFF, binaryF), - ENTRY( floor, 0.0f, 0.0f, FTZ_OFF, unaryF), - ENTRY( fma, 0.0f, 0.0f, FTZ_OFF, ternaryF), - ENTRY( fmax, 0.0f, 0.0f, FTZ_OFF, binaryF), - ENTRY( fmin, 0.0f, 0.0f, FTZ_OFF, binaryF), - ENTRY( fmod, 0.0f, 0.0f, FTZ_OFF, binaryF ), - ENTRY( fract, 0.0f, 0.0f, FTZ_OFF, unaryF_two_results), - ENTRY( frexp, 0.0f, 0.0f, FTZ_OFF, unaryF_two_results_i), - ENTRY( hypot, 4.0f, 4.0f, FTZ_OFF, binaryF), - ENTRY( ilogb, 0.0f, 0.0f, FTZ_OFF, i_unaryF), - ENTRY( isequal, 0.0f, 0.0f, FTZ_OFF, macro_binaryF), - ENTRY( isfinite, 0.0f, 0.0f, FTZ_OFF, macro_unaryF), - ENTRY( isgreater, 0.0f, 0.0f, FTZ_OFF, macro_binaryF), - ENTRY( isgreaterequal, 0.0f, 0.0f, FTZ_OFF, macro_binaryF), - ENTRY( isinf, 0.0f, 0.0f, FTZ_OFF, macro_unaryF), - ENTRY( isless, 0.0f, 0.0f, FTZ_OFF, macro_binaryF), - ENTRY( islessequal, 0.0f, 0.0f, FTZ_OFF, macro_binaryF), - ENTRY( islessgreater, 0.0f, 0.0f, FTZ_OFF, macro_binaryF), - ENTRY( isnan, 0.0f, 0.0f, FTZ_OFF, macro_unaryF), - ENTRY( isnormal, 0.0f, 0.0f, FTZ_OFF, macro_unaryF), - ENTRY( isnotequal, 0.0f, 0.0f, FTZ_OFF, macro_binaryF), - ENTRY( isordered, 0.0f, 0.0f, FTZ_OFF, macro_binaryF), - ENTRY( isunordered, 0.0f, 0.0f, FTZ_OFF, macro_binaryF), - ENTRY( ldexp, 0.0f, 0.0f, FTZ_OFF, binaryF_i), - ENTRY( lgamma, INFINITY, INFINITY, FTZ_OFF, unaryF), - ENTRY( lgamma_r, INFINITY, INFINITY, FTZ_OFF, unaryF_two_results_i), - ENTRY_EXT( log, 3.0f, 4.0f, 4.76837158203125e-7f, FTZ_OFF, unaryF), //relaxed ulp 2^-21 - ENTRY_EXT( log2, 3.0f, 4.0f, 4.76837158203125e-7f, FTZ_OFF, unaryF), //relaxed ulp 2^-21 - ENTRY( log10, 3.0f, 4.0f, FTZ_OFF, unaryF), - ENTRY( log1p, 2.0f, 4.0f, FTZ_OFF, unaryF), - ENTRY( logb, 0.0f, 0.0f, FTZ_OFF, unaryF), - ENTRY_EXT( mad, INFINITY, INFINITY, INFINITY, FTZ_OFF, mad_function), //in fast-relaxed-math mode it has to be either exactly rounded fma or exactly rounded a*b+c - ENTRY( maxmag, 0.0f, 0.0f, FTZ_OFF, binaryF ), - ENTRY( minmag, 0.0f, 0.0f, FTZ_OFF, binaryF ), - ENTRY( modf, 0.0f, 0.0f, FTZ_OFF, unaryF_two_results ), - ENTRY( nan, 0.0f, 0.0f, FTZ_OFF, unaryF_u), - ENTRY( nextafter, 0.0f, 0.0f, FTZ_OFF, binaryF_nextafter), - ENTRY_EXT( pow, 16.0f, 16.0f, 8192.0f, FTZ_OFF, binaryF), //in derived mode the ulp error is calculated as exp2(y*log2(x)) and in non-derived it is the same as half_pow - ENTRY( pown, 16.0f, 16.0f, FTZ_OFF, binaryF_i), - ENTRY( powr, 16.0f, 16.0f, FTZ_OFF, binaryF), -// ENTRY( reciprocal, 1.0f, 1.0f, FTZ_OFF, unaryF), - ENTRY( remainder, 0.0f, 0.0f, FTZ_OFF, binaryF), - ENTRY( remquo, 0.0f, 0.0f, FTZ_OFF, binaryF_two_results_i), - ENTRY( rint, 0.0f, 0.0f, FTZ_OFF, unaryF), - ENTRY( rootn, 16.0f, 16.0f, FTZ_OFF, binaryF_i), - ENTRY( round, 0.0f, 0.0f, FTZ_OFF, unaryF), - ENTRY( rsqrt, 2.0f, 4.0f, FTZ_OFF, unaryF), - ENTRY( signbit, 0.0f, 0.0f, FTZ_OFF, macro_unaryF), - ENTRY_EXT( sin, 4.0f, 4.0f, 0.00048828125f, FTZ_OFF, unaryF), //relaxed ulp 2^-11 - ENTRY_EXT( sincos, 4.0f, 4.0f, 0.00048828125f, FTZ_OFF, unaryF_two_results), //relaxed ulp 2^-11 - ENTRY( sinh, 4.0f, 4.0f, FTZ_OFF, unaryF), - ENTRY( sinpi, 4.0f, 4.0f, FTZ_OFF, unaryF), - { "sqrt", "sqrt", {(void*)reference_sqrt}, {(void*)reference_sqrtl}, {NULL}, 3.0f, 0.0f, 4.0f, INFINITY, FTZ_OFF, RELAXED_OFF, unaryF }, - { "sqrt_cr", "sqrt", {(void*)reference_sqrt}, {(void*)reference_sqrtl}, {NULL}, 0.0f, 0.0f, 0.0f, INFINITY, FTZ_OFF, RELAXED_OFF, unaryF }, - ENTRY_EXT( tan, 5.0f, 5.0f, 8192.0f, FTZ_OFF, unaryF), //in derived mode it the ulp error is calculated as sin/cos and in non-derived mode it is the same as half_tan. - ENTRY( tanh, 5.0f, 5.0f, FTZ_OFF, unaryF), - ENTRY( tanpi, 6.0f, 6.0f, FTZ_OFF, unaryF), -// ENTRY( tgamma, 16.0f, 16.0f, FTZ_OFF, unaryF), // Commented this out until we can be sure this requirement is realistic - ENTRY( trunc, 0.0f, 0.0f, FTZ_OFF, unaryF), +const Func functionList[] = { + ENTRY(acos, 4.0f, 4.0f, FTZ_OFF, unaryF), + ENTRY(acosh, 4.0f, 4.0f, FTZ_OFF, unaryF), + ENTRY(acospi, 5.0f, 5.0f, FTZ_OFF, unaryF), + ENTRY(asin, 4.0f, 4.0f, FTZ_OFF, unaryF), + ENTRY(asinh, 4.0f, 4.0f, FTZ_OFF, unaryF), + ENTRY(asinpi, 5.0f, 5.0f, FTZ_OFF, unaryF), + ENTRY(atan, 5.0f, 5.0f, FTZ_OFF, unaryF), + ENTRY(atanh, 5.0f, 5.0f, FTZ_OFF, unaryF), + ENTRY(atanpi, 5.0f, 5.0f, FTZ_OFF, unaryF), + ENTRY(atan2, 6.0f, 6.0f, FTZ_OFF, binaryF), + ENTRY(atan2pi, 6.0f, 6.0f, FTZ_OFF, binaryF), + ENTRY(cbrt, 2.0f, 4.0f, FTZ_OFF, unaryF), + ENTRY(ceil, 0.0f, 0.0f, FTZ_OFF, unaryF), + ENTRY(copysign, 0.0f, 0.0f, FTZ_OFF, binaryF), + ENTRY_EXT(cos, 4.0f, 4.0f, 0.00048828125f, FTZ_OFF, unaryF, + 0.00048828125f), // relaxed ulp 2^-11 + ENTRY(cosh, 4.0f, 4.0f, FTZ_OFF, unaryF), + ENTRY(cospi, 4.0f, 4.0f, FTZ_OFF, unaryF), + // ENTRY( erfc, 16.0f, + // 16.0f, FTZ_OFF, unaryF), + // //disabled for 1.0 due to lack of + // reference implementation ENTRY( erf, + // 16.0f, 16.0f, FTZ_OFF, + // unaryF), //disabled for 1.0 due to lack + // of reference implementation + ENTRY_EXT(exp, 3.0f, 4.0f, 3.0f, FTZ_OFF, unaryF, + 4.0f), // relaxed error is actually overwritten in unary.c as it + // is 3+floor(fabs(2*x)) + ENTRY_EXT(exp2, 3.0f, 4.0f, 3.0f, FTZ_OFF, unaryF, + 4.0f), // relaxed error is actually overwritten in unary.c as it + // is 3+floor(fabs(2*x)) + ENTRY_EXT(exp10, 3.0f, 4.0f, 8192.0f, FTZ_OFF, unaryF, + 8192.0f), // relaxed error is actually overwritten in unary.c as + // it is 3+floor(fabs(2*x)) in derived mode, + // in non-derived mode it uses the ulp error for half_exp10. + ENTRY(expm1, 3.0f, 4.0f, FTZ_OFF, unaryF), + ENTRY(fabs, 0.0f, 0.0f, FTZ_OFF, unaryF), + ENTRY(fdim, 0.0f, 0.0f, FTZ_OFF, binaryF), + ENTRY(floor, 0.0f, 0.0f, FTZ_OFF, unaryF), + ENTRY(fma, 0.0f, 0.0f, FTZ_OFF, ternaryF), + ENTRY(fmax, 0.0f, 0.0f, FTZ_OFF, binaryF), + ENTRY(fmin, 0.0f, 0.0f, FTZ_OFF, binaryF), + ENTRY(fmod, 0.0f, 0.0f, FTZ_OFF, binaryF), + ENTRY(fract, 0.0f, 0.0f, FTZ_OFF, unaryF_two_results), + ENTRY(frexp, 0.0f, 0.0f, FTZ_OFF, unaryF_two_results_i), + ENTRY(hypot, 4.0f, 4.0f, FTZ_OFF, binaryF), + ENTRY(ilogb, 0.0f, 0.0f, FTZ_OFF, i_unaryF), + ENTRY(isequal, 0.0f, 0.0f, FTZ_OFF, macro_binaryF), + ENTRY(isfinite, 0.0f, 0.0f, FTZ_OFF, macro_unaryF), + ENTRY(isgreater, 0.0f, 0.0f, FTZ_OFF, macro_binaryF), + ENTRY(isgreaterequal, 0.0f, 0.0f, FTZ_OFF, macro_binaryF), + ENTRY(isinf, 0.0f, 0.0f, FTZ_OFF, macro_unaryF), + ENTRY(isless, 0.0f, 0.0f, FTZ_OFF, macro_binaryF), + ENTRY(islessequal, 0.0f, 0.0f, FTZ_OFF, macro_binaryF), + ENTRY(islessgreater, 0.0f, 0.0f, FTZ_OFF, macro_binaryF), + ENTRY(isnan, 0.0f, 0.0f, FTZ_OFF, macro_unaryF), + ENTRY(isnormal, 0.0f, 0.0f, FTZ_OFF, macro_unaryF), + ENTRY(isnotequal, 0.0f, 0.0f, FTZ_OFF, macro_binaryF), + ENTRY(isordered, 0.0f, 0.0f, FTZ_OFF, macro_binaryF), + ENTRY(isunordered, 0.0f, 0.0f, FTZ_OFF, macro_binaryF), + ENTRY(ldexp, 0.0f, 0.0f, FTZ_OFF, binaryF_i), + ENTRY(lgamma, INFINITY, INFINITY, FTZ_OFF, unaryF), + ENTRY(lgamma_r, INFINITY, INFINITY, FTZ_OFF, unaryF_two_results_i), + ENTRY_EXT(log, 3.0f, 4.0f, 4.76837158203125e-7f, FTZ_OFF, unaryF, + 4.76837158203125e-7f), // relaxed ulp 2^-21 + ENTRY_EXT(log2, 3.0f, 4.0f, 4.76837158203125e-7f, FTZ_OFF, unaryF, + 4.76837158203125e-7f), // relaxed ulp 2^-21 + ENTRY(log10, 3.0f, 4.0f, FTZ_OFF, unaryF), + ENTRY(log1p, 2.0f, 4.0f, FTZ_OFF, unaryF), + ENTRY(logb, 0.0f, 0.0f, FTZ_OFF, unaryF), + ENTRY_EXT(mad, INFINITY, INFINITY, INFINITY, FTZ_OFF, mad_function, + INFINITY), // in fast-relaxed-math mode it has to be either + // exactly rounded fma or exactly rounded a*b+c + ENTRY(maxmag, 0.0f, 0.0f, FTZ_OFF, binaryF), + ENTRY(minmag, 0.0f, 0.0f, FTZ_OFF, binaryF), + ENTRY(modf, 0.0f, 0.0f, FTZ_OFF, unaryF_two_results), + ENTRY(nan, 0.0f, 0.0f, FTZ_OFF, unaryF_u), + ENTRY(nextafter, 0.0f, 0.0f, FTZ_OFF, binaryF_nextafter), + ENTRY_EXT(pow, 16.0f, 16.0f, 8192.0f, FTZ_OFF, binaryF, + 8192.0f), // in derived mode the ulp error is calculated as + // exp2(y*log2(x)) and in non-derived it is the same as + // half_pow + ENTRY(pown, 16.0f, 16.0f, FTZ_OFF, binaryF_i), + ENTRY(powr, 16.0f, 16.0f, FTZ_OFF, binaryF), + // ENTRY( reciprocal, 1.0f, + // 1.0f, FTZ_OFF, unaryF), + ENTRY(remainder, 0.0f, 0.0f, FTZ_OFF, binaryF), + ENTRY(remquo, 0.0f, 0.0f, FTZ_OFF, binaryF_two_results_i), + ENTRY(rint, 0.0f, 0.0f, FTZ_OFF, unaryF), + ENTRY(rootn, 16.0f, 16.0f, FTZ_OFF, binaryF_i), + ENTRY(round, 0.0f, 0.0f, FTZ_OFF, unaryF), + ENTRY(rsqrt, 2.0f, 4.0f, FTZ_OFF, unaryF), + ENTRY(signbit, 0.0f, 0.0f, FTZ_OFF, macro_unaryF), + ENTRY_EXT(sin, 4.0f, 4.0f, 0.00048828125f, FTZ_OFF, unaryF, + 0.00048828125f), // relaxed ulp 2^-11 + ENTRY_EXT(sincos, 4.0f, 4.0f, 0.00048828125f, FTZ_OFF, unaryF_two_results, + 0.00048828125f), // relaxed ulp 2^-11 + ENTRY(sinh, 4.0f, 4.0f, FTZ_OFF, unaryF), + ENTRY(sinpi, 4.0f, 4.0f, FTZ_OFF, unaryF), + { "sqrt", + "sqrt", + { (void*)reference_sqrt }, + { (void*)reference_sqrtl }, + { NULL }, + 3.0f, + 0.0f, + 4.0f, + INFINITY, + INFINITY, + FTZ_OFF, + RELAXED_OFF, + unaryF }, + { "sqrt_cr", + "sqrt", + { (void*)reference_sqrt }, + { (void*)reference_sqrtl }, + { NULL }, + 0.0f, + 0.0f, + 0.0f, + INFINITY, + INFINITY, + FTZ_OFF, + RELAXED_OFF, + unaryF }, + ENTRY_EXT( + tan, 5.0f, 5.0f, 8192.0f, FTZ_OFF, unaryF, + 8192.0f), // in derived mode it the ulp error is calculated as sin/cos + // and in non-derived mode it is the same as half_tan. + ENTRY(tanh, 5.0f, 5.0f, FTZ_OFF, unaryF), + ENTRY(tanpi, 6.0f, 6.0f, FTZ_OFF, unaryF), + // ENTRY( tgamma, 16.0f, + // 16.0f, FTZ_OFF, unaryF), + // // Commented this out until we can be + // sure this requirement is realistic + ENTRY(trunc, 0.0f, 0.0f, FTZ_OFF, unaryF), - HALF_ENTRY( cos, 8192.0f, 8192.0f, FTZ_ON, unaryF), - HALF_ENTRY( divide, 8192.0f, 8192.0f, FTZ_ON, binaryF), - HALF_ENTRY( exp, 8192.0f, 8192.0f, FTZ_ON, unaryF), - HALF_ENTRY( exp2, 8192.0f, 8192.0f, FTZ_ON, unaryF), - HALF_ENTRY( exp10, 8192.0f, 8192.0f, FTZ_ON, unaryF), - HALF_ENTRY( log, 8192.0f, 8192.0f, FTZ_ON, unaryF), - HALF_ENTRY( log2, 8192.0f, 8192.0f, FTZ_ON, unaryF), - HALF_ENTRY( log10, 8192.0f, 8192.0f, FTZ_ON, unaryF), - HALF_ENTRY( powr, 8192.0f, 8192.0f, FTZ_ON, binaryF), - HALF_ENTRY( recip, 8192.0f, 8192.0f, FTZ_ON, unaryF), - HALF_ENTRY( rsqrt, 8192.0f, 8192.0f, FTZ_ON, unaryF), - HALF_ENTRY( sin, 8192.0f, 8192.0f, FTZ_ON, unaryF), - HALF_ENTRY( sqrt, 8192.0f, 8192.0f, FTZ_ON, unaryF), - HALF_ENTRY( tan, 8192.0f, 8192.0f, FTZ_ON, unaryF), + HALF_ENTRY(cos, 8192.0f, 8192.0f, FTZ_ON, unaryF), + HALF_ENTRY(divide, 8192.0f, 8192.0f, FTZ_ON, binaryF), + HALF_ENTRY(exp, 8192.0f, 8192.0f, FTZ_ON, unaryF), + HALF_ENTRY(exp2, 8192.0f, 8192.0f, FTZ_ON, unaryF), + HALF_ENTRY(exp10, 8192.0f, 8192.0f, FTZ_ON, unaryF), + HALF_ENTRY(log, 8192.0f, 8192.0f, FTZ_ON, unaryF), + HALF_ENTRY(log2, 8192.0f, 8192.0f, FTZ_ON, unaryF), + HALF_ENTRY(log10, 8192.0f, 8192.0f, FTZ_ON, unaryF), + HALF_ENTRY(powr, 8192.0f, 8192.0f, FTZ_ON, binaryF), + HALF_ENTRY(recip, 8192.0f, 8192.0f, FTZ_ON, unaryF), + HALF_ENTRY(rsqrt, 8192.0f, 8192.0f, FTZ_ON, unaryF), + HALF_ENTRY(sin, 8192.0f, 8192.0f, FTZ_ON, unaryF), + HALF_ENTRY(sqrt, 8192.0f, 8192.0f, FTZ_ON, unaryF), + HALF_ENTRY(tan, 8192.0f, 8192.0f, FTZ_ON, unaryF), - // basic operations - OPERATOR_ENTRY( add, "+", 0.0f, 0.0f, FTZ_OFF, binaryOperatorF), - OPERATOR_ENTRY( subtract, "-", 0.0f, 0.0f, FTZ_OFF, binaryOperatorF), - { "divide", "/", {(void*)reference_divide}, {(void*)reference_dividel}, {(void*)reference_relaxed_divide}, 2.5f, 0.0f, 3.0f, 2.5f, FTZ_OFF, RELAXED_ON, binaryOperatorF }, - { "divide_cr", "/", {(void*)reference_divide}, {(void*)reference_dividel}, {(void*)reference_relaxed_divide}, 0.0f, 0.0f, 0.0f, 0.f, FTZ_OFF, RELAXED_OFF, binaryOperatorF }, - OPERATOR_ENTRY( multiply, "*", 0.0f, 0.0f, FTZ_OFF, binaryOperatorF), - OPERATOR_ENTRY( assignment, "", 0.0f, 0.0f, FTZ_OFF, unaryF), // A simple copy operation - OPERATOR_ENTRY( not, "!", 0.0f, 0.0f, FTZ_OFF, macro_unaryF), - }; + // basic operations + OPERATOR_ENTRY(add, "+", 0.0f, 0.0f, FTZ_OFF, binaryOperatorF), + OPERATOR_ENTRY(subtract, "-", 0.0f, 0.0f, FTZ_OFF, binaryOperatorF), + { "divide", + "/", + { (void*)reference_divide }, + { (void*)reference_dividel }, + { (void*)reference_relaxed_divide }, + 2.5f, + 0.0f, + 3.0f, + 2.5f, + INFINITY, + FTZ_OFF, + RELAXED_ON, + binaryOperatorF }, + { "divide_cr", + "/", + { (void*)reference_divide }, + { (void*)reference_dividel }, + { (void*)reference_relaxed_divide }, + 0.0f, + 0.0f, + 0.0f, + 0.f, + INFINITY, + FTZ_OFF, + RELAXED_OFF, + binaryOperatorF }, + OPERATOR_ENTRY(multiply, "*", 0.0f, 0.0f, FTZ_OFF, binaryOperatorF), + OPERATOR_ENTRY(assignment, "", 0.0f, 0.0f, FTZ_OFF, + unaryF), // A simple copy operation + OPERATOR_ENTRY(not, "!", 0.0f, 0.0f, FTZ_OFF, macro_unaryF), +}; const size_t functionListCount = sizeof( functionList ) / sizeof( functionList[0] ); diff --git a/test_conformance/math_brute_force/FunctionList.h b/test_conformance/math_brute_force/FunctionList.h index 460e7e82..c22bceeb 100644 --- a/test_conformance/math_brute_force/FunctionList.h +++ b/test_conformance/math_brute_force/FunctionList.h @@ -1,6 +1,6 @@ // // Copyright (c) 2017 The Khronos Group Inc. -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -85,6 +85,7 @@ typedef struct Func float double_ulps; float float_embedded_ulps; float relaxed_error; + float relaxed_embedded_error; int ftz; int relaxed; const vtbl *vtbl_ptr; diff --git a/test_conformance/math_brute_force/Utility.cpp b/test_conformance/math_brute_force/Utility.cpp index 3c706fab..9ab7c7fa 100644 --- a/test_conformance/math_brute_force/Utility.cpp +++ b/test_conformance/math_brute_force/Utility.cpp @@ -1,6 +1,6 @@ // // Copyright (c) 2017 The Khronos Group Inc. -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -14,6 +14,7 @@ // limitations under the License. // #include "Utility.h" +#include "FunctionList.h" #if defined(__PPC__) // Global varaiable used to hold the FPU control register state. The FPSCR register can not @@ -167,3 +168,32 @@ void logFunctionInfo(const char *fname, unsigned int float_size, unsigned int is vlog("%15s %4s %4s",fname, fpSizeStr, fpFastRelaxedStr); } +float getAllowedUlpError(const Func *f, const bool relaxed) +{ + float ulp; + + if (relaxed) + { + if (gIsEmbedded) + { + ulp = f->relaxed_embedded_error; + } + else + { + ulp = f->relaxed_error; + } + } + else + { + if (gIsEmbedded) + { + ulp = f->float_embedded_ulps; + } + else + { + ulp = f->float_ulps; + } + } + + return ulp; +} \ No newline at end of file diff --git a/test_conformance/math_brute_force/Utility.h b/test_conformance/math_brute_force/Utility.h index 7011c95f..7a4cac6c 100644 --- a/test_conformance/math_brute_force/Utility.h +++ b/test_conformance/math_brute_force/Utility.h @@ -1,6 +1,6 @@ // // Copyright (c) 2017 The Khronos Group Inc. -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -29,6 +29,7 @@ #include "harness/testHarness.h" #include "harness/ThreadPool.h" #include "harness/conversions.h" + #define BUFFER_SIZE (1024*1024*2) #if defined( __GNUC__ ) @@ -37,6 +38,8 @@ #define UNUSED #endif +struct Func; + extern int gWimpyBufferSize; extern int gWimpyReductionFactor; @@ -224,6 +227,8 @@ int compareDoubles(double x, double y); void logFunctionInfo(const char *fname, unsigned int float_size, unsigned int isFastRelaxed); +float getAllowedUlpError(const Func *f, const bool relaxed); + #endif /* UTILITY_H */ diff --git a/test_conformance/math_brute_force/binary.cpp b/test_conformance/math_brute_force/binary.cpp index f53d2f12..eb5007c0 100644 --- a/test_conformance/math_brute_force/binary.cpp +++ b/test_conformance/math_brute_force/binary.cpp @@ -500,10 +500,10 @@ static cl_int TestFloat( cl_uint job_id, cl_uint thread_id, void *data ) size_t buffer_size = buffer_elements * sizeof( cl_float ); cl_uint base = job_id * (cl_uint) job->step; ThreadInfo *tinfo = job->tinfo + thread_id; - float ulps = job->ulps; fptr func = job->f->func; int ftz = job->ftz; bool relaxedMode = job->relaxedMode; + float ulps = getAllowedUlpError(job->f, relaxedMode); MTdata d = tinfo->d; cl_uint j, k; cl_int error; @@ -528,7 +528,6 @@ static cl_int TestFloat( cl_uint job_id, cl_uint thread_id, void *data ) }else { func = job->f->rfunc; - ulps = job->f->relaxed_error; } } diff --git a/test_conformance/math_brute_force/binaryOperator.cpp b/test_conformance/math_brute_force/binaryOperator.cpp index fde5dd59..0742964d 100644 --- a/test_conformance/math_brute_force/binaryOperator.cpp +++ b/test_conformance/math_brute_force/binaryOperator.cpp @@ -491,9 +491,9 @@ static cl_int TestFloat(cl_uint job_id, cl_uint thread_id, void *data) size_t buffer_size = buffer_elements * sizeof( cl_float ); cl_uint base = job_id * (cl_uint) job->step; ThreadInfo *tinfo = job->tinfo + thread_id; - float ulps = job->ulps; fptr func = job->f->func; bool relaxedMode = job->relaxedMode; + float ulps = getAllowedUlpError(job->f, relaxedMode); if (relaxedMode) { func = job->f->rfunc; @@ -731,8 +731,6 @@ static cl_int TestFloat(cl_uint job_id, cl_uint thread_id, void *data) float err = Ulp_Error( test, correct ); float errB = Ulp_Error( test, (float) correct ); - if (relaxedMode) ulps = job->f->relaxed_error; - int fail = ((!(fabsf(err) <= ulps)) && (!(fabsf(errB) <= ulps))); if( fabsf( errB ) < fabsf(err ) ) err = errB; diff --git a/test_conformance/math_brute_force/unary.cpp b/test_conformance/math_brute_force/unary.cpp index 3ed2ed16..5a45d23d 100644 --- a/test_conformance/math_brute_force/unary.cpp +++ b/test_conformance/math_brute_force/unary.cpp @@ -463,13 +463,12 @@ static cl_int TestFloat( cl_uint job_id, cl_uint thread_id, void *data ) cl_uint scale = job->scale; cl_uint base = job_id * (cl_uint) job->step; ThreadInfo *tinfo = job->tinfo + thread_id; - float ulps = job->ulps; fptr func = job->f->func; const char * fname = job->f->name; bool relaxedMode = job->relaxedMode; + float ulps = getAllowedUlpError(job->f, relaxedMode); if (relaxedMode) { - ulps = job->f->relaxed_error; func = job->f->rfunc; } @@ -634,8 +633,13 @@ static cl_int TestFloat( cl_uint job_id, cl_uint thread_id, void *data ) if ( strcmp(fname, "exp") == 0 || strcmp(fname, "exp2") == 0 ) { + float exp_error = ulps; + + if (!gIsEmbedded) + { + exp_error += floor(fabs(2 * s[j])); + } - float exp_error = 3+floor(fabs(2*s[j])); fail = ! (fabsf(err) <= exp_error); ulps = exp_error; } diff --git a/test_conformance/math_brute_force/unary_two_results.cpp b/test_conformance/math_brute_force/unary_two_results.cpp index 779681b1..4f39fde4 100644 --- a/test_conformance/math_brute_force/unary_two_results.cpp +++ b/test_conformance/math_brute_force/unary_two_results.cpp @@ -208,19 +208,13 @@ int TestFunc_Float2_Float(const Func *f, MTdata d, bool relaxedMode) cl_uchar overflow[BUFFER_SIZE / sizeof( float )]; int isFract = 0 == strcmp( "fract", f->nameInCode ); int skipNanInf = isFract && ! gInfNanSupport; - float float_ulps; + float float_ulps = getAllowedUlpError(f, relaxedMode); logFunctionInfo(f->name, sizeof(cl_float), relaxedMode); if( gWimpyMode ) { step = (1ULL<<32) * gWimpyReductionFactor / (512); } - if( gIsEmbedded ) - float_ulps = f->float_embedded_ulps; - else - float_ulps = f->float_ulps; - - if (relaxedMode) float_ulps = f->relaxed_error; // Init the kernels BuildKernelInfo build_info = { gMinVectorSizeIndex, kernels, programs,