File size: 2,929 Bytes
d1a84ee
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/*
 * 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.
 */

#ifndef LYRA_CODEC_SPARSE_MATMUL_NUMERICS_TEST_UTILS_H_
#define LYRA_CODEC_SPARSE_MATMUL_NUMERICS_TEST_UTILS_H_

#include <cmath>
#include <limits>
#include <type_traits>

#include "gtest/gtest.h"
#include "sparse_matmul/numerics/type_utils.h"

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

#endif  // LYRA_CODEC_SPARSE_MATMUL_NUMERICS_TEST_UTILS_H_