/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_PRIVATE_COMMON_H_ #define _ODE_PRIVATE_COMMON_H_ #include "typedefs.h" #include "error.h" #include #include #ifndef SIZE_MAX #define SIZE_MAX ((sizeint)(-1)) #endif #define dMACRO_MAX(a, b) ((a) > (b) ? (a) : (b)) #define dMACRO_MIN(a, b) ((a) < (b) ? (a) : (b)) #ifdef dSINGLE #define dEpsilon FLT_EPSILON #else #define dEpsilon DBL_EPSILON #endif #ifdef dSINGLE #if !defined(FLT_MANT_DIG) #define FLT_MANT_DIG 24 #endif #define dMaxExact ((float)((1UL << FLT_MANT_DIG) - 1)) #define dMinExact ((float)(-dMaxExact)) #else // #ifndef dSINGLE #if !defined(DBL_MANT_DIG) #define DBL_MANT_DIG 53 #endif #define dMaxExact (double)((1ULL << DBL_MANT_DIG) - 1) #define dMinExact ((double)(-dMaxExact)) #endif // #ifndef dSINGLE #define dMaxIntExact dMACRO_MIN(dMaxExact, (dReal)INT_MAX) #define dMinIntExact dMACRO_MAX(dMinExact, (dReal)INT_MIN) #ifndef offsetof #define offsetof(s, m) ((sizeint)&(((s *)8)->m) - (sizeint)8) #endif #ifndef membersize #define membersize(s, m) (sizeof(((s *)8)->m)) #endif #ifndef endoffsetof #define endoffsetof(s, m) ((sizeint)((sizeint)&(((s *)8)->m) - (sizeint)8) + sizeof(((s *)8)->m)) #endif /* the efficient alignment. most platforms align data structures to some * number of bytes, but this is not always the most efficient alignment. * for example, many x86 compilers align to 4 bytes, but on a pentium it * is important to align doubles to 8 byte boundaries (for speed), and * the 4 floats in a SIMD register to 16 byte boundaries. many other * platforms have similar behavior. setting a larger alignment can waste * a (very) small amount of memory. NOTE: this number must be a power of * two. this is set to 16 by default. */ #ifndef EFFICIENT_ALIGNMENT #define EFFICIENT_ALIGNMENT 16 #endif #define dALIGN_SIZE(buf_size, alignment) (((buf_size) + (alignment - 1)) & (int)(~(alignment - 1))) // Casting the mask to int ensures sign-extension to larger integer sizes #define dALIGN_PTR(buf_ptr, alignment) ((void *)(((uintptr)(buf_ptr) + ((alignment) - 1)) & (int)(~(alignment - 1)))) // Casting the mask to int ensures sign-extension to larger integer sizes /* round something up to be a multiple of the EFFICIENT_ALIGNMENT */ #define dEFFICIENT_SIZE(x) dALIGN_SIZE(x, EFFICIENT_ALIGNMENT) #define dEFFICIENT_PTR(p) dALIGN_PTR(p, EFFICIENT_ALIGNMENT) #define dOFFSET_EFFICIENTLY(p, b) ((void *)((uintptr)(p) + dEFFICIENT_SIZE(b))) #define dOVERALIGNED_SIZE(size, alignment) dEFFICIENT_SIZE((size) + ((alignment) - EFFICIENT_ALIGNMENT)) #define dOVERALIGNED_PTR(buf_ptr, alignment) dALIGN_PTR(buf_ptr, alignment) #define dOFFSET_OVERALIGNEDLY(buf_ptr, size, alignment) ((void *)((uintptr)(buf_ptr) + dOVERALIGNED_SIZE(size, alignment))) #define dDERIVE_SIZE_UNION_PADDING_ELEMENTS(DataSize, ElementType) (((DataSize) + sizeof(ElementType) - 1) / sizeof(ElementType)) #define dDERIVE_TYPE_UNION_PADDING_ELEMENTS(DataType, ElementType) dDERIVE_SIZE_UNION_PADDING_ELEMENTS(sizeof(DataType), ElementType) #define dDERIVE_SIZE_EXTRA_PADDING_ELEMENTS(DataSize, AlignmentSize, ElementType) (((dALIGN_SIZE(DataSize, dMACRO_MAX(AlignmentSize, sizeof(ElementType))) - (DataSize)) / sizeof(ElementType)) /* alloca aligned to the EFFICIENT_ALIGNMENT. note that this can waste * up to 15 bytes per allocation, depending on what alloca() returns. */ #define dALLOCA16(n) \ dEFFICIENT_PTR(alloca((n)+(EFFICIENT_ALIGNMENT))) class dxAlignedAllocation { public: dxAlignedAllocation(): m_userAreaPointer(NULL), m_bufferAllocated(NULL), m_sizeUsed(0) {} ~dxAlignedAllocation() { freeAllocation(); } void *allocAligned(sizeint sizeRequired, unsigned alignmentRequired) { dIASSERT((alignmentRequired & (alignmentRequired - 1)) == 0); dIASSERT(alignmentRequired <= SIZE_MAX - sizeRequired); sizeint sizeToUse = sizeRequired + alignmentRequired; void *bufferPointer = dAlloc(sizeToUse); void *userAreaPointer = bufferPointer != NULL && alignmentRequired != 0 ? dALIGN_PTR(bufferPointer, alignmentRequired) : bufferPointer; assignData(userAreaPointer, bufferPointer, sizeToUse); return userAreaPointer; } void *getUserAreaPointer() const { return m_userAreaPointer; } sizeint getUserAreaSize() const { return m_sizeUsed - ((uint8 *)m_userAreaPointer - (uint8 *)m_bufferAllocated); } void freeAllocation() { sizeint sizeUsed; void *bufferPointer = extractData(sizeUsed); if (bufferPointer != NULL) { dFree(bufferPointer, sizeUsed); } } private: void assignData(void *userAreaPointer, void *bufferAllocated, sizeint sizeUsed) { dIASSERT(m_userAreaPointer == NULL); dIASSERT(m_bufferAllocated == NULL); dIASSERT(m_sizeUsed == 0); m_userAreaPointer = userAreaPointer; m_bufferAllocated = bufferAllocated; m_sizeUsed = sizeUsed; } void *extractData(sizeint &out_sizeUsed) { void *bufferPointer = m_bufferAllocated; if (bufferPointer != NULL) { out_sizeUsed = m_sizeUsed; m_userAreaPointer = NULL; m_bufferAllocated = NULL; m_sizeUsed = 0; } return bufferPointer; } private: void *m_userAreaPointer; void *m_bufferAllocated; sizeint m_sizeUsed; }; template inline bool _cast_to_smaller(DstType &dtOutResult, const SrcType &stArgument) { return (SrcType)(dtOutResult = (DstType)stArgument) == stArgument; } #if defined(__GNUC__) #define dCAST_TO_SMALLER(TargetType, SourceValue) ({ TargetType ttCastSmallerValue; dIVERIFY(_cast_to_smaller(ttCastSmallerValue, SourceValue)); ttCastSmallerValue; }) #else // #if !defined(__GNUC__) #define dCAST_TO_SMALLER(TargetType, SourceValue) templateCAST_TO_SMALLER(SourceValue) template inline TTargetType templateCAST_TO_SMALLER(const TSourceType &stSourceValue) { TTargetType ttCastSmallerValue; dIVERIFY(_cast_to_smaller(ttCastSmallerValue, stSourceValue)); return ttCastSmallerValue; } #endif // #if !defined(__GNUC__) template inline void dxSwap(value_type &one, value_type &another) { std::swap(one, another); } template inline value_type dxClamp(const value_type &value, const lo_type &lo, const hi_type &hi) { return value < lo ? (value_type)lo : value > hi ? (value_type)hi : value; } template union _const_type_cast_union { explicit _const_type_cast_union(const void *psvCharBuffer): m_psvCharBuffer(psvCharBuffer) {} operator const Type *() const { return m_pstTypedPointer; } const Type &operator *() const { return *m_pstTypedPointer; } const Type *operator ->() const { return m_pstTypedPointer; } const Type &operator [](diffint diElementIndex) const { return m_pstTypedPointer[diElementIndex]; } const Type &operator [](sizeint siElementIndex) const { return m_pstTypedPointer[siElementIndex]; } const void *m_psvCharBuffer; const Type *m_pstTypedPointer; }; template union _type_cast_union { explicit _type_cast_union(void *psvCharBuffer): m_psvCharBuffer(psvCharBuffer) {} operator Type *() const { return m_pstTypedPointer; } Type &operator *() const { return *m_pstTypedPointer; } Type *operator ->() const { return m_pstTypedPointer; } Type &operator [](diffint diElementIndex) const { return m_pstTypedPointer[diElementIndex]; } Type &operator [](sizeint siElementIndex) const { return m_pstTypedPointer[siElementIndex]; } void *m_psvCharBuffer; Type *m_pstTypedPointer; }; template struct _sized_signed; template<> struct _sized_signed { typedef int8 type; }; template<> struct _sized_signed { typedef int16 type; }; template<> struct _sized_signed { typedef int32 type; }; template<> struct _sized_signed { typedef int64 type; }; template struct _make_signed { typedef typename _sized_signed::type type; }; template struct _sized_unsigned; template<> struct _sized_unsigned { typedef uint8 type; }; template<> struct _sized_unsigned { typedef uint16 type; }; template<> struct _sized_unsigned { typedef uint32 type; }; template<> struct _sized_unsigned { typedef uint64 type; }; template struct _make_unsigned { typedef typename _sized_unsigned::type type; }; // template // inline // bool dxInRange(tvalueint viValue, tminint miMin, tmaxint miMax) // { // return (typename _sized_unsigned::type)(viValue - miMin) < (typename _sized_unsigned::type)(miMax - miMin); // } // #define dIN_RANGE(aval, amin, amax) dxInRange(aval, amin, amax) #define dIN_RANGE(aval, amin, amax) ((_sized_unsigned::type)((_sized_unsigned::type)(aval) - (_sized_unsigned::type)(amin)) < (_sized_unsigned::type)((_sized_unsigned::type)(amax) - (_sized_unsigned::type)(amin))) #define dTMPL_IN_RANGE(aval, amin, amax) ((typename _sized_unsigned::type)((typename _sized_unsigned::type)(aval) - (typename _sized_unsigned::type)(amin)) < (typename _sized_unsigned::type)((typename _sized_unsigned::type)(amax) - (typename _sized_unsigned::type)(amin))) #define dCLAMP(aval, alo, ahi) dxClamp(aval, alo, ahi) #define dARRAY_SIZE(aarr) (sizeof(aarr) / sizeof((aarr)[0])) #define dSTATIC_ARRAY_SIZE(aclass, aarr) dARRAY_SIZE(((aclass *)sizeof(void *))->aarr) #endif