Simbody

Scalar.h

Go to the documentation of this file.
00001 #ifndef SimTK_SIMMATRIX_SCALAR_H_
00002 #define SimTK_SIMMATRIX_SCALAR_H_
00003 
00004 /* -------------------------------------------------------------------------- *
00005  *                      SimTK Core: SimTK Simmatrix(tm)                       *
00006  * -------------------------------------------------------------------------- *
00007  * This is part of the SimTK Core biosimulation toolkit originating from      *
00008  * Simbios, the NIH National Center for Physics-Based Simulation of           *
00009  * Biological Structures at Stanford, funded under the NIH Roadmap for        *
00010  * Medical Research, grant U54 GM072970. See https://simtk.org.               *
00011  *                                                                            *
00012  * Portions copyright (c) 2005-10 Stanford University and the Authors.        *
00013  * Authors: Michael Sherman                                                   *
00014  * Contributors:                                                              *
00015  *                                                                            *
00016  * Permission is hereby granted, free of charge, to any person obtaining a    *
00017  * copy of this software and associated documentation files (the "Software"), *
00018  * to deal in the Software without restriction, including without limitation  *
00019  * the rights to use, copy, modify, merge, publish, distribute, sublicense,   *
00020  * and/or sell copies of the Software, and to permit persons to whom the      *
00021  * Software is furnished to do so, subject to the following conditions:       *
00022  *                                                                            *
00023  * The above copyright notice and this permission notice shall be included in *
00024  * all copies or substantial portions of the Software.                        *
00025  *                                                                            *
00026  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
00027  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   *
00028  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    *
00029  * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,    *
00030  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR      *
00031  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  *
00032  * USE OR OTHER DEALINGS IN THE SOFTWARE.                                     *
00033  * -------------------------------------------------------------------------- */
00034 
00041 #include "SimTKcommon/internal/common.h"
00042 #include "SimTKcommon/Constants.h"
00043 #include "SimTKcommon/internal/Exception.h"
00044 #include "SimTKcommon/internal/ExceptionMacros.h"
00045 #include "SimTKcommon/internal/String.h"
00046 #include "SimTKcommon/internal/Array.h"
00047 
00048 #include "SimTKcommon/internal/conjugate.h"
00049 #include "SimTKcommon/internal/CompositeNumericalTypes.h"
00050 #include "SimTKcommon/internal/NTraits.h"
00051 #include "SimTKcommon/internal/negator.h"
00052 
00053 #include <complex>
00054 #include <cmath>
00055 #include <climits>
00056 #include <cassert>
00057 #include <utility>
00058 
00059 namespace SimTK {
00060 
00062     // Handy default-precision definitions //
00064 
00065 typedef conjugate<Real> Conjugate;  // like Complex
00066 
00099 static const Real& NaN               = NTraits<Real>::getNaN(); 
00103 static const Real& Infinity          = NTraits<Real>::getInfinity();
00104 
00108 static const Real& Eps               = NTraits<Real>::getEps();
00112 static const Real& SqrtEps           = NTraits<Real>::getSqrtEps();
00118 static const Real& TinyReal          = NTraits<Real>::getTiny(); 
00123 static const Real& SignificantReal   = NTraits<Real>::getSignificant(); 
00124 
00127 static const Real& LeastPositiveReal = NTraits<Real>::getLeastPositive(); 
00131 static const Real& MostPositiveReal  = NTraits<Real>::getMostPositive();  
00134 static const Real& LeastNegativeReal = NTraits<Real>::getLeastNegative();
00138 static const Real& MostNegativeReal  = NTraits<Real>::getMostNegative();
00139 
00143 static const int NumDigitsReal = NTraits<Real>::getNumDigits(); 
00144 
00150 static const int LosslessNumDigitsReal = NTraits<Real>::getLosslessNumDigits(); // double ~20, float ~9
00151 
00152     // Carefully calculated constants, with convenient memory addresses.
00153 
00154 static const Real& Zero         = NTraits<Real>::getZero();  
00155 static const Real& One          = NTraits<Real>::getOne();   
00156 static const Real& MinusOne     = NTraits<Real>::getMinusOne(); 
00157 static const Real& Two          = NTraits<Real>::getTwo();   
00158 static const Real& Three        = NTraits<Real>::getThree(); 
00159 
00160 static const Real& OneHalf      = NTraits<Real>::getOneHalf();   
00161 static const Real& OneThird     = NTraits<Real>::getOneThird();  
00162 static const Real& OneFourth    = NTraits<Real>::getOneFourth(); 
00163 static const Real& OneFifth     = NTraits<Real>::getOneFifth();  
00164 static const Real& OneSixth     = NTraits<Real>::getOneSixth();  
00165 static const Real& OneSeventh   = NTraits<Real>::getOneSeventh();
00166 static const Real& OneEighth    = NTraits<Real>::getOneEighth(); 
00167 static const Real& OneNinth     = NTraits<Real>::getOneNinth();  
00168 static const Real& Pi           = NTraits<Real>::getPi();        
00169 static const Real& OneOverPi    = NTraits<Real>::getOneOverPi(); 
00170 static const Real& E            = NTraits<Real>::getE();     
00171 static const Real& Log2E        = NTraits<Real>::getLog2E(); 
00172 static const Real& Log10E       = NTraits<Real>::getLog10E();
00173 static const Real& Sqrt2        = NTraits<Real>::getSqrt2(); 
00174 static const Real& OneOverSqrt2 = NTraits<Real>::getOneOverSqrt2(); 
00175 static const Real& Sqrt3        = NTraits<Real>::getSqrt3();        
00176 static const Real& OneOverSqrt3 = NTraits<Real>::getOneOverSqrt3(); 
00177 static const Real& CubeRoot2    = NTraits<Real>::getCubeRoot2();    
00178 static const Real& CubeRoot3    = NTraits<Real>::getCubeRoot3();    
00179 static const Real& Ln2          = NTraits<Real>::getLn2();  
00180 static const Real& Ln10         = NTraits<Real>::getLn10(); 
00181 
00187 static const Complex& I = NTraits<Complex>::getI();
00190 
00191     // SOME SCALAR UTILITIES //
00193 
00194 
00208 // We use the trick that v & v-1 returns the value that is v with its
00209 // rightmost bit cleared (if it has a rightmost bit set).
00210 inline bool atMostOneBitIsSet(unsigned char v)      {return (v&v-1)==0;}
00211 inline bool atMostOneBitIsSet(unsigned short v)     {return (v&v-1)==0;}
00212 inline bool atMostOneBitIsSet(unsigned int v)       {return (v&v-1)==0;}
00213 inline bool atMostOneBitIsSet(unsigned long v)      {return (v&v-1)==0;}
00214 inline bool atMostOneBitIsSet(unsigned long long v) {return (v&v-1)==0;}
00215 inline bool atMostOneBitIsSet(signed char v)        {return (v&v-1)==0;}
00216 inline bool atMostOneBitIsSet(char v)               {return (v&v-1)==0;}
00217 inline bool atMostOneBitIsSet(short v)              {return (v&v-1)==0;}
00218 inline bool atMostOneBitIsSet(int v)                {return (v&v-1)==0;}
00219 inline bool atMostOneBitIsSet(long v)               {return (v&v-1)==0;}
00220 inline bool atMostOneBitIsSet(long long v)          {return (v&v-1)==0;}
00222 
00237 inline bool exactlyOneBitIsSet(unsigned char v)      {return v && atMostOneBitIsSet(v);}
00238 inline bool exactlyOneBitIsSet(unsigned short v)     {return v && atMostOneBitIsSet(v);}
00239 inline bool exactlyOneBitIsSet(unsigned int v)       {return v && atMostOneBitIsSet(v);}
00240 inline bool exactlyOneBitIsSet(unsigned long v)      {return v && atMostOneBitIsSet(v);}
00241 inline bool exactlyOneBitIsSet(unsigned long long v) {return v && atMostOneBitIsSet(v);}
00242 inline bool exactlyOneBitIsSet(signed char v)        {return v && atMostOneBitIsSet(v);}
00243 inline bool exactlyOneBitIsSet(char v)               {return v && atMostOneBitIsSet(v);}
00244 inline bool exactlyOneBitIsSet(short v)              {return v && atMostOneBitIsSet(v);}
00245 inline bool exactlyOneBitIsSet(int v)                {return v && atMostOneBitIsSet(v);}
00246 inline bool exactlyOneBitIsSet(long v)               {return v && atMostOneBitIsSet(v);}
00247 inline bool exactlyOneBitIsSet(long long v)          {return v && atMostOneBitIsSet(v);}
00249 
00276 
00277 inline bool signBit(unsigned char i)      {return false;}
00278 inline bool signBit(unsigned short i)     {return false;}
00279 inline bool signBit(unsigned int i)       {return false;}
00280 inline bool signBit(unsigned long i)      {return false;}
00281 inline bool signBit(unsigned long long i) {return false;}
00282 
00283 // Note that plain 'char' type is not overloaded -- see above.
00284 
00285 // We're assuming sizeof(char)==1, short==2, int==4, long long==8 which is safe
00286 // for all our anticipated platforms. But some 64 bit implementations have
00287 // sizeof(long)==4 while others have sizeof(long)==8 so we'll use the ANSI
00288 // standard value LONG_MIN which is a long value with just the high bit set.
00289 // (We're assuming two's complement integers here; I haven't seen anything
00290 // else in decades.)
00291 inline bool signBit(signed char i) {return ((unsigned char)i      & 0x80U) != 0;}
00292 inline bool signBit(short       i) {return ((unsigned short)i     & 0x8000U) != 0;}
00293 inline bool signBit(int         i) {return ((unsigned int)i       & 0x80000000U) != 0;}
00294 inline bool signBit(long long   i) {return ((unsigned long long)i & 0x8000000000000000ULL) != 0;}
00295 
00296 inline bool signBit(long        i) {return ((unsigned long)i
00297                                             & (unsigned long)LONG_MIN) != 0;}
00298 
00299 inline bool signBit(const float&  f) {return std::signbit(f);}
00300 inline bool signBit(const double& d) {return std::signbit(d);}
00301 inline bool signBit(const negator<float>&  nf) {return std::signbit(-nf);} // !!
00302 inline bool signBit(const negator<double>& nd) {return std::signbit(-nd);} // !!
00303 
00318 inline unsigned int sign(unsigned char      u) {return u==0 ? 0 : 1;}
00319 inline unsigned int sign(unsigned short     u) {return u==0 ? 0 : 1;}
00320 inline unsigned int sign(unsigned int       u) {return u==0 ? 0 : 1;}
00321 inline unsigned int sign(unsigned long      u) {return u==0 ? 0 : 1;}
00322 inline unsigned int sign(unsigned long long u) {return u==0 ? 0 : 1;}
00323 
00324 // Don't overload for plain "char" because it may be signed or unsigned
00325 // depending on the compiler.
00326 
00327 inline int sign(signed char i) {return i>0 ? 1 : (i<0 ? -1 : 0);}
00328 inline int sign(short       i) {return i>0 ? 1 : (i<0 ? -1 : 0);}
00329 inline int sign(int         i) {return i>0 ? 1 : (i<0 ? -1 : 0);}
00330 inline int sign(long        i) {return i>0 ? 1 : (i<0 ? -1 : 0);}
00331 inline int sign(long long   i) {return i>0 ? 1 : (i<0 ? -1 : 0);}
00332 
00333 inline int sign(const float&       x) {return x>0 ? 1 : (x<0 ? -1 : 0);}
00334 inline int sign(const double&      x) {return x>0 ? 1 : (x<0 ? -1 : 0);}
00335 inline int sign(const long double& x) {return x>0 ? 1 : (x<0 ? -1 : 0);}
00336 
00337 inline int sign(const negator<float>&       x) {return -sign(-x);} // -x is free
00338 inline int sign(const negator<double>&      x) {return -sign(-x);}
00339 inline int sign(const negator<long double>& x) {return -sign(-x);}
00341 
00358 inline unsigned char  square(unsigned char  u) {return u*u;}
00359 inline unsigned short square(unsigned short u) {return u*u;}
00360 inline unsigned int   square(unsigned int   u) {return u*u;}
00361 inline unsigned long  square(unsigned long  u) {return u*u;}
00362 inline unsigned long long square(unsigned long long u) {return u*u;}
00363 
00364 inline char        square(char c) {return c*c;}
00365 
00366 inline signed char square(signed char i) {return i*i;}
00367 inline short       square(short       i) {return i*i;}
00368 inline int         square(int         i) {return i*i;}
00369 inline long        square(long        i) {return i*i;}
00370 inline long long   square(long long   i) {return i*i;}
00371 
00372 inline float       square(const float&       x) {return x*x;}
00373 inline double      square(const double&      x) {return x*x;}
00374 inline long double square(const long double& x) {return x*x;}
00375 
00376 // Negation is free for negators, so we can square them and clean
00377 // them up at the same time at no extra cost.
00378 inline float       square(const negator<float>&       x) {return square(-x);}
00379 inline double      square(const negator<double>&      x) {return square(-x);}
00380 inline long double square(const negator<long double>& x) {return square(-x);}
00381 
00382 // It is safer to templatize using complex classes, and doesn't make
00383 // debugging any worse since complex is already templatized. 
00384 // 5 flops vs. 6 for general complex multiply.
00385 template <class P> inline 
00386 std::complex<P> square(const std::complex<P>& x) {
00387     const P re=x.real(), im=x.imag();
00388     return std::complex<P>(re*re-im*im, 2*re*im);
00389 }
00390 
00391 // We can square a conjugate and clean it up back to complex at
00392 // the same time at zero cost (or maybe 1 negation depending
00393 // on how the compiler handles the "-2" below).
00394 template <class P> inline 
00395 std::complex<P> square(const conjugate<P>& x) {
00396     const P re=x.real(), nim=x.negImag();
00397     return std::complex<P>(re*re-nim*nim, -2*re*nim);
00398 }
00399 
00400 template <class P> inline
00401 std::complex<P> square(const negator< std::complex<P> >& x) {
00402     return square(-x); // negation is free for negators
00403 }
00404 
00405 // Note return type here after squaring negator<conjugate>
00406 // is complex, not conjugate.
00407 template <class P> inline
00408 std::complex<P> square(const negator< conjugate<P> >& x) {
00409     return square(-x); // negation is free for negators
00410 }
00412 
00431 inline unsigned char  cube(unsigned char  u) {return u*u*u;}
00432 inline unsigned short cube(unsigned short u) {return u*u*u;}
00433 inline unsigned int   cube(unsigned int   u) {return u*u*u;}
00434 inline unsigned long  cube(unsigned long  u) {return u*u*u;}
00435 inline unsigned long long cube(unsigned long long u) {return u*u*u;}
00436 
00437 inline char        cube(char c) {return c*c*c;}
00438 
00439 inline signed char cube(signed char i) {return i*i*i;}
00440 inline short       cube(short       i) {return i*i*i;}
00441 inline int         cube(int         i) {return i*i*i;}
00442 inline long        cube(long        i) {return i*i*i;}
00443 inline long long   cube(long long   i) {return i*i*i;}
00444 
00445 inline float       cube(const float&       x) {return x*x*x;}
00446 inline double      cube(const double&      x) {return x*x*x;}
00447 inline long double cube(const long double& x) {return x*x*x;}
00448 
00449 // To keep this cheap we'll defer getting rid of the negator<> until
00450 // some other operation. We cube -x and then recast that to negator<>
00451 // on return, for a total cost of 2 flops.
00452 inline negator<float> cube(const negator<float>& x) {
00453     return negator<float>::recast(cube(-x));
00454 }
00455 inline negator<double> cube(const negator<double>& x) {
00456     return negator<double>::recast(cube(-x));
00457 }
00458 inline negator<long double> cube(const negator<long double>& x) {
00459     return negator<long double>::recast(cube(-x));
00460 }
00461 
00462 // Cubing a complex this way is cheaper than doing it by
00463 // multiplication. Cost here is 8 flops vs. 11 for a square
00464 // followed by a multiply.
00465 template <class P> inline
00466 std::complex<P> cube(const std::complex<P>& x) {
00467     const P re=x.real(), im=x.imag(), rr=re*re, ii=im*im;
00468     return std::complex<P>(re*(rr-3*ii), im*(3*rr-ii));
00469 }
00470 
00471 // Cubing a negated complex allows us to cube and eliminate the
00472 // negator at the same time for zero extra cost. Compare the 
00473 // expressions here to the normal cube above to see the free
00474 // sign changes in both parts. 8 flops here.
00475 template <class P> inline
00476 std::complex<P> cube(const negator< std::complex<P> >& x) {
00477     // -x is free for a negator
00478     const P nre=(-x).real(), nim=(-x).imag(), rr=nre*nre, ii=nim*nim;
00479     return std::complex<P>(nre*(3*ii-rr), nim*(ii-3*rr));
00480 }
00481 
00482 // Cubing a conjugate this way saves a lot over multiplying, and
00483 // also lets us convert the result to complex for free.
00484 template <class P> inline
00485 std::complex<P> cube(const conjugate<P>& x) {
00486     const P re=x.real(), nim=x.negImag(), rr=re*re, ii=nim*nim;
00487     return std::complex<P>(re*(rr-3*ii), nim*(ii-3*rr));
00488 }
00489 
00490 
00491 // Cubing a negated conjugate this way saves a lot over multiplying, and
00492 // also lets us convert the result to non-negated complex for free.
00493 template <class P> inline
00494 std::complex<P> cube(const negator< conjugate<P> >& x) {
00495     // -x is free for a negator
00496     const P nre=(-x).real(), im=(-x).negImag(), rr=nre*nre, ii=im*im;
00497     return std::complex<P>(nre*(3*ii-rr), im*(3*rr-ii));
00498 }
00500 
00532 
00548 inline double& clampInPlace(double low, double& v, double high) 
00549 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00551 inline float& clampInPlace(float low, float& v, float high) 
00552 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00554 inline long double& clampInPlace(long double low, long double& v, long double high) 
00555 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00556 
00557     // Floating point clamps with integer bounds; without these
00558     // explicit casts are required.
00559 
00562 inline double& clampInPlace(int low, double& v, int high) 
00563 {   return clampInPlace((double)low,v,(double)high); }
00566 inline float& clampInPlace(int low, float& v, int high) 
00567 {   return clampInPlace((float)low,v,(float)high); }
00570 inline long double& clampInPlace(int low, long double& v, int high) 
00571 {   return clampInPlace((long double)low,v,(long double)high); }
00572 
00575 inline double& clampInPlace(int low, double& v, double high) 
00576 {   return clampInPlace((double)low,v,high); }
00579 inline float& clampInPlace(int low, float& v, float high) 
00580 {   return clampInPlace((float)low,v,high); }
00583 inline long double& clampInPlace(int low, long double& v, long double high) 
00584 {   return clampInPlace((long double)low,v,high); }
00585 
00588 inline double& clampInPlace(double low, double& v, int high) 
00589 {   return clampInPlace(low,v,(double)high); }
00592 inline float& clampInPlace(float low, float& v, int high) 
00593 {   return clampInPlace(low,v,(float)high); }
00596 inline long double& clampInPlace(long double low, long double& v, int high) 
00597 {   return clampInPlace(low,v,(long double)high); }
00598 
00600 inline unsigned char& clampInPlace(unsigned char low, unsigned char& v, unsigned char high) 
00601 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00603 inline unsigned short& clampInPlace(unsigned short low, unsigned short& v, unsigned short high) 
00604 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00606 inline unsigned int& clampInPlace(unsigned int low, unsigned int& v, unsigned int high) 
00607 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00609 inline unsigned long& clampInPlace(unsigned long low, unsigned long& v, unsigned long high) 
00610 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00612 inline unsigned long long& clampInPlace(unsigned long long low, unsigned long long& v, unsigned long long high) 
00613 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00614 
00616 inline char& clampInPlace(char low, char& v, char high) 
00617 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00619 inline signed char& clampInPlace(signed char low, signed char& v, signed char high) 
00620 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00621 
00623 inline short& clampInPlace(short low, short& v, short high) 
00624 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00626 inline int& clampInPlace(int low, int& v, int high) 
00627 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00629 inline long& clampInPlace(long low, long& v, long high) 
00630 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00632 inline long long& clampInPlace(long long low, long long& v, long long high) 
00633 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00634 
00636 inline negator<float>& clampInPlace(float low, negator<float>& v, float high) 
00637 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00639 inline negator<double>& clampInPlace(double low, negator<double>& v, double high) 
00640 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00642 inline negator<long double>& clampInPlace(long double low, negator<long double>& v, long double high) 
00643 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00644 
00645 
00646 
00667 inline double clamp(double low, double v, double high) 
00668 {   return clampInPlace(low,v,high); }
00670 inline float clamp(float low, float v, float high) 
00671 {   return clampInPlace(low,v,high); }
00673 inline long double clamp(long double low, long double v, long double high) 
00674 {   return clampInPlace(low,v,high); }
00675 
00678 inline double clamp(int low, double v, int high) 
00679 {   return clampInPlace(low,v,high); }
00682 inline float clamp(int low, float v, int high) 
00683 {   return clampInPlace(low,v,high); }
00686 inline long double clamp(int low, long double v, int high) 
00687 {   return clampInPlace(low,v,high); }
00688 
00691 inline double clamp(int low, double v, double high) 
00692 {   return clampInPlace(low,v,high); }
00695 inline float clamp(int low, float v, float high) 
00696 {   return clampInPlace(low,v,high); }
00699 inline long double clamp(int low, long double v, long double high) 
00700 {   return clampInPlace(low,v,high); }
00701 
00704 inline double clamp(double low, double v, int high) 
00705 {   return clampInPlace(low,v,high); }
00708 inline float clamp(float low, float v, int high) 
00709 {   return clampInPlace(low,v,high); }
00712 inline long double clamp(long double low, long double v, int high) 
00713 {   return clampInPlace(low,v,high); }
00714 
00716 inline unsigned char clamp(unsigned char low, unsigned char v, unsigned char high) 
00717 {   return clampInPlace(low,v,high); }
00719 inline unsigned short clamp(unsigned short low, unsigned short v, unsigned short high) 
00720 {   return clampInPlace(low,v,high); }
00722 inline unsigned int clamp(unsigned int low, unsigned int v, unsigned int high) 
00723 {   return clampInPlace(low,v,high); }
00725 inline unsigned long clamp(unsigned long low, unsigned long v, unsigned long high) 
00726 {   return clampInPlace(low,v,high); }
00728 inline unsigned long long clamp(unsigned long long low, unsigned long long v, unsigned long long high) 
00729 {   return clampInPlace(low,v,high); }
00730 
00732 inline char clamp(char low, char v, char high) 
00733 {   return clampInPlace(low,v,high); }
00735 inline signed char clamp(signed char low, signed char v, signed char high) 
00736 {   return clampInPlace(low,v,high); }
00737 
00739 inline short clamp(short low, short v, short high) 
00740 {   return clampInPlace(low,v,high); }
00742 inline int clamp(int low, int v, int high) 
00743 {   return clampInPlace(low,v,high); }
00745 inline long clamp(long low, long v, long high) 
00746 {   return clampInPlace(low,v,high); }
00748 inline long long clamp(long long low, long long v, long long high) 
00749 {   return clampInPlace(low,v,high); }
00750 
00751 
00752 // These aren't strictly necessary but are here to help the
00753 // compiler find the right overload to call. These cost an
00754 // extra flop because the negator<T> has to be cast to T which
00755 // requires that the pending negation be performed. Note that
00756 // the result types are not negated.
00757 
00762 inline float clamp(float low, negator<float> v, float high)
00763 {   return clamp(low,(float)v,high); }
00768 inline double clamp(double low, negator<double> v, double high) 
00769 {   return clamp(low,(double)v,high); }
00774 inline long double clamp(long double low, negator<long double> v, long double high) 
00775 {   return clamp(low,(long double)v,high); }
00816 
00831 inline double stepUp(double x)
00832 {   assert(0 <= x && x <= 1);
00833     return x*x*x*(10+x*(6*x-15)); }  //10x^3-15x^4+6x^5
00834 
00835 
00850 inline double stepDown(double x) {return 1.0 -stepUp(x);}
00851 
00852 
00927 inline double stepAny(double y0, double yRange,
00928                       double x0, double oneOverXRange,
00929                       double x) 
00930 {   double xadj = (x-x0)*oneOverXRange;    
00931     assert(-NTraits<double>::getSignificant() <= xadj
00932            && xadj <= 1 + NTraits<double>::getSignificant());
00933     clampInPlace(0.0,xadj,1.0);
00934     return y0 + yRange*stepUp(xadj); }
00935 
00939 inline double dstepUp(double x) {
00940     assert(0 <= x && x <= 1);
00941     const double xxm1=x*(x-1);
00942     return 30*xxm1*xxm1;        //30x^2-60x^3+30x^4
00943 }
00944 
00948 inline double dstepDown(double x) {return -dstepUp(x);}
00949 
00953 inline double dstepAny(double yRange,
00954                        double x0, double oneOverXRange,
00955                        double x) 
00956 {   double xadj = (x-x0)*oneOverXRange;    
00957     assert(-NTraits<double>::getSignificant() <= xadj
00958            && xadj <= 1 + NTraits<double>::getSignificant());
00959     clampInPlace(0.0,xadj,1.0);
00960     return yRange*oneOverXRange*dstepUp(xadj); }
00961 
00965 inline double d2stepUp(double x) {
00966     assert(0 <= x && x <= 1);
00967     return 60*x*(1+x*(2*x-3));  //60x-180x^2+120x^3
00968 }
00969 
00973 inline double d2stepDown(double x) {return -d2stepUp(x);}
00974 
00978 inline double d2stepAny(double yRange,
00979                         double x0, double oneOverXRange,
00980                         double x) 
00981 {   double xadj = (x-x0)*oneOverXRange;    
00982     assert(-NTraits<double>::getSignificant() <= xadj
00983            && xadj <= 1 + NTraits<double>::getSignificant());
00984     clampInPlace(0.0,xadj,1.0);
00985     return yRange*square(oneOverXRange)*d2stepUp(xadj); }
00986 
00990 inline double d3stepUp(double x) {
00991     assert(0 <= x && x <= 1);
00992     return 60+360*x*(x-1);      //60-360*x+360*x^2
00993 }
00994 
00998 inline double d3stepDown(double x) {return -d3stepUp(x);}
00999 
01003 inline double d3stepAny(double yRange,
01004                         double x0, double oneOverXRange,
01005                         double x) 
01006 {   double xadj = (x-x0)*oneOverXRange;    
01007     assert(-NTraits<double>::getSignificant() <= xadj
01008            && xadj <= 1 + NTraits<double>::getSignificant());
01009     clampInPlace(0.0,xadj,1.0);
01010     return yRange*cube(oneOverXRange)*d3stepUp(xadj); }
01011 
01012             // float
01013 
01015 inline float stepUp(float x) 
01016 {   assert(0 <= x && x <= 1);
01017     return x*x*x*(10+x*(6*x-15)); }  //10x^3-15x^4+6x^5
01019 inline float stepDown(float x) {return 1.0f-stepUp(x);}
01021 inline float stepAny(float y0, float yRange,
01022                      float x0, float oneOverXRange,
01023                      float x) 
01024 {   float xadj = (x-x0)*oneOverXRange;    
01025     assert(-NTraits<float>::getSignificant() <= xadj
01026            && xadj <= 1 + NTraits<float>::getSignificant());
01027     clampInPlace(0.0f,xadj,1.0f);
01028     return y0 + yRange*stepUp(xadj); }
01029 
01031 inline float dstepUp(float x) 
01032 {   assert(0 <= x && x <= 1);
01033     const float xxm1=x*(x-1);
01034     return 30*xxm1*xxm1; }  //30x^2-60x^3+30x^4
01036 inline float dstepDown(float x) {return -dstepUp(x);}
01038 inline float dstepAny(float yRange,
01039                       float x0, float oneOverXRange,
01040                       float x) 
01041 {   float xadj = (x-x0)*oneOverXRange;    
01042     assert(-NTraits<float>::getSignificant() <= xadj
01043            && xadj <= 1 + NTraits<float>::getSignificant());
01044     clampInPlace(0.0f,xadj,1.0f);
01045     return yRange*oneOverXRange*dstepUp(xadj); }
01046 
01048 inline float d2stepUp(float x) 
01049 {   assert(0 <= x && x <= 1);
01050     return 60*x*(1+x*(2*x-3)); }    //60x-180x^2+120x^3
01052 inline float d2stepDown(float x) {return -d2stepUp(x);}
01054 inline float d2stepAny(float yRange,
01055                        float x0, float oneOverXRange,
01056                        float x) 
01057 {   float xadj = (x-x0)*oneOverXRange;    
01058     assert(-NTraits<float>::getSignificant() <= xadj
01059            && xadj <= 1 + NTraits<float>::getSignificant());
01060     clampInPlace(0.0f,xadj,1.0f);
01061     return yRange*square(oneOverXRange)*d2stepUp(xadj); }
01062 
01064 inline float d3stepUp(float x) 
01065 {   assert(0 <= x && x <= 1);
01066     return 60+360*x*(x-1); }    //60-360*x+360*x^2
01068 inline float d3stepDown(float x) {return -d3stepUp(x);}
01070 inline float d3stepAny(float yRange,
01071                        float x0, float oneOverXRange,
01072                        float x) 
01073 {   float xadj = (x-x0)*oneOverXRange;    
01074     assert(-NTraits<float>::getSignificant() <= xadj
01075            && xadj <= 1 + NTraits<float>::getSignificant());
01076     clampInPlace(0.0f,xadj,1.0f);
01077     return yRange*cube(oneOverXRange)*d3stepUp(xadj); }
01078 
01079             // long double
01080 
01082 inline long double stepUp(long double x) 
01083 {   assert(0 <= x && x <= 1);
01084     return x*x*x*(10+x*(6*x-15)); }  //10x^3-15x^4+6x^5
01086 inline long double stepDown(long double x) {return 1.0L-stepUp(x);}
01088 inline long double stepAny(long double y0, long double yRange,
01089                            long double x0, long double oneOverXRange,
01090                            long double x) 
01091 {   long double xadj = (x-x0)*oneOverXRange;    
01092     assert(-NTraits<long double>::getSignificant() <= xadj
01093            && xadj <= 1 + NTraits<long double>::getSignificant());
01094     clampInPlace(0.0L,xadj,1.0L);
01095     return y0 + yRange*stepUp(xadj); }
01096 
01097 
01099 inline long double dstepUp(long double x) 
01100 {   assert(0 <= x && x <= 1);
01101     const long double xxm1=x*(x-1);
01102     return 30*xxm1*xxm1; }          //30x^2-60x^3+30x^4
01104 inline long double dstepDown(long double x) {return -dstepUp(x);}
01106 inline long double dstepAny(long double yRange,
01107                             long double x0, long double oneOverXRange,
01108                             long double x) 
01109 {   long double xadj = (x-x0)*oneOverXRange;    
01110     assert(-NTraits<long double>::getSignificant() <= xadj
01111            && xadj <= 1 + NTraits<long double>::getSignificant());
01112     clampInPlace(0.0L,xadj,1.0L);
01113     return yRange*oneOverXRange*dstepUp(xadj); }
01114 
01116 inline long double d2stepUp(long double x) 
01117 {   assert(0 <= x && x <= 1);
01118     return 60*x*(1+x*(2*x-3)); }    //60x-180x^2+120x^3
01120 inline long double d2stepDown(long double x) {return -d2stepUp(x);}
01122 inline long double d2stepAny(long double yRange,
01123                              long double x0, long double oneOverXRange,
01124                              long double x) 
01125 {   long double xadj = (x-x0)*oneOverXRange;    
01126     assert(-NTraits<long double>::getSignificant() <= xadj
01127            && xadj <= 1 + NTraits<long double>::getSignificant());
01128     clampInPlace(0.0L,xadj,1.0L);
01129     return yRange*square(oneOverXRange)*d2stepUp(xadj); }
01130 
01131 
01133 inline long double d3stepUp(long double x) 
01134 {   assert(0 <= x && x <= 1);
01135     return 60+360*x*(x-1); }        //60-360*x+360*x^2
01137 inline long double d3stepDown(long double x) {return -d3stepUp(x);}
01139 inline long double d3stepAny(long double yRange,
01140                              long double x0, long double oneOverXRange,
01141                              long double x) 
01142 {   long double xadj = (x-x0)*oneOverXRange;    
01143     assert(-NTraits<long double>::getSignificant() <= xadj
01144            && xadj <= 1 + NTraits<long double>::getSignificant());
01145     clampInPlace(0.0L,xadj,1.0L);
01146     return yRange*cube(oneOverXRange)*d3stepUp(xadj); }
01147 
01148         // int converts to double; only supplied for stepUp(), stepDown()
01151 inline double stepUp(int x) {return stepUp((double)x);}
01154 inline double stepDown(int x) {return stepDown((double)x);}
01155 
01156 
01215  // Doxygen should skip this helper template function
01217 template <class T> // float or double 
01218 static inline std::pair<T,T> approxCompleteEllipticIntegralsKE_T(T m) {
01219     static const T a[] =
01220     {   (T)1.38629436112, (T)0.09666344259, (T)0.03590092383,
01221         (T)0.03742563713, (T)0.01451196212 };
01222     static const T b[] = 
01223     {   (T)0.5,           (T)0.12498593597, (T)0.06880248576,
01224         (T)0.03328355346, (T)0.00441787012 };
01225     static const T c[] =
01226     {   (T)1,             (T)0.44325141463, (T)0.06260601220,
01227         (T)0.04757383546, (T)0.01736506451 };
01228     static const T d[] =
01229     {   (T)0,             (T)0.24998368310, (T)0.09200180037,
01230         (T)0.04069697526, (T)0.00526449639 };
01231 
01232     const T SignificantReal = NTraits<T>::getSignificant();
01233     const T PiOver2         = NTraits<T>::getPi()/2;
01234     const T Infinity        = NTraits<T>::getInfinity();
01235 
01236     SimTK_ERRCHK1_ALWAYS(-SignificantReal < m && m < 1+SignificantReal,
01237         "approxCompleteEllipticIntegralsKE()", 
01238         "Argument m (%g) is outside the legal range [0,1].", (double)m);
01239     if (m >= 1) return std::make_pair(Infinity, (T)1);
01240     if (m <= 0) return std::make_pair(PiOver2, PiOver2);
01241 
01242     const T m1=1-m, m2=m1*m1, m3=m1*m2, m4=m2*m2; // 4 flops
01243     const T lnm2 = std::log(m1);  // ~50 flops
01244 
01245     // The rest is 35 flops.
01246     const T K = (a[0] + a[1]*m1 + a[2]*m2 + a[3]*m3 + a[4]*m4) 
01247          - lnm2*(b[0] + b[1]*m1 + b[2]*m2 + b[3]*m3 + b[4]*m4);
01248     const T E = (c[0] + c[1]*m1 + c[2]*m2 + c[3]*m3 + c[4]*m4) 
01249          - lnm2*(       d[1]*m1 + d[2]*m2 + d[3]*m3 + d[4]*m4);
01250 
01251     return std::make_pair(K,E);
01252 }
01291 inline std::pair<double,double> 
01292 approxCompleteEllipticIntegralsKE(double m)
01293 {   return approxCompleteEllipticIntegralsKE_T<double>(m); }
01299 inline std::pair<float,float> 
01300 approxCompleteEllipticIntegralsKE(float m)
01301 {   return approxCompleteEllipticIntegralsKE_T<float>(m); }
01308 inline std::pair<double,double> 
01309 approxCompleteEllipticIntegralsKE(int m)
01310 {   return approxCompleteEllipticIntegralsKE_T<double>((double)m); }
01311 
01312  // Doxygen should skip this template helper function
01314 template <class T> // float or double
01315 static inline std::pair<T,T> completeEllipticIntegralsKE_T(T m) {
01316     const T SignificantReal = NTraits<T>::getSignificant();
01317     const T TenEps          = 10*NTraits<T>::getEps();
01318     const T Infinity        = NTraits<T>::getInfinity();
01319     const T PiOver2         = NTraits<T>::getPi() / 2;
01320 
01321     // Allow a little slop in the argument since it may have resulted
01322     // from a numerical operation that gave 0 or 1 plus or minus
01323     // roundoff noise.
01324     SimTK_ERRCHK1_ALWAYS(-SignificantReal < m && m < 1+SignificantReal,
01325         "completeEllipticIntegralsKE()", 
01326         "Argument m (%g) is outside the legal range [0,1].", (double)m);
01327     if (m >= 1) return std::make_pair(Infinity, (T)1);
01328     if (m <= 0) return std::make_pair(PiOver2, PiOver2);
01329 
01330     const T k = std::sqrt(1-m); // ~25 flops
01331     T v1=1, w1=k, c1=1, d1=k*k; // initialize iteration
01332     do { // ~50 flops per iteration
01333         T v2 = (v1+w1)/2;
01334         T w2 = std::sqrt(v1*w1);
01335         T c2 = (c1+d1)/2;
01336         T d2 = (w1*c1+v1*d1)/(v1+w1);
01337         v1=v2; w1=w2; c1=c2; d1=d2;
01338     } while(std::abs(v1-w1) >= TenEps);
01339 
01340     const T K = PiOver2/v1; // ~20 flops
01341     const T E = K*c1;
01342 
01343     return std::make_pair(K,E);
01344 }
01371 inline std::pair<double,double> completeEllipticIntegralsKE(double m)
01372 {   return completeEllipticIntegralsKE_T<double>(m); }
01380 inline std::pair<float,float> completeEllipticIntegralsKE(float m)
01381 {   return completeEllipticIntegralsKE_T<float>(m); }
01388 inline std::pair<double,double> completeEllipticIntegralsKE(int m)
01389 {   return completeEllipticIntegralsKE_T<double>((double)m); }
01390 
01393 } // namespace SimTK
01394 
01395 #endif //SimTK_SIMMATRIX_SCALAR_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines