aboutsummaryrefslogtreecommitdiff
path: root/reference_model/src/verify/verify_ulp.cc
diff options
context:
space:
mode:
Diffstat (limited to 'reference_model/src/verify/verify_ulp.cc')
-rw-r--r--reference_model/src/verify/verify_ulp.cc36
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) {