qgenericmatrix.h

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
00004 ** All rights reserved.
00005 ** Contact: Nokia Corporation (qt-info@nokia.com)
00006 **
00007 ** This file is part of the QtGui module of the Qt Toolkit.
00008 **
00009 ** $QT_BEGIN_LICENSE:LGPL$
00010 ** Commercial Usage
00011 ** Licensees holding valid Qt Commercial licenses may use this file in
00012 ** accordance with the Qt Commercial License Agreement provided with the
00013 ** Software or, alternatively, in accordance with the terms contained in
00014 ** a written agreement between you and Nokia.
00015 **
00016 ** GNU Lesser General Public License Usage
00017 ** Alternatively, this file may be used under the terms of the GNU Lesser
00018 ** General Public License version 2.1 as published by the Free Software
00019 ** Foundation and appearing in the file LICENSE.LGPL included in the
00020 ** packaging of this file.  Please review the following information to
00021 ** ensure the GNU Lesser General Public License version 2.1 requirements
00022 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
00023 **
00024 ** In addition, as a special exception, Nokia gives you certain additional
00025 ** rights.  These rights are described in the Nokia Qt LGPL Exception
00026 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this module.
00027 **
00028 ** GNU General Public License Usage
00029 ** Alternatively, this file may be used under the terms of the GNU
00030 ** General Public License version 3.0 as published by the Free Software
00031 ** Foundation and appearing in the file LICENSE.GPL included in the
00032 ** packaging of this file.  Please review the following information to
00033 ** ensure the GNU General Public License version 3.0 requirements will be
00034 ** met: http://www.gnu.org/copyleft/gpl.html.
00035 **
00036 ** If you have questions regarding the use of this file, please contact
00037 ** Nokia at qt-info@nokia.com.
00038 ** $QT_END_LICENSE$
00039 **
00040 ****************************************************************************/
00041 
00042 #ifndef QGENERICMATRIX_H
00043 #define QGENERICMATRIX_H
00044 
00045 #include <QtCore/qmetatype.h>
00046 #include <QtCore/qdebug.h>
00047 #include <QtCore/qdatastream.h>
00048 
00049 QT_BEGIN_HEADER
00050 
00051 QT_BEGIN_NAMESPACE
00052 
00053 QT_MODULE(Gui)
00054 
00055 template <int N, int M, typename T>
00056 class QGenericMatrix
00057 {
00058 public:
00059     QGenericMatrix();
00060     QGenericMatrix(const QGenericMatrix<N, M, T>& other);
00061     explicit QGenericMatrix(const T *values);
00062 
00063     const T& operator()(int row, int column) const;
00064     T& operator()(int row, int column);
00065 
00066     bool isIdentity() const;
00067     void setToIdentity();
00068 
00069     void fill(T value);
00070 
00071     QGenericMatrix<M, N, T> transposed() const;
00072 
00073     QGenericMatrix<N, M, T>& operator+=(const QGenericMatrix<N, M, T>& other);
00074     QGenericMatrix<N, M, T>& operator-=(const QGenericMatrix<N, M, T>& other);
00075     QGenericMatrix<N, M, T>& operator*=(T factor);
00076     QGenericMatrix<N, M, T>& operator/=(T divisor);
00077     bool operator==(const QGenericMatrix<N, M, T>& other) const;
00078     bool operator!=(const QGenericMatrix<N, M, T>& other) const;
00079 
00080     void copyDataTo(T *values) const;
00081 
00082     T *data() { return m[0]; }
00083     const T *data() const { return m[0]; }
00084     const T *constData() const { return m[0]; }
00085 
00086 #if !defined(Q_NO_TEMPLATE_FRIENDS)
00087     template<int NN, int MM, typename TT>
00088     friend QGenericMatrix<NN, MM, TT> operator+(const QGenericMatrix<NN, MM, TT>& m1, const QGenericMatrix<NN, MM, TT>& m2);
00089     template<int NN, int MM, typename TT>
00090     friend QGenericMatrix<NN, MM, TT> operator-(const QGenericMatrix<NN, MM, TT>& m1, const QGenericMatrix<NN, MM, TT>& m2);
00091     template<int NN, int M1, int M2, typename TT>
00092     friend QGenericMatrix<M1, M2, TT> operator*(const QGenericMatrix<NN, M2, TT>& m1, const QGenericMatrix<M1, NN, TT>& m2);
00093     template<int NN, int MM, typename TT>
00094     friend QGenericMatrix<NN, MM, TT> operator-(const QGenericMatrix<NN, MM, TT>& matrix);
00095     template<int NN, int MM, typename TT>
00096     friend QGenericMatrix<NN, MM, TT> operator*(TT factor, const QGenericMatrix<NN, MM, TT>& matrix);
00097     template<int NN, int MM, typename TT>
00098     friend QGenericMatrix<NN, MM, TT> operator*(const QGenericMatrix<NN, MM, TT>& matrix, TT factor);
00099     template<int NN, int MM, typename TT>
00100     friend QGenericMatrix<NN, MM, TT> operator/(const QGenericMatrix<NN, MM, TT>& matrix, TT divisor);
00101 
00102 private:
00103 #endif
00104     T m[N][M];    // Column-major order to match OpenGL.
00105 
00106     QGenericMatrix(int) {}       // Construct without initializing identity matrix.
00107 
00108 #if !defined(Q_NO_TEMPLATE_FRIENDS)
00109     template <int NN, int MM, typename TT>
00110     friend class QGenericMatrix;
00111 #endif
00112 };
00113 
00114 template <int N, int M, typename T>
00115 Q_INLINE_TEMPLATE QGenericMatrix<N, M, T>::QGenericMatrix()
00116 {
00117     setToIdentity();
00118 }
00119 
00120 template <int N, int M, typename T>
00121 Q_INLINE_TEMPLATE QGenericMatrix<N, M, T>::QGenericMatrix(const QGenericMatrix<N, M, T>& other)
00122 {
00123     for (int col = 0; col < N; ++col)
00124         for (int row = 0; row < M; ++row)
00125             m[col][row] = other.m[col][row];
00126 }
00127 
00128 template <int N, int M, typename T>
00129 Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T>::QGenericMatrix(const T *values)
00130 {
00131     for (int col = 0; col < N; ++col)
00132         for (int row = 0; row < M; ++row)
00133             m[col][row] = values[row * N + col];
00134 }
00135 
00136 template <int N, int M, typename T>
00137 Q_INLINE_TEMPLATE const T& QGenericMatrix<N, M, T>::operator()(int row, int column) const
00138 {
00139     Q_ASSERT(row >= 0 && row < M && column >= 0 && column < N);
00140     return m[column][row];
00141 }
00142 
00143 template <int N, int M, typename T>
00144 Q_INLINE_TEMPLATE T& QGenericMatrix<N, M, T>::operator()(int row, int column)
00145 {
00146     Q_ASSERT(row >= 0 && row < M && column >= 0 && column < N);
00147     return m[column][row];
00148 }
00149 
00150 template <int N, int M, typename T>
00151 Q_OUTOFLINE_TEMPLATE bool QGenericMatrix<N, M, T>::isIdentity() const
00152 {
00153     for (int col = 0; col < N; ++col) {
00154         for (int row = 0; row < M; ++row) {
00155             if (row == col) {
00156                 if (m[col][row] != 1.0f)
00157                     return false;
00158             } else {
00159                 if (m[col][row] != 0.0f)
00160                     return false;
00161             }
00162         }
00163     }
00164     return true;
00165 }
00166 
00167 template <int N, int M, typename T>
00168 Q_OUTOFLINE_TEMPLATE void QGenericMatrix<N, M, T>::setToIdentity()
00169 {
00170     for (int col = 0; col < N; ++col) {
00171         for (int row = 0; row < M; ++row) {
00172             if (row == col)
00173                 m[col][row] = 1.0f;
00174             else
00175                 m[col][row] = 0.0f;
00176         }
00177     }
00178 }
00179 
00180 template <int N, int M, typename T>
00181 Q_OUTOFLINE_TEMPLATE void QGenericMatrix<N, M, T>::fill(T value)
00182 {
00183     for (int col = 0; col < N; ++col)
00184         for (int row = 0; row < M; ++row)
00185             m[col][row] = value;
00186 }
00187 
00188 template <int N, int M, typename T>
00189 Q_OUTOFLINE_TEMPLATE QGenericMatrix<M, N, T> QGenericMatrix<N, M, T>::transposed() const
00190 {
00191     QGenericMatrix<M, N, T> result(1);
00192     for (int row = 0; row < M; ++row)
00193         for (int col = 0; col < N; ++col)
00194             result.m[row][col] = m[col][row];
00195     return result;
00196 }
00197 
00198 template <int N, int M, typename T>
00199 Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T>& QGenericMatrix<N, M, T>::operator+=(const QGenericMatrix<N, M, T>& other)
00200 {
00201     for (int index = 0; index < N * M; ++index)
00202         m[0][index] += other.m[0][index];
00203     return *this;
00204 }
00205 
00206 template <int N, int M, typename T>
00207 Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T>& QGenericMatrix<N, M, T>::operator-=(const QGenericMatrix<N, M, T>& other)
00208 {
00209     for (int index = 0; index < N * M; ++index)
00210         m[0][index] -= other.m[0][index];
00211     return *this;
00212 }
00213 
00214 template <int N, int M, typename T>
00215 Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T>& QGenericMatrix<N, M, T>::operator*=(T factor)
00216 {
00217     for (int index = 0; index < N * M; ++index)
00218         m[0][index] *= factor;
00219     return *this;
00220 }
00221 
00222 template <int N, int M, typename T>
00223 Q_OUTOFLINE_TEMPLATE bool QGenericMatrix<N, M, T>::operator==(const QGenericMatrix<N, M, T>& other) const
00224 {
00225     for (int index = 0; index < N * M; ++index) {
00226         if (m[0][index] != other.m[0][index])
00227             return false;
00228     }
00229     return true;
00230 }
00231 
00232 template <int N, int M, typename T>
00233 Q_OUTOFLINE_TEMPLATE bool QGenericMatrix<N, M, T>::operator!=(const QGenericMatrix<N, M, T>& other) const
00234 {
00235     for (int index = 0; index < N * M; ++index) {
00236         if (m[0][index] != other.m[0][index])
00237             return true;
00238     }
00239     return false;
00240 }
00241 
00242 template <int N, int M, typename T>
00243 Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T>& QGenericMatrix<N, M, T>::operator/=(T divisor)
00244 {
00245     for (int index = 0; index < N * M; ++index)
00246         m[0][index] /= divisor;
00247     return *this;
00248 }
00249 
00250 template <int N, int M, typename T>
00251 Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T> operator+(const QGenericMatrix<N, M, T>& m1, const QGenericMatrix<N, M, T>& m2)
00252 {
00253     QGenericMatrix<N, M, T> result(1);
00254     for (int index = 0; index < N * M; ++index)
00255         result.m[0][index] = m1.m[0][index] + m2.m[0][index];
00256     return result;
00257 }
00258 
00259 template <int N, int M, typename T>
00260 Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T> operator-(const QGenericMatrix<N, M, T>& m1, const QGenericMatrix<N, M, T>& m2)
00261 {
00262     QGenericMatrix<N, M, T> result(1);
00263     for (int index = 0; index < N * M; ++index)
00264         result.m[0][index] = m1.m[0][index] - m2.m[0][index];
00265     return result;
00266 }
00267 
00268 template <int N, int M1, int M2, typename T>
00269 Q_OUTOFLINE_TEMPLATE QGenericMatrix<M1, M2, T> operator*(const QGenericMatrix<N, M2, T>& m1, const QGenericMatrix<M1, N, T>& m2)
00270 {
00271     QGenericMatrix<M1, M2, T> result(1);
00272     for (int row = 0; row < M2; ++row) {
00273         for (int col = 0; col < M1; ++col) {
00274             T sum(0.0f);
00275             for (int j = 0; j < N; ++j)
00276                 sum += m1.m[j][row] * m2.m[col][j];
00277             result.m[col][row] = sum;
00278         }
00279     }
00280     return result;
00281 }
00282 
00283 template <int N, int M, typename T>
00284 Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T> operator-(const QGenericMatrix<N, M, T>& matrix)
00285 {
00286     QGenericMatrix<N, M, T> result(1);
00287     for (int index = 0; index < N * M; ++index)
00288         result.m[0][index] = -matrix.m[0][index];
00289     return result;
00290 }
00291 
00292 template <int N, int M, typename T>
00293 Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T> operator*(T factor, const QGenericMatrix<N, M, T>& matrix)
00294 {
00295     QGenericMatrix<N, M, T> result(1);
00296     for (int index = 0; index < N * M; ++index)
00297         result.m[0][index] = matrix.m[0][index] * factor;
00298     return result;
00299 }
00300 
00301 template <int N, int M, typename T>
00302 Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T> operator*(const QGenericMatrix<N, M, T>& matrix, T factor)
00303 {
00304     QGenericMatrix<N, M, T> result(1);
00305     for (int index = 0; index < N * M; ++index)
00306         result.m[0][index] = matrix.m[0][index] * factor;
00307     return result;
00308 }
00309 
00310 template <int N, int M, typename T>
00311 Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T> operator/(const QGenericMatrix<N, M, T>& matrix, T divisor)
00312 {
00313     QGenericMatrix<N, M, T> result(1);
00314     for (int index = 0; index < N * M; ++index)
00315         result.m[0][index] = matrix.m[0][index] / divisor;
00316     return result;
00317 }
00318 
00319 template <int N, int M, typename T>
00320 Q_OUTOFLINE_TEMPLATE void QGenericMatrix<N, M, T>::copyDataTo(T *values) const
00321 {
00322     for (int col = 0; col < N; ++col)
00323         for (int row = 0; row < M; ++row)
00324             values[row * N + col] = T(m[col][row]);
00325 }
00326 
00327 // Define aliases for the useful variants of QGenericMatrix.
00328 typedef QGenericMatrix<2, 2, qreal> QMatrix2x2;
00329 typedef QGenericMatrix<2, 3, qreal> QMatrix2x3;
00330 typedef QGenericMatrix<2, 4, qreal> QMatrix2x4;
00331 typedef QGenericMatrix<3, 2, qreal> QMatrix3x2;
00332 typedef QGenericMatrix<3, 3, qreal> QMatrix3x3;
00333 typedef QGenericMatrix<3, 4, qreal> QMatrix3x4;
00334 typedef QGenericMatrix<4, 2, qreal> QMatrix4x2;
00335 typedef QGenericMatrix<4, 3, qreal> QMatrix4x3;
00336 
00337 #ifndef QT_NO_DEBUG_STREAM
00338 
00339 template <int N, int M, typename T>
00340 QDebug operator<<(QDebug dbg, const QGenericMatrix<N, M, T> &m)
00341 {
00342     dbg.nospace() << "QGenericMatrix<" << N << ", " << M
00343         << ", " << QTypeInfo<T>::name()
00344         << ">(" << endl << qSetFieldWidth(10);
00345     for (int row = 0; row < M; ++row) {
00346         for (int col = 0; col < N; ++col)
00347             dbg << m(row, col);
00348         dbg << endl;
00349     }
00350     dbg << qSetFieldWidth(0) << ')';
00351     return dbg.space();
00352 }
00353 
00354 #endif
00355 
00356 #ifndef QT_NO_DATASTREAM
00357 
00358 template <int N, int M, typename T>
00359 QDataStream &operator<<(QDataStream &stream, const QGenericMatrix<N, M, T> &matrix)
00360 {
00361     for (int row = 0; row < M; ++row)
00362         for (int col = 0; col < N; ++col)
00363             stream << double(matrix(row, col));
00364     return stream;
00365 }
00366 
00367 template <int N, int M, typename T>
00368 QDataStream &operator>>(QDataStream &stream, QGenericMatrix<N, M, T> &matrix)
00369 {
00370     double x;
00371     for (int row = 0; row < M; ++row) {
00372         for (int col = 0; col < N; ++col) {
00373             stream >> x;
00374             matrix(row, col) = T(x);
00375         }
00376     }
00377     return stream;
00378 }
00379 
00380 #endif
00381 
00382 QT_END_NAMESPACE
00383 
00384 Q_DECLARE_METATYPE(QMatrix2x2)
00385 Q_DECLARE_METATYPE(QMatrix2x3)
00386 Q_DECLARE_METATYPE(QMatrix2x4)
00387 Q_DECLARE_METATYPE(QMatrix3x2)
00388 Q_DECLARE_METATYPE(QMatrix3x3)
00389 Q_DECLARE_METATYPE(QMatrix3x4)
00390 Q_DECLARE_METATYPE(QMatrix4x2)
00391 Q_DECLARE_METATYPE(QMatrix4x3)
00392 
00393 QT_END_HEADER
00394 
00395 #endif