1 /*
2     Scan Tailor - Interactive post-processing tool for scanned pages.
3     Copyright (C)  Joseph Artsimovich <joseph.artsimovich@gmail.com>
4 
5     This program is free software: you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation, either version 3 of the License, or
8     (at your option) any later version.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifndef MAT_MNT_H_
20 #define MAT_MNT_H_
21 
22 #include <cstddef>
23 
24 template <size_t M, size_t N, typename T>
25 class MatMNT;
26 
27 typedef MatMNT<2, 2, float> Mat22f;
28 typedef MatMNT<2, 2, double> Mat22d;
29 typedef MatMNT<3, 3, float> Mat33f;
30 typedef MatMNT<3, 3, double> Mat33d;
31 typedef MatMNT<4, 4, float> Mat44f;
32 typedef MatMNT<4, 4, double> Mat44d;
33 
34 /**
35  * \brief A matrix with pre-defined dimensions.
36  *
37  * \note The memory layout is always column-major, as that's what MatrixCalc uses.
38  */
39 template <size_t M, size_t N, typename T>
40 class MatMNT {
41  public:
42   typedef T type;
43   enum { ROWS = static_cast<int>(M), COLS = static_cast<int>(N) };
44 
45   /**
46    * \brief Initializes matrix elements to T().
47    */
48   MatMNT();
49 
50   /**
51    * \brief Construction from an array of elements of possibly different type.
52    *
53    * Conversion is done by static casts.  Data elements must be in column-major order.
54    */
55   template <typename OT>
56   explicit MatMNT(const OT* data);
57 
58   /**
59    * \brief Construction from a matrix of same dimensions but another type.
60    *
61    * Conversion is done by static casts.
62    */
63   template <typename OT>
64   explicit MatMNT(const MatMNT<M, N, OT>& other);
65 
66   /**
67    * \brief Assignment from a matrix of same dimensions but another type.
68    *
69    * Conversion is done by static casts.
70    */
71   template <typename OT>
72   MatMNT& operator=(const MatMNT<M, N, OT>& other);
73 
data()74   const T* data() const { return m_data; }
75 
data()76   T* data() { return m_data; }
77 
operator()78   const T& operator()(int i, int j) const { return m_data[i + j * M]; }
79 
operator()80   T& operator()(int i, int j) { return m_data[i + j * M]; }
81 
82  private:
83   T m_data[M * N];
84 };
85 
86 
87 template <size_t M, size_t N, typename T>
MatMNT()88 MatMNT<M, N, T>::MatMNT() {
89   const size_t len = ROWS * COLS;
90   for (size_t i = 0; i < len; ++i) {
91     m_data[i] = T();
92   }
93 }
94 
95 template <size_t M, size_t N, typename T>
96 template <typename OT>
MatMNT(const OT * data)97 MatMNT<M, N, T>::MatMNT(const OT* data) {
98   const size_t len = ROWS * COLS;
99   for (size_t i = 0; i < len; ++i) {
100     m_data[i] = static_cast<T>(data[i]);
101   }
102 }
103 
104 template <size_t M, size_t N, typename T>
105 template <typename OT>
MatMNT(const MatMNT<M,N,OT> & other)106 MatMNT<M, N, T>::MatMNT(const MatMNT<M, N, OT>& other) {
107   const OT* data = other.data();
108   const size_t len = ROWS * COLS;
109   for (size_t i = 0; i < len; ++i) {
110     m_data[i] = static_cast<T>(data[i]);
111   }
112 }
113 
114 #endif  // ifndef MAT_MNT_H_
115