diff options
Diffstat (limited to 'reference_model/src/verify/verify_ulp.cc')
-rw-r--r-- | reference_model/src/verify/verify_ulp.cc | 47 |
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"); |