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 Sep 27 22:02:22 2009