mirror of https://github.com/mosra/magnum.git
Browse Source
Fuzzy comparison is implemented only on floating-point types with type-specific epsilon, on integral types classic operator== is used. TypeTraits class is now extension of Math::TypeTraits (where it makes sense).pull/279/head
5 changed files with 232 additions and 17 deletions
@ -0,0 +1,60 @@
|
||||
/*
|
||||
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
This file is part of Magnum. |
||||
|
||||
Magnum is free software: you can redistribute it and/or modify |
||||
it under the terms of the GNU Lesser General Public License version 3 |
||||
only, as published by the Free Software Foundation. |
||||
|
||||
Magnum is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU Lesser General Public License version 3 for more details. |
||||
*/ |
||||
|
||||
#include "TypeTraitsTest.h" |
||||
|
||||
#include <QtTest/QTest> |
||||
|
||||
#include "TypeTraits.h" |
||||
|
||||
QTEST_APPLESS_MAIN(Magnum::Math::Test::TypeTraitsTest) |
||||
|
||||
namespace Magnum { namespace Math { namespace Test { |
||||
|
||||
void TypeTraitsTest::equalsIntegral() { |
||||
_equalsIntegral<unsigned char>(); |
||||
_equalsIntegral<char>(); |
||||
_equalsIntegral<unsigned short>(); |
||||
_equalsIntegral<short>(); |
||||
_equalsIntegral<unsigned int>(); |
||||
_equalsIntegral<int>(); |
||||
_equalsIntegral<unsigned long int>(); |
||||
_equalsIntegral<long int>(); |
||||
_equalsIntegral<unsigned long long>(); |
||||
_equalsIntegral<long long>(); |
||||
} |
||||
|
||||
void TypeTraitsTest::equalsFloatingPoint() { |
||||
_equalsFloatingPoint<float>(); |
||||
_equalsFloatingPoint<double>(); |
||||
} |
||||
|
||||
template<class T> void TypeTraitsTest::_equalsIntegral() { |
||||
QVERIFY(TypeTraits<T>::equals(1, 1+TypeTraits<T>::epsilon())); |
||||
QVERIFY(!TypeTraits<T>::equals(1, 2)); |
||||
} |
||||
|
||||
template<class T> void TypeTraitsTest::_equalsFloatingPoint() { |
||||
QVERIFY(TypeTraits<T>::equals(1.0f+TypeTraits<T>::epsilon()/2, 1.0f)); |
||||
QVERIFY(!TypeTraits<T>::equals(1.0f+TypeTraits<T>::epsilon()*2, 1.0f)); |
||||
|
||||
QEXPECT_FAIL(0, "Comparing to infinity is broken", Continue); |
||||
QVERIFY(TypeTraits<T>::equals(std::numeric_limits<T>::infinity(), |
||||
std::numeric_limits<T>::infinity())); |
||||
QVERIFY(!TypeTraits<T>::equals(std::numeric_limits<T>::quiet_NaN(), |
||||
std::numeric_limits<T>::quiet_NaN())); |
||||
} |
||||
|
||||
}}} |
||||
@ -0,0 +1,36 @@
|
||||
#ifndef Magnum_Math_Test_TypeTraitsTest_h |
||||
#define Magnum_Math_Test_TypeTraitsTest_h |
||||
/*
|
||||
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
This file is part of Magnum. |
||||
|
||||
Magnum is free software: you can redistribute it and/or modify |
||||
it under the terms of the GNU Lesser General Public License version 3 |
||||
only, as published by the Free Software Foundation. |
||||
|
||||
Magnum is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU Lesser General Public License version 3 for more details. |
||||
*/ |
||||
|
||||
#include <QtCore/QObject> |
||||
|
||||
namespace Magnum { namespace Math { namespace Test { |
||||
|
||||
class TypeTraitsTest: public QObject { |
||||
Q_OBJECT |
||||
|
||||
private slots: |
||||
void equalsFloatingPoint(); |
||||
void equalsIntegral(); |
||||
|
||||
private: |
||||
template<class T> void _equalsFloatingPoint(); |
||||
template<class T> void _equalsIntegral(); |
||||
}; |
||||
|
||||
}}} |
||||
|
||||
#endif |
||||
@ -0,0 +1,110 @@
|
||||
#ifndef Magnum_Math_TypeTraits_h |
||||
#define Magnum_Math_TypeTraits_h |
||||
/*
|
||||
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
This file is part of Magnum. |
||||
|
||||
Magnum is free software: you can redistribute it and/or modify |
||||
it under the terms of the GNU Lesser General Public License version 3 |
||||
only, as published by the Free Software Foundation. |
||||
|
||||
Magnum is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU Lesser General Public License version 3 for more details. |
||||
*/ |
||||
|
||||
/** @file
|
||||
* @brief Class Magnum::Math::TypeTraits |
||||
*/ |
||||
|
||||
#include <cmath> |
||||
|
||||
namespace Magnum { namespace Math { |
||||
|
||||
/**
|
||||
@brief Traits class for numeric types |
||||
|
||||
Traits classes are usable for detecting type features at compile time without |
||||
the need for repeated code such as method overloading or template |
||||
specialization for given types. |
||||
|
||||
This class and class methods are specialized only for types where it makes |
||||
sense, it has empty implementation for unknown types or types which don't |
||||
support given feature, thus forcing the compilation stop with an error. |
||||
*/ |
||||
template<class T> struct TypeTraits { |
||||
#ifdef DOXYGEN_GENERATING_OUTPUT |
||||
/* Development note: the following values are implemented as inline
|
||||
functions, not as static const variables, because the compiler will |
||||
inline the return values instead of referencing to static data and |
||||
unlike static const variables these functions can return floats. */ |
||||
|
||||
/**
|
||||
* @brief Epsilon value for fuzzy compare |
||||
* |
||||
* Returns 0 for integer types and reasonably small value for |
||||
* floating-point types. |
||||
*/ |
||||
constexpr inline static T epsilon(); |
||||
|
||||
/**
|
||||
* @brief Fuzzy compare |
||||
* |
||||
* Uses equality for integer types and fuzzy compare for floating-point |
||||
* types (using @ref epsilon value). |
||||
*/ |
||||
static bool equals(T a, T b); |
||||
#endif |
||||
}; |
||||
|
||||
/** @bug Infinity comparison! */ |
||||
|
||||
/**
|
||||
* @todo Implement better fuzzy comparison algorithm, like at |
||||
* http://floating-point-gui.de/errors/comparison/ or
|
||||
* http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
|
||||
*/ |
||||
|
||||
#ifndef DOXYGEN_GENERATING_OUTPUT |
||||
template<class T> struct _TypeTraitsIntegral { |
||||
constexpr inline static T epsilon() { return 0; } |
||||
|
||||
inline constexpr static bool equals(T a, T b) { |
||||
return a == b; |
||||
} |
||||
}; |
||||
template<> struct TypeTraits<unsigned char>: public _TypeTraitsIntegral<unsigned char> {}; |
||||
template<> struct TypeTraits<char>: public _TypeTraitsIntegral<char> {}; |
||||
|
||||
template<> struct TypeTraits<unsigned short>: public _TypeTraitsIntegral<unsigned short> {}; |
||||
template<> struct TypeTraits<short>: public _TypeTraitsIntegral<short> {}; |
||||
|
||||
template<> struct TypeTraits<unsigned int>: public _TypeTraitsIntegral<unsigned int> {}; |
||||
template<> struct TypeTraits<int>: public _TypeTraitsIntegral<int> {}; |
||||
|
||||
/* long is 32 bits somewhere and 64 bits elsewhere, so it cannot be mapped to
|
||||
any of them */ |
||||
template<> struct TypeTraits<long unsigned int>: public _TypeTraitsIntegral<long unsigned int> {}; |
||||
template<> struct TypeTraits<long int>: public _TypeTraitsIntegral<long int> {}; |
||||
|
||||
template<> struct TypeTraits<unsigned long long>: public _TypeTraitsIntegral<unsigned long long> {}; |
||||
template<> struct TypeTraits<long long>: public _TypeTraitsIntegral<long long> {}; |
||||
|
||||
template<class T> struct _TypeTraitsFloatingPoint { |
||||
inline static bool equals(T a, T b) { |
||||
return std::abs(a - b) < TypeTraits<T>::epsilon(); |
||||
} |
||||
}; |
||||
template<> struct TypeTraits<float>: public _TypeTraitsFloatingPoint<float> { |
||||
constexpr inline static float epsilon() { return 1.0e-6f; } |
||||
}; |
||||
template<> struct TypeTraits<double>: public _TypeTraitsFloatingPoint<double> { |
||||
constexpr inline static double epsilon() { return 1.0e-12; } |
||||
}; |
||||
#endif |
||||
|
||||
}} |
||||
|
||||
#endif |
||||
Loading…
Reference in new issue