Spaces:
Running
Running
| /* | |
| * Copyright 2021 Google LLC | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| namespace csrblocksparse { | |
| // Computes the relative difference between two floating point numbers | |
| // std::abs(b - a) / a. If the a is < 10 * epsilon, then use the absolute | |
| // difference instead of the relative one. | |
| template <typename T> | |
| T RelDiff(T a, T b) { | |
| static_assert(std::is_floating_point<T>::value, | |
| "RelDiff should only be used on floating point types."); | |
| if (std::abs(a) < 600 * std::numeric_limits<T>::epsilon()) { | |
| return std::abs(b - a); | |
| } | |
| return std::abs((b - a) / a); | |
| } | |
| // Compares two CacheAlignedVectors elementwise, checks if each pair passes a | |
| // RelDiff check. The result of RelDiff is scaled by the log of the size of the | |
| // column to account for increasing summation errors as the number of summands | |
| // increases. | |
| template <typename VectorType> | |
| void CheckResult(const VectorType& lhs, const VectorType& rhs, int columns) { | |
| ASSERT_EQ(lhs.size(), rhs.size()); | |
| float epsilon = | |
| 1.0f / | |
| (1 << (MantissaBitsOf<typename VectorType::value_type>::value - 1)); | |
| // if we're summing a large number of values, then we can relax the tolerance | |
| float log_scale = std::max(1.f, logf(columns)); | |
| // The tolerance is so large because it is a relative tolerance used to test | |
| // numbers that are close to zero at the limit of the resolution of the | |
| // representation. It would probably be better to focus on an absolute | |
| // tolerance, based on the epsilon above. | |
| const float tolerance = 0.026f; | |
| for (int i = 0; i < lhs.size(); ++i) { | |
| float lhs_value = static_cast<float>(lhs.data()[i]); | |
| float rhs_value = static_cast<float>(rhs.data()[i]); | |
| // If the absolute difference is no more than the epsilon for the | |
| // representation, then it is OK. | |
| if (std::abs(lhs_value - rhs_value) <= epsilon) continue; | |
| float rel_diff = RelDiff(lhs_value, rhs_value) / log_scale; | |
| EXPECT_LT(rel_diff, tolerance) << i % columns << " " << i / columns << " " | |
| << lhs_value << " " << rhs_value; | |
| } | |
| } | |
| } // namespace csrblocksparse | |