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 
00058 namespace SimTK {
00059 
00061     // Handy default-precision definitions //
00063 
00064 typedef conjugate<Real> Conjugate;  // like Complex
00065 
00066     // Note that these constants have memory addresses, so you can
00067     // return references to them.
00068     // These are static variables rather than static members to avoid
00069     // problems with static initialization order.
00070 
00071     // Properties of the floaing point representation.
00072 
00073 static const Real& NaN               = NTraits<Real>::getNaN();      // "not a number"
00074 static const Real& Infinity          = NTraits<Real>::getInfinity();
00075 
00076 // Epsilon is the size of roundoff noise; it is the smallest positive number
00077 // such that 1+Eps != 1.
00078 static const Real& Eps               = NTraits<Real>::getEps();         // double ~1e-16, float ~1e-7
00079 static const Real& SqrtEps           = NTraits<Real>::getSqrtEps();     // eps^(1/2): double ~1e- 8, float ~3e-4
00080 static const Real& TinyReal          = NTraits<Real>::getTiny();        // eps^(5/4): double ~1e-20, float ~1e-9
00081 static const Real& SignificantReal   = NTraits<Real>::getSignificant(); // eps^(7/8): double ~1e-14, float ~1e-6
00082 
00083 static const Real& LeastPositiveReal = NTraits<Real>::getLeastPositive(); // double ~1e-308, float ~1e-38
00084 static const Real& MostPositiveReal  = NTraits<Real>::getMostPositive();  // double ~1e+308, float ~1e+38
00085 static const Real& LeastNegativeReal = NTraits<Real>::getLeastNegative();
00086 static const Real& MostNegativeReal  = NTraits<Real>::getMostNegative();
00087 
00088 // This is the number of decimal digits that can be reliably stored and
00089 // retrieved in the default Real precision (typically log10(1/eps)-1).
00090 static const int NumDigitsReal = NTraits<Real>::getNumDigits(); // double ~15, float ~6
00091 
00092 // This is the smallest number of decimal digits you should store in a file
00093 // if you want to be able to get exactly the same bit pattern back when you
00094 // read it in. Typically, this is about log10(1/tiny).
00095 static const int LosslessNumDigitsReal = NTraits<Real>::getLosslessNumDigits(); // double ~20, float ~9
00096 
00097     // Carefully calculated constants, with convenient memory addresses.
00098 
00099 static const Real& Zero         = NTraits<Real>::getZero();
00100 static const Real& One          = NTraits<Real>::getOne();
00101 static const Real& MinusOne     = NTraits<Real>::getMinusOne();
00102 static const Real& Two          = NTraits<Real>::getTwo();
00103 static const Real& Three        = NTraits<Real>::getThree();
00104 
00105 static const Real& OneHalf      = NTraits<Real>::getOneHalf();
00106 static const Real& OneThird     = NTraits<Real>::getOneThird();
00107 static const Real& OneFourth    = NTraits<Real>::getOneFourth();
00108 static const Real& OneFifth     = NTraits<Real>::getOneFifth();
00109 static const Real& OneSixth     = NTraits<Real>::getOneSixth();
00110 static const Real& OneSeventh   = NTraits<Real>::getOneSeventh();
00111 static const Real& OneEighth    = NTraits<Real>::getOneEighth();
00112 static const Real& OneNinth     = NTraits<Real>::getOneNinth();
00113 static const Real& Pi           = NTraits<Real>::getPi();
00114 static const Real& OneOverPi    = NTraits<Real>::getOneOverPi();
00115 static const Real& E            = NTraits<Real>::getE();
00116 static const Real& Log2E        = NTraits<Real>::getLog2E();
00117 static const Real& Log10E       = NTraits<Real>::getLog10E();
00118 static const Real& Sqrt2        = NTraits<Real>::getSqrt2();
00119 static const Real& OneOverSqrt2 = NTraits<Real>::getOneOverSqrt2();  // also sqrt(2)/2
00120 static const Real& Sqrt3        = NTraits<Real>::getSqrt3();
00121 static const Real& OneOverSqrt3 = NTraits<Real>::getOneOverSqrt3();
00122 static const Real& CubeRoot2    = NTraits<Real>::getCubeRoot2();
00123 static const Real& CubeRoot3    = NTraits<Real>::getCubeRoot3();
00124 static const Real& Ln2          = NTraits<Real>::getLn2();
00125 static const Real& Ln10         = NTraits<Real>::getLn10();
00126 
00127 // We only need one complex constant. For the rest just use
00128 // Complex(the Real constant), or if you need an address use
00129 // NTraits<Complex>::getPi(), etc.
00130 static const Complex& I = NTraits<Complex>::getI();
00131 
00132 
00134     // SOME SCALAR UTILITIES //
00136 
00137 
00151 // We use the trick that v & v-1 returns the value that is v with its
00152 // rightmost bit cleared (if it has a rightmost bit set).
00153 inline bool atMostOneBitIsSet(unsigned char v)      {return (v&v-1)==0;}
00154 inline bool atMostOneBitIsSet(unsigned short v)     {return (v&v-1)==0;}
00155 inline bool atMostOneBitIsSet(unsigned int v)       {return (v&v-1)==0;}
00156 inline bool atMostOneBitIsSet(unsigned long v)      {return (v&v-1)==0;}
00157 inline bool atMostOneBitIsSet(unsigned long long v) {return (v&v-1)==0;}
00158 inline bool atMostOneBitIsSet(signed char v)        {return (v&v-1)==0;}
00159 inline bool atMostOneBitIsSet(char v)               {return (v&v-1)==0;}
00160 inline bool atMostOneBitIsSet(short v)              {return (v&v-1)==0;}
00161 inline bool atMostOneBitIsSet(int v)                {return (v&v-1)==0;}
00162 inline bool atMostOneBitIsSet(long v)               {return (v&v-1)==0;}
00163 inline bool atMostOneBitIsSet(long long v)          {return (v&v-1)==0;}
00165 
00180 inline bool exactlyOneBitIsSet(unsigned char v)      {return v && atMostOneBitIsSet(v);}
00181 inline bool exactlyOneBitIsSet(unsigned short v)     {return v && atMostOneBitIsSet(v);}
00182 inline bool exactlyOneBitIsSet(unsigned int v)       {return v && atMostOneBitIsSet(v);}
00183 inline bool exactlyOneBitIsSet(unsigned long v)      {return v && atMostOneBitIsSet(v);}
00184 inline bool exactlyOneBitIsSet(unsigned long long v) {return v && atMostOneBitIsSet(v);}
00185 inline bool exactlyOneBitIsSet(signed char v)        {return v && atMostOneBitIsSet(v);}
00186 inline bool exactlyOneBitIsSet(char v)               {return v && atMostOneBitIsSet(v);}
00187 inline bool exactlyOneBitIsSet(short v)              {return v && atMostOneBitIsSet(v);}
00188 inline bool exactlyOneBitIsSet(int v)                {return v && atMostOneBitIsSet(v);}
00189 inline bool exactlyOneBitIsSet(long v)               {return v && atMostOneBitIsSet(v);}
00190 inline bool exactlyOneBitIsSet(long long v)          {return v && atMostOneBitIsSet(v);}
00192 
00219 
00220 inline bool signBit(unsigned char i)      {return false;}
00221 inline bool signBit(unsigned short i)     {return false;}
00222 inline bool signBit(unsigned int i)       {return false;}
00223 inline bool signBit(unsigned long i)      {return false;}
00224 inline bool signBit(unsigned long long i) {return false;}
00225 
00226 // Note that plain 'char' type is not overloaded -- see above.
00227 
00228 // We're assuming sizeof(char)==1, short==2, int==4, long long==8 which is safe
00229 // for all our anticipated platforms. But some 64 bit implementations have
00230 // sizeof(long)==4 while others have sizeof(long)==8 so we'll use the ANSI
00231 // standard value LONG_MIN which is a long value with just the high bit set.
00232 // (We're assuming two's complement integers here; I haven't seen anything
00233 // else in decades.)
00234 inline bool signBit(signed char i) {return ((unsigned char)i      & 0x80U) != 0;}
00235 inline bool signBit(short       i) {return ((unsigned short)i     & 0x8000U) != 0;}
00236 inline bool signBit(int         i) {return ((unsigned int)i       & 0x80000000U) != 0;}
00237 inline bool signBit(long long   i) {return ((unsigned long long)i & 0x8000000000000000ULL) != 0;}
00238 
00239 inline bool signBit(long        i) {return ((unsigned long)i
00240                                             & (unsigned long)LONG_MIN) != 0;}
00241 
00242 inline bool signBit(const float&  f) {return std::signbit(f);}
00243 inline bool signBit(const double& d) {return std::signbit(d);}
00244 inline bool signBit(const negator<float>&  nf) {return std::signbit(-nf);} // !!
00245 inline bool signBit(const negator<double>& nd) {return std::signbit(-nd);} // !!
00246 
00261 inline unsigned int sign(unsigned char      u) {return u==0 ? 0 : 1;}
00262 inline unsigned int sign(unsigned short     u) {return u==0 ? 0 : 1;}
00263 inline unsigned int sign(unsigned int       u) {return u==0 ? 0 : 1;}
00264 inline unsigned int sign(unsigned long      u) {return u==0 ? 0 : 1;}
00265 inline unsigned int sign(unsigned long long u) {return u==0 ? 0 : 1;}
00266 
00267 // Don't overload for plain "char" because it may be signed or unsigned
00268 // depending on the compiler.
00269 
00270 inline int sign(signed char i) {return i>0 ? 1 : (i<0 ? -1 : 0);}
00271 inline int sign(short       i) {return i>0 ? 1 : (i<0 ? -1 : 0);}
00272 inline int sign(int         i) {return i>0 ? 1 : (i<0 ? -1 : 0);}
00273 inline int sign(long        i) {return i>0 ? 1 : (i<0 ? -1 : 0);}
00274 inline int sign(long long   i) {return i>0 ? 1 : (i<0 ? -1 : 0);}
00275 
00276 inline int sign(const float&       x) {return x>0 ? 1 : (x<0 ? -1 : 0);}
00277 inline int sign(const double&      x) {return x>0 ? 1 : (x<0 ? -1 : 0);}
00278 inline int sign(const long double& x) {return x>0 ? 1 : (x<0 ? -1 : 0);}
00279 
00280 inline int sign(const negator<float>&       x) {return -sign(-x);} // -x is free
00281 inline int sign(const negator<double>&      x) {return -sign(-x);}
00282 inline int sign(const negator<long double>& x) {return -sign(-x);}
00284 
00301 inline unsigned char  square(unsigned char  u) {return u*u;}
00302 inline unsigned short square(unsigned short u) {return u*u;}
00303 inline unsigned int   square(unsigned int   u) {return u*u;}
00304 inline unsigned long  square(unsigned long  u) {return u*u;}
00305 
00306 inline char        square(char c) {return c*c;}
00307 
00308 inline signed char square(signed char i) {return i*i;}
00309 inline short       square(short       i) {return i*i;}
00310 inline int         square(int         i) {return i*i;}
00311 inline long        square(long        i) {return i*i;}
00312 
00313 inline float       square(const float&       x) {return x*x;}
00314 inline double      square(const double&      x) {return x*x;}
00315 inline long double square(const long double& x) {return x*x;}
00316 
00317 // Negation is free for negators, so we can square them and clean
00318 // them up at the same time at no extra cost.
00319 inline float       square(const negator<float>&       x) {return square(-x);}
00320 inline double      square(const negator<double>&      x) {return square(-x);}
00321 inline long double square(const negator<long double>& x) {return square(-x);}
00322 
00323 // It is safer to templatize using complex classes, and doesn't make
00324 // debugging any worse since complex is already templatized. 
00325 // 5 flops vs. 6 for general complex multiply.
00326 template <class P> inline 
00327 std::complex<P> square(const std::complex<P>& x) {
00328     const P re=x.real(), im=x.imag();
00329     return std::complex<P>(re*re-im*im, 2*re*im);
00330 }
00331 
00332 // We can square a conjugate and clean it up back to complex at
00333 // the same time at zero cost (or maybe 1 negation depending
00334 // on how the compiler handles the "-2" below).
00335 template <class P> inline 
00336 std::complex<P> square(const conjugate<P>& x) {
00337     const P re=x.real(), nim=x.negImag();
00338     return std::complex<P>(re*re-nim*nim, -2*re*nim);
00339 }
00340 
00341 template <class P> inline
00342 std::complex<P> square(const negator< std::complex<P> >& x) {
00343     return square(-x); // negation is free for negators
00344 }
00345 
00346 // Note return type here after squaring negator<conjugate>
00347 // is complex, not conjugate.
00348 template <class P> inline
00349 std::complex<P> square(const negator< conjugate<P> >& x) {
00350     return square(-x); // negation is free for negators
00351 }
00353 
00372 inline unsigned char  cube(unsigned char  u) {return u*u*u;}
00373 inline unsigned short cube(unsigned short u) {return u*u*u;}
00374 inline unsigned int   cube(unsigned int   u) {return u*u*u;}
00375 inline unsigned long  cube(unsigned long  u) {return u*u*u;}
00376 
00377 inline char        cube(char c) {return c*c*c;}
00378 
00379 inline signed char cube(signed char i) {return i*i*i;}
00380 inline short       cube(short       i) {return i*i*i;}
00381 inline int         cube(int         i) {return i*i*i;}
00382 inline long        cube(long        i) {return i*i*i;}
00383 
00384 inline float       cube(const float&       x) {return x*x*x;}
00385 inline double      cube(const double&      x) {return x*x*x;}
00386 inline long double cube(const long double& x) {return x*x*x;}
00387 
00388 // To keep this cheap we'll defer getting rid of the negator<> until
00389 // some other operation. We cube -x and then recast that to negator<>
00390 // on return, for a total cost of 2 flops.
00391 inline negator<float> cube(const negator<float>& x) {
00392     return negator<float>::recast(cube(-x));
00393 }
00394 inline negator<double> cube(const negator<double>& x) {
00395     return negator<double>::recast(cube(-x));
00396 }
00397 inline negator<long double> cube(const negator<long double>& x) {
00398     return negator<long double>::recast(cube(-x));
00399 }
00400 
00401 // Cubing a complex this way is cheaper than doing it by
00402 // multiplication. Cost here is 8 flops vs. 11 for a square
00403 // followed by a multiply.
00404 template <class P> inline
00405 std::complex<P> cube(const std::complex<P>& x) {
00406     const P re=x.real(), im=x.imag(), rr=re*re, ii=im*im;
00407     return std::complex<P>(re*(rr-3*ii), im*(3*rr-ii));
00408 }
00409 
00410 // Cubing a negated complex allows us to cube and eliminate the
00411 // negator at the same time for zero extra cost. Compare the 
00412 // expressions here to the normal cube above to see the free
00413 // sign changes in both parts. 8 flops here.
00414 template <class P> inline
00415 std::complex<P> cube(const negator< std::complex<P> >& x) {
00416     // -x is free for a negator
00417     const P nre=(-x).real(), nim=(-x).imag(), rr=nre*nre, ii=nim*nim;
00418     return std::complex<P>(nre*(3*ii-rr), nim*(ii-3*rr));
00419 }
00420 
00421 // Cubing a conjugate this way saves a lot over multiplying, and
00422 // also lets us convert the result to complex for free.
00423 template <class P> inline
00424 std::complex<P> cube(const conjugate<P>& x) {
00425     const P re=x.real(), nim=x.negImag(), rr=re*re, ii=nim*nim;
00426     return std::complex<P>(re*(rr-3*ii), nim*(ii-3*rr));
00427 }
00428 
00429 
00430 // Cubing a negated conjugate this way saves a lot over multiplying, and
00431 // also lets us convert the result to non-negated complex for free.
00432 template <class P> inline
00433 std::complex<P> cube(const negator< conjugate<P> >& x) {
00434     // -x is free for a negator
00435     const P nre=(-x).real(), im=(-x).negImag(), rr=nre*nre, ii=im*im;
00436     return std::complex<P>(nre*(3*ii-rr), im*(3*rr-ii));
00437 }
00439 
00471 
00487 inline double& clampInPlace(double low, double& v, double high) 
00488 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00490 inline float& clampInPlace(float low, float& v, float high) 
00491 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00493 inline long double& clampInPlace(long double low, long double& v, long double high) 
00494 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00495 
00496     // Floating point clamps with integer bounds; without these
00497     // explicit casts are required.
00498 
00501 inline double& clampInPlace(int low, double& v, int high) 
00502 {   return clampInPlace((double)low,v,(double)high); }
00505 inline float& clampInPlace(int low, float& v, int high) 
00506 {   return clampInPlace((float)low,v,(float)high); }
00509 inline long double& clampInPlace(int low, long double& v, int high) 
00510 {   return clampInPlace((long double)low,v,(long double)high); }
00511 
00514 inline double& clampInPlace(int low, double& v, double high) 
00515 {   return clampInPlace((double)low,v,high); }
00518 inline float& clampInPlace(int low, float& v, float high) 
00519 {   return clampInPlace((float)low,v,high); }
00522 inline long double& clampInPlace(int low, long double& v, long double high) 
00523 {   return clampInPlace((long double)low,v,high); }
00524 
00527 inline double& clampInPlace(double low, double& v, int high) 
00528 {   return clampInPlace(low,v,(double)high); }
00531 inline float& clampInPlace(float low, float& v, int high) 
00532 {   return clampInPlace(low,v,(float)high); }
00535 inline long double& clampInPlace(long double low, long double& v, int high) 
00536 {   return clampInPlace(low,v,(long double)high); }
00537 
00539 inline unsigned char& clampInPlace(unsigned char low, unsigned char& v, unsigned char high) 
00540 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00542 inline unsigned short& clampInPlace(unsigned short low, unsigned short& v, unsigned short high) 
00543 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00545 inline unsigned int& clampInPlace(unsigned int low, unsigned int& v, unsigned int high) 
00546 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00548 inline unsigned long& clampInPlace(unsigned long low, unsigned long& v, unsigned long high) 
00549 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00551 inline unsigned long long& clampInPlace(unsigned long long low, unsigned long long& v, unsigned long long high) 
00552 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00553 
00555 inline char& clampInPlace(char low, char& v, char high) 
00556 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00558 inline signed char& clampInPlace(signed char low, signed char& v, signed char high) 
00559 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00560 
00562 inline short& clampInPlace(short low, short& v, short high) 
00563 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00565 inline int& clampInPlace(int low, int& v, int high) 
00566 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00568 inline long& clampInPlace(long low, long& v, long high) 
00569 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00571 inline long long& clampInPlace(long long low, long long& v, long long high) 
00572 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00573 
00575 inline negator<float>& clampInPlace(float low, negator<float>& v, float high) 
00576 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00578 inline negator<double>& clampInPlace(double low, negator<double>& v, double high) 
00579 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00581 inline negator<long double>& clampInPlace(long double low, negator<long double>& v, long double high) 
00582 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00583 
00584 
00585 
00606 inline double clamp(double low, double v, double high) 
00607 {   return clampInPlace(low,v,high); }
00609 inline float clamp(float low, float v, float high) 
00610 {   return clampInPlace(low,v,high); }
00612 inline long double clamp(long double low, long double v, long double high) 
00613 {   return clampInPlace(low,v,high); }
00614 
00617 inline double clamp(int low, double v, int high) 
00618 {   return clampInPlace(low,v,high); }
00621 inline float clamp(int low, float v, int high) 
00622 {   return clampInPlace(low,v,high); }
00625 inline long double clamp(int low, long double v, int high) 
00626 {   return clampInPlace(low,v,high); }
00627 
00630 inline double clamp(int low, double v, double high) 
00631 {   return clampInPlace(low,v,high); }
00634 inline float clamp(int low, float v, float high) 
00635 {   return clampInPlace(low,v,high); }
00638 inline long double clamp(int low, long double v, long double high) 
00639 {   return clampInPlace(low,v,high); }
00640 
00643 inline double clamp(double low, double v, int high) 
00644 {   return clampInPlace(low,v,high); }
00647 inline float clamp(float low, float v, int high) 
00648 {   return clampInPlace(low,v,high); }
00651 inline long double clamp(long double low, long double v, int high) 
00652 {   return clampInPlace(low,v,high); }
00653 
00655 inline unsigned char clamp(unsigned char low, unsigned char v, unsigned char high) 
00656 {   return clampInPlace(low,v,high); }
00658 inline unsigned short clamp(unsigned short low, unsigned short v, unsigned short high) 
00659 {   return clampInPlace(low,v,high); }
00661 inline unsigned int clamp(unsigned int low, unsigned int v, unsigned int high) 
00662 {   return clampInPlace(low,v,high); }
00664 inline unsigned long clamp(unsigned long low, unsigned long v, unsigned long high) 
00665 {   return clampInPlace(low,v,high); }
00667 inline unsigned long long clamp(unsigned long long low, unsigned long long v, unsigned long long high) 
00668 {   return clampInPlace(low,v,high); }
00669 
00671 inline char clamp(char low, char v, char high) 
00672 {   return clampInPlace(low,v,high); }
00674 inline signed char clamp(signed char low, signed char v, signed char high) 
00675 {   return clampInPlace(low,v,high); }
00676 
00678 inline short clamp(short low, short v, short high) 
00679 {   return clampInPlace(low,v,high); }
00681 inline int clamp(int low, int v, int high) 
00682 {   return clampInPlace(low,v,high); }
00684 inline long clamp(long low, long v, long high) 
00685 {   return clampInPlace(low,v,high); }
00687 inline long long clamp(long long low, long long v, long long high) 
00688 {   return clampInPlace(low,v,high); }
00689 
00690 
00691 // These aren't strictly necessary but are here to help the
00692 // compiler find the right overload to call. These cost an
00693 // extra flop because the negator<T> has to be cast to T which
00694 // requires that the pending negation be performed. Note that
00695 // the result types are not negated.
00696 
00701 inline float clamp(float low, negator<float> v, float high)
00702 {   return clamp(low,(float)v,high); }
00707 inline double clamp(double low, negator<double> v, double high) 
00708 {   return clamp(low,(double)v,high); }
00713 inline long double clamp(long double low, negator<long double> v, long double high) 
00714 {   return clamp(low,(long double)v,high); }
00755 
00770 inline double stepUp(double x)
00771 {   assert(0 <= x && x <= 1);
00772     return x*x*x*(10+x*(6*x-15)); }  //10x^3-15x^4+6x^5
00773 
00774 
00789 inline double stepDown(double x) {return 1.0 -stepUp(x);}
00790 
00791 
00866 inline double stepAny(double y0, double yRange,
00867                       double x0, double oneOverXRange,
00868                       double x) 
00869 {   double xadj = (x-x0)*oneOverXRange;    
00870     assert(-NTraits<double>::getSignificant() <= xadj
00871            && xadj <= 1 + NTraits<double>::getSignificant());
00872     clampInPlace(0.0,xadj,1.0);
00873     return y0 + yRange*stepUp(xadj); }
00874 
00878 inline double dstepUp(double x) {
00879     assert(0 <= x && x <= 1);
00880     const double xxm1=x*(x-1);
00881     return 30*xxm1*xxm1;        //30x^2-60x^3+30x^4
00882 }
00883 
00887 inline double dstepDown(double x) {return -dstepUp(x);}
00888 
00892 inline double dstepAny(double yRange,
00893                        double x0, double oneOverXRange,
00894                        double x) 
00895 {   double xadj = (x-x0)*oneOverXRange;    
00896     assert(-NTraits<double>::getSignificant() <= xadj
00897            && xadj <= 1 + NTraits<double>::getSignificant());
00898     clampInPlace(0.0,xadj,1.0);
00899     return yRange*oneOverXRange*dstepUp(xadj); }
00900 
00904 inline double d2stepUp(double x) {
00905     assert(0 <= x && x <= 1);
00906     return 60*x*(1+x*(2*x-3));  //60x-180x^2+120x^3
00907 }
00908 
00912 inline double d2stepDown(double x) {return -d2stepUp(x);}
00913 
00917 inline double d2stepAny(double yRange,
00918                         double x0, double oneOverXRange,
00919                         double x) 
00920 {   double xadj = (x-x0)*oneOverXRange;    
00921     assert(-NTraits<double>::getSignificant() <= xadj
00922            && xadj <= 1 + NTraits<double>::getSignificant());
00923     clampInPlace(0.0,xadj,1.0);
00924     return yRange*square(oneOverXRange)*d2stepUp(xadj); }
00925 
00929 inline double d3stepUp(double x) {
00930     assert(0 <= x && x <= 1);
00931     return 60+360*x*(x-1);      //60-360*x+360*x^2
00932 }
00933 
00937 inline double d3stepDown(double x) {return -d3stepUp(x);}
00938 
00942 inline double d3stepAny(double yRange,
00943                         double x0, double oneOverXRange,
00944                         double x) 
00945 {   double xadj = (x-x0)*oneOverXRange;    
00946     assert(-NTraits<double>::getSignificant() <= xadj
00947            && xadj <= 1 + NTraits<double>::getSignificant());
00948     clampInPlace(0.0,xadj,1.0);
00949     return yRange*cube(oneOverXRange)*d3stepUp(xadj); }
00950 
00951             // float
00952 
00954 inline float stepUp(float x) 
00955 {   assert(0 <= x && x <= 1);
00956     return x*x*x*(10+x*(6*x-15)); }  //10x^3-15x^4+6x^5
00958 inline float stepDown(float x) {return 1.0f-stepUp(x);}
00960 inline float stepAny(float y0, float yRange,
00961                      float x0, float oneOverXRange,
00962                      float x) 
00963 {   float xadj = (x-x0)*oneOverXRange;    
00964     assert(-NTraits<float>::getSignificant() <= xadj
00965            && xadj <= 1 + NTraits<float>::getSignificant());
00966     clampInPlace(0.0f,xadj,1.0f);
00967     return y0 + yRange*stepUp(xadj); }
00968 
00970 inline float dstepUp(float x) 
00971 {   assert(0 <= x && x <= 1);
00972     const float xxm1=x*(x-1);
00973     return 30*xxm1*xxm1; }  //30x^2-60x^3+30x^4
00975 inline float dstepDown(float x) {return -dstepUp(x);}
00977 inline float dstepAny(float yRange,
00978                       float x0, float oneOverXRange,
00979                       float x) 
00980 {   float xadj = (x-x0)*oneOverXRange;    
00981     assert(-NTraits<float>::getSignificant() <= xadj
00982            && xadj <= 1 + NTraits<float>::getSignificant());
00983     clampInPlace(0.0f,xadj,1.0f);
00984     return yRange*oneOverXRange*dstepUp(xadj); }
00985 
00987 inline float d2stepUp(float x) 
00988 {   assert(0 <= x && x <= 1);
00989     return 60*x*(1+x*(2*x-3)); }    //60x-180x^2+120x^3
00991 inline float d2stepDown(float x) {return -d2stepUp(x);}
00993 inline float d2stepAny(float yRange,
00994                        float x0, float oneOverXRange,
00995                        float x) 
00996 {   float xadj = (x-x0)*oneOverXRange;    
00997     assert(-NTraits<float>::getSignificant() <= xadj
00998            && xadj <= 1 + NTraits<float>::getSignificant());
00999     clampInPlace(0.0f,xadj,1.0f);
01000     return yRange*square(oneOverXRange)*d2stepUp(xadj); }
01001 
01003 inline float d3stepUp(float x) 
01004 {   assert(0 <= x && x <= 1);
01005     return 60+360*x*(x-1); }    //60-360*x+360*x^2
01007 inline float d3stepDown(float x) {return -d3stepUp(x);}
01009 inline float d3stepAny(float yRange,
01010                        float x0, float oneOverXRange,
01011                        float x) 
01012 {   float xadj = (x-x0)*oneOverXRange;    
01013     assert(-NTraits<float>::getSignificant() <= xadj
01014            && xadj <= 1 + NTraits<float>::getSignificant());
01015     clampInPlace(0.0f,xadj,1.0f);
01016     return yRange*cube(oneOverXRange)*d3stepUp(xadj); }
01017 
01018             // long double
01019 
01021 inline long double stepUp(long double x) 
01022 {   assert(0 <= x && x <= 1);
01023     return x*x*x*(10+x*(6*x-15)); }  //10x^3-15x^4+6x^5
01025 inline long double stepDown(long double x) {return 1.0L-stepUp(x);}
01027 inline long double stepAny(long double y0, long double yRange,
01028                            long double x0, long double oneOverXRange,
01029                            long double x) 
01030 {   long double xadj = (x-x0)*oneOverXRange;    
01031     assert(-NTraits<long double>::getSignificant() <= xadj
01032            && xadj <= 1 + NTraits<long double>::getSignificant());
01033     clampInPlace(0.0L,xadj,1.0L);
01034     return y0 + yRange*stepUp(xadj); }
01035 
01036 
01038 inline long double dstepUp(long double x) 
01039 {   assert(0 <= x && x <= 1);
01040     const long double xxm1=x*(x-1);
01041     return 30*xxm1*xxm1; }          //30x^2-60x^3+30x^4
01043 inline long double dstepDown(long double x) {return -dstepUp(x);}
01045 inline long double dstepAny(long double yRange,
01046                             long double x0, long double oneOverXRange,
01047                             long double x) 
01048 {   long double xadj = (x-x0)*oneOverXRange;    
01049     assert(-NTraits<long double>::getSignificant() <= xadj
01050            && xadj <= 1 + NTraits<long double>::getSignificant());
01051     clampInPlace(0.0L,xadj,1.0L);
01052     return yRange*oneOverXRange*dstepUp(xadj); }
01053 
01055 inline long double d2stepUp(long double x) 
01056 {   assert(0 <= x && x <= 1);
01057     return 60*x*(1+x*(2*x-3)); }    //60x-180x^2+120x^3
01059 inline long double d2stepDown(long double x) {return -d2stepUp(x);}
01061 inline long double d2stepAny(long double yRange,
01062                              long double x0, long double oneOverXRange,
01063                              long double x) 
01064 {   long double xadj = (x-x0)*oneOverXRange;    
01065     assert(-NTraits<long double>::getSignificant() <= xadj
01066            && xadj <= 1 + NTraits<long double>::getSignificant());
01067     clampInPlace(0.0L,xadj,1.0L);
01068     return yRange*square(oneOverXRange)*d2stepUp(xadj); }
01069 
01070 
01072 inline long double d3stepUp(long double x) 
01073 {   assert(0 <= x && x <= 1);
01074     return 60+360*x*(x-1); }        //60-360*x+360*x^2
01076 inline long double d3stepDown(long double x) {return -d3stepUp(x);}
01078 inline long double d3stepAny(long double yRange,
01079                              long double x0, long double oneOverXRange,
01080                              long double x) 
01081 {   long double xadj = (x-x0)*oneOverXRange;    
01082     assert(-NTraits<long double>::getSignificant() <= xadj
01083            && xadj <= 1 + NTraits<long double>::getSignificant());
01084     clampInPlace(0.0L,xadj,1.0L);
01085     return yRange*cube(oneOverXRange)*d3stepUp(xadj); }
01086 
01087         // int converts to double; only supplied for stepUp(), stepDown()
01090 inline double stepUp(int x) {return stepUp((double)x);}
01093 inline double stepDown(int x) {return stepDown((double)x);}
01094 
01095 
01098 } // namespace SimTK
01099 
01100 #endif //SimTK_SIMMATRIX_SCALAR_H_

Generated on Thu Aug 12 16:37:14 2010 for SimTKcore by  doxygen 1.6.1