OgreBitwise.h
Go to the documentation of this file.

    00001 /*
    00002 -----------------------------------------------------------------------------
    00003 This source file is part of OGRE
    00004     (Object-oriented Graphics Rendering Engine)
    00005 For the latest info, see http://www.ogre3d.org/
    00006
    00007 Copyright (c) 2000-2012 Torus Knot Software Ltd
    00008
    00009 Permission is hereby granted, free of charge, to any person obtaining a copy
    00010 of this software and associated documentation files (the "Software"), to deal
    00011 in the Software without restriction, including without limitation the rights
    00012 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    00013 copies of the Software, and to permit persons to whom the Software is
    00014 furnished to do so, subject to the following conditions:
    00015
    00016 The above copyright notice and this permission notice shall be included in
    00017 all copies or substantial portions of the Software.
    00018
    00019 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    00020 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    00021 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    00022 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    00023 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    00024 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    00025 THE SOFTWARE.
    00026 -----------------------------------------------------------------------------
    00027 */
    00028 #ifndef _Bitwise_H__
    00029 #define _Bitwise_H__
    00030
    00031 #include "OgrePrerequisites.h"
    00032
    00033 namespace Ogre {
    00043     class Bitwise {
    00044     public:
    00047         static FORCEINLINE unsigned int mostSignificantBitSet(unsigned int value)
    00048         {
    00049             unsigned int result = 0;
    00050             while (value != 0) {
    00051                 ++result;
    00052                 value >>= 1;
    00053             }
    00054             return result-1;
    00055         }
    00060         static FORCEINLINE uint32 firstPO2From(uint32 n)
    00061         {
    00062             --n;
    00063             n |= n >> 16;
    00064             n |= n >> 8;
    00065             n |= n >> 4;
    00066             n |= n >> 2;
    00067             n |= n >> 1;
    00068             ++n;
    00069             return n;
    00070         }
    00074         template<typename T>
    00075         static FORCEINLINE bool isPO2(T n)
    00076         {
    00077             return (n & (n-1)) == 0;
    00078         }
    00082         template<typename T>
    00083         static FORCEINLINE unsigned int getBitShift(T mask)
    00084         {
    00085             if (mask == 0)
    00086                 return 0;
    00087
    00088             unsigned int result = 0;
    00089             while ((mask & 1) == 0) {
    00090                 ++result;
    00091                 mask >>= 1;
    00092             }
    00093             return result;
    00094         }
    00095
    00101         template<typename SrcT, typename DestT>
    00102         static inline DestT convertBitPattern(SrcT srcValue, SrcT srcBitMask, DestT destBitMask)
    00103         {
    00104             // Mask off irrelevant source value bits (if any)
    00105             srcValue = srcValue & srcBitMask;
    00106
    00107             // Shift source down to bottom of DWORD
    00108             const unsigned int srcBitShift = getBitShift(srcBitMask);
    00109             srcValue >>= srcBitShift;
    00110
    00111             // Get max value possible in source from srcMask
    00112             const SrcT srcMax = srcBitMask >> srcBitShift;
    00113
    00114             // Get max available in dest
    00115             const unsigned int destBitShift = getBitShift(destBitMask);
    00116             const DestT destMax = destBitMask >> destBitShift;
    00117
    00118             // Scale source value into destination, and shift back
    00119             DestT destValue = (srcValue * destMax) / srcMax;
    00120             return (destValue << destBitShift);
    00121         }
    00122
    00127         static inline unsigned int fixedToFixed(uint32 value, unsigned int n, unsigned int p)
    00128         {
    00129             if(n > p)
    00130             {
    00131                 // Less bits required than available; this is easy
    00132                 value >>= n-p;
    00133             }
    00134             else if(n < p)
    00135             {
    00136                 // More bits required than are there, do the fill
    00137                 // Use old fashioned division, probably better than a loop
    00138                 if(value == 0)
    00139                         value = 0;
    00140                 else if(value == (static_cast<unsigned int>(1)<<n)-1)
    00141                         value = (1<<p)-1;
    00142                 else    value = value*(1<<p)/((1<<n)-1);
    00143             }
    00144             return value;
    00145         }
    00146
    00151         static inline unsigned int floatToFixed(const float value, const unsigned int bits)
    00152         {
    00153             if(value <= 0.0f) return 0;
    00154             else if (value >= 1.0f) return (1<<bits)-1;
    00155             else return (unsigned int)(value * (1<<bits));
    00156         }
    00157
    00161         static inline float fixedToFloat(unsigned value, unsigned int bits)
    00162         {
    00163             return (float)value/(float)((1<<bits)-1);
    00164         }
    00165
    00169         static inline void intWrite(void *dest, const int n, const unsigned int value)
    00170         {
    00171             switch(n) {
    00172                 case 1:
    00173                     ((uint8*)dest)[0] = (uint8)value;
    00174                     break;
    00175                 case 2:
    00176                     ((uint16*)dest)[0] = (uint16)value;
    00177                     break;
    00178                 case 3:
    00179 #if OGRE_ENDIAN == OGRE_ENDIAN_BIG
    00180                     ((uint8*)dest)[0] = (uint8)((value >> 16) & 0xFF);
    00181                     ((uint8*)dest)[1] = (uint8)((value >> 8) & 0xFF);
    00182                     ((uint8*)dest)[2] = (uint8)(value & 0xFF);
    00183 #else
    00184                     ((uint8*)dest)[2] = (uint8)((value >> 16) & 0xFF);
    00185                     ((uint8*)dest)[1] = (uint8)((value >> 8) & 0xFF);
    00186                     ((uint8*)dest)[0] = (uint8)(value & 0xFF);
    00187 #endif
    00188                     break;
    00189                 case 4:
    00190                     ((uint32*)dest)[0] = (uint32)value;
    00191                     break;
    00192             }
    00193         }
    00197         static inline unsigned int intRead(const void *src, int n) {
    00198             switch(n) {
    00199                 case 1:
    00200                     return ((uint8*)src)[0];
    00201                 case 2:
    00202                     return ((uint16*)src)[0];
    00203                 case 3:
    00204 #if OGRE_ENDIAN == OGRE_ENDIAN_BIG
    00205                     return ((uint32)((uint8*)src)[0]<<16)|
    00206                             ((uint32)((uint8*)src)[1]<<8)|
    00207                             ((uint32)((uint8*)src)[2]);
    00208 #else
    00209                     return ((uint32)((uint8*)src)[0])|
    00210                             ((uint32)((uint8*)src)[1]<<8)|
    00211                             ((uint32)((uint8*)src)[2]<<16);
    00212 #endif
    00213                 case 4:
    00214                     return ((uint32*)src)[0];
    00215             }
    00216             return 0; // ?
    00217         }
    00218
    00222         static inline uint16 floatToHalf(float i)
    00223         {
    00224             union { float f; uint32 i; } v;
    00225             v.f = i;
    00226             return floatToHalfI(v.i);
    00227         }
    00230         static inline uint16 floatToHalfI(uint32 i)
    00231         {
    00232             register int s =  (i >> 16) & 0x00008000;
    00233             register int e = ((i >> 23) & 0x000000ff) - (127 - 15);
    00234             register int m =   i        & 0x007fffff;
    00235
    00236             if (e <= 0)
    00237             {
    00238                 if (e < -10)
    00239                 {
    00240                     return 0;
    00241                 }
    00242                 m = (m | 0x00800000) >> (1 - e);
    00243
    00244                 return static_cast<uint16>(s | (m >> 13));
    00245             }
    00246             else if (e == 0xff - (127 - 15))
    00247             {
    00248                 if (m == 0) // Inf
    00249                 {
    00250                     return static_cast<uint16>(s | 0x7c00);
    00251                 }
    00252                 else    // NAN
    00253                 {
    00254                     m >>= 13;
    00255                     return static_cast<uint16>(s | 0x7c00 | m | (m == 0));
    00256                 }
    00257             }
    00258             else
    00259             {
    00260                 if (e > 30) // Overflow
    00261                 {
    00262                     return static_cast<uint16>(s | 0x7c00);
    00263                 }
    00264
    00265                 return static_cast<uint16>(s | (e << 10) | (m >> 13));
    00266             }
    00267         }
    00268
    00273         static inline float halfToFloat(uint16 y)
    00274         {
    00275             union { float f; uint32 i; } v;
    00276             v.i = halfToFloatI(y);
    00277             return v.f;
    00278         }
    00282         static inline uint32 halfToFloatI(uint16 y)
    00283         {
    00284             register int s = (y >> 15) & 0x00000001;
    00285             register int e = (y >> 10) & 0x0000001f;
    00286             register int m =  y        & 0x000003ff;
    00287
    00288             if (e == 0)
    00289             {
    00290                 if (m == 0) // Plus or minus zero
    00291                 {
    00292                     return s << 31;
    00293                 }
    00294                 else // Denormalized number -- renormalize it
    00295                 {
    00296                     while (!(m & 0x00000400))
    00297                     {
    00298                         m <<= 1;
    00299                         e -=  1;
    00300                     }
    00301
    00302                     e += 1;
    00303                     m &= ~0x00000400;
    00304                 }
    00305             }
    00306             else if (e == 31)
    00307             {
    00308                 if (m == 0) // Inf
    00309                 {
    00310                     return (s << 31) | 0x7f800000;
    00311                 }
    00312                 else // NaN
    00313                 {
    00314                     return (s << 31) | 0x7f800000 | (m << 13);
    00315                 }
    00316             }
    00317
    00318             e = e + (127 - 15);
    00319             m = m << 13;
    00320
    00321             return (s << 31) | (e << 23) | m;
    00322         }
    00323
    00324
    00325     };
    00329 }
    00330
    00331 #endif

Copyright © 2012 Torus Knot Software Ltd
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Last modified Sun Sep 2 2012 07:27:20