aboutsummaryrefslogtreecommitdiff
path: root/test/test.h
blob: b381bad648447161d032c201f09ff8b746106ce6 (plain)
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Copyright 2015 The Gemmlowp Authors. All Rights Reserved.
//
// 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.

// test.h: shared testing helpers.

#ifndef GEMMLOWP_TEST_TEST_H_
#define GEMMLOWP_TEST_TEST_H_

#ifdef GEMMLOWP_TEST_PROFILE
#define GEMMLOWP_PROFILING
#include "../profiling/profiler.h"
#endif

#include <cstring>
#include <iostream>
#include <random>
#include <vector>

#include "../public/gemmlowp.h"

namespace gemmlowp {

#define GEMMLOWP_STRINGIFY2(x) #x
#define GEMMLOWP_STRINGIFY(x) GEMMLOWP_STRINGIFY2(x)

#define Check(b)                                                         \
  do {                                                                   \
    ReleaseBuildAssertion(                                               \
        b, "test failed at " __FILE__ ":" GEMMLOWP_STRINGIFY(__LINE__)); \
  } while (false)

// gemmlowp itself doesn't have a Matrix class, only a MatrixMap class,
// since it only maps existing data. In tests though, we need to
// create our own matrices.
template <typename tScalar, MapOrder tOrder>
class Matrix : public MatrixMap<tScalar, tOrder> {
 public:
  typedef MatrixMap<tScalar, tOrder> Map;
  typedef MatrixMap<const tScalar, tOrder> ConstMap;
  typedef typename Map::Scalar Scalar;
  static constexpr MapOrder Order = tOrder;
  using Map::kOrder;
  using Map::rows_;
  using Map::cols_;
  using Map::stride_;
  using Map::data_;

 public:
  Matrix() : Map(nullptr, 0, 0, 0) {}

  Matrix(int rows, int cols) : Map(nullptr, 0, 0, 0) { Resize(rows, cols); }

  Matrix(const Matrix& other) : Map(nullptr, 0, 0, 0) { *this = other; }

  Matrix& operator=(const Matrix& other) {
    Resize(other.rows_, other.cols_);
    std::memcpy(data_, other.data_, size() * sizeof(Scalar));
    return *this;
  }

  friend bool operator==(const Matrix& a, const Matrix& b) {
    return a.rows_ == b.rows_ && a.cols_ == b.cols_ &&
           !std::memcmp(a.data_, b.data_, a.size());
  }

  void Resize(int rows, int cols) {
    rows_ = rows;
    cols_ = cols;
    stride_ = kOrder == MapOrder::ColMajor ? rows : cols;
    storage.resize(size());
    data_ = storage.data();
  }

  int size() const { return rows_ * cols_; }

  Map& map() { return *static_cast<Map*>(this); }

  ConstMap const_map() const { return ConstMap(data_, rows_, cols_, stride_); }

 protected:
  std::vector<Scalar> storage;
};

inline std::mt19937& RandomEngine() {
  static std::mt19937 engine;
  return engine;
}

inline int Random() {
  std::uniform_int_distribution<int> dist(0, std::numeric_limits<int>::max());
  return dist(RandomEngine());
}

#ifdef _MSC_VER
// msvc does not support 8bit types in uniform_int_distribution<>.
// Take 32 bit uniform_int_distribution<> and only use the lower 8 bits.
template <typename OperandRange, typename MatrixType>
void MakeRandom(MatrixType* m) {
  ScopedProfilingLabel("MakeRandom(matrix)");
  for (int c = 0; c < m->cols(); c++) {
    for (int r = 0; r < m->rows(); r++) {
      (*m)(r, c) = Random() % OperandRange::kMaxValue;
    }
  }
}
#else
template <typename OperandRange, typename MatrixType>
void MakeRandom(MatrixType* m) {
  ScopedProfilingLabel("MakeRandom(matrix)");
  typedef typename MatrixType::Scalar Scalar;
  std::uniform_int_distribution<Scalar> dist(OperandRange::kMinValue,
                                             OperandRange::kMaxValue);
  for (int c = 0; c < m->cols(); c++) {
    for (int r = 0; r < m->rows(); r++) {
      (*m)(r, c) = dist(RandomEngine());
    }
  }
}
#endif

template <typename MatrixType>
void MakeConstant(MatrixType* m, typename MatrixType::Scalar val) {
  ScopedProfilingLabel("MakeConstant(matrix)");
  for (int c = 0; c < m->cols(); c++) {
    for (int r = 0; r < m->rows(); r++) {
      (*m)(r, c) = val;
    }
  }
}

template <typename MatrixType>
void MakeZero(MatrixType* m) {
  ScopedProfilingLabel("MakeZero(matrix)");
  MakeConstant(m, 0);
}

}  // namespace gemmlowp

#endif  // GEMMLOWP_TEST_TEST_H_