1 /*! ========================================================================
2 ** Extended Template and Library
3 ** Fixed-Point Math Class Implementation
6 ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
7 ** Copyright (c) 2007 Chris Moore
9 ** This package is free software; you can redistribute it and/or
10 ** modify it under the terms of the GNU General Public License as
11 ** published by the Free Software Foundation; either version 2 of
12 ** the License, or (at your option) any later version.
14 ** This package is distributed in the hope that it will be useful,
15 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 ** General Public License for more details.
19 ** === N O T E S ===========================================================
21 ** This is an internal header file, included by other ETL headers.
22 ** You should not attempt to use it directly.
24 ** ========================================================================= */
26 /* === S T A R T =========================================================== */
28 #ifndef __ETL__FIXED_H
29 #define __ETL__FIXED_H
31 /* === H E A D E R S ======================================================= */
35 /* === M A C R O S ========================================================= */
37 // the "+0.5" code was commented out - maybe to make thing run faster?
38 // it can be re-enabled by uncommenting this next line:
39 // #define ROUND_TO_NEAREST_INTEGER
41 #ifndef ETL_FIXED_TYPE
42 # define ETL_FIXED_TYPE int
45 #ifndef ETL_FIXED_BITS
46 #define ETL_FIXED_BITS 12
49 #ifndef ETL_FIXED_EPSILON
50 #define ETL_FIXED_EPSILON _EPSILON()
54 #define ETL_ATTRIB_CONST __attribute__ ((const))
55 #define ETL_ATTRIB_PURE __attribute__ ((pure))
56 #define ETL_ATTRIB_INLINE __attribute__ ((always_inline))
58 #define ETL_ATTRIB_CONST
59 #define ETL_ATTRIB_PURE
60 #define ETL_ATTRIB_INLINE
63 /* === C L A S S E S & S T R U C T S ======================================= */
67 // Forward declarations
68 template<typename T, unsigned int FIXED_BITS> class fixed_base;
69 //template<> class fixed_base<char>;
74 template<typename T, unsigned int FIXED_BITS> _ETL::fixed_base<T,FIXED_BITS> abs(const _ETL::fixed_base<T,FIXED_BITS>&);
75 template<typename T, unsigned int FIXED_BITS> _ETL::fixed_base<T,FIXED_BITS> cos(const _ETL::fixed_base<T,FIXED_BITS>&);
76 template<typename T, unsigned int FIXED_BITS> _ETL::fixed_base<T,FIXED_BITS> cosh(const _ETL::fixed_base<T,FIXED_BITS>&);
77 template<typename T, unsigned int FIXED_BITS> _ETL::fixed_base<T,FIXED_BITS> exp(const _ETL::fixed_base<T,FIXED_BITS>&);
78 template<typename T, unsigned int FIXED_BITS> _ETL::fixed_base<T,FIXED_BITS> log(const _ETL::fixed_base<T,FIXED_BITS>&);
79 template<typename T, unsigned int FIXED_BITS> _ETL::fixed_base<T,FIXED_BITS> log10(const _ETL::fixed_base<T,FIXED_BITS>&);
80 template<typename T, unsigned int FIXED_BITS> _ETL::fixed_base<T,FIXED_BITS> pow(const _ETL::fixed_base<T,FIXED_BITS>&, int);
81 template<typename T, unsigned int FIXED_BITS> _ETL::fixed_base<T,FIXED_BITS> pow(const _ETL::fixed_base<T,FIXED_BITS>&, const T&);
82 template<typename T, unsigned int FIXED_BITS> _ETL::fixed_base<T,FIXED_BITS> pow(const _ETL::fixed_base<T,FIXED_BITS>&,
83 const _ETL::fixed_base<T,FIXED_BITS>&);
84 template<typename T, unsigned int FIXED_BITS> _ETL::fixed_base<T,FIXED_BITS> pow(const _ETL::fixed_base<T,FIXED_BITS>&, const _ETL::fixed_base<T,FIXED_BITS>&);
85 template<typename T, unsigned int FIXED_BITS> _ETL::fixed_base<T,FIXED_BITS> sin(const _ETL::fixed_base<T,FIXED_BITS>&);
86 template<typename T, unsigned int FIXED_BITS> _ETL::fixed_base<T,FIXED_BITS> sinh(const _ETL::fixed_base<T,FIXED_BITS>&);
87 template<typename T, unsigned int FIXED_BITS> _ETL::fixed_base<T,FIXED_BITS> sqrt(const _ETL::fixed_base<T,FIXED_BITS>&);
88 template<typename T, unsigned int FIXED_BITS> _ETL::fixed_base<T,FIXED_BITS> tan(const _ETL::fixed_base<T,FIXED_BITS>&);
89 template<typename T, unsigned int FIXED_BITS> _ETL::fixed_base<T,FIXED_BITS> tanh(const _ETL::fixed_base<T,FIXED_BITS>&);
93 /*! ========================================================================
95 ** \brief Fixed-point template base class
97 ** A more detailed description needs to be written.
99 template <class T,unsigned int FIXED_BITS>
103 typedef T value_type;
107 typedef fixed_base<T,FIXED_BITS> _fixed;
108 typedef fixed_base<T,FIXED_BITS> self_type;
110 inline static bool _TYPE_SMALLER_THAN_INT() ETL_ATTRIB_CONST ETL_ATTRIB_INLINE;
111 inline static bool _USING_ALL_BITS() ETL_ATTRIB_CONST ETL_ATTRIB_INLINE;
112 inline static value_type _ONE() ETL_ATTRIB_CONST ETL_ATTRIB_INLINE;
113 inline static value_type _F_MASK() ETL_ATTRIB_CONST ETL_ATTRIB_INLINE;
114 inline static float _EPSILON() ETL_ATTRIB_CONST ETL_ATTRIB_INLINE;
118 fixed_base()ETL_ATTRIB_INLINE;
119 fixed_base(const float &f)ETL_ATTRIB_INLINE;
120 fixed_base(const double &f)ETL_ATTRIB_INLINE;
121 fixed_base(const long double &f)ETL_ATTRIB_INLINE;
122 fixed_base(const int &i)ETL_ATTRIB_INLINE;
123 fixed_base(const int &n,const int &d)ETL_ATTRIB_INLINE; //!< Fraction constructor
124 fixed_base(const _fixed &x)ETL_ATTRIB_INLINE;
125 fixed_base(value_type x,raw)ETL_ATTRIB_INLINE;
127 T &data() ETL_ATTRIB_PURE ETL_ATTRIB_INLINE;
128 const T &data()const ETL_ATTRIB_PURE ETL_ATTRIB_INLINE;
130 const _fixed& operator+=(const _fixed &rhs) ETL_ATTRIB_INLINE;
131 const _fixed& operator-=(const _fixed &rhs) ETL_ATTRIB_INLINE;
132 template<typename U> const _fixed& operator*=(const U &rhs) ETL_ATTRIB_INLINE;
133 template<typename U> const _fixed& operator/=(const U &rhs) ETL_ATTRIB_INLINE;
134 const _fixed& operator*=(const _fixed &rhs) ETL_ATTRIB_INLINE;
135 const _fixed& operator/=(const _fixed &rhs) ETL_ATTRIB_INLINE;
136 const _fixed& operator*=(const int &rhs) ETL_ATTRIB_INLINE;
137 const _fixed& operator/=(const int &rhs) ETL_ATTRIB_INLINE;
140 template<typename U> _fixed operator+(const U &rhs)const ETL_ATTRIB_INLINE;
141 template<typename U> _fixed operator-(const U &rhs)const ETL_ATTRIB_INLINE;
142 template<typename U> _fixed operator*(const U &rhs)const ETL_ATTRIB_INLINE;
143 template<typename U> _fixed operator/(const U &rhs)const ETL_ATTRIB_INLINE;
144 _fixed operator+(const _fixed &rhs)const ETL_ATTRIB_INLINE;
145 _fixed operator-(const _fixed &rhs)const ETL_ATTRIB_INLINE;
146 _fixed operator*(const _fixed &rhs)const ETL_ATTRIB_INLINE;
147 _fixed operator/(const _fixed &rhs)const ETL_ATTRIB_INLINE;
148 _fixed operator*(const int &rhs)const ETL_ATTRIB_INLINE;
149 _fixed operator/(const int &rhs)const ETL_ATTRIB_INLINE;
150 _fixed operator*(const float &rhs)const ETL_ATTRIB_INLINE;
151 _fixed operator*(const double &rhs)const ETL_ATTRIB_INLINE;
154 _fixed operator-()const ETL_ATTRIB_INLINE;
157 inline operator float()const ETL_ATTRIB_INLINE;
158 inline operator double()const ETL_ATTRIB_INLINE;
159 inline operator long double()const ETL_ATTRIB_INLINE;
160 inline operator int()const ETL_ATTRIB_INLINE;
161 inline operator bool()const ETL_ATTRIB_INLINE;
167 bool operator==(const _fixed &rhs)const { return data()==rhs.data(); }
168 bool operator!=(const _fixed &rhs)const { return data()!=rhs.data(); }
169 bool operator<(const _fixed &rhs)const { return data()<rhs.data(); }
170 bool operator>(const _fixed &rhs)const { return data()>rhs.data(); }
171 bool operator<=(const _fixed &rhs)const { return data()<=rhs.data(); }
172 bool operator>=(const _fixed &rhs)const { return data()>=rhs.data(); }
176 template <class T,unsigned int FIXED_BITS>
177 fixed_base<T,FIXED_BITS>::fixed_base()
180 template <class T,unsigned int FIXED_BITS>
181 fixed_base<T,FIXED_BITS>::fixed_base(const _fixed &x):_data(x._data)
184 template <class T,unsigned int FIXED_BITS>
185 fixed_base<T,FIXED_BITS>::fixed_base(const float &f):_data(static_cast<value_type>(f*_ONE()
186 #ifdef ROUND_TO_NEAREST_INTEGER
191 template <class T,unsigned int FIXED_BITS>
192 fixed_base<T,FIXED_BITS>::fixed_base(const double &f):_data(static_cast<value_type>(f*_ONE()
193 #ifdef ROUND_TO_NEAREST_INTEGER
198 template <class T,unsigned int FIXED_BITS>
199 fixed_base<T,FIXED_BITS>::fixed_base(const long double &f):_data(static_cast<value_type>(f*_ONE()
200 #ifdef ROUND_TO_NEAREST_INTEGER
205 template <class T,unsigned int FIXED_BITS>
206 fixed_base<T,FIXED_BITS>::fixed_base(const int &i):_data(i<<FIXED_BITS)
209 template <class T,unsigned int FIXED_BITS>
210 fixed_base<T,FIXED_BITS>::fixed_base(value_type x,raw):_data(x) { }
212 template <class T,unsigned int FIXED_BITS>
213 fixed_base<T,FIXED_BITS>::fixed_base(const int &n,const int &d):_data((n<<FIXED_BITS)/d) { }
217 template <class T,unsigned int FIXED_BITS> inline bool
218 fixed_base<T,FIXED_BITS>::_TYPE_SMALLER_THAN_INT()
220 return sizeof(T)<sizeof(int);
223 template <class T,unsigned int FIXED_BITS> inline bool
224 fixed_base<T,FIXED_BITS>::_USING_ALL_BITS()
226 return sizeof(T)*8==FIXED_BITS;
229 template <class T,unsigned int FIXED_BITS> inline T
230 fixed_base<T,FIXED_BITS>::_ONE()
232 return static_cast<T>((_USING_ALL_BITS()?~T(0):1<<FIXED_BITS));
235 template <class T,unsigned int FIXED_BITS> inline T
236 fixed_base<T,FIXED_BITS>::_F_MASK()
238 return static_cast<T>(_USING_ALL_BITS()?~T(0):_ONE()-1);
241 template <class T,unsigned int FIXED_BITS> inline float
242 fixed_base<T,FIXED_BITS>::_EPSILON()
244 return 1.0f/((float)_ONE()*2);
248 template <class T,unsigned int FIXED_BITS>T &
249 fixed_base<T,FIXED_BITS>::data()
254 template <class T,unsigned int FIXED_BITS>const T &
255 fixed_base<T,FIXED_BITS>::data()const
261 template <class T,unsigned int FIXED_BITS>const fixed_base<T,FIXED_BITS> &
262 fixed_base<T,FIXED_BITS>::operator+=(const _fixed &rhs)
269 template <class T,unsigned int FIXED_BITS>const fixed_base<T,FIXED_BITS> &
270 fixed_base<T,FIXED_BITS>::operator-=(const _fixed &rhs)
277 template <class T,unsigned int FIXED_BITS>const fixed_base<T,FIXED_BITS> &
278 fixed_base<T,FIXED_BITS>::operator*=(const _fixed &rhs)
280 if(_TYPE_SMALLER_THAN_INT())
281 _data=static_cast<T>((int)_data*(int)rhs._data>>FIXED_BITS);
292 template <class T,unsigned int FIXED_BITS>const fixed_base<T,FIXED_BITS> &
293 fixed_base<T,FIXED_BITS>::operator/=(const _fixed &rhs)
295 if(_TYPE_SMALLER_THAN_INT())
296 _data=static_cast<T>((int)_data/(int)rhs._data<<FIXED_BITS);
305 template <class T,unsigned int FIXED_BITS> template<typename U> const fixed_base<T,FIXED_BITS> &
306 fixed_base<T,FIXED_BITS>::operator*=(const U &rhs)
308 return operator*=(fixed_base<T,FIXED_BITS>(rhs));
311 template <class T,unsigned int FIXED_BITS> template<typename U> const fixed_base<T,FIXED_BITS> &
312 fixed_base<T,FIXED_BITS>::operator/=(const U &rhs)
314 return operator/=(fixed_base<T,FIXED_BITS>(rhs));
318 template <class T,unsigned int FIXED_BITS>const fixed_base<T,FIXED_BITS> &
319 fixed_base<T,FIXED_BITS>::operator*=(const int &rhs)
321 _data*=rhs; return *this;
325 template <class T,unsigned int FIXED_BITS>const fixed_base<T,FIXED_BITS> &
326 fixed_base<T,FIXED_BITS>::operator/=(const int &rhs)
328 _data/=rhs; return *this;
338 template <class T,unsigned int FIXED_BITS>fixed_base<T,FIXED_BITS>
339 fixed_base<T,FIXED_BITS>::operator+(const _fixed &rhs)const
342 ret._data=_data+rhs._data;
347 template <class T,unsigned int FIXED_BITS>fixed_base<T,FIXED_BITS>
348 fixed_base<T,FIXED_BITS>::operator-(const _fixed &rhs)const
351 ret._data=_data-rhs._data;
356 template <class T,unsigned int FIXED_BITS>fixed_base<T,FIXED_BITS>
357 fixed_base<T,FIXED_BITS>::operator*(const _fixed &rhs)const
360 ret._data=((_data*rhs._data)>>FIXED_BITS);
362 //return reinterpret_cast<_fixed>((_data*rhs._data)>>FIXED_BITS);
366 template <class T,unsigned int FIXED_BITS>fixed_base<T,FIXED_BITS>
367 fixed_base<T,FIXED_BITS>::operator/(const _fixed &rhs)const
370 ret._data=((_data/rhs._data)<<FIXED_BITS);
372 //return reinterpret_cast<_fixed>((_data/rhs._data)<<FIXED_BITS);
376 template <class T,unsigned int FIXED_BITS> template<typename U> fixed_base<T,FIXED_BITS>
377 fixed_base<T,FIXED_BITS>::operator+(const U &rhs) const
379 return operator+(fixed_base<T,FIXED_BITS>(rhs));
383 template <class T,unsigned int FIXED_BITS> template<typename U> fixed_base<T,FIXED_BITS>
384 fixed_base<T,FIXED_BITS>::operator-(const U &rhs) const
386 return operator-(fixed_base<T,FIXED_BITS>(rhs));
390 template <class T,unsigned int FIXED_BITS> template<typename U> fixed_base<T,FIXED_BITS>
391 fixed_base<T,FIXED_BITS>::operator*(const U &rhs) const
393 return operator*(fixed_base<T,FIXED_BITS>(rhs));
397 template <class T,unsigned int FIXED_BITS> template<typename U> fixed_base<T,FIXED_BITS>
398 fixed_base<T,FIXED_BITS>::operator/(const U &rhs) const
400 return operator/(fixed_base<T,FIXED_BITS>(rhs));
404 template <class T,unsigned int FIXED_BITS>fixed_base<T,FIXED_BITS>
405 fixed_base<T,FIXED_BITS>::operator*(const int &rhs)const
410 //return reinterpret_cast<_fixed>(_data*rhs);
414 template <class T,unsigned int FIXED_BITS>fixed_base<T,FIXED_BITS>
415 fixed_base<T,FIXED_BITS>::operator*(const float &rhs)const
417 return (*this)*_fixed(rhs);
421 template <class T,unsigned int FIXED_BITS>fixed_base<T,FIXED_BITS>
422 fixed_base<T,FIXED_BITS>::operator*(const double &rhs)const
424 return (*this)*_fixed(rhs);
429 template <class T,unsigned int FIXED_BITS>fixed_base<T,FIXED_BITS>
430 fixed_base<T,FIXED_BITS>::operator/(const int &rhs)const
435 //return reinterpret_cast<_fixed>(_data/rhs);
439 template <class T,unsigned int FIXED_BITS>fixed_base<T,FIXED_BITS>
440 operator*(const float& lhs, const fixed_base<T,FIXED_BITS> &rhs)
446 template <class T,unsigned int FIXED_BITS>fixed_base<T,FIXED_BITS>
447 operator*(const double& lhs, const fixed_base<T,FIXED_BITS> &rhs)
458 template <class T,unsigned int FIXED_BITS>fixed_base<T,FIXED_BITS>
459 fixed_base<T,FIXED_BITS>::operator-()const
461 _fixed ret; ret._data=-_data; return ret;
465 template <class T,unsigned int FIXED_BITS>
466 fixed_base<T,FIXED_BITS>::operator float()const
468 return static_cast<float>(_data)/static_cast<float>(_ONE());
471 template <class T,unsigned int FIXED_BITS>
472 fixed_base<T,FIXED_BITS>::operator double()const
474 return static_cast<double>(_data)/static_cast<double>(_ONE());
477 template <class T,unsigned int FIXED_BITS>
478 fixed_base<T,FIXED_BITS>::operator long double()const
480 return static_cast<long double>(_data)/static_cast<long double>(_ONE());
483 template <class T,unsigned int FIXED_BITS>
484 fixed_base<T,FIXED_BITS>::operator int()const
486 return static_cast<int>(_data>>FIXED_BITS);
489 template <class T,unsigned int FIXED_BITS>
490 fixed_base<T,FIXED_BITS>::operator bool()const
492 return static_cast<bool>(_data);
496 template <class T,unsigned int FIXED_BITS> fixed_base<T,FIXED_BITS>
497 fixed_base<T,FIXED_BITS>::floor()const
500 ret._data&=~_F_MASK();
504 template <class T,unsigned int FIXED_BITS> fixed_base<T,FIXED_BITS>
505 fixed_base<T,FIXED_BITS>::ceil()const
508 if(ret._data&_F_MASK())
509 ret._data=(ret._data&~_F_MASK()) + _ONE();
511 ret._data&=~_F_MASK();
515 template <class T,unsigned int FIXED_BITS> fixed_base<T,FIXED_BITS>
516 fixed_base<T,FIXED_BITS>::round()const
519 ret._data+=_ONE()>>1;
520 ret._data&=~_F_MASK();
549 typedef fixed_base<ETL_FIXED_TYPE,ETL_FIXED_BITS> fixed;
555 template <class T,unsigned int FIXED_BITS>
556 inline _ETL::fixed_base<T,FIXED_BITS>
557 ceil(const _ETL::fixed_base<T,FIXED_BITS> &rhs)
558 { return rhs.ceil(); }
560 template <class T,unsigned int FIXED_BITS>
561 _ETL::fixed_base<T,FIXED_BITS>
562 floor(const _ETL::fixed_base<T,FIXED_BITS> &rhs)
563 { return rhs.floor(); }
565 template <class T,unsigned int FIXED_BITS>
566 _ETL::fixed_base<T,FIXED_BITS>
567 round(const _ETL::fixed_base<T,FIXED_BITS> &rhs)
568 { return rhs.round(); }
570 template <class T,unsigned int FIXED_BITS>
571 _ETL::fixed_base<T,FIXED_BITS>
572 abs(const _ETL::fixed_base<T,FIXED_BITS> &rhs)
573 { return rhs<_ETL::fixed_base<T,FIXED_BITS>(0)?-rhs:rhs; }
578 template <class T,unsigned int FIXED_BITS, typename U> bool
579 operator==(const _ETL::fixed_base<T,FIXED_BITS>& lhs, const _ETL::fixed_base<T,FIXED_BITS>& rhs)
580 { return lhs.data()==rhs.data(); }
582 template <class T,unsigned int FIXED_BITS, typename U> bool
583 operator!=(const _ETL::fixed_base<T,FIXED_BITS>& lhs, const _ETL::fixed_base<T,FIXED_BITS>& rhs)
584 { return lhs.data()!=rhs.data(); }
586 template <class T,unsigned int FIXED_BITS, typename U> bool
587 operator>(const _ETL::fixed_base<T,FIXED_BITS>& lhs, const _ETL::fixed_base<T,FIXED_BITS>& rhs)
588 { return lhs.data()>rhs.data(); }
590 template <class T,unsigned int FIXED_BITS, typename U> bool
591 operator<(const _ETL::fixed_base<T,FIXED_BITS>& lhs, const _ETL::fixed_base<T,FIXED_BITS>& rhs)
592 { return lhs.data()<rhs.data(); }
594 template <class T,unsigned int FIXED_BITS, typename U> bool
595 operator>=(const _ETL::fixed_base<T,FIXED_BITS>& lhs, const _ETL::fixed_base<T,FIXED_BITS>& rhs)
596 { return lhs.data()>=rhs.data(); }
598 template <class T,unsigned int FIXED_BITS, typename U> bool
599 operator<=(const _ETL::fixed_base<T,FIXED_BITS>& lhs, const _ETL::fixed_base<T,FIXED_BITS>& rhs)
600 { return lhs.data()<=rhs.data(); }
604 #if defined(__GNUC__) && __GNUC__ == 3
605 template <class T,unsigned int FIXED_BITS, typename U> U
606 operator*(const U &a,const _ETL::fixed_base<T,FIXED_BITS> &b)
607 { return a*static_cast<double>(b); }
609 template <class T,unsigned int FIXED_BITS, typename U> U
610 operator/(const U &a,const _ETL::fixed_base<T,FIXED_BITS> &b)
611 { return a/static_cast<double>(b); }
613 template <class T,unsigned int FIXED_BITS, typename U> U
614 operator+(const U &a,const _ETL::fixed_base<T,FIXED_BITS> &b)
615 { return a+static_cast<double>(b); }
617 template <class T,unsigned int FIXED_BITS, typename U> U
618 operator-(const U &a,const _ETL::fixed_base<T,FIXED_BITS> &b)
619 { return a-static_cast<double>(b); }
624 operator*=(float &a,const _ETL::fixed &b)
625 { a*=(float)b; return a; }
628 operator/=(float &a,const _ETL::fixed &b)
629 { a/=(float)b; return a; }
632 operator-=(float &a,const _ETL::fixed &b)
633 { a-=(float)b; return a; }
636 operator+=(float &a,const _ETL::fixed &b)
637 { a+=(float)b; return a; }
641 /* === E N D =============================================================== */