range: convert static members to constexpr methods
This commit is contained in:
parent
2dcb315ce6
commit
2e0fa64494
@ -261,15 +261,15 @@ template <size_t S, typename T>
|
||||
matrix4<T>
|
||||
matrix<S,T>::perspective (T fov, T aspect, range<T> Z)
|
||||
{
|
||||
CHECK_GE (Z.min, 0);
|
||||
CHECK_GE (Z.max, 0);
|
||||
CHECK_GE (Z.lo, 0);
|
||||
CHECK_GE (Z.hi, 0);
|
||||
|
||||
T f = 1 / std::tan (fov / 2);
|
||||
|
||||
T x = f / aspect;
|
||||
T y = f;
|
||||
T z1 = (Z.max + Z.min) / (Z.min - Z.max);
|
||||
T z2 = (2 * Z.max * Z.min) / (Z.min - Z.max);
|
||||
T z1 = (Z.hi + Z.lo) / (Z.lo - Z.hi);
|
||||
T z2 = (2 * Z.hi * Z.lo) / (Z.lo - Z.hi);
|
||||
|
||||
return { {
|
||||
{ x, 0, 0, 0 },
|
||||
|
80
range.cpp
80
range.cpp
@ -21,37 +21,15 @@
|
||||
#include "json/tree.hpp"
|
||||
#include "maths.hpp"
|
||||
|
||||
#include <limits>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
const util::range<T>
|
||||
util::range<T>::UNLIMITED (std::numeric_limits<T>::has_infinity ? -std::numeric_limits<T>::infinity () :
|
||||
std::numeric_limits<T>::lowest (),
|
||||
std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity () :
|
||||
std::numeric_limits<T>::max ());
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
const util::range<T>
|
||||
util::range<T>::MAX (std::numeric_limits<T>::lowest (),
|
||||
std::numeric_limits<T>::max ());
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
const util::range<T>
|
||||
util::range<T>::UNIT (0.0, 1.0);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
util::range<T>::range (T _min, T _max):
|
||||
min (_min),
|
||||
max (_max)
|
||||
util::range<T>::range (T _lo, T _hi):
|
||||
lo (_lo),
|
||||
hi (_hi)
|
||||
{
|
||||
sanity ();
|
||||
}
|
||||
@ -62,7 +40,7 @@ template <typename T>
|
||||
T
|
||||
util::range<T>::magnitude (void) const
|
||||
{
|
||||
return max - min;
|
||||
return hi - lo;
|
||||
}
|
||||
|
||||
|
||||
@ -71,7 +49,7 @@ template <typename T>
|
||||
bool
|
||||
util::range<T>::contains (T val) const
|
||||
{
|
||||
return val >= min && val <= max;
|
||||
return val >= lo && val <= hi;
|
||||
}
|
||||
|
||||
|
||||
@ -80,7 +58,7 @@ template <typename T>
|
||||
bool
|
||||
util::range<T>::contains (const range <T> &r) const
|
||||
{
|
||||
return r.min >= min && r.max <= max;
|
||||
return r.lo >= lo && r.hi <= hi;
|
||||
}
|
||||
|
||||
|
||||
@ -89,7 +67,7 @@ template <typename T>
|
||||
T
|
||||
util::range<T>::at (float t) const
|
||||
{
|
||||
return static_cast<T> (min + (max - min) * t);
|
||||
return static_cast<T> (lo + (hi - lo) * t);
|
||||
}
|
||||
|
||||
|
||||
@ -98,7 +76,7 @@ template <typename T>
|
||||
T
|
||||
util::range<T>::clamp (T val) const
|
||||
{
|
||||
return std::max (min, std::min (val, max));
|
||||
return std::max (lo, std::min (val, hi));
|
||||
}
|
||||
|
||||
|
||||
@ -109,8 +87,8 @@ util::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);
|
||||
lo = std::min (val, lo);
|
||||
hi = std::max (val, hi);
|
||||
}
|
||||
|
||||
|
||||
@ -119,8 +97,8 @@ template <typename T>
|
||||
util::range<T>&
|
||||
util::range<T>::operator*= (T val)
|
||||
{
|
||||
min *= val;
|
||||
max *= val;
|
||||
lo *= val;
|
||||
hi *= val;
|
||||
|
||||
return *this;
|
||||
}
|
||||
@ -131,7 +109,7 @@ template <typename T>
|
||||
util::range<T>
|
||||
util::range<T>::operator* (T val) const
|
||||
{
|
||||
return util::range<T> (min * val, max * val);
|
||||
return util::range<T> (lo * val, hi * val);
|
||||
}
|
||||
|
||||
|
||||
@ -140,7 +118,7 @@ template <typename T>
|
||||
util::range<T>
|
||||
util::range<T>::operator- (T val) const
|
||||
{
|
||||
return util::range<T> (min - val, max - val);
|
||||
return util::range<T> (lo - val, hi - val);
|
||||
}
|
||||
|
||||
|
||||
@ -151,7 +129,7 @@ namespace util {
|
||||
range<double>::random (void) const
|
||||
{
|
||||
double pos = ::rand () / (double)(RAND_MAX);
|
||||
return (max - min) * pos + min;
|
||||
return (hi - lo) * pos + lo;
|
||||
}
|
||||
|
||||
template <>
|
||||
@ -159,7 +137,7 @@ namespace util {
|
||||
range<float>::random (void) const
|
||||
{
|
||||
float pos = ::rand () / (float)(RAND_MAX);
|
||||
return (max - min) * pos + min;
|
||||
return (hi - lo) * pos + lo;
|
||||
}
|
||||
}
|
||||
|
||||
@ -169,7 +147,7 @@ template <typename T>
|
||||
T
|
||||
util::range<T>::random (void) const
|
||||
{
|
||||
return min + (T)::rand () % (max - min);
|
||||
return lo + (T)::rand () % (hi - lo);
|
||||
}
|
||||
|
||||
|
||||
@ -179,8 +157,8 @@ namespace util {
|
||||
bool
|
||||
range<float>::operator ==(const range<float> &rhs) const
|
||||
{
|
||||
return almost_equal (min, rhs.min) &&
|
||||
almost_equal (max, rhs.max);
|
||||
return almost_equal (lo, rhs.lo) &&
|
||||
almost_equal (hi, rhs.hi);
|
||||
}
|
||||
|
||||
|
||||
@ -188,8 +166,8 @@ namespace util {
|
||||
bool
|
||||
range<double>::operator ==(const range<double> &rhs) const
|
||||
{
|
||||
return almost_equal (min, rhs.min) &&
|
||||
almost_equal (max, rhs.max);
|
||||
return almost_equal (lo, rhs.lo) &&
|
||||
almost_equal (hi, rhs.hi);
|
||||
}
|
||||
}
|
||||
|
||||
@ -199,7 +177,7 @@ template <typename T>
|
||||
bool
|
||||
util::range<T>::operator ==(const util::range<T> &rhs) const
|
||||
{
|
||||
return min == rhs.min && max == rhs.max;
|
||||
return lo == rhs.lo && hi == rhs.hi;
|
||||
}
|
||||
|
||||
|
||||
@ -208,7 +186,7 @@ template <typename T>
|
||||
void
|
||||
util::range<T>::sanity (void) const
|
||||
{
|
||||
CHECK (min <= max);
|
||||
CHECK (lo <= hi);
|
||||
}
|
||||
|
||||
|
||||
@ -218,9 +196,9 @@ namespace util {
|
||||
void
|
||||
range<double>::sanity (void) const
|
||||
{
|
||||
if (std::isnan (min) || std::isnan (max))
|
||||
if (std::isnan (lo) || std::isnan (hi))
|
||||
return;
|
||||
CHECK (min <= max);
|
||||
CHECK (lo <= hi);
|
||||
}
|
||||
}
|
||||
|
||||
@ -237,17 +215,17 @@ namespace util {
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
namespace json { namespace tree {
|
||||
namespace json::tree {
|
||||
template <>
|
||||
util::range<double>
|
||||
io<util::range<double>>::deserialise (const json::tree::node &node)
|
||||
{
|
||||
if (node.is_string () && (node == "UNIT" ||
|
||||
node == "unit")) {
|
||||
return util::range<double>::UNIT;
|
||||
return util::range<double>::unit ();
|
||||
} else if (node.is_string () && (node == "UNLIMITED" ||
|
||||
node == "unlimited")) {
|
||||
return util::range<double>::UNLIMITED;
|
||||
return util::range<double>::unlimited ();
|
||||
} else {
|
||||
return {
|
||||
node[0].as_number (),
|
||||
@ -255,4 +233,4 @@ namespace json { namespace tree {
|
||||
};
|
||||
}
|
||||
}
|
||||
} }
|
||||
}
|
||||
|
10
range.hpp
10
range.hpp
@ -28,8 +28,8 @@ namespace util {
|
||||
*/
|
||||
template <typename T>
|
||||
struct range {
|
||||
T min;
|
||||
T max;
|
||||
T lo;
|
||||
T hi;
|
||||
|
||||
range (T _min, T _max);
|
||||
|
||||
@ -78,10 +78,10 @@ namespace util {
|
||||
{ return !(*this == rhs); }
|
||||
|
||||
/// A range which is guaranteed to contain all elements type T
|
||||
static const range<T> UNLIMITED;
|
||||
static const range<T> MAX;
|
||||
static constexpr range<T> unlimited (void);
|
||||
static constexpr range<T> max (void);
|
||||
/// A range which only contains elements between 0 and 1 inclusive
|
||||
static const range<T> UNIT;
|
||||
static constexpr range<T> unit (void);
|
||||
|
||||
void sanity (void) const;
|
||||
};
|
||||
|
60
range.ipp
60
range.ipp
@ -20,19 +20,59 @@
|
||||
#define __UTIL_RANGE_IPP
|
||||
#endif
|
||||
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
namespace util {
|
||||
template <typename T>
|
||||
template <typename U>
|
||||
U
|
||||
range<T>::normalise (T val) const {
|
||||
static_assert (std::is_floating_point<U>::value,
|
||||
"normalise isn't implemented for integer types");
|
||||
template <typename T>
|
||||
template <typename U>
|
||||
U
|
||||
util::range<T>::normalise (T val) const
|
||||
{
|
||||
static_assert (std::is_floating_point<U>::value,
|
||||
"normalise isn't implemented for integer types");
|
||||
|
||||
return static_cast<U> (val - min) /
|
||||
static_cast<U> (max - min);
|
||||
}
|
||||
return static_cast<U> (val - lo) /
|
||||
static_cast<U> ( hi - lo);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
constexpr
|
||||
util::range<T>
|
||||
util::range<T>::unlimited (void)
|
||||
{
|
||||
return {
|
||||
std::numeric_limits<T>::has_infinity ? -std::numeric_limits<T>::infinity () :
|
||||
std::numeric_limits<T>::lowest (),
|
||||
std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity () :
|
||||
std::numeric_limits<T>::max ()
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
constexpr
|
||||
util::range<T>
|
||||
util::range<T>::max (void)
|
||||
{
|
||||
return {
|
||||
std::numeric_limits<T>::lowest (),
|
||||
std::numeric_limits<T>::max ()
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
constexpr
|
||||
util::range<T>
|
||||
util::range<T>::unit (void)
|
||||
{
|
||||
return {
|
||||
T {0}, T {1}
|
||||
};
|
||||
}
|
||||
|
@ -11,34 +11,34 @@ main (int, char **)
|
||||
util::TAP::logger tap;
|
||||
|
||||
// Check some simple cases close to the edges of a unit range. Tests float rounding.
|
||||
tap.expect ( util::range<double>::UNIT.contains ( 0.0), "floating unit contains 0");
|
||||
tap.expect ( util::range<double>::UNIT.contains ( 1.0), "floating unit contains 1");
|
||||
tap.expect ( util::range<double>::UNIT.contains (std::numeric_limits<double>::min ()), "floating unit contains min");
|
||||
tap.expect (!util::range<double>::UNIT.contains (-0.00001), "doesn't contain fractionally low value");
|
||||
tap.expect (!util::range<double>::UNIT.contains ( 1.00001), "doesn't contain fractionally high value");
|
||||
tap.expect ( util::range<double>::unit ().contains ( 0.0), "floating unit contains 0");
|
||||
tap.expect ( util::range<double>::unit ().contains ( 1.0), "floating unit contains 1");
|
||||
tap.expect ( util::range<double>::unit ().contains (std::numeric_limits<double>::min ()), "floating unit contains min");
|
||||
tap.expect (!util::range<double>::unit ().contains (-0.00001), "doesn't contain fractionally low value");
|
||||
tap.expect (!util::range<double>::unit ().contains ( 1.00001), "doesn't contain fractionally high value");
|
||||
|
||||
// Check edge cases of unit with integer values
|
||||
tap.expect ( util::range<uint16_t>::UNIT.contains (0), "unsigned unit contains 0");
|
||||
tap.expect ( util::range<uint16_t>::UNIT.contains (1), "unsigned unit contains 1");
|
||||
tap.expect (!util::range<uint16_t>::UNIT.contains (2), "unsigned unit doesn't contain 2");
|
||||
tap.expect (!util::range<uint16_t>::UNIT.contains (std::numeric_limits <uint16_t>::max ()), "unsigned unit doesn't contain max");
|
||||
tap.expect ( util::range<uint16_t>::unit ().contains (0), "unsigned unit contains 0");
|
||||
tap.expect ( util::range<uint16_t>::unit ().contains (1), "unsigned unit contains 1");
|
||||
tap.expect (!util::range<uint16_t>::unit ().contains (2), "unsigned unit doesn't contain 2");
|
||||
tap.expect (!util::range<uint16_t>::unit ().contains (std::numeric_limits <uint16_t>::max ()), "unsigned unit doesn't contain max");
|
||||
|
||||
// Check the inclusivity of UNLIMITED with special floating values
|
||||
tap.expect ( util::range<double>::UNLIMITED.contains (0.0), "floating unlimited contains 0");
|
||||
tap.expect ( util::range<double>::UNLIMITED.contains (+std::numeric_limits<double>::infinity ()), "floating unlimited contains +INF");
|
||||
tap.expect ( util::range<double>::UNLIMITED.contains (-std::numeric_limits<double>::infinity ()), "floating unlimited contains -INF");
|
||||
tap.expect (!util::range<double>::UNLIMITED.contains ( std::numeric_limits<double>::quiet_NaN ()), "floating unlimited doesn't contain NAN");
|
||||
// Check the inclusivity of unlimited with special floating values
|
||||
tap.expect ( util::range<double>::unlimited ().contains (0.0), "floating unlimited contains 0");
|
||||
tap.expect ( util::range<double>::unlimited ().contains (+std::numeric_limits<double>::infinity ()), "floating unlimited contains +INF");
|
||||
tap.expect ( util::range<double>::unlimited ().contains (-std::numeric_limits<double>::infinity ()), "floating unlimited contains -INF");
|
||||
tap.expect (!util::range<double>::unlimited ().contains ( std::numeric_limits<double>::quiet_NaN ()), "floating unlimited doesn't contain NAN");
|
||||
|
||||
// Check the inclusivity of UNLIMITED with some large numbers
|
||||
tap.expect ( util::range<uint16_t>::UNLIMITED.contains (std::numeric_limits<uint16_t>::min()), "floating unlimited contains min");
|
||||
tap.expect ( util::range<uint16_t>::UNLIMITED.contains (std::numeric_limits<uint16_t>::max()), "floating unlimited contains max");
|
||||
// Check the inclusivity of unlimited with some large numbers
|
||||
tap.expect ( util::range<uint16_t>::unlimited ().contains (std::numeric_limits<uint16_t>::min()), "floating unlimited contains min");
|
||||
tap.expect ( util::range<uint16_t>::unlimited ().contains (std::numeric_limits<uint16_t>::max()), "floating unlimited contains max");
|
||||
|
||||
// Check inclusivity of MAX
|
||||
tap.expect (!util::range<double>::MAX.contains ( std::numeric_limits<double>::infinity ()), "floating max contains +INF");
|
||||
tap.expect (!util::range<double>::MAX.contains (-std::numeric_limits<double>::infinity ()), "floating max contains -INF");
|
||||
// Check inclusivity of max
|
||||
tap.expect (!util::range<double>::max ().contains ( std::numeric_limits<double>::infinity ()), "floating max contains +INF");
|
||||
tap.expect (!util::range<double>::max ().contains (-std::numeric_limits<double>::infinity ()), "floating max contains -INF");
|
||||
|
||||
tap.expect ( util::range<uint16_t>::MAX.contains (std::numeric_limits<uint16_t>::min()), "unsigned max contains min");
|
||||
tap.expect ( util::range<uint16_t>::MAX.contains (std::numeric_limits<uint16_t>::max()), "unsigned max contains max");
|
||||
tap.expect ( util::range<uint16_t>::max ().contains (std::numeric_limits<uint16_t>::min()), "unsigned max contains min");
|
||||
tap.expect ( util::range<uint16_t>::max ().contains (std::numeric_limits<uint16_t>::max()), "unsigned max contains max");
|
||||
|
||||
// Check that expansion via NaN is a noop
|
||||
{
|
||||
@ -46,8 +46,8 @@ main (int, char **)
|
||||
std::numeric_limits<double>::quiet_NaN ());
|
||||
initial_nan.expand (1.0);
|
||||
|
||||
tap.expect_eq (initial_nan.min, 1.0, "NAN expansion noop for min");
|
||||
tap.expect_eq (initial_nan.max, 1.0, "NAN expansion noop for max");
|
||||
tap.expect_eq (initial_nan.lo, 1.0, "NAN expansion noop for lo");
|
||||
tap.expect_eq (initial_nan.hi, 1.0, "NAN expansion noop for hi");
|
||||
}
|
||||
|
||||
return tap.status ();
|
||||
|
Loading…
Reference in New Issue
Block a user