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-2006 Torus Knot Software Ltd
00008 Also see acknowledgements in Readme.html
00009 
00010 This program is free software; you can redistribute it and/or modify it under
00011 the terms of the GNU Lesser General Public License as published by the Free Software
00012 Foundation; either version 2 of the License, or (at your option) any later
00013 version.
00014 
00015 This program is distributed in the hope that it will be useful, but WITHOUT
00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00018 
00019 You should have received a copy of the GNU Lesser General Public License along with
00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00022 http://www.gnu.org/copyleft/lesser.txt.
00023 
00024 You may alternatively use this source under the terms of a specific version of
00025 the OGRE Unrestricted License provided you have obtained such a license from
00026 Torus Knot Software Ltd.
00027 -----------------------------------------------------------------------------
00028 */
00029 #ifndef _Bitwise_H__
00030 #define _Bitwise_H__
00031 
00032 #include "OgrePrerequisites.h"
00033 
00034 namespace Ogre {
00035 
00038     class Bitwise {
00039     public:
00042         static FORCEINLINE unsigned int mostSignificantBitSet(unsigned int value)
00043         {
00044             unsigned int result = 0;
00045             while (value != 0) {
00046                 ++result;
00047                 value >>= 1;
00048             }
00049             return result-1;
00050         }
00055         static FORCEINLINE uint32 firstPO2From(uint32 n)
00056         {
00057             --n;            
00058             n |= n >> 16;
00059             n |= n >> 8;
00060             n |= n >> 4;
00061             n |= n >> 2;
00062             n |= n >> 1;
00063             ++n;
00064             return n;
00065         }
00069         template<typename T>
00070         static FORCEINLINE bool isPO2(T n)
00071         {
00072             return (n & (n-1)) == 0;
00073         }
00077         template<typename T>
00078         static FORCEINLINE unsigned int getBitShift(T mask)
00079         {
00080             if (mask == 0)
00081                 return 0;
00082 
00083             unsigned int result = 0;
00084             while ((mask & 1) == 0) {
00085                 ++result;
00086                 mask >>= 1;
00087             }
00088             return result;
00089         }
00090 
00096         template<typename SrcT, typename DestT>
00097         static inline DestT convertBitPattern(SrcT srcValue, SrcT srcBitMask, DestT destBitMask)
00098         {
00099             // Mask off irrelevant source value bits (if any)
00100             srcValue = srcValue & srcBitMask;
00101 
00102             // Shift source down to bottom of DWORD
00103             const unsigned int srcBitShift = getBitShift(srcBitMask);
00104             srcValue >>= srcBitShift;
00105 
00106             // Get max value possible in source from srcMask
00107             const SrcT srcMax = srcBitMask >> srcBitShift;
00108 
00109             // Get max available in dest
00110             const unsigned int destBitShift = getBitShift(destBitMask);
00111             const DestT destMax = destBitMask >> destBitShift;
00112 
00113             // Scale source value into destination, and shift back
00114             DestT destValue = (srcValue * destMax) / srcMax;
00115             return (destValue << destBitShift);
00116         }
00117 
00122         static inline unsigned int fixedToFixed(uint32 value, unsigned int n, unsigned int p) 
00123         {
00124             if(n > p) 
00125             {
00126                 // Less bits required than available; this is easy
00127                 value >>= n-p;
00128             } 
00129             else if(n < p)
00130             {
00131                 // More bits required than are there, do the fill
00132                 // Use old fashioned division, probably better than a loop
00133                 if(value == 0)
00134                         value = 0;
00135                 else if(value == (static_cast<unsigned int>(1)<<n)-1)
00136                         value = (1<<p)-1;
00137                 else    value = value*(1<<p)/((1<<n)-1);
00138             }
00139             return value;    
00140         }
00141 
00146         static inline unsigned int floatToFixed(const float value, const unsigned int bits)
00147         {
00148             if(value <= 0.0f) return 0;
00149             else if (value >= 1.0f) return (1<<bits)-1;
00150             else return (unsigned int)(value * (1<<bits));     
00151         }
00152 
00156         static inline float fixedToFloat(unsigned value, unsigned int bits)
00157         {
00158             return (float)value/(float)((1<<bits)-1);
00159         }
00160 
00164         static inline void intWrite(void *dest, const int n, const unsigned int value)
00165         {
00166             switch(n) {
00167                 case 1:
00168                     ((uint8*)dest)[0] = (uint8)value;
00169                     break;
00170                 case 2:
00171                     ((uint16*)dest)[0] = (uint16)value;
00172                     break;
00173                 case 3:
00174 #if OGRE_ENDIAN == OGRE_ENDIAN_BIG      
00175                     ((uint8*)dest)[0] = (uint8)((value >> 16) & 0xFF);
00176                     ((uint8*)dest)[1] = (uint8)((value >> 8) & 0xFF);
00177                     ((uint8*)dest)[2] = (uint8)(value & 0xFF);
00178 #else
00179                     ((uint8*)dest)[2] = (uint8)((value >> 16) & 0xFF);
00180                     ((uint8*)dest)[1] = (uint8)((value >> 8) & 0xFF);
00181                     ((uint8*)dest)[0] = (uint8)(value & 0xFF);
00182 #endif
00183                     break;
00184                 case 4:
00185                     ((uint32*)dest)[0] = (uint32)value;                
00186                     break;                
00187             }        
00188         }
00192         static inline unsigned int intRead(const void *src, int n) {
00193             switch(n) {
00194                 case 1:
00195                     return ((uint8*)src)[0];
00196                 case 2:
00197                     return ((uint16*)src)[0];
00198                 case 3:
00199 #if OGRE_ENDIAN == OGRE_ENDIAN_BIG      
00200                     return ((uint32)((uint8*)src)[0]<<16)|
00201                             ((uint32)((uint8*)src)[1]<<8)|
00202                             ((uint32)((uint8*)src)[2]);
00203 #else
00204                     return ((uint32)((uint8*)src)[0])|
00205                             ((uint32)((uint8*)src)[1]<<8)|
00206                             ((uint32)((uint8*)src)[2]<<16);
00207 #endif
00208                 case 4:
00209                     return ((uint32*)src)[0];
00210             } 
00211             return 0; // ?
00212         }
00213 
00217         static inline uint16 floatToHalf(float i)
00218         {
00219             union { float f; uint32 i; } v;
00220             v.f = i;
00221             return floatToHalfI(v.i);
00222         }
00225         static inline uint16 floatToHalfI(uint32 i)
00226         {
00227             register int s =  (i >> 16) & 0x00008000;
00228             register int e = ((i >> 23) & 0x000000ff) - (127 - 15);
00229             register int m =   i        & 0x007fffff;
00230         
00231             if (e <= 0)
00232             {
00233                 if (e < -10)
00234                 {
00235                     return 0;
00236                 }
00237                 m = (m | 0x00800000) >> (1 - e);
00238         
00239                 return s | (m >> 13);
00240             }
00241             else if (e == 0xff - (127 - 15))
00242             {
00243                 if (m == 0) // Inf
00244                 {
00245                     return s | 0x7c00;
00246                 } 
00247                 else    // NAN
00248                 {
00249                     m >>= 13;
00250                     return s | 0x7c00 | m | (m == 0);
00251                 }
00252             }
00253             else
00254             {
00255                 if (e > 30) // Overflow
00256                 {
00257                     return s | 0x7c00;
00258                 }
00259         
00260                 return s | (e << 10) | (m >> 13);
00261             }
00262         }
00263         
00268         static inline float halfToFloat(uint16 y)
00269         {
00270             union { float f; uint32 i; } v;
00271             v.i = halfToFloatI(y);
00272             return v.f;
00273         }
00277         static inline uint32 halfToFloatI(uint16 y)
00278         {
00279             register int s = (y >> 15) & 0x00000001;
00280             register int e = (y >> 10) & 0x0000001f;
00281             register int m =  y        & 0x000003ff;
00282         
00283             if (e == 0)
00284             {
00285                 if (m == 0) // Plus or minus zero
00286                 {
00287                     return s << 31;
00288                 }
00289                 else // Denormalized number -- renormalize it
00290                 {
00291                     while (!(m & 0x00000400))
00292                     {
00293                         m <<= 1;
00294                         e -=  1;
00295                     }
00296         
00297                     e += 1;
00298                     m &= ~0x00000400;
00299                 }
00300             }
00301             else if (e == 31)
00302             {
00303                 if (m == 0) // Inf
00304                 {
00305                     return (s << 31) | 0x7f800000;
00306                 }
00307                 else // NaN
00308                 {
00309                     return (s << 31) | 0x7f800000 | (m << 13);
00310                 }
00311             }
00312         
00313             e = e + (127 - 15);
00314             m = m << 13;
00315         
00316             return (s << 31) | (e << 23) | m;
00317         }
00318          
00319 
00320     };
00321 }
00322 
00323 #endif

Copyright © 2008 Torus Knot Software Ltd
Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sun Sep 27 22:02:22 2009