![]() |
pl-nk v0.4.5
Plonk|Plink|Plank are a set of cross-platform C/C++ frameworks for audio software development
|
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