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 union { float f; uint32 i; } v; 00208 v.f = i; 00209 return floatToHalfI(v.i); 00210 } 00213 static inline uint16 floatToHalfI(uint32 i) 00214 { 00215 register int s = (i >> 16) & 0x00008000; 00216 register int e = ((i >> 23) & 0x000000ff) - (127 - 15); 00217 register int m = i & 0x007fffff; 00218 00219 if (e <= 0) 00220 { 00221 if (e < -10) 00222 { 00223 return 0; 00224 } 00225 m = (m | 0x00800000) >> (1 - e); 00226 00227 return s | (m >> 13); 00228 } 00229 else if (e == 0xff - (127 - 15)) 00230 { 00231 if (m == 0) // Inf 00232 { 00233 return s | 0x7c00; 00234 } 00235 else // NAN 00236 { 00237 m >>= 13; 00238 return s | 0x7c00 | m | (m == 0); 00239 } 00240 } 00241 else 00242 { 00243 if (e > 30) // Overflow 00244 { 00245 return s | 0x7c00; 00246 } 00247 00248 return s | (e << 10) | (m >> 13); 00249 } 00250 } 00251 00256 static inline float halfToFloat(uint16 y) 00257 { 00258 union { float f; uint32 i; } v; 00259 v.i = halfToFloatI(y); 00260 return v.f; 00261 } 00265 static inline uint32 halfToFloatI(uint16 y) 00266 { 00267 register int s = (y >> 15) & 0x00000001; 00268 register int e = (y >> 10) & 0x0000001f; 00269 register int m = y & 0x000003ff; 00270 00271 if (e == 0) 00272 { 00273 if (m == 0) // Plus or minus zero 00274 { 00275 return s << 31; 00276 } 00277 else // Denormalized number -- renormalize it 00278 { 00279 while (!(m & 0x00000400)) 00280 { 00281 m <<= 1; 00282 e -= 1; 00283 } 00284 00285 e += 1; 00286 m &= ~0x00000400; 00287 } 00288 } 00289 else if (e == 31) 00290 { 00291 if (m == 0) // Inf 00292 { 00293 return (s << 31) | 0x7f800000; 00294 } 00295 else // NaN 00296 { 00297 return (s << 31) | 0x7f800000 | (m << 13); 00298 } 00299 } 00300 00301 e = e + (127 - 15); 00302 m = m << 13; 00303 00304 return (s << 31) | (e << 23) | m; 00305 } 00306 00307 00308 }; 00309 } 00310 00311 #endif
Copyright © 2000-2005 by The OGRE Team
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sun Nov 12 10:50:09 2006