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-7 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 
00047 #include "SimTKcommon/internal/conjugate.h"
00048 #include "SimTKcommon/internal/CompositeNumericalTypes.h"
00049 #include "SimTKcommon/internal/NTraits.h"
00050 #include "SimTKcommon/internal/negator.h"
00051 
00052 #include <complex>
00053 
00054 namespace SimTK {
00055 
00057     // Handy default-precision definitions //
00059 
00060 typedef conjugate<Real> Conjugate;  // like Complex
00061 
00062     // Note that these constants have memory addresses, so you can
00063     // return references to them.
00064     // These are static variables rather than static members to avoid
00065     // problems with static initialization order.
00066 
00067     // Properties of the floaing point representation.
00068 
00069 static const Real& NaN               = NTraits<Real>::getNaN();      // "not a number"
00070 static const Real& Infinity          = NTraits<Real>::getInfinity();
00071 
00072 // Epsilon is the size of roundoff noise; it is the smallest positive number
00073 // such that 1+Eps != 1.
00074 static const Real& Eps               = NTraits<Real>::getEps();         // double ~1e-16, float ~1e-7
00075 static const Real& SqrtEps           = NTraits<Real>::getSqrtEps();     // eps^(1/2): double ~1e- 8, float ~3e-4
00076 static const Real& TinyReal          = NTraits<Real>::getTiny();        // eps^(5/4): double ~1e-20, float ~1e-9
00077 static const Real& SignificantReal   = NTraits<Real>::getSignificant(); // eps^(7/8): double ~1e-14, float ~1e-6
00078 
00079 static const Real& LeastPositiveReal = NTraits<Real>::getLeastPositive(); // double ~1e-308, float ~1e-38
00080 static const Real& MostPositiveReal  = NTraits<Real>::getMostPositive();  // double ~1e+308, float ~1e+38
00081 static const Real& LeastNegativeReal = NTraits<Real>::getLeastNegative();
00082 static const Real& MostNegativeReal  = NTraits<Real>::getMostNegative();
00083 
00084 // This is the number of decimal digits that can be reliably stored and
00085 // retrieved in the default Real precision (typically log10(1/eps)-1).
00086 static const int NumDigitsReal = NTraits<Real>::getNumDigits(); // double ~15, float ~6
00087 
00088 // This is the smallest number of decimal digits you should store in a file
00089 // if you want to be able to get exactly the same bit pattern back when you
00090 // read it in. Typically, this is about log10(1/tiny).
00091 static const int LosslessNumDigitsReal = NTraits<Real>::getLosslessNumDigits(); // double ~20, float ~9
00092 
00093     // Carefully calculated constants, with convenient memory addresses.
00094 
00095 static const Real& Zero         = NTraits<Real>::getZero();
00096 static const Real& One          = NTraits<Real>::getOne();
00097 static const Real& MinusOne     = NTraits<Real>::getMinusOne();
00098 static const Real& Two          = NTraits<Real>::getTwo();
00099 static const Real& Three        = NTraits<Real>::getThree();
00100 
00101 static const Real& OneHalf      = NTraits<Real>::getOneHalf();
00102 static const Real& OneThird     = NTraits<Real>::getOneThird();
00103 static const Real& OneFourth    = NTraits<Real>::getOneFourth();
00104 static const Real& OneFifth     = NTraits<Real>::getOneFifth();
00105 static const Real& OneSixth     = NTraits<Real>::getOneSixth();
00106 static const Real& OneSeventh   = NTraits<Real>::getOneSeventh();
00107 static const Real& OneEighth    = NTraits<Real>::getOneEighth();
00108 static const Real& OneNinth     = NTraits<Real>::getOneNinth();
00109 static const Real& Pi           = NTraits<Real>::getPi();
00110 static const Real& OneOverPi    = NTraits<Real>::getOneOverPi();
00111 static const Real& E            = NTraits<Real>::getE();
00112 static const Real& Log2E        = NTraits<Real>::getLog2E();
00113 static const Real& Log10E       = NTraits<Real>::getLog10E();
00114 static const Real& Sqrt2        = NTraits<Real>::getSqrt2();
00115 static const Real& OneOverSqrt2 = NTraits<Real>::getOneOverSqrt2();  // also sqrt(2)/2
00116 static const Real& Sqrt3        = NTraits<Real>::getSqrt3();
00117 static const Real& OneOverSqrt3 = NTraits<Real>::getOneOverSqrt3();
00118 static const Real& CubeRoot2    = NTraits<Real>::getCubeRoot2();
00119 static const Real& CubeRoot3    = NTraits<Real>::getCubeRoot3();
00120 static const Real& Ln2          = NTraits<Real>::getLn2();
00121 static const Real& Ln10         = NTraits<Real>::getLn10();
00122 
00123 // We only need one complex constant. For the rest just use
00124 // Complex(the Real constant), or if you need an address use
00125 // NTraits<Complex>::getPi(), etc.
00126 static const Complex& I = NTraits<Complex>::getI();
00127 
00128 
00130     // SOME SCALAR UTILITIES //
00132 
00133 // This utility answers the question "if I put this integral value in an int and then
00134 // get it back, will its value be the same?".
00135 inline bool canStoreInInt(char)            {return true;}
00136 inline bool canStoreInInt(unsigned char)   {return true;}
00137 inline bool canStoreInInt(signed char)     {return true;}
00138 inline bool canStoreInInt(short)           {return true;}
00139 inline bool canStoreInInt(unsigned short)  {return true;}
00140 inline bool canStoreInInt(int)             {return true;}
00141 inline bool canStoreInInt(unsigned int  u) {return (unsigned int)(int(u)) == u;}
00142 inline bool canStoreInInt(long i)          {return long(int(i)) == i;}
00143 inline bool canStoreInInt(unsigned long u) {return (unsigned long)(int(u)) == u;}
00144 
00145 // This utility answers the question "is this integral value a nonnegative number
00146 // that can be stored in an int?".
00147 inline bool canStoreInNonnegativeInt(char c)           {return c >= 0;}
00148 inline bool canStoreInNonnegativeInt(unsigned char c)  {return true;}
00149 inline bool canStoreInNonnegativeInt(signed char c)    {return c >= 0;}
00150 inline bool canStoreInNonnegativeInt(short s)          {return s >= 0;}
00151 inline bool canStoreInNonnegativeInt(unsigned short s) {return true;}
00152 inline bool canStoreInNonnegativeInt(int  i)           {return i >= 0;}
00153 inline bool canStoreInNonnegativeInt(long l)           {return canStoreInInt(l) && l >= 0;}
00154 inline bool canStoreInNonnegativeInt(unsigned int  u)  {return canStoreInInt(u);}
00155 inline bool canStoreInNonnegativeInt(unsigned long u)  {return canStoreInInt(u);}
00156 
00169 inline bool isNaN(const float& x) {
00170     volatile float xx = x; // prevent clever optimizations
00171     return x != xx;
00172 }
00173 
00174 inline bool isNaN(const double& x) {
00175     volatile double xx = x; // prevent clever optimizations
00176     return x != xx;
00177 }
00178 
00179 inline bool isNaN(const long double& x) {
00180     volatile long double xx = x; // prevent clever optimizations
00181     return x != xx;
00182 }
00183 
00184 
00185 template <class P> inline bool
00186 isNaN(const std::complex<P>& x) {
00187     return isNaN(x.real()) || isNaN(x.imag());
00188 }
00189 
00190 template <class P> inline bool
00191 isNaN(const conjugate<P>& x) {
00192     return isNaN(x.real()) || isNaN(x.negImag());
00193 }
00194 
00195 inline bool isNaN(const negator<float>&       x) {return isNaN(-x);}
00196 inline bool isNaN(const negator<double>&      x) {return isNaN(-x);}
00197 inline bool isNaN(const negator<long double>& x) {return isNaN(-x);}
00198 
00199 template <class P> inline bool
00200 isNaN(const negator< std::complex<P> >& x) {return isNaN(-x);}
00201 template <class P> inline bool
00202 isNaN(const negator< conjugate<P> >&    x) {return isNaN(-x);}
00203 
00212 inline unsigned int sign(unsigned char  u) {return u==0 ? 0 : 1;}
00213 inline unsigned int sign(unsigned short u) {return u==0 ? 0 : 1;}
00214 inline unsigned int sign(unsigned int   u) {return u==0 ? 0 : 1;}
00215 inline unsigned int sign(unsigned long  u) {return u==0 ? 0 : 1;}
00216 
00217 // Don't overload for plain "char" because it may be signed or unsigned
00218 // depending on the compiler.
00219 
00220 inline int sign(signed char i) {return i>0 ? 1 : (i<0 ? -1 : 0);}
00221 inline int sign(short       i) {return i>0 ? 1 : (i<0 ? -1 : 0);}
00222 inline int sign(int         i) {return i>0 ? 1 : (i<0 ? -1 : 0);}
00223 inline int sign(long        i) {return i>0 ? 1 : (i<0 ? -1 : 0);}
00224 
00225 inline int sign(const float&       x) {return x>0 ? 1 : (x<0 ? -1 : 0);}
00226 inline int sign(const double&      x) {return x>0 ? 1 : (x<0 ? -1 : 0);}
00227 inline int sign(const long double& x) {return x>0 ? 1 : (x<0 ? -1 : 0);}
00228 
00229 inline int sign(const negator<float>&       x) {return -sign(-x);} // -x is free
00230 inline int sign(const negator<double>&      x) {return -sign(-x);}
00231 inline int sign(const negator<long double>& x) {return -sign(-x);}
00232 
00241 inline unsigned char  square(unsigned char  u) {return u*u;}
00242 inline unsigned short square(unsigned short u) {return u*u;}
00243 inline unsigned int   square(unsigned int   u) {return u*u;}
00244 inline unsigned long  square(unsigned long  u) {return u*u;}
00245 
00246 inline char        square(char c) {return c*c;}
00247 
00248 inline signed char square(signed char i) {return i*i;}
00249 inline short       square(short       i) {return i*i;}
00250 inline int         square(int         i) {return i*i;}
00251 inline long        square(long        i) {return i*i;}
00252 
00253 inline float       square(const float&       x) {return x*x;}
00254 inline double      square(const double&      x) {return x*x;}
00255 inline long double square(const long double& x) {return x*x;}
00256 
00257 // Negation is free for negators, so we can square them and clean
00258 // them up at the same time at no extra cost.
00259 inline float       square(const negator<float>&       x) {return square(-x);}
00260 inline double      square(const negator<double>&      x) {return square(-x);}
00261 inline long double square(const negator<long double>& x) {return square(-x);}
00262 
00263 // It is safer to templatize using complex classes, and doesn't make
00264 // debugging any worse since complex is already templatized. 
00265 // 5 flops vs. 6 for general complex multiply.
00266 template <class P> inline 
00267 std::complex<P> square(const std::complex<P>& x) {
00268     const P re=x.real(), im=x.imag();
00269     return std::complex<P>(re*re-im*im, 2*re*im);
00270 }
00271 
00272 // We can square a conjugate and clean it up back to complex at
00273 // the same time at zero cost (or maybe 1 negation depending
00274 // on how the compiler handles the "-2" below).
00275 template <class P> inline 
00276 std::complex<P> square(const conjugate<P>& x) {
00277     const P re=x.real(), nim=x.negImag();
00278     return std::complex<P>(re*re-nim*nim, -2*re*nim);
00279 }
00280 
00281 template <class P> inline
00282 std::complex<P> square(const negator< std::complex<P> >& x) {
00283     return square(-x); // negation is free for negators
00284 }
00285 
00286 // Note return type here after squaring negator<conjugate>
00287 // is complex, not conjugate.
00288 template <class P> inline
00289 std::complex<P> square(const negator< conjugate<P> >& x) {
00290     return square(-x); // negation is free for negators
00291 }
00292 
00302 inline unsigned char  cube(unsigned char  u) {return u*u*u;}
00303 inline unsigned short cube(unsigned short u) {return u*u*u;}
00304 inline unsigned int   cube(unsigned int   u) {return u*u*u;}
00305 inline unsigned long  cube(unsigned long  u) {return u*u*u;}
00306 
00307 inline char        cube(char c) {return c*c*c;}
00308 
00309 inline signed char cube(signed char i) {return i*i*i;}
00310 inline short       cube(short       i) {return i*i*i;}
00311 inline int         cube(int         i) {return i*i*i;}
00312 inline long        cube(long        i) {return i*i*i;}
00313 
00314 inline float       cube(const float&       x) {return x*x*x;}
00315 inline double      cube(const double&      x) {return x*x*x;}
00316 inline long double cube(const long double& x) {return x*x*x;}
00317 
00318 // To keep this cheap we'll defer getting rid of the negator<> until
00319 // some other operation. We cube -x and then recast that to negator<>
00320 // on return, for a total cost of 2 flops.
00321 inline negator<float> cube(const negator<float>& x) {
00322     return negator<float>::recast(cube(-x));
00323 }
00324 inline negator<double> cube(const negator<double>& x) {
00325     return negator<double>::recast(cube(-x));
00326 }
00327 inline negator<long double> cube(const negator<long double>& x) {
00328     return negator<long double>::recast(cube(-x));
00329 }
00330 
00331 // Cubing a complex this way is cheaper than doing it by
00332 // multiplication. Cost here is 8 flops vs. 11 for a square
00333 // followed by a multiply.
00334 template <class P> inline
00335 std::complex<P> cube(const std::complex<P>& x) {
00336     const P re=x.real(), im=x.imag(), rr=re*re, ii=im*im;
00337     return std::complex<P>(re*(rr-3*ii), im*(3*rr-ii));
00338 }
00339 
00340 // Cubing a negated complex allows us to cube and eliminate the
00341 // negator at the same time for zero extra cost. Compare the 
00342 // expressions here to the normal cube above to see the free
00343 // sign changes in both parts. 8 flops here.
00344 template <class P> inline
00345 std::complex<P> cube(const negator< std::complex<P> >& x) {
00346     const P nre=(-x).real(), nim=(-x).imag(), // -x is free for negator
00347             rr=nre*nre, ii=nim*nim;
00348     return std::complex<P>(nre*(3*ii-rr), nim*(ii-3*rr));
00349 }
00350 
00351 } // namespace SimTK
00352 
00353 #endif //SimTK_SIMMATRIX_SCALAR_H_

Generated on Thu Feb 28 01:34:31 2008 for SimTKcommon by  doxygen 1.4.7