/* * 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-2015 Danny Robson */ #include "fixed.hpp" #include "maths.hpp" using namespace util; /////////////////////////////////////////////////////////////////////////////// // Constructors template fixed::fixed (native_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::native_t fixed::to_integer (void) const { return m_value >> E; } //----------------------------------------------------------------------------- template typename fixed::native_t fixed::to_native (void) const { return m_value; } //----------------------------------------------------------------------------- template fixed fixed::from_native (native_t i) { fixed v; v.m_value = i; return v; } //----------------------------------------------------------------------------- template typename fixed::native_t fixed::to_integer (native_t n) { return n >> E; } /////////////////////////////////////////////////////////////////////////////// // Fixed operators #define SIMPLE_FIXED_REF(OP) \ template \ util::fixed& \ util::fixed::operator OP (const fixed rhs) \ { \ m_value OP rhs.m_value; \ return *this; \ } SIMPLE_FIXED_REF(-=) SIMPLE_FIXED_REF(+=) #define SIMPLE_FIXED_LIT(OP) \ template \ util::fixed \ util::fixed::operator OP (const fixed rhs) const \ { \ fixed v; \ v.m_value = m_value OP rhs.m_value; \ return v; \ } SIMPLE_FIXED_LIT(-) SIMPLE_FIXED_LIT(+) /////////////////////////////////////////////////////////////////////////////// // Integer operators #define SIMPLE_INTEGER_REF(OP) \ template \ fixed& \ fixed::operator OP (native_t val) \ { \ m_value OP val << E; \ return *this; \ } SIMPLE_INTEGER_REF(+=) SIMPLE_INTEGER_REF(-=) SIMPLE_INTEGER_REF(*=) SIMPLE_INTEGER_REF(/=) //----------------------------------------------------------------------------- #define SIMPLE_INTEGER_LIT(OP) \ template \ fixed \ fixed::operator OP (native_t val) const \ { \ return fixed::from_native (m_value OP val << E); \ } SIMPLE_INTEGER_LIT(+) SIMPLE_INTEGER_LIT(-) SIMPLE_INTEGER_LIT(*) SIMPLE_INTEGER_LIT(/) /////////////////////////////////////////////////////////////////////////////// // 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(T,I,E) \ template class util::fixed; \ template std::ostream& util::operator<< (std::ostream&, fixed); \ template bool util::operator== (util::fixed, util::fixed); \ template bool util::operator!= (util::fixed, util::fixed); \ template bool util::operator< (util::fixed, util::fixed); \ template bool util::operator<= (util::fixed, util::fixed); \ template bool util::operator> (util::fixed, util::fixed); \ template bool util::operator>= (util::fixed, util::fixed); template class util::fixed; INSTANTIATE(signed,16,16) INSTANTIATE(signed,26, 6) INSTANTIATE(signed,32,32) INSTANTIATE(unsigned,16,16) INSTANTIATE(unsigned,26, 6) INSTANTIATE(unsigned,32,32)