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
Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Last modified Fri May 25 23:36:23 2012