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
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sun Mar 12 14:37:37 2006