/********************************************************************** Filename : GFunctions.h Content : General purpose bit access functions Created : December 28, 1998 Authors : Michael Antonov History : 1/16/1999 MA Revised Bit operation parameters Copyright : (c) 1998-2006 Scaleform Corp. All Rights Reserved. Licensees may use this file in accordance with the valid Scaleform Commercial License Agreement provided with the software. This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR ANY PURPOSE. **********************************************************************/ #ifndef INC_GFUNCTIONS_H #define INC_GFUNCTIONS_H #include "GTypes.h" #include // ******* Special (optimized) memory routines // Note: null (bad) pointer is not tested class GMemUtil { public: // Memory copy GINLINE static void* Copy (void* pdest, const void* psrc, UPInt byteCount) { return memcpy(pdest, psrc, byteCount); } GINLINE static void* Copy16(void* pdest, const void* psrc, UPInt int16Count) { return memcpy(pdest, psrc, int16Count*2); } GINLINE static void* Copy32(void* pdest, const void* psrc, UPInt int32Count) { return memcpy(pdest, psrc, int32Count*4); } GINLINE static void* Copy64(void* pdest, const void* psrc, UPInt int64Count) { return memcpy(pdest, psrc, int64Count*8); } // Memory move GINLINE static void* Move (void* pdest, const void* psrc, UPInt byteCount) { return memmove(pdest, psrc, byteCount); } GINLINE static void* Move16(void* pdest, const void* psrc, UPInt int16Count) { return memmove(pdest, psrc, int16Count*2); } GINLINE static void* Move32(void* pdest, const void* psrc, UPInt int32Count) { return memmove(pdest, psrc, int32Count*4); } GINLINE static void* Move64(void* pdest, const void* psrc, UPInt int64Count) { return memmove(pdest, psrc, int64Count*8); } // Memory compare GINLINE static SInt Cmp (const void* p1, const void* p2, UPInt byteCount) { return memcmp(p1, p2, byteCount); } GINLINE static SInt Cmp16(const void* p1, const void* p2, UPInt int16Count); GINLINE static SInt Cmp32(const void* p1, const void* p2, UPInt int32Count); GINLINE static SInt Cmp64(const void* p1, const void* p2, UPInt int64Count); // Memory set GINLINE static void Set (void* pdest, SInt value, UPInt byteCount) { memset(pdest, value, byteCount); } // GEXPORT static void GSTDCALL Set16(void* pdest, SInt16 value, UPInt int16Count); // GEXPORT static void GSTDCALL Set32(void* pdest, SInt32 value, UPInt int32Count); // GEXPORT static void GSTDCALL Set64(void* pdest, SInt64 value, UPInt int64Count); }; // ** Inline Implementation GINLINE SInt GMemUtil::Cmp16(const void* p1, const void* p2, UPInt int16Count) { SInt16* pa = (SInt16*)p1; SInt16* pb = (SInt16*)p2; UInt ic = 0; if (int16Count == 0) return 0; while (pa[ic] == pb[ic]) if (++ic==int16Count) return 0; return pa[ic] > pb[ic] ? 1 : -1; } GINLINE SInt GMemUtil::Cmp32(const void* p1, const void* p2, UPInt int32Count) { SInt32* pa = (SInt32*)p1; SInt32* pb = (SInt32*)p2; UInt ic = 0; if (int32Count == 0) return 0; while (pa[ic] == pb[ic]) if (++ic==int32Count) return 0; return pa[ic] > pb[ic] ? 1 : -1; } GINLINE SInt GMemUtil::Cmp64(const void* p1, const void* p2, UPInt int64Count) { SInt64* pa = (SInt64*)p1; SInt64* pb = (SInt64*)p2; UInt 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 class GByteUtil { public: // *** Swap Byte Order // Swap the byte order of a byte array GINLINE static void SwapOrder(void* pv, SInt size) { UByte* pb = (UByte*)pv; UByte temp; for (SInt 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 GINLINE static UInt8 SwapOrder(UInt8 v) { return v; } GINLINE static SInt8 SwapOrder(SInt8 v) { return v; } GINLINE static UInt16 SwapOrder(UInt16 v) { return UInt16(v>>8)|UInt16(v<<8); } GINLINE static SInt16 SwapOrder(SInt16 v) { return SInt16((UInt16(v)>>8)|(v<<8)); } GINLINE static UInt32 SwapOrder(UInt32 v) { return (v>>24)|((v&0x00FF0000)>>8)|((v&0x0000FF00)<<8)|(v<<24); } GINLINE static SInt32 SwapOrder(SInt32 p) { return (SInt32)SwapOrder(UInt32(p)); } GINLINE static UInt64 SwapOrder(UInt64 v) { return (v>>56) | ((v&GUINT64(0x00FF000000000000))>>40) | ((v&GUINT64(0x0000FF0000000000))>>24) | ((v&GUINT64(0x000000FF00000000))>>8) | ((v&GUINT64(0x00000000FF000000))<<8) | ((v&GUINT64(0x0000000000FF0000))<<24) | ((v&GUINT64(0x000000000000FF00))<<40) | (v<<56); } GINLINE static SInt64 SwapOrder(SInt64 v) { return (SInt64)SwapOrder(UInt64(v)); } GINLINE static Float SwapOrder(Float p) { union { Float p; UInt32 v; } u; u.p = p; u.v = SwapOrder(u.v); return u.p; } #ifndef GFC_NO_DOUBLE GINLINE static Double SwapOrder(Double p) { union { Double p; UInt64 v; } u; u.p = p; u.v = SwapOrder(u.v); return u.p; } #endif // *** Byte-order conversion #if (GFC_BYTE_ORDER == GFC_LITTLE_ENDIAN) // Little Endian to System (LE) GINLINE static UInt8 LEToSystem(UInt8 v) { return v; } GINLINE static SInt8 LEToSystem(SInt8 v) { return v; } GINLINE static UInt16 LEToSystem(UInt16 v) { return v; } GINLINE static SInt16 LEToSystem(SInt16 v) { return v; } GINLINE static UInt32 LEToSystem(UInt32 v) { return v; } GINLINE static SInt32 LEToSystem(SInt32 v) { return v; } GINLINE static UInt64 LEToSystem(UInt64 v) { return v; } GINLINE static SInt64 LEToSystem(SInt64 v) { return v; } GINLINE static Float LEToSystem(Float v) { return v; } #ifndef GFC_NO_DOUBLE GINLINE static Double LEToSystem(Double v) { return v; } #endif // Big Endian to System (LE) GINLINE static UInt8 BEToSystem(UInt8 v) { return SwapOrder(v); } GINLINE static SInt8 BEToSystem(SInt8 v) { return SwapOrder(v); } GINLINE static UInt16 BEToSystem(UInt16 v) { return SwapOrder(v); } GINLINE static SInt16 BEToSystem(SInt16 v) { return SwapOrder(v); } GINLINE static UInt32 BEToSystem(UInt32 v) { return SwapOrder(v); } GINLINE static SInt32 BEToSystem(SInt32 v) { return SwapOrder(v); } GINLINE static UInt64 BEToSystem(UInt64 v) { return SwapOrder(v); } GINLINE static SInt64 BEToSystem(SInt64 v) { return SwapOrder(v); } GINLINE static Float BEToSystem(Float v) { return SwapOrder(v); } #ifndef GFC_NO_DOUBLE GINLINE static Double BEToSystem(Double v) { return SwapOrder(v); } #endif // System (LE) to Little Endian GINLINE static UInt8 SystemToLE(UInt8 v) { return v; } GINLINE static SInt8 SystemToLE(SInt8 v) { return v; } GINLINE static UInt16 SystemToLE(UInt16 v) { return v; } GINLINE static SInt16 SystemToLE(SInt16 v) { return v; } GINLINE static UInt32 SystemToLE(UInt32 v) { return v; } GINLINE static SInt32 SystemToLE(SInt32 v) { return v; } GINLINE static UInt64 SystemToLE(UInt64 v) { return v; } GINLINE static SInt64 SystemToLE(SInt64 v) { return v; } GINLINE static Float SystemToLE(Float v) { return v; } #ifndef GFC_NO_DOUBLE GINLINE static Double SystemToLE(Double v) { return v; } #endif // System (LE) to Big Endian GINLINE static UInt8 SystemToBE(UInt8 v) { return SwapOrder(v); } GINLINE static SInt8 SystemToBE(SInt8 v) { return SwapOrder(v); } GINLINE static UInt16 SystemToBE(UInt16 v) { return SwapOrder(v); } GINLINE static SInt16 SystemToBE(SInt16 v) { return SwapOrder(v); } GINLINE static UInt32 SystemToBE(UInt32 v) { return SwapOrder(v); } GINLINE static SInt32 SystemToBE(SInt32 v) { return SwapOrder(v); } GINLINE static UInt64 SystemToBE(UInt64 v) { return SwapOrder(v); } GINLINE static SInt64 SystemToBE(SInt64 v) { return SwapOrder(v); } GINLINE static Float SystemToBE(Float v) { return SwapOrder(v); } #ifndef GFC_NO_DOUBLE GINLINE static Double SystemToBE(Double v) { return SwapOrder(v); } #endif #elif (GFC_BYTE_ORDER == GFC_BIG_ENDIAN) // Little Endian to System (BE) GINLINE static UInt8 LEToSystem(UInt8 v) { return SwapOrder(v); } GINLINE static SInt8 LEToSystem(SInt8 v) { return SwapOrder(v); } GINLINE static UInt16 LEToSystem(UInt16 v) { return SwapOrder(v); } GINLINE static SInt16 LEToSystem(SInt16 v) { return SwapOrder(v); } GINLINE static UInt32 LEToSystem(UInt32 v) { return SwapOrder(v); } GINLINE static SInt32 LEToSystem(SInt32 v) { return SwapOrder(v); } GINLINE static UInt64 LEToSystem(UInt64 v) { return SwapOrder(v); } GINLINE static SInt64 LEToSystem(SInt64 v) { return SwapOrder(v); } GINLINE static Float LEToSystem(Float v) { return SwapOrder(v); } #ifndef GFC_NO_DOUBLE GINLINE static Double LEToSystem(Double v) { return SwapOrder(v); } #endif // Big Endian to System (BE) GINLINE static UInt8 BEToSystem(UInt8 v) { return v; } GINLINE static SInt8 BEToSystem(SInt8 v) { return v; } GINLINE static UInt16 BEToSystem(UInt16 v) { return v; } GINLINE static SInt16 BEToSystem(SInt16 v) { return v; } GINLINE static UInt32 BEToSystem(UInt32 v) { return v; } GINLINE static SInt32 BEToSystem(SInt32 v) { return v; } GINLINE static UInt64 BEToSystem(UInt64 v) { return v; } GINLINE static SInt64 BEToSystem(SInt64 v) { return v; } GINLINE static Float BEToSystem(Float v) { return v; } #ifndef GFC_NO_DOUBLE GINLINE static Double BEToSystem(Double v) { return v; } #endif // System (BE) to Little Endian GINLINE static UInt8 SystemToLE(UInt8 v) { return SwapOrder(v); } GINLINE static SInt8 SystemToLE(SInt8 v) { return SwapOrder(v); } GINLINE static UInt16 SystemToLE(UInt16 v) { return SwapOrder(v); } GINLINE static SInt16 SystemToLE(SInt16 v) { return SwapOrder(v); } GINLINE static UInt32 SystemToLE(UInt32 v) { return SwapOrder(v); } GINLINE static SInt32 SystemToLE(SInt32 v) { return SwapOrder(v); } GINLINE static UInt64 SystemToLE(UInt64 v) { return SwapOrder(v); } GINLINE static SInt64 SystemToLE(SInt64 v) { return SwapOrder(v); } GINLINE static Float SystemToLE(Float v) { return SwapOrder(v); } #ifndef GFC_NO_DOUBLE GINLINE static Double SystemToLE(Double v) { return SwapOrder(v); } #endif // System (BE) to Big Endian GINLINE static UInt8 SystemToBE(UInt8 v) { return v; } GINLINE static SInt8 SystemToBE(SInt8 v) { return v; } GINLINE static UInt16 SystemToBE(UInt16 v) { return v; } GINLINE static SInt16 SystemToBE(SInt16 v) { return v; } GINLINE static UInt32 SystemToBE(UInt32 v) { return v; } GINLINE static SInt32 SystemToBE(SInt32 v) { return v; } GINLINE static UInt64 SystemToBE(UInt64 v) { return v; } GINLINE static SInt64 SystemToBE(SInt64 v) { return v; } GINLINE static Float SystemToBE(Float v) { return v; } #ifndef GFC_NO_DOUBLE GINLINE static Double SystemToBE(Double v) { return v; } #endif #else #error "GFC_BYTE_ORDER must be defined to GFC_LITTLE_ENDIAN or GFC_BIG_ENDIAN" #endif }; class GBitsUtil { public: // Return number of bits set to true template static UInt8 Cardinality(T v); // Return number of bits required to represent the value GINLINE static UInt8 BitCount32(UInt32 value); }; template UInt8 GBitsUtil::Cardinality(T v) { const T MASK_01010101 = (((T)(-1))/3); const T MASK_00110011 = (((T)(-1))/5); const T MASK_00001111 = (((T)(-1))/17); v = (v & MASK_01010101) + ((v >> 1) & MASK_01010101) ; v = (v & MASK_00110011) + ((v >> 2) & MASK_00110011) ; v = (v & MASK_00001111) + ((v >> 4) & MASK_00001111) ; return (UInt8)(v % 255); } GINLINE UInt8 GBitsUtil::BitCount32(UInt32 value) { /* Binary search - decision tree (5 tests, rarely 6) */ return ((value < 1UL<<15) ? ((value < 1UL<<7) ? ((value < 1UL<<3) ? ((value < 1UL<<1) ? ((value < 1UL<<0) ? 0 : 1) : ((value < 1UL<<2) ? 2 : 3)) : ((value < 1UL<<5) ? ((value < 1UL<<4) ? 4 : 5) : ((value < 1UL<<6) ? 6 : 7))) : ((value < 1UL<<11) ? ((value < 1UL<<9) ? ((value < 1UL<<8) ? 8 : 9) : ((value < 1UL<<10) ? 10 : 11)) : ((value < 1UL<<13) ? ((value < 1UL<<12) ? 12 : 13) : ((value < 1UL<<14) ? 14 : 15)))) : ((value < 1UL<<23) ? ((value < 1UL<<19) ? ((value < 1UL<<17) ? ((value < 1UL<<16) ? 16 : 17) : ((value < 1UL<<18) ? 18 : 19)) : ((value < 1UL<<21) ? ((value < 1UL<<20) ? 20 : 21) : ((value < 1UL<<22) ? 22 : 23))) : ((value < 1UL<<27) ? ((value < 1UL<<25) ? ((value < 1UL<<24) ? 24 : 25) : ((value < 1UL<<26) ? 26 : 27)) : ((value < 1UL<<29) ? ((value < 1UL<<28) ? 28 : 29) : ((value < 1UL<<30) ? 30 : ((value < 1UL<<31) ? 31 : 32)))))); } #endif