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 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 95 std::mt19937& RandomEngine() { 96 static std::mt19937 engine; 97 return engine; 98 } 99 100 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> 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> 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> 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> 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