libcruft-util/range.cpp

161 lines
3.3 KiB
C++
Raw Normal View History

2011-05-23 17:18:52 +10:00
#include "range.hpp"
#include "debug.hpp"
#include "maths.hpp"
#include <limits>
#include <cstdint>
using namespace std;
2011-08-15 20:11:42 +10:00
using namespace util;
2011-05-23 17:18:52 +10:00
/*
* Range
*/
template <typename T>
range<T>::range (const json::node &node) {
if (node.is_string () && (node == "UNIT" ||
node == "unit")) {
2011-05-23 17:18:52 +10:00
min = UNIT.min;
max = UNIT.max;
} else if (node.is_string () && (node == "UNLIMITED" ||
node == "unlimited")) {
2011-05-23 17:18:52 +10:00
min = UNLIMITED.min;
max = UNLIMITED.max;
} else {
min = node[0].as_number ();
max = node[1].as_number ();
2011-05-23 17:18:52 +10:00
}
sanity ();
}
template <typename T>
range<T>::range (T _min, T _max):
min (_min),
max (_max)
{ sanity (); }
template <typename T>
bool
range<T>::contains (T val) const
2011-05-23 17:18:52 +10:00
{ return val >= min && val <= max; }
template <typename T>
bool
range<T>::contains (const range <T> &r) const
2011-05-23 17:18:52 +10:00
{ return r.min >= min && r.max <= max; }
template <typename T>
void
range<T>::sanity (void) const
2012-05-11 12:34:21 +10:00
{ CHECK (min <= max); }
2011-05-23 17:18:52 +10:00
namespace util {
template <>
void
range<double>::sanity (void) const {
if (std::isnan (min) || std::isnan (max))
return;
2012-05-11 12:34:21 +10:00
CHECK (min <= max);
}
}
2011-05-23 17:18:52 +10:00
template <typename T>
T
range<T>::clamp (T val) const
{ return std::max (min, std::min (val, max)); }
2012-05-22 14:12:06 +10:00
template <typename T>
2012-05-23 17:01:54 +10:00
void
2012-05-22 14:12:06 +10:00
range<T>::expand (T val) {
// The arguments to min and max are such that expansion from initial NaN
// values should change both min and max to be that value.
min = std::min (val, min);
max = std::max (val, max);
2012-05-22 14:12:06 +10:00
}
2011-05-23 17:18:52 +10:00
template <typename T>
double
range<T>::normalise (T val) const {
return ((double)val - min) /
((double)max - min);
}
namespace util {
template <>
double
range<double>::random (void) const {
double pos = ::rand () / (double)(RAND_MAX);
return (max - min) * pos + min;
}
template <>
float
range<float>::random (void) const {
float pos = ::rand () / (float)(RAND_MAX);
return (max - min) * pos + min;
}
}
2011-05-23 17:18:52 +10:00
template <typename T>
T
range<T>::random (void) const {
return min + (T)::rand () % (max - min);
2011-05-23 17:18:52 +10:00
}
2011-08-15 20:11:42 +10:00
namespace util {
template <>
bool
range<float>::operator ==(const range<float> &rhs) const
{ return almost_equal (min, rhs.min) &&
almost_equal (max, rhs.max); }
2011-05-23 17:18:52 +10:00
2011-08-15 20:11:42 +10:00
template <>
bool
range<double>::operator ==(const range<double> &rhs) const
{ return almost_equal (min, rhs.min) &&
almost_equal (max, rhs.max); }
}
2011-05-23 17:18:52 +10:00
template <typename T>
bool
range<T>::operator ==(const range<T> &rhs) const
{ return min == rhs.min && max == rhs.max; }
template <typename T>
const range<T>
range<T>::UNLIMITED (numeric_limits <T>::is_integer ? numeric_limits <T>::min () :
-numeric_limits <T>::infinity (),
numeric_limits <T>::is_integer ? numeric_limits <T>::max () :
numeric_limits <T>::infinity ());
template <typename T>
const range<T>
range<T>::UNIT (0.0, 1.0);
template struct range<double>;
template struct range<float>;
template struct range<uint8_t>;
template struct range<uint16_t>;
2011-09-13 15:12:57 +10:00
template struct range<uint32_t>;
template struct range<uint64_t>;