/************************************************************************************ PublicHeader: OVR.h Filename : OVR_Alg.h Content : Simple general purpose algorithms: Sort, Binary Search, etc. Created : September 19, 2012 Notes : Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. Use of this software is subject to the terms of the Oculus license agreement provided at the time of installation or download, or which otherwise accompanies this software in either electronic or hard copy form. ************************************************************************************/ #ifndef OVR_Alg_h #define OVR_Alg_h #include "OVR_Types.h" #include <string.h> namespace OVR { namespace Alg { //----------------------------------------------------------------------------------- // ***** Operator extensions template <typename T> OVR_FORCE_INLINE void Swap(T &a, T &b) { T temp(a); a = b; b = temp; } // ***** min/max are not implemented in Visual Studio 6 standard STL template <typename T> OVR_FORCE_INLINE const T Min(const T a, const T b) { return (a < b) ? a : b; } template <typename T> OVR_FORCE_INLINE const T Max(const T a, const T b) { return (b < a) ? a : b; } template <typename T> OVR_FORCE_INLINE const T Clamp(const T v, const T minVal, const T maxVal) { return Max<T>(minVal, Min<T>(v, maxVal)); } template <typename T> OVR_FORCE_INLINE int Chop(T f) { return (int)f; } template <typename T> OVR_FORCE_INLINE T Lerp(T a, T b, T f) { return (b - a) * f + a; } // These functions stand to fix a stupid VC++ warning (with /Wp64 on): // "warning C4267: 'argument' : conversion from 'size_t' to 'const unsigned', possible loss of data" // Use these functions instead of gmin/gmax if the argument has size // of the pointer to avoid the warning. Though, functionally they are // absolutelly the same as regular gmin/gmax. template <typename T> OVR_FORCE_INLINE const T PMin(const T a, const T b) { OVR_COMPILER_ASSERT(sizeof(T) == sizeof(UPInt)); return (a < b) ? a : b; } template <typename T> OVR_FORCE_INLINE const T PMax(const T a, const T b) { OVR_COMPILER_ASSERT(sizeof(T) == sizeof(UPInt)); return (b < a) ? a : b; } template <typename T> OVR_FORCE_INLINE const T Abs(const T v) { return (v>=0) ? v : -v; } //----------------------------------------------------------------------------------- // ***** OperatorLess // template<class T> struct OperatorLess { static bool Compare(const T& a, const T& b) { return a < b; } }; //----------------------------------------------------------------------------------- // ***** QuickSortSliced // // Sort any part of any array: plain, Array, ArrayPaged, ArrayUnsafe. // The range is specified with start, end, where "end" is exclusive! // The comparison predicate must be specified. template<class Array, class Less> void QuickSortSliced(Array& arr, UPInt start, UPInt end, Less less) { enum { Threshold = 9 }; if(end - start < 2) return; SPInt stack[80]; SPInt* top = stack; SPInt base = (SPInt)start; SPInt limit = (SPInt)end; for(;;) { SPInt len = limit - base; SPInt i, j, pivot; if(len > Threshold) { // we use base + len/2 as the pivot pivot = base + len / 2; Swap(arr[base], arr[pivot]); i = base + 1; j = limit - 1; // now ensure that *i <= *base <= *j if(less(arr[j], arr[i])) Swap(arr[j], arr[i]); if(less(arr[base], arr[i])) Swap(arr[base], arr[i]); if(less(arr[j], arr[base])) Swap(arr[j], arr[base]); for(;;) { do i++; while( less(arr[i], arr[base]) ); do j--; while( less(arr[base], arr[j]) ); if( i > j ) { break; } Swap(arr[i], arr[j]); } Swap(arr[base], arr[j]); // now, push the largest sub-array if(j - base > limit - i) { top[0] = base; top[1] = j; base = i; } else { top[0] = i; top[1] = limit; limit = j; } top += 2; } else { // the sub-array is small, perform insertion sort j = base; i = j + 1; for(; i < limit; j = i, i++) { for(; less(arr[j + 1], arr[j]); j--) { Swap(arr[j + 1], arr[j]); if(j == base) { break; } } } if(top > stack) { top -= 2; base = top[0]; limit = top[1]; } else { break; } } } } //----------------------------------------------------------------------------------- // ***** QuickSortSliced // // Sort any part of any array: plain, Array, ArrayPaged, ArrayUnsafe. // The range is specified with start, end, where "end" is exclusive! // The data type must have a defined "<" operator. template<class Array> void QuickSortSliced(Array& arr, UPInt start, UPInt end) { typedef typename Array::ValueType ValueType; QuickSortSliced(arr, start, end, OperatorLess<ValueType>::Compare); } // Same as corresponding G_QuickSortSliced but with checking array limits to avoid // crash in the case of wrong comparator functor. template<class Array, class Less> bool QuickSortSlicedSafe(Array& arr, UPInt start, UPInt end, Less less) { enum { Threshold = 9 }; if(end - start < 2) return true; SPInt stack[80]; SPInt* top = stack; SPInt base = (SPInt)start; SPInt limit = (SPInt)end; for(;;) { SPInt len = limit - base; SPInt i, j, pivot; if(len > Threshold) { // we use base + len/2 as the pivot pivot = base + len / 2; Swap(arr[base], arr[pivot]); i = base + 1; j = limit - 1; // now ensure that *i <= *base <= *j if(less(arr[j], arr[i])) Swap(arr[j], arr[i]); if(less(arr[base], arr[i])) Swap(arr[base], arr[i]); if(less(arr[j], arr[base])) Swap(arr[j], arr[base]); for(;;) { do { i++; if (i >= limit) return false; } while( less(arr[i], arr[base]) ); do { j--; if (j < 0) return false; } while( less(arr[base], arr[j]) ); if( i > j ) { break; } Swap(arr[i], arr[j]); } Swap(arr[base], arr[j]); // now, push the largest sub-array if(j - base > limit - i) { top[0] = base; top[1] = j; base = i; } else { top[0] = i; top[1] = limit; limit = j; } top += 2; } else { // the sub-array is small, perform insertion sort j = base; i = j + 1; for(; i < limit; j = i, i++) { for(; less(arr[j + 1], arr[j]); j--) { Swap(arr[j + 1], arr[j]); if(j == base) { break; } } } if(top > stack) { top -= 2; base = top[0]; limit = top[1]; } else { break; } } } return true; } template<class Array> bool QuickSortSlicedSafe(Array& arr, UPInt start, UPInt end) { typedef typename Array::ValueType ValueType; return QuickSortSlicedSafe(arr, start, end, OperatorLess<ValueType>::Compare); } //----------------------------------------------------------------------------------- // ***** QuickSort // // Sort an array Array, ArrayPaged, ArrayUnsafe. // The array must have GetSize() function. // The comparison predicate must be specified. template<class Array, class Less> void QuickSort(Array& arr, Less less) { QuickSortSliced(arr, 0, arr.GetSize(), less); } // checks for boundaries template<class Array, class Less> bool QuickSortSafe(Array& arr, Less less) { return QuickSortSlicedSafe(arr, 0, arr.GetSize(), less); } //----------------------------------------------------------------------------------- // ***** QuickSort // // Sort an array Array, ArrayPaged, ArrayUnsafe. // The array must have GetSize() function. // The data type must have a defined "<" operator. template<class Array> void QuickSort(Array& arr) { typedef typename Array::ValueType ValueType; QuickSortSliced(arr, 0, arr.GetSize(), OperatorLess<ValueType>::Compare); } template<class Array> bool QuickSortSafe(Array& arr) { typedef typename Array::ValueType ValueType; return QuickSortSlicedSafe(arr, 0, arr.GetSize(), OperatorLess<ValueType>::Compare); } //----------------------------------------------------------------------------------- // ***** InsertionSortSliced // // Sort any part of any array: plain, Array, ArrayPaged, ArrayUnsafe. // The range is specified with start, end, where "end" is exclusive! // The comparison predicate must be specified. // Unlike Quick Sort, the Insertion Sort works much slower in average, // but may be much faster on almost sorted arrays. Besides, it guarantees // that the elements will not be swapped if not necessary. For example, // an array with all equal elements will remain "untouched", while // Quick Sort will considerably shuffle the elements in this case. template<class Array, class Less> void InsertionSortSliced(Array& arr, UPInt start, UPInt end, Less less) { UPInt j = start; UPInt i = j + 1; UPInt limit = end; for(; i < limit; j = i, i++) { for(; less(arr[j + 1], arr[j]); j--) { Swap(arr[j + 1], arr[j]); if(j <= start) { break; } } } } //----------------------------------------------------------------------------------- // ***** InsertionSortSliced // // Sort any part of any array: plain, Array, ArrayPaged, ArrayUnsafe. // The range is specified with start, end, where "end" is exclusive! // The data type must have a defined "<" operator. template<class Array> void InsertionSortSliced(Array& arr, UPInt start, UPInt end) { typedef typename Array::ValueType ValueType; InsertionSortSliced(arr, start, end, OperatorLess<ValueType>::Compare); } //----------------------------------------------------------------------------------- // ***** InsertionSort // // Sort an array Array, ArrayPaged, ArrayUnsafe. // The array must have GetSize() function. // The comparison predicate must be specified. template<class Array, class Less> void InsertionSort(Array& arr, Less less) { InsertionSortSliced(arr, 0, arr.GetSize(), less); } //----------------------------------------------------------------------------------- // ***** InsertionSort // // Sort an array Array, ArrayPaged, ArrayUnsafe. // The array must have GetSize() function. // The data type must have a defined "<" operator. template<class Array> void InsertionSort(Array& arr) { typedef typename Array::ValueType ValueType; InsertionSortSliced(arr, 0, arr.GetSize(), OperatorLess<ValueType>::Compare); } //----------------------------------------------------------------------------------- // ***** LowerBoundSliced // template<class Array, class Value, class Less> UPInt LowerBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val, Less less) { SPInt first = (SPInt)start; SPInt len = (SPInt)(end - start); SPInt half; SPInt middle; while(len > 0) { half = len >> 1; middle = first + half; if(less(arr[middle], val)) { first = middle + 1; len = len - half - 1; } else { len = half; } } return (UPInt)first; } //----------------------------------------------------------------------------------- // ***** LowerBoundSliced // template<class Array, class Value> UPInt LowerBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val) { return LowerBoundSliced(arr, start, end, val, OperatorLess<Value>::Compare); } //----------------------------------------------------------------------------------- // ***** LowerBoundSized // template<class Array, class Value> UPInt LowerBoundSized(const Array& arr, UPInt size, const Value& val) { return LowerBoundSliced(arr, 0, size, val, OperatorLess<Value>::Compare); } //----------------------------------------------------------------------------------- // ***** LowerBound // template<class Array, class Value, class Less> UPInt LowerBound(const Array& arr, const Value& val, Less less) { return LowerBoundSliced(arr, 0, arr.GetSize(), val, less); } //----------------------------------------------------------------------------------- // ***** LowerBound // template<class Array, class Value> UPInt LowerBound(const Array& arr, const Value& val) { return LowerBoundSliced(arr, 0, arr.GetSize(), val, OperatorLess<Value>::Compare); } //----------------------------------------------------------------------------------- // ***** UpperBoundSliced // template<class Array, class Value, class Less> UPInt UpperBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val, Less less) { SPInt first = (SPInt)start; SPInt len = (SPInt)(end - start); SPInt half; SPInt middle; while(len > 0) { half = len >> 1; middle = first + half; if(less(val, arr[middle])) { len = half; } else { first = middle + 1; len = len - half - 1; } } return (UPInt)first; } //----------------------------------------------------------------------------------- // ***** UpperBoundSliced // template<class Array, class Value> UPInt UpperBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val) { return UpperBoundSliced(arr, start, end, val, OperatorLess<Value>::Compare); } //----------------------------------------------------------------------------------- // ***** UpperBoundSized // template<class Array, class Value> UPInt UpperBoundSized(const Array& arr, UPInt size, const Value& val) { return UpperBoundSliced(arr, 0, size, val, OperatorLess<Value>::Compare); } //----------------------------------------------------------------------------------- // ***** UpperBound // template<class Array, class Value, class Less> UPInt UpperBound(const Array& arr, const Value& val, Less less) { return UpperBoundSliced(arr, 0, arr.GetSize(), val, less); } //----------------------------------------------------------------------------------- // ***** UpperBound // template<class Array, class Value> UPInt UpperBound(const Array& arr, const Value& val) { return UpperBoundSliced(arr, 0, arr.GetSize(), val, OperatorLess<Value>::Compare); } //----------------------------------------------------------------------------------- // ***** ReverseArray // template<class Array> void ReverseArray(Array& arr) { SPInt from = 0; SPInt to = arr.GetSize() - 1; while(from < to) { Swap(arr[from], arr[to]); ++from; --to; } } // ***** AppendArray // template<class CDst, class CSrc> void AppendArray(CDst& dst, const CSrc& src) { UPInt i; for(i = 0; i < src.GetSize(); i++) dst.PushBack(src[i]); } //----------------------------------------------------------------------------------- // ***** ArrayAdaptor // // A simple adapter that provides the GetSize() method and overloads // operator []. Used to wrap plain arrays in QuickSort and such. template<class T> class ArrayAdaptor { public: typedef T ValueType; ArrayAdaptor() : Data(0), Size(0) {} ArrayAdaptor(T* ptr, UPInt size) : Data(ptr), Size(size) {} UPInt GetSize() const { return Size; } const T& operator [] (UPInt i) const { return Data[i]; } T& operator [] (UPInt i) { return Data[i]; } private: T* Data; UPInt Size; }; //----------------------------------------------------------------------------------- // ***** GConstArrayAdaptor // // A simple const adapter that provides the GetSize() method and overloads // operator []. Used to wrap plain arrays in LowerBound and such. template<class T> class ConstArrayAdaptor { public: typedef T ValueType; ConstArrayAdaptor() : Data(0), Size(0) {} ConstArrayAdaptor(const T* ptr, UPInt size) : Data(ptr), Size(size) {} UPInt GetSize() const { return Size; } const T& operator [] (UPInt i) const { return Data[i]; } private: const T* Data; UPInt Size; }; //----------------------------------------------------------------------------------- extern const UByte UpperBitTable[256]; extern const UByte LowerBitTable[256]; //----------------------------------------------------------------------------------- inline UByte UpperBit(UPInt val) { #ifndef OVR_64BIT_POINTERS if (val & 0xFFFF0000) { return (val & 0xFF000000) ? UpperBitTable[(val >> 24) ] + 24: UpperBitTable[(val >> 16) & 0xFF] + 16; } return (val & 0xFF00) ? UpperBitTable[(val >> 8) & 0xFF] + 8: UpperBitTable[(val ) & 0xFF]; #else if (val & 0xFFFFFFFF00000000) { if (val & 0xFFFF000000000000) { return (val & 0xFF00000000000000) ? UpperBitTable[(val >> 56) ] + 56: UpperBitTable[(val >> 48) & 0xFF] + 48; } return (val & 0xFF0000000000) ? UpperBitTable[(val >> 40) & 0xFF] + 40: UpperBitTable[(val >> 32) & 0xFF] + 32; } else { if (val & 0xFFFF0000) { return (val & 0xFF000000) ? UpperBitTable[(val >> 24) ] + 24: UpperBitTable[(val >> 16) & 0xFF] + 16; } return (val & 0xFF00) ? UpperBitTable[(val >> 8) & 0xFF] + 8: UpperBitTable[(val ) & 0xFF]; } #endif } //----------------------------------------------------------------------------------- inline UByte LowerBit(UPInt val) { #ifndef OVR_64BIT_POINTERS if (val & 0xFFFF) { return (val & 0xFF) ? LowerBitTable[ val & 0xFF]: LowerBitTable[(val >> 8) & 0xFF] + 8; } return (val & 0xFF0000) ? LowerBitTable[(val >> 16) & 0xFF] + 16: LowerBitTable[(val >> 24) & 0xFF] + 24; #else if (val & 0xFFFFFFFF) { if (val & 0xFFFF) { return (val & 0xFF) ? LowerBitTable[ val & 0xFF]: LowerBitTable[(val >> 8) & 0xFF] + 8; } return (val & 0xFF0000) ? LowerBitTable[(val >> 16) & 0xFF] + 16: LowerBitTable[(val >> 24) & 0xFF] + 24; } else { if (val & 0xFFFF00000000) { return (val & 0xFF00000000) ? LowerBitTable[(val >> 32) & 0xFF] + 32: LowerBitTable[(val >> 40) & 0xFF] + 40; } return (val & 0xFF000000000000) ? LowerBitTable[(val >> 48) & 0xFF] + 48: LowerBitTable[(val >> 56) & 0xFF] + 56; } #endif } // ******* Special (optimized) memory routines // Note: null (bad) pointer is not tested class MemUtil { public: // Memory compare static int Cmp (const void* p1, const void* p2, UPInt byteCount) { return memcmp(p1, p2, byteCount); } static int Cmp16(const void* p1, const void* p2, UPInt int16Count); static int Cmp32(const void* p1, const void* p2, UPInt int32Count); static int Cmp64(const void* p1, const void* p2, UPInt int64Count); }; // ** Inline Implementation inline int MemUtil::Cmp16(const void* p1, const void* p2, UPInt int16Count) { SInt16* pa = (SInt16*)p1; SInt16* pb = (SInt16*)p2; unsigned ic = 0; if (int16Count == 0) return 0; while (pa[ic] == pb[ic]) if (++ic==int16Count) return 0; return pa[ic] > pb[ic] ? 1 : -1; } inline int MemUtil::Cmp32(const void* p1, const void* p2, UPInt int32Count) { SInt32* pa = (SInt32*)p1; SInt32* pb = (SInt32*)p2; unsigned ic = 0; if (int32Count == 0) return 0; while (pa[ic] == pb[ic]) if (++ic==int32Count) return 0; return pa[ic] > pb[ic] ? 1 : -1; } inline int MemUtil::Cmp64(const void* p1, const void* p2, UPInt int64Count) { SInt64* pa = (SInt64*)p1; SInt64* pb = (SInt64*)p2; unsigned ic = 0; if (int64Count == 0) return 0; while (pa[ic] == pb[ic]) if (++ic==int64Count) return 0; return pa[ic] > pb[ic] ? 1 : -1; } // ** End Inline Implementation //----------------------------------------------------------------------------------- // ******* Byte Order Conversions namespace ByteUtil { // *** Swap Byte Order // Swap the byte order of a byte array inline void SwapOrder(void* pv, int size) { UByte* pb = (UByte*)pv; UByte temp; for (int i = 0; i < size>>1; i++) { temp = pb[size-1-i]; pb[size-1-i] = pb[i]; pb[i] = temp; } } // Swap the byte order of primitive types inline UByte SwapOrder(UByte v) { return v; } inline SByte SwapOrder(SByte v) { return v; } inline UInt16 SwapOrder(UInt16 v) { return UInt16(v>>8)|UInt16(v<<8); } inline SInt16 SwapOrder(SInt16 v) { return SInt16((UInt16(v)>>8)|(v<<8)); } inline UInt32 SwapOrder(UInt32 v) { return (v>>24)|((v&0x00FF0000)>>8)|((v&0x0000FF00)<<8)|(v<<24); } inline SInt32 SwapOrder(SInt32 p) { return (SInt32)SwapOrder(UInt32(p)); } inline UInt64 SwapOrder(UInt64 v) { return (v>>56) | ((v&UInt64(0x00FF000000000000))>>40) | ((v&UInt64(0x0000FF0000000000))>>24) | ((v&UInt64(0x000000FF00000000))>>8) | ((v&UInt64(0x00000000FF000000))<<8) | ((v&UInt64(0x0000000000FF0000))<<24) | ((v&UInt64(0x000000000000FF00))<<40) | (v<<56); } inline SInt64 SwapOrder(SInt64 v) { return (SInt64)SwapOrder(UInt64(v)); } inline float SwapOrder(float p) { union { float p; UInt32 v; } u; u.p = p; u.v = SwapOrder(u.v); return u.p; } inline double SwapOrder(double p) { union { double p; UInt64 v; } u; u.p = p; u.v = SwapOrder(u.v); return u.p; } // *** Byte-order conversion #if (OVR_BYTE_ORDER == OVR_LITTLE_ENDIAN) // Little Endian to System (LE) inline UByte LEToSystem(UByte v) { return v; } inline SByte LEToSystem(SByte v) { return v; } inline UInt16 LEToSystem(UInt16 v) { return v; } inline SInt16 LEToSystem(SInt16 v) { return v; } inline UInt32 LEToSystem(UInt32 v) { return v; } inline SInt32 LEToSystem(SInt32 v) { return v; } inline UInt64 LEToSystem(UInt64 v) { return v; } inline SInt64 LEToSystem(SInt64 v) { return v; } inline float LEToSystem(float v) { return v; } inline double LEToSystem(double v) { return v; } // Big Endian to System (LE) inline UByte BEToSystem(UByte v) { return SwapOrder(v); } inline SByte BEToSystem(SByte v) { return SwapOrder(v); } inline UInt16 BEToSystem(UInt16 v) { return SwapOrder(v); } inline SInt16 BEToSystem(SInt16 v) { return SwapOrder(v); } inline UInt32 BEToSystem(UInt32 v) { return SwapOrder(v); } inline SInt32 BEToSystem(SInt32 v) { return SwapOrder(v); } inline UInt64 BEToSystem(UInt64 v) { return SwapOrder(v); } inline SInt64 BEToSystem(SInt64 v) { return SwapOrder(v); } inline float BEToSystem(float v) { return SwapOrder(v); } inline double BEToSystem(double v) { return SwapOrder(v); } // System (LE) to Little Endian inline UByte SystemToLE(UByte v) { return v; } inline SByte SystemToLE(SByte v) { return v; } inline UInt16 SystemToLE(UInt16 v) { return v; } inline SInt16 SystemToLE(SInt16 v) { return v; } inline UInt32 SystemToLE(UInt32 v) { return v; } inline SInt32 SystemToLE(SInt32 v) { return v; } inline UInt64 SystemToLE(UInt64 v) { return v; } inline SInt64 SystemToLE(SInt64 v) { return v; } inline float SystemToLE(float v) { return v; } inline double SystemToLE(double v) { return v; } // System (LE) to Big Endian inline UByte SystemToBE(UByte v) { return SwapOrder(v); } inline SByte SystemToBE(SByte v) { return SwapOrder(v); } inline UInt16 SystemToBE(UInt16 v) { return SwapOrder(v); } inline SInt16 SystemToBE(SInt16 v) { return SwapOrder(v); } inline UInt32 SystemToBE(UInt32 v) { return SwapOrder(v); } inline SInt32 SystemToBE(SInt32 v) { return SwapOrder(v); } inline UInt64 SystemToBE(UInt64 v) { return SwapOrder(v); } inline SInt64 SystemToBE(SInt64 v) { return SwapOrder(v); } inline float SystemToBE(float v) { return SwapOrder(v); } inline double SystemToBE(double v) { return SwapOrder(v); } #elif (OVR_BYTE_ORDER == OVR_BIG_ENDIAN) // Little Endian to System (BE) inline UByte LEToSystem(UByte v) { return SwapOrder(v); } inline SByte LEToSystem(SByte v) { return SwapOrder(v); } inline UInt16 LEToSystem(UInt16 v) { return SwapOrder(v); } inline SInt16 LEToSystem(SInt16 v) { return SwapOrder(v); } inline UInt32 LEToSystem(UInt32 v) { return SwapOrder(v); } inline SInt32 LEToSystem(SInt32 v) { return SwapOrder(v); } inline UInt64 LEToSystem(UInt64 v) { return SwapOrder(v); } inline SInt64 LEToSystem(SInt64 v) { return SwapOrder(v); } inline float LEToSystem(float v) { return SwapOrder(v); } inline double LEToSystem(double v) { return SwapOrder(v); } // Big Endian to System (BE) inline UByte BEToSystem(UByte v) { return v; } inline SByte BEToSystem(SByte v) { return v; } inline UInt16 BEToSystem(UInt16 v) { return v; } inline SInt16 BEToSystem(SInt16 v) { return v; } inline UInt32 BEToSystem(UInt32 v) { return v; } inline SInt32 BEToSystem(SInt32 v) { return v; } inline UInt64 BEToSystem(UInt64 v) { return v; } inline SInt64 BEToSystem(SInt64 v) { return v; } inline float BEToSystem(float v) { return v; } inline double BEToSystem(double v) { return v; } // System (BE) to Little Endian inline UByte SystemToLE(UByte v) { return SwapOrder(v); } inline SByte SystemToLE(SByte v) { return SwapOrder(v); } inline UInt16 SystemToLE(UInt16 v) { return SwapOrder(v); } inline SInt16 SystemToLE(SInt16 v) { return SwapOrder(v); } inline UInt32 SystemToLE(UInt32 v) { return SwapOrder(v); } inline SInt32 SystemToLE(SInt32 v) { return SwapOrder(v); } inline UInt64 SystemToLE(UInt64 v) { return SwapOrder(v); } inline SInt64 SystemToLE(SInt64 v) { return SwapOrder(v); } inline float SystemToLE(float v) { return SwapOrder(v); } inline double SystemToLE(double v) { return SwapOrder(v); } // System (BE) to Big Endian inline UByte SystemToBE(UByte v) { return v; } inline SByte SystemToBE(SByte v) { return v; } inline UInt16 SystemToBE(UInt16 v) { return v; } inline SInt16 SystemToBE(SInt16 v) { return v; } inline UInt32 SystemToBE(UInt32 v) { return v; } inline SInt32 SystemToBE(SInt32 v) { return v; } inline UInt64 SystemToBE(UInt64 v) { return v; } inline SInt64 SystemToBE(SInt64 v) { return v; } inline float SystemToBE(float v) { return v; } inline double SystemToBE(double v) { return v; } #else #error "OVR_BYTE_ORDER must be defined to OVR_LITTLE_ENDIAN or OVR_BIG_ENDIAN" #endif } // namespace ByteUtil }} // OVR::Alg #endif