Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | 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             return floatToHalfI(*reinterpret_cast<uint32*>(&i));
00208         }
00211         static inline uint16 floatToHalfI(uint32 i)
00212         {
00213             register int s =  (i >> 16) & 0x00008000;
00214             register int e = ((i >> 23) & 0x000000ff) - (127 - 15);
00215             register int m =   i        & 0x007fffff;
00216         
00217             if (e <= 0)
00218             {
00219                 if (e < -10)
00220                 {
00221                     return 0;
00222                 }
00223                 m = (m | 0x00800000) >> (1 - e);
00224         
00225                 return s | (m >> 13);
00226             }
00227             else if (e == 0xff - (127 - 15))
00228             {
00229                 if (m == 0) // Inf
00230                 {
00231                     return s | 0x7c00;
00232                 } 
00233                 else    // NAN
00234                 {
00235                     m >>= 13;
00236                     return s | 0x7c00 | m | (m == 0);
00237                 }
00238             }
00239             else
00240             {
00241                 if (e > 30) // Overflow
00242                 {
00243                     return s | 0x7c00;
00244                 }
00245         
00246                 return s | (e << 10) | (m >> 13);
00247             }
00248         }
00249         
00254         static inline float halfToFloat(uint16 y)
00255         {
00256             uint32 r = halfToFloatI(y);
00257             return *reinterpret_cast<float*>(&r);
00258         }
00262         static inline uint32 halfToFloatI(uint16 y)
00263         {
00264             register int s = (y >> 15) & 0x00000001;
00265             register int e = (y >> 10) & 0x0000001f;
00266             register int m =  y        & 0x000003ff;
00267         
00268             if (e == 0)
00269             {
00270                 if (m == 0) // Plus or minus zero
00271                 {
00272                     return s << 31;
00273                 }
00274                 else // Denormalized number -- renormalize it
00275                 {
00276                     while (!(m & 0x00000400))
00277                     {
00278                         m <<= 1;
00279                         e -=  1;
00280                     }
00281         
00282                     e += 1;
00283                     m &= ~0x00000400;
00284                 }
00285             }
00286             else if (e == 31)
00287             {
00288                 if (m == 0) // Inf
00289                 {
00290                     return (s << 31) | 0x7f800000;
00291                 }
00292                 else // NaN
00293                 {
00294                     return (s << 31) | 0x7f800000 | (m << 13);
00295                 }
00296             }
00297         
00298             e = e + (127 - 15);
00299             m = m << 13;
00300         
00301             return (s << 31) | (e << 23) | m;
00302         }
00303          
00304 
00305     };
00306 }
00307 
00308 #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 Mar 12 14:37:37 2006