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.cc47
1 files changed, 23 insertions, 24 deletions
diff --git a/reference_model/src/verify/verify_ulp.cc b/reference_model/src/verify/verify_ulp.cc
index 486c0ff..8c27191 100644
--- a/reference_model/src/verify/verify_ulp.cc
+++ b/reference_model/src/verify/verify_ulp.cc
@@ -31,7 +31,7 @@ static_assert(std::numeric_limits<double>::is_iec559,
"TOSA Reference Model has not been built with standard IEE574 64-bit float support; ULP based "
"verifcation is invalid");
-bool tosaCheckULP(float testValue, double referenceValue, int64_t ulpCount)
+bool tosaCheckULP(double referenceValue, float testValue, double ulpNum)
{
// Start by sanitizing the input.
@@ -71,57 +71,55 @@ bool tosaCheckULP(float testValue, double referenceValue, int64_t ulpCount)
else
{
// Find the exponent of the reference value.
- int referenceExponent;
- std::frexp(referenceValue, &referenceExponent);
+ int32_t referenceExponent = ilog2(referenceValue);
// 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(std::ldexp(1.0, referenceExponent), static_cast<double>(std::numeric_limits<float>::min()));
+ const double referencePower2 = std::max(exp2(referenceExponent), AccPrecision<float>::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 * std::ldexp(1.0, -23);
-
- // It is possible that within one ULP we cross a boundary where we need to change the exponent,
- // if this happens we will take the ULP for the larger exponent.
- if (referenceValue + ulpValue > 2 * referencePower2)
- {
- ulpValue = 2 * ulpValue;
- }
+ double ulpValue = referencePower2 * exp2(-AccPrecision<float>::normal_frac);
// Scale by the number of ULPs requested by the user.
- referenceMax = referenceValue + ulpValue * ulpCount;
- referenceMin = referenceValue - ulpValue * ulpCount;
+ referenceMax = referenceValue + ulpValue * ulpNum;
+ referenceMin = referenceValue - ulpValue * ulpNum;
// Handle the overflow cases.
- if (referenceMax > std::numeric_limits<float>::max())
+ if (referenceMax > AccPrecision<float>::normal_max)
{
referenceMax = std::numeric_limits<float>::infinity();
}
- if (referenceMin > std::numeric_limits<float>::max())
+ if (referenceMin > AccPrecision<float>::normal_max)
{
referenceMin = std::numeric_limits<float>::infinity();
}
// And the underflow cases.
- if (referenceMax < std::numeric_limits<float>::min())
+ if (referenceMax < AccPrecision<float>::normal_min)
{
- referenceMax = std::numeric_limits<float>::min();
+ referenceMax = AccPrecision<float>::normal_min;
}
- if (referenceMin < std::numeric_limits<float>::min())
+ if (referenceMin < AccPrecision<float>::normal_min)
{
- referenceMin = 0;
+ referenceMin = 0.0;
}
}
// And finally... Do the comparison.
- return static_cast<double>(testValue) >= referenceMin && static_cast<double>(testValue) <= referenceMax;
+ double testValue64 = static_cast<double>(testValue);
+ bool withinUlp = testValue64 >= referenceMin && testValue64 <= referenceMax;
+ if (!withinUlp)
+ {
+ WARNING("[Verfier][ULP] value (%10f) is not in ULP %g range (%10f <= ref (%10f) <= %10f).", testValue64, ulpNum,
+ referenceMin, referenceValue, referenceMax);
+ }
+ return withinUlp;
}
} // namespace
-bool verifyULP(const CTensor* referenceTensor, const CTensor* implementationTensor, uint64_t ulp)
+bool verifyULP(const CTensor* referenceTensor, const CTensor* implementationTensor, const UlpInfo& ulpInfo)
{
// Validate that tensors are provided
TOSA_REF_REQUIRE(referenceTensor != nullptr, "[ULP] Reference tensor is missing");
@@ -132,10 +130,11 @@ bool verifyULP(const CTensor* referenceTensor, const CTensor* implementationTens
numElements(std::vector<int32_t>(referenceTensor->shape, referenceTensor->shape + referenceTensor->num_dims));
TOSA_REF_REQUIRE(elementCount > 0, "[ULP] Invalid shape for reference tensor");
+ const double ulp = ulpInfo.ulp;
switch (implementationTensor->data_type)
{
case tosa_datatype_fp32_t: {
- const auto* refData = reinterpret_cast<const float*>(referenceTensor->data);
+ 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");