simtkcommon/trunk/include/SimTKcommon/internal/common.h

Go to the documentation of this file.
00001 #ifndef SimTK_SimTKCOMMON_COMMON_H_
00002 #define SimTK_SimTKCOMMON_COMMON_H_
00003 
00004 /* -------------------------------------------------------------------------- *
00005  *                      SimTK Core: SimTKcommon                               *
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 
00048 /*****************************/
00049 /* ANSI-C COMPATIBLE SECTION */
00050 /*****************************/
00051 
00052 /* Set up a few compile-time options that affect all SimTK Core headers. */
00053 
00054 /* 
00055  * This compile-time constant determines the default precision used everywhere
00056  * in SimTK Core code. Wherever a SimTK::Real, SimTK::Vector, SimTK::Matrix,
00057  * etc. appears with no precision specified, it will have this underlying precision.
00058  * We use 1==float, 2==double, 4==long double. Any other value will cause
00059  * a compile time error. The default is 2.
00060  */
00061 #ifndef SimTK_DEFAULT_PRECISION
00062 #   define SimTK_DEFAULT_PRECISION 2
00063 #endif
00064 
00065 /* This type is for use in C. In C++ use SimTK::Real instead. */
00066 #if   (SimTK_DEFAULT_PRECISION == 1)
00067     typedef float SimTK_Real;
00068 #elif (SimTK_DEFAULT_PRECISION == 2)
00069     typedef double SimTK_Real;
00070 #elif (SimTK_DEFAULT_PRECISION == 4)
00071     typedef long double SimTK_Real;
00072 #else
00073     #error ILLEGAL VALUE FOR DEFAULT PRECISION
00074 #endif
00075 
00076 #ifndef NDEBUG
00077     #if defined(__cplusplus)
00078         #include <cstdio>
00079         #define SimTK_DEBUG(s) std::printf("DBG: " s)
00080         #define SimTK_DEBUG1(s,a1) std::printf("DBG: " s,a1)    
00081         #define SimTK_DEBUG2(s,a1,a2) std::printf("DBG: " s,a1,a2)  
00082         #define SimTK_DEBUG3(s,a1,a2,a3) std::printf("DBG: " s,a1,a2,a3)    
00083         #define SimTK_DEBUG4(s,a1,a2,a3,a4) std::printf("DBG: " s,a1,a2,a3,a4)
00084     #else
00085         #include <stdio.h>
00086         #define SimTK_DEBUG(s) printf("DBG: " s)
00087         #define SimTK_DEBUG1(s,a1) printf("DBG: " s,a1) 
00088         #define SimTK_DEBUG2(s,a1,a2) printf("DBG: " s,a1,a2)   
00089         #define SimTK_DEBUG3(s,a1,a2,a3) printf("DBG: " s,a1,a2,a3) 
00090         #define SimTK_DEBUG4(s,a1,a2,a3,a4) printf("DBG: " s,a1,a2,a3,a4)
00091     #endif
00092 #else
00093     #define SimTK_DEBUG(s)
00094     #define SimTK_DEBUG1(s,a1)
00095     #define SimTK_DEBUG2(s,a1,a2)
00096     #define SimTK_DEBUG3(s,a1,a2,a3)    
00097     #define SimTK_DEBUG4(s,a1,a2,a3,a4)
00098 #endif
00099 
00100 /*
00101  * Shared libraries are messy in Visual Studio. We have to distinguish three
00102  * cases:
00103  *   (1) this header is being used to build the SimTKcommon shared library (dllexport)
00104  *   (2) this header is being used by a *client* of the SimTKcommon shared
00105  *       library (dllimport)
00106  *   (3) we are building the SimTKcommon static library, or the client is
00107  *       being compiled with the expectation of linking with the
00108  *       SimTKcommon static library (nothing special needed)
00109  * In the CMake script for building this library, we define one of the symbols
00110  *     SimTK_SimTKCOMMON_BUILDING_{SHARED|STATIC}_LIBRARY
00111  * Client code normally has no special symbol defined, in which case we'll
00112  * assume it wants to use the shared library. However, if the client defines
00113  * the symbol SimTK_USE_STATIC_LIBRARIES we'll suppress the dllimport so
00114  * that the client code can be linked with static libraries. Note that
00115  * the client symbol is not library dependent, while the library symbols
00116  * affect only the SimTKcommon library, meaning that other libraries can
00117  * be clients of this one. However, we are assuming all-static or all-shared.
00118  */
00119 
00120 #ifdef WIN32
00121     #ifdef _MSC_VER
00122     #pragma warning(disable:4231) // need to use 'extern' template explicit instantiation
00123     #endif
00124     #if defined(SimTK_SimTKCOMMON_BUILDING_SHARED_LIBRARY)
00125         #define SimTK_SimTKCOMMON_EXPORT __declspec(dllexport)
00126         // Keep MS VC++ quiet when it tries to instantiate incomplete template classes in a DLL.
00127         #ifdef _MSC_VER
00128         #pragma warning(disable:4661)
00129         #endif
00130     #elif defined(SimTK_SimTKCOMMON_BUILDING_STATIC_LIBRARY) || defined(SimTK_USE_STATIC_LIBRARIES)
00131         #define SimTK_SimTKCOMMON_EXPORT
00132     #else
00133         #define SimTK_SimTKCOMMON_EXPORT __declspec(dllimport)   // i.e., a client of a shared library
00134     #endif
00135 #else
00136     #define SimTK_SimTKCOMMON_EXPORT // Linux, Mac
00137 #endif
00138 
00139 /* Every SimTK Core library must provide these two routines, with the library
00140  * name appearing after the "version_" and "about_".
00141  */
00142 #if defined(__cplusplus)
00143 extern "C" {
00144 #endif
00145     SimTK_SimTKCOMMON_EXPORT void SimTK_version_SimTKcommon(int* major, int* minor, int* build);
00146     SimTK_SimTKCOMMON_EXPORT void SimTK_about_SimTKcommon(const char* key, int maxlen, char* value);
00147 #if defined(__cplusplus)
00148 }
00149 #endif
00150 
00151 /************************************/
00152 /* END OF ANSI-C COMPATIBLE SECTION */
00153 /************************************/
00154 
00155 #if defined(__cplusplus)
00156 
00157 #include <cstddef>
00158 #include <cassert>
00159 #include <complex>
00160 #include <limits>
00161 
00190 namespace SimTK {
00191     static const int InvalidIndex = -1111111111;
00192 }
00193 
00196 #define SimTK_DEFINE_UNIQUE_INDEX_TYPE(NAME)                   \
00197     SimTK_DEFINE_AND_EXPORT_UNIQUE_LOCAL_INDEX_TYPE(,,,NAME)   \
00198     static const NAME Invalid ## NAME;
00199 
00202 #define SimTK_DEFINE_AND_EXPORT_UNIQUE_INDEX_TYPE(EXPORT,NAME)     \
00203     SimTK_DEFINE_AND_EXPORT_UNIQUE_LOCAL_INDEX_TYPE(EXPORT,,,NAME) \
00204     static const NAME Invalid ## NAME;
00205 
00207 #define SimTK_DEFINE_UNIQUE_LOCAL_INDEX_TYPE(PARENT,NAME) \
00208     SimTK_DEFINE_AND_EXPORT_UNIQUE_LOCAL_INDEX_TYPE(,PARENT,::,NAME)
00209 
00212 #define SimTK_DEFINE_AND_EXPORT_UNIQUE_LOCAL_INDEX_TYPE(EXPORT,PARENT,SEP,NAME)   \
00213 class EXPORT NAME {                         \
00214     int ix;                                 \
00215 public:                                     \
00216     NAME() : ix(SimTK::InvalidIndex) { }       \
00217     explicit NAME(int i) : ix(i)      {assert(i>=0 || i==SimTK::InvalidIndex);} \
00218     explicit NAME(long l): ix((int)l) {assert(canStoreInNonnegativeInt(l));}    \
00219     explicit NAME(unsigned int  u)  : ix((int)u)  {assert(canStoreInInt(u));}   \
00220     explicit NAME(unsigned long ul) : ix((int)ul) {assert(canStoreInInt(ul));}  \
00221     operator int() const {return ix;}               \
00222     bool isValid() const {return ix>=0;}            \
00223     bool isValidExtended() const {return ix>=-1;}   \
00224     void invalidate(){ix=SimTK::InvalidIndex;}      \
00225     \
00226     bool operator==(int  i) const {assert(isValidExtended() && isValidExtended(i)); return ix==i;}    \
00227     bool operator==(long l) const {assert(isValidExtended() && isValidExtended(l)); return ix==(int)l;}  \
00228     bool operator==(unsigned int  u)  const {assert(isValidExtended() && isValid(u)); return ix==(int)u;}   \
00229     bool operator==(unsigned long ul) const {assert(isValidExtended() && isValid(ul)); return ix==(int)ul;} \
00230     bool operator!=(int  i)           const {return !operator==(i);}    \
00231     bool operator!=(long l)           const {return !operator==(l);}    \
00232     bool operator!=(unsigned int  u)  const {return !operator==(u);}    \
00233     bool operator!=(unsigned long ul) const {return !operator==(ul);}   \
00234     \
00235     bool operator< (int  i) const {assert(isValidExtended() && isValidExtended(i)); return ix<i;}        \
00236     bool operator< (long l) const {assert(isValidExtended() && isValidExtended(l)); return ix<(int)l;}   \
00237     bool operator< (unsigned int  u)  const {assert(isValidExtended() && isValid(u));  return ix<(int)u;}    \
00238     bool operator< (unsigned long ul) const {assert(isValidExtended() && isValid(ul)); return ix<(int)ul;}   \
00239     bool operator>=(int  i)           const {return !operator<(i);}    \
00240     bool operator>=(long l)           const {return !operator<(l);}    \
00241     bool operator>=(unsigned int  u)  const {return !operator<(u);}    \
00242     bool operator>=(unsigned long ul) const {return !operator<(ul);}   \
00243     \
00244     bool operator> (int  i) const {assert(isValidExtended() && isValidExtended(i)); return ix>i;}        \
00245     bool operator> (long l) const {assert(isValidExtended() && isValidExtended(l)); return ix>(int)l;}   \
00246     bool operator> (unsigned int  u)  const {assert(isValidExtended() && isValid(u));  return ix>(int)u;}    \
00247     bool operator> (unsigned long ul) const {assert(isValidExtended() && isValid(ul)); return ix>(int)ul;}   \
00248     bool operator<=(int  i)           const {return !operator>(i);}    \
00249     bool operator<=(long l)           const {return !operator>(l);}    \
00250     bool operator<=(unsigned int  u)  const {return !operator>(u);}    \
00251     bool operator<=(unsigned long ul) const {return !operator>(ul);}   \
00252     \
00253     const NAME& operator++() {assert(isValid()); ++ix; return *this;}       /*prefix */   \
00254     NAME operator++(int)     {assert(isValid()); ++ix; return NAME(ix-1);}  /*postfix*/   \
00255     const NAME& operator--() {assert(isValid()); --ix; return *this;}       /*prefix */   \
00256     NAME operator--(int)     {assert(isValid()); --ix; return NAME(ix+1);}  /*postfix*/   \
00257     \
00258     NAME& operator+=(int i)  {assert(isValid() && isValidExtended(ix+i)); ix+=i; return *this;}     \
00259     NAME& operator-=(int i)  {assert(isValid() && isValidExtended(ix-i)); ix-=i; return *this;}     \
00260     NAME& operator+=(long l) {assert(isValid() && canStoreInInt(l) && isValidExtended(ix+(int)l)); ix+=(int)l; return *this;}     \
00261     NAME& operator-=(long l) {assert(isValid() && canStoreInInt(l) && isValidExtended(ix-(int)l)); ix-=(int)l; return *this;}     \
00262     NAME& operator+=(unsigned int  u)  {assert(isValid()&& canStoreInInt(u)  && isValid(ix+(int)u));  ix+=(int)u;  return *this;}  \
00263     NAME& operator-=(unsigned int  u)  {assert(isValid()&& canStoreInInt(u)  && isValidExtended(ix-(int)u));  ix-=(int)u;  return *this;}  \
00264     NAME& operator+=(unsigned long ul) {assert(isValid()&& canStoreInInt(ul) && isValid(ix+(int)ul)); ix+=(int)ul; return *this;}  \
00265     NAME& operator-=(unsigned long ul) {assert(isValid()&& canStoreInInt(ul) && isValidExtended(ix-(int)ul)); ix-=(int)ul; return *this;}  \
00266     \
00267     static const NAME& Invalid() {static const NAME invalid; return invalid;}       \
00268     static bool isValid(int  i) {return i>=0;}                                      \
00269     static bool isValid(long l) {return canStoreInNonnegativeInt(l);}               \
00270     static bool isValid(unsigned int  u)  {return canStoreInInt(u);}                \
00271     static bool isValid(unsigned long ul) {return canStoreInInt(ul);}               \
00272     static bool isValidExtended(int  i) {return i>=-1;}                             \
00273     static bool isValidExtended(long l) {return canStoreInInt(l) && l>=-1;}         \
00274 };
00275 
00281 #define SimTK_DOWNCAST(Derived,Parent) \
00282     static bool isA(const Parent& p)                        \
00283         { return dynamic_cast<const Derived*>(&p) != 0; }   \
00284     static const Derived& downcast(const Parent& p)         \
00285         { return dynamic_cast<const Derived&>(p); }         \
00286     static Derived& downcast(Parent& p)                     \
00287         { return dynamic_cast<Derived&>(p); }
00288 
00293 #define SimTK_DOWNCAST2(Derived,Helper,Parent) \
00294     static bool isA(const Parent& p)                                        \
00295         { return Helper::isA(p); }                                          \
00296     static const Derived& downcast(const Parent& p)                         \
00297         { return reinterpret_cast<const Derived&>(Helper::downcast(p)); }   \
00298     static Derived& downcast(Parent& p)                                     \
00299         { return reinterpret_cast<Derived&>(Helper::downcast(p)); }
00300 
00301 
00302 // Similar to the above but for private implementation abstract classes, that
00303 // is, abstract class hierarchies where the virtual function table is 
00304 // hidden on the library side.
00305 #define SimTK_PIMPL_DOWNCAST(Derived, Parent)           \
00306     static bool           isInstanceOf(const Parent&);  \
00307     static const Derived& downcast(const Parent&);      \
00308     static Derived&       updDowncast(Parent&)
00309 
00310 namespace SimTK {
00311     
00312 namespace Options { }
00313 namespace Exception { }
00314 
00315 typedef SimTK_Real              Real;
00316 typedef std::complex<Real>      Complex;
00317 
00318 struct Segment {
00319     Segment() : length(0), offset(0) { }
00320     explicit Segment(int l, int ofs=0) : length(l), offset(ofs) { 
00321         assert(l>=0 && ofs>=0);
00322     }
00323     // default copy, assignment, destructor
00324     int length;
00325     int offset;
00326 };  
00327 
00328 template <class T> class TypeInfo {
00329 public:
00330     static const char* name() {return typeid(T).name();}
00331 };
00332 
00333 #define SimTK_TYPEINFO_SPECIALIZE(T)            \
00334 template <> class TypeInfo< T > {               \
00335 public:                                         \
00336     static const char* name() { return #T; }    \
00337 };
00338 // Built-in types
00339 SimTK_TYPEINFO_SPECIALIZE(bool);            SimTK_TYPEINFO_SPECIALIZE(signed char); 
00340 SimTK_TYPEINFO_SPECIALIZE(char);            SimTK_TYPEINFO_SPECIALIZE(unsigned char);
00341 SimTK_TYPEINFO_SPECIALIZE(short);           SimTK_TYPEINFO_SPECIALIZE(int); 
00342 SimTK_TYPEINFO_SPECIALIZE(long);
00343 SimTK_TYPEINFO_SPECIALIZE(unsigned short);  SimTK_TYPEINFO_SPECIALIZE(unsigned int); 
00344 SimTK_TYPEINFO_SPECIALIZE(unsigned long);
00345 SimTK_TYPEINFO_SPECIALIZE(float);           SimTK_TYPEINFO_SPECIALIZE(double); 
00346 SimTK_TYPEINFO_SPECIALIZE(long double);
00347 SimTK_TYPEINFO_SPECIALIZE(std::complex<float>);
00348 SimTK_TYPEINFO_SPECIALIZE(std::complex<double>); 
00349 SimTK_TYPEINFO_SPECIALIZE(std::complex<long double>); 
00350 
00351 
00352 } // namespace SimTK
00353 
00354 namespace SimTKimpl {
00355 
00358 typedef void*       (*IndexT)(void* tp, int n);
00359 typedef const void* (*IndexConstT)(const void* tp, int n);
00360 typedef void*       (*CreateOneT)(const void* iptr);
00361 typedef void        (*DestructOneT)(void*& tvptr);  
00362 typedef void        (*AssignArrayOfT)(void* dest, const void* src, int n);
00363 typedef void        (*SetT)(void* dest, const void* valuep, int n);
00364 typedef void*       (*CreateArrayOfT)(int n, const void* iptr);
00365 typedef void        (*DestructArrayOfT)(void*& tvptr);
00367 
00368 struct TypeManipulatorT {
00369     TypeManipulatorT(int z, IndexT it, IndexConstT ict,
00370                      CreateOneT c1t, DestructOneT d1t, AssignArrayOfT aat, SetT st,
00371                      CreateArrayOfT cat, DestructArrayOfT dat)
00372         : sizeOfT(z), indexT(it), indexConstT(ict), 
00373           createOneT(c1t), destructOneT(d1t), assignArrayOfT(aat), setT(st),
00374           createArrayOfT(cat), destructArrayOfT(dat)
00375     { }
00376     
00377     bool operator==(const TypeManipulatorT& t) const
00378       { return sizeOfT==t.sizeOfT && indexT==t.indexT; }
00379 
00380     // THESE MUST NEVER CHANGE ORDER! This is effectively a compiler-independent
00381     // virtual function table. The first entry is a size in bytes and the rest have
00382     // type "pointer to function" so all the data should have a very predictable
00383     // and stable layout in memory.
00384     //
00385     // This is the one place in the SimTK API where the client
00386     // side and library side must agree on the physical layout of the class. 
00387     // It is safe to add new entries to the end of this list, but inserting earlier,
00388     // deleting or reordering anything already here will break binary compatibility.
00389     const int               sizeOfT;
00390     const IndexT            indexT;
00391     const IndexConstT       indexConstT;
00392     const CreateOneT        createOneT;
00393     const DestructOneT      destructOneT;
00394     const AssignArrayOfT    assignArrayOfT;
00395     const SetT              setT;
00396     const CreateArrayOfT    createArrayOfT;
00397     const DestructArrayOfT  destructArrayOfT;
00398 };
00399 
00414 template <class T> class MakeTypeManipulator {
00415 public:
00416     MakeTypeManipulator() { }
00417     // default copy, assignment, destructor
00418     
00419     static const TypeManipulatorT& getTypeManipulatorT() { return manipT; }
00420     static T& updAs(void* v) 
00421       { assert(v); return *reinterpret_cast<T*>(v); }
00422     static const T& getAs(const void* v) 
00423       { assert(v); return *reinterpret_cast<const T*>(v); }
00424 
00425 private:    
00431     static int sizeT() { return (int)sizeof(T); }
00432     
00437     static void* indexT(void* tp, int n)
00438         { return (void*)(reinterpret_cast<T*>(tp) + n); }
00439     static const void* indexConstT(const void* tp, int n)
00440         { return (const void*)(reinterpret_cast<const T*>(tp) + n); }
00442 
00446     static void* createOneT(const void* iptr=0)
00447     {
00448         T* tptr = new T;
00449         if (iptr) *tptr = *reinterpret_cast<const T*>(iptr);
00450         return tptr;
00451     }
00452     
00455     static void destructOneT(void*& tvptr)
00456     {
00457         T* tptr = reinterpret_cast<T*>(tvptr);
00458         delete tptr;
00459         tvptr = 0;
00460     }
00461 
00467     static void assignArrayOfT(void* dest, const void* src, int n)
00468     {   assert(n>=0);
00469         if (n==0) return;
00470         assert(dest && src);
00471         assert(indexT(dest,n) < src || indexConstT(src,n) < dest);      
00472         T*       d = reinterpret_cast<T*>(dest);
00473         const T* s = reinterpret_cast<const T*>(src);
00474         for (int i=0; i < n; ++i) *d++ = *s++;
00475     }
00476         
00481     static void setT(void* dest, const void* valuep, int n=1)
00482     {   assert(n>=0);
00483         if (n==0) return;
00484         assert(dest && valuep);
00485         T*       d = reinterpret_cast<T*>(dest);
00486         const T& v = *reinterpret_cast<const T*>(valuep);
00487         for (int i=0; i < n; ++i) *d++ = v; 
00488     }
00489     
00492     static void* createArrayOfT(int n, const void* iptr=0)
00493     {   assert(n>=0);
00494         if (n == 0) return 0;
00495         T* tptr = new T[n];
00496         if (iptr) {
00497             const T& init = *reinterpret_cast<const T*>(iptr);
00498             for (int i=0; i < n; ++i) tptr[i] = init;
00499         }       
00500         return tptr;
00501     }
00502     
00507     static void destructArrayOfT(void*& tvptr)
00508     {
00509         T* tptr = reinterpret_cast<T*>(tvptr);
00510         delete[] tptr;
00511         tvptr = 0;
00512     }
00513     
00514 private:    
00515     static const TypeManipulatorT manipT;
00516 };
00517 
00518 /*static*/ template <class T> const TypeManipulatorT
00519 MakeTypeManipulator<T>::manipT = TypeManipulatorT(
00520                                     (int)sizeof(T),indexT,indexConstT,
00521                                     createOneT, destructOneT, assignArrayOfT, setT, 
00522                                     createArrayOfT, destructArrayOfT);
00523 } // namespace SimTKimpl
00524 
00525 
00526 #endif /* C++ stuff */
00527 
00528 #endif /* SimTK_SimTKCOMMON_COMMON_H_ */

Generated on Fri Sep 26 07:44:08 2008 for SimTKcore by  doxygen 1.5.6