/*! ======================================================================== ** Extended Template and Library ** Fixed-Point Math Class Implementation ** $Id$ ** ** Copyright (c) 2002 Robert B. Quattlebaum Jr. ** Copyright (c) 2007 Chris Moore ** ** This package 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 2 of ** the License, or (at your option) any later version. ** ** This package 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. ** ** === N O T E S =========================================================== ** ** This is an internal header file, included by other ETL headers. ** You should not attempt to use it directly. ** ** ========================================================================= */ /* === S T A R T =========================================================== */ #ifndef __ETL__FIXED_H #define __ETL__FIXED_H /* === H E A D E R S ======================================================= */ #include /* === M A C R O S ========================================================= */ // the "+0.5" code was commented out - maybe to make thing run faster? // it can be re-enabled by uncommenting this next line: // #define ROUND_TO_NEAREST_INTEGER #ifndef ETL_FIXED_TYPE # define ETL_FIXED_TYPE int #endif #ifndef ETL_FIXED_BITS #define ETL_FIXED_BITS 12 #endif #ifndef ETL_FIXED_EPSILON #define ETL_FIXED_EPSILON _EPSILON() #endif #ifdef __GNUC___ #define ETL_ATTRIB_CONST __attribute__ ((const)) #define ETL_ATTRIB_PURE __attribute__ ((pure)) #define ETL_ATTRIB_INLINE __attribute__ ((always_inline)) #else #define ETL_ATTRIB_CONST #define ETL_ATTRIB_PURE #define ETL_ATTRIB_INLINE #endif /* === C L A S S E S & S T R U C T S ======================================= */ _ETL_BEGIN_NAMESPACE // Forward declarations template class fixed_base; //template<> class fixed_base; _ETL_END_NAMESPACE _STD_BEGIN_NAMESPACE template _ETL::fixed_base abs(const _ETL::fixed_base&); template _ETL::fixed_base cos(const _ETL::fixed_base&); template _ETL::fixed_base cosh(const _ETL::fixed_base&); template _ETL::fixed_base exp(const _ETL::fixed_base&); template _ETL::fixed_base log(const _ETL::fixed_base&); template _ETL::fixed_base log10(const _ETL::fixed_base&); template _ETL::fixed_base pow(const _ETL::fixed_base&, int); template _ETL::fixed_base pow(const _ETL::fixed_base&, const T&); template _ETL::fixed_base pow(const _ETL::fixed_base&, const _ETL::fixed_base&); template _ETL::fixed_base pow(const _ETL::fixed_base&, const _ETL::fixed_base&); template _ETL::fixed_base sin(const _ETL::fixed_base&); template _ETL::fixed_base sinh(const _ETL::fixed_base&); template _ETL::fixed_base sqrt(const _ETL::fixed_base&); template _ETL::fixed_base tan(const _ETL::fixed_base&); template _ETL::fixed_base tanh(const _ETL::fixed_base&); _STD_END_NAMESPACE _ETL_BEGIN_NAMESPACE /*! ======================================================================== ** \class fixed_base ** \brief Fixed-point template base class ** ** A more detailed description needs to be written. */ template class fixed_base { public: typedef T value_type; private: T _data; typedef fixed_base _fixed; typedef fixed_base self_type; inline static bool _TYPE_SMALLER_THAN_INT() ETL_ATTRIB_CONST ETL_ATTRIB_INLINE; inline static bool _USING_ALL_BITS() ETL_ATTRIB_CONST ETL_ATTRIB_INLINE; inline static value_type _ONE() ETL_ATTRIB_CONST ETL_ATTRIB_INLINE; inline static value_type _F_MASK() ETL_ATTRIB_CONST ETL_ATTRIB_INLINE; inline static float _EPSILON() ETL_ATTRIB_CONST ETL_ATTRIB_INLINE; class raw { }; public: fixed_base()ETL_ATTRIB_INLINE; fixed_base(const float &f)ETL_ATTRIB_INLINE; fixed_base(const double &f)ETL_ATTRIB_INLINE; fixed_base(const long double &f)ETL_ATTRIB_INLINE; fixed_base(const int &i)ETL_ATTRIB_INLINE; fixed_base(const int &n,const int &d)ETL_ATTRIB_INLINE; //!< Fraction constructor fixed_base(const _fixed &x)ETL_ATTRIB_INLINE; fixed_base(value_type x,raw)ETL_ATTRIB_INLINE; T &data() ETL_ATTRIB_PURE ETL_ATTRIB_INLINE; const T &data()const ETL_ATTRIB_PURE ETL_ATTRIB_INLINE; const _fixed& operator+=(const _fixed &rhs) ETL_ATTRIB_INLINE; const _fixed& operator-=(const _fixed &rhs) ETL_ATTRIB_INLINE; template const _fixed& operator*=(const U &rhs) ETL_ATTRIB_INLINE; template const _fixed& operator/=(const U &rhs) ETL_ATTRIB_INLINE; const _fixed& operator*=(const _fixed &rhs) ETL_ATTRIB_INLINE; const _fixed& operator/=(const _fixed &rhs) ETL_ATTRIB_INLINE; const _fixed& operator*=(const int &rhs) ETL_ATTRIB_INLINE; const _fixed& operator/=(const int &rhs) ETL_ATTRIB_INLINE; template _fixed operator+(const U &rhs)const ETL_ATTRIB_INLINE; template _fixed operator-(const U &rhs)const ETL_ATTRIB_INLINE; template _fixed operator*(const U &rhs)const ETL_ATTRIB_INLINE; template _fixed operator/(const U &rhs)const ETL_ATTRIB_INLINE; _fixed operator+(const _fixed &rhs)const ETL_ATTRIB_INLINE; _fixed operator-(const _fixed &rhs)const ETL_ATTRIB_INLINE; _fixed operator*(const _fixed &rhs)const ETL_ATTRIB_INLINE; _fixed operator/(const _fixed &rhs)const ETL_ATTRIB_INLINE; _fixed operator*(const int &rhs)const ETL_ATTRIB_INLINE; _fixed operator/(const int &rhs)const ETL_ATTRIB_INLINE; _fixed operator*(const float &rhs)const ETL_ATTRIB_INLINE; _fixed operator*(const double &rhs)const ETL_ATTRIB_INLINE; // Negation Operator _fixed operator-()const ETL_ATTRIB_INLINE; // Casting Operators inline operator float()const ETL_ATTRIB_INLINE; inline operator double()const ETL_ATTRIB_INLINE; inline operator long double()const ETL_ATTRIB_INLINE; inline operator int()const ETL_ATTRIB_INLINE; inline operator bool()const ETL_ATTRIB_INLINE; _fixed floor()const; _fixed ceil()const; _fixed round()const; bool operator==(const _fixed &rhs)const { return data()==rhs.data(); } bool operator!=(const _fixed &rhs)const { return data()!=rhs.data(); } bool operator<(const _fixed &rhs)const { return data()(const _fixed &rhs)const { return data()>rhs.data(); } bool operator<=(const _fixed &rhs)const { return data()<=rhs.data(); } bool operator>=(const _fixed &rhs)const { return data()>=rhs.data(); } }; template fixed_base::fixed_base() {} template fixed_base::fixed_base(const _fixed &x):_data(x._data) {} template fixed_base::fixed_base(const float &f):_data(static_cast(f*_ONE() #ifdef ROUND_TO_NEAREST_INTEGER +0.5f #endif )) {} template fixed_base::fixed_base(const double &f):_data(static_cast(f*_ONE() #ifdef ROUND_TO_NEAREST_INTEGER +0.5 #endif )) {} template fixed_base::fixed_base(const long double &f):_data(static_cast(f*_ONE() #ifdef ROUND_TO_NEAREST_INTEGER +0.5 #endif )) {} template fixed_base::fixed_base(const int &i):_data(i< fixed_base::fixed_base(value_type x,raw):_data(x) { } template fixed_base::fixed_base(const int &n,const int &d):_data((n< inline bool fixed_base::_TYPE_SMALLER_THAN_INT() { return sizeof(T) inline bool fixed_base::_USING_ALL_BITS() { return sizeof(T)*8==FIXED_BITS; } template inline T fixed_base::_ONE() { return static_cast((_USING_ALL_BITS()?~T(0):1< inline T fixed_base::_F_MASK() { return static_cast(_USING_ALL_BITS()?~T(0):_ONE()-1); } template inline float fixed_base::_EPSILON() { return 1.0f/((float)_ONE()*2); } template T & fixed_base::data() { return _data; } template const T & fixed_base::data()const { return _data; } //! fixed+=fixed template const fixed_base & fixed_base::operator+=(const _fixed &rhs) { _data+=rhs._data; return *this; } //! fixed-=fixed template const fixed_base & fixed_base::operator-=(const _fixed &rhs) { _data-=rhs._data; return *this; } //! fixed*=fixed template const fixed_base & fixed_base::operator*=(const _fixed &rhs) { if(_TYPE_SMALLER_THAN_INT()) _data=static_cast((int)_data*(int)rhs._data>>FIXED_BITS); else { _data*=rhs._data; _data>>=FIXED_BITS; } return *this; } //! fixed/=fixed template const fixed_base & fixed_base::operator/=(const _fixed &rhs) { if(_TYPE_SMALLER_THAN_INT()) _data=static_cast((int)_data/(int)rhs._data< template const fixed_base & fixed_base::operator*=(const U &rhs) { return operator*=(fixed_base(rhs)); } template template const fixed_base & fixed_base::operator/=(const U &rhs) { return operator/=(fixed_base(rhs)); } //! fixed*=int template const fixed_base & fixed_base::operator*=(const int &rhs) { _data*=rhs; return *this; } //! fixed/=int template const fixed_base & fixed_base::operator/=(const int &rhs) { _data/=rhs; return *this; } //! fixed + fixed template fixed_base fixed_base::operator+(const _fixed &rhs)const { _fixed ret; ret._data=_data+rhs._data; return ret; } //! fixed - fixed template fixed_base fixed_base::operator-(const _fixed &rhs)const { _fixed ret; ret._data=_data-rhs._data; return ret; } //! fixed * fixed template fixed_base fixed_base::operator*(const _fixed &rhs)const { _fixed ret; ret._data=((_data*rhs._data)>>FIXED_BITS); return ret; //return reinterpret_cast<_fixed>((_data*rhs._data)>>FIXED_BITS); } //! fixed / fixed template fixed_base fixed_base::operator/(const _fixed &rhs)const { _fixed ret; ret._data=((_data/rhs._data)<((_data/rhs._data)< template fixed_base fixed_base::operator+(const U &rhs) const { return operator+(fixed_base(rhs)); } //! fixed - ... template template fixed_base fixed_base::operator-(const U &rhs) const { return operator-(fixed_base(rhs)); } //! fixed * ... template template fixed_base fixed_base::operator*(const U &rhs) const { return operator*(fixed_base(rhs)); } //! fixed / ... template template fixed_base fixed_base::operator/(const U &rhs) const { return operator/(fixed_base(rhs)); } //! fixed * int template fixed_base fixed_base::operator*(const int &rhs)const { _fixed ret; ret._data=_data*rhs; return ret; //return reinterpret_cast<_fixed>(_data*rhs); } //! fixed * float template fixed_base fixed_base::operator*(const float &rhs)const { return (*this)*_fixed(rhs); } //! fixed * double template fixed_base fixed_base::operator*(const double &rhs)const { return (*this)*_fixed(rhs); } //! fixed / int template fixed_base fixed_base::operator/(const int &rhs)const { _fixed ret; ret._data=_data/rhs; return ret; //return reinterpret_cast<_fixed>(_data/rhs); } //! float * fixed template fixed_base operator*(const float& lhs, const fixed_base &rhs) { return rhs*lhs; } //! double * fixed template fixed_base operator*(const double& lhs, const fixed_base &rhs) { return rhs*lhs; } // Negation Operator template fixed_base fixed_base::operator-()const { _fixed ret; ret._data=-_data; return ret; } // Casting Operators template fixed_base::operator float()const { return static_cast(_data)/static_cast(_ONE()); } template fixed_base::operator double()const { return static_cast(_data)/static_cast(_ONE()); } template fixed_base::operator long double()const { return static_cast(_data)/static_cast(_ONE()); } template fixed_base::operator int()const { return static_cast(_data>>FIXED_BITS); } template fixed_base::operator bool()const { return static_cast(_data); } template fixed_base fixed_base::floor()const { _fixed ret(*this); ret._data&=~_F_MASK(); return ret; } template fixed_base fixed_base::ceil()const { _fixed ret(*this); if(ret._data&_F_MASK()) ret._data=(ret._data&~_F_MASK()) + _ONE(); else ret._data&=~_F_MASK(); return ret; } template fixed_base fixed_base::round()const { _fixed ret(*this); ret._data+=_ONE()>>1; ret._data&=~_F_MASK(); return ret; } typedef fixed_base fixed; _ETL_END_NAMESPACE _STD_BEGIN_NAMESPACE template inline _ETL::fixed_base ceil(const _ETL::fixed_base &rhs) { return rhs.ceil(); } template _ETL::fixed_base floor(const _ETL::fixed_base &rhs) { return rhs.floor(); } template _ETL::fixed_base round(const _ETL::fixed_base &rhs) { return rhs.round(); } template _ETL::fixed_base abs(const _ETL::fixed_base &rhs) { return rhs<_ETL::fixed_base(0)?-rhs:rhs; } _STD_END_NAMESPACE /* template bool operator==(const _ETL::fixed_base& lhs, const _ETL::fixed_base& rhs) { return lhs.data()==rhs.data(); } template bool operator!=(const _ETL::fixed_base& lhs, const _ETL::fixed_base& rhs) { return lhs.data()!=rhs.data(); } template bool operator>(const _ETL::fixed_base& lhs, const _ETL::fixed_base& rhs) { return lhs.data()>rhs.data(); } template bool operator<(const _ETL::fixed_base& lhs, const _ETL::fixed_base& rhs) { return lhs.data() bool operator>=(const _ETL::fixed_base& lhs, const _ETL::fixed_base& rhs) { return lhs.data()>=rhs.data(); } template bool operator<=(const _ETL::fixed_base& lhs, const _ETL::fixed_base& rhs) { return lhs.data()<=rhs.data(); } */ #if defined(__GNUC__) && __GNUC__ == 3 template U operator*(const U &a,const _ETL::fixed_base &b) { return a*static_cast(b); } template U operator/(const U &a,const _ETL::fixed_base &b) { return a/static_cast(b); } template U operator+(const U &a,const _ETL::fixed_base &b) { return a+static_cast(b); } template U operator-(const U &a,const _ETL::fixed_base &b) { return a-static_cast(b); } /* inline const float & operator*=(float &a,const _ETL::fixed &b) { a*=(float)b; return a; } inline const float & operator/=(float &a,const _ETL::fixed &b) { a/=(float)b; return a; } inline const float & operator-=(float &a,const _ETL::fixed &b) { a-=(float)b; return a; } inline const float & operator+=(float &a,const _ETL::fixed &b) { a+=(float)b; return a; } */ #endif /* === E N D =============================================================== */ #endif