# 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
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sun Sep 17 15:39:07 2006