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