/*
* 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 .
*
* Copyright 2011-2012 Danny Robson
*/
#include "range.hpp"
#include "debug.hpp"
#include "json/tree.hpp"
#include "maths.hpp"
#include
#include
#include
//-----------------------------------------------------------------------------
using namespace std;
using namespace util;
//-----------------------------------------------------------------------------
template
range::range (T _min, T _max):
min (_min),
max (_max)
{ sanity (); }
template
bool
range::contains (T val) const
{ return val >= min && val <= max; }
template
bool
range::contains (const range &r) const
{ return r.min >= min && r.max <= max; }
template
void
range::sanity (void) const
{ CHECK (min <= max); }
namespace util {
template <>
void
range::sanity (void) const {
if (std::isnan (min) || std::isnan (max))
return;
CHECK (min <= max);
}
}
template
T
range::clamp (T val) const
{ return std::max (min, std::min (val, max)); }
template
void
range::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);
}
template
range&
range::operator*= (T val) {
min *= val;
max *= val;
return *this;
}
template
range
range::operator* (T val) const {
return range (min * val, max * val);
}
namespace util {
template <>
double
range::random (void) const {
double pos = ::rand () / (double)(RAND_MAX);
return (max - min) * pos + min;
}
template <>
float
range::random (void) const {
float pos = ::rand () / (float)(RAND_MAX);
return (max - min) * pos + min;
}
}
template
T
range::random (void) const {
return min + (T)::rand () % (max - min);
}
namespace util {
template <>
bool
range::operator ==(const range &rhs) const
{ return almost_equal (min, rhs.min) &&
almost_equal (max, rhs.max); }
template <>
bool
range::operator ==(const range &rhs) const
{ return almost_equal (min, rhs.min) &&
almost_equal (max, rhs.max); }
}
template
bool
range::operator ==(const range &rhs) const
{ return min == rhs.min && max == rhs.max; }
template
const range
range::UNLIMITED (numeric_limits::has_infinity ? -numeric_limits::infinity () :
numeric_limits::lowest (),
numeric_limits::has_infinity ? numeric_limits::infinity () :
numeric_limits::max ());
template
const range
range::MAX (numeric_limits::lowest (),
numeric_limits::max ());
template
const range
range::UNIT (0.0, 1.0);
namespace util {
template struct range;
template struct range;
template struct range;
template struct range;
template struct range;
template struct range;
}
//-----------------------------------------------------------------------------
namespace json { namespace tree {
template <>
util::range
io>::deserialise (const json::tree::node &node) {
if (node.is_string () && (node == "UNIT" ||
node == "unit")) {
return util::range::UNIT;
} else if (node.is_string () && (node == "UNLIMITED" ||
node == "unlimited")) {
return util::range::UNLIMITED;
} else {
return {
node[0].as_number (),
node[1].as_number ()
};
}
}
} }