Simbody
|
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_