# 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:
    00039         template<typename T>
    00040         static FORCEINLINE unsigned int getBitShift(T mask)
    00041         {
    00042             if (mask == 0)
    00043                 return 0;
    00044
    00045             unsigned int result = 0;
    00046             while ((mask & 1) == 0) {
    00047                 ++result;
    00048                 mask >>= 1;
    00049             }
    00050             return result;
    00051         }
    00052
    00058         template<typename SrcT, typename DestT>
    00059         static inline DestT convertBitPattern(SrcT srcValue, SrcT srcBitMask, DestT destBitMask)
    00060         {
    00061             // Mask off irrelevant source value bits (if any)
    00062             srcValue = srcValue & srcBitMask;
    00063
    00064             // Shift source down to bottom of DWORD
    00065             const unsigned int srcBitShift = getBitShift(srcBitMask);
    00066             srcValue >>= srcBitShift;
    00067
    00068             // Get max value possible in source from srcMask
    00069             const SrcT srcMax = srcBitMask >> srcBitShift;
    00070
    00071             // Get max avaiable in dest
    00072             const unsigned int destBitShift = getBitShift(destBitMask);
    00073             const DestT destMax = destBitMask >> destBitShift;
    00074
    00075             // Scale source value into destination, and shift back
    00076             DestT destValue = (srcValue * destMax) / srcMax;
    00077             return (destValue << destBitShift);
    00078         }
    00079
    00084         static inline unsigned int fixedToFixed(uint32 value, unsigned int n, unsigned int p)
    00085         {
    00086             if(n > p)
    00087             {
    00088                 // Less bits required than available; this is easy
    00089                 value >>= n-p;
    00090             }
    00091             else if(n < p)
    00092             {
    00093                 // More bits required than are there, do the fill
    00094                 // Use old fashioned division, probably better than a loop
    00095                 if(value == 0)
    00096                         value = 0;
    00097                 else if(value == (static_cast<unsigned int>(1)<<n)-1)
    00098                         value = (1<<p)-1;
    00099                 else    value = value*(1<<p)/((1<<n)-1);
    00100             }
    00101             return value;
    00102         }
    00103
    00108         static inline unsigned int floatToFixed(const float value, const unsigned int bits)
    00109         {
    00110             if(value <= 0.0f) return 0;
    00111             else if (value >= 1.0f) return (1<<bits)-1;
    00112             else return (unsigned int)(value * (1<<bits));
    00113         }
    00114
    00118         static inline float fixedToFloat(unsigned value, unsigned int bits)
    00119         {
    00120             return (float)value/(float)((1<<bits)-1);
    00121         }
    00122
    00126         static inline void intWrite(const void *dest, const int n, const unsigned int value)
    00127         {
    00128             switch(n) {
    00129                 case 1:
    00130                     ((uint8*)dest)[0] = (uint8)value;
    00131                     break;
    00132                 case 2:
    00133                     ((uint16*)dest)[0] = (uint16)value;
    00134                     break;
    00135                 case 3:
    00136 #if OGRE_ENDIAN == OGRE_ENDIAN_BIG
    00137                     ((uint8*)dest)[0] = (uint8)((value >> 16) & 0xFF);
    00138                     ((uint8*)dest)[1] = (uint8)((value >> 8) & 0xFF);
    00139                     ((uint8*)dest)[2] = (uint8)(value & 0xFF);
    00140 #else
    00141                     ((uint8*)dest)[2] = (uint8)((value >> 16) & 0xFF);
    00142                     ((uint8*)dest)[1] = (uint8)((value >> 8) & 0xFF);
    00143                     ((uint8*)dest)[0] = (uint8)(value & 0xFF);
    00144 #endif
    00145                     break;
    00146                 case 4:
    00147                     ((uint32*)dest)[0] = (uint32)value;
    00148                     break;
    00149             }
    00150         }
    00154         static inline unsigned int intRead(const void *src, int n) {
    00155             switch(n) {
    00156                 case 1:
    00157                     return ((uint8*)src)[0];
    00158                 case 2:
    00159                     return ((uint16*)src)[0];
    00160                 case 3:
    00161 #if OGRE_ENDIAN == OGRE_ENDIAN_BIG
    00162                     return ((uint32)((uint8*)src)[0]<<16)|
    00163                             ((uint32)((uint8*)src)[1]<<8)|
    00164                             ((uint32)((uint8*)src)[2]);
    00165 #else
    00166                     return ((uint32)((uint8*)src)[0])|
    00167                             ((uint32)((uint8*)src)[1]<<8)|
    00168                             ((uint32)((uint8*)src)[2]<<16);
    00169 #endif
    00170                 case 4:
    00171                     return ((uint32*)src)[0];
    00172             }
    00173             return 0; // ?
    00174         }
    00175
    00179         static inline uint16 floatToHalf(float i)
    00180         {
    00181             return floatToHalfI(*reinterpret_cast<uint32*>(&i));
    00182         }
    00185         static inline uint16 floatToHalfI(uint32 i)
    00186         {
    00187             register int s =  (i >> 16) & 0x00008000;
    00188             register int e = ((i >> 23) & 0x000000ff) - (127 - 15);
    00189             register int m =   i        & 0x007fffff;
    00190
    00191             if (e <= 0)
    00192             {
    00193                 if (e < -10)
    00194                 {
    00195                     return 0;
    00196                 }
    00197                 m = (m | 0x00800000) >> (1 - e);
    00198
    00199                 return s | (m >> 13);
    00200             }
    00201             else if (e == 0xff - (127 - 15))
    00202             {
    00203                 if (m == 0) // Inf
    00204                 {
    00205                     return s | 0x7c00;
    00206                 }
    00207                 else    // NAN
    00208                 {
    00209                     m >>= 13;
    00210                     return s | 0x7c00 | m | (m == 0);
    00211                 }
    00212             }
    00213             else
    00214             {
    00215                 if (e > 30) // Overflow
    00216                 {
    00217                     return s | 0x7c00;
    00218                 }
    00219
    00220                 return s | (e << 10) | (m >> 13);
    00221             }
    00222         }
    00223
    00228         static inline float halfToFloat(uint16 y)
    00229         {
    00230             uint32 r = halfToFloatI(y);
    00231             return *reinterpret_cast<float*>(&r);
    00232         }
    00236         static inline uint32 halfToFloatI(uint16 y)
    00237         {
    00238             register int s = (y >> 15) & 0x00000001;
    00239             register int e = (y >> 10) & 0x0000001f;
    00240             register int m =  y        & 0x000003ff;
    00241
    00242             if (e == 0)
    00243             {
    00244                 if (m == 0) // Plus or minus zero
    00245                 {
    00246                     return s << 31;
    00247                 }
    00248                 else // Denormalized number -- renormalize it
    00249                 {
    00250                     while (!(m & 0x00000400))
    00251                     {
    00252                         m <<= 1;
    00253                         e -=  1;
    00254                     }
    00255
    00256                     e += 1;
    00257                     m &= ~0x00000400;
    00258                 }
    00259             }
    00260             else if (e == 31)
    00261             {
    00262                 if (m == 0) // Inf
    00263                 {
    00264                     return (s << 31) | 0x7f800000;
    00265                 }
    00266                 else // NaN
    00267                 {
    00268                     return (s << 31) | 0x7f800000 | (m << 13);
    00269                 }
    00270             }
    00271
    00272             e = e + (127 - 15);
    00273             m = m << 13;
    00274
    00275             return (s << 31) | (e << 23) | m;
    00276         }
    00277
    00278
    00279     };
    00280 }
    00281
    00282 #endif

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