/* * 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 /////////////////////////////////////////////////////////////////////////////// template util::range::range (T _lo, T _hi): lo (_lo), hi (_hi) { sanity (); } /////////////////////////////////////////////////////////////////////////////// template T util::range::magnitude (void) const { return hi - lo; } /////////////////////////////////////////////////////////////////////////////// template bool util::range::contains (T val) const { return val >= lo && val <= hi; } //----------------------------------------------------------------------------- template bool util::range::contains (const range &r) const { return r.lo >= lo && r.hi <= hi; } //----------------------------------------------------------------------------- template T util::range::at (float t) const { return static_cast (lo + (hi - lo) * t); } //----------------------------------------------------------------------------- template T util::range::clamp (T val) const { return std::max (lo, std::min (val, hi)); } //----------------------------------------------------------------------------- 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. lo = std::min (val, lo); hi = std::max (val, hi); } /////////////////////////////////////////////////////////////////////////////// template util::range& util::range::operator*= (T val) { lo *= val; hi *= val; return *this; } //----------------------------------------------------------------------------- template util::range util::range::operator* (T val) const { return util::range (lo * val, hi * val); } //----------------------------------------------------------------------------- template util::range util::range::operator- (T val) const { return util::range (lo - val, hi - val); } /////////////////////////////////////////////////////////////////////////////// namespace util { template <> double range::random (void) const { double pos = ::rand () / (double)(RAND_MAX); return (hi - lo) * pos + lo; } template <> float range::random (void) const { float pos = ::rand () / (float)(RAND_MAX); return (hi - lo) * pos + lo; } } //----------------------------------------------------------------------------- template T util::range::random (void) const { return lo + (T)::rand () % (hi - lo); } /////////////////////////////////////////////////////////////////////////////// namespace util { template <> bool range::operator ==(const range &rhs) const { return almost_equal (lo, rhs.lo) && almost_equal (hi, rhs.hi); } template <> bool range::operator ==(const range &rhs) const { return almost_equal (lo, rhs.lo) && almost_equal (hi, rhs.hi); } } //----------------------------------------------------------------------------- template bool util::range::operator ==(const util::range &rhs) const { return lo == rhs.lo && hi == rhs.hi; } /////////////////////////////////////////////////////////////////////////////// template void util::range::sanity (void) const { CHECK (lo <= hi); } //----------------------------------------------------------------------------- namespace util { template <> void range::sanity (void) const { if (std::isnan (lo) || std::isnan (hi)) return; CHECK (lo <= hi); } } //----------------------------------------------------------------------------- template struct util::range; template struct util::range; template struct util::range; template struct util::range; template struct util::range; template struct util::range; template struct util::range; template struct util::range; template struct util::range; template struct util::range; //----------------------------------------------------------------------------- namespace json::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 () }; } } }