Home | History | Annotate | Download | only in test
      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