/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Copyright 2011-2015 Danny Robson */ #include "fixed.hpp" #include "maths.hpp" #include using namespace cruft; /////////////////////////////////////////////////////////////////////////////// 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::integer_type fixed::to_integer (void) const { return m_value >> E; } //----------------------------------------------------------------------------- template typename fixed::native_type fixed::to_native (void) const { return m_value; } //----------------------------------------------------------------------------- template fixed fixed::from_native (native_type i) { fixed v; v.m_value = i; return v; } //----------------------------------------------------------------------------- template fixed fixed::from_integer (integer_type val) { constexpr auto rshift = sizeof (val) * 8 - I; constexpr auto lshift = E - rshift; fixed res; res.m_value = static_cast (val) << lshift; return res; } //----------------------------------------------------------------------------- template typename fixed::integer_type fixed::to_integer (native_type n) { return n >> E; } /////////////////////////////////////////////////////////////////////////////// // Fixed operators #define SIMPLE_FIXED_REF(OP) \ template \ cruft::fixed& \ cruft::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 \ cruft::fixed \ cruft::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 (integer_type val) \ { \ m_value OP (static_cast (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 (integer_type val) const \ { \ return fixed::from_native (m_value OP (native_type{val} << E)); \ } SIMPLE_INTEGER_LIT(+) SIMPLE_INTEGER_LIT(-) SIMPLE_INTEGER_LIT(*) SIMPLE_INTEGER_LIT(/) /////////////////////////////////////////////////////////////////////////////// // logical operators #define LOGIC_OP(OP) \ template \ bool \ cruft::operator OP (cruft::fixed a, \ cruft::fixed b) \ { \ return a.to_native () OP b.to_native (); \ } \ \ template \ bool \ cruft::operator OP (cruft::fixed a, \ typename cruft::fixed::integer_type b) \ { \ return a OP cruft::fixed::from_integer (b); \ } LOGIC_OP(==) LOGIC_OP(!=) LOGIC_OP(<) LOGIC_OP(<=) LOGIC_OP(>) LOGIC_OP(>=) /////////////////////////////////////////////////////////////////////////////// // iostream operators template std::ostream& cruft::operator<< (std::ostream &os, fixed v) { return os << v.to_double (); } /////////////////////////////////////////////////////////////////////////////// // Instantiations #define INSTANTIATE(T,I,E) \ template class cruft::fixed; \ template std::ostream& cruft::operator<< (std::ostream&, fixed); \ template bool cruft::operator== (cruft::fixed, cruft::fixed); \ template bool cruft::operator!= (cruft::fixed, cruft::fixed); \ template bool cruft::operator< (cruft::fixed, cruft::fixed); \ template bool cruft::operator<= (cruft::fixed, cruft::fixed); \ template bool cruft::operator> (cruft::fixed, cruft::fixed); \ template bool cruft::operator>= (cruft::fixed, cruft::fixed); \ template bool cruft::operator== (cruft::fixed, typename cruft::fixed::integer_type); \ template bool cruft::operator!= (cruft::fixed, typename cruft::fixed::integer_type); \ template bool cruft::operator< (cruft::fixed, typename cruft::fixed::integer_type); \ template bool cruft::operator<= (cruft::fixed, typename cruft::fixed::integer_type); \ template bool cruft::operator> (cruft::fixed, typename cruft::fixed::integer_type); \ template bool cruft::operator>= (cruft::fixed, typename cruft::fixed::integer_type); template class cruft::fixed; INSTANTIATE(signed, 2,14) INSTANTIATE(signed,16,16) INSTANTIATE(signed,26, 6) INSTANTIATE(signed,32,32) INSTANTIATE(unsigned,16,16) INSTANTIATE(unsigned,26, 6) INSTANTIATE(unsigned,32,32)