Fixed some issue with scalar multiplications (explicit) and continued with UNIT tests

This commit is contained in:
Klaus Basan
2013-04-21 01:13:23 +02:00
parent f4affe55ef
commit bd53371de4
16 changed files with 255 additions and 91 deletions

View File

@@ -18,9 +18,10 @@ int BlackMiscTest::CSamplesVectorMatrix::samples()
CMatrix3x3 mr = m; CMatrix3x3 mr = m;
qDebug() << m << mr; qDebug() << m << mr;
mr.setRandom(); mr.setRandom();
CMatrix3x3 mi = mr.inverse(); bool im;
CMatrix3x3 mi = mr.inverse(im);
CMatrix3x3 mid = mr * mi; CMatrix3x3 mid = mr * mi;
qDebug() << mr << mi << mid; qDebug() << mr << mi << mid << im;
// bye // bye
qDebug() << "-----------------------------------------------"; qDebug() << "-----------------------------------------------";

View File

@@ -51,8 +51,10 @@ CCoordinateEcef CCoordinateTransformation::toEcef(const CCoordinateNed &ned)
dcm = dcm1 * dcm2 * dcm3; dcm = dcm1 * dcm2 * dcm3;
bool inverse;
invDcm.setZero(); invDcm.setZero();
invDcm = dcm.inverse(); invDcm = dcm.inverse(inverse);
Q_ASSERT_X(inverse, "toEcef", "Inverse matrix could not be calculated");
CVector3D tempResult = invDcm * ned.toMathVector(); // to generic vector CVector3D tempResult = invDcm * ned.toMathVector(); // to generic vector
CCoordinateEcef result(tempResult); CCoordinateEcef result(tempResult);

View File

@@ -25,18 +25,18 @@ public:
*/ */
CMatrix1x3() : CMatrixBase() {} CMatrix1x3() : CMatrixBase() {}
/*!
* \brief init with value
* \param fillValue
*/
CMatrix1x3(double fillValue) : CMatrixBase(fillValue) {}
/*! /*!
* \brief Copy constructor * \brief Copy constructor
* \param other * \param other
*/ */
CMatrix1x3(const CMatrix1x3 &otherMatrix) : CMatrixBase(otherMatrix) {} CMatrix1x3(const CMatrix1x3 &otherMatrix) : CMatrixBase(otherMatrix) {}
/*!
* \brief Init by fill value
* \param fillValue
*/
explicit CMatrix1x3(double fillValue) : CMatrixBase(fillValue) {}
/*! /*!
* \brief CMatrix 3x1 * \brief CMatrix 3x1
* \param c1 * \param c1

View File

@@ -40,18 +40,18 @@ public:
this->m_matrix(2, 0) = r3; this->m_matrix(2, 0) = r3;
} }
/*!
* \brief init with value
* \param fillValue
*/
CMatrix3x1(qreal fillValue) : CMatrixBase(fillValue) {}
/*! /*!
* \brief Copy constructor * \brief Copy constructor
* \param other * \param other
*/ */
CMatrix3x1(const CMatrix3x1 &otherMatrix) : CMatrixBase(otherMatrix) {} CMatrix3x1(const CMatrix3x1 &otherMatrix) : CMatrixBase(otherMatrix) {}
/*!
* \brief Init by fill value
* \param fillValue
*/
explicit CMatrix3x1(double fillValue) : CMatrixBase(fillValue) {}
/*! /*!
* \brief Convert to vector * \brief Convert to vector
* \return * \return

View File

@@ -13,9 +13,9 @@ namespace Math
/* /*
* Determinant * Determinant
*/ */
qreal CMatrix3x3::determinant() const double CMatrix3x3::determinant() const
{ {
qreal determinant = double determinant =
this->m_matrix(0, 0) * this->m_matrix(1, 1) * this->m_matrix(2, 2) + this->m_matrix(0, 0) * this->m_matrix(1, 1) * this->m_matrix(2, 2) +
this->m_matrix(0, 1) * this->m_matrix(1, 2) * this->m_matrix(2, 0) + this->m_matrix(0, 1) * this->m_matrix(1, 2) * this->m_matrix(2, 0) +
this->m_matrix(0, 2) * this->m_matrix(1, 0) * this->m_matrix(2, 1) - this->m_matrix(0, 2) * this->m_matrix(1, 0) * this->m_matrix(2, 1) -
@@ -27,17 +27,19 @@ qreal CMatrix3x3::determinant() const
} }
/* /*
* Determinant * Inverse
*/ */
CMatrix3x3 CMatrix3x3::inverse() const CMatrix3x3 CMatrix3x3::inverse(bool &invertible) const
{ {
CMatrix3x3 inverse; CMatrix3x3 inverse;
qreal det = determinant(); double det;
if (this->allValuesEqual() || (det = determinant()) == 0)
// should we throw an assert / error here? {
if (det == 0) return inverse; invertible = false;
inverse.setZero();
qreal invdet = 1.0 / det; return inverse;
}
double invdet = 1.0 / det;
inverse.m_matrix(0, 0) = (this->m_matrix(1, 1) * this->m_matrix(2, 2) - this->m_matrix(1, 2) * this->m_matrix(2, 1)) * invdet; inverse.m_matrix(0, 0) = (this->m_matrix(1, 1) * this->m_matrix(2, 2) - this->m_matrix(1, 2) * this->m_matrix(2, 1)) * invdet;
inverse.m_matrix(0, 1) = (- this->m_matrix(0, 1) * this->m_matrix(2, 2) + this->m_matrix(0, 2) * this->m_matrix(2, 1)) * invdet; inverse.m_matrix(0, 1) = (- this->m_matrix(0, 1) * this->m_matrix(2, 2) + this->m_matrix(0, 2) * this->m_matrix(2, 1)) * invdet;
@@ -49,6 +51,7 @@ CMatrix3x3 CMatrix3x3::inverse() const
inverse.m_matrix(2, 1) = (- this->m_matrix(0, 0) * this->m_matrix(2, 1) + this->m_matrix(0, 1) * this->m_matrix(2, 0)) * invdet; inverse.m_matrix(2, 1) = (- this->m_matrix(0, 0) * this->m_matrix(2, 1) + this->m_matrix(0, 1) * this->m_matrix(2, 0)) * invdet;
inverse.m_matrix(2, 2) = (this->m_matrix(0, 0) * this->m_matrix(1, 1) - this->m_matrix(0, 1) * this->m_matrix(1, 0)) * invdet; inverse.m_matrix(2, 2) = (this->m_matrix(0, 0) * this->m_matrix(1, 1) - this->m_matrix(0, 1) * this->m_matrix(1, 0)) * invdet;
invertible = true;
return inverse; return inverse;
} }

View File

@@ -24,18 +24,45 @@ public:
*/ */
CMatrix3x3() : CMatrixBase() {} CMatrix3x3() : CMatrixBase() {}
/*!
* \brief init with value
* \param fillValue
*/
CMatrix3x3(double fillValue) : CMatrixBase(fillValue) {}
/*! /*!
* \brief Copy constructor * \brief Copy constructor
* \param other * \param other
*/ */
CMatrix3x3(const CMatrix3x3 &otherMatrix) : CMatrixBase(otherMatrix) {} CMatrix3x3(const CMatrix3x3 &otherMatrix) : CMatrixBase(otherMatrix) {}
/*!
* \brief Init by fill value
* \param fillValue
*/
explicit CMatrix3x3(double fillValue) : CMatrixBase(fillValue) {}
/*!
* \brief Stupid but handy constructor
* \param r1c1
* \param r1c2
* \param r1c3
* \param r2c1
* \param r2c2
* \param r2c3
* \param r3c1
* \param r3c2
* \param r3c3
*/
explicit CMatrix3x3(double r1c1, double r1c2, double r1c3,
double r2c1, double r2c2, double r2c3,
double r3c1, double r3c2, double r3c3) : CMatrixBase()
{
this->setElement(0, 0, r1c1);
this->setElement(0, 1, r1c2);
this->setElement(0, 2, r1c3);
this->setElement(1, 0, r2c1);
this->setElement(1, 1, r2c2);
this->setElement(1, 2, r2c3);
this->setElement(2, 0, r3c1);
this->setElement(2, 1, r3c2);
this->setElement(2, 2, r3c3);
}
/*! /*!
* \brief Calculates the determinant of the matrix * \brief Calculates the determinant of the matrix
* \return * \return
@@ -44,9 +71,10 @@ public:
/*! /*!
* \brief Calculate the inverse * \brief Calculate the inverse
* \param invertible
* \return * \return
*/ */
CMatrix3x3 inverse() const; CMatrix3x3 inverse(bool &invertible) const;
/*! /*!
* \brief Operator *= * \brief Operator *=
@@ -78,7 +106,7 @@ public:
*/ */
CMatrix3x3 operator *(const CMatrix3x3 &otherMatrix) const CMatrix3x3 operator *(const CMatrix3x3 &otherMatrix) const
{ {
CMatrix3x3 m(otherMatrix); CMatrix3x3 m(*this);
m *= otherMatrix; m *= otherMatrix;
return m; return m;
} }
@@ -95,13 +123,36 @@ public:
return v; return v;
} }
/*!
* \brief Multiply with factor
* \param factor
* \return
*/
CMatrix3x3 operator *(double factor) const
{
CMatrix3x3 m(*this);
m *= factor;
return m;
}
/*!
* \brief Multiply with factor
* \param factor
* \return
*/
CMatrix3x3 &operator *=(double factor)
{
CMatrixBase::operator *=(factor);
return (*this);
}
/*! /*!
* \brief Transposed matrix * \brief Transposed matrix
* \return * \return
*/ */
CMatrix3x3 transposed() const CMatrix3x3 transposed() const
{ {
CMatrix3x3 m(0.0); CMatrix3x3 m(0);
m.m_matrix = this->m_matrix.transposed(); m.m_matrix = this->m_matrix.transposed();
return m; return m;
} }
@@ -126,4 +177,4 @@ public:
} // namespace } // namespace
#endif // BLACKMISC_POSMATRIX3X3_H #endif // guard

View File

@@ -68,6 +68,23 @@ template<class ImplMatrix, int Rows, int Columns> bool CMatrixBase<ImplMatrix, R
return true; return true;
} }
/*
* All values zero?
*/
template<class ImplMatrix, int Rows, int Columns> bool CMatrixBase<ImplMatrix, Rows, Columns>::allValuesEqual() const
{
double v = this->getElement(0,0);
for (int r = 0; r < Rows; r++)
{
for (int c = 0; c < Columns; c++)
{
if (this->m_matrix(r, c) != v) return false;
}
}
return true;
}
/* /*
* Convert to string * Convert to string
*/ */

View File

@@ -37,18 +37,21 @@ public:
*/ */
CMatrixBase() : m_matrix() {} CMatrixBase() : m_matrix() {}
/*!
* \brief Constructor with init value
* \param fillValue
*/
CMatrixBase(double fillValue) : m_matrix() { this->m_matrix.fill(fillValue);}
/*! /*!
* \brief Copy constructor * \brief Copy constructor
* \param other * \param other
*/ */
CMatrixBase(const CMatrixBase &otherMatrix) : m_matrix(otherMatrix.m_matrix) {} CMatrixBase(const CMatrixBase &otherMatrix) : m_matrix(otherMatrix.m_matrix) {}
/*!
* \brief Fill with value
* \param fillValue
*/
explicit CMatrixBase(double fillValue) : m_matrix()
{
this->fill(fillValue);
}
/*! /*!
* \brief Virtual destructor * \brief Virtual destructor
*/ */
@@ -104,9 +107,9 @@ public:
* \param factor * \param factor
* \return * \return
*/ */
CMatrixBase &operator *(double factor) ImplMatrix operator *(double factor) const
{ {
ImplMatrix m(0.0); ImplMatrix m(0);
m += (*this); m += (*this);
m *= factor; m *= factor;
return m; return m;
@@ -135,9 +138,9 @@ public:
* \param factor * \param factor
* \return * \return
*/ */
CMatrixBase &operator /(double factor) ImplMatrix operator /(double factor) const
{ {
ImplMatrix m(0.0); ImplMatrix m(0);
m += (*this); m += (*this);
m /= factor; m /= factor;
return m; return m;
@@ -161,7 +164,7 @@ public:
*/ */
ImplMatrix operator +(const ImplMatrix &otherMatrix) const ImplMatrix operator +(const ImplMatrix &otherMatrix) const
{ {
ImplMatrix m(0.0); ImplMatrix m(0);
m += (*this); m += (*this);
m += otherMatrix; m += otherMatrix;
return m; return m;
@@ -185,7 +188,7 @@ public:
*/ */
ImplMatrix operator -(const ImplMatrix &otherMatrix) const ImplMatrix operator -(const ImplMatrix &otherMatrix) const
{ {
ImplMatrix m(0.0); ImplMatrix m(0);
m += (*this); m += (*this);
m -= otherMatrix; m -= otherMatrix;
return m; return m;
@@ -220,11 +223,17 @@ public:
void setZero() { this->m_matrix.fill(0.0); } void setZero() { this->m_matrix.fill(0.0); }
/*! /*!
* \brief isZero * \brief Is zero
* \return * \return
*/ */
bool isZero() const; bool isZero() const;
/*!
* \brief All values equal, if so matirx is not invertible
* \return
*/
bool allValuesEqual() const;
/*! /*!
* \brief Set a dedicated value * \brief Set a dedicated value
* \param value * \param value

View File

@@ -31,7 +31,7 @@ public:
* \brief Constructor by value * \brief Constructor by value
* \param value * \param value
*/ */
CVector3D(double value) : CVector3DBase(value) {} explicit CVector3D(double value) : CVector3DBase(value) {}
/*! /*!
* \brief Copy constructor * \brief Copy constructor

View File

@@ -46,7 +46,7 @@ protected:
* \brief Constructor by value * \brief Constructor by value
* \param value * \param value
*/ */
CVector3DBase(double value) : m_i(value), m_j(value), m_k(value) {} explicit CVector3DBase(double value) : m_i(value), m_j(value), m_k(value) {}
/*! /*!
* \brief Copy constructor * \brief Copy constructor
@@ -225,6 +225,58 @@ public:
return v; return v;
} }
/*!
* \brief Multiply with scalar
* \param factor
* \return
*/
CVector3DBase &operator *=(double factor)
{
this->m_i *= factor;
this->m_j *= factor;
this->m_k *= factor;
return (*this);
}
/*!
* \brief Multiply with scalar
* \param factor
* \return
*/
ImplClass operator *(double factor) const
{
ImplClass v;
v += (*this);
v *= factor;
return v;
}
/*!
* \brief Divide by scalar
* \param divisor
* \return
*/
CVector3DBase &operator /=(double divisor)
{
this->m_i /= divisor;
this->m_j /= divisor;
this->m_k /= divisor;
return (*this);
}
/*!
* \brief Divide by scalar
* \param divisor
* \return
*/
ImplClass operator /(double divisor) const
{
ImplClass v;
v += (*this);
v /= divisor;
return v;
}
/*! /*!
* \brief Operator /=, just x/x, y/y, z/z * \brief Operator /=, just x/x, y/y, z/z
* \param otherVector * \param otherVector

View File

@@ -11,13 +11,13 @@ INCLUDEPATH += . ../../src
SOURCES += main.cpp testmain.cpp \ SOURCES += main.cpp testmain.cpp \
testphysicalquantitiesbase.cpp \ testphysicalquantitiesbase.cpp \
testaviationbase.cpp \ testaviationbase.cpp \
testvectormatrix.cpp testvectormatrixbase.cpp
HEADERS += testmain.h \ HEADERS += testmain.h \
testphysicalquantitiesbase.h \ testphysicalquantitiesbase.h \
blackmisctest.h \ blackmisctest.h \
testaviationbase.h \ testaviationbase.h \
testvectormatrix.h testvectormatrixbase.h
win32-msvc* { win32-msvc* {
PRE_TARGETDEPS += ../../lib/blackmisc.lib PRE_TARGETDEPS += ../../lib/blackmisc.lib

View File

@@ -16,7 +16,7 @@ int CTestMain::unitMain(int argc, char *argv[])
{ {
CTestPhysicalQuantitiesBase pqBaseTests ; CTestPhysicalQuantitiesBase pqBaseTests ;
CTestAviationBase avBaseTests; CTestAviationBase avBaseTests;
CTestVectorMatrix vmTests; CTestVectorMatrixBase vmTests;
status |= QTest::qExec(&pqBaseTests, argc, argv); status |= QTest::qExec(&pqBaseTests, argc, argv);
status |= QTest::qExec(&avBaseTests, argc, argv); status |= QTest::qExec(&avBaseTests, argc, argv);
status |= QTest::qExec(&vmTests, argc, argv); status |= QTest::qExec(&vmTests, argc, argv);

View File

@@ -8,7 +8,7 @@
#include "testphysicalquantitiesbase.h" #include "testphysicalquantitiesbase.h"
#include "testaviationbase.h" #include "testaviationbase.h"
#include "testvectormatrix.h" #include "testvectormatrixbase.h"
#include <QtTest/QtTest> #include <QtTest/QtTest>
namespace BlackMiscTest namespace BlackMiscTest

View File

@@ -1,35 +0,0 @@
/* Copyright (C) 2013 VATSIM Community / contributors
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "testvectormatrix.h"
using namespace BlackMisc::Math;
namespace BlackMiscTest
{
/*
* Basic tests vector
*/
void CTestVectorMatrix::vectorBasics()
{
}
/*
* Matrix tests
*/
void CTestVectorMatrix::matrixBasics()
{
CMatrix3x3 m1;
CMatrix3x3 m2 = m1 - m1;
QVERIFY2(m1.isIdentity(), "Default matrix should be identity");
QVERIFY2(m2.isZero(), "Matrix should be zero");
}
} // namespace
#include "testvectormatrix.h"

View File

@@ -0,0 +1,64 @@
/* Copyright (C) 2013 VATSIM Community / contributors
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "testvectormatrixbase.h"
using namespace BlackMisc::Math;
namespace BlackMiscTest
{
/*
* Basic tests vector
*/
void CTestVectorMatrixBase::vectorBasics()
{
CVector3D v1(1);
v1 *= 2.0;
CVector3D v2(2);
QVERIFY2(v1 == v2, "Matrix should be zero");
}
/*
* Matrix tests
* http://www.bluebit.gr/matrix-calculator/
*/
void CTestVectorMatrixBase::matrixBasics()
{
CMatrix3x3 m1;
CMatrix3x3 m2 = m1 - m1;
QVERIFY2(m1.isIdentity(), "Default matrix should be identity");
QVERIFY2(m2.isZero(), "Matrix should be zero");
bool invertible;
CMatrix3x3 mr;
CMatrix3x3 msame(3.0);
mr = msame.inverse(invertible);
QVERIFY2(!invertible, "Matrix with sigular values cannot be inverted");
mr.setToIdentity();
QVERIFY2(mr.determinant() == 1, "Identity matrix should have determinant 1");
mr = mr.inverse(invertible);
QVERIFY2(invertible && mr.isIdentity() == 1, "Identity matrix should have inverse identity");
m1.setToIdentity();
m2 = m1 + m1;
m1 = m1 * 2.0;
QVERIFY2(m1 == m2, "2* Identity should be Identity + Identity");
m1 /= 2.0;
m2 -= m1;
QVERIFY2(m1 == m2, "Identity should be Identity");
m1 = CMatrix3x3(1, 5, 3, 2, 4, 7, 4, 6, 2);
double det = m1.determinant();
QVERIFY2(det == 74, qPrintable(QString("Determinant should be 74, but is: %1").arg(det)));
QVERIFY2(m1(0, 0) == 1 && m1(1, 0) == 2 && m1(0, 2) == 3, "Index error");
CMatrix3x3 mi = m1.inverse(invertible);
CMatrix3x3 mid = m1 * mi;
QVERIFY2(mid.isIdentity(), qPrintable(QString("Multiply with inverse should be identity: %1").arg(mid)));
}
} // namespace

View File

@@ -15,7 +15,7 @@ namespace BlackMiscTest
/*! /*!
* \brief Vector and Matrix classes basic tests * \brief Vector and Matrix classes basic tests
*/ */
class CTestVectorMatrix : public QObject class CTestVectorMatrixBase : public QObject
{ {
Q_OBJECT Q_OBJECT
@@ -24,7 +24,7 @@ public:
* \brief Standard test case constructor * \brief Standard test case constructor
* \param parent * \param parent
*/ */
explicit CTestVectorMatrix(QObject *parent = 0) : QObject(parent) {} explicit CTestVectorMatrixBase(QObject *parent = 0) : QObject(parent) {}
private slots: private slots:
/*! /*!