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