/* * 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 * * http://www.apache.org/licenses/LICENSE-2.0 * * 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 */ #include "range.hpp" #include "debug.hpp" #include "json/tree.hpp" #include "maths.hpp" #include #include #include /////////////////////////////////////////////////////////////////////////////// template util::range::range (T _min, T _max): min (_min), max (_max) { sanity (); } /////////////////////////////////////////////////////////////////////////////// template T util::range::magnitude (void) const { return max - min; } /////////////////////////////////////////////////////////////////////////////// template bool util::range::contains (T val) const { return val >= min && val <= max; } //----------------------------------------------------------------------------- template bool util::range::contains (const range &r) const { return r.min >= min && r.max <= max; } //----------------------------------------------------------------------------- template T util::range::at (float t) const { return static_cast (min + (max - min) * t); } //----------------------------------------------------------------------------- template T util::range::clamp (T val) const { return std::max (min, std::min (val, max)); } //----------------------------------------------------------------------------- template void util::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 util::range& util::range::operator*= (T val) { min *= val; max *= val; return *this; } //----------------------------------------------------------------------------- template util::range util::range::operator* (T val) const { return util::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 util::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 util::range::operator ==(const util::range &rhs) const { return min == rhs.min && max == rhs.max; } /////////////////////////////////////////////////////////////////////////////// template const util::range util::range::UNLIMITED (std::numeric_limits::has_infinity ? -std::numeric_limits::infinity () : std::numeric_limits::lowest (), std::numeric_limits::has_infinity ? std::numeric_limits::infinity () : std::numeric_limits::max ()); //----------------------------------------------------------------------------- template const util::range util::range::MAX (std::numeric_limits::lowest (), std::numeric_limits::max ()); //----------------------------------------------------------------------------- template const util::range util::range::UNIT (0.0, 1.0); /////////////////////////////////////////////////////////////////////////////// template void util::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); } } //----------------------------------------------------------------------------- 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 () }; } } } }