ScummVM API documentation
math.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_MATH_H
25 #define COMMON_MATH_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 #ifndef FLT_MIN
55  #define FLT_MIN 1E-37f
56 #endif
57 
58 #ifndef FLT_MAX
59  #define FLT_MAX 1E+37f
60 #endif
61 
62 namespace Common {
63 
64 #if defined(__GNUC__)
65 inline int intLog2(uint32 v) {
66  // This is a slightly optimized implementation of log2 for natural numbers
67  // targeting gcc. It also saves some binary size over our fallback
68  // implementation, since it does not need any table.
69  if (v == 0)
70  return -1;
71  else
72  // This is really "sizeof(unsigned int) * CHAR_BIT - 1" but using 8
73  // instead of CHAR_BIT is sane enough and it saves us from including
74  // limits.h
75  return (sizeof(unsigned int) * 8 - 1) - __builtin_clz(v);
76 }
77 #elif defined(_MSC_VER)
78 inline int intLog2(uint32 v) {
79  unsigned long result = 0;
80  unsigned char nonZero = _BitScanReverse(&result, v);
81  // _BitScanReverse stores the position of the MSB set in case its result
82  // is non zero, thus we can just return it as is.
83  return nonZero ? result : -1;
84 }
85 #else
86 // See http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogLookup
87 static const char LogTable256[256] = {
88 #define LT(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n
89  -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
90  LT(4), LT(5), LT(5), LT(6), LT(6), LT(6), LT(6),
91  LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7)
92 #undef LT
93 };
94 
95 inline int intLog2(uint32 v) {
96  uint32 t, tt;
97 
98  if ((tt = v >> 16))
99  return (t = tt >> 8) ? 24 + LogTable256[t] : 16 + LogTable256[tt];
100  else
101  return (t = v >> 8) ? 8 + LogTable256[t] : LogTable256[v];
102 }
103 #endif
104 
105 // Round a number towards zero
106 // Input and Output type can be different
107 template<class InputT, class OutputT>
108 inline OutputT trunc(InputT x) {
109  return (x > 0) ? floor(x) : ceil(x);
110 }
111 
112 // Round a number towards zero
113 // Input and Output type are the same
114 template<class T>
115 inline T trunc(T x) {
116  return trunc<T,T>(x);
117 }
118 
119 // Convert radians to degrees
120 // Input and Output type can be different
121 // Upconvert everything to floats
122 template<class InputT, class OutputT>
123 inline OutputT rad2deg(InputT rad) {
124  return (OutputT)( (float)rad * (float)57.2957795130823); // 180.0/M_PI = 57.2957795130823
125 }
126 
127 // Handle the case differently when the input type is double
128 template<class OutputT>
129 inline OutputT rad2deg(double rad) {
130  return (OutputT)( rad * 57.2957795130823);
131 }
132 
133 // Convert radians to degrees
134 // Input and Output type are the same
135 template<class T>
136 inline T rad2deg(T rad) {
137  return rad2deg<T,T>(rad);
138 }
139 
140 // Convert degrees to radians
141 // Input and Output type can be different
142 // Upconvert everything to floats
143 template<class InputT, class OutputT>
144 inline OutputT deg2rad(InputT deg) {
145  return (OutputT)( (float)deg * (float)0.0174532925199433); // M_PI/180.0 = 0.0174532925199433
146 }
147 
148 // Handle the case differently when the input type is double
149 template<class OutputT>
150 inline OutputT deg2rad(double deg) {
151  return (OutputT)( deg * 0.0174532925199433);
152 }
153 
154 // Convert degrees to radians
155 // Input and Output type are the same
156 template<class T>
157 inline T deg2rad(T deg) {
158  return deg2rad<T,T>(deg);
159 }
160 
161 template<class T>
162 inline T hypotenuse(T xv, T yv) {
163  return (T)sqrt((double)(xv * xv + yv * yv));
164 }
165 
166 } // End of namespace Common
167 
168 #endif // COMMON_MATH_H
Definition: algorithm.h:29