ScummVM API documentation
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
intrinsics.h
1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 // Based on eos' math code
23 
24 #ifndef COMMON_INTRINSICS_H
25 #define COMMON_INTRINSICS_H
26 
27 #include "common/scummsys.h"
28 #ifdef _MSC_VER
29 // HACK:
30 // intrin.h on MSVC includes setjmp.h, which will fail compiling due to our
31 // forbidden symbol colde. Since we also can not assure that defining
32 // FORBIDDEN_SYMBOL_EXCEPTION_setjmp and FORBIDDEN_SYMBOL_EXCEPTION_longjmp
33 // will actually allow the symbols, since forbidden.h might be included
34 // earlier already we need to undefine them here...
35 #undef setjmp
36 #undef longjmp
37 #include <intrin.h>
38 // ...and redefine them here so no code can actually use it.
39 // This could be resolved by including intrin.h on MSVC in scummsys.h before
40 // the forbidden.h include. This might make sense, in case we use MSVC
41 // extensions like _BitScanReverse in more places. But for now this hack should
42 // be ok...
43 #ifndef FORBIDDEN_SYMBOL_EXCEPTION_setjmp
44 #undef setjmp
45 #define setjmp(a) FORBIDDEN_SYMBOL_REPLACEMENT
46 #endif
47 
48 #ifndef FORBIDDEN_SYMBOL_EXCEPTION_longjmp
49 #undef longjmp
50 #define longjmp(a,b) FORBIDDEN_SYMBOL_REPLACEMENT
51 #endif
52 #endif
53 
54 namespace Common {
55 
56 #if defined(__GNUC__)
57 inline int intLog2(uint32 v) {
58  // This is a slightly optimized implementation of log2 for natural numbers
59  // targeting gcc. It also saves some binary size over our fallback
60  // implementation, since it does not need any table.
61  if (v == 0)
62  return -1;
63  else
64  // This is really "sizeof(unsigned int) * CHAR_BIT - 1" but using 8
65  // instead of CHAR_BIT is sane enough and it saves us from including
66  // limits.h
67  return (sizeof(unsigned int) * 8 - 1) - __builtin_clz(v);
68 }
69 #elif defined(_MSC_VER)
70 inline int intLog2(uint32 v) {
71  unsigned long result = 0;
72  unsigned char nonZero = _BitScanReverse(&result, v);
73  // _BitScanReverse stores the position of the MSB set in case its result
74  // is non zero, thus we can just return it as is.
75  return nonZero ? result : -1;
76 }
77 #else
78 // See http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogLookup
79 static const char LogTable256[256] = {
80 #define LT(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n
81  -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
82  LT(4), LT(5), LT(5), LT(6), LT(6), LT(6), LT(6),
83  LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7)
84 #undef LT
85 };
86 
87 inline int intLog2(uint32 v) {
88  uint32 t, tt;
89 
90  if ((tt = v >> 16))
91  return (t = tt >> 8) ? 24 + LogTable256[t] : 16 + LogTable256[tt];
92  else
93  return (t = v >> 8) ? 8 + LogTable256[t] : LogTable256[v];
94 }
95 #endif
96 
97 } // End of namespace Common
98 
99 #endif // COMMON_INTRINSICS_H
Definition: algorithm.h:29