/* * 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-2015 Danny Robson */ #include "fixed.hpp" #include "maths.hpp" #include using namespace util; /////////////////////////////////////////////////////////////////////////////// // Constructors template fixed::fixed (uint_t val): m_value (val << E) { static_assert (I > 0, "must use positive integer bits"); static_assert (E > 0, "must use positive fractional bits"); static_assert (I + E == sizeof (m_value) * 8, "underlying storage must be exactly I+E sized"); } /////////////////////////////////////////////////////////////////////////////// // Conversions template double fixed::to_double (void) const { return static_cast (m_value) / pow (2, E); } //----------------------------------------------------------------------------- template float fixed::to_float (void) const { return static_cast (m_value) / pow (2, E); } //----------------------------------------------------------------------------- template typename fixed::uint_t fixed::to_integer (void) const { return m_value >> E; } //----------------------------------------------------------------------------- template typename fixed::uint_t fixed::to_native (void) const { return m_value; } //----------------------------------------------------------------------------- template fixed fixed::from_native (uint_t i) { fixed v; v.m_value = i; return v; } //----------------------------------------------------------------------------- template typename fixed::uint_t fixed::to_integer (uint_t n) { return n >> E; } /////////////////////////////////////////////////////////////////////////////// // Integer operators template fixed& fixed::operator+= (uint_t val) { m_value += val << E; return *this; } //----------------------------------------------------------------------------- template fixed& fixed::operator-= (uint_t val) { m_value -= val << E; return *this; } //----------------------------------------------------------------------------- template fixed& fixed::operator*= (uint_t val) { m_value *= val; return *this; } //----------------------------------------------------------------------------- template fixed& fixed::operator/= (uint_t val) { m_value /= val; return *this; } //----------------------------------------------------------------------------- template fixed fixed::operator+ (uint_t val) const { return fixed (m_value + val << E); } //----------------------------------------------------------------------------- template fixed fixed::operator- (uint_t val) const { return fixed (m_value - val << E); } //----------------------------------------------------------------------------- template fixed fixed::operator* (uint_t val) const { return fixed (m_value * val); } //----------------------------------------------------------------------------- template fixed fixed::operator /(uint_t val) const { return fixed (m_value / val); } /////////////////////////////////////////////////////////////////////////////// // logical operators #define LOGIC_OP(OP) \ template \ bool \ util::operator OP (util::fixed a, \ util::fixed b) \ { \ return a.to_native () OP b.to_native (); \ } LOGIC_OP(==) LOGIC_OP(!=) LOGIC_OP(<) LOGIC_OP(<=) LOGIC_OP(>) LOGIC_OP(>=) /////////////////////////////////////////////////////////////////////////////// // iostream operators template std::ostream& util::operator<< (std::ostream &os, fixed v) { return os << v.to_double (); } /////////////////////////////////////////////////////////////////////////////// // Instantiations #define INSTANTIATE(I,E) \ template class util::fixed<(I),(E)>; \ template std::ostream& util::operator<< (std::ostream&, fixed<(I),(E)>); \ template bool util::operator== (util::fixed<(I),(E)>, util::fixed<(I),(E)>); \ template bool util::operator!= (util::fixed<(I),(E)>, util::fixed<(I),(E)>); \ template bool util::operator< (util::fixed<(I),(E)>, util::fixed<(I),(E)>); \ template bool util::operator<= (util::fixed<(I),(E)>, util::fixed<(I),(E)>); \ template bool util::operator> (util::fixed<(I),(E)>, util::fixed<(I),(E)>); \ template bool util::operator>= (util::fixed<(I),(E)>, util::fixed<(I),(E)>); INSTANTIATE(16,16) INSTANTIATE(26, 6) INSTANTIATE(32,32)