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
32 namespace 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.
46 template <typename tScalar, MapOrder tOrder>
47 class 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 constexpr 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:
Matrix()60 Matrix() : Map(nullptr, 0, 0, 0) {}
61
Matrix(int rows,int cols)62 Matrix(int rows, int cols) : Map(nullptr, 0, 0, 0) { Resize(rows, cols); }
63
Matrix(const Matrix & other)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
Resize(int rows,int cols)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
size()85 int size() const { return rows_ * cols_; }
86
map()87 Map& map() { return *static_cast<Map*>(this); }
88
const_map()89 ConstMap const_map() const { return ConstMap(data_, rows_, cols_, stride_); }
90
91 protected:
92 std::vector<Scalar> storage;
93 };
94
RandomEngine()95 inline std::mt19937& RandomEngine() {
96 static std::mt19937 engine;
97 return engine;
98 }
99
Random()100 inline int Random() {
101 std::uniform_int_distribution<int> dist(0, std::numeric_limits<int>::max());
102 return dist(RandomEngine());
103 }
104
105 #ifdef _MSC_VER
106 // msvc does not support 8bit types in uniform_int_distribution<>.
107 // Take 32 bit uniform_int_distribution<> and only use the lower 8 bits.
108 template <typename OperandRange, typename MatrixType>
MakeRandom(MatrixType * m)109 void MakeRandom(MatrixType* m) {
110 ScopedProfilingLabel("MakeRandom(matrix)");
111 for (int c = 0; c < m->cols(); c++) {
112 for (int r = 0; r < m->rows(); r++) {
113 (*m)(r, c) = Random() % OperandRange::kMaxValue;
114 }
115 }
116 }
117 #else
118 template <typename OperandRange, typename MatrixType>
MakeRandom(MatrixType * m)119 void MakeRandom(MatrixType* m) {
120 ScopedProfilingLabel("MakeRandom(matrix)");
121 typedef typename MatrixType::Scalar Scalar;
122 std::uniform_int_distribution<Scalar> dist(OperandRange::kMinValue,
123 OperandRange::kMaxValue);
124 for (int c = 0; c < m->cols(); c++) {
125 for (int r = 0; r < m->rows(); r++) {
126 (*m)(r, c) = dist(RandomEngine());
127 }
128 }
129 }
130 #endif
131
132 template <typename MatrixType>
MakeConstant(MatrixType * m,typename MatrixType::Scalar val)133 void MakeConstant(MatrixType* m, typename MatrixType::Scalar val) {
134 ScopedProfilingLabel("MakeConstant(matrix)");
135 for (int c = 0; c < m->cols(); c++) {
136 for (int r = 0; r < m->rows(); r++) {
137 (*m)(r, c) = val;
138 }
139 }
140 }
141
142 template <typename MatrixType>
MakeZero(MatrixType * m)143 void MakeZero(MatrixType* m) {
144 ScopedProfilingLabel("MakeZero(matrix)");
145 MakeConstant(m, 0);
146 }
147
148 } // namespace gemmlowp
149
150 #endif // GEMMLOWP_TEST_TEST_H_
151