# 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
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sun Dec 27 17:31:04 2009