1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
|
#ifndef FLOATTOOLS_H_
#define FLOATTOOLS_H_
/* greebo: this contains some handy (?) functions for manipulating float variables
*/
#include <iostream>
#include "lrint.h"
#if defined (_MSC_VER)
/*inline int lrint (double flt) {
int i;
_asm
{
fld flt
fistp i
};
return i;
} */
#elif defined(__FreeBSD__)
inline int lrint(double f) {
return static_cast<int>(f + 0.5);
}
#elif defined(__GNUC__)
// lrint is part of ISO C99
#define _ISOC9X_SOURCE 1
#define _ISOC99_SOURCE 1
#define __USE_ISOC9X 1
#define __USE_ISOC99 1
#else
#error "unsupported platform"
#endif
#include <cmath>
#include <float.h>
#include <algorithm>
#include <limits>
// =========================================================================================
/// \brief Returns true if \p self is equal to other \p other within \p epsilon.
template<typename Element, typename OtherElement>
inline bool float_equal_epsilon(const Element& self, const OtherElement& other, const Element& epsilon)
{
return fabs(other - self) < epsilon;
}
/// \brief Returns the value midway between \p self and \p other.
template<typename Element>
inline Element float_mid(const Element& self, const Element& other)
{
return Element((self + other) * 0.5);
}
/// \brief Returns \p f rounded to the nearest integer. Note that this is not the same behaviour as casting from float to int.
template<typename Element>
inline int float_to_integer(const Element& f)
{
return static_cast<int>(lrint(f));
}
/// \brief Returns \p f rounded to the nearest multiple of \p snap.
template<typename Element, typename OtherElement>
inline Element float_snapped(const Element& f, const OtherElement& snap)
{
return Element(float_to_integer(f / snap) * snap);
}
/// \brief Returns true if \p f has no decimal fraction part.
template<typename Element>
inline bool float_is_integer(const Element& f)
{
return f == Element(float_to_integer(f));
}
/// \brief Returns \p self modulated by the range [0, \p modulus)
/// \p self must be in the range [\p -modulus, \p modulus)
template<typename Element, typename ModulusElement>
inline Element float_mod_range(const Element& self, const ModulusElement& modulus)
{
return Element((self < 0.0) ? self + modulus : self);
}
/// \brief Returns \p self modulated by the range [0, \p modulus)
template<typename Element, typename ModulusElement>
inline Element float_mod(const Element& self, const ModulusElement& modulus)
{
return float_mod_range(Element(fmod(static_cast<float>(self), static_cast<float>(modulus))), modulus);
}
template<typename Element>
inline bool isNaN(Element x) {
return x != x;
}
// greebo: This checks the given element for NaN and infinity
// returns TRUE if the number is safe
template <typename Element>
inline bool isValid(Element x) {
// Check for infinity and NaN
return !isNaN(x) && !(std::numeric_limits<Element>::has_infinity &&
fabs(x) == std::numeric_limits<Element>::infinity());
}
#endif /*FLOATTOOLS_H_*/
|