blob: b49ce48d60510ba95be4665d0d23c741b87353e8 [file] [log] [blame]
Jeremy Johnsond80ea5e2024-01-03 10:54:12 +00001// Copyright (c) 2023-2024, ARM Limited.
Jeremy Johnson9a758382023-11-07 16:27:35 +00002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include <cmath>
16#include <limits>
17#include <memory>
18#include <type_traits>
19#include <utility>
20
Jeremy Johnson718f3472023-11-30 14:18:19 +000021#include "half.hpp"
Jeremy Johnson9a758382023-11-07 16:27:35 +000022#include "verifiers.h"
Jeremy Johnson9a758382023-11-07 16:27:35 +000023namespace TosaReference
24{
25
26namespace
27{
Jeremy Johnson08965d32024-02-19 13:57:21 +000028template <typename OutType>
29double calcErrorBound(double referenceValue, double boundsValue, const void* cfgPtr)
Jeremy Johnson9a758382023-11-07 16:27:35 +000030{
Jeremy Johnson08965d32024-02-19 13:57:21 +000031 const auto cfg = reinterpret_cast<const AbsErrorVerifyInfo*>(cfgPtr);
Jeremy Johnson9a758382023-11-07 16:27:35 +000032
Jeremy Johnson1eb14552024-04-11 16:21:54 +010033 double boundsMagnitude;
34 if (cfg->boundAsMagnitude)
Jeremy Johnson9a758382023-11-07 16:27:35 +000035 {
Jeremy Johnson1eb14552024-04-11 16:21:54 +010036 // Special case for SIN/COS
37 // use the input value (stored in the bounds tensor) as the magnitude and value
38 boundsMagnitude = boundsValue;
39 boundsValue = std::abs(boundsValue);
40 }
41 else
42 {
43 // Use the referenceValue as the magnitude
44 boundsMagnitude = referenceValue;
45 }
46
47 double errorBound = 0.0;
48 if (std::isfinite(boundsValue) || std::abs(boundsMagnitude) != 0.0)
49 {
50 double valueBound = std::abs(boundsMagnitude) * (boundsValue + cfg->boundAddition);
evacha019c96eef2024-02-07 11:21:55 +000051 if (cfg->lowerBound > 0)
52 {
Jeremy Johnson1eb14552024-04-11 16:21:54 +010053 valueBound = std::max(cfg->lowerBound, valueBound);
evacha019c96eef2024-02-07 11:21:55 +000054 }
Jeremy Johnson1eb14552024-04-11 16:21:54 +010055 errorBound = exp2(-AccPrecision<OutType>::normal_frac / cfg->normalDivisor) * valueBound;
Jeremy Johnson9a758382023-11-07 16:27:35 +000056 }
evacha019c96eef2024-02-07 11:21:55 +000057 return errorBound;
Jeremy Johnson9a758382023-11-07 16:27:35 +000058}
59} // namespace
Jeremy Johnson08965d32024-02-19 13:57:21 +000060
61bool verifyAbsError(const CTensor* referenceTensor,
62 const CTensor* boundsTensor,
63 const CTensor* implementationTensor,
64 const AbsErrorVerifyInfo& aeInfo)
Jeremy Johnson9a758382023-11-07 16:27:35 +000065{
66 // Validate that tensors are provided
Jeremy Johnson08965d32024-02-19 13:57:21 +000067 TOSA_REF_REQUIRE(referenceTensor != nullptr, "[AE] Reference tensor is missing");
68 TOSA_REF_REQUIRE(boundsTensor != nullptr, "[AE] Reference bounds tensor is missing");
69 TOSA_REF_REQUIRE(implementationTensor != nullptr, "[AE] Implementation tensor is missing");
Jeremy Johnson9a758382023-11-07 16:27:35 +000070
Jeremy Johnson08965d32024-02-19 13:57:21 +000071 const std::vector<int32_t> refShape(referenceTensor->shape, referenceTensor->shape + referenceTensor->num_dims);
Jeremy Johnson9a758382023-11-07 16:27:35 +000072
Jeremy Johnson08965d32024-02-19 13:57:21 +000073 const double* refData = reinterpret_cast<const double*>(referenceTensor->data);
74 const double* refBndData = reinterpret_cast<const double*>(boundsTensor->data);
Jeremy Johnson9a758382023-11-07 16:27:35 +000075 TOSA_REF_REQUIRE(refData != nullptr && refBndData != nullptr, "[AE] Missing data for reference or bounds tensors");
76
Jeremy Johnson08965d32024-02-19 13:57:21 +000077 const std::string modeStr = "AE";
78
79 switch (implementationTensor->data_type)
Jeremy Johnson9a758382023-11-07 16:27:35 +000080 {
81 case tosa_datatype_fp32_t: {
Jeremy Johnson08965d32024-02-19 13:57:21 +000082 const auto* impData = reinterpret_cast<const float*>(implementationTensor->data);
Jeremy Johnson718f3472023-11-30 14:18:19 +000083 TOSA_REF_REQUIRE(impData != nullptr, "[AE] Missing data for implementation");
Jeremy Johnson08965d32024-02-19 13:57:21 +000084 return validateData(refData, refBndData, impData, refShape, modeStr, &aeInfo, &calcErrorBound<float>);
Jeremy Johnson718f3472023-11-30 14:18:19 +000085 }
86 case tosa_datatype_fp16_t: {
Jeremy Johnson08965d32024-02-19 13:57:21 +000087 const auto* impData = reinterpret_cast<const half_float::half*>(implementationTensor->data);
Jeremy Johnson9a758382023-11-07 16:27:35 +000088 TOSA_REF_REQUIRE(impData != nullptr, "[AE] Missing data for implementation");
Jeremy Johnson08965d32024-02-19 13:57:21 +000089 return validateData(refData, refBndData, impData, refShape, modeStr, &aeInfo,
90 &calcErrorBound<half_float::half>);
Jeremy Johnson9a758382023-11-07 16:27:35 +000091 }
92 default:
93 WARNING("[Verifier][AE] Data-type not supported.");
94 break;
95 }
96
97 return false;
98}
99} // namespace TosaReference