1 /*! ========================================================================
2 ** Extended Template and Library
3 ** Fixed-Point Math Class Implementation
6 ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
8 ** This package is free software; you can redistribute it and/or
9 ** modify it under the terms of the GNU General Public License as
10 ** published by the Free Software Foundation; either version 2 of
11 ** the License, or (at your option) any later version.
13 ** This package is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 ** General Public License for more details.
18 ** === N O T E S ===========================================================
20 ** This is an internal header file, included by other ETL headers.
21 ** You should not attempt to use it directly.
23 ** ========================================================================= */
25 /* === S T A R T =========================================================== */
27 #ifndef __ETL__FIXED_H
28 #define __ETL__FIXED_H
30 /* === H E A D E R S ======================================================= */
34 /* === M A C R O S ========================================================= */
36 // the "+0.5" code was commented out - maybe to make thing run faster?
37 // it can be re-enabled by uncommenting this next line:
38 // #define ROUND_TO_NEAREST_INTEGER
40 #ifndef ETL_FIXED_TYPE
41 # define ETL_FIXED_TYPE int
44 #ifndef ETL_FIXED_BITS
45 #define ETL_FIXED_BITS 12
48 #ifndef ETL_FIXED_EPSILON
49 #define ETL_FIXED_EPSILON _EPSILON()
53 #define ETL_ATTRIB_CONST __attribute__ ((const))
54 #define ETL_ATTRIB_PURE __attribute__ ((pure))
55 #define ETL_ATTRIB_INLINE __attribute__ ((always_inline))
57 #define ETL_ATTRIB_CONST
58 #define ETL_ATTRIB_PURE
59 #define ETL_ATTRIB_INLINE
62 /* === C L A S S E S & S T R U C T S ======================================= */
66 // Forward declarations
67 template<typename T, unsigned int FIXED_BITS> class fixed_base;
68 //template<> class fixed_base<char>;
73 template<typename T, unsigned int FIXED_BITS> _ETL::fixed_base<T,FIXED_BITS> abs(const _ETL::fixed_base<T,FIXED_BITS>&);
74 template<typename T, unsigned int FIXED_BITS> _ETL::fixed_base<T,FIXED_BITS> cos(const _ETL::fixed_base<T,FIXED_BITS>&);
75 template<typename T, unsigned int FIXED_BITS> _ETL::fixed_base<T,FIXED_BITS> cosh(const _ETL::fixed_base<T,FIXED_BITS>&);
76 template<typename T, unsigned int FIXED_BITS> _ETL::fixed_base<T,FIXED_BITS> exp(const _ETL::fixed_base<T,FIXED_BITS>&);
77 template<typename T, unsigned int FIXED_BITS> _ETL::fixed_base<T,FIXED_BITS> log(const _ETL::fixed_base<T,FIXED_BITS>&);
78 template<typename T, unsigned int FIXED_BITS> _ETL::fixed_base<T,FIXED_BITS> log10(const _ETL::fixed_base<T,FIXED_BITS>&);
79 template<typename T, unsigned int FIXED_BITS> _ETL::fixed_base<T,FIXED_BITS> pow(const _ETL::fixed_base<T,FIXED_BITS>&, int);
80 template<typename T, unsigned int FIXED_BITS> _ETL::fixed_base<T,FIXED_BITS> pow(const _ETL::fixed_base<T,FIXED_BITS>&, const T&);
81 template<typename T, unsigned int FIXED_BITS> _ETL::fixed_base<T,FIXED_BITS> pow(const _ETL::fixed_base<T,FIXED_BITS>&,
82 const _ETL::fixed_base<T,FIXED_BITS>&);
83 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>&);
84 template<typename T, unsigned int FIXED_BITS> _ETL::fixed_base<T,FIXED_BITS> sin(const _ETL::fixed_base<T,FIXED_BITS>&);
85 template<typename T, unsigned int FIXED_BITS> _ETL::fixed_base<T,FIXED_BITS> sinh(const _ETL::fixed_base<T,FIXED_BITS>&);
86 template<typename T, unsigned int FIXED_BITS> _ETL::fixed_base<T,FIXED_BITS> sqrt(const _ETL::fixed_base<T,FIXED_BITS>&);
87 template<typename T, unsigned int FIXED_BITS> _ETL::fixed_base<T,FIXED_BITS> tan(const _ETL::fixed_base<T,FIXED_BITS>&);
88 template<typename T, unsigned int FIXED_BITS> _ETL::fixed_base<T,FIXED_BITS> tanh(const _ETL::fixed_base<T,FIXED_BITS>&);
92 /*! ========================================================================
94 ** \brief Fixed-point template base class
96 ** A more detailed description needs to be written.
98 template <class T,unsigned int FIXED_BITS>
102 typedef T value_type;
106 typedef fixed_base<T,FIXED_BITS> _fixed;
107 typedef fixed_base<T,FIXED_BITS> self_type;
109 inline static bool _TYPE_SMALLER_THAN_INT() ETL_ATTRIB_CONST ETL_ATTRIB_INLINE;
110 inline static bool _USING_ALL_BITS() ETL_ATTRIB_CONST ETL_ATTRIB_INLINE;
111 inline static value_type _ONE() ETL_ATTRIB_CONST ETL_ATTRIB_INLINE;
112 inline static value_type _F_MASK() ETL_ATTRIB_CONST ETL_ATTRIB_INLINE;
113 inline static float _EPSILON() ETL_ATTRIB_CONST ETL_ATTRIB_INLINE;
117 fixed_base()ETL_ATTRIB_INLINE;
118 fixed_base(const float &f)ETL_ATTRIB_INLINE;
119 fixed_base(const double &f)ETL_ATTRIB_INLINE;
120 fixed_base(const long double &f)ETL_ATTRIB_INLINE;
121 fixed_base(const int &i)ETL_ATTRIB_INLINE;
122 fixed_base(const int &n,const int &d)ETL_ATTRIB_INLINE; //!< Fraction constructor
123 fixed_base(const _fixed &x)ETL_ATTRIB_INLINE;
124 fixed_base(value_type x,raw)ETL_ATTRIB_INLINE;
126 T &data() ETL_ATTRIB_PURE ETL_ATTRIB_INLINE;
127 const T &data()const ETL_ATTRIB_PURE ETL_ATTRIB_INLINE;
129 const _fixed& operator+=(const _fixed &rhs) ETL_ATTRIB_INLINE;
130 const _fixed& operator-=(const _fixed &rhs) ETL_ATTRIB_INLINE;
131 template<typename U> const _fixed& operator*=(const U &rhs) ETL_ATTRIB_INLINE;
132 template<typename U> const _fixed& operator/=(const U &rhs) ETL_ATTRIB_INLINE;
133 const _fixed& operator*=(const _fixed &rhs) ETL_ATTRIB_INLINE;
134 const _fixed& operator/=(const _fixed &rhs) ETL_ATTRIB_INLINE;
135 const _fixed& operator*=(const int &rhs) ETL_ATTRIB_INLINE;
136 const _fixed& operator/=(const int &rhs) ETL_ATTRIB_INLINE;
139 template<typename U> _fixed operator+(const U &rhs)const 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 _fixed operator+(const _fixed &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 int &rhs)const ETL_ATTRIB_INLINE;
148 _fixed operator/(const int &rhs)const ETL_ATTRIB_INLINE;
149 _fixed operator*(const float &rhs)const ETL_ATTRIB_INLINE;
150 _fixed operator*(const double &rhs)const ETL_ATTRIB_INLINE;
153 _fixed operator-()const ETL_ATTRIB_INLINE;
156 inline operator float()const ETL_ATTRIB_INLINE;
157 inline operator double()const ETL_ATTRIB_INLINE;
158 inline operator long double()const ETL_ATTRIB_INLINE;
159 inline operator int()const ETL_ATTRIB_INLINE;
160 inline operator bool()const ETL_ATTRIB_INLINE;
166 bool operator==(const _fixed &rhs)const { return data()==rhs.data(); }
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(); }
175 template <class T,unsigned int FIXED_BITS>
176 fixed_base<T,FIXED_BITS>::fixed_base()
179 template <class T,unsigned int FIXED_BITS>
180 fixed_base<T,FIXED_BITS>::fixed_base(const _fixed &x):_data(x._data)
183 template <class T,unsigned int FIXED_BITS>
184 fixed_base<T,FIXED_BITS>::fixed_base(const float &f):_data(static_cast<value_type>(f*_ONE()
185 #ifdef ROUND_TO_NEAREST_INTEGER
190 template <class T,unsigned int FIXED_BITS>
191 fixed_base<T,FIXED_BITS>::fixed_base(const double &f):_data(static_cast<value_type>(f*_ONE()
192 #ifdef ROUND_TO_NEAREST_INTEGER
197 template <class T,unsigned int FIXED_BITS>
198 fixed_base<T,FIXED_BITS>::fixed_base(const long double &f):_data(static_cast<value_type>(f*_ONE()
199 #ifdef ROUND_TO_NEAREST_INTEGER
204 template <class T,unsigned int FIXED_BITS>
205 fixed_base<T,FIXED_BITS>::fixed_base(const int &i):_data(i<<FIXED_BITS)
208 template <class T,unsigned int FIXED_BITS>
209 fixed_base<T,FIXED_BITS>::fixed_base(value_type x,raw):_data(x) { }
211 template <class T,unsigned int FIXED_BITS>
212 fixed_base<T,FIXED_BITS>::fixed_base(const int &n,const int &d):_data((n<<FIXED_BITS)/d) { }
216 template <class T,unsigned int FIXED_BITS> inline bool
217 fixed_base<T,FIXED_BITS>::_TYPE_SMALLER_THAN_INT()
219 return sizeof(T)<sizeof(int);
222 template <class T,unsigned int FIXED_BITS> inline bool
223 fixed_base<T,FIXED_BITS>::_USING_ALL_BITS()
225 return sizeof(T)*8==FIXED_BITS;
228 template <class T,unsigned int FIXED_BITS> inline T
229 fixed_base<T,FIXED_BITS>::_ONE()
231 return static_cast<T>((_USING_ALL_BITS()?~T(0):1<<FIXED_BITS));
234 template <class T,unsigned int FIXED_BITS> inline T
235 fixed_base<T,FIXED_BITS>::_F_MASK()
237 return static_cast<T>(_USING_ALL_BITS()?~T(0):_ONE()-1);
240 template <class T,unsigned int FIXED_BITS> inline float
241 fixed_base<T,FIXED_BITS>::_EPSILON()
243 return 1.0f/((float)_ONE()*2);
247 template <class T,unsigned int FIXED_BITS>T &
248 fixed_base<T,FIXED_BITS>::data()
253 template <class T,unsigned int FIXED_BITS>const T &
254 fixed_base<T,FIXED_BITS>::data()const
260 template <class T,unsigned int FIXED_BITS>const fixed_base<T,FIXED_BITS> &
261 fixed_base<T,FIXED_BITS>::operator+=(const fixed_base<T,FIXED_BITS> &rhs)
268 template <class T,unsigned int FIXED_BITS>const fixed_base<T,FIXED_BITS> &
269 fixed_base<T,FIXED_BITS>::operator-=(const fixed_base<T,FIXED_BITS> &rhs)
276 template <class T,unsigned int FIXED_BITS>const fixed_base<T,FIXED_BITS> &
277 fixed_base<T,FIXED_BITS>::operator*=(const fixed_base<T,FIXED_BITS> &rhs)
279 if(_TYPE_SMALLER_THAN_INT())
280 _data=static_cast<T>((int)_data*(int)rhs._data>>FIXED_BITS);
291 template <class T,unsigned int FIXED_BITS>const fixed_base<T,FIXED_BITS> &
292 fixed_base<T,FIXED_BITS>::operator/=(const fixed_base<T,FIXED_BITS> &rhs)
294 if(_TYPE_SMALLER_THAN_INT())
295 _data=static_cast<T>((int)_data/(int)rhs._data<<FIXED_BITS);
304 template <class T,unsigned int FIXED_BITS> template<typename U> const fixed_base<T,FIXED_BITS> &
305 fixed_base<T,FIXED_BITS>::operator*=(const U &rhs)
307 return operator*=(fixed_base<T,FIXED_BITS>(rhs));
310 template <class T,unsigned int FIXED_BITS> template<typename U> const fixed_base<T,FIXED_BITS> &
311 fixed_base<T,FIXED_BITS>::operator/=(const U &rhs)
313 return operator/=(fixed_base<T,FIXED_BITS>(rhs));
317 template <class T,unsigned int FIXED_BITS>const fixed_base<T,FIXED_BITS> &
318 fixed_base<T,FIXED_BITS>::operator*=(const int &rhs)
320 _data*=rhs; return *this;
324 template <class T,unsigned int FIXED_BITS>const fixed_base<T,FIXED_BITS> &
325 fixed_base<T,FIXED_BITS>::operator/=(const int &rhs)
327 _data/=rhs; return *this;
337 template <class T,unsigned int FIXED_BITS>fixed_base<T,FIXED_BITS>
338 fixed_base<T,FIXED_BITS>::operator+(const fixed_base<T,FIXED_BITS> &rhs)const
341 ret._data=_data+rhs._data;
346 template <class T,unsigned int FIXED_BITS>fixed_base<T,FIXED_BITS>
347 fixed_base<T,FIXED_BITS>::operator-(const fixed_base<T,FIXED_BITS> &rhs)const
350 ret._data=_data-rhs._data;
355 template <class T,unsigned int FIXED_BITS>fixed_base<T,FIXED_BITS>
356 fixed_base<T,FIXED_BITS>::operator*(const fixed_base<T,FIXED_BITS> &rhs)const
359 ret._data=((_data*rhs._data)>>FIXED_BITS);
361 //return reinterpret_cast<_fixed>((_data*rhs._data)>>FIXED_BITS);
365 template <class T,unsigned int FIXED_BITS>fixed_base<T,FIXED_BITS>
366 fixed_base<T,FIXED_BITS>::operator/(const fixed_base<T,FIXED_BITS> &rhs)const
369 ret._data=((_data/rhs._data)<<FIXED_BITS);
371 //return reinterpret_cast<_fixed>((_data/rhs._data)<<FIXED_BITS);
375 template <class T,unsigned int FIXED_BITS> template<typename U> fixed_base<T,FIXED_BITS>
376 fixed_base<T,FIXED_BITS>::operator+(const U &rhs) const
378 return operator+(fixed_base<T,FIXED_BITS>(rhs));
382 template <class T,unsigned int FIXED_BITS> template<typename U> fixed_base<T,FIXED_BITS>
383 fixed_base<T,FIXED_BITS>::operator-(const U &rhs) const
385 return operator-(fixed_base<T,FIXED_BITS>(rhs));
389 template <class T,unsigned int FIXED_BITS> template<typename U> fixed_base<T,FIXED_BITS>
390 fixed_base<T,FIXED_BITS>::operator*(const U &rhs) const
392 return operator*(fixed_base<T,FIXED_BITS>(rhs));
396 template <class T,unsigned int FIXED_BITS> template<typename U> fixed_base<T,FIXED_BITS>
397 fixed_base<T,FIXED_BITS>::operator/(const U &rhs) const
399 return operator/(fixed_base<T,FIXED_BITS>(rhs));
403 template <class T,unsigned int FIXED_BITS>fixed_base<T,FIXED_BITS>
404 fixed_base<T,FIXED_BITS>::operator*(const int &rhs)const
409 //return reinterpret_cast<_fixed>(_data*rhs);
413 template <class T,unsigned int FIXED_BITS>fixed_base<T,FIXED_BITS>
414 fixed_base<T,FIXED_BITS>::operator*(const float &rhs)const
416 return (*this)*_fixed(rhs);
420 template <class T,unsigned int FIXED_BITS>fixed_base<T,FIXED_BITS>
421 fixed_base<T,FIXED_BITS>::operator*(const double &rhs)const
423 return (*this)*_fixed(rhs);
428 template <class T,unsigned int FIXED_BITS>fixed_base<T,FIXED_BITS>
429 fixed_base<T,FIXED_BITS>::operator/(const int &rhs)const
434 //return reinterpret_cast<_fixed>(_data/rhs);
438 template <class T,unsigned int FIXED_BITS>fixed_base<T,FIXED_BITS>
439 operator*(const float& lhs, const fixed_base<T,FIXED_BITS> &rhs)
445 template <class T,unsigned int FIXED_BITS>fixed_base<T,FIXED_BITS>
446 operator*(const double& lhs, const fixed_base<T,FIXED_BITS> &rhs)
457 template <class T,unsigned int FIXED_BITS>fixed_base<T,FIXED_BITS>
458 fixed_base<T,FIXED_BITS>::operator-()const
460 _fixed ret; ret._data=-_data; return ret;
464 template <class T,unsigned int FIXED_BITS>
465 fixed_base<T,FIXED_BITS>::operator float()const
467 return static_cast<float>(_data)/static_cast<float>(_ONE());
470 template <class T,unsigned int FIXED_BITS>
471 fixed_base<T,FIXED_BITS>::operator double()const
473 return static_cast<double>(_data)/static_cast<double>(_ONE());
476 template <class T,unsigned int FIXED_BITS>
477 fixed_base<T,FIXED_BITS>::operator long double()const
479 return static_cast<long double>(_data)/static_cast<long double>(_ONE());
482 template <class T,unsigned int FIXED_BITS>
483 fixed_base<T,FIXED_BITS>::operator int()const
485 return static_cast<int>(_data>>FIXED_BITS);
488 template <class T,unsigned int FIXED_BITS>
489 fixed_base<T,FIXED_BITS>::operator bool()const
491 return static_cast<bool>(_data);
495 template <class T,unsigned int FIXED_BITS> fixed_base<T,FIXED_BITS>
496 fixed_base<T,FIXED_BITS>::floor()const
499 ret._data&=~_F_MASK();
503 template <class T,unsigned int FIXED_BITS> fixed_base<T,FIXED_BITS>
504 fixed_base<T,FIXED_BITS>::ceil()const
507 if(ret._data&_F_MASK())
508 ret._data=(ret._data&~_F_MASK()) + _ONE();
510 ret._data&=~_F_MASK();
514 template <class T,unsigned int FIXED_BITS> fixed_base<T,FIXED_BITS>
515 fixed_base<T,FIXED_BITS>::round()const
518 ret._data+=_ONE()>>1;
519 ret._data&=~_F_MASK();
548 typedef fixed_base<ETL_FIXED_TYPE,ETL_FIXED_BITS> fixed;
554 template <class T,unsigned int FIXED_BITS>
555 inline _ETL::fixed_base<T,FIXED_BITS>
556 ceil(const _ETL::fixed_base<T,FIXED_BITS> &rhs)
557 { return rhs.ceil(); }
559 template <class T,unsigned int FIXED_BITS>
560 _ETL::fixed_base<T,FIXED_BITS>
561 floor(const _ETL::fixed_base<T,FIXED_BITS> &rhs)
562 { return rhs.floor(); }
564 template <class T,unsigned int FIXED_BITS>
565 _ETL::fixed_base<T,FIXED_BITS>
566 round(const _ETL::fixed_base<T,FIXED_BITS> &rhs)
567 { return rhs.round(); }
569 template <class T,unsigned int FIXED_BITS>
570 _ETL::fixed_base<T,FIXED_BITS>
571 abs(const _ETL::fixed_base<T,FIXED_BITS> &rhs)
572 { return rhs<_ETL::fixed_base<T,FIXED_BITS>(0)?-rhs:rhs; }
577 template <class T,unsigned int FIXED_BITS, typename U> bool
578 operator==(const _ETL::fixed_base<T,FIXED_BITS>& lhs, const _ETL::fixed_base<T,FIXED_BITS>& rhs)
579 { return lhs.data()==rhs.data(); }
581 template <class T,unsigned int FIXED_BITS, typename U> bool
582 operator!=(const _ETL::fixed_base<T,FIXED_BITS>& lhs, const _ETL::fixed_base<T,FIXED_BITS>& rhs)
583 { return lhs.data()!=rhs.data(); }
585 template <class T,unsigned int FIXED_BITS, typename U> bool
586 operator>(const _ETL::fixed_base<T,FIXED_BITS>& lhs, const _ETL::fixed_base<T,FIXED_BITS>& rhs)
587 { return lhs.data()>rhs.data(); }
589 template <class T,unsigned int FIXED_BITS, typename U> bool
590 operator<(const _ETL::fixed_base<T,FIXED_BITS>& lhs, const _ETL::fixed_base<T,FIXED_BITS>& rhs)
591 { return lhs.data()<rhs.data(); }
593 template <class T,unsigned int FIXED_BITS, typename U> bool
594 operator>=(const _ETL::fixed_base<T,FIXED_BITS>& lhs, const _ETL::fixed_base<T,FIXED_BITS>& rhs)
595 { return lhs.data()>=rhs.data(); }
597 template <class T,unsigned int FIXED_BITS, typename U> bool
598 operator<=(const _ETL::fixed_base<T,FIXED_BITS>& lhs, const _ETL::fixed_base<T,FIXED_BITS>& rhs)
599 { return lhs.data()<=rhs.data(); }
603 #if defined(__GNUC__) && __GNUC__ == 3
604 template <class T,unsigned int FIXED_BITS, typename U> U
605 operator*(const U &a,const _ETL::fixed_base<T,FIXED_BITS> &b)
606 { return a*static_cast<double>(b); }
608 template <class T,unsigned int FIXED_BITS, typename U> U
609 operator/(const U &a,const _ETL::fixed_base<T,FIXED_BITS> &b)
610 { return a/static_cast<double>(b); }
612 template <class T,unsigned int FIXED_BITS, typename U> U
613 operator+(const U &a,const _ETL::fixed_base<T,FIXED_BITS> &b)
614 { return a+static_cast<double>(b); }
616 template <class T,unsigned int FIXED_BITS, typename U> U
617 operator-(const U &a,const _ETL::fixed_base<T,FIXED_BITS> &b)
618 { return a-static_cast<double>(b); }
623 operator*=(float &a,const _ETL::fixed &b)
624 { a*=(float)b; return a; }
627 operator/=(float &a,const _ETL::fixed &b)
628 { a/=(float)b; return a; }
631 operator-=(float &a,const _ETL::fixed &b)
632 { a-=(float)b; return a; }
635 operator+=(float &a,const _ETL::fixed &b)
636 { a+=(float)b; return a; }
640 /* === E N D =============================================================== */