Simbody  3.4 (development)
Scalar.h
Go to the documentation of this file.
00001 #ifndef SimTK_SIMMATRIX_SCALAR_H_
00002 #define SimTK_SIMMATRIX_SCALAR_H_
00003 
00004 /* -------------------------------------------------------------------------- *
00005  *                       Simbody(tm): SimTKcommon                             *
00006  * -------------------------------------------------------------------------- *
00007  * This is part of the SimTK 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/home/simbody.  *
00011  *                                                                            *
00012  * Portions copyright (c) 2005-12 Stanford University and the Authors.        *
00013  * Authors: Michael Sherman                                                   *
00014  * Contributors:                                                              *
00015  *                                                                            *
00016  * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
00017  * not use this file except in compliance with the License. You may obtain a  *
00018  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
00019  *                                                                            *
00020  * Unless required by applicable law or agreed to in writing, software        *
00021  * distributed under the License is distributed on an "AS IS" BASIS,          *
00022  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
00023  * See the License for the specific language governing permissions and        *
00024  * limitations under the License.                                             *
00025  * -------------------------------------------------------------------------- */
00026 
00033 #include "SimTKcommon/internal/common.h"
00034 #include "SimTKcommon/Constants.h"
00035 #include "SimTKcommon/internal/Exception.h"
00036 #include "SimTKcommon/internal/ExceptionMacros.h"
00037 #include "SimTKcommon/internal/String.h"
00038 #include "SimTKcommon/internal/Array.h"
00039 
00040 #include "SimTKcommon/internal/conjugate.h"
00041 #include "SimTKcommon/internal/CompositeNumericalTypes.h"
00042 #include "SimTKcommon/internal/NTraits.h"
00043 #include "SimTKcommon/internal/negator.h"
00044 
00045 #include <complex>
00046 #include <cmath>
00047 #include <climits>
00048 #include <cassert>
00049 #include <utility>
00050 
00051 namespace SimTK {
00052 
00054     // Handy default-precision definitions //
00056 
00057 typedef conjugate<Real> Conjugate;  // like Complex
00058 
00091 extern SimTK_SimTKCOMMON_EXPORT const Real NaN; 
00095 extern SimTK_SimTKCOMMON_EXPORT const Real Infinity;
00096 
00100 extern SimTK_SimTKCOMMON_EXPORT const Real Eps;
00104 extern SimTK_SimTKCOMMON_EXPORT const Real SqrtEps;
00110 extern SimTK_SimTKCOMMON_EXPORT const Real TinyReal; 
00115 extern SimTK_SimTKCOMMON_EXPORT const Real SignificantReal; 
00116 
00119 extern SimTK_SimTKCOMMON_EXPORT const Real LeastPositiveReal; 
00123 extern SimTK_SimTKCOMMON_EXPORT const Real MostPositiveReal;  
00126 extern SimTK_SimTKCOMMON_EXPORT const Real LeastNegativeReal;
00130 extern SimTK_SimTKCOMMON_EXPORT const Real MostNegativeReal;
00131 
00135 extern SimTK_SimTKCOMMON_EXPORT const int NumDigitsReal; 
00136 
00142 extern SimTK_SimTKCOMMON_EXPORT const int LosslessNumDigitsReal; // double ~20, 
00143                                                                  // float ~9
00144 
00145     // Carefully calculated constants, with convenient memory addresses.
00146 
00147 extern SimTK_SimTKCOMMON_EXPORT const Real Zero;        
00148 extern SimTK_SimTKCOMMON_EXPORT const Real One;         
00149 extern SimTK_SimTKCOMMON_EXPORT const Real MinusOne;    
00150 extern SimTK_SimTKCOMMON_EXPORT const Real Two;         
00151 extern SimTK_SimTKCOMMON_EXPORT const Real Three;       
00152 
00153 extern SimTK_SimTKCOMMON_EXPORT const Real OneHalf;     
00154 extern SimTK_SimTKCOMMON_EXPORT const Real OneThird;    
00155 extern SimTK_SimTKCOMMON_EXPORT const Real OneFourth;   
00156 extern SimTK_SimTKCOMMON_EXPORT const Real OneFifth;    
00157 extern SimTK_SimTKCOMMON_EXPORT const Real OneSixth;    
00158 extern SimTK_SimTKCOMMON_EXPORT const Real OneSeventh;  
00159 extern SimTK_SimTKCOMMON_EXPORT const Real OneEighth;   
00160 extern SimTK_SimTKCOMMON_EXPORT const Real OneNinth;    
00161 extern SimTK_SimTKCOMMON_EXPORT const Real Pi;          
00162 extern SimTK_SimTKCOMMON_EXPORT const Real OneOverPi;   
00163 extern SimTK_SimTKCOMMON_EXPORT const Real E;           
00164 extern SimTK_SimTKCOMMON_EXPORT const Real Log2E;       
00165 extern SimTK_SimTKCOMMON_EXPORT const Real Log10E;      
00166 extern SimTK_SimTKCOMMON_EXPORT const Real Sqrt2;       
00167 extern SimTK_SimTKCOMMON_EXPORT const Real OneOverSqrt2;
00168 extern SimTK_SimTKCOMMON_EXPORT const Real Sqrt3;       
00169 extern SimTK_SimTKCOMMON_EXPORT const Real OneOverSqrt3;
00170 extern SimTK_SimTKCOMMON_EXPORT const Real CubeRoot2;   
00171 extern SimTK_SimTKCOMMON_EXPORT const Real CubeRoot3;   
00172 extern SimTK_SimTKCOMMON_EXPORT const Real Ln2;         
00173 extern SimTK_SimTKCOMMON_EXPORT const Real Ln10;        
00174        
00180 extern SimTK_SimTKCOMMON_EXPORT const Complex I;
00183 
00184     // SOME SCALAR UTILITIES //
00186 
00187 
00201 // We use the trick that v & v-1 returns the value that is v with its
00202 // rightmost bit cleared (if it has a rightmost bit set).
00203 inline bool atMostOneBitIsSet(unsigned char v)      {return (v&(v-1))==0;}
00204 inline bool atMostOneBitIsSet(unsigned short v)     {return (v&(v-1))==0;}
00205 inline bool atMostOneBitIsSet(unsigned int v)       {return (v&(v-1))==0;}
00206 inline bool atMostOneBitIsSet(unsigned long v)      {return (v&(v-1))==0;}
00207 inline bool atMostOneBitIsSet(unsigned long long v) {return (v&(v-1))==0;}
00208 inline bool atMostOneBitIsSet(signed char v)        {return (v&(v-1))==0;}
00209 inline bool atMostOneBitIsSet(char v)               {return (v&(v-1))==0;}
00210 inline bool atMostOneBitIsSet(short v)              {return (v&(v-1))==0;}
00211 inline bool atMostOneBitIsSet(int v)                {return (v&(v-1))==0;}
00212 inline bool atMostOneBitIsSet(long v)               {return (v&(v-1))==0;}
00213 inline bool atMostOneBitIsSet(long long v)          {return (v&(v-1))==0;}
00215 
00230 inline bool exactlyOneBitIsSet(unsigned char v)      {return v && atMostOneBitIsSet(v);}
00231 inline bool exactlyOneBitIsSet(unsigned short v)     {return v && atMostOneBitIsSet(v);}
00232 inline bool exactlyOneBitIsSet(unsigned int v)       {return v && atMostOneBitIsSet(v);}
00233 inline bool exactlyOneBitIsSet(unsigned long v)      {return v && atMostOneBitIsSet(v);}
00234 inline bool exactlyOneBitIsSet(unsigned long long v) {return v && atMostOneBitIsSet(v);}
00235 inline bool exactlyOneBitIsSet(signed char v)        {return v && atMostOneBitIsSet(v);}
00236 inline bool exactlyOneBitIsSet(char v)               {return v && atMostOneBitIsSet(v);}
00237 inline bool exactlyOneBitIsSet(short v)              {return v && atMostOneBitIsSet(v);}
00238 inline bool exactlyOneBitIsSet(int v)                {return v && atMostOneBitIsSet(v);}
00239 inline bool exactlyOneBitIsSet(long v)               {return v && atMostOneBitIsSet(v);}
00240 inline bool exactlyOneBitIsSet(long long v)          {return v && atMostOneBitIsSet(v);}
00242 
00269 
00270 inline bool signBit(unsigned char u)      {return false;}
00271 inline bool signBit(unsigned short u)     {return false;}
00272 inline bool signBit(unsigned int u)       {return false;}
00273 inline bool signBit(unsigned long u)      {return false;}
00274 inline bool signBit(unsigned long long u) {return false;}
00275 
00276 // Note that plain 'char' type is not overloaded -- see above.
00277 
00278 // We're assuming sizeof(char)==1, short==2, int==4, long long==8 which is safe
00279 // for all our anticipated platforms. But some 64 bit implementations have
00280 // sizeof(long)==4 while others have sizeof(long)==8 so we'll use the ANSI
00281 // standard value LONG_MIN which is a long value with just the high bit set.
00282 // (We're assuming two's complement integers here; I haven't seen anything
00283 // else in decades.)
00284 inline bool signBit(signed char i) {return ((unsigned char)i      & 0x80U) != 0;}
00285 inline bool signBit(short       i) {return ((unsigned short)i     & 0x8000U) != 0;}
00286 inline bool signBit(int         i) {return ((unsigned int)i       & 0x80000000U) != 0;}
00287 inline bool signBit(long long   i) {return ((unsigned long long)i & 0x8000000000000000ULL) != 0;}
00288 
00289 inline bool signBit(long        i) {return ((unsigned long)i
00290                                             & (unsigned long)LONG_MIN) != 0;}
00291 
00292 inline bool signBit(const float&  f) {return std::signbit(f);}
00293 inline bool signBit(const double& d) {return std::signbit(d);}
00294 inline bool signBit(const negator<float>&  nf) {return std::signbit(-nf);} // !!
00295 inline bool signBit(const negator<double>& nd) {return std::signbit(-nd);} // !!
00296 
00311 inline unsigned int sign(unsigned char      u) {return u==0 ? 0 : 1;}
00312 inline unsigned int sign(unsigned short     u) {return u==0 ? 0 : 1;}
00313 inline unsigned int sign(unsigned int       u) {return u==0 ? 0 : 1;}
00314 inline unsigned int sign(unsigned long      u) {return u==0 ? 0 : 1;}
00315 inline unsigned int sign(unsigned long long u) {return u==0 ? 0 : 1;}
00316 
00317 // Don't overload for plain "char" because it may be signed or unsigned
00318 // depending on the compiler.
00319 
00320 inline int sign(signed char i) {return i>0 ? 1 : (i<0 ? -1 : 0);}
00321 inline int sign(short       i) {return i>0 ? 1 : (i<0 ? -1 : 0);}
00322 inline int sign(int         i) {return i>0 ? 1 : (i<0 ? -1 : 0);}
00323 inline int sign(long        i) {return i>0 ? 1 : (i<0 ? -1 : 0);}
00324 inline int sign(long long   i) {return i>0 ? 1 : (i<0 ? -1 : 0);}
00325 
00326 inline int sign(const float&       x) {return x>0 ? 1 : (x<0 ? -1 : 0);}
00327 inline int sign(const double&      x) {return x>0 ? 1 : (x<0 ? -1 : 0);}
00328 inline int sign(const long double& x) {return x>0 ? 1 : (x<0 ? -1 : 0);}
00329 
00330 inline int sign(const negator<float>&       x) {return -sign(-x);} // -x is free
00331 inline int sign(const negator<double>&      x) {return -sign(-x);}
00332 inline int sign(const negator<long double>& x) {return -sign(-x);}
00334 
00351 inline unsigned char  square(unsigned char  u) {return u*u;}
00352 inline unsigned short square(unsigned short u) {return u*u;}
00353 inline unsigned int   square(unsigned int   u) {return u*u;}
00354 inline unsigned long  square(unsigned long  u) {return u*u;}
00355 inline unsigned long long square(unsigned long long u) {return u*u;}
00356 
00357 inline char        square(char c) {return c*c;}
00358 
00359 inline signed char square(signed char i) {return i*i;}
00360 inline short       square(short       i) {return i*i;}
00361 inline int         square(int         i) {return i*i;}
00362 inline long        square(long        i) {return i*i;}
00363 inline long long   square(long long   i) {return i*i;}
00364 
00365 inline float       square(const float&       x) {return x*x;}
00366 inline double      square(const double&      x) {return x*x;}
00367 inline long double square(const long double& x) {return x*x;}
00368 
00369 // Negation is free for negators, so we can square them and clean
00370 // them up at the same time at no extra cost.
00371 inline float       square(const negator<float>&       x) {return square(-x);}
00372 inline double      square(const negator<double>&      x) {return square(-x);}
00373 inline long double square(const negator<long double>& x) {return square(-x);}
00374 
00375 // It is safer to templatize using complex classes, and doesn't make
00376 // debugging any worse since complex is already templatized. 
00377 // 5 flops vs. 6 for general complex multiply.
00378 template <class P> inline 
00379 std::complex<P> square(const std::complex<P>& x) {
00380     const P re=x.real(), im=x.imag();
00381     return std::complex<P>(re*re-im*im, 2*re*im);
00382 }
00383 
00384 // We can square a conjugate and clean it up back to complex at
00385 // the same time at zero cost (or maybe 1 negation depending
00386 // on how the compiler handles the "-2" below).
00387 template <class P> inline 
00388 std::complex<P> square(const conjugate<P>& x) {
00389     const P re=x.real(), nim=x.negImag();
00390     return std::complex<P>(re*re-nim*nim, -2*re*nim);
00391 }
00392 
00393 template <class P> inline
00394 std::complex<P> square(const negator< std::complex<P> >& x) {
00395     return square(-x); // negation is free for negators
00396 }
00397 
00398 // Note return type here after squaring negator<conjugate>
00399 // is complex, not conjugate.
00400 template <class P> inline
00401 std::complex<P> square(const negator< conjugate<P> >& x) {
00402     return square(-x); // negation is free for negators
00403 }
00405 
00424 inline unsigned char  cube(unsigned char  u) {return u*u*u;}
00425 inline unsigned short cube(unsigned short u) {return u*u*u;}
00426 inline unsigned int   cube(unsigned int   u) {return u*u*u;}
00427 inline unsigned long  cube(unsigned long  u) {return u*u*u;}
00428 inline unsigned long long cube(unsigned long long u) {return u*u*u;}
00429 
00430 inline char        cube(char c) {return c*c*c;}
00431 
00432 inline signed char cube(signed char i) {return i*i*i;}
00433 inline short       cube(short       i) {return i*i*i;}
00434 inline int         cube(int         i) {return i*i*i;}
00435 inline long        cube(long        i) {return i*i*i;}
00436 inline long long   cube(long long   i) {return i*i*i;}
00437 
00438 inline float       cube(const float&       x) {return x*x*x;}
00439 inline double      cube(const double&      x) {return x*x*x;}
00440 inline long double cube(const long double& x) {return x*x*x;}
00441 
00442 // To keep this cheap we'll defer getting rid of the negator<> until
00443 // some other operation. We cube -x and then recast that to negator<>
00444 // on return, for a total cost of 2 flops.
00445 inline negator<float> cube(const negator<float>& x) {
00446     return negator<float>::recast(cube(-x));
00447 }
00448 inline negator<double> cube(const negator<double>& x) {
00449     return negator<double>::recast(cube(-x));
00450 }
00451 inline negator<long double> cube(const negator<long double>& x) {
00452     return negator<long double>::recast(cube(-x));
00453 }
00454 
00455 // Cubing a complex this way is cheaper than doing it by
00456 // multiplication. Cost here is 8 flops vs. 11 for a square
00457 // followed by a multiply.
00458 template <class P> inline
00459 std::complex<P> cube(const std::complex<P>& x) {
00460     const P re=x.real(), im=x.imag(), rr=re*re, ii=im*im;
00461     return std::complex<P>(re*(rr-3*ii), im*(3*rr-ii));
00462 }
00463 
00464 // Cubing a negated complex allows us to cube and eliminate the
00465 // negator at the same time for zero extra cost. Compare the 
00466 // expressions here to the normal cube above to see the free
00467 // sign changes in both parts. 8 flops here.
00468 template <class P> inline
00469 std::complex<P> cube(const negator< std::complex<P> >& x) {
00470     // -x is free for a negator
00471     const P nre=(-x).real(), nim=(-x).imag(), rr=nre*nre, ii=nim*nim;
00472     return std::complex<P>(nre*(3*ii-rr), nim*(ii-3*rr));
00473 }
00474 
00475 // Cubing a conjugate this way saves a lot over multiplying, and
00476 // also lets us convert the result to complex for free.
00477 template <class P> inline
00478 std::complex<P> cube(const conjugate<P>& x) {
00479     const P re=x.real(), nim=x.negImag(), rr=re*re, ii=nim*nim;
00480     return std::complex<P>(re*(rr-3*ii), nim*(ii-3*rr));
00481 }
00482 
00483 
00484 // Cubing a negated conjugate this way saves a lot over multiplying, and
00485 // also lets us convert the result to non-negated complex for free.
00486 template <class P> inline
00487 std::complex<P> cube(const negator< conjugate<P> >& x) {
00488     // -x is free for a negator
00489     const P nre=(-x).real(), im=(-x).negImag(), rr=nre*nre, ii=im*im;
00490     return std::complex<P>(nre*(3*ii-rr), im*(3*rr-ii));
00491 }
00493 
00525 
00541 inline double& clampInPlace(double low, double& v, double high) 
00542 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00544 inline float& clampInPlace(float low, float& v, float high) 
00545 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00547 inline long double& clampInPlace(long double low, long double& v, long double high) 
00548 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00549 
00550     // Floating point clamps with integer bounds; without these
00551     // explicit casts are required.
00552 
00555 inline double& clampInPlace(int low, double& v, int high) 
00556 {   return clampInPlace((double)low,v,(double)high); }
00559 inline float& clampInPlace(int low, float& v, int high) 
00560 {   return clampInPlace((float)low,v,(float)high); }
00563 inline long double& clampInPlace(int low, long double& v, int high) 
00564 {   return clampInPlace((long double)low,v,(long double)high); }
00565 
00568 inline double& clampInPlace(int low, double& v, double high) 
00569 {   return clampInPlace((double)low,v,high); }
00572 inline float& clampInPlace(int low, float& v, float high) 
00573 {   return clampInPlace((float)low,v,high); }
00576 inline long double& clampInPlace(int low, long double& v, long double high) 
00577 {   return clampInPlace((long double)low,v,high); }
00578 
00581 inline double& clampInPlace(double low, double& v, int high) 
00582 {   return clampInPlace(low,v,(double)high); }
00585 inline float& clampInPlace(float low, float& v, int high) 
00586 {   return clampInPlace(low,v,(float)high); }
00589 inline long double& clampInPlace(long double low, long double& v, int high) 
00590 {   return clampInPlace(low,v,(long double)high); }
00591 
00593 inline unsigned char& clampInPlace(unsigned char low, unsigned char& v, unsigned char high) 
00594 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00596 inline unsigned short& clampInPlace(unsigned short low, unsigned short& v, unsigned short high) 
00597 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00599 inline unsigned int& clampInPlace(unsigned int low, unsigned int& v, unsigned int high) 
00600 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00602 inline unsigned long& clampInPlace(unsigned long low, unsigned long& v, unsigned long high) 
00603 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00605 inline unsigned long long& clampInPlace(unsigned long long low, unsigned long long& v, unsigned long long high) 
00606 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00607 
00609 inline char& clampInPlace(char low, char& v, char high) 
00610 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00612 inline signed char& clampInPlace(signed char low, signed char& v, signed char high) 
00613 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00614 
00616 inline short& clampInPlace(short low, short& v, short high) 
00617 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00619 inline int& clampInPlace(int low, int& v, int high) 
00620 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00622 inline long& clampInPlace(long low, long& v, long high) 
00623 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00625 inline long long& clampInPlace(long long low, long long& v, long long high) 
00626 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00627 
00629 inline negator<float>& clampInPlace(float low, negator<float>& v, float high) 
00630 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00632 inline negator<double>& clampInPlace(double low, negator<double>& v, double high) 
00633 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00635 inline negator<long double>& clampInPlace(long double low, negator<long double>& v, long double high) 
00636 {   assert(low<=high); if (v<low) v=low; else if (v>high) v=high; return v; }
00637 
00638 
00639 
00660 inline double clamp(double low, double v, double high) 
00661 {   return clampInPlace(low,v,high); }
00663 inline float clamp(float low, float v, float high) 
00664 {   return clampInPlace(low,v,high); }
00666 inline long double clamp(long double low, long double v, long double high) 
00667 {   return clampInPlace(low,v,high); }
00668 
00671 inline double clamp(int low, double v, int high) 
00672 {   return clampInPlace(low,v,high); }
00675 inline float clamp(int low, float v, int high) 
00676 {   return clampInPlace(low,v,high); }
00679 inline long double clamp(int low, long double v, int high) 
00680 {   return clampInPlace(low,v,high); }
00681 
00684 inline double clamp(int low, double v, double high) 
00685 {   return clampInPlace(low,v,high); }
00688 inline float clamp(int low, float v, float high) 
00689 {   return clampInPlace(low,v,high); }
00692 inline long double clamp(int low, long double v, long double high) 
00693 {   return clampInPlace(low,v,high); }
00694 
00697 inline double clamp(double low, double v, int high) 
00698 {   return clampInPlace(low,v,high); }
00701 inline float clamp(float low, float v, int high) 
00702 {   return clampInPlace(low,v,high); }
00705 inline long double clamp(long double low, long double v, int high) 
00706 {   return clampInPlace(low,v,high); }
00707 
00709 inline unsigned char clamp(unsigned char low, unsigned char v, unsigned char high) 
00710 {   return clampInPlace(low,v,high); }
00712 inline unsigned short clamp(unsigned short low, unsigned short v, unsigned short high) 
00713 {   return clampInPlace(low,v,high); }
00715 inline unsigned int clamp(unsigned int low, unsigned int v, unsigned int high) 
00716 {   return clampInPlace(low,v,high); }
00718 inline unsigned long clamp(unsigned long low, unsigned long v, unsigned long high) 
00719 {   return clampInPlace(low,v,high); }
00721 inline unsigned long long clamp(unsigned long long low, unsigned long long v, unsigned long long high) 
00722 {   return clampInPlace(low,v,high); }
00723 
00725 inline char clamp(char low, char v, char high) 
00726 {   return clampInPlace(low,v,high); }
00728 inline signed char clamp(signed char low, signed char v, signed char high) 
00729 {   return clampInPlace(low,v,high); }
00730 
00732 inline short clamp(short low, short v, short high) 
00733 {   return clampInPlace(low,v,high); }
00735 inline int clamp(int low, int v, int high) 
00736 {   return clampInPlace(low,v,high); }
00738 inline long clamp(long low, long v, long high) 
00739 {   return clampInPlace(low,v,high); }
00741 inline long long clamp(long long low, long long v, long long high) 
00742 {   return clampInPlace(low,v,high); }
00743 
00744 
00745 // These aren't strictly necessary but are here to help the
00746 // compiler find the right overload to call. These cost an
00747 // extra flop because the negator<T> has to be cast to T which
00748 // requires that the pending negation be performed. Note that
00749 // the result types are not negated.
00750 
00755 inline float clamp(float low, negator<float> v, float high)
00756 {   return clamp(low,(float)v,high); }
00761 inline double clamp(double low, negator<double> v, double high) 
00762 {   return clamp(low,(double)v,high); }
00767 inline long double clamp(long double low, negator<long double> v, long double high) 
00768 {   return clamp(low,(long double)v,high); }
00809 
00824 inline double stepUp(double x)
00825 {   assert(0 <= x && x <= 1);
00826     return x*x*x*(10+x*(6*x-15)); }  //10x^3-15x^4+6x^5
00827 
00828 
00843 inline double stepDown(double x) {return 1.0 -stepUp(x);}
00844 
00845 
00920 inline double stepAny(double y0, double yRange,
00921                       double x0, double oneOverXRange,
00922                       double x) 
00923 {   double xadj = (x-x0)*oneOverXRange;    
00924     assert(-NTraits<double>::getSignificant() <= xadj
00925            && xadj <= 1 + NTraits<double>::getSignificant());
00926     clampInPlace(0.0,xadj,1.0);
00927     return y0 + yRange*stepUp(xadj); }
00928 
00932 inline double dstepUp(double x) {
00933     assert(0 <= x && x <= 1);
00934     const double xxm1=x*(x-1);
00935     return 30*xxm1*xxm1;        //30x^2-60x^3+30x^4
00936 }
00937 
00941 inline double dstepDown(double x) {return -dstepUp(x);}
00942 
00946 inline double dstepAny(double yRange,
00947                        double x0, double oneOverXRange,
00948                        double x) 
00949 {   double xadj = (x-x0)*oneOverXRange;    
00950     assert(-NTraits<double>::getSignificant() <= xadj
00951            && xadj <= 1 + NTraits<double>::getSignificant());
00952     clampInPlace(0.0,xadj,1.0);
00953     return yRange*oneOverXRange*dstepUp(xadj); }
00954 
00958 inline double d2stepUp(double x) {
00959     assert(0 <= x && x <= 1);
00960     return 60*x*(1+x*(2*x-3));  //60x-180x^2+120x^3
00961 }
00962 
00966 inline double d2stepDown(double x) {return -d2stepUp(x);}
00967 
00971 inline double d2stepAny(double yRange,
00972                         double x0, double oneOverXRange,
00973                         double x) 
00974 {   double xadj = (x-x0)*oneOverXRange;    
00975     assert(-NTraits<double>::getSignificant() <= xadj
00976            && xadj <= 1 + NTraits<double>::getSignificant());
00977     clampInPlace(0.0,xadj,1.0);
00978     return yRange*square(oneOverXRange)*d2stepUp(xadj); }
00979 
00983 inline double d3stepUp(double x) {
00984     assert(0 <= x && x <= 1);
00985     return 60+360*x*(x-1);      //60-360*x+360*x^2
00986 }
00987 
00991 inline double d3stepDown(double x) {return -d3stepUp(x);}
00992 
00996 inline double d3stepAny(double yRange,
00997                         double x0, double oneOverXRange,
00998                         double x) 
00999 {   double xadj = (x-x0)*oneOverXRange;    
01000     assert(-NTraits<double>::getSignificant() <= xadj
01001            && xadj <= 1 + NTraits<double>::getSignificant());
01002     clampInPlace(0.0,xadj,1.0);
01003     return yRange*cube(oneOverXRange)*d3stepUp(xadj); }
01004 
01005             // float
01006 
01008 inline float stepUp(float x) 
01009 {   assert(0 <= x && x <= 1);
01010     return x*x*x*(10+x*(6*x-15)); }  //10x^3-15x^4+6x^5
01012 inline float stepDown(float x) {return 1.0f-stepUp(x);}
01014 inline float stepAny(float y0, float yRange,
01015                      float x0, float oneOverXRange,
01016                      float x) 
01017 {   float xadj = (x-x0)*oneOverXRange;    
01018     assert(-NTraits<float>::getSignificant() <= xadj
01019            && xadj <= 1 + NTraits<float>::getSignificant());
01020     clampInPlace(0.0f,xadj,1.0f);
01021     return y0 + yRange*stepUp(xadj); }
01022 
01024 inline float dstepUp(float x) 
01025 {   assert(0 <= x && x <= 1);
01026     const float xxm1=x*(x-1);
01027     return 30*xxm1*xxm1; }  //30x^2-60x^3+30x^4
01029 inline float dstepDown(float x) {return -dstepUp(x);}
01031 inline float dstepAny(float yRange,
01032                       float x0, float oneOverXRange,
01033                       float x) 
01034 {   float xadj = (x-x0)*oneOverXRange;    
01035     assert(-NTraits<float>::getSignificant() <= xadj
01036            && xadj <= 1 + NTraits<float>::getSignificant());
01037     clampInPlace(0.0f,xadj,1.0f);
01038     return yRange*oneOverXRange*dstepUp(xadj); }
01039 
01041 inline float d2stepUp(float x) 
01042 {   assert(0 <= x && x <= 1);
01043     return 60*x*(1+x*(2*x-3)); }    //60x-180x^2+120x^3
01045 inline float d2stepDown(float x) {return -d2stepUp(x);}
01047 inline float d2stepAny(float yRange,
01048                        float x0, float oneOverXRange,
01049                        float x) 
01050 {   float xadj = (x-x0)*oneOverXRange;    
01051     assert(-NTraits<float>::getSignificant() <= xadj
01052            && xadj <= 1 + NTraits<float>::getSignificant());
01053     clampInPlace(0.0f,xadj,1.0f);
01054     return yRange*square(oneOverXRange)*d2stepUp(xadj); }
01055 
01057 inline float d3stepUp(float x) 
01058 {   assert(0 <= x && x <= 1);
01059     return 60+360*x*(x-1); }    //60-360*x+360*x^2
01061 inline float d3stepDown(float x) {return -d3stepUp(x);}
01063 inline float d3stepAny(float yRange,
01064                        float x0, float oneOverXRange,
01065                        float x) 
01066 {   float xadj = (x-x0)*oneOverXRange;    
01067     assert(-NTraits<float>::getSignificant() <= xadj
01068            && xadj <= 1 + NTraits<float>::getSignificant());
01069     clampInPlace(0.0f,xadj,1.0f);
01070     return yRange*cube(oneOverXRange)*d3stepUp(xadj); }
01071 
01072             // long double
01073 
01075 inline long double stepUp(long double x) 
01076 {   assert(0 <= x && x <= 1);
01077     return x*x*x*(10+x*(6*x-15)); }  //10x^3-15x^4+6x^5
01079 inline long double stepDown(long double x) {return 1.0L-stepUp(x);}
01081 inline long double stepAny(long double y0, long double yRange,
01082                            long double x0, long double oneOverXRange,
01083                            long double x) 
01084 {   long double xadj = (x-x0)*oneOverXRange;    
01085     assert(-NTraits<long double>::getSignificant() <= xadj
01086            && xadj <= 1 + NTraits<long double>::getSignificant());
01087     clampInPlace(0.0L,xadj,1.0L);
01088     return y0 + yRange*stepUp(xadj); }
01089 
01090 
01092 inline long double dstepUp(long double x) 
01093 {   assert(0 <= x && x <= 1);
01094     const long double xxm1=x*(x-1);
01095     return 30*xxm1*xxm1; }          //30x^2-60x^3+30x^4
01097 inline long double dstepDown(long double x) {return -dstepUp(x);}
01099 inline long double dstepAny(long double yRange,
01100                             long double x0, long double oneOverXRange,
01101                             long double x) 
01102 {   long double xadj = (x-x0)*oneOverXRange;    
01103     assert(-NTraits<long double>::getSignificant() <= xadj
01104            && xadj <= 1 + NTraits<long double>::getSignificant());
01105     clampInPlace(0.0L,xadj,1.0L);
01106     return yRange*oneOverXRange*dstepUp(xadj); }
01107 
01109 inline long double d2stepUp(long double x) 
01110 {   assert(0 <= x && x <= 1);
01111     return 60*x*(1+x*(2*x-3)); }    //60x-180x^2+120x^3
01113 inline long double d2stepDown(long double x) {return -d2stepUp(x);}
01115 inline long double d2stepAny(long double yRange,
01116                              long double x0, long double oneOverXRange,
01117                              long double x) 
01118 {   long double xadj = (x-x0)*oneOverXRange;    
01119     assert(-NTraits<long double>::getSignificant() <= xadj
01120            && xadj <= 1 + NTraits<long double>::getSignificant());
01121     clampInPlace(0.0L,xadj,1.0L);
01122     return yRange*square(oneOverXRange)*d2stepUp(xadj); }
01123 
01124 
01126 inline long double d3stepUp(long double x) 
01127 {   assert(0 <= x && x <= 1);
01128     return 60+360*x*(x-1); }        //60-360*x+360*x^2
01130 inline long double d3stepDown(long double x) {return -d3stepUp(x);}
01132 inline long double d3stepAny(long double yRange,
01133                              long double x0, long double oneOverXRange,
01134                              long double x) 
01135 {   long double xadj = (x-x0)*oneOverXRange;    
01136     assert(-NTraits<long double>::getSignificant() <= xadj
01137            && xadj <= 1 + NTraits<long double>::getSignificant());
01138     clampInPlace(0.0L,xadj,1.0L);
01139     return yRange*cube(oneOverXRange)*d3stepUp(xadj); }
01140 
01141         // int converts to double; only supplied for stepUp(), stepDown()
01144 inline double stepUp(int x) {return stepUp((double)x);}
01147 inline double stepDown(int x) {return stepDown((double)x);}
01148 
01149 
01208  // Doxygen should skip this helper template function
01210 template <class T> // float or double 
01211 static inline std::pair<T,T> approxCompleteEllipticIntegralsKE_T(T m) {
01212     static const T a[] =
01213     {   (T)1.38629436112, (T)0.09666344259, (T)0.03590092383,
01214         (T)0.03742563713, (T)0.01451196212 };
01215     static const T b[] = 
01216     {   (T)0.5,           (T)0.12498593597, (T)0.06880248576,
01217         (T)0.03328355346, (T)0.00441787012 };
01218     static const T c[] =
01219     {   (T)1,             (T)0.44325141463, (T)0.06260601220,
01220         (T)0.04757383546, (T)0.01736506451 };
01221     static const T d[] =
01222     {   (T)0,             (T)0.24998368310, (T)0.09200180037,
01223         (T)0.04069697526, (T)0.00526449639 };
01224 
01225     const T SignificantReal = NTraits<T>::getSignificant();
01226     const T PiOver2         = NTraits<T>::getPi()/2;
01227     const T Infinity        = NTraits<T>::getInfinity();
01228 
01229     SimTK_ERRCHK1_ALWAYS(-SignificantReal < m && m < 1+SignificantReal,
01230         "approxCompleteEllipticIntegralsKE()", 
01231         "Argument m (%g) is outside the legal range [0,1].", (double)m);
01232     if (m >= 1) return std::make_pair(Infinity, (T)1);
01233     if (m <= 0) return std::make_pair(PiOver2, PiOver2);
01234 
01235     const T m1=1-m, m2=m1*m1, m3=m1*m2, m4=m2*m2; // 4 flops
01236     const T lnm2 = std::log(m1);  // ~50 flops
01237 
01238     // The rest is 35 flops.
01239     const T K = (a[0] + a[1]*m1 + a[2]*m2 + a[3]*m3 + a[4]*m4) 
01240          - lnm2*(b[0] + b[1]*m1 + b[2]*m2 + b[3]*m3 + b[4]*m4);
01241     const T E = (c[0] + c[1]*m1 + c[2]*m2 + c[3]*m3 + c[4]*m4) 
01242          - lnm2*(       d[1]*m1 + d[2]*m2 + d[3]*m3 + d[4]*m4);
01243 
01244     return std::make_pair(K,E);
01245 }
01284 inline std::pair<double,double> 
01285 approxCompleteEllipticIntegralsKE(double m)
01286 {   return approxCompleteEllipticIntegralsKE_T<double>(m); }
01292 inline std::pair<float,float> 
01293 approxCompleteEllipticIntegralsKE(float m)
01294 {   return approxCompleteEllipticIntegralsKE_T<float>(m); }
01301 inline std::pair<double,double> 
01302 approxCompleteEllipticIntegralsKE(int m)
01303 {   return approxCompleteEllipticIntegralsKE_T<double>((double)m); }
01304 
01305  // Doxygen should skip this template helper function
01307 template <class T> // float or double
01308 static inline std::pair<T,T> completeEllipticIntegralsKE_T(T m) {
01309     const T SignificantReal = NTraits<T>::getSignificant();
01310     const T TenEps          = 10*NTraits<T>::getEps();
01311     const T Infinity        = NTraits<T>::getInfinity();
01312     const T PiOver2         = NTraits<T>::getPi() / 2;
01313 
01314     // Allow a little slop in the argument since it may have resulted
01315     // from a numerical operation that gave 0 or 1 plus or minus
01316     // roundoff noise.
01317     SimTK_ERRCHK1_ALWAYS(-SignificantReal < m && m < 1+SignificantReal,
01318         "completeEllipticIntegralsKE()", 
01319         "Argument m (%g) is outside the legal range [0,1].", (double)m);
01320     if (m >= 1) return std::make_pair(Infinity, (T)1);
01321     if (m <= 0) return std::make_pair(PiOver2, PiOver2);
01322 
01323     const T k = std::sqrt(1-m); // ~25 flops
01324     T v1=1, w1=k, c1=1, d1=k*k; // initialize iteration
01325     do { // ~50 flops per iteration
01326         T v2 = (v1+w1)/2;
01327         T w2 = std::sqrt(v1*w1);
01328         T c2 = (c1+d1)/2;
01329         T d2 = (w1*c1+v1*d1)/(v1+w1);
01330         v1=v2; w1=w2; c1=c2; d1=d2;
01331     } while(std::abs(v1-w1) >= TenEps);
01332 
01333     const T K = PiOver2/v1; // ~20 flops
01334     const T E = K*c1;
01335 
01336     return std::make_pair(K,E);
01337 }
01364 inline std::pair<double,double> completeEllipticIntegralsKE(double m)
01365 {   return completeEllipticIntegralsKE_T<double>(m); }
01373 inline std::pair<float,float> completeEllipticIntegralsKE(float m)
01374 {   return completeEllipticIntegralsKE_T<float>(m); }
01381 inline std::pair<double,double> completeEllipticIntegralsKE(int m)
01382 {   return completeEllipticIntegralsKE_T<double>((double)m); }
01383 
01386 } // namespace SimTK
01387 
01388 #endif //SimTK_SIMMATRIX_SCALAR_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines