libcruft-util/range.cpp

244 lines
6.2 KiB
C++
Raw Normal View History

/*
* This file is part of libgim.
*
* libgim is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* libgim 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 General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with libgim. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2012 Danny Robson <danny@nerdcruft.net>
*/
2011-05-23 17:18:52 +10:00
#include "range.hpp"
#include "debug.hpp"
#include "json/tree.hpp"
2011-05-23 17:18:52 +10:00
#include "maths.hpp"
#include <limits>
#include <cmath>
2011-05-23 17:18:52 +10:00
#include <cstdint>
2015-02-20 20:49:41 +11:00
///////////////////////////////////////////////////////////////////////////////
2011-05-23 17:18:52 +10:00
template <typename T>
2015-02-20 20:45:39 +11:00
util::range<T>::range (T _min, T _max):
2011-05-23 17:18:52 +10:00
min (_min),
max (_max)
2015-02-20 20:45:39 +11:00
{
sanity ();
}
2011-05-23 17:18:52 +10:00
2015-02-20 20:49:41 +11:00
///////////////////////////////////////////////////////////////////////////////
2011-05-23 17:18:52 +10:00
template <typename T>
2015-02-20 20:49:41 +11:00
T
util::range<T>::magnitude (void) const
2015-02-20 20:45:39 +11:00
{
2015-02-20 20:49:41 +11:00
return max - min;
2015-02-20 20:45:39 +11:00
}
2011-05-23 17:18:52 +10:00
2015-02-20 20:49:41 +11:00
///////////////////////////////////////////////////////////////////////////////
2011-05-23 17:18:52 +10:00
template <typename T>
bool
2015-02-20 20:49:41 +11:00
util::range<T>::contains (T val) const
2015-02-20 20:45:39 +11:00
{
2015-02-20 20:49:41 +11:00
return val >= min && val <= max;
2015-02-20 20:45:39 +11:00
}
2011-05-23 17:18:52 +10:00
2015-02-20 20:40:01 +11:00
//-----------------------------------------------------------------------------
2011-05-23 17:18:52 +10:00
template <typename T>
2015-02-20 20:49:41 +11:00
bool
util::range<T>::contains (const range <T> &r) const
2015-02-20 20:45:39 +11:00
{
2015-02-20 20:49:41 +11:00
return r.min >= min && r.max <= max;
}
2015-02-20 20:40:01 +11:00
//-----------------------------------------------------------------------------
2011-05-23 17:18:52 +10:00
template <typename T>
T
2015-02-20 20:45:39 +11:00
util::range<T>::clamp (T val) const
{
return std::max (min, std::min (val, max));
}
2011-05-23 17:18:52 +10:00
2015-02-20 20:40:01 +11:00
//-----------------------------------------------------------------------------
2012-05-22 14:12:06 +10:00
template <typename T>
2012-05-23 17:01:54 +10:00
void
2015-02-20 20:45:39 +11:00
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);
2012-05-22 14:12:06 +10:00
}
2015-02-20 20:49:41 +11:00
///////////////////////////////////////////////////////////////////////////////
2012-05-24 15:03:26 +10:00
template <typename T>
2015-02-20 20:45:39 +11:00
util::range<T>&
util::range<T>::operator*= (T val)
{
2012-05-24 15:03:26 +10:00
min *= val;
max *= val;
return *this;
}
2015-02-20 20:40:01 +11:00
//-----------------------------------------------------------------------------
2012-05-24 15:03:26 +10:00
template <typename T>
2015-02-20 20:45:39 +11:00
util::range<T>
util::range<T>::operator* (T val) const
{
return util::range<T> (min * val, max * val);
2012-05-24 15:03:26 +10:00
}
2015-02-20 20:49:41 +11:00
///////////////////////////////////////////////////////////////////////////////
namespace util {
template <>
double
2015-02-20 20:45:39 +11:00
range<double>::random (void) const
{
double pos = ::rand () / (double)(RAND_MAX);
return (max - min) * pos + min;
}
template <>
float
2015-02-20 20:45:39 +11:00
range<float>::random (void) const
{
float pos = ::rand () / (float)(RAND_MAX);
return (max - min) * pos + min;
}
}
2015-02-20 20:40:01 +11:00
//-----------------------------------------------------------------------------
2011-05-23 17:18:52 +10:00
template <typename T>
T
2015-02-20 20:45:39 +11:00
util::range<T>::random (void) const
{
return min + (T)::rand () % (max - min);
2011-05-23 17:18:52 +10:00
}
2015-02-20 20:49:41 +11:00
///////////////////////////////////////////////////////////////////////////////
2011-08-15 20:11:42 +10:00
namespace util {
template <>
bool
range<float>::operator ==(const range<float> &rhs) const
2015-02-20 20:45:39 +11:00
{
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
2015-02-20 20:45:39 +11:00
{
return almost_equal (min, rhs.min) &&
almost_equal (max, rhs.max);
}
2011-08-15 20:11:42 +10:00
}
2011-05-23 17:18:52 +10:00
2015-02-20 20:40:01 +11:00
//-----------------------------------------------------------------------------
2011-05-23 17:18:52 +10:00
template <typename T>
bool
2015-02-20 20:45:39 +11:00
util::range<T>::operator ==(const util::range<T> &rhs) const
{
return min == rhs.min && max == rhs.max;
}
2011-05-23 17:18:52 +10:00
2015-02-20 20:49:41 +11:00
///////////////////////////////////////////////////////////////////////////////
2011-05-23 17:18:52 +10:00
template <typename T>
2015-02-20 20:45:39 +11:00
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 ());
2012-06-15 16:38:10 +10:00
2015-02-20 20:40:01 +11:00
//-----------------------------------------------------------------------------
2012-06-15 16:38:10 +10:00
template <typename T>
2015-02-20 20:45:39 +11:00
const util::range<T>
util::range<T>::MAX (std::numeric_limits<T>::lowest (),
std::numeric_limits<T>::max ());
2012-06-15 16:38:10 +10:00
2011-05-23 17:18:52 +10:00
2015-02-20 20:40:01 +11:00
//-----------------------------------------------------------------------------
2011-05-23 17:18:52 +10:00
template <typename T>
2015-02-20 20:45:39 +11:00
const util::range<T>
util::range<T>::UNIT (0.0, 1.0);
2011-05-23 17:18:52 +10:00
2015-02-20 20:49:41 +11:00
///////////////////////////////////////////////////////////////////////////////
template <typename T>
void
util::range<T>::sanity (void) const
{
CHECK (min <= max);
}
//-----------------------------------------------------------------------------
namespace util {
template <>
void
range<double>::sanity (void) const
{
if (std::isnan (min) || std::isnan (max))
return;
CHECK (min <= max);
}
}
2015-02-20 20:40:01 +11:00
//-----------------------------------------------------------------------------
namespace util {
template struct range<double>;
template struct range<float>;
template struct range<uint8_t>;
template struct range<uint16_t>;
template struct range<uint32_t>;
template struct range<uint64_t>;
}
//-----------------------------------------------------------------------------
namespace json { namespace tree {
template <>
util::range<double>
2015-02-20 20:45:39 +11:00
io<util::range<double>>::deserialise (const json::tree::node &node)
{
if (node.is_string () && (node == "UNIT" ||
node == "unit")) {
return util::range<double>::UNIT;
} else if (node.is_string () && (node == "UNLIMITED" ||
node == "unlimited")) {
return util::range<double>::UNLIMITED;
} else {
return {
node[0].as_number (),
node[1].as_number ()
};
}
}
} }