1 /****************************************************************************
2 **
3 ** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of a Qt Solutions component.
8 **
9 ** Commercial Usage
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Solutions Commercial License Agreement provided
12 ** with the Software or, alternatively, in accordance with the terms
13 ** contained in a written agreement between you and Nokia.
14 **
15 ** GNU Lesser General Public License Usage
16 ** Alternatively, this file may be used under the terms of the GNU Lesser
17 ** General Public License version 2.1 as published by the Free Software
18 ** Foundation and appearing in the file LICENSE.LGPL included in the
19 ** packaging of this file.  Please review the following information to
20 ** ensure the GNU Lesser General Public License version 2.1 requirements
21 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22 **
23 ** In addition, as a special exception, Nokia gives you certain
24 ** additional rights. These rights are described in the Nokia Qt LGPL
25 ** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
26 ** package.
27 **
28 ** GNU General Public License Usage
29 ** Alternatively, this file may be used under the terms of the GNU
30 ** General Public License version 3.0 as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL included in the
32 ** packaging of this file.  Please review the following information to
33 ** ensure the GNU General Public License version 3.0 requirements will be
34 ** met: http://www.gnu.org/copyleft/gpl.html.
35 **
36 ** Please note Third Party Software included with Qt Solutions may impose
37 ** additional restrictions and it is the user's responsibility to ensure
38 ** that they have met the licensing requirements of the GPL, LGPL, or Qt
39 ** Solutions Commercial license and the relevant license of the Third
40 ** Party Software they are using.
41 **
42 ** If you are unsure which license is appropriate for your use, please
43 ** contact Nokia at qt-info@nokia.com.
44 **
45 ****************************************************************************/
46 
47 #ifndef QTMATRIX_H
48 #define QTMATRIX_H
49 
50 
51 /**
52  * A general, simple matrix class
53  */
54 
55 template <typename T>
56 class QtMatrix {
57 
58 public:
QtMatrix(int rows,int columns)59     QtMatrix(int rows, int columns)
60     {
61         m_rows = rows;
62         m_cols = columns;
63         m_data = (T*)malloc(m_rows * m_cols * sizeof(T));
64     }
QtMatrix()65     QtMatrix()
66     {
67         m_rows = 0;
68         m_cols = 0;
69         m_data = nullptr;
70     }
QtMatrix(const T * elements,int rows,int columns)71     QtMatrix(const T *elements, int rows, int columns)
72     {
73         m_data = nullptr;
74         set(elements, rows, columns);
75     }
76 
~QtMatrix()77     ~QtMatrix()
78     {
79         if (m_data) free(m_data);
80     }
81 
QtMatrix(const QtMatrix & other)82     QtMatrix(const QtMatrix &other)
83     {
84         m_data = nullptr;
85         set(other);
86     }
87 
88     QtMatrix<T> &operator=(const QtMatrix<T> &other)
89     {
90         set(other);
91         return *this;
92     }
93 
set(const T * data,int rows,int columns)94     void set(const T* data, int rows, int columns)
95     {
96         m_rows = rows;
97         m_cols = columns;
98         m_data = (T*)realloc(m_data, m_rows * m_cols * sizeof(T));
99         memcpy(m_data, data, m_rows * m_cols * sizeof(T));
100     }
101 
setData(int row,int column,const T & value)102     void setData(int row, int column, const T &value)
103     {
104         Q_ASSERT(row < m_rows && column < m_cols);
105         m_data[row * m_cols + column] = value;
106     }
107 
set(const QtMatrix & other)108     void set(const QtMatrix &other)
109     {
110         set(other.m_data, other.rowCount(), other.columnCount());
111     }
112 
fill(const T & value)113     void fill(const T &value)
114     {
115         for (int i = 0; i < m_rows * m_cols; i++) {
116             m_data[i]=value;
117         }
118     }
119 
transposed()120     QtMatrix<T> transposed() const
121     {
122         QtMatrix<T> result(m_cols, m_rows);
123         QtMatrix<T>::transpose(data(), result.data(), m_rows, m_cols);
124         return result;
125     }
126 
127     QtMatrix<T> &operator*=(T scalar)
128     {
129         for (int i = 0; i < m_rows * m_cols; i++) {
130             m_data[i]*=scalar;
131         }
132         return (*this);
133     }
134 
sum()135     T sum() const
136     {
137         T sum = 0;
138         for (int i = 0; i < m_rows * m_cols; i++) {
139             sum+=m_data[i];
140         }
141         return sum;
142     }
143 
convertBasetype()144     QtMatrix<int> convertBasetype()
145     {
146         QtMatrix<int> result( rowCount(), columnCount() );
147         for (int i = 0; i < rowCount() * columnCount(); ++i) {
148             result.data()[i] = qRound(m_data[i]);
149         }
150         return result;
151     }
152 
at(int i)153     T at(int i) const
154     {
155         Q_ASSERT(i < m_rows * m_cols);
156         return m_data[i];
157     }
158 
r_at(int i)159     T &r_at(int i)
160     {
161         Q_ASSERT(i < m_rows * m_cols);
162         return m_data[i];
163     }
164 
at(int row,int column)165     T at(int row, int column) const
166     {
167         Q_ASSERT(row < m_rows && column < m_cols);
168         return m_data[row * m_cols + column];
169     }
170 
r_at(int row,int column)171     T &r_at(int row, int column)
172     {
173         Q_ASSERT(row < m_rows && column < m_cols);
174         return m_data[row * m_cols + column];
175     }
176 
rowCount()177     inline int rowCount() const { return m_rows; }
columnCount()178     inline int columnCount() const { return m_cols; }
179 
data()180     inline T* data() { return m_data; }
data()181     inline T* data() const { return m_data; }
182 
183 private:
resize(int rows,int columns)184     void resize(int rows, int columns)
185     {
186         m_data = (T*)qRealloc(m_data, sizeof(T) * rows * columns);
187     }
188 
189     /**
190      * These inline statics are used by both fixed-size and variable-size matrix classes.
191      */
192     inline static
multiply(const T * left,const T * right,T * result,int lrows,int lcols,int rcols)193     T* multiply( const T *left, const T* right, T* result, int lrows, int lcols, int rcols)
194     {
195         for (int i = 0; i < lrows; i++) {
196             for (int j = 0; j < rcols; j++) {
197                 T sum = 0;
198                 for (int r = 0; r < lcols; r++) {
199                     sum += left[i * lcols + r] * right[r * rcols + j];
200                 }
201                 result[i * rcols + j] = sum;
202             }
203         }
204         return result;
205     }
206 
207     inline static
negate(T * other,int rows,int cols)208     T* negate(T *other, int rows, int cols)
209     {
210         for (int i = 0; i < rows * cols; i++) {
211             other[i] = -other[i];
212         }
213         return other;
214     }
215 
216     inline static
add(T * left,const T * right,int rows,int cols)217     void add(T *left, const T *right, int rows, int cols)
218     {
219         for (int i = 0; i < cols*rows; i++) {
220             left[i] += right[i];
221         }
222     }
223 
224     inline static
sub(T * left,const T * right,int rows,int cols)225     void sub(T *left, const T *right, int rows, int cols)
226     {
227         for (int i = 0; i < cols*rows; i++) {
228             left[i] -= right[i];
229         }
230     }
231 
232     inline static
equals(const T * left,const T * right,int rows,int cols)233     bool equals( const T *left, const T *right, int rows, int cols)
234     {
235         bool eq = true;
236         for (int i = 0; i < cols*rows && eq; i++) {
237             eq = (left[i] == right[i]);
238         }
239         return eq;
240     }
241 
242     inline static
transpose(const T * other,T * result,int rows,int cols)243     T* transpose(const T *other, T *result, int rows, int cols)
244     {
245         for (int r = 0; r < rows; r++) {
246             for (int c = 0; c < cols; c++) {
247                 result[c * rows + r] = other[r * cols + c];
248             }
249         }
250         return result;
251     }
252 
253 private:
254     T*  m_data;
255     int m_rows;
256     int m_cols;
257 };
258 
259 template <typename T>
260 QtMatrix<T> operator*( const QtMatrix<T> &left,
261                         const QtMatrix<T> &right)
262 {
263     Q_ASSERT(left.columnCount() == right.rowCount());
264     if (left.columnCount() != right.rowCount()) return QtMatrix<T>();
265     QtMatrix<T> result(left.rowCount(), right.columnCount());
266     QtMatrix<T>::multiply(left.data(), right.data(), result.data(), left.rowCount(), left.columnCount(), right.columnCount());
267     return result;
268 }
269 
270 template <typename T>
271 QtMatrix<T> operator*(const QtMatrix<T> &left, const T &scalar)
272 {
273     QtMatrix<T> m(left);
274     return m*=scalar;
275 }
276 
277 template <typename T>
278 QtMatrix<T> operator+(const QtMatrix<T> &left, const T &scalar)
279 {
280     QtMatrix<T> m(left);
281     return m+=scalar;
282 }
283 
284 template <typename T1, typename T2>
convertMatrixBasetype(const QtMatrix<T2> & other)285 inline QtMatrix<T1> convertMatrixBasetype(const QtMatrix<T2> &other)
286 {
287     QtMatrix<int> result(other.rowCount(), other.columnCount());
288     for (int i = 0; i < other.rowCount() * other.columnCount();++i) {
289         result.data()[i] = (T1)other.at(i);
290     }
291     return result;
292 }
293 template <> //specialization
294 inline QtMatrix<int> convertMatrixBasetype<int,double>(const QtMatrix<double> &other)
295 {
296     QtMatrix<int> result(other.rowCount(), other.columnCount());
297     for (int i = 0; i < other.rowCount() * other.columnCount();++i) {
298         result.data()[i] = qRound((double)other.at(i));
299     }
300     return result;
301 }
302 
303 
304 #ifndef QT_NO_DEBUG_STREAM
305 #include <QtCore/QDebug>
306 template<typename T>
307 QDebug operator<<(QDebug dbg, const QtMatrix<T> &matrix) {
308     dbg.nospace() << "QtMatrix(";
309         int rows = matrix.rowCount();
310         int cols = matrix.columnCount();
311         dbg << "[";
312         for (int r = 0; r < rows; r++) {
313             dbg << "[";
314             dbg << matrix.getData(r, 0);
315             for (int c = 1; c < cols; c++) {
316                 dbg << ',' << matrix.getData(r, c);
317             }
318             dbg << "]" << "\n";
319         }
320         dbg << "]";
321 
322     dbg << ')';
323     return dbg.space();
324 }
325 #endif
326 
327 #endif //QTMATRIX_H
328 
329