libcruft-util/range.cpp

224 lines
5.4 KiB
C++
Raw Normal View History

/*
2015-04-13 18:05:28 +10:00
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
2015-04-13 18:05:28 +10:00
* http://www.apache.org/licenses/LICENSE-2.0
*
2015-04-13 18:05:28 +10:00
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* 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"
2018-05-03 18:32:08 +10:00
#include "random.hpp"
2011-05-23 17:18:52 +10:00
#include <cmath>
2011-05-23 17:18:52 +10:00
#include <cstdint>
///////////////////////////////////////////////////////////////////////////////
template <typename T>
util::range<T>::range (T _lo, T _hi):
lo (_lo),
hi (_hi)
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
{
return hi - lo;
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
{
return val >= lo && val <= hi;
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
{
return r.lo >= lo && r.hi <= hi;
}
2015-03-11 16:27:37 +11:00
//-----------------------------------------------------------------------------
template <typename T>
T
util::range<T>::at (float t) const
{
return static_cast<T> (lo + (hi - lo) * t);
2015-03-11 16:27:37 +11:00
}
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 (lo, std::min (val, hi));
2015-02-20 20:45:39 +11:00
}
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.
lo = std::min (val, lo);
hi = std::max (val, hi);
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)
{
lo *= val;
hi *= val;
2012-05-24 15:03:26 +10:00
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> (lo * val, hi * val);
2012-05-24 15:03:26 +10:00
}
//-----------------------------------------------------------------------------
template <typename T>
util::range<T>
util::range<T>::operator- (T val) const
{
return util::range<T> (lo - val, hi - val);
}
2015-02-20 20:49:41 +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
{
2018-05-03 18:32:08 +10:00
if constexpr (std::is_floating_point_v<T>) {
return std::uniform_real_distribution<T> (lo, hi) (util::random::generator ());
} else {
return std::uniform_int_distribution<T> (lo, hi) (util::random::generator ());
}
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 (lo, rhs.lo) &&
almost_equal (hi, rhs.hi);
2015-02-20 20:45:39 +11:00
}
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 (lo, rhs.lo) &&
almost_equal (hi, rhs.hi);
2015-02-20 20:45:39 +11:00
}
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 lo == rhs.lo && hi == rhs.hi;
2015-02-20 20:45:39 +11:00
}
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 (lo <= hi);
2015-02-20 20:49:41 +11:00
}
//-----------------------------------------------------------------------------
namespace util {
template <>
void
range<double>::sanity (void) const
{
if (std::isnan (lo) || std::isnan (hi))
2015-02-20 20:49:41 +11:00
return;
CHECK (lo <= hi);
2015-02-20 20:49:41 +11:00
}
}
2015-02-20 20:40:01 +11:00
//-----------------------------------------------------------------------------
template struct util::range<double>;
template struct util::range<float>;
template struct util::range<int8_t>;
template struct util::range<int16_t>;
template struct util::range<int32_t>;
template struct util::range<int64_t>;
template struct util::range<uint8_t>;
template struct util::range<uint16_t>;
template struct util::range<uint32_t>;
template struct util::range<uint64_t>;
//-----------------------------------------------------------------------------
namespace json::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 ()
};
}
}
}