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-2012 Torus Knot Software Ltd 00008 00009 Permission is hereby granted, free of charge, to any person obtaining a copy 00010 of this software and associated documentation files (the "Software"), to deal 00011 in the Software without restriction, including without limitation the rights 00012 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00013 copies of the Software, and to permit persons to whom the Software is 00014 furnished to do so, subject to the following conditions: 00015 00016 The above copyright notice and this permission notice shall be included in 00017 all copies or substantial portions of the Software. 00018 00019 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00020 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00021 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00022 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00023 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00024 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00025 THE SOFTWARE. 00026 ----------------------------------------------------------------------------- 00027 */ 00028 #ifndef _Bitwise_H__ 00029 #define _Bitwise_H__ 00030 00031 #include "OgrePrerequisites.h" 00032 00033 namespace Ogre { 00043 class Bitwise { 00044 public: 00047 static FORCEINLINE unsigned int mostSignificantBitSet(unsigned int value) 00048 { 00049 unsigned int result = 0; 00050 while (value != 0) { 00051 ++result; 00052 value >>= 1; 00053 } 00054 return result-1; 00055 } 00060 static FORCEINLINE uint32 firstPO2From(uint32 n) 00061 { 00062 --n; 00063 n |= n >> 16; 00064 n |= n >> 8; 00065 n |= n >> 4; 00066 n |= n >> 2; 00067 n |= n >> 1; 00068 ++n; 00069 return n; 00070 } 00074 template<typename T> 00075 static FORCEINLINE bool isPO2(T n) 00076 { 00077 return (n & (n-1)) == 0; 00078 } 00082 template<typename T> 00083 static FORCEINLINE unsigned int getBitShift(T mask) 00084 { 00085 if (mask == 0) 00086 return 0; 00087 00088 unsigned int result = 0; 00089 while ((mask & 1) == 0) { 00090 ++result; 00091 mask >>= 1; 00092 } 00093 return result; 00094 } 00095 00101 template<typename SrcT, typename DestT> 00102 static inline DestT convertBitPattern(SrcT srcValue, SrcT srcBitMask, DestT destBitMask) 00103 { 00104 // Mask off irrelevant source value bits (if any) 00105 srcValue = srcValue & srcBitMask; 00106 00107 // Shift source down to bottom of DWORD 00108 const unsigned int srcBitShift = getBitShift(srcBitMask); 00109 srcValue >>= srcBitShift; 00110 00111 // Get max value possible in source from srcMask 00112 const SrcT srcMax = srcBitMask >> srcBitShift; 00113 00114 // Get max available in dest 00115 const unsigned int destBitShift = getBitShift(destBitMask); 00116 const DestT destMax = destBitMask >> destBitShift; 00117 00118 // Scale source value into destination, and shift back 00119 DestT destValue = (srcValue * destMax) / srcMax; 00120 return (destValue << destBitShift); 00121 } 00122 00127 static inline unsigned int fixedToFixed(uint32 value, unsigned int n, unsigned int p) 00128 { 00129 if(n > p) 00130 { 00131 // Less bits required than available; this is easy 00132 value >>= n-p; 00133 } 00134 else if(n < p) 00135 { 00136 // More bits required than are there, do the fill 00137 // Use old fashioned division, probably better than a loop 00138 if(value == 0) 00139 value = 0; 00140 else if(value == (static_cast<unsigned int>(1)<<n)-1) 00141 value = (1<<p)-1; 00142 else value = value*(1<<p)/((1<<n)-1); 00143 } 00144 return value; 00145 } 00146 00151 static inline unsigned int floatToFixed(const float value, const unsigned int bits) 00152 { 00153 if(value <= 0.0f) return 0; 00154 else if (value >= 1.0f) return (1<<bits)-1; 00155 else return (unsigned int)(value * (1<<bits)); 00156 } 00157 00161 static inline float fixedToFloat(unsigned value, unsigned int bits) 00162 { 00163 return (float)value/(float)((1<<bits)-1); 00164 } 00165 00169 static inline void intWrite(void *dest, const int n, const unsigned int value) 00170 { 00171 switch(n) { 00172 case 1: 00173 ((uint8*)dest)[0] = (uint8)value; 00174 break; 00175 case 2: 00176 ((uint16*)dest)[0] = (uint16)value; 00177 break; 00178 case 3: 00179 #if OGRE_ENDIAN == OGRE_ENDIAN_BIG 00180 ((uint8*)dest)[0] = (uint8)((value >> 16) & 0xFF); 00181 ((uint8*)dest)[1] = (uint8)((value >> 8) & 0xFF); 00182 ((uint8*)dest)[2] = (uint8)(value & 0xFF); 00183 #else 00184 ((uint8*)dest)[2] = (uint8)((value >> 16) & 0xFF); 00185 ((uint8*)dest)[1] = (uint8)((value >> 8) & 0xFF); 00186 ((uint8*)dest)[0] = (uint8)(value & 0xFF); 00187 #endif 00188 break; 00189 case 4: 00190 ((uint32*)dest)[0] = (uint32)value; 00191 break; 00192 } 00193 } 00197 static inline unsigned int intRead(const void *src, int n) { 00198 switch(n) { 00199 case 1: 00200 return ((uint8*)src)[0]; 00201 case 2: 00202 return ((uint16*)src)[0]; 00203 case 3: 00204 #if OGRE_ENDIAN == OGRE_ENDIAN_BIG 00205 return ((uint32)((uint8*)src)[0]<<16)| 00206 ((uint32)((uint8*)src)[1]<<8)| 00207 ((uint32)((uint8*)src)[2]); 00208 #else 00209 return ((uint32)((uint8*)src)[0])| 00210 ((uint32)((uint8*)src)[1]<<8)| 00211 ((uint32)((uint8*)src)[2]<<16); 00212 #endif 00213 case 4: 00214 return ((uint32*)src)[0]; 00215 } 00216 return 0; // ? 00217 } 00218 00222 static inline uint16 floatToHalf(float i) 00223 { 00224 union { float f; uint32 i; } v; 00225 v.f = i; 00226 return floatToHalfI(v.i); 00227 } 00230 static inline uint16 floatToHalfI(uint32 i) 00231 { 00232 register int s = (i >> 16) & 0x00008000; 00233 register int e = ((i >> 23) & 0x000000ff) - (127 - 15); 00234 register int m = i & 0x007fffff; 00235 00236 if (e <= 0) 00237 { 00238 if (e < -10) 00239 { 00240 return 0; 00241 } 00242 m = (m | 0x00800000) >> (1 - e); 00243 00244 return static_cast<uint16>(s | (m >> 13)); 00245 } 00246 else if (e == 0xff - (127 - 15)) 00247 { 00248 if (m == 0) // Inf 00249 { 00250 return static_cast<uint16>(s | 0x7c00); 00251 } 00252 else // NAN 00253 { 00254 m >>= 13; 00255 return static_cast<uint16>(s | 0x7c00 | m | (m == 0)); 00256 } 00257 } 00258 else 00259 { 00260 if (e > 30) // Overflow 00261 { 00262 return static_cast<uint16>(s | 0x7c00); 00263 } 00264 00265 return static_cast<uint16>(s | (e << 10) | (m >> 13)); 00266 } 00267 } 00268 00273 static inline float halfToFloat(uint16 y) 00274 { 00275 union { float f; uint32 i; } v; 00276 v.i = halfToFloatI(y); 00277 return v.f; 00278 } 00282 static inline uint32 halfToFloatI(uint16 y) 00283 { 00284 register int s = (y >> 15) & 0x00000001; 00285 register int e = (y >> 10) & 0x0000001f; 00286 register int m = y & 0x000003ff; 00287 00288 if (e == 0) 00289 { 00290 if (m == 0) // Plus or minus zero 00291 { 00292 return s << 31; 00293 } 00294 else // Denormalized number -- renormalize it 00295 { 00296 while (!(m & 0x00000400)) 00297 { 00298 m <<= 1; 00299 e -= 1; 00300 } 00301 00302 e += 1; 00303 m &= ~0x00000400; 00304 } 00305 } 00306 else if (e == 31) 00307 { 00308 if (m == 0) // Inf 00309 { 00310 return (s << 31) | 0x7f800000; 00311 } 00312 else // NaN 00313 { 00314 return (s << 31) | 0x7f800000 | (m << 13); 00315 } 00316 } 00317 00318 e = e + (127 - 15); 00319 m = m << 13; 00320 00321 return (s << 31) | (e << 23) | m; 00322 } 00323 00324 00325 }; 00329 } 00330 00331 #endif
Copyright © 2012 Torus Knot Software Ltd
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Last modified Fri May 25 23:36:23 2012