Simbody 3.9
Loading...
Searching...
No Matches
SimTKcommon/include/SimTKcommon/internal/common.h
Go to the documentation of this file.
1#ifndef SimTK_SimTKCOMMON_COMMON_H_
2#define SimTK_SimTKCOMMON_COMMON_H_
3
4/* -------------------------------------------------------------------------- *
5 * Simbody(tm): SimTKcommon *
6 * -------------------------------------------------------------------------- *
7 * This is part of the SimTK biosimulation toolkit originating from *
8 * Simbios, the NIH National Center for Physics-Based Simulation of *
9 * Biological Structures at Stanford, funded under the NIH Roadmap for *
10 * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. *
11 * *
12 * Portions copyright (c) 2005-15 Stanford University and the Authors. *
13 * Authors: Michael Sherman *
14 * Contributors: Chris Dembia *
15 * *
16 * Licensed under the Apache License, Version 2.0 (the "License"); you may *
17 * not use this file except in compliance with the License. You may obtain a *
18 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. *
19 * *
20 * Unless required by applicable law or agreed to in writing, software *
21 * distributed under the License is distributed on an "AS IS" BASIS, *
22 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
23 * See the License for the specific language governing permissions and *
24 * limitations under the License. *
25 * -------------------------------------------------------------------------- */
26
39// Provide doxygen documentation for the SimTK namespace.
40
49// Define shared doxygen "modules" and sub-modules here. We'll put things
50// in them at various places when appropriate.
51
91/*****************************/
92/* ANSI-C COMPATIBLE SECTION */
93/*****************************/
94
95/* Set up a few compile-time options that affect all SimTK Core headers. */
96
104#ifndef SimTK_DEFAULT_PRECISION
105# define SimTK_DEFAULT_PRECISION 2
106#endif
107
108#if (SimTK_DEFAULT_PRECISION == 1)
110 typedef float SimTK_Real;
111#elif (SimTK_DEFAULT_PRECISION == 2)
113 typedef double SimTK_Real;
114#else
115 #error ILLEGAL VALUE FOR DEFAULT PRECISION
116#endif
117
118#ifndef NDEBUG
119 #if defined(__cplusplus)
120 #include <cstdio>
121 #define SimTK_DEBUG(s) std::printf("DBG: " s)
122 #define SimTK_DEBUG1(s,a1) std::printf("DBG: " s,a1)
123 #define SimTK_DEBUG2(s,a1,a2) std::printf("DBG: " s,a1,a2)
124 #define SimTK_DEBUG3(s,a1,a2,a3) std::printf("DBG: " s,a1,a2,a3)
125 #define SimTK_DEBUG4(s,a1,a2,a3,a4) std::printf("DBG: " s,a1,a2,a3,a4)
126 #else
127 #include <stdio.h>
128 #define SimTK_DEBUG(s) printf("DBG: " s)
129 #define SimTK_DEBUG1(s,a1) printf("DBG: " s,a1)
130 #define SimTK_DEBUG2(s,a1,a2) printf("DBG: " s,a1,a2)
131 #define SimTK_DEBUG3(s,a1,a2,a3) printf("DBG: " s,a1,a2,a3)
132 #define SimTK_DEBUG4(s,a1,a2,a3,a4) printf("DBG: " s,a1,a2,a3,a4)
133 #endif
134#else
135 #define SimTK_DEBUG(s)
136 #define SimTK_DEBUG1(s,a1)
137 #define SimTK_DEBUG2(s,a1,a2)
138 #define SimTK_DEBUG3(s,a1,a2,a3)
139 #define SimTK_DEBUG4(s,a1,a2,a3,a4)
140#endif
141
142/*
143 * Shared libraries are messy in Visual Studio. We have to distinguish three
144 * cases:
145 * (1) this header is being used to build the SimTKcommon shared library (dllexport)
146 * (2) this header is being used by a *client* of the SimTKcommon shared
147 * library (dllimport)
148 * (3) we are building the SimTKcommon static library, or the client is
149 * being compiled with the expectation of linking with the
150 * SimTKcommon static library (nothing special needed)
151 * In the CMake script for building this library, we define one of the symbols
152 * SimTK_SimTKCOMMON_BUILDING_{SHARED|STATIC}_LIBRARY
153 * Client code normally has no special symbol defined, in which case we'll
154 * assume it wants to use the shared library. However, if the client defines
155 * the symbol SimTK_USE_STATIC_LIBRARIES we'll suppress the dllimport so
156 * that the client code can be linked with static libraries. Note that
157 * the client symbol is not library dependent, while the library symbols
158 * affect only the SimTKcommon library, meaning that other libraries can
159 * be clients of this one. However, we are assuming all-static or all-shared.
160 */
161
162#ifdef _WIN32
163 #ifdef _MSC_VER
164 #pragma warning(disable:4231) /*need to use 'extern' template explicit instantiation*/
165 #pragma warning(disable:4251) /*no DLL interface for type of member of exported class*/
166 #pragma warning(disable:4275) /*no DLL interface for base class of exported class*/
167 #pragma warning(disable:4345) /*warning about PODs being default-initialized*/
168
169
170 /* Until VS2015 struct timespec was missing from <ctime> so is faked here
171 if needed. When Simbody used pthreads and provided its own pthread.h for
172 Windows, we had to avoid a duplicate declaration with timespec in pthread.h
173 via the HAVE_STRUCT_TIMESPEC guard. In 2018, we removed pthread.h, but we
174 left in the HAVE_STRUCT_TIMESPEC guard in case a third party defines
175 timespec.
176 TODO: there is a potential problem here since VS2015's struct timespec
177 doesn't appear to match pthread's definition. */
178 #ifndef HAVE_STRUCT_TIMESPEC
179 #define HAVE_STRUCT_TIMESPEC 1
180 #if _MSC_VER < 1900
181 struct timespec {
182 long tv_sec; /* TODO(sherm1,chrisdembia) should be time_t? */
183 long tv_nsec;
184 };
185 #endif
186 #endif /* HAVE_STRUCT_TIMESPEC */
187 #endif
188 #if defined(SimTK_SimTKCOMMON_BUILDING_SHARED_LIBRARY)
189 #ifdef _MSC_VER
190 #define SimTK_SimTKCOMMON_EXPORT __declspec(dllexport)
191 /* Keep MS VC++ quiet when it tries to instantiate incomplete template classes in a DLL. */
192 #pragma warning(disable:4661)
193 #else
194 #define SimTK_SimTKCOMMON_EXPORT
195 #endif
196 #elif defined(SimTK_SimTKCOMMON_BUILDING_STATIC_LIBRARY) || defined(SimTK_USE_STATIC_LIBRARIES)
197 #define SimTK_SimTKCOMMON_EXPORT
198 #else
199 #ifdef _MSC_VER
200 #define SimTK_SimTKCOMMON_EXPORT __declspec(dllimport) /*i.e., a client of a shared library*/
201 #else
202 #define SimTK_SimTKCOMMON_EXPORT
203 #endif
204 #endif
205 /* VC++ tries to be secure by leaving bounds checking on for STL containers
206 * even in Release mode. This macro exists to disable that feature and can
207 * result in a considerable speedup.
208 * CAUTION: every linked-together compilation unit must have this set the same
209 * way. Everyone who properly includes this file first is fine; but as of this
210 * writing Simmath's IpOpt doesn't do so.
211 * NOTE: Microsoft corrected this problem with VC10 -- the feature is
212 * disabled by default in that compiler and later.
213 */
214 /* (sherm 081204 disabling for now: doesn't work on VC++ 8 and is
215 * tricky on VC++ 9 because all libraries, including 3rd party, must
216 * be built the same way). Better to use the SimTK::Array_<T> class in
217 * place of the std::vector<T> class to get better performance.
218 #ifdef NDEBUG
219 #undef _SECURE_SCL
220 #define _SECURE_SCL 0
221 #endif
222 */
223#else
224 #define SimTK_SimTKCOMMON_EXPORT // Linux, Mac
225#endif
226
227/* Every SimTK Core library must provide these two routines, with the library
228 * name appearing after the "version_" and "about_".
229 */
230#if defined(__cplusplus)
231extern "C" {
232#endif
234 SimTK_SimTKCOMMON_EXPORT void SimTK_version_SimTKcommon(int* major, int* minor, int* build);
241 SimTK_SimTKCOMMON_EXPORT void SimTK_about_SimTKcommon(const char* key, int maxlen, char* value);
242#if defined(__cplusplus)
243}
244#endif
245
246/************************************/
247/* END OF ANSI-C COMPATIBLE SECTION */
248/************************************/
249
250#if defined(__cplusplus)
251
252#include <cstddef>
253#include <cassert>
254#include <cstring>
255#include <cmath>
256#include <cfloat>
257#include <complex>
258#include <limits>
259#include <typeinfo>
260#include <algorithm>
261
262/* Be very careful with this macro -- don't use it unless you have measured
263a performance improvement. You can end up with serious code bloat if you
264override the compiler's judgement about when to inline, and that can cause
265cache misses which ultimately reduce performance. */
266#ifdef _MSC_VER
267 #define SimTK_FORCE_INLINE __forceinline
268#else
269 #define SimTK_FORCE_INLINE __attribute__((always_inline)) inline
270#endif
271
272/* Microsoft added noexcept in VS2015 */
273#if defined(_MSC_VER) && _MSC_VER < 1900
274 #define NOEXCEPT_11 throw()
275#else
276 #define NOEXCEPT_11 noexcept
277#endif
278
279/* C++14 introduces a standard way to mark deprecated declarations. Before
280that we can use non-standard compiler hacks. */
281#ifndef SWIG
282 #if __cplusplus >= 201402L
283 /* C++14 */
284 #define DEPRECATED_14(MSG) [[deprecated(MSG)]]
285 #elif _MSC_VER
286 /* VC++ just says warning C4996 so add "DEPRECATED" to the message. */
287 #define DEPRECATED_14(MSG) __declspec(deprecated("DEPRECATED: " MSG))
288 #else /* gcc or clang */
289 #define DEPRECATED_14(MSG) __attribute__((deprecated(MSG)))
290 #endif
291#else /* Swigging */
292 #define DEPRECATED_14(MSG)
293#endif
294
295/* These macros are deprecated, leftover from before C++11 was available.
296Don't use them. Sorry, can't use the DEPRECATED_14 macro here! */
297#define OVERRIDE_11 override
298#define FINAL_11 final
299
300/* -------------------------------------------------------------------------- *
301 * SimTK_NODISCARD *
302 * -------------------------------------------------------------------------- */
306#if defined(SWIG) || defined(DOXYGEN)
307 #define SimTK_NODISCARD
308#elif defined(__cplusplus) && \
309 ((__cplusplus >= 201703L) || \
310 (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L))
311 #define SimTK_NODISCARD [[nodiscard]]
312#elif defined(__clang__) || defined(__GNUC__)
313 #define SimTK_NODISCARD __attribute__((warn_unused_result))
314#else
315 #define SimTK_NODISCARD
316#endif
317
318
319namespace SimTK {
320
321
322// This utility answers the question "if I put this integral value in an int and then
323// get it back, will its value be the same?".
324inline bool canStoreInInt(bool) {return true;}
325inline bool canStoreInInt(char) {return true;}
326inline bool canStoreInInt(unsigned char) {return true;}
327inline bool canStoreInInt(signed char) {return true;}
328inline bool canStoreInInt(short) {return true;}
329inline bool canStoreInInt(unsigned short) {return true;}
330inline bool canStoreInInt(int) {return true;}
331inline bool canStoreInInt(unsigned int u) {return (unsigned int)(int(u)) == u;}
332inline bool canStoreInInt(long i) {return long(int(i)) == i;}
333inline bool canStoreInInt(unsigned long u) {return (unsigned long)(int(u)) == u;}
334inline bool canStoreInInt(long long i) {return (long long)(int(i)) == i;}
335inline bool canStoreInInt(unsigned long long u) {return (unsigned long long)(int(u)) == u;}
336
337// This utility answers the question "is this integral value a nonnegative number
338// that can be stored in an int?".
339inline bool canStoreInNonnegativeInt(bool) {return true;}
340inline bool canStoreInNonnegativeInt(char c) {return c >= 0;}
341inline bool canStoreInNonnegativeInt(unsigned char) {return true;}
342inline bool canStoreInNonnegativeInt(signed char c) {return c >= 0;}
343inline bool canStoreInNonnegativeInt(short s) {return s >= 0;}
344inline bool canStoreInNonnegativeInt(unsigned short) {return true;}
345inline bool canStoreInNonnegativeInt(int i) {return i >= 0;}
346inline bool canStoreInNonnegativeInt(long l) {return canStoreInInt(l) && l >= 0;}
347inline bool canStoreInNonnegativeInt(long long l) {return canStoreInInt(l) && l >= 0;}
348inline bool canStoreInNonnegativeInt(unsigned int u) {return canStoreInInt(u);}
349inline bool canStoreInNonnegativeInt(unsigned long u) {return canStoreInInt(u);}
350inline bool canStoreInNonnegativeInt(unsigned long long u) {return canStoreInInt(u);}
351
352// This utility answers the question of whether an integer is suitable as a size
353// limited by the given maximum size. Signed types must be checked for being
354// nonegative; doing that with unsigned types leads to compiler warnings.
355
356// char can be signed or unsigned depending on the compiler; assume signed.
357inline bool isSizeInRange(char sz, char mx){return 0<=sz&&sz<=mx;}
358inline bool isSizeInRange(signed char sz, signed char mx){return 0<=sz&&sz<=mx;}
359inline bool isSizeInRange(short sz, short mx){return 0<=sz&&sz<=mx;}
360inline bool isSizeInRange(int sz, int mx){return 0<=sz&&sz<=mx;}
361inline bool isSizeInRange(long sz, long mx){return 0<=sz&&sz<=mx;}
362inline bool isSizeInRange(long long sz, long long mx){return 0<=sz&&sz<=mx;}
363inline bool isSizeInRange(unsigned char sz, unsigned char mx){return sz<=mx;}
364inline bool isSizeInRange(unsigned short sz, unsigned short mx){return sz<=mx;}
365inline bool isSizeInRange(unsigned int sz, unsigned int mx){return sz<=mx;}
366inline bool isSizeInRange(unsigned long sz, unsigned long mx){return sz<=mx;}
367inline bool isSizeInRange(unsigned long long sz, unsigned long long mx){return sz<=mx;}
368
369// This utility answers the question of whether an integer is suitable as an index
370// for an array limited by the given maximum size. Signed types must be checked for being
371// nonegative; doing that with unsigned types leads to compiler warnings. This is just
372// like the "size in range" check above except the maximum value allowed for an index
373// is one less that the size.
374
375// char can be signed or unsigned depending on the compiler; assume signed.
376inline bool isIndexInRange(char ix, char sz){return 0<=ix&&ix<sz;}
377inline bool isIndexInRange(signed char ix, signed char sz){return 0<=ix&&ix<sz;}
378inline bool isIndexInRange(short ix, short sz){return 0<=ix&&ix<sz;}
379inline bool isIndexInRange(int ix, int sz){return 0<=ix&&ix<sz;}
380inline bool isIndexInRange(long ix, long sz){return 0<=ix&&ix<sz;}
381inline bool isIndexInRange(long long ix, long long sz){return 0<=ix&&ix<sz;}
382inline bool isIndexInRange(unsigned char ix, unsigned char sz){return ix<sz;}
383inline bool isIndexInRange(unsigned short ix, unsigned short sz){return ix<sz;}
384inline bool isIndexInRange(unsigned int ix, unsigned int sz){return ix<sz;}
385inline bool isIndexInRange(unsigned long ix, unsigned long sz){return ix<sz;}
386inline bool isIndexInRange(unsigned long long ix, unsigned long long sz){return ix<sz;}
387
388// This utility answers the question: is this integral value nonnegative? The answer
389// is always true for unsigned types and you'll get a warning from some compilers if
390// you check.
391
392inline bool isNonnegative(bool) {return true;}
393// char can be signed or unsigned depending on the compiler; assume signed.
394inline bool isNonnegative(char n) {return n>=0;}
395inline bool isNonnegative(signed char n) {return n>=0;}
396inline bool isNonnegative(short n) {return n>=0;}
397inline bool isNonnegative(int n) {return n>=0;}
398inline bool isNonnegative(long n) {return n>=0;}
399inline bool isNonnegative(long long n) {return n>=0;}
400inline bool isNonnegative(unsigned char) {return true;}
401inline bool isNonnegative(unsigned short) {return true;}
402inline bool isNonnegative(unsigned int) {return true;}
403inline bool isNonnegative(unsigned long) {return true;}
404inline bool isNonnegative(unsigned long long){return true;}
405
406// A NaN-like value for unique index types created using the macro
407// SimTK_DEFINE_UNIQUE_INDEX_TYPE(). A unique, typed constant with
408// this numerical value is created for each index type.
409static const int InvalidIndex = -1111111111;
410}
411
412
413
445#define SimTK_DEFINE_UNIQUE_INDEX_TYPE(NAME) \
446 SimTK_DEFINE_AND_EXPORT_UNIQUE_LOCAL_INDEX_TYPE(,,,NAME) \
447 static const NAME Invalid ## NAME;
448
451#define SimTK_DEFINE_AND_EXPORT_UNIQUE_INDEX_TYPE(EXPORT,NAME) \
452 SimTK_DEFINE_AND_EXPORT_UNIQUE_LOCAL_INDEX_TYPE(EXPORT,,,NAME) \
453 static const NAME Invalid ## NAME;
454
456#define SimTK_DEFINE_UNIQUE_LOCAL_INDEX_TYPE(PARENT,NAME) \
457 SimTK_DEFINE_AND_EXPORT_UNIQUE_LOCAL_INDEX_TYPE(,PARENT,::,NAME)
458
461#define SimTK_DEFINE_AND_EXPORT_UNIQUE_LOCAL_INDEX_TYPE(EXPORT,PARENT,SEP,NAME) \
462class EXPORT NAME { \
463 int ix; \
464public: \
465 NAME() : ix(SimTK::InvalidIndex) { } \
466 explicit NAME(int i) : ix(i) {assert(i>=0 || i==SimTK::InvalidIndex);} \
467 explicit NAME(long l): ix((int)l) {assert(SimTK::canStoreInNonnegativeInt(l));} \
468 explicit NAME(long long l): ix((int)l) {assert(SimTK::canStoreInNonnegativeInt(l));} \
469 explicit NAME(unsigned int u) : ix((int)u) {assert(SimTK::canStoreInInt(u));} \
470 explicit NAME(unsigned long ul) : ix((int)ul) {assert(SimTK::canStoreInInt(ul));} \
471 explicit NAME(unsigned long long ul) : ix((int)ul) {assert(SimTK::canStoreInInt(ul));} \
472 operator int() const {return ix;} \
473 bool isValid() const {return ix>=0;} \
474 bool isValidExtended() const {return ix>=-1;} \
475 void invalidate(){clear();} \
476 void clear(){ix=SimTK::InvalidIndex;} \
477 \
478 bool operator==(const NAME& other) const {assert(isValidExtended() && isValidExtended(other)); return ix == other.ix; } \
479 bool operator==(int i) const {assert(isValidExtended() && isValidExtended(i)); return ix==i;} \
480 bool operator==(short s) const{assert(isValidExtended() && isValidExtended(s)); return ix==(int)s;} \
481 bool operator==(long l) const {assert(isValidExtended() && isValidExtended(l)); return ix==(int)l;} \
482 bool operator==(long long l) const {assert(isValidExtended() && isValidExtended(l)); return ix==(int)l;} \
483 bool operator==(unsigned int u) const {assert(isValidExtended() && isValid(u)); return ix==(int)u;} \
484 bool operator==(unsigned short us)const {assert(isValidExtended() && isValid(us)); return ix==(int)us;} \
485 bool operator==(unsigned long ul) const {assert(isValidExtended() && isValid(ul)); return ix==(int)ul;} \
486 bool operator==(unsigned long long ul) const {assert(isValidExtended() && isValid(ul)); return ix==(int)ul;} \
487 bool operator!=(int i) const {return !operator==(i);} \
488 bool operator!=(short s) const {return !operator==(s);} \
489 bool operator!=(long l) const {return !operator==(l);} \
490 bool operator!=(long long l) const {return !operator==(l);} \
491 bool operator!=(unsigned int u) const {return !operator==(u);} \
492 bool operator!=(unsigned long ul) const {return !operator==(ul);} \
493 bool operator!=(unsigned long long ul) const {return !operator==(ul);} \
494 \
495 bool operator< (int i) const {assert(isValidExtended() && isValidExtended(i)); return ix<i;} \
496 bool operator< (short s) const{assert(isValidExtended() && isValidExtended(s)); return ix<(int)s;} \
497 bool operator< (long l) const {assert(isValidExtended() && isValidExtended(l)); return ix<(int)l;} \
498 bool operator< (long long l) const {assert(isValidExtended() && isValidExtended(l)); return ix<(int)l;} \
499 bool operator< (unsigned int u) const {assert(isValidExtended() && isValid(u)); return ix<(int)u;} \
500 bool operator< (unsigned short us)const {assert(isValidExtended() && isValid(us)); return ix<(int)us;} \
501 bool operator< (unsigned long ul) const {assert(isValidExtended() && isValid(ul)); return ix<(int)ul;} \
502 bool operator< (unsigned long long ul) const {assert(isValidExtended() && isValid(ul)); return ix<(int)ul;} \
503 bool operator>=(int i) const {return !operator<(i);} \
504 bool operator>=(short s) const {return !operator<(s);} \
505 bool operator>=(long l) const {return !operator<(l);} \
506 bool operator>=(long long l) const {return !operator<(l);} \
507 bool operator>=(unsigned int u) const {return !operator<(u);} \
508 bool operator>=(unsigned short us)const {return !operator<(us);} \
509 bool operator>=(unsigned long ul) const {return !operator<(ul);} \
510 bool operator>=(unsigned long long ul) const {return !operator<(ul);} \
511 \
512 bool operator> (int i) const {assert(isValidExtended() && isValidExtended(i)); return ix>i;} \
513 bool operator> (short s) const{assert(isValidExtended() && isValidExtended(s)); return ix>(int)s;} \
514 bool operator> (long l) const {assert(isValidExtended() && isValidExtended(l)); return ix>(int)l;} \
515 bool operator> (long long l) const {assert(isValidExtended() && isValidExtended(l)); return ix>(int)l;} \
516 bool operator> (unsigned int u) const {assert(isValidExtended() && isValid(u)); return ix>(int)u;} \
517 bool operator> (unsigned short us)const {assert(isValidExtended() && isValid(us)); return ix>(int)us;} \
518 bool operator> (unsigned long ul) const {assert(isValidExtended() && isValid(ul)); return ix>(int)ul;} \
519 bool operator> (unsigned long long ul) const {assert(isValidExtended() && isValid(ul)); return ix>(int)ul;} \
520 bool operator<=(int i) const {return !operator>(i);} \
521 bool operator<=(short s) const {return !operator>(s);} \
522 bool operator<=(long l) const {return !operator>(l);} \
523 bool operator<=(long long l) const {return !operator>(l);} \
524 bool operator<=(unsigned int u) const {return !operator>(u);} \
525 bool operator<=(unsigned short us)const {return !operator>(us);} \
526 bool operator<=(unsigned long ul) const {return !operator>(ul);} \
527 bool operator<=(unsigned long long ul) const {return !operator>(ul);} \
528 \
529 const NAME& operator++() {assert(isValid()); ++ix; return *this;} /*prefix */ \
530 NAME operator++(int) {assert(isValid()); ++ix; return NAME(ix-1);} /*postfix*/ \
531 const NAME& operator--() {assert(isValid()); --ix; return *this;} /*prefix */ \
532 NAME operator--(int) {assert(isValid()); --ix; return NAME(ix+1);} /*postfix*/ \
533 NAME next() const {assert(isValid()); return NAME(ix+1);} \
534 NAME prev() const {assert(isValid()); return NAME(ix-1);} /*might return -1*/ \
535 \
536 NAME& operator+=(int i) {assert(isValid() && isValidExtended(ix+i)); ix+=i; return *this;} \
537 NAME& operator-=(int i) {assert(isValid() && isValidExtended(ix-i)); ix-=i; return *this;} \
538 NAME& operator+=(short s){assert(isValid() && SimTK::canStoreInInt(s) && isValidExtended(ix+(int)s)); ix+=(int)s; return *this;} \
539 NAME& operator-=(short s){assert(isValid() && SimTK::canStoreInInt(s) && isValidExtended(ix-(int)s)); ix-=(int)s; return *this;} \
540 NAME& operator+=(long l) {assert(isValid() && SimTK::canStoreInInt(l) && isValidExtended(ix+(int)l)); ix+=(int)l; return *this;} \
541 NAME& operator-=(long l) {assert(isValid() && SimTK::canStoreInInt(l) && isValidExtended(ix-(int)l)); ix-=(int)l; return *this;} \
542 NAME& operator+=(long long l) {assert(isValid() && SimTK::canStoreInInt(l) && isValidExtended(ix+(int)l)); ix+=(int)l; return *this;} \
543 NAME& operator-=(long long l) {assert(isValid() && SimTK::canStoreInInt(l) && isValidExtended(ix-(int)l)); ix-=(int)l; return *this;} \
544 NAME& operator+=(unsigned int u) {assert(isValid()&& SimTK::canStoreInInt(u) && isValid(ix+(int)u)); ix+=(int)u; return *this;} \
545 NAME& operator-=(unsigned int u) {assert(isValid()&& SimTK::canStoreInInt(u) && isValidExtended(ix-(int)u)); ix-=(int)u; return *this;} \
546 NAME& operator+=(unsigned short us){assert(isValid()&& SimTK::canStoreInInt(us) && isValid(ix+(int)us)); ix+=(int)us; return *this;} \
547 NAME& operator-=(unsigned short us){assert(isValid()&& SimTK::canStoreInInt(us) && isValidExtended(ix-(int)us)); ix-=(int)us; return *this;} \
548 NAME& operator+=(unsigned long ul) {assert(isValid()&& SimTK::canStoreInInt(ul) && isValid(ix+(int)ul)); ix+=(int)ul; return *this;} \
549 NAME& operator-=(unsigned long ul) {assert(isValid()&& SimTK::canStoreInInt(ul) && isValidExtended(ix-(int)ul)); ix-=(int)ul; return *this;} \
550 NAME& operator+=(unsigned long long ul) {assert(isValid()&& SimTK::canStoreInInt(ul) && isValid(ix+(int)ul)); ix+=(int)ul; return *this;} \
551 NAME& operator-=(unsigned long long ul) {assert(isValid()&& SimTK::canStoreInInt(ul) && isValidExtended(ix-(int)ul)); ix-=(int)ul; return *this;} \
552 \
553 static const NAME& Invalid() {static const NAME invalid; return invalid;} \
554 static bool isValid(int i) {return i>=0;} \
555 static bool isValid(short s){return s>=0;} \
556 static bool isValid(long l) {return SimTK::canStoreInNonnegativeInt(l);} \
557 static bool isValid(long long l) {return SimTK::canStoreInNonnegativeInt(l);} \
558 static bool isValid(unsigned int u) {return SimTK::canStoreInInt(u);} \
559 static bool isValid(unsigned short) {return true;} \
560 static bool isValid(unsigned long ul) {return SimTK::canStoreInInt(ul);} \
561 static bool isValid(unsigned long long ul) {return SimTK::canStoreInInt(ul);} \
562 static bool isValidExtended(int i) {return i>=-1;} \
563 static bool isValidExtended(short s){return s>=-1;} \
564 static bool isValidExtended(long l) {return SimTK::canStoreInInt(l) && l>=-1;} \
565 static bool isValidExtended(long long l) {return SimTK::canStoreInInt(l) && l>=-1;} \
566 /* IndexTraits for use in Array_<T,X> with this as X; same as int */ \
567 typedef int size_type; \
568 typedef int difference_type; \
569 static size_type max_size() {return std::numeric_limits<int>::max();} \
570};
571
578#ifndef NDEBUG
579 #define SimTK_DYNAMIC_CAST_DEBUG dynamic_cast // safe but slow
580#else
581 #define SimTK_DYNAMIC_CAST_DEBUG static_cast // unsafe but fast
582#endif
583
587#define SimTK_DOWNCAST(Derived,Parent) \
588 static bool isA(const Parent& p) \
589 { return dynamic_cast<const Derived*>(&p) != 0; } \
590 static const Derived& downcast(const Parent& p) \
591 { return SimTK_DYNAMIC_CAST_DEBUG<const Derived&>(p); } \
592 static Derived& updDowncast(Parent& p) \
593 { return SimTK_DYNAMIC_CAST_DEBUG<Derived&>(p); } \
594 static Derived& downcast(Parent& p) \
595 { return SimTK_DYNAMIC_CAST_DEBUG<Derived&>(p); }
596
599#define SimTK_DOWNCAST2(Derived,Helper,Parent) \
600 static bool isA(const Parent& p) \
601 { return Helper::isA(p); } \
602 static const Derived& downcast(const Parent& p) \
603 { return static_cast<const Derived&>(Helper::downcast(p)); } \
604 static Derived& updDowncast(Parent& p) \
605 { return static_cast<Derived&>(Helper::downcast(p)); } \
606 static Derived& downcast(Parent& p) \
607 { return static_cast<Derived&>(Helper::downcast(p)); }
608
609
613#define SimTK_PIMPL_DOWNCAST(Derived, Parent) \
614 static bool isInstanceOf(const Parent&); \
615 static const Derived& downcast(const Parent&); \
616 static Derived& updDowncast(Parent&)
617
618namespace SimTK {
619
622namespace Exception { }
623
626typedef SimTK_Real Real;
629typedef std::complex<Real> Complex;
631typedef std::complex<float> fComplex;
633typedef std::complex<double> dComplex;
634
635
636// Forward declaration giving template defaults must come before any
637// other declarations.
638template <int M, class ELT=Real, int STRIDE=1> class Vec;
639template <int N, class ELT=Real, int STRIDE=1> class Row;
640template <int M, int N, class ELT=Real, int CS=M, int RS=1> class Mat;
641template <int M, class ELT=Real, int RS=1> class SymMat;
642
645struct Segment {
646 Segment() : length(0), offset(0) { }
647 explicit Segment(int l, int ofs=0) : length(l), offset(ofs) {
648 assert(l>=0 && ofs>=0);
649 }
650 // default copy, assignment, destructor
653};
654
655// With compiler support for <=> operator these four methods below don't
656// need to be manually defined. (from gcc 10, clang 10 & msvc 19.22)
657// also exclude if SWIG_PYTHON is defined to build python bindings in OpenSim
658#if !defined(__cpp_lib_three_way_comparison) && !defined SWIG_PYTHON
659// These next four methods supply the missing relational operators for any
660// types L and R where L==R and L<R have been defined. This is like the
661// operators in the std::rel_ops namespace, except that those require both
662// types to be the same.
663template<class L, class R> inline
664bool operator!=(const L& left, const R& right)
665{ // test for inequality, in terms of equality
666 return !(left == right);
667}
668
669template<class L, class R> inline
670bool operator>(const L& left, const R& right)
671{ // test if left > right, in terms of operator<
672 return right < left;
673}
674
675template<class L, class R> inline
676bool operator<=(const L& left, const R& right)
677{ // test if left <= right, in terms of operator<
678 return !(right < left);
679}
680
681template<class L, class R> inline
682bool operator>=(const L& left, const R& right)
683{ // test if left >= right, in terms of operator<
684 return !(left < right);
685}
686#endif
687
693struct DontCopy {};
697struct TrustMe {};
698
701struct FalseType {};
704struct TrueType {};
705
707template <class L, class R> struct AndOpType {};
708template<> struct AndOpType<FalseType,FalseType> {typedef FalseType Result;};
709template<> struct AndOpType<FalseType,TrueType> {typedef FalseType Result;};
710template<> struct AndOpType<TrueType, FalseType> {typedef FalseType Result;};
711template<> struct AndOpType<TrueType, TrueType> {typedef TrueType Result;};
712
714template <class L, class R> struct OrOpType {};
715template<> struct OrOpType<FalseType,FalseType> {typedef FalseType Result;};
716template<> struct OrOpType<FalseType,TrueType> {typedef TrueType Result;};
717template<> struct OrOpType<TrueType, FalseType> {typedef TrueType Result;};
718template<> struct OrOpType<TrueType, TrueType> {typedef TrueType Result;};
719
721template <class L, class R> struct XorOpType {};
722template<> struct XorOpType<FalseType,FalseType> {typedef FalseType Result;};
723template<> struct XorOpType<FalseType,TrueType> {typedef TrueType Result;};
724template<> struct XorOpType<TrueType, FalseType> {typedef TrueType Result;};
725template<> struct XorOpType<TrueType, TrueType> {typedef FalseType Result;};
726
728template <class T> struct IsIntegralType {
734 static const bool result = false;
735};
738#define SimTK_SPECIALIZE_INTEGRAL_TYPE(T) \
739 template<> struct IsIntegralType<T> \
740 {typedef TrueType Result; static const bool result = true;}
741
744// This causes problems when used with Qt which for some crazy
745// reason likes to make its own wchar_t rather than using the built in.
746// SimTK_SPECIALIZE_INTEGRAL_TYPE(wchar_t);
752SimTK_SPECIALIZE_INTEGRAL_TYPE(unsigned int); // a.k.a. "unsigned"
757
759template <class T> struct IsFloatingType {
765 static const bool result = false;
766};
769#define SimTK_SPECIALIZE_FLOATING_TYPE(T) \
770 template<> struct IsFloatingType<T> \
771 {typedef TrueType Result; static const bool result = true;}
772
775
777template <class T> struct IsVoidType {
783 static const bool result = false;
784};
785template<> struct IsVoidType<void>
786{typedef TrueType Result; static const bool result = true;};
787
800
801// This struct's sole use is to allow us to define the typedef
802// Is64BitPlatformType as equivalent to either TrueType or FalseType.
803template <bool is64Bit> struct Is64BitHelper {};
804template<> struct Is64BitHelper<true>
805{typedef TrueType Result; static const bool result = true;};
806template<> struct Is64BitHelper<false>
807{typedef FalseType Result; static const bool result = false;};
808
813// We use a constexpr function to avoid a bug in SWIG.
814constexpr bool detect64BitPlatform() { return (sizeof(size_t) > sizeof(int)); }
817
818
824std::string demangle(const char* name);
825
834std::string canonicalizeTypeName(std::string&& demangledTypeName);
835
838inline std::string canonicalizeTypeName(const std::string& demangledTypeName)
839{ return canonicalizeTypeName(std::string(demangledTypeName)); }
840
847std::string encodeTypeNameForXML(std::string&& canonicalizedTypeName);
848
851inline std::string encodeTypeNameForXML(const std::string& niceTypeName)
852{ return encodeTypeNameForXML(std::string(niceTypeName)); }
853
859std::string decodeXMLTypeName(std::string&& xmlTypeName);
860
863inline std::string decodeXMLTypeName(const std::string& xmlTypeName)
864{ return decodeXMLTypeName(std::string(xmlTypeName)); }
865
881template <class T> struct NiceTypeName {
885 static const char* name() {return typeid(T).name();}
890 static const std::string& namestr() {
891 static const std::string canonical =
893 return canonical;
894 }
897 static const std::string& xmlstr() {
898 static const std::string xml = encodeTypeNameForXML(namestr());
899 return xml;
900 }
901};
902
903} // namespace SimTK
904
911#define SimTK_NICETYPENAME_LITERAL(T) \
912namespace SimTK { \
913template <> struct NiceTypeName< T > { \
914 static const char* name() { return #T; } \
915 static const std::string& namestr() { \
916 static const std::string str(#T); \
917 return str; \
918 } \
919 static const std::string& xmlstr() { \
920 static const std::string xml = encodeTypeNameForXML(namestr()); \
921 return xml; \
922 } \
923}; \
924}
925
926// Some types for which we'd like to see nice type names.
929// This causes problems when used with Qt which for some crazy
930// reason likes to make its own wchar_t rather than using the built in.
931// SimTK_NICETYPENAME_LITERAL(wchar_t);
937SimTK_NICETYPENAME_LITERAL(unsigned); // preferred to "unsigned int"
941SimTK_NICETYPENAME_LITERAL(unsigned long long);
946SimTK_NICETYPENAME_LITERAL(std::complex<float>);
947SimTK_NICETYPENAME_LITERAL(std::complex<double>);
948SimTK_NICETYPENAME_LITERAL(std::complex<long double>);
951
952
953#endif /* C++ stuff */
954
955#endif /* SimTK_SimTKCOMMON_COMMON_H_ */
#define SimTK_SimTKCOMMON_EXPORT
Definition SimTKcommon/include/SimTKcommon/internal/common.h:224
#define SimTK_SPECIALIZE_INTEGRAL_TYPE(T)
This macro must be invoked once for each of the built-in integral types to specialize the IsIntegralT...
Definition SimTKcommon/include/SimTKcommon/internal/common.h:738
#define SimTK_NICETYPENAME_LITERAL(T)
This specializes the name of a type to be exactly the text you use to specify it, rather than whateve...
Definition SimTKcommon/include/SimTKcommon/internal/common.h:911
#define SimTK_SPECIALIZE_FLOATING_TYPE(T)
This macro must be invoked once for each of the built-in floating point types to specialize the IsFlo...
Definition SimTKcommon/include/SimTKcommon/internal/common.h:769
void SimTK_version_SimTKcommon(int *major, int *minor, int *build)
Obtain version information for the currently-loaded SimTKcommon library.
void SimTK_about_SimTKcommon(const char *key, int maxlen, char *value)
Obtain "about" information for the currently-loaded SimTKcommon library.
This class represents a small matrix whose size is known at compile time, containing elements of any ...
Definition Mat.h:100
This is a fixed-length row vector designed for no-overhead inline computation.
Definition Row.h:132
This is a small, fixed-size symmetric or Hermitian matrix designed for no-overhead inline computation...
Definition SymMat.h:87
This is a fixed-length column vector designed for no-overhead inline computation.
Definition Vec.h:186
This is the top-level SimTK namespace into which all SimTK names are placed to avoid collision with o...
Definition Assembler.h:37
bool isIndexInRange(char ix, char sz)
Definition SimTKcommon/include/SimTKcommon/internal/common.h:376
std::complex< double > dComplex
An abbreviation for std::complex<double> for consistency with others.
Definition SimTKcommon/include/SimTKcommon/internal/common.h:633
std::complex< Real > Complex
This is the default complex type for SimTK, with precision for the real and imaginary parts set to th...
Definition SimTKcommon/include/SimTKcommon/internal/common.h:629
bool canStoreInNonnegativeInt(bool)
Definition SimTKcommon/include/SimTKcommon/internal/common.h:339
bool isSizeInRange(char sz, char mx)
Definition SimTKcommon/include/SimTKcommon/internal/common.h:357
std::complex< float > fComplex
An abbreviation for std::complex<float> for consistency with others.
Definition SimTKcommon/include/SimTKcommon/internal/common.h:631
bool operator>(const L &left, const R &right)
Definition SimTKcommon/include/SimTKcommon/internal/common.h:670
bool operator>=(const L &left, const R &right)
Definition SimTKcommon/include/SimTKcommon/internal/common.h:682
constexpr bool detect64BitPlatform()
Compile-time test: this typedef will be TrueType if this is a 64-bit platform, meaning that the size ...
Definition SimTKcommon/include/SimTKcommon/internal/common.h:814
bool operator<=(const L &left, const R &right)
Definition SimTKcommon/include/SimTKcommon/internal/common.h:676
bool isNonnegative(bool)
Definition SimTKcommon/include/SimTKcommon/internal/common.h:392
SimTK_Real Real
This is the default compiled-in floating point type for SimTK, either float or double.
Definition SimTKcommon/include/SimTKcommon/internal/common.h:626
Is64BitHelper< Is64BitPlatform >::Result Is64BitPlatformType
Definition SimTKcommon/include/SimTKcommon/internal/common.h:816
bool operator!=(const L &left, const R &right)
Definition SimTKcommon/include/SimTKcommon/internal/common.h:664
bool canStoreInInt(bool)
Definition SimTKcommon/include/SimTKcommon/internal/common.h:324
static const bool Is64BitPlatform
Definition SimTKcommon/include/SimTKcommon/internal/common.h:815
static const int InvalidIndex
Definition SimTKcommon/include/SimTKcommon/internal/common.h:409
FalseType Result
Definition SimTKcommon/include/SimTKcommon/internal/common.h:708
FalseType Result
Definition SimTKcommon/include/SimTKcommon/internal/common.h:709
FalseType Result
Definition SimTKcommon/include/SimTKcommon/internal/common.h:710
TrueType Result
Definition SimTKcommon/include/SimTKcommon/internal/common.h:711
This is an operator for and-ing compile-time truth types.
Definition SimTKcommon/include/SimTKcommon/internal/common.h:707
This is a special type used for causing invocation of a particular constructor or method overload tha...
Definition SimTKcommon/include/SimTKcommon/internal/common.h:693
This is a compile-time equivalent of "false", used in compile-time condition checking in templatized ...
Definition SimTKcommon/include/SimTKcommon/internal/common.h:701
Definition SimTKcommon/include/SimTKcommon/internal/common.h:803
Compile-time test: is this one of the built-in "arithmetic" types, meaning an integral or floating ty...
Definition SimTKcommon/include/SimTKcommon/internal/common.h:790
static const bool result
This compile-time constant bool is true if the template type T is one of the integral or floating poi...
Definition SimTKcommon/include/SimTKcommon/internal/common.h:797
OrOpType< typename IsIntegralType< T >::Result, typename IsFloatingType< T >::Result > Result
This typedef is TrueType if the template type T is one of the integral; or floating point types,...
Definition SimTKcommon/include/SimTKcommon/internal/common.h:794
Compile-time type test: is this one of the built-in floating point types?
Definition SimTKcommon/include/SimTKcommon/internal/common.h:759
static const bool result
This compile-time constant bool is true if the template type T is a floating point type otherwise it ...
Definition SimTKcommon/include/SimTKcommon/internal/common.h:765
FalseType Result
This typedef is TrueType if the template type T is a floating point type; otherwise it is FalseType.
Definition SimTKcommon/include/SimTKcommon/internal/common.h:762
Compile-time type test: is this one of the built-in integral types?
Definition SimTKcommon/include/SimTKcommon/internal/common.h:728
FalseType Result
This typedef is TrueType if the template type T is an integral type; otherwise it is FalseType.
Definition SimTKcommon/include/SimTKcommon/internal/common.h:731
static const bool result
This compile-time constant bool is true if the template type T is an integral type otherwise it is fa...
Definition SimTKcommon/include/SimTKcommon/internal/common.h:734
Compile-time type test: is this the void type?
Definition SimTKcommon/include/SimTKcommon/internal/common.h:777
static const bool result
This compile-time constant bool is true if the template type T is "void" otherwise it is false.
Definition SimTKcommon/include/SimTKcommon/internal/common.h:783
FalseType Result
This typedef is TrueType if the template type T is "void"; otherwise it is FalseType.
Definition SimTKcommon/include/SimTKcommon/internal/common.h:780
Obtain human-readable and XML-usable names for arbitrarily-complicated C++ types.
Definition SimTKcommon/include/SimTKcommon/internal/common.h:881
static const char * name()
The default implementation of name() here returns the raw result from typeid(T).name() which will be ...
Definition SimTKcommon/include/SimTKcommon/internal/common.h:885
static const std::string & namestr()
The default implementation of namestr() attempts to return a nicely demangled and canonicalized type ...
Definition SimTKcommon/include/SimTKcommon/internal/common.h:890
std::string canonicalizeTypeName(const std::string &demangledTypeName)
Same, but takes an lvalue reference so has to copy the input.
Definition SimTKcommon/include/SimTKcommon/internal/common.h:838
std::string encodeTypeNameForXML(std::string &&canonicalizedTypeName)
Given a canonicalized type name, produce a modified version that is better-suited to use as an XML at...
std::string decodeXMLTypeName(const std::string &xmlTypeName)
Same, but takes an lvalue reference so has to copy the input.
Definition SimTKcommon/include/SimTKcommon/internal/common.h:863
std::string canonicalizeTypeName(std::string &&demangledTypeName)
Given a compiler-dependent demangled type name string as returned by SimTK::demangle(),...
std::string demangle(const char *name)
Attempt to demangle a type name as returned by typeid.name(), with the result hopefully suitable for ...
std::string encodeTypeNameForXML(const std::string &niceTypeName)
Same, but takes an lvalue reference so has to copy the input.
Definition SimTKcommon/include/SimTKcommon/internal/common.h:851
static const std::string & xmlstr()
The default implementation of xmlstr() takes the output of namestr() and invokes SimTK::encodeTypeNam...
Definition SimTKcommon/include/SimTKcommon/internal/common.h:897
std::string decodeXMLTypeName(std::string &&xmlTypeName)
Given a type name that was encoded for XML by SimTK::encodeTypeNameForXML(), restore it to its canoni...
FalseType Result
Definition SimTKcommon/include/SimTKcommon/internal/common.h:715
TrueType Result
Definition SimTKcommon/include/SimTKcommon/internal/common.h:716
TrueType Result
Definition SimTKcommon/include/SimTKcommon/internal/common.h:717
TrueType Result
Definition SimTKcommon/include/SimTKcommon/internal/common.h:718
This is an operator for or-ing compile-time truth types.
Definition SimTKcommon/include/SimTKcommon/internal/common.h:714
A convenient struct for anything requiring an offset and length to specify a segment of some larger s...
Definition SimTKcommon/include/SimTKcommon/internal/common.h:645
int length
Definition SimTKcommon/include/SimTKcommon/internal/common.h:651
int offset
Definition SimTKcommon/include/SimTKcommon/internal/common.h:652
Segment(int l, int ofs=0)
Definition SimTKcommon/include/SimTKcommon/internal/common.h:647
Segment()
Definition SimTKcommon/include/SimTKcommon/internal/common.h:646
This is a compile-time equivalent of "true", used in compile-time condition checking in templatized i...
Definition SimTKcommon/include/SimTKcommon/internal/common.h:704
This is a special type used for forcing invocation of a particularly dangerous constructor or method ...
Definition SimTKcommon/include/SimTKcommon/internal/common.h:697
FalseType Result
Definition SimTKcommon/include/SimTKcommon/internal/common.h:722
TrueType Result
Definition SimTKcommon/include/SimTKcommon/internal/common.h:723
TrueType Result
Definition SimTKcommon/include/SimTKcommon/internal/common.h:724
FalseType Result
Definition SimTKcommon/include/SimTKcommon/internal/common.h:725
This is an operator for exclusive or-ing compile-time truth types.
Definition SimTKcommon/include/SimTKcommon/internal/common.h:721