pl-nk v0.4.5
Plonk|Plink|Plank are a set of cross-platform C/C++ frameworks for audio software development
plonk_Fix.h
00001 /*
00002  -------------------------------------------------------------------------------
00003  This file is part of the Plink, Plonk, Plank libraries
00004   by Martin Robinson
00005  
00006  http://code.google.com/p/pl-nk/
00007  
00008  Copyright University of the West of England, Bristol 2011-14
00009  All rights reserved.
00010  
00011  Redistribution and use in source and binary forms, with or without
00012  modification, are permitted provided that the following conditions are met:
00013  
00014  * Redistributions of source code must retain the above copyright
00015    notice, this list of conditions and the following disclaimer.
00016  * Redistributions in binary form must reproduce the above copyright
00017    notice, this list of conditions and the following disclaimer in the
00018    documentation and/or other materials provided with the distribution.
00019  * Neither the name of University of the West of England, Bristol nor 
00020    the names of its contributors may be used to endorse or promote products
00021    derived from this software without specific prior written permission.
00022  
00023  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00024  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00025  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00026  DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF THE WEST OF ENGLAND, BRISTOL BE 
00027  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
00028  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 
00029  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
00030  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
00031  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 
00032  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00033  
00034  This software makes use of third party libraries. For more information see:
00035  doc/license.txt included in the distribution.
00036  -------------------------------------------------------------------------------
00037  */
00038 
00039 /* Algorithms from libfixmath and Fixed Point Math Library
00040  - see doc/license.txt included in the distribution */
00041 
00042 #ifndef PLONK_FIX_H
00043 #define PLONK_FIX_H
00044 
00045 #include "../core/plonk_CoreForwardDeclarations.h"
00046 #include "plonk_ContainerForwardDeclarations.h"
00047 
00048 template<class Base>
00049 class FixBase
00050 {
00051 private:
00052     FixBase(); // to prevent using unsupported Base internal types (must be char, short or int).
00053 };
00054 
00055 // supported Base type specialisations
00056 template<> class FixBase<char>        { public: FixBase(){} };
00057 template<> class FixBase<short>       { public: FixBase(){} };
00058 template<> class FixBase<int>         { public: FixBase(){} };
00059 
00060 template<class DstBase, class SrcBase>
00061 class FixBaseConvert
00062 {
00063     // prevent unsupported conversions
00064 };
00065 
00066 // supported conversions
00067 template<> class FixBaseConvert<char,char>      { public: typedef char  ConvertBase; };
00068 template<> class FixBaseConvert<char,short>     { public: typedef short ConvertBase; };
00069 template<> class FixBaseConvert<char,int>       { public: typedef int   ConvertBase; };
00070 template<> class FixBaseConvert<short,short>    { public: typedef short ConvertBase; };
00071 template<> class FixBaseConvert<short,char>     { public: typedef short ConvertBase; };
00072 template<> class FixBaseConvert<short,int>      { public: typedef int   ConvertBase; };
00073 template<> class FixBaseConvert<int,int>        { public: typedef int   ConvertBase; };
00074 template<> class FixBaseConvert<int,char>       { public: typedef int   ConvertBase; };
00075 template<> class FixBaseConvert<int,short>      { public: typedef int   ConvertBase; };
00076 
00079 template<class Base, unsigned IBits, unsigned FBits>                
00080 class Fix : public FixBase<Base>
00081 {
00082 public:
00083     typedef Fix<Base,IBits,FBits> FixType;
00084     typedef Math<FixType> MathType;
00085     typedef Base BaseType;
00086     typedef typename TypeUtility<Base>::UnsignedType UnsignedBase;
00087     typedef typename TypeUtility<Base>::WideType WideBase;
00088     typedef typename TypeUtility<Base>::UnsignedWideType UnsignedWideBase;
00089             
00090     static const unsigned IBitsCount;
00091     static const unsigned FBitsCount;
00092     
00093     class Internal
00094     {
00095     public:
00096         inline Internal (Base const& value) throw() 
00097         :   internal (value)
00098         {
00099         }
00100         
00101         Base internal;
00102         
00103     private:
00104         Internal();
00105     };
00106             
00107     Fix() throw()
00108     {
00109     }
00110     
00111     inline Fix (const char value) throw()
00112     :   internal (value * getOne().internal)
00113     {
00114     }
00115     
00116     inline Fix (const short value) throw()
00117     :   internal (value * getOne().internal)
00118     {
00119     }
00120     
00121     inline Fix (const int value) throw()
00122     :   internal (value * getOne().internal)
00123     {
00124     }
00125     
00126     inline Fix (LongLong const& value) throw()
00127     :   internal (value * getOne().internal)
00128     {
00129     }
00130     
00131     inline Fix (const float value) throw()
00132     :   internal (value * getOneFloat())
00133     {
00134     }
00135     
00136     inline Fix (double const& value) throw()
00137     :   internal (value * getOneDouble())
00138     {
00139     }
00140     
00141     inline explicit Fix (Internal const& value) throw()
00142     :   internal (value.internal)
00143     {
00144     }
00145     
00146     inline Fix (Fix const& copy) throw()
00147     :   internal (copy.internal)
00148     {
00149     }
00150     
00151     template<class BaseOther, unsigned IBitsOther, unsigned FBitsOther>
00152     inline Fix (Fix<BaseOther,IBitsOther,FBitsOther> const& other) throw()
00153     :   internal (Base (convert (other) << (FBits - FBitsOther)))
00154     {
00155     }
00156           
00157 #if PLONK_DEBUG
00158     inline ~Fix()
00159     {
00160         plonk_staticassert (IBits != 0);
00161         plonk_staticassert (FBits != 0);
00162         plonk_staticassert ((sizeof (Base) * 8) == (IBits + FBits));
00163     }
00164 #endif
00165     
00166     inline operator bool () const throw()
00167     {
00168         return internal;
00169     }
00170     
00171     inline operator int () const throw()
00172     {
00173         return internal >> FBits;
00174     }
00175     
00176     inline int toInt() const throw()
00177     {
00178         return internal >> FBits;
00179     }
00180 
00181     inline operator LongLong () const throw()
00182     {
00183         return internal >> FBits;
00184     }
00185     
00186     inline int toLongLong() const throw()
00187     {
00188         return internal >> FBits;
00189     }
00190     
00191     inline operator float () const throw()
00192     {
00193         return float (internal) / getOneFloat();
00194     }
00195     
00196     inline float toFloat() const throw()
00197     {
00198         return float (internal) / getOneFloat();
00199     }
00200 
00201     inline operator double () const throw()
00202     {
00203         return double (internal) / getOneDouble();
00204     }
00205     
00206     inline double toDouble() const throw()
00207     {
00208         return double (internal) / getOneDouble();
00209     }
00210         
00211     template<class BaseOther, unsigned IBitsOther, unsigned FBitsOther>
00212     inline operator Fix<BaseOther,IBitsOther,FBitsOther> () const throw()
00213     {
00214         return Fix<BaseOther,IBitsOther,FBitsOther> (*this);
00215     }
00216 
00217     inline Fix operator-() const throw()    { return neg(); }
00218     
00219     inline Fix operator+ (Fix const& rightOperand) const throw()    { return addop (rightOperand); }
00220     inline Fix operator- (Fix const& rightOperand) const throw()    { return subop (rightOperand); }
00221     inline Fix operator* (Fix const& rightOperand) const throw()    { return mulop (rightOperand); }
00222     inline Fix operator/ (Fix const& rightOperand) const throw()    { return divop (rightOperand); }
00223     inline Fix operator% (Fix const& rightOperand) const throw()    { return modop (rightOperand); }
00224     inline Fix operator+ (float const& rightOperand) const throw()  { return addop (Fix (rightOperand)); }
00225     inline Fix operator- (float const& rightOperand) const throw()  { return subop (Fix (rightOperand)); }
00226     inline Fix operator* (float const& rightOperand) const throw()  { return mulop (Fix (rightOperand)); }
00227     inline Fix operator/ (float const& rightOperand) const throw()  { return divop (Fix (rightOperand)); }
00228     inline Fix operator% (float const& rightOperand) const throw()  { return modop (Fix (rightOperand)); }
00229     inline Fix operator+ (double const& rightOperand) const throw() { return addop (Fix (rightOperand)); }
00230     inline Fix operator- (double const& rightOperand) const throw() { return subop (Fix (rightOperand)); }
00231     inline Fix operator* (double const& rightOperand) const throw() { return mulop (Fix (rightOperand)); }
00232     inline Fix operator/ (double const& rightOperand) const throw() { return divop (Fix (rightOperand)); }
00233     inline Fix operator% (double const& rightOperand) const throw() { return modop ((rightOperand)); }
00234     inline Fix operator+ (int const& rightOperand) const throw()    { return addop (Fix (rightOperand)); }
00235     inline Fix operator- (int const& rightOperand) const throw()    { return subop (Fix (rightOperand)); }
00236     inline Fix operator* (int const& rightOperand) const throw()    { return mulop (Fix (rightOperand)); }
00237     inline Fix operator/ (int const& rightOperand) const throw()    { return divop (Fix (rightOperand)); }
00238     inline Fix operator% (int const& rightOperand) const throw()    { return modop (Fix (rightOperand)); }
00239 
00240     friend inline Fix operator+ (float const& leftOperand, Fix const& rightOperand) throw()  { return Fix (leftOperand) + rightOperand; }
00241     friend inline Fix operator- (float const& leftOperand, Fix const& rightOperand) throw()  { return Fix (leftOperand) + rightOperand; }
00242     friend inline Fix operator* (float const& leftOperand, Fix const& rightOperand) throw()  { return Fix (leftOperand) + rightOperand; }
00243     friend inline Fix operator/ (float const& leftOperand, Fix const& rightOperand) throw()  { return Fix (leftOperand) + rightOperand; }
00244     friend inline Fix operator% (float const& leftOperand, Fix const& rightOperand) throw()  { return Fix (leftOperand) + rightOperand; }
00245     friend inline Fix operator+ (double const& leftOperand, Fix const& rightOperand) throw() { return Fix (leftOperand) + rightOperand; }
00246     friend inline Fix operator- (double const& leftOperand, Fix const& rightOperand) throw() { return Fix (leftOperand) + rightOperand; }
00247     friend inline Fix operator* (double const& leftOperand, Fix const& rightOperand) throw() { return Fix (leftOperand) + rightOperand; }
00248     friend inline Fix operator/ (double const& leftOperand, Fix const& rightOperand) throw() { return Fix (leftOperand) + rightOperand; }
00249     friend inline Fix operator% (double const& leftOperand, Fix const& rightOperand) throw() { return Fix (leftOperand) + rightOperand; }
00250     friend inline Fix operator+ (int const& leftOperand, Fix const& rightOperand) throw()    { return Fix (leftOperand) + rightOperand; }
00251     friend inline Fix operator- (int const& leftOperand, Fix const& rightOperand) throw()    { return Fix (leftOperand) + rightOperand; }
00252     friend inline Fix operator* (int const& leftOperand, Fix const& rightOperand) throw()    { return Fix (leftOperand) + rightOperand; }
00253     friend inline Fix operator/ (int const& leftOperand, Fix const& rightOperand) throw()    { return Fix (leftOperand) + rightOperand; }
00254     friend inline Fix operator% (int const& leftOperand, Fix const& rightOperand) throw()    { return Fix (leftOperand) + rightOperand; }
00255 
00256     inline Fix operator<< (const int shift) const throw()           { return Fix (Internal (internal << shift)); }
00257     inline Fix operator>> (const int shift) const throw()           { return Fix (Internal (internal >> shift)); }
00258     
00259     inline Fix& operator= (Fix const& other) throw()            { if (this != &other) internal = other.internal; return *this; }
00260     inline Fix& operator= (float const& other) throw()          { internal = Fix (other).internal; return *this; }
00261     inline Fix& operator= (double const& other) throw()         { internal = Fix (other).internal; return *this; }
00262     inline Fix& operator= (int const& other) throw()            { internal = Fix (other).internal; return *this; }
00263     inline Fix& operator= (Internal const& other) throw()       { internal = other.internal; return *this; }
00264     
00265     template<class BaseOther, unsigned IBitsOther, unsigned FBitsOther>
00266     inline Fix& operator= (Fix<BaseOther,IBitsOther,FBitsOther> const& other) throw()
00267     { 
00268         const Fix copy (other);
00269         return operator= (copy); 
00270     }
00271     
00272     // could optimise these better
00273     inline Fix& operator+= (Fix const& rightOperand) throw()        { return operator=  ( (*this) + rightOperand); }
00274     inline Fix& operator-= (Fix const& rightOperand) throw()        { return operator=  ( (*this) - rightOperand); }
00275     inline Fix& operator*= (Fix const& rightOperand) throw()        { return operator=  ( (*this) * rightOperand); }
00276     inline Fix& operator/= (Fix const& rightOperand) throw()        { return operator=  ( (*this) / rightOperand); }
00277     inline Fix& operator%= (Fix const& rightOperand) throw()        { return operator=  ( (*this) % rightOperand); }
00278     inline Fix& operator+= (float const& rightOperand) throw()      { return operator=  ( (*this) + Fix (rightOperand)); }
00279     inline Fix& operator-= (float const& rightOperand) throw()      { return operator=  ( (*this) - Fix (rightOperand)); }
00280     inline Fix& operator*= (float const& rightOperand) throw()      { return operator=  ( (*this) * Fix (rightOperand)); }
00281     inline Fix& operator/= (float const& rightOperand) throw()      { return operator=  ( (*this) / Fix (rightOperand)); }
00282     inline Fix& operator%= (float const& rightOperand) throw()      { return operator=  ( (*this) % Fix (rightOperand)); }
00283     inline Fix& operator+= (double const& rightOperand) throw()     { return operator=  ( (*this) + Fix (rightOperand)); }
00284     inline Fix& operator-= (double const& rightOperand) throw()     { return operator=  ( (*this) - Fix (rightOperand)); }
00285     inline Fix& operator*= (double const& rightOperand) throw()     { return operator=  ( (*this) * Fix (rightOperand)); }
00286     inline Fix& operator/= (double const& rightOperand) throw()     { return operator=  ( (*this) / Fix (rightOperand)); }
00287     inline Fix& operator%= (double const& rightOperand) throw()     { return operator=  ( (*this) % Fix (rightOperand)); }
00288     inline Fix& operator+= (int const& rightOperand) throw()        { return operator=  ( (*this) + Fix (rightOperand)); }
00289     inline Fix& operator-= (int const& rightOperand) throw()        { return operator=  ( (*this) - Fix (rightOperand)); }
00290     inline Fix& operator*= (int const& rightOperand) throw()        { return operator=  ( (*this) * Fix (rightOperand)); }
00291     inline Fix& operator/= (int const& rightOperand) throw()        { return operator=  ( (*this) / Fix (rightOperand)); }
00292     inline Fix& operator%= (int const& rightOperand) throw()        { return operator=  ( (*this) % Fix (rightOperand)); }
00293     inline Fix& operator+= (Internal const& rightOperand) throw()   { return operator=  ( (*this) + Fix (rightOperand)); }
00294     inline Fix& operator-= (Internal const& rightOperand) throw()   { return operator=  ( (*this) - Fix (rightOperand)); }
00295     inline Fix& operator*= (Internal const& rightOperand) throw()   { return operator=  ( (*this) * Fix (rightOperand)); }
00296     inline Fix& operator/= (Internal const& rightOperand) throw()   { return operator=  ( (*this) / Fix (rightOperand)); }
00297     inline Fix& operator%= (Internal const& rightOperand) throw()   { return operator=  ( (*this) % Fix (rightOperand)); }
00298 
00299     inline Fix& operator<<= (const int shift) throw()                { internal << shift; return *this; }
00300     inline Fix& operator>>= (const int shift) throw()                { internal >> shift; return *this; }
00301 
00302     inline bool operator== (Fix const& rightOperand) const throw()      { return internal == rightOperand.internal; }
00303     inline bool operator== (float const& rightOperand) const throw()    { return internal == Fix (rightOperand).internal; }
00304     inline bool operator== (double const& rightOperand) const throw()   { return internal == Fix (rightOperand).internal; }
00305     inline bool operator== (int const& rightOperand) const throw()      { return internal == Fix (rightOperand).internal; }
00306     inline bool operator== (Internal const& rightOperand) const throw() { return internal == rightOperand; }
00307 
00308     inline bool operator!= (Fix const& rightOperand) const throw()      { return internal != rightOperand.internal; }
00309     inline bool operator!= (float const& rightOperand) const throw()    { return internal != Fix (rightOperand).internal; }
00310     inline bool operator!= (double const& rightOperand) const throw()   { return internal != Fix (rightOperand).internal; }
00311     inline bool operator!= (int const& rightOperand) const throw()      { return internal != Fix (rightOperand).internal; }
00312     inline bool operator!= (Internal const& rightOperand) const throw() { return internal != rightOperand; }
00313 
00314     inline bool operator<  (Fix const& rightOperand) const throw()      { return internal <  rightOperand.internal; }
00315     inline bool operator<  (float const& rightOperand) const throw()    { return internal <  Fix (rightOperand).internal; }
00316     inline bool operator<  (double const& rightOperand) const throw()   { return internal <  Fix (rightOperand).internal; }
00317     inline bool operator<  (int const& rightOperand) const throw()      { return internal <  Fix (rightOperand).internal; }
00318     inline bool operator<  (Internal const& rightOperand) const throw() { return internal <  rightOperand; }
00319 
00320     inline bool operator<= (Fix const& rightOperand) const throw()      { return internal <= rightOperand.internal; }
00321     inline bool operator<= (float const& rightOperand) const throw()    { return internal <= Fix (rightOperand).internal; }
00322     inline bool operator<= (double const& rightOperand) const throw()   { return internal <= Fix (rightOperand).internal; }
00323     inline bool operator<= (int const& rightOperand) const throw()      { return internal <= Fix (rightOperand).internal; }
00324     inline bool operator<= (Internal const& rightOperand) const throw() { return internal <= rightOperand; }
00325 
00326     inline bool operator>  (Fix const& rightOperand) const throw()      { return internal >  rightOperand.internal; }
00327     inline bool operator>  (float const& rightOperand) const throw()    { return internal >  Fix (rightOperand).internal; }
00328     inline bool operator>  (double const& rightOperand) const throw()   { return internal >  Fix (rightOperand).internal; }
00329     inline bool operator>  (int const& rightOperand) const throw()      { return internal >  Fix (rightOperand).internal; }
00330     inline bool operator>  (Internal const& rightOperand) const throw() { return internal >  rightOperand; }
00331 
00332     inline bool operator>= (Fix const& rightOperand) const throw()      { return internal >= rightOperand.internal; }
00333     inline bool operator>= (float const& rightOperand) const throw()    { return internal >= Fix (rightOperand).internal; }
00334     inline bool operator>= (double const& rightOperand) const throw()   { return internal >= Fix (rightOperand).internal; }
00335     inline bool operator>= (int const& rightOperand) const throw()      { return internal >= Fix (rightOperand).internal; }
00336     inline bool operator>= (Internal const& rightOperand) const throw() { return internal >= rightOperand; }
00337 
00338     // -- unary ops --------------------------------------------------------- //
00339     
00340     friend inline Fix move (Fix const& a) throw()             
00341     { 
00342         return a; 
00343     }
00344     
00345     inline Fix move() const throw()             
00346     { 
00347         return *this; 
00348     }
00349 
00350     friend inline Fix neg (Fix const& a) throw()              
00351     { 
00352         return a.neg();
00353     }
00354     
00355     inline Fix neg() const throw()              
00356     { 
00357         return Fix (Internal (-internal)); 
00358     }
00359     
00360     friend inline Fix abs (Fix const& a) throw()            
00361     { 
00362         return a.abs();
00363     }
00364     
00365     inline Fix abs() const throw()            
00366     { 
00367         return Fix (internal < 0 ? Internal (-internal) : Internal (internal)); 
00368     }
00369     
00370     friend inline Fix reciprocal (Fix const& a) throw()            
00371     {         
00372         return a.reciprocal();
00373     }
00374 
00375     inline Fix reciprocal() const throw()            
00376     {         
00377         return Fix::getOne() / *this; 
00378     }
00379     
00380     friend inline Fix log2 (Fix const& a) throw()            
00381     { 
00382         return a.log2();
00383     }
00384     
00385 //    inline Fix log2 () const throw()            
00386 //    { 
00387 //        return log() * Math<Fix>::get1_Log2();
00388 //    }
00389 
00390     inline Fix log2() const throw()            
00391     {
00392         // Note that a negative x gives a non-real result.
00393         // If x == 0, the limit of log2(x)  as x -> 0 = -infinity.
00394         // log2(-ve) gives a complex result.
00395         if (internal <= 0) 
00396             return Fix::getOverflow();
00397         
00398         // If the input is less than one, the result is -log2(1.0 / in)
00399         if (isLessThan (Fix::getOne()))
00400         {
00401             // Note that the inverse of this would overflow.
00402             // This is the exact answer for log2(1.0 / (1<<FBits))
00403             if (internal == 1) 
00404                 return Fix (Internal (-FBits));
00405                 
00406             return -log2Internal (reciprocal());
00407         }
00408         
00409         // If input >= 1, just proceed as normal.
00410         // Note that x == fix16_one is a special case, where the answer is 0.
00411         return log2Internal (*this);
00412     }
00413     
00414     friend inline Fix sin (Fix const& a) throw()            
00415     { 
00416         return a.sin();
00417     }
00418     
00419     inline Fix sin() const throw()            
00420     { 
00421         const Fix pi (Math<Fix>::getPi());        
00422         const Fix twoPi (Math<Fix>::get2Pi());
00423         
00424         Fix x = modop (twoPi);
00425         
00426                 if (x > pi)
00427                         x -= twoPi;
00428                 
00429                 const Fix xx = x.squared();          
00430         const Fix f_7 = Series<Fix,7>::get1_Factorial();
00431         const Fix f_5 = Series<Fix,5>::get1_Factorial();
00432         const Fix f_3 = Series<Fix,3>::get1_Factorial();
00433         const Fix one = Fix::getOne();
00434         
00435         return (((-xx * f_7 + f_5) * xx - f_3) * xx + one) * x;
00436     }
00437 
00438     friend inline Fix cos (Fix const& a) throw()            
00439     { 
00440         return a.cos(); 
00441     }
00442     
00443     inline Fix cos() const throw()            
00444     { 
00445         const Fix pi (Math<Fix>::getPi());        
00446         const Fix twoPi (Math<Fix>::get2Pi());
00447         
00448         Fix x = modop (twoPi);
00449         
00450                 if (x > pi)
00451                         x -= twoPi;
00452         
00453                 const Fix xx = x.squared();          
00454         const Fix f_6 = Series<Fix,6>::get1_Factorial();
00455         const Fix f_4 = Series<Fix,4>::get1_Factorial();
00456         const Fix f_2 = Series<Fix,2>::get1_Factorial();
00457         const Fix one = Fix::getOne();
00458         
00459         return ((-xx * f_6 + f_4) * xx - f_2) * xx + one;
00460     }
00461     
00462     friend inline Fix tan (Fix const& a) throw()            
00463     { 
00464         return a.tan();
00465     }
00466     
00467     inline Fix tan() const throw()            
00468     { 
00469         return  sin().divsat (cos());
00470     }
00471 
00472     friend inline Fix asin (Fix const& a) throw()            
00473     { 
00474         return a.asin();
00475     }
00476     
00477     inline Fix asin() const throw()            
00478     { 
00479         const Fix one = Fix::getOne();
00480         
00481         if (isGreaterThan (one) || (isLessThan(Math<Fix>::get_1())))
00482             return Math<Fix>::get0();
00483         
00484         return divop ((one - squared()).sqrt()).atan();
00485     }
00486     
00487     friend inline Fix acos (Fix const& a) throw()            
00488     { 
00489         return a.acos(); 
00490     }
00491 
00492     inline Fix acos() const throw()            
00493     { 
00494         return Math<Fix>::getPi_2() - sin();
00495     }
00496 
00497     friend inline Fix atan (Fix const& a) throw()            
00498     { 
00499         return a.atan(); 
00500     }
00501     
00502     inline Fix atan() const throw()            
00503     { 
00504         return atan2 (Fix::getOne());
00505     }
00506     
00507     friend inline Fix sinh (Fix const& a) throw()            
00508     { 
00509         return a.sinh();
00510     }
00511     
00512     inline Fix sinh() const throw()            
00513     { 
00514         const Fix e = exp();
00515         return (e - e.reciprocal()) >> 1;
00516     }
00517     
00518     friend inline Fix cosh (Fix const& a) throw()            
00519     { 
00520         return a.cosh();
00521     }
00522     
00523     inline Fix cosh() const throw()            
00524     { 
00525         const Fix e = exp();
00526         return (e + e.reciprocal()) >> 1;
00527     }
00528     
00529     friend inline Fix tanh (Fix const& a) throw()            
00530     { 
00531         return a.tanh();
00532     }
00533     
00534     inline Fix tanh() const throw()            
00535     { 
00536         const Fix e = exp();
00537         const Fix ne = e.reciprocal();
00538         return (e - ne) / (e + ne);
00539     }
00540 
00541     friend inline Fix sqrt (Fix const& a) throw()            
00542     { 
00543         return a.sqrt();
00544     }
00545     
00546     inline Fix sqrt() const throw()            
00547     {                 
00548         if (internal < 0)
00549                         return Math<Fix>::get0();;
00550         
00551         UnsignedWideBase op = UnsignedWideBase (internal) << (FBits - 1);
00552         UnsignedWideBase res = 0;               
00553         UnsignedWideBase one = UnsignedWideBase (1) << ((FBits + IBits) * 2 - 1);
00554          
00555                 while (one > op)
00556                         one >>= 2;
00557         
00558                 while (one != 0)
00559                 {
00560                         if (op >= (res + one))
00561                         {
00562                                 op = op - (res + one);
00563                                 res = res + (one << 1);
00564                         }
00565             
00566                         res >>= 1;
00567                         one >>= 2;
00568                 }
00569         
00570                 return Fix (Internal (Base (res)));
00571     }
00572     
00573     friend inline Fix log (Fix const& a) throw()            
00574     { 
00575         return a.log();
00576     }
00577     
00578     inline Fix log() const throw()            
00579     { 
00580         if (internal <= 0)
00581             return Fix::getMinimum();
00582         
00583         // Bring the value to the most accurate range (1 < x < 100)
00584         const Fix e4 = Math<Fix>::getE4();
00585         
00586         Fix value = *this;
00587         int scaling = 0;
00588 
00589         while (internal > Math<Fix>::get100().internal)
00590         {
00591             value /= e4;
00592             scaling += 4;
00593         }
00594         
00595         while (value < Fix::getOne())
00596         {
00597             value *= e4;
00598             scaling -= 4;
00599         }
00600         
00601         const Fix three = Math<Fix>::get3();
00602         Fix guess = Math<Fix>::get2();
00603         Fix delta;
00604         int count = 0;
00605 
00606         do
00607         {
00608             // Solving e(x) = y using Newton's method
00609             // f(x) = e(x) - y
00610             // f'(x) = e(x)
00611             Fix e = guess.exp();
00612             delta = (value - e) / e;
00613             
00614             // It's unlikely that logarithm is very large, so avoid overshooting.
00615             if (delta > three)
00616                 delta = three;
00617             
00618             guess += delta;
00619         } while ((count++ < 10) && ((delta.internal > 1) || (delta.internal < -1)));
00620         
00621         return guess + Fix (scaling);
00622     }
00623     
00624     friend inline Fix log10 (Fix const& a) throw()            
00625     { 
00626         return a.log10();
00627     }
00628     
00629     inline Fix log10() const throw()            
00630     { 
00631         return log() * Math<Fix>::get1_Log10();
00632     }
00633     
00634     friend inline Fix exp (Fix const& a) throw()            
00635     {  
00636         return a.exp();
00637     }
00638     
00639     inline Fix exp() const throw()            
00640     {         
00641         const Base raw1 (Fix::getOne().getRaw());
00642         Base araw (internal);
00643         
00644         if (araw == 0) 
00645             return Fix::getOne();
00646         
00647         if (araw == raw1) 
00648             return Math<Fix>::getE();
00649         
00650         //      if(a >= 681391   ) return fix16_maximum;
00651         //      if(a <= -772243  ) return 0;
00652         
00653         bool neg (araw < 0);
00654         
00655         if (neg) 
00656             araw = -araw;
00657         
00658         Base result (araw + raw1);
00659         Fix term = Fix (Internal (araw));
00660         
00661         int i;        
00662         for (i = 2; i < (IBits + FBits - 2); ++i)
00663         {
00664             term *= Fix (Internal (araw)) / Fix (i);
00665             
00666             const Base rawterm (term.getRaw());
00667             result += rawterm;
00668             
00669             if ((rawterm < 500) && ((i > (FBits - 1)) || (rawterm < (FBits + 4))))
00670                 break;
00671         }
00672         
00673         return neg ? plonk::reciprocal (Fix (Internal (result))) : Fix (Internal (result));
00674     }
00675     
00676     friend inline Fix squared (Fix const& a) throw()            
00677     { 
00678         return a * a; 
00679     }
00680     
00681     inline Fix squared() const throw()            
00682     { 
00683         return (*this) * (*this); 
00684     }
00685     
00686     friend inline Fix cubed (Fix const& a) throw()            
00687     { 
00688         return a * a * a; 
00689     }
00690     
00691     inline Fix cubed() const throw()            
00692     { 
00693         return (*this) * (*this) * (*this); 
00694     }
00695     
00696     friend inline Fix floor (Fix const& a) throw()            
00697     { 
00698         return a.floor();
00699     }
00700     
00701     inline Fix floor() const throw()            
00702     { 
00703         return Fix (Internal (internal & Fix::getIMask().getRaw())); 
00704     }
00705     
00706     friend inline Fix ceil (Fix const& a) throw()             
00707     {
00708         return a.ceil();
00709     }
00710     
00711     inline Fix ceil() const throw()             
00712     { 
00713         const Base imask (Fix::getIMask().getRaw());
00714         const Base fmask (Fix::getFMask().getRaw());
00715         const Base one (Fix::getOne().getRaw());
00716         return Fix (Internal ((internal & imask) + (internal & fmask ? one : 0))); 
00717     }
00718     
00719     friend inline Fix frac (Fix const& a) throw()            
00720     { 
00721         return a.frac();
00722     }
00723     
00724     inline Fix frac() const throw()            
00725     { 
00726         return Fix (Internal (internal & Fix::getFMask())); 
00727     }
00728     
00729     friend inline Fix sign (Fix const& a) throw()            
00730     { 
00731         const Base araw (a.getRaw());
00732         return araw == 0 ? Math<Fix>::get0() : araw < 0 ? Math<Fix>::get_1() : Math<Fix>::get1(); 
00733     }
00734     
00735     inline Fix sign() const throw()            
00736     { 
00737         return internal == 0 ? Math<Fix>::get0() : internal < 0 ? Math<Fix>::get_1() : Math<Fix>::get1(); 
00738     }
00739     
00740     friend inline Fix m2f (Fix const& a) throw()            
00741     { 
00742         return a.m2f();
00743     }
00744     
00745     inline Fix m2f() const throw()            
00746     { 
00747         return Math<Fix>::get440() * ((subop (69) / Math<Fix>::get12()) * Math<Fix>::getLog2()).exp();
00748     }
00749     
00750     friend inline Fix f2m (Fix const& a) throw()            
00751     { 
00752         return a.f2m();
00753     }
00754     
00755     inline Fix f2m() const throw()            
00756     { 
00757         return mulop (Math<Fix>::get1_440()).log2() * Math<Fix>::get12() + Math<Fix>::get69();
00758     }
00759     
00760     friend inline Fix a2dB (Fix const& a) throw()            
00761     { 
00762         return a.a2dB(); 
00763     }
00764     
00765     inline Fix a2dB() const throw()            
00766     { 
00767         plonk_assertfalse;
00768         return a2dB (float (*this)); 
00769     }
00770     
00771     friend inline Fix dB2a (Fix const& a) throw()            
00772     { 
00773         return a.dB2a();
00774     }
00775     
00776     inline Fix dB2a() const throw()            
00777     { 
00778         plonk_assertfalse;
00779         return dB2a (float (*this)); 
00780     }
00781     
00782     friend inline Fix d2r (Fix const& a) throw()            
00783     { 
00784         return a.d2r(); 
00785     }
00786     
00787     inline Fix d2r() const throw()            
00788     { 
00789         plonk_assertfalse;
00790         return d2r (float (*this)); 
00791     }
00792     
00793     friend inline Fix r2d (Fix const& a) throw()            
00794     { 
00795         return a.r2d();
00796     }
00797     
00798     inline Fix r2d() const throw()            
00799     { 
00800         plonk_assertfalse;
00801         return r2d (float (*this)); 
00802     }
00803     
00804     friend inline Fix distort (Fix const& a) throw()            
00805     { 
00806         return a.distort();
00807     }
00808     
00809     inline Fix distort() const throw()            
00810     { 
00811         return reciprocal (*this) + abs (*this); 
00812     }
00813     
00814     friend inline Fix zap (Fix const& a) throw()            
00815     { 
00816         return a; 
00817     }
00818     
00819     inline Fix zap() const throw()            
00820     { 
00821         return *this; 
00822     }
00823 
00824     // -- binary ops -------------------------------------------------------- //
00825             
00826     friend inline Fix addop (Fix const& a, Fix const& b) throw()              
00827     { 
00828         return a.addop (b); 
00829     }
00830 
00831     inline Fix addop (Fix const& b) const throw()              
00832     { 
00833         return FixType (Internal (internal + b.internal)); 
00834     }
00835     
00836     friend inline Fix subop (Fix const& a, Fix const& b) throw()              
00837     { 
00838         return a.subop (b); 
00839     }
00840 
00841     inline Fix subop (Fix const& b) const throw()              
00842     { 
00843         return FixType (Internal (internal - b.internal)); 
00844     }
00845     
00846     friend inline Fix mulop (Fix const& a, Fix const& b) throw()              
00847     { 
00848         return a.mulop (b); 
00849     }
00850 
00851     inline Fix mulop (Fix const& b) const throw()              
00852     { 
00853         const WideBase product = WideBase (internal) * WideBase (b.internal);
00854         return Fix (Internal (product >> FBits)); 
00855     }
00856     
00857     friend inline Fix divop (Fix const& a, Fix const& b) throw()              
00858     { 
00859         return a.divop (b); 
00860     }
00861 
00862     inline Fix divop (Fix const& b) const throw()              
00863     { 
00864         return FixType (Internal ((WideBase (internal) << FBits) / WideBase (b.internal))); 
00865     }
00866     
00867     friend inline Fix addsat (Fix const& a, Fix const& b) throw()              
00868     { 
00869         return a.addsat (b); 
00870     }
00871     
00872     inline Fix addsat (Fix const& b) const throw()              
00873     { 
00874         const Fix result = addop (b);
00875         
00876         if (internal > 0 && b.internal > 0)
00877             return result.internal < 0 ? Fix::getOverflow() : result;
00878         else if (internal < 0 && b.internal < 0)
00879             return result.internal > 0 ? Fix::getOverflow() : result;
00880             
00881         return result;
00882     }
00883     
00884     friend inline Fix subsat (Fix const& a, Fix const& b) throw()              
00885     { 
00886         return a.subsat (b); 
00887     }
00888     
00889     inline Fix subsat (Fix const& b) const throw()              
00890     { 
00891         const Fix result = subop (b);
00892         
00893         if (internal > 0 && b.internal < 0)
00894             return result.internal < 0 ? Fix::getOverflow() : result;
00895         else if (internal < 0 && b.internal > 0)
00896             return result.internal > 0 ? Fix::getOverflow() : result;
00897         
00898         return result;
00899     }
00900     
00901     friend inline Fix mulsat (Fix const& a, Fix const& b) throw()              
00902     { 
00903         return a.mulsat (b); 
00904     }
00905     
00906     inline Fix mulsat (Fix const& b) const throw()              
00907     { 
00908         const WideBase product = WideBase (internal) * WideBase (b.internal);
00909         const UnsignedBase upper = product >> ((FBits + IBits) * 2 - FBits - 1);
00910         
00911         if (((product < 0) && ~upper) || upper)
00912             return Fix::getOverflow();
00913         
00914         return Fix (Internal (product >> FBits)); 
00915     }
00916     
00917     friend inline Fix divsat (Fix const& a, Fix const& b) throw()              
00918     { 
00919         return a.divsat (b); 
00920     }
00921     
00922     inline Fix divsat (Fix const& b) const throw()              
00923     { 
00924         if (b.internal == 0)
00925             return Fix::getOverflow();
00926 
00927         WideBase calc = (WideBase (internal) << FBits) / WideBase (b.internal);
00928         
00929         if (plonk::abs (internal) > plonk::abs (b.internal))
00930         {        
00931             const bool aIsPos = internal >= 0;
00932             const bool bIsPos = b.internal >= 0;
00933             
00934             if ((aIsPos == bIsPos) && (calc <= 0))
00935                 return Fix::getOverflow();
00936         }
00937         
00938         return FixType (Internal (calc)); 
00939     }
00940     
00941     friend inline Fix modop (Fix const& a, Fix const& b) throw()              
00942     { 
00943         return a.modop (b); 
00944     }
00945 
00946     inline Fix modop (Fix const& b) const throw()              
00947     { 
00948         return FixType (Internal (internal % b.internal)); 
00949     }
00950     
00951     friend inline Fix min (Fix const& a, Fix const& b) throw()              
00952     { 
00953         return a.min (b); 
00954     }
00955 
00956     inline Fix min (Fix const& b) const throw()              
00957     { 
00958         return (*this > b) ? b : *this; 
00959     }
00960     
00961     friend inline Fix max (Fix const& a, Fix const& b) throw()              
00962     { 
00963         return a.max (b); 
00964     }
00965 
00966     inline Fix max (Fix const& b) const throw()              
00967     { 
00968         return (*this < b) ? b : *this; 
00969     }
00970     
00971     friend inline Fix pow (Fix const& a, Fix const& b) throw()              
00972     { 
00973         return a.pow (b); 
00974     }
00975 
00976     inline Fix pow (Fix const& b) const throw()              
00977     { 
00978         return (b * log()).exp();
00979     }
00980     
00981     friend inline Fix hypot (Fix const& a, Fix const& b) throw()              
00982     { 
00983         return a.hypot (b); 
00984     }
00985 
00986     inline Fix hypot (Fix const& b) const throw()              
00987     { 
00988         return sumsqr (b).sqrt();
00989     }
00990     
00991     friend inline Fix atan2 (Fix const& a, Fix const& b) throw()              
00992     { 
00993         return a.atan2 (b); 
00994     }
00995      
00996     inline Fix atan2 (Fix const& b) const throw()              
00997     { 
00998         Fix angle;
00999         
01000         const Base mask = internal >> (IBits + FBits - 1);
01001         const Fix absa (Internal ((internal + mask) ^ mask));
01002         
01003         if (b.internal >= 0)
01004         {
01005             Fix r = (b - absa) / (b + absa);
01006             Fix rrr = r.cubed();
01007             angle = Fix::getAtan2Magic1() * rrr - Fix::getAtan2Magic2() * r + Math<Fix>::getPi_4();
01008         } 
01009         else 
01010         {
01011             Fix r = (b + absa) / (absa - b);
01012             Fix rrr = r.cubed();
01013             angle = Fix::getAtan2Magic1() * rrr - Fix::getAtan2Magic2() * r + Math<Fix>::get3Pi_4();
01014         }
01015         
01016         if (internal < 0)
01017             angle = -angle;
01018         
01019         return angle;
01020     }
01021     
01022     friend inline Fix sumsqr (Fix const& a, Fix const& b) throw()              
01023     { 
01024         return a.sumsqr (b); 
01025     }
01026 
01027     inline Fix sumsqr (Fix const& b) const throw()              
01028     { 
01029         return squared() + b.squared(); 
01030     }
01031     
01032     friend inline Fix difsqr (Fix const& a, Fix const& b) throw()              
01033     { 
01034         return a.difsqr (b); 
01035     }
01036     
01037     inline Fix difsqr (Fix const& b) const throw()              
01038     { 
01039         return squared() - b.squared(); 
01040     }
01041     
01042     friend inline Fix sqrsum (Fix const& a, Fix const& b) throw()              
01043     { 
01044         return a.sqrsum (b); 
01045     }
01046     
01047     inline Fix sqrsum (Fix const& b) const throw()              
01048     { 
01049         return addop (b).squared();
01050     }
01051     
01052     friend inline Fix sqrdif (Fix const& a, Fix const& b) throw()              
01053     { 
01054         return a.sqrdif (b); 
01055     }
01056     
01057     inline Fix sqrdif (Fix const& b) const throw()              
01058     { 
01059         return subop (b).squared();
01060     }
01061     
01062     friend inline Fix absdif (Fix const& a, Fix const& b) throw()              
01063     { 
01064         return a.absdif (b); 
01065     }
01066 
01067     inline Fix absdif (Fix const& b) const throw()              
01068     { 
01069         return subop (b).abs();
01070     }
01071     
01072     friend inline Fix thresh (Fix const& a, Fix const& b) throw()              
01073     { 
01074         return a.thresh (b); 
01075     }
01076 
01077     inline Fix thresh (Fix const& b) const throw()              
01078     { 
01079         return internal < b.internal ? 0 : *this;
01080     }
01081     
01082     friend inline Fix isEqualTo (Fix const& a, Fix const& b) throw()              
01083     { 
01084         return a.isEqualTo (b); 
01085     }
01086 
01087     inline Fix isEqualTo (Fix const& b) const throw()              
01088     { 
01089         return internal == b.internal;
01090     }
01091     
01092     friend inline Fix isNotEqualTo (Fix const& a, Fix const& b) throw()              
01093     { 
01094         return a.isNotEqualTo (b); 
01095     }
01096 
01097     inline Fix isNotEqualTo (Fix const& b) const throw()              
01098     { 
01099         return internal != b.internal;
01100     }
01101 
01102     friend inline Fix isGreaterThan (Fix const& a, Fix const& b) throw()              
01103     { 
01104         return a.isGreaterThan (b); 
01105     }
01106 
01107     inline Fix isGreaterThan (Fix const& b) const throw()              
01108     { 
01109         return internal > b.internal;
01110     }
01111     
01112     friend inline Fix isGreaterThanOrEqualTo (Fix const& a, Fix const& b) throw()              
01113     { 
01114         return a.isGreaterThanOrEqualTo (b); 
01115     }
01116 
01117     inline Fix isGreaterThanOrEqualTo (Fix const& b) const throw()              
01118     { 
01119         return internal >= b.internal;
01120     }
01121     
01122     friend inline Fix isLessThan (Fix const& a, Fix const& b) throw()              
01123     { 
01124         return a.isLessThan (b); 
01125     }
01126 
01127     inline Fix isLessThan (Fix const& b) const throw()              
01128     { 
01129         return internal < b.internal;
01130     }
01131     
01132     friend inline Fix isLessThanOrEqualTo (Fix const& a, Fix const& b) throw()              
01133     { 
01134         return a.isLessThanOrEqualTo (b); 
01135     }
01136 
01137     inline Fix isLessThanOrEqualTo (Fix const& b) const throw()              
01138     { 
01139         return internal <= b.internal;
01140     }
01141 
01142     // -- contants ---------------------------------------------------------- //
01143     
01144     inline static const Fix& getOne() throw()
01145     {
01146         static Fix v (Internal (Base (1) << FBits));
01147         return v;
01148     }
01149         
01150     inline static const Fix& getMinimum() throw()
01151     {
01152         static Fix v (Internal (Base (1) << (IBits + FBits - 1)));
01153         return v;
01154     }
01155     
01156     inline static const Fix& getEpsilson() throw()
01157     {
01158         static Fix v (Internal (Base (1)));
01159         return v;
01160     }
01161 
01162     inline static const Fix& getMaximum() throw()
01163     {
01164         static Fix v (Internal (~(getMinimum().internal)));
01165         return v;
01166     }
01167 
01168     inline static const Fix& getOverflow() throw()
01169     {
01170         static Fix v (getMinimum());
01171         return v;
01172     }
01173     
01174     inline static const Fix& getAtan2Magic1() throw()
01175     {
01176         static Fix v (0.1963);
01177         return v;
01178     }
01179     
01180     inline static const Fix& getAtan2Magic2() throw()
01181     {
01182         static Fix v (0.9817);
01183         return v;
01184     }
01185         
01186     inline static const Base& getIMask() throw()
01187     {
01188         static Base v (getIMaskInternal()); // getIMaskInternal() is slow but only happens once at init
01189         return v;
01190     }
01191 
01192     inline static const Base& getFMask() throw()
01193     {
01194         static Base v (getFMaskInternal()); // getFMaskInternal() is slow but only happens once at init
01195         return v;
01196     }
01197     
01198     inline const Base& getRaw() const throw() { return internal; }
01199     
01200 #if !PLONK_ANDROID
01201     friend std::istream& operator>> (std::istream &inputStream, Fix& value)
01202     {
01203         float floatValue;
01204         inputStream >> floatValue;
01205         value = Fix (floatValue);
01206         return inputStream;
01207     }
01208     
01209     friend std::ostream& operator<< (std::ostream &outputStream, Fix const& value)
01210     {
01211         outputStream << float (value);
01212         return outputStream;
01213     }
01214 #endif
01215     
01216 private:
01217     Base internal;
01218     
01219     inline static const float& getOneFloat() throw()
01220     {
01221         static float v (float (getOne().internal));
01222         return v;
01223     }
01224     
01225     inline static const double& getOneDouble() throw()
01226     {
01227         static double v (double (getOne().internal));
01228         return v;
01229     }
01230     
01231     inline static Base getIMaskInternal() throw()
01232     {
01233         Base v = 0;
01234         
01235         for (int i = 0; i < IBits; ++i)
01236             v = (v << 1) | 1;
01237         
01238         return v << FBits;
01239     }
01240         
01241     inline static Base getFMaskInternal() throw()
01242     {
01243         Base v = 0;
01244         
01245         for (int i = 0; i < FBits; ++i)
01246             v = (v << 1) | 1;
01247         
01248         return v;
01249     }
01250 
01251     static Fix log2Internal (Fix const& a) throw()
01252     {
01253         const Fix two (Math<Fix>::get2());
01254         Fix x = a;
01255         Fix result = 0;
01256         
01257         while (x.internal >= two.internal)
01258         {
01259             result.internal++;
01260             x.internal >>= 1;
01261         }
01262         
01263         if (x.internal == 0) 
01264             return Fix (Internal (result.internal << 16));
01265         
01266         for(int i = 16; i > 0; --i)
01267         {
01268             x *= x;
01269             result.internal <<= 1;
01270             
01271             if (x.internal >= two.internal)
01272             {
01273                 result.internal |= 1;
01274                 x.internal >>= 1;
01275             }
01276         }
01277         
01278         return result;
01279     }
01280 
01281     
01283     template<class OtherFixType>
01284     static inline typename FixBaseConvert<Base,typename OtherFixType::BaseType>::ConvertBase convert (OtherFixType const& other) throw()
01285     {
01286         typedef typename FixBaseConvert<Base,typename OtherFixType::BaseType>::ConvertBase ConvertBase;
01287         return ConvertBase (other.getRaw());
01288     }
01289 };
01290 
01291 template<class Base, unsigned IBits, unsigned FBits> const unsigned Fix<Base,IBits,FBits>::IBitsCount = IBits;
01292 template<class Base, unsigned IBits, unsigned FBits> const unsigned Fix<Base,IBits,FBits>::FBitsCount = FBits;
01293 
01294 #define PLONK_FIXBINARYOPFUNCTION_DEFINE(OP)\
01295     static inline OperandType OP (OperandType const& a, OperandType const& b) throw() { return a.OP (b); }
01296 
01297 template<class FixType>
01298 class FixBinaryOpFunctions
01299 {
01300 public:
01301     typedef FixType OperandType;
01302 
01303     PLONK_FIXBINARYOPFUNCTION_DEFINE(addop)
01304     PLONK_FIXBINARYOPFUNCTION_DEFINE(subop)
01305     PLONK_FIXBINARYOPFUNCTION_DEFINE(mulop)
01306     PLONK_FIXBINARYOPFUNCTION_DEFINE(divop)
01307     PLONK_FIXBINARYOPFUNCTION_DEFINE(modop)
01308     PLONK_FIXBINARYOPFUNCTION_DEFINE(isEqualTo)
01309     PLONK_FIXBINARYOPFUNCTION_DEFINE(isNotEqualTo)
01310     PLONK_FIXBINARYOPFUNCTION_DEFINE(isGreaterThan)
01311     PLONK_FIXBINARYOPFUNCTION_DEFINE(isGreaterThanOrEqualTo)
01312     PLONK_FIXBINARYOPFUNCTION_DEFINE(isLessThan)
01313     PLONK_FIXBINARYOPFUNCTION_DEFINE(isLessThanOrEqualTo)
01314     PLONK_FIXBINARYOPFUNCTION_DEFINE(hypot)
01315     PLONK_FIXBINARYOPFUNCTION_DEFINE(pow)
01316     PLONK_FIXBINARYOPFUNCTION_DEFINE(min)
01317     PLONK_FIXBINARYOPFUNCTION_DEFINE(max)
01318     PLONK_FIXBINARYOPFUNCTION_DEFINE(sumsqr)
01319     PLONK_FIXBINARYOPFUNCTION_DEFINE(difsqr)
01320     PLONK_FIXBINARYOPFUNCTION_DEFINE(sqrsum)
01321     PLONK_FIXBINARYOPFUNCTION_DEFINE(sqrdif)
01322     PLONK_FIXBINARYOPFUNCTION_DEFINE(absdif)
01323     PLONK_FIXBINARYOPFUNCTION_DEFINE(thresh)
01324     PLONK_FIXBINARYOPFUNCTION_DEFINE(round)
01325     PLONK_FIXBINARYOPFUNCTION_DEFINE(trunc)
01326     PLONK_FIXBINARYOPFUNCTION_DEFINE(clip2)
01327     PLONK_FIXBINARYOPFUNCTION_DEFINE(decayFeedback)
01328 };
01329 
01330 #define PLONK_FIXUNARYOPFUNCTION_DEFINE(OP)\
01331     static inline OperandType OP (OperandType const& a) throw() { return a.OP(); }
01332 
01333 template<class FixType>
01334 class FixUnaryOpFunctions
01335 {
01336 public:
01337     typedef FixType OperandType;
01338     
01339     PLONK_FIXUNARYOPFUNCTION_DEFINE(move)
01340     PLONK_FIXUNARYOPFUNCTION_DEFINE(inc)
01341     PLONK_FIXUNARYOPFUNCTION_DEFINE(dec)
01342     PLONK_FIXUNARYOPFUNCTION_DEFINE(abs)
01343     PLONK_FIXUNARYOPFUNCTION_DEFINE(log2)
01344     PLONK_FIXUNARYOPFUNCTION_DEFINE(neg)
01345     PLONK_FIXUNARYOPFUNCTION_DEFINE(reciprocal)
01346     PLONK_FIXUNARYOPFUNCTION_DEFINE(sin)
01347     PLONK_FIXUNARYOPFUNCTION_DEFINE(cos)
01348     PLONK_FIXUNARYOPFUNCTION_DEFINE(tan)
01349     PLONK_FIXUNARYOPFUNCTION_DEFINE(asin)
01350     PLONK_FIXUNARYOPFUNCTION_DEFINE(acos)
01351     PLONK_FIXUNARYOPFUNCTION_DEFINE(atan)
01352     PLONK_FIXUNARYOPFUNCTION_DEFINE(sinh)
01353     PLONK_FIXUNARYOPFUNCTION_DEFINE(cosh)
01354     PLONK_FIXUNARYOPFUNCTION_DEFINE(tanh)
01355     PLONK_FIXUNARYOPFUNCTION_DEFINE(sqrt)
01356     PLONK_FIXUNARYOPFUNCTION_DEFINE(log)
01357     PLONK_FIXUNARYOPFUNCTION_DEFINE(log10)
01358     PLONK_FIXUNARYOPFUNCTION_DEFINE(exp)
01359     PLONK_FIXUNARYOPFUNCTION_DEFINE(squared)
01360     PLONK_FIXUNARYOPFUNCTION_DEFINE(cubed)
01361     PLONK_FIXUNARYOPFUNCTION_DEFINE(ceil)
01362     PLONK_FIXUNARYOPFUNCTION_DEFINE(floor)
01363     PLONK_FIXUNARYOPFUNCTION_DEFINE(frac)
01364     PLONK_FIXUNARYOPFUNCTION_DEFINE(sign)
01365     PLONK_FIXUNARYOPFUNCTION_DEFINE(m2f)
01366     PLONK_FIXUNARYOPFUNCTION_DEFINE(f2m)
01367     PLONK_FIXUNARYOPFUNCTION_DEFINE(a2dB)
01368     PLONK_FIXUNARYOPFUNCTION_DEFINE(dB2a)
01369     PLONK_FIXUNARYOPFUNCTION_DEFINE(d2r)
01370     PLONK_FIXUNARYOPFUNCTION_DEFINE(r2d)
01371     PLONK_FIXUNARYOPFUNCTION_DEFINE(distort)
01372     PLONK_FIXUNARYOPFUNCTION_DEFINE(zap)
01373 };
01374 
01375 
01376 
01377 #define PLONK_OPFUNCTIONSHELPERS_DEFINE(TYPE,I,F)\
01378     template<> class BinaryOpFunctionsHelper<Fix<TYPE,I,F> > { public: typedef FixBinaryOpFunctions<Fix<TYPE,I,F> > BinaryOpFunctionsType; };\
01379     template<> class UnaryOpFunctionsHelper<Fix<TYPE,I,F> > { public: typedef FixUnaryOpFunctions<Fix<TYPE,I,F> > UnaryOpFunctionsType; };
01380 
01381 // need to specialise all the possibilities of this just in case..
01382 
01383 PLONK_OPFUNCTIONSHELPERS_DEFINE(char,1,7)
01384 PLONK_OPFUNCTIONSHELPERS_DEFINE(char,2,6)
01385 PLONK_OPFUNCTIONSHELPERS_DEFINE(char,3,5)
01386 PLONK_OPFUNCTIONSHELPERS_DEFINE(char,4,4)
01387 PLONK_OPFUNCTIONSHELPERS_DEFINE(char,5,3)
01388 PLONK_OPFUNCTIONSHELPERS_DEFINE(char,6,2)
01389 PLONK_OPFUNCTIONSHELPERS_DEFINE(char,7,1)
01390 
01391 PLONK_OPFUNCTIONSHELPERS_DEFINE(short, 1,15)
01392 PLONK_OPFUNCTIONSHELPERS_DEFINE(short, 2,14)
01393 PLONK_OPFUNCTIONSHELPERS_DEFINE(short, 3,13)
01394 PLONK_OPFUNCTIONSHELPERS_DEFINE(short, 4,12)
01395 PLONK_OPFUNCTIONSHELPERS_DEFINE(short, 5,11)
01396 PLONK_OPFUNCTIONSHELPERS_DEFINE(short, 6,10)
01397 PLONK_OPFUNCTIONSHELPERS_DEFINE(short, 7, 9)
01398 PLONK_OPFUNCTIONSHELPERS_DEFINE(short, 8, 8)
01399 PLONK_OPFUNCTIONSHELPERS_DEFINE(short, 9, 7)
01400 PLONK_OPFUNCTIONSHELPERS_DEFINE(short,10, 6)
01401 PLONK_OPFUNCTIONSHELPERS_DEFINE(short,11, 5)
01402 PLONK_OPFUNCTIONSHELPERS_DEFINE(short,12, 4)
01403 PLONK_OPFUNCTIONSHELPERS_DEFINE(short,13, 3)
01404 PLONK_OPFUNCTIONSHELPERS_DEFINE(short,14, 2)
01405 PLONK_OPFUNCTIONSHELPERS_DEFINE(short,15, 1)
01406 
01407 PLONK_OPFUNCTIONSHELPERS_DEFINE(int, 1,31)
01408 PLONK_OPFUNCTIONSHELPERS_DEFINE(int, 2,30)
01409 PLONK_OPFUNCTIONSHELPERS_DEFINE(int, 3,29)
01410 PLONK_OPFUNCTIONSHELPERS_DEFINE(int, 4,28)
01411 PLONK_OPFUNCTIONSHELPERS_DEFINE(int, 5,27)
01412 PLONK_OPFUNCTIONSHELPERS_DEFINE(int, 6,26)
01413 PLONK_OPFUNCTIONSHELPERS_DEFINE(int, 7,25)
01414 PLONK_OPFUNCTIONSHELPERS_DEFINE(int, 8,24)
01415 PLONK_OPFUNCTIONSHELPERS_DEFINE(int, 9,23)
01416 PLONK_OPFUNCTIONSHELPERS_DEFINE(int,10,22)
01417 PLONK_OPFUNCTIONSHELPERS_DEFINE(int,11,21)
01418 PLONK_OPFUNCTIONSHELPERS_DEFINE(int,12,20)
01419 PLONK_OPFUNCTIONSHELPERS_DEFINE(int,13,19)
01420 PLONK_OPFUNCTIONSHELPERS_DEFINE(int,14,18)
01421 PLONK_OPFUNCTIONSHELPERS_DEFINE(int,15,17)
01422 PLONK_OPFUNCTIONSHELPERS_DEFINE(int,16,16)
01423 PLONK_OPFUNCTIONSHELPERS_DEFINE(int,17,15)
01424 PLONK_OPFUNCTIONSHELPERS_DEFINE(int,18,14)
01425 PLONK_OPFUNCTIONSHELPERS_DEFINE(int,19,13)
01426 PLONK_OPFUNCTIONSHELPERS_DEFINE(int,20,12)
01427 PLONK_OPFUNCTIONSHELPERS_DEFINE(int,21,11)
01428 PLONK_OPFUNCTIONSHELPERS_DEFINE(int,22,10)
01429 PLONK_OPFUNCTIONSHELPERS_DEFINE(int,23, 9)
01430 PLONK_OPFUNCTIONSHELPERS_DEFINE(int,24, 8)
01431 PLONK_OPFUNCTIONSHELPERS_DEFINE(int,25, 7)
01432 PLONK_OPFUNCTIONSHELPERS_DEFINE(int,26, 6)
01433 PLONK_OPFUNCTIONSHELPERS_DEFINE(int,27, 5)
01434 PLONK_OPFUNCTIONSHELPERS_DEFINE(int,28, 4)
01435 PLONK_OPFUNCTIONSHELPERS_DEFINE(int,29, 3)
01436 PLONK_OPFUNCTIONSHELPERS_DEFINE(int,30, 2)
01437 PLONK_OPFUNCTIONSHELPERS_DEFINE(int,31, 1)
01438 
01439 
01440 
01441 
01442 // stuff like this will work for vector specialisations too..
01443 //template<>
01444 //class NumericalArrayBinaryOp< FixI8F8,plonk::mulop<FixI8F8> >
01445 //{
01446 //public:    
01447 //    static inline void calcNN (FixI8F8* dst, const FixI8F8* left, const FixI8F8* right, const UnsignedLong numItems) throw()
01448 //    {
01449 //        for (UnsignedLong i = 0; i < numItems; ++i)
01450 //            dst[i] = plonk::mulop (left[i], right[i]);
01451 //    }
01452 //    
01453 //    static inline void calcN1 (FixI8F8* dst, const FixI8F8* left, const FixI8F8 right, const UnsignedLong numItems) throw()
01454 //    {
01455 //        for (UnsignedLong i = 0; i < numItems; ++i)
01456 //            dst[i] = plonk::mulop (left[i], right);
01457 //    }
01458 //    
01459 //    static inline void calc1N (FixI8F8* dst, const FixI8F8 left, const FixI8F8* right, const UnsignedLong numItems) throw()
01460 //    {
01461 //        for (UnsignedLong i = 0; i < numItems; ++i)
01462 //            dst[i] = plonk::mulop (left, right[i]);
01463 //    }
01464 //
01465 //};
01466 
01467 
01468 
01469 #endif // PLONK_FIX_H
 All Classes Functions Typedefs Enumerations Enumerator Properties