oculus1

view libovr/Src/Kernel/OVR_Alg.h @ 29:9a973ef0e2a3

fixed the performance issue under MacOSX by replacing glutSolidTeapot (which uses glEvalMesh) with my own teapot generator.
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 27 Oct 2013 06:31:18 +0200
parents e2f9e4603129
children
line source
1 /************************************************************************************
3 PublicHeader: OVR.h
4 Filename : OVR_Alg.h
5 Content : Simple general purpose algorithms: Sort, Binary Search, etc.
6 Created : September 19, 2012
7 Notes :
9 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
11 Use of this software is subject to the terms of the Oculus license
12 agreement provided at the time of installation or download, or which
13 otherwise accompanies this software in either electronic or hard copy form.
15 ************************************************************************************/
17 #ifndef OVR_Alg_h
18 #define OVR_Alg_h
20 #include "OVR_Types.h"
21 #include <string.h>
23 namespace OVR { namespace Alg {
26 //-----------------------------------------------------------------------------------
27 // ***** Operator extensions
29 template <typename T> OVR_FORCE_INLINE void Swap(T &a, T &b)
30 { T temp(a); a = b; b = temp; }
33 // ***** min/max are not implemented in Visual Studio 6 standard STL
35 template <typename T> OVR_FORCE_INLINE const T Min(const T a, const T b)
36 { return (a < b) ? a : b; }
38 template <typename T> OVR_FORCE_INLINE const T Max(const T a, const T b)
39 { return (b < a) ? a : b; }
41 template <typename T> OVR_FORCE_INLINE const T Clamp(const T v, const T minVal, const T maxVal)
42 { return Max<T>(minVal, Min<T>(v, maxVal)); }
44 template <typename T> OVR_FORCE_INLINE int Chop(T f)
45 { return (int)f; }
47 template <typename T> OVR_FORCE_INLINE T Lerp(T a, T b, T f)
48 { return (b - a) * f + a; }
51 // These functions stand to fix a stupid VC++ warning (with /Wp64 on):
52 // "warning C4267: 'argument' : conversion from 'size_t' to 'const unsigned', possible loss of data"
53 // Use these functions instead of gmin/gmax if the argument has size
54 // of the pointer to avoid the warning. Though, functionally they are
55 // absolutelly the same as regular gmin/gmax.
56 template <typename T> OVR_FORCE_INLINE const T PMin(const T a, const T b)
57 {
58 OVR_COMPILER_ASSERT(sizeof(T) == sizeof(UPInt));
59 return (a < b) ? a : b;
60 }
61 template <typename T> OVR_FORCE_INLINE const T PMax(const T a, const T b)
62 {
63 OVR_COMPILER_ASSERT(sizeof(T) == sizeof(UPInt));
64 return (b < a) ? a : b;
65 }
68 template <typename T> OVR_FORCE_INLINE const T Abs(const T v)
69 { return (v>=0) ? v : -v; }
72 //-----------------------------------------------------------------------------------
73 // ***** OperatorLess
74 //
75 template<class T> struct OperatorLess
76 {
77 static bool Compare(const T& a, const T& b)
78 {
79 return a < b;
80 }
81 };
84 //-----------------------------------------------------------------------------------
85 // ***** QuickSortSliced
86 //
87 // Sort any part of any array: plain, Array, ArrayPaged, ArrayUnsafe.
88 // The range is specified with start, end, where "end" is exclusive!
89 // The comparison predicate must be specified.
90 template<class Array, class Less>
91 void QuickSortSliced(Array& arr, UPInt start, UPInt end, Less less)
92 {
93 enum
94 {
95 Threshold = 9
96 };
98 if(end - start < 2) return;
100 SPInt stack[80];
101 SPInt* top = stack;
102 SPInt base = (SPInt)start;
103 SPInt limit = (SPInt)end;
105 for(;;)
106 {
107 SPInt len = limit - base;
108 SPInt i, j, pivot;
110 if(len > Threshold)
111 {
112 // we use base + len/2 as the pivot
113 pivot = base + len / 2;
114 Swap(arr[base], arr[pivot]);
116 i = base + 1;
117 j = limit - 1;
119 // now ensure that *i <= *base <= *j
120 if(less(arr[j], arr[i])) Swap(arr[j], arr[i]);
121 if(less(arr[base], arr[i])) Swap(arr[base], arr[i]);
122 if(less(arr[j], arr[base])) Swap(arr[j], arr[base]);
124 for(;;)
125 {
126 do i++; while( less(arr[i], arr[base]) );
127 do j--; while( less(arr[base], arr[j]) );
129 if( i > j )
130 {
131 break;
132 }
134 Swap(arr[i], arr[j]);
135 }
137 Swap(arr[base], arr[j]);
139 // now, push the largest sub-array
140 if(j - base > limit - i)
141 {
142 top[0] = base;
143 top[1] = j;
144 base = i;
145 }
146 else
147 {
148 top[0] = i;
149 top[1] = limit;
150 limit = j;
151 }
152 top += 2;
153 }
154 else
155 {
156 // the sub-array is small, perform insertion sort
157 j = base;
158 i = j + 1;
160 for(; i < limit; j = i, i++)
161 {
162 for(; less(arr[j + 1], arr[j]); j--)
163 {
164 Swap(arr[j + 1], arr[j]);
165 if(j == base)
166 {
167 break;
168 }
169 }
170 }
171 if(top > stack)
172 {
173 top -= 2;
174 base = top[0];
175 limit = top[1];
176 }
177 else
178 {
179 break;
180 }
181 }
182 }
183 }
186 //-----------------------------------------------------------------------------------
187 // ***** QuickSortSliced
188 //
189 // Sort any part of any array: plain, Array, ArrayPaged, ArrayUnsafe.
190 // The range is specified with start, end, where "end" is exclusive!
191 // The data type must have a defined "<" operator.
192 template<class Array>
193 void QuickSortSliced(Array& arr, UPInt start, UPInt end)
194 {
195 typedef typename Array::ValueType ValueType;
196 QuickSortSliced(arr, start, end, OperatorLess<ValueType>::Compare);
197 }
199 // Same as corresponding G_QuickSortSliced but with checking array limits to avoid
200 // crash in the case of wrong comparator functor.
201 template<class Array, class Less>
202 bool QuickSortSlicedSafe(Array& arr, UPInt start, UPInt end, Less less)
203 {
204 enum
205 {
206 Threshold = 9
207 };
209 if(end - start < 2) return true;
211 SPInt stack[80];
212 SPInt* top = stack;
213 SPInt base = (SPInt)start;
214 SPInt limit = (SPInt)end;
216 for(;;)
217 {
218 SPInt len = limit - base;
219 SPInt i, j, pivot;
221 if(len > Threshold)
222 {
223 // we use base + len/2 as the pivot
224 pivot = base + len / 2;
225 Swap(arr[base], arr[pivot]);
227 i = base + 1;
228 j = limit - 1;
230 // now ensure that *i <= *base <= *j
231 if(less(arr[j], arr[i])) Swap(arr[j], arr[i]);
232 if(less(arr[base], arr[i])) Swap(arr[base], arr[i]);
233 if(less(arr[j], arr[base])) Swap(arr[j], arr[base]);
235 for(;;)
236 {
237 do
238 {
239 i++;
240 if (i >= limit)
241 return false;
242 } while( less(arr[i], arr[base]) );
243 do
244 {
245 j--;
246 if (j < 0)
247 return false;
248 } while( less(arr[base], arr[j]) );
250 if( i > j )
251 {
252 break;
253 }
255 Swap(arr[i], arr[j]);
256 }
258 Swap(arr[base], arr[j]);
260 // now, push the largest sub-array
261 if(j - base > limit - i)
262 {
263 top[0] = base;
264 top[1] = j;
265 base = i;
266 }
267 else
268 {
269 top[0] = i;
270 top[1] = limit;
271 limit = j;
272 }
273 top += 2;
274 }
275 else
276 {
277 // the sub-array is small, perform insertion sort
278 j = base;
279 i = j + 1;
281 for(; i < limit; j = i, i++)
282 {
283 for(; less(arr[j + 1], arr[j]); j--)
284 {
285 Swap(arr[j + 1], arr[j]);
286 if(j == base)
287 {
288 break;
289 }
290 }
291 }
292 if(top > stack)
293 {
294 top -= 2;
295 base = top[0];
296 limit = top[1];
297 }
298 else
299 {
300 break;
301 }
302 }
303 }
304 return true;
305 }
307 template<class Array>
308 bool QuickSortSlicedSafe(Array& arr, UPInt start, UPInt end)
309 {
310 typedef typename Array::ValueType ValueType;
311 return QuickSortSlicedSafe(arr, start, end, OperatorLess<ValueType>::Compare);
312 }
314 //-----------------------------------------------------------------------------------
315 // ***** QuickSort
316 //
317 // Sort an array Array, ArrayPaged, ArrayUnsafe.
318 // The array must have GetSize() function.
319 // The comparison predicate must be specified.
320 template<class Array, class Less>
321 void QuickSort(Array& arr, Less less)
322 {
323 QuickSortSliced(arr, 0, arr.GetSize(), less);
324 }
326 // checks for boundaries
327 template<class Array, class Less>
328 bool QuickSortSafe(Array& arr, Less less)
329 {
330 return QuickSortSlicedSafe(arr, 0, arr.GetSize(), less);
331 }
334 //-----------------------------------------------------------------------------------
335 // ***** QuickSort
336 //
337 // Sort an array Array, ArrayPaged, ArrayUnsafe.
338 // The array must have GetSize() function.
339 // The data type must have a defined "<" operator.
340 template<class Array>
341 void QuickSort(Array& arr)
342 {
343 typedef typename Array::ValueType ValueType;
344 QuickSortSliced(arr, 0, arr.GetSize(), OperatorLess<ValueType>::Compare);
345 }
347 template<class Array>
348 bool QuickSortSafe(Array& arr)
349 {
350 typedef typename Array::ValueType ValueType;
351 return QuickSortSlicedSafe(arr, 0, arr.GetSize(), OperatorLess<ValueType>::Compare);
352 }
354 //-----------------------------------------------------------------------------------
355 // ***** InsertionSortSliced
356 //
357 // Sort any part of any array: plain, Array, ArrayPaged, ArrayUnsafe.
358 // The range is specified with start, end, where "end" is exclusive!
359 // The comparison predicate must be specified.
360 // Unlike Quick Sort, the Insertion Sort works much slower in average,
361 // but may be much faster on almost sorted arrays. Besides, it guarantees
362 // that the elements will not be swapped if not necessary. For example,
363 // an array with all equal elements will remain "untouched", while
364 // Quick Sort will considerably shuffle the elements in this case.
365 template<class Array, class Less>
366 void InsertionSortSliced(Array& arr, UPInt start, UPInt end, Less less)
367 {
368 UPInt j = start;
369 UPInt i = j + 1;
370 UPInt limit = end;
372 for(; i < limit; j = i, i++)
373 {
374 for(; less(arr[j + 1], arr[j]); j--)
375 {
376 Swap(arr[j + 1], arr[j]);
377 if(j <= start)
378 {
379 break;
380 }
381 }
382 }
383 }
386 //-----------------------------------------------------------------------------------
387 // ***** InsertionSortSliced
388 //
389 // Sort any part of any array: plain, Array, ArrayPaged, ArrayUnsafe.
390 // The range is specified with start, end, where "end" is exclusive!
391 // The data type must have a defined "<" operator.
392 template<class Array>
393 void InsertionSortSliced(Array& arr, UPInt start, UPInt end)
394 {
395 typedef typename Array::ValueType ValueType;
396 InsertionSortSliced(arr, start, end, OperatorLess<ValueType>::Compare);
397 }
399 //-----------------------------------------------------------------------------------
400 // ***** InsertionSort
401 //
402 // Sort an array Array, ArrayPaged, ArrayUnsafe.
403 // The array must have GetSize() function.
404 // The comparison predicate must be specified.
406 template<class Array, class Less>
407 void InsertionSort(Array& arr, Less less)
408 {
409 InsertionSortSliced(arr, 0, arr.GetSize(), less);
410 }
412 //-----------------------------------------------------------------------------------
413 // ***** InsertionSort
414 //
415 // Sort an array Array, ArrayPaged, ArrayUnsafe.
416 // The array must have GetSize() function.
417 // The data type must have a defined "<" operator.
418 template<class Array>
419 void InsertionSort(Array& arr)
420 {
421 typedef typename Array::ValueType ValueType;
422 InsertionSortSliced(arr, 0, arr.GetSize(), OperatorLess<ValueType>::Compare);
423 }
427 //-----------------------------------------------------------------------------------
428 // ***** LowerBoundSliced
429 //
430 template<class Array, class Value, class Less>
431 UPInt LowerBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val, Less less)
432 {
433 SPInt first = (SPInt)start;
434 SPInt len = (SPInt)(end - start);
435 SPInt half;
436 SPInt middle;
438 while(len > 0)
439 {
440 half = len >> 1;
441 middle = first + half;
442 if(less(arr[middle], val))
443 {
444 first = middle + 1;
445 len = len - half - 1;
446 }
447 else
448 {
449 len = half;
450 }
451 }
452 return (UPInt)first;
453 }
456 //-----------------------------------------------------------------------------------
457 // ***** LowerBoundSliced
458 //
459 template<class Array, class Value>
460 UPInt LowerBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val)
461 {
462 return LowerBoundSliced(arr, start, end, val, OperatorLess<Value>::Compare);
463 }
465 //-----------------------------------------------------------------------------------
466 // ***** LowerBoundSized
467 //
468 template<class Array, class Value>
469 UPInt LowerBoundSized(const Array& arr, UPInt size, const Value& val)
470 {
471 return LowerBoundSliced(arr, 0, size, val, OperatorLess<Value>::Compare);
472 }
474 //-----------------------------------------------------------------------------------
475 // ***** LowerBound
476 //
477 template<class Array, class Value, class Less>
478 UPInt LowerBound(const Array& arr, const Value& val, Less less)
479 {
480 return LowerBoundSliced(arr, 0, arr.GetSize(), val, less);
481 }
484 //-----------------------------------------------------------------------------------
485 // ***** LowerBound
486 //
487 template<class Array, class Value>
488 UPInt LowerBound(const Array& arr, const Value& val)
489 {
490 return LowerBoundSliced(arr, 0, arr.GetSize(), val, OperatorLess<Value>::Compare);
491 }
495 //-----------------------------------------------------------------------------------
496 // ***** UpperBoundSliced
497 //
498 template<class Array, class Value, class Less>
499 UPInt UpperBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val, Less less)
500 {
501 SPInt first = (SPInt)start;
502 SPInt len = (SPInt)(end - start);
503 SPInt half;
504 SPInt middle;
506 while(len > 0)
507 {
508 half = len >> 1;
509 middle = first + half;
510 if(less(val, arr[middle]))
511 {
512 len = half;
513 }
514 else
515 {
516 first = middle + 1;
517 len = len - half - 1;
518 }
519 }
520 return (UPInt)first;
521 }
524 //-----------------------------------------------------------------------------------
525 // ***** UpperBoundSliced
526 //
527 template<class Array, class Value>
528 UPInt UpperBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val)
529 {
530 return UpperBoundSliced(arr, start, end, val, OperatorLess<Value>::Compare);
531 }
534 //-----------------------------------------------------------------------------------
535 // ***** UpperBoundSized
536 //
537 template<class Array, class Value>
538 UPInt UpperBoundSized(const Array& arr, UPInt size, const Value& val)
539 {
540 return UpperBoundSliced(arr, 0, size, val, OperatorLess<Value>::Compare);
541 }
544 //-----------------------------------------------------------------------------------
545 // ***** UpperBound
546 //
547 template<class Array, class Value, class Less>
548 UPInt UpperBound(const Array& arr, const Value& val, Less less)
549 {
550 return UpperBoundSliced(arr, 0, arr.GetSize(), val, less);
551 }
554 //-----------------------------------------------------------------------------------
555 // ***** UpperBound
556 //
557 template<class Array, class Value>
558 UPInt UpperBound(const Array& arr, const Value& val)
559 {
560 return UpperBoundSliced(arr, 0, arr.GetSize(), val, OperatorLess<Value>::Compare);
561 }
564 //-----------------------------------------------------------------------------------
565 // ***** ReverseArray
566 //
567 template<class Array> void ReverseArray(Array& arr)
568 {
569 SPInt from = 0;
570 SPInt to = arr.GetSize() - 1;
571 while(from < to)
572 {
573 Swap(arr[from], arr[to]);
574 ++from;
575 --to;
576 }
577 }
580 // ***** AppendArray
581 //
582 template<class CDst, class CSrc>
583 void AppendArray(CDst& dst, const CSrc& src)
584 {
585 UPInt i;
586 for(i = 0; i < src.GetSize(); i++)
587 dst.PushBack(src[i]);
588 }
590 //-----------------------------------------------------------------------------------
591 // ***** ArrayAdaptor
592 //
593 // A simple adapter that provides the GetSize() method and overloads
594 // operator []. Used to wrap plain arrays in QuickSort and such.
595 template<class T> class ArrayAdaptor
596 {
597 public:
598 typedef T ValueType;
599 ArrayAdaptor() : Data(0), Size(0) {}
600 ArrayAdaptor(T* ptr, UPInt size) : Data(ptr), Size(size) {}
601 UPInt GetSize() const { return Size; }
602 const T& operator [] (UPInt i) const { return Data[i]; }
603 T& operator [] (UPInt i) { return Data[i]; }
604 private:
605 T* Data;
606 UPInt Size;
607 };
610 //-----------------------------------------------------------------------------------
611 // ***** GConstArrayAdaptor
612 //
613 // A simple const adapter that provides the GetSize() method and overloads
614 // operator []. Used to wrap plain arrays in LowerBound and such.
615 template<class T> class ConstArrayAdaptor
616 {
617 public:
618 typedef T ValueType;
619 ConstArrayAdaptor() : Data(0), Size(0) {}
620 ConstArrayAdaptor(const T* ptr, UPInt size) : Data(ptr), Size(size) {}
621 UPInt GetSize() const { return Size; }
622 const T& operator [] (UPInt i) const { return Data[i]; }
623 private:
624 const T* Data;
625 UPInt Size;
626 };
630 //-----------------------------------------------------------------------------------
631 extern const UByte UpperBitTable[256];
632 extern const UByte LowerBitTable[256];
636 //-----------------------------------------------------------------------------------
637 inline UByte UpperBit(UPInt val)
638 {
639 #ifndef OVR_64BIT_POINTERS
641 if (val & 0xFFFF0000)
642 {
643 return (val & 0xFF000000) ?
644 UpperBitTable[(val >> 24) ] + 24:
645 UpperBitTable[(val >> 16) & 0xFF] + 16;
646 }
647 return (val & 0xFF00) ?
648 UpperBitTable[(val >> 8) & 0xFF] + 8:
649 UpperBitTable[(val ) & 0xFF];
651 #else
653 if (val & 0xFFFFFFFF00000000)
654 {
655 if (val & 0xFFFF000000000000)
656 {
657 return (val & 0xFF00000000000000) ?
658 UpperBitTable[(val >> 56) ] + 56:
659 UpperBitTable[(val >> 48) & 0xFF] + 48;
660 }
661 return (val & 0xFF0000000000) ?
662 UpperBitTable[(val >> 40) & 0xFF] + 40:
663 UpperBitTable[(val >> 32) & 0xFF] + 32;
664 }
665 else
666 {
667 if (val & 0xFFFF0000)
668 {
669 return (val & 0xFF000000) ?
670 UpperBitTable[(val >> 24) ] + 24:
671 UpperBitTable[(val >> 16) & 0xFF] + 16;
672 }
673 return (val & 0xFF00) ?
674 UpperBitTable[(val >> 8) & 0xFF] + 8:
675 UpperBitTable[(val ) & 0xFF];
676 }
678 #endif
679 }
681 //-----------------------------------------------------------------------------------
682 inline UByte LowerBit(UPInt val)
683 {
684 #ifndef OVR_64BIT_POINTERS
686 if (val & 0xFFFF)
687 {
688 return (val & 0xFF) ?
689 LowerBitTable[ val & 0xFF]:
690 LowerBitTable[(val >> 8) & 0xFF] + 8;
691 }
692 return (val & 0xFF0000) ?
693 LowerBitTable[(val >> 16) & 0xFF] + 16:
694 LowerBitTable[(val >> 24) & 0xFF] + 24;
696 #else
698 if (val & 0xFFFFFFFF)
699 {
700 if (val & 0xFFFF)
701 {
702 return (val & 0xFF) ?
703 LowerBitTable[ val & 0xFF]:
704 LowerBitTable[(val >> 8) & 0xFF] + 8;
705 }
706 return (val & 0xFF0000) ?
707 LowerBitTable[(val >> 16) & 0xFF] + 16:
708 LowerBitTable[(val >> 24) & 0xFF] + 24;
709 }
710 else
711 {
712 if (val & 0xFFFF00000000)
713 {
714 return (val & 0xFF00000000) ?
715 LowerBitTable[(val >> 32) & 0xFF] + 32:
716 LowerBitTable[(val >> 40) & 0xFF] + 40;
717 }
718 return (val & 0xFF000000000000) ?
719 LowerBitTable[(val >> 48) & 0xFF] + 48:
720 LowerBitTable[(val >> 56) & 0xFF] + 56;
721 }
723 #endif
724 }
728 // ******* Special (optimized) memory routines
729 // Note: null (bad) pointer is not tested
730 class MemUtil
731 {
732 public:
734 // Memory compare
735 static int Cmp (const void* p1, const void* p2, UPInt byteCount) { return memcmp(p1, p2, byteCount); }
736 static int Cmp16(const void* p1, const void* p2, UPInt int16Count);
737 static int Cmp32(const void* p1, const void* p2, UPInt int32Count);
738 static int Cmp64(const void* p1, const void* p2, UPInt int64Count);
739 };
741 // ** Inline Implementation
743 inline int MemUtil::Cmp16(const void* p1, const void* p2, UPInt int16Count)
744 {
745 SInt16* pa = (SInt16*)p1;
746 SInt16* pb = (SInt16*)p2;
747 unsigned ic = 0;
748 if (int16Count == 0)
749 return 0;
750 while (pa[ic] == pb[ic])
751 if (++ic==int16Count)
752 return 0;
753 return pa[ic] > pb[ic] ? 1 : -1;
754 }
755 inline int MemUtil::Cmp32(const void* p1, const void* p2, UPInt int32Count)
756 {
757 SInt32* pa = (SInt32*)p1;
758 SInt32* pb = (SInt32*)p2;
759 unsigned ic = 0;
760 if (int32Count == 0)
761 return 0;
762 while (pa[ic] == pb[ic])
763 if (++ic==int32Count)
764 return 0;
765 return pa[ic] > pb[ic] ? 1 : -1;
766 }
767 inline int MemUtil::Cmp64(const void* p1, const void* p2, UPInt int64Count)
768 {
769 SInt64* pa = (SInt64*)p1;
770 SInt64* pb = (SInt64*)p2;
771 unsigned ic = 0;
772 if (int64Count == 0)
773 return 0;
774 while (pa[ic] == pb[ic])
775 if (++ic==int64Count)
776 return 0;
777 return pa[ic] > pb[ic] ? 1 : -1;
778 }
780 // ** End Inline Implementation
783 //-----------------------------------------------------------------------------------
784 // ******* Byte Order Conversions
785 namespace ByteUtil {
787 // *** Swap Byte Order
789 // Swap the byte order of a byte array
790 inline void SwapOrder(void* pv, int size)
791 {
792 UByte* pb = (UByte*)pv;
793 UByte temp;
794 for (int i = 0; i < size>>1; i++)
795 {
796 temp = pb[size-1-i];
797 pb[size-1-i] = pb[i];
798 pb[i] = temp;
799 }
800 }
802 // Swap the byte order of primitive types
803 inline UByte SwapOrder(UByte v) { return v; }
804 inline SByte SwapOrder(SByte v) { return v; }
805 inline UInt16 SwapOrder(UInt16 v) { return UInt16(v>>8)|UInt16(v<<8); }
806 inline SInt16 SwapOrder(SInt16 v) { return SInt16((UInt16(v)>>8)|(v<<8)); }
807 inline UInt32 SwapOrder(UInt32 v) { return (v>>24)|((v&0x00FF0000)>>8)|((v&0x0000FF00)<<8)|(v<<24); }
808 inline SInt32 SwapOrder(SInt32 p) { return (SInt32)SwapOrder(UInt32(p)); }
809 inline UInt64 SwapOrder(UInt64 v)
810 {
811 return (v>>56) |
812 ((v&UInt64(0x00FF000000000000))>>40) |
813 ((v&UInt64(0x0000FF0000000000))>>24) |
814 ((v&UInt64(0x000000FF00000000))>>8) |
815 ((v&UInt64(0x00000000FF000000))<<8) |
816 ((v&UInt64(0x0000000000FF0000))<<24) |
817 ((v&UInt64(0x000000000000FF00))<<40) |
818 (v<<56);
819 }
820 inline SInt64 SwapOrder(SInt64 v) { return (SInt64)SwapOrder(UInt64(v)); }
821 inline float SwapOrder(float p)
822 {
823 union {
824 float p;
825 UInt32 v;
826 } u;
827 u.p = p;
828 u.v = SwapOrder(u.v);
829 return u.p;
830 }
832 inline double SwapOrder(double p)
833 {
834 union {
835 double p;
836 UInt64 v;
837 } u;
838 u.p = p;
839 u.v = SwapOrder(u.v);
840 return u.p;
841 }
843 // *** Byte-order conversion
845 #if (OVR_BYTE_ORDER == OVR_LITTLE_ENDIAN)
846 // Little Endian to System (LE)
847 inline UByte LEToSystem(UByte v) { return v; }
848 inline SByte LEToSystem(SByte v) { return v; }
849 inline UInt16 LEToSystem(UInt16 v) { return v; }
850 inline SInt16 LEToSystem(SInt16 v) { return v; }
851 inline UInt32 LEToSystem(UInt32 v) { return v; }
852 inline SInt32 LEToSystem(SInt32 v) { return v; }
853 inline UInt64 LEToSystem(UInt64 v) { return v; }
854 inline SInt64 LEToSystem(SInt64 v) { return v; }
855 inline float LEToSystem(float v) { return v; }
856 inline double LEToSystem(double v) { return v; }
858 // Big Endian to System (LE)
859 inline UByte BEToSystem(UByte v) { return SwapOrder(v); }
860 inline SByte BEToSystem(SByte v) { return SwapOrder(v); }
861 inline UInt16 BEToSystem(UInt16 v) { return SwapOrder(v); }
862 inline SInt16 BEToSystem(SInt16 v) { return SwapOrder(v); }
863 inline UInt32 BEToSystem(UInt32 v) { return SwapOrder(v); }
864 inline SInt32 BEToSystem(SInt32 v) { return SwapOrder(v); }
865 inline UInt64 BEToSystem(UInt64 v) { return SwapOrder(v); }
866 inline SInt64 BEToSystem(SInt64 v) { return SwapOrder(v); }
867 inline float BEToSystem(float v) { return SwapOrder(v); }
868 inline double BEToSystem(double v) { return SwapOrder(v); }
870 // System (LE) to Little Endian
871 inline UByte SystemToLE(UByte v) { return v; }
872 inline SByte SystemToLE(SByte v) { return v; }
873 inline UInt16 SystemToLE(UInt16 v) { return v; }
874 inline SInt16 SystemToLE(SInt16 v) { return v; }
875 inline UInt32 SystemToLE(UInt32 v) { return v; }
876 inline SInt32 SystemToLE(SInt32 v) { return v; }
877 inline UInt64 SystemToLE(UInt64 v) { return v; }
878 inline SInt64 SystemToLE(SInt64 v) { return v; }
879 inline float SystemToLE(float v) { return v; }
880 inline double SystemToLE(double v) { return v; }
882 // System (LE) to Big Endian
883 inline UByte SystemToBE(UByte v) { return SwapOrder(v); }
884 inline SByte SystemToBE(SByte v) { return SwapOrder(v); }
885 inline UInt16 SystemToBE(UInt16 v) { return SwapOrder(v); }
886 inline SInt16 SystemToBE(SInt16 v) { return SwapOrder(v); }
887 inline UInt32 SystemToBE(UInt32 v) { return SwapOrder(v); }
888 inline SInt32 SystemToBE(SInt32 v) { return SwapOrder(v); }
889 inline UInt64 SystemToBE(UInt64 v) { return SwapOrder(v); }
890 inline SInt64 SystemToBE(SInt64 v) { return SwapOrder(v); }
891 inline float SystemToBE(float v) { return SwapOrder(v); }
892 inline double SystemToBE(double v) { return SwapOrder(v); }
894 #elif (OVR_BYTE_ORDER == OVR_BIG_ENDIAN)
895 // Little Endian to System (BE)
896 inline UByte LEToSystem(UByte v) { return SwapOrder(v); }
897 inline SByte LEToSystem(SByte v) { return SwapOrder(v); }
898 inline UInt16 LEToSystem(UInt16 v) { return SwapOrder(v); }
899 inline SInt16 LEToSystem(SInt16 v) { return SwapOrder(v); }
900 inline UInt32 LEToSystem(UInt32 v) { return SwapOrder(v); }
901 inline SInt32 LEToSystem(SInt32 v) { return SwapOrder(v); }
902 inline UInt64 LEToSystem(UInt64 v) { return SwapOrder(v); }
903 inline SInt64 LEToSystem(SInt64 v) { return SwapOrder(v); }
904 inline float LEToSystem(float v) { return SwapOrder(v); }
905 inline double LEToSystem(double v) { return SwapOrder(v); }
907 // Big Endian to System (BE)
908 inline UByte BEToSystem(UByte v) { return v; }
909 inline SByte BEToSystem(SByte v) { return v; }
910 inline UInt16 BEToSystem(UInt16 v) { return v; }
911 inline SInt16 BEToSystem(SInt16 v) { return v; }
912 inline UInt32 BEToSystem(UInt32 v) { return v; }
913 inline SInt32 BEToSystem(SInt32 v) { return v; }
914 inline UInt64 BEToSystem(UInt64 v) { return v; }
915 inline SInt64 BEToSystem(SInt64 v) { return v; }
916 inline float BEToSystem(float v) { return v; }
917 inline double BEToSystem(double v) { return v; }
919 // System (BE) to Little Endian
920 inline UByte SystemToLE(UByte v) { return SwapOrder(v); }
921 inline SByte SystemToLE(SByte v) { return SwapOrder(v); }
922 inline UInt16 SystemToLE(UInt16 v) { return SwapOrder(v); }
923 inline SInt16 SystemToLE(SInt16 v) { return SwapOrder(v); }
924 inline UInt32 SystemToLE(UInt32 v) { return SwapOrder(v); }
925 inline SInt32 SystemToLE(SInt32 v) { return SwapOrder(v); }
926 inline UInt64 SystemToLE(UInt64 v) { return SwapOrder(v); }
927 inline SInt64 SystemToLE(SInt64 v) { return SwapOrder(v); }
928 inline float SystemToLE(float v) { return SwapOrder(v); }
929 inline double SystemToLE(double v) { return SwapOrder(v); }
931 // System (BE) to Big Endian
932 inline UByte SystemToBE(UByte v) { return v; }
933 inline SByte SystemToBE(SByte v) { return v; }
934 inline UInt16 SystemToBE(UInt16 v) { return v; }
935 inline SInt16 SystemToBE(SInt16 v) { return v; }
936 inline UInt32 SystemToBE(UInt32 v) { return v; }
937 inline SInt32 SystemToBE(SInt32 v) { return v; }
938 inline UInt64 SystemToBE(UInt64 v) { return v; }
939 inline SInt64 SystemToBE(SInt64 v) { return v; }
940 inline float SystemToBE(float v) { return v; }
941 inline double SystemToBE(double v) { return v; }
943 #else
944 #error "OVR_BYTE_ORDER must be defined to OVR_LITTLE_ENDIAN or OVR_BIG_ENDIAN"
945 #endif
947 } // namespace ByteUtil
951 }} // OVR::Alg
953 #endif