Fixed all issues detected by the test cases under MinGW - such as usage of abs() -> changed to qAbs(), rounding issues detected during calculations, and changed streaming methods with qDebug() (QDebug vs &QDebug issue).

This commit is contained in:
Klaus Basan
2013-04-30 01:43:14 +02:00
parent c6426a0759
commit 8f5d9263fd
11 changed files with 70 additions and 38 deletions

View File

@@ -17,6 +17,7 @@ namespace BlackMiscTest
int CSamplesAviation::samples() int CSamplesAviation::samples()
{ {
// CSpeed s1(10, CSpeedUnit::kts()); // CSpeed s1(10, CSpeedUnit::kts());
CMeasurementPrefix p1 = CMeasurementPrefix::G(); CMeasurementPrefix p1 = CMeasurementPrefix::G();
CAngle a(10, CAngleUnit::deg()); CAngle a(10, CAngleUnit::deg());
qDebug() << a; qDebug() << a;

View File

@@ -2,7 +2,7 @@
using namespace BlackMisc::Math; using namespace BlackMisc::Math;
/*! /*
* Run the samples * Run the samples
*/ */
int BlackMiscTest::CSamplesVectorMatrix::samples() int BlackMiscTest::CSamplesVectorMatrix::samples()

View File

@@ -20,12 +20,27 @@ template <class UsingClass> class CBaseStreamStringifier
* \param uc * \param uc
* \return * \return
*/ */
friend QDebug &operator<<(QDebug &debug, const UsingClass &uc) friend QDebug operator<<(QDebug debug, const UsingClass &uc)
{ {
const CBaseStreamStringifier &s = uc; const CBaseStreamStringifier &sf = uc; // allows to acces protected method
debug << s.stringForStreaming(); debug << sf.stringForStreaming();
return debug; return debug;
} }
// msvc2010: friend QDebug &operator<<(QDebug &debug, const UsingClass &uc)
// MinGW: No reference
/*!
* \brief Operator << based on text stream
* \param textStream
* \param uc
* \return
*/
friend QTextStream &operator<<(QTextStream &textStream, const UsingClass &uc)
{
const CBaseStreamStringifier &sf = uc; // allows to acces protected method
textStream << sf.stringForStreaming();
return textStream;
}
/*! /*!
* \brief Operator << when there is no debug stream * \brief Operator << when there is no debug stream
@@ -46,8 +61,8 @@ template <class UsingClass> class CBaseStreamStringifier
*/ */
friend QDataStream &operator<<(QDataStream &stream, const UsingClass &uc) friend QDataStream &operator<<(QDataStream &stream, const UsingClass &uc)
{ {
const CBaseStreamStringifier &s = uc; const CBaseStreamStringifier &sf = uc; // allows to acces protected method
stream << s.stringForStreaming(); stream << sf.stringForStreaming();
return stream; return stream;
} }
@@ -59,8 +74,8 @@ template <class UsingClass> class CBaseStreamStringifier
*/ */
friend CLogMessage &operator<<(CLogMessage &log, const UsingClass &uc) friend CLogMessage &operator<<(CLogMessage &log, const UsingClass &uc)
{ {
const CBaseStreamStringifier &s = uc; const CBaseStreamStringifier &sf = uc; // allows to acces protected method
log << s.stringForStreaming(); log << sf.stringForStreaming();
return log; return log;
} }
@@ -72,8 +87,8 @@ template <class UsingClass> class CBaseStreamStringifier
*/ */
friend std::ostream &operator<<(std::ostream &ostr, const UsingClass &uc) friend std::ostream &operator<<(std::ostream &ostr, const UsingClass &uc)
{ {
const CBaseStreamStringifier &s = uc; const CBaseStreamStringifier &sf = uc; // allows to acces protected method
ostr << s.stringForStreaming().toStdString(); ostr << sf.stringForStreaming().toStdString();
return ostr; return ostr;
} }

View File

@@ -66,8 +66,6 @@ CCoordinateEcef CCoordinateTransformation::toEcef(const CCoordinateNed &ned)
*/ */
CCoordinateEcef CCoordinateTransformation::toEcef(const CCoordinateGeodetic &geo) CCoordinateEcef CCoordinateTransformation::toEcef(const CCoordinateGeodetic &geo)
{ {
// TODO: Clarify the comparisons with fixed angles (==90, ==180) -> what happens here
CLatitude lat = geo.latitude(); CLatitude lat = geo.latitude();
CLongitude lon = geo.longitude(); CLongitude lon = geo.longitude();
@@ -96,10 +94,9 @@ CCoordinateEcef CCoordinateTransformation::toEcef(const CCoordinateGeodetic &geo
*/ */
CCoordinateNed CCoordinateTransformation::toNed(const CCoordinateEcef &ecef, const CCoordinateGeodetic &referencePosition) CCoordinateNed CCoordinateTransformation::toNed(const CCoordinateEcef &ecef, const CCoordinateGeodetic &referencePosition)
{ {
CLatitude lat = referencePosition.latitude(); CLatitude lat = referencePosition.latitude();
CLongitude lon = referencePosition.longitude(); CLongitude lon = referencePosition.longitude();
double angleRad = - (lat.value(CAngleUnit::rad())) - CMath::PI() / 2; double angleRad = - (lat.value(CAngleUnit::rad())) - CMath::PIHALF();
CMatrix3x3 dcm1; CMatrix3x3 dcm1;
CMatrix3x3 dcm2(0.0); CMatrix3x3 dcm2(0.0);

View File

@@ -46,7 +46,7 @@ private:
*/ */
static const double &Flattening() static const double &Flattening()
{ {
static double f = 1 / 298.257223563; static double f = 1.0 / 298.257223563;
return f; return f;
} }
@@ -76,7 +76,7 @@ private:
*/ */
static const double &e2abs() static const double &e2abs()
{ {
static double e2abs = abs(e2()); static double e2abs = qAbs(e2());
return e2abs; return e2abs;
} }
@@ -86,7 +86,7 @@ private:
*/ */
static const double &e2m() static const double &e2m()
{ {
static double e2m = BlackMisc::Math::CMath::square(1 - Flattening()); static double e2m = BlackMisc::Math::CMath::square(1.0 - Flattening());
return e2m; return e2m;
} }
@@ -95,7 +95,6 @@ private:
*/ */
CCoordinateTransformation() {} CCoordinateTransformation() {}
public: public:
/*! /*!
* \brief NED to ECEF * \brief NED to ECEF

View File

@@ -1,10 +1,10 @@
/* Copyright (C) 2013 VATSIM Community / authors /* Copyright (C) 2013 VATSIM Community / contributors
* This Source Code Form is subject to the terms of the Mozilla Public * 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 * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "blackmisc/mathematics.h" #include "blackmisc/mathematics.h"
#include <algorithm> // std::max #include <algorithm> // std::max
#include <cmath> #include <cmath>
namespace BlackMisc namespace BlackMisc
@@ -17,8 +17,8 @@ namespace Math
*/ */
double CMath::hypot(double x, double y) double CMath::hypot(double x, double y)
{ {
x = abs(x); x = qAbs(x);
y = abs(y); y = qAbs(y);
double max = std::max(x, y); double max = std::max(x, y);
double min = std::min(x, y); double min = std::min(x, y);
double r = min / max; double r = min / max;
@@ -31,7 +31,7 @@ double CMath::hypot(double x, double y)
double CMath::cubicRootReal(double x) double CMath::cubicRootReal(double x)
{ {
double result; double result;
result = std::pow(std::abs(x), (double)1 / 3); result = std::pow(qAbs(x), (double)1.0 / 3.0);
return x < 0 ? -result : result; return x < 0 ? -result : result;
} }

View File

@@ -70,6 +70,16 @@ public:
*/ */
static double roundEpsilon(double value, double epsilon); static double roundEpsilon(double value, double epsilon);
/*!
* \brief PI
* \return
*/
static const double &PIHALF()
{
static double pi = 2.0 * qAtan(1.0);
return pi;
}
/*! /*!
* \brief PI * \brief PI
* \return * \return
@@ -86,7 +96,7 @@ public:
*/ */
static const double &PI2() static const double &PI2()
{ {
static double pi2 = PI(); static double pi2 = 8.0 * qAtan(1.0);
return pi2; return pi2;
} }

View File

@@ -57,26 +57,29 @@ template <class MU, class PQ> bool CPhysicalQuantity<MU, PQ>::operator ==(const
// some special cases for best quality // some special cases for best quality
double diff; double diff;
const double lenient = 1.001; // even diff already has a rounding issue to be avoided const double lenient = 1.001; // even diff already has a rounding issue to be avoided
bool eq = false;
if (this->m_unit == otherQuantity.m_unit) if (this->m_unit == otherQuantity.m_unit)
{ {
// same unit // same unit
if (this->m_isIntegerBaseValue && otherQuantity.m_isIntegerBaseValue) if (this->m_isIntegerBaseValue && otherQuantity.m_isIntegerBaseValue)
{ {
// pure integer comparison, no rounding issues // pure integer comparison, no rounding issues
return this->m_unitValueI == otherQuantity.m_unitValueI; eq = this->m_unitValueI == otherQuantity.m_unitValueI;
} }
else else
{ {
diff = abs(this->m_unitValueD - otherQuantity.m_unitValueD); // same unit, comparison based on double
return diff <= (lenient * this->m_unit.getEpsilon()); diff = qAbs(this->m_unitValueD - otherQuantity.m_unitValueD);
eq = diff <= (lenient * this->m_unit.getEpsilon());
} }
} }
else else
{ {
// based on SI value // based on SI value
diff = abs(this->m_convertedSiUnitValueD - otherQuantity.m_convertedSiUnitValueD); diff = qAbs(this->m_convertedSiUnitValueD - otherQuantity.m_convertedSiUnitValueD);
return diff <= (lenient * this->m_unit.getEpsilon()); eq = diff <= (lenient * this->m_conversionSiUnit.getEpsilon());
} }
return eq;
} }
/* /*
@@ -89,7 +92,7 @@ template <class MU, class PQ> bool CPhysicalQuantity<MU, PQ>::operator !=(const
} }
/* /*
* Assigment operator = * Assignment operator =
*/ */
template <class MU, class PQ> CPhysicalQuantity<MU, PQ>& CPhysicalQuantity<MU, PQ>::operator=(const CPhysicalQuantity<MU, PQ> &otherQuantity) template <class MU, class PQ> CPhysicalQuantity<MU, PQ>& CPhysicalQuantity<MU, PQ>::operator=(const CPhysicalQuantity<MU, PQ> &otherQuantity)
{ {
@@ -238,9 +241,11 @@ template <class MU, class PQ> PQ CPhysicalQuantity<MU, PQ>::operator /(double di
*/ */
template <class MU, class PQ> bool CPhysicalQuantity<MU, PQ>::operator <(const CPhysicalQuantity<MU, PQ> &otherQuantity) const template <class MU, class PQ> bool CPhysicalQuantity<MU, PQ>::operator <(const CPhysicalQuantity<MU, PQ> &otherQuantity) const
{ {
if (this == &otherQuantity) return false; if ((*this) == otherQuantity) return false;
// == considers epsilon, so we now have a diff > epsilon here
double diff = this->m_convertedSiUnitValueD - otherQuantity.m_convertedSiUnitValueD; double diff = this->m_convertedSiUnitValueD - otherQuantity.m_convertedSiUnitValueD;
return (diff < 0 && abs(diff) >= this->m_unit.getEpsilon()); return (diff < 0);
} }
/* /*
@@ -249,7 +254,7 @@ template <class MU, class PQ> bool CPhysicalQuantity<MU, PQ>::operator <(const C
template <class MU, class PQ> bool CPhysicalQuantity<MU, PQ>::operator >(const CPhysicalQuantity<MU, PQ> &otherQuantity) const template <class MU, class PQ> bool CPhysicalQuantity<MU, PQ>::operator >(const CPhysicalQuantity<MU, PQ> &otherQuantity) const
{ {
if (this == &otherQuantity) return false; if (this == &otherQuantity) return false;
return otherQuantity < *this; return otherQuantity < (*this);
} }
/* /*

View File

@@ -32,7 +32,8 @@ void CTestAviation::headingBasics()
h4 = h1; h4 = h1;
QVERIFY2(h1 != h2, "Magnetic and true heading are not the same"); QVERIFY2(h1 != h2, "Magnetic and true heading are not the same");
QVERIFY2(h1 < h3, "180deg are less than 181deg"); QVERIFY2(h1 < h3, "180deg are less than 181deg");
QVERIFY2(a1 > h3, "200deg are more than 200deg"); QVERIFY2(h3 > h1, "181deg are more than 181deg");
QVERIFY2(a1 > h3, "200deg are more than 181deg");
QVERIFY2(h4 == h1, "Values shall be equal"); QVERIFY2(h4 == h1, "Values shall be equal");
h1 -= h1; h1 -= h1;

View File

@@ -20,12 +20,14 @@ void CTestGeo::geoBasics()
CCoordinateGeodetic startGeoVec(lat, lon, h); CCoordinateGeodetic startGeoVec(lat, lon, h);
CCoordinateEcef mediumEcefVec = CCoordinateTransformation::toEcef(startGeoVec); CCoordinateEcef mediumEcefVec = CCoordinateTransformation::toEcef(startGeoVec);
CCoordinateGeodetic endGeoVec = CCoordinateTransformation::toGeodetic(mediumEcefVec); CCoordinateGeodetic endGeoVec = CCoordinateTransformation::toGeodetic(mediumEcefVec);
// this == contains some implicit rounding, since it is based on PQs
QVERIFY2(startGeoVec == endGeoVec, "Reconverted geo vector should be equal "); QVERIFY2(startGeoVec == endGeoVec, "Reconverted geo vector should be equal ");
CCoordinateNed nedVec = CCoordinateTransformation::toNed(mediumEcefVec, startGeoVec); CCoordinateNed nedVec = CCoordinateTransformation::toNed(mediumEcefVec, startGeoVec);
CCoordinateEcef ecefReconvert = CCoordinateTransformation::toEcef(nedVec); CCoordinateEcef ecefReconvert = CCoordinateTransformation::toEcef(nedVec);
QVERIFY2(mediumEcefVec != ecefReconvert, "Reconverted geo vector, expect some minor rounding issues"); // check against rounded reconvert
QVERIFY2(mediumEcefVec.round() == ecefReconvert.round(), "Reconverted geo vector should be equal"); QVERIFY2(mediumEcefVec.round() == ecefReconvert.round(), "Reconverted geo vector should be equal");
} }

View File

@@ -53,12 +53,14 @@ void CTestPhysicalQuantities::lengthBasics()
QVERIFY2(!(d1 > d2), "Nothing shall be less / greater"); QVERIFY2(!(d1 > d2), "Nothing shall be less / greater");
// epsilon tests // epsilon tests
d1 = d2; // both in same unit
d1.addUnitValue(d1.getUnit().getEpsilon()); // this should be still the same d1.addUnitValue(d1.getUnit().getEpsilon()); // this should be still the same
QVERIFY2(d1 == d2, "Epsilon: 1meter+epsilon shall be 100cm"); QVERIFY2(d1 == d2, "Epsilon: 100cm + epsilon shall be 100cm");
QVERIFY2(!(d1 != d2), "Epsilon: 1meter+epsilon shall be 100cm"); QVERIFY2(!(d1 != d2), "Epsilon: 100cm + epsilon shall be still 100cm");
QVERIFY2(!(d1 > d2), "d1 shall not be greater");
d1.addUnitValue(d1.getUnit().getEpsilon()); // now over epsilon threshold d1.addUnitValue(d1.getUnit().getEpsilon()); // now over epsilon threshold
QVERIFY2(d1 != d2, "Epsilon exceeded: 1meter+2epsilon shall not be 100cm"); QVERIFY2(d1 != d2, "Epsilon exceeded: 100 cm + 2 epsilon shall not be 100cm");
QVERIFY2(d1 > d2, "d1 shall be greater"); QVERIFY2(d1 > d2, "d1 shall be greater");
} }