Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

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-2005 The OGRE Team
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 */
00025 #ifndef _Bitwise_H__
00026 #define _Bitwise_H__
00027 
00028 #include "OgrePrerequisites.h"
00029 
00030 namespace Ogre {
00031 
00034     class Bitwise {
00035     public:
00038         static FORCEINLINE unsigned int mostSignificantBitSet(unsigned int value)
00039         {
00040             unsigned int result = 0;
00041             while (value != 0) {
00042                 ++result;
00043                 value >>= 1;
00044             }
00045             return result-1;
00046         }
00051         static FORCEINLINE uint32 firstPO2From(uint32 n)
00052         {
00053             --n;            
00054             n |= n >> 16;
00055             n |= n >> 8;
00056             n |= n >> 4;
00057             n |= n >> 2;
00058             n |= n >> 1;
00059             ++n;
00060             return n;
00061         }
00065         template<typename T>
00066         static FORCEINLINE unsigned int getBitShift(T mask)
00067         {
00068             if (mask == 0)
00069                 return 0;
00070 
00071             unsigned int result = 0;
00072             while ((mask & 1) == 0) {
00073                 ++result;
00074                 mask >>= 1;
00075             }
00076             return result;
00077         }
00078 
00084         template<typename SrcT, typename DestT>
00085         static inline DestT convertBitPattern(SrcT srcValue, SrcT srcBitMask, DestT destBitMask)
00086         {
00087             // Mask off irrelevant source value bits (if any)
00088             srcValue = srcValue & srcBitMask;
00089 
00090             // Shift source down to bottom of DWORD
00091             const unsigned int srcBitShift = getBitShift(srcBitMask);
00092             srcValue >>= srcBitShift;
00093 
00094             // Get max value possible in source from srcMask
00095             const SrcT srcMax = srcBitMask >> srcBitShift;
00096 
00097             // Get max avaiable in dest
00098             const unsigned int destBitShift = getBitShift(destBitMask);
00099             const DestT destMax = destBitMask >> destBitShift;
00100 
00101             // Scale source value into destination, and shift back
00102             DestT destValue = (srcValue * destMax) / srcMax;
00103             return (destValue << destBitShift);
00104         }
00105 
00110         static inline unsigned int fixedToFixed(uint32 value, unsigned int n, unsigned int p) 
00111         {
00112             if(n > p) 
00113             {
00114                 // Less bits required than available; this is easy
00115                 value >>= n-p;
00116             } 
00117             else if(n < p)
00118             {
00119                 // More bits required than are there, do the fill
00120                 // Use old fashioned division, probably better than a loop
00121                 if(value == 0)
00122                         value = 0;
00123                 else if(value == (static_cast<unsigned int>(1)<<n)-1)
00124                         value = (1<<p)-1;
00125                 else    value = value*(1<<p)/((1<<n)-1);
00126             }
00127             return value;    
00128         }
00129 
00134         static inline unsigned int floatToFixed(const float value, const unsigned int bits)
00135         {
00136             if(value <= 0.0f) return 0;
00137             else if (value >= 1.0f) return (1<<bits)-1;
00138             else return (unsigned int)(value * (1<<bits));     
00139         }
00140 
00144         static inline float fixedToFloat(unsigned value, unsigned int bits)
00145         {
00146             return (float)value/(float)((1<<bits)-1);
00147         }
00148 
00152         static inline void intWrite(const void *dest, const int n, const unsigned int value)
00153         {
00154             switch(n) {
00155                 case 1:
00156                     ((uint8*)dest)[0] = (uint8)value;
00157                     break;
00158                 case 2:
00159                     ((uint16*)dest)[0] = (uint16)value;
00160                     break;
00161                 case 3:
00162 #if OGRE_ENDIAN == OGRE_ENDIAN_BIG      
00163                     ((uint8*)dest)[0] = (uint8)((value >> 16) & 0xFF);
00164                     ((uint8*)dest)[1] = (uint8)((value >> 8) & 0xFF);
00165                     ((uint8*)dest)[2] = (uint8)(value & 0xFF);
00166 #else
00167                     ((uint8*)dest)[2] = (uint8)((value >> 16) & 0xFF);
00168                     ((uint8*)dest)[1] = (uint8)((value >> 8) & 0xFF);
00169                     ((uint8*)dest)[0] = (uint8)(value & 0xFF);
00170 #endif
00171                     break;
00172                 case 4:
00173                     ((uint32*)dest)[0] = (uint32)value;                
00174                     break;                
00175             }        
00176         }
00180         static inline unsigned int intRead(const void *src, int n) {
00181             switch(n) {
00182                 case 1:
00183                     return ((uint8*)src)[0];
00184                 case 2:
00185                     return ((uint16*)src)[0];
00186                 case 3:
00187 #if OGRE_ENDIAN == OGRE_ENDIAN_BIG      
00188                     return ((uint32)((uint8*)src)[0]<<16)|
00189                             ((uint32)((uint8*)src)[1]<<8)|
00190                             ((uint32)((uint8*)src)[2]);
00191 #else
00192                     return ((uint32)((uint8*)src)[0])|
00193                             ((uint32)((uint8*)src)[1]<<8)|
00194                             ((uint32)((uint8*)src)[2]<<16);
00195 #endif
00196                 case 4:
00197                     return ((uint32*)src)[0];
00198             } 
00199             return 0; // ?
00200         }
00201 
00205         static inline uint16 floatToHalf(float i)
00206         {
00207             union { float f; uint32 i; } v;
00208             v.f = i;
00209             return floatToHalfI(v.i);
00210         }
00213         static inline uint16 floatToHalfI(uint32 i)
00214         {
00215             register int s =  (i >> 16) & 0x00008000;
00216             register int e = ((i >> 23) & 0x000000ff) - (127 - 15);
00217             register int m =   i        & 0x007fffff;
00218         
00219             if (e <= 0)
00220             {
00221                 if (e < -10)
00222                 {
00223                     return 0;
00224                 }
00225                 m = (m | 0x00800000) >> (1 - e);
00226         
00227                 return s | (m >> 13);
00228             }
00229             else if (e == 0xff - (127 - 15))
00230             {
00231                 if (m == 0) // Inf
00232                 {
00233                     return s | 0x7c00;
00234                 } 
00235                 else    // NAN
00236                 {
00237                     m >>= 13;
00238                     return s | 0x7c00 | m | (m == 0);
00239                 }
00240             }
00241             else
00242             {
00243                 if (e > 30) // Overflow
00244                 {
00245                     return s | 0x7c00;
00246                 }
00247         
00248                 return s | (e << 10) | (m >> 13);
00249             }
00250         }
00251         
00256         static inline float halfToFloat(uint16 y)
00257         {
00258             union { float f; uint32 i; } v;
00259             v.i = halfToFloatI(y);
00260             return v.f;
00261         }
00265         static inline uint32 halfToFloatI(uint16 y)
00266         {
00267             register int s = (y >> 15) & 0x00000001;
00268             register int e = (y >> 10) & 0x0000001f;
00269             register int m =  y        & 0x000003ff;
00270         
00271             if (e == 0)
00272             {
00273                 if (m == 0) // Plus or minus zero
00274                 {
00275                     return s << 31;
00276                 }
00277                 else // Denormalized number -- renormalize it
00278                 {
00279                     while (!(m & 0x00000400))
00280                     {
00281                         m <<= 1;
00282                         e -=  1;
00283                     }
00284         
00285                     e += 1;
00286                     m &= ~0x00000400;
00287                 }
00288             }
00289             else if (e == 31)
00290             {
00291                 if (m == 0) // Inf
00292                 {
00293                     return (s << 31) | 0x7f800000;
00294                 }
00295                 else // NaN
00296                 {
00297                     return (s << 31) | 0x7f800000 | (m << 13);
00298                 }
00299             }
00300         
00301             e = e + (127 - 15);
00302             m = m << 13;
00303         
00304             return (s << 31) | (e << 23) | m;
00305         }
00306          
00307 
00308     };
00309 }
00310 
00311 #endif

Copyright © 2000-2005 by The OGRE Team
Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sun Nov 12 10:50:09 2006