diff options
Diffstat (limited to 'reference_model/src/verify/verify_ulp.cc')
-rw-r--r-- | reference_model/src/verify/verify_ulp.cc | 36 |
1 files changed, 29 insertions, 7 deletions
diff --git a/reference_model/src/verify/verify_ulp.cc b/reference_model/src/verify/verify_ulp.cc index 6e78b96..1b38fe6 100644 --- a/reference_model/src/verify/verify_ulp.cc +++ b/reference_model/src/verify/verify_ulp.cc @@ -18,6 +18,7 @@ #include <type_traits> #include <utility> +#include "half.hpp" #include "verifiers.h" namespace TosaReference @@ -25,7 +26,8 @@ namespace TosaReference namespace { -bool tosaCheckULP(float testValue, double referenceValue, double ulpNum) +template <typename OutType> +bool tosaCheckULP(OutType testValue, double referenceValue, double ulpNum) { double errorBound = 0.0; if (std::isfinite(referenceValue) && std::abs(referenceValue) != 0.0) @@ -35,10 +37,10 @@ bool tosaCheckULP(float testValue, double referenceValue, double ulpNum) // Work out the values magnitude - by raising 2 to the power of the // exponent and taking the normalized minimum for denormal values - const double referencePower2 = std::max(exp2(referenceExponent), AccPrecision<float>::normal_min); + const double referencePower2 = std::max(exp2(referenceExponent), AccPrecision<OutType>::normal_min); // Get the value of changing the last bit - by shifting the least significant bit to this magnitude // i.e. the ULP. - double ulpValue = referencePower2 * exp2(-AccPrecision<float>::normal_frac); + double ulpValue = referencePower2 * exp2(-AccPrecision<OutType>::normal_frac); errorBound = ulpValue * ulpNum; } @@ -57,15 +59,35 @@ bool verifyULP(const CTensor* referenceTensor, const CTensor* implementationTens const auto elementCount = numElements(refShape); TOSA_REF_REQUIRE(elementCount > 0, "[ULP] Invalid shape for reference tensor"); - const double ulp = ulpInfo.ulp; + const double ulp = ulpInfo.ulp; + const auto* refData = reinterpret_cast<const double*>(referenceTensor->data); + TOSA_REF_REQUIRE(refData != nullptr, "[ULP] Missing data for reference"); + const auto* refDataEnd = std::next(refData, elementCount); switch (implementationTensor->data_type) { case tosa_datatype_fp32_t: { - const auto* refData = reinterpret_cast<const double*>(referenceTensor->data); - TOSA_REF_REQUIRE(refData != nullptr, "[ULP] Missing data for reference"); const auto* impData = reinterpret_cast<const float*>(implementationTensor->data); TOSA_REF_REQUIRE(impData != nullptr, "[ULP] Missing data for implementation"); - const auto* refDataEnd = std::next(refData, elementCount); + // Use mismatch to get the location of the first unequal value + auto pair = std::mismatch(refData, refDataEnd, impData, std::next(impData, elementCount), + [ulp](const auto& referenceValue, const auto& implementationValue) { + return tosaCheckULP(implementationValue, referenceValue, ulp); + }); + if (std::get<0>(pair) == refDataEnd) + { + // No mismatch found + return true; + } + else + { + auto pos = indexToPosition(std::get<0>(pair) - refData, refShape); + WARNING("[Verfier][ULP] Location %s", positionToString(pos).c_str()); + return false; + } + } + case tosa_datatype_fp16_t: { + const auto* impData = reinterpret_cast<const half_float::half*>(implementationTensor->data); + TOSA_REF_REQUIRE(impData != nullptr, "[ULP] Missing data for implementation"); // Use mismatch to get the location of the first unequal value auto pair = std::mismatch(refData, refDataEnd, impData, std::next(impData, elementCount), [ulp](const auto& referenceValue, const auto& implementationValue) { |