1// Copyright 2015 The Gemmlowp Authors. All Rights Reserved.
2//
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// test.h: shared testing helpers.
16
17#ifndef GEMMLOWP_TEST_TEST_H_
18#define GEMMLOWP_TEST_TEST_H_
19
20#ifdef GEMMLOWP_TEST_PROFILE
21#define GEMMLOWP_PROFILING
22#include "../profiling/profiler.h"
23#endif
24
25#include <cstring>
26#include <iostream>
27#include <random>
28#include <vector>
29
30#include "../public/gemmlowp.h"
31
32namespace gemmlowp {
33
34#define GEMMLOWP_STRINGIFY2(x) #x
35#define GEMMLOWP_STRINGIFY(x) GEMMLOWP_STRINGIFY2(x)
36
37#define Check(b)                                                         \
38  do {                                                                   \
39    ReleaseBuildAssertion(                                               \
40        b, "test failed at " __FILE__ ":" GEMMLOWP_STRINGIFY(__LINE__)); \
41  } while (false)
42
43// gemmlowp itself doesn't have a Matrix class, only a MatrixMap class,
44// since it only maps existing data. In tests though, we need to
45// create our own matrices.
46template <typename tScalar, MapOrder tOrder>
47class Matrix : public MatrixMap<tScalar, tOrder> {
48 public:
49  typedef MatrixMap<tScalar, tOrder> Map;
50  typedef MatrixMap<const tScalar, tOrder> ConstMap;
51  typedef typename Map::Scalar Scalar;
52  static const MapOrder Order = tOrder;
53  using Map::kOrder;
54  using Map::rows_;
55  using Map::cols_;
56  using Map::stride_;
57  using Map::data_;
58
59 public:
60  Matrix() : Map(nullptr, 0, 0, 0) {}
61
62  Matrix(int rows, int cols) : Map(nullptr, 0, 0, 0) { Resize(rows, cols); }
63
64  Matrix(const Matrix& other) : Map(nullptr, 0, 0, 0) { *this = other; }
65
66  Matrix& operator=(const Matrix& other) {
67    Resize(other.rows_, other.cols_);
68    std::memcpy(data_, other.data_, size() * sizeof(Scalar));
69    return *this;
70  }
71
72  friend bool operator==(const Matrix& a, const Matrix& b) {
73    return a.rows_ == b.rows_ && a.cols_ == b.cols_ &&
74           !std::memcmp(a.data_, b.data_, a.size());
75  }
76
77  void Resize(int rows, int cols) {
78    rows_ = rows;
79    cols_ = cols;
80    stride_ = kOrder == MapOrder::ColMajor ? rows : cols;
81    storage.resize(size());
82    data_ = storage.data();
83  }
84
85  int size() const { return rows_ * cols_; }
86
87  Map& map() { return *static_cast<Map*>(this); }
88
89  ConstMap const_map() const { return ConstMap(data_, rows_, cols_, stride_); }
90
91 protected:
92  std::vector<Scalar> storage;
93};
94
95std::mt19937& RandomEngine() {
96  static std::mt19937 engine;
97  return engine;
98}
99
100int Random() {
101  std::uniform_int_distribution<int> dist(0, std::numeric_limits<int>::max());
102  return dist(RandomEngine());
103}
104
105template <typename OperandRange, typename MatrixType>
106void MakeRandom(MatrixType* m) {
107  ScopedProfilingLabel("MakeRandom(matrix)");
108  typedef typename MatrixType::Scalar Scalar;
109  std::uniform_int_distribution<Scalar> dist(OperandRange::kMinValue,
110                                             OperandRange::kMaxValue);
111  for (int c = 0; c < m->cols(); c++) {
112    for (int r = 0; r < m->rows(); r++) {
113      (*m)(r, c) = dist(RandomEngine());
114    }
115  }
116}
117
118template <typename MatrixType>
119void MakeConstant(MatrixType* m, typename MatrixType::Scalar val) {
120  ScopedProfilingLabel("MakeConstant(matrix)");
121  for (int c = 0; c < m->cols(); c++) {
122    for (int r = 0; r < m->rows(); r++) {
123      (*m)(r, c) = val;
124    }
125  }
126}
127
128template <typename MatrixType>
129void MakeZero(MatrixType* m) {
130  ScopedProfilingLabel("MakeZero(matrix)");
131  MakeConstant(m, 0);
132}
133
134}  // namespace gemmlowp
135
136#endif  // GEMMLOWP_TEST_TEST_H_
137