/* * 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 "maths.hpp" #include #include //----------------------------------------------------------------------------- using namespace std; using namespace util; //----------------------------------------------------------------------------- template range::range (const json::node &node) { if (node.is_string () && (node == "UNIT" || node == "unit")) { min = UNIT.min; max = UNIT.max; } else if (node.is_string () && (node == "UNLIMITED" || node == "unlimited")) { min = UNLIMITED.min; max = UNLIMITED.max; } else { min = node[0].as_number (); max = node[1].as_number (); } sanity (); } 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 double range::normalise (T val) const { return ((double)val - min) / ((double)max - min); } 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; }