-
-
Notifications
You must be signed in to change notification settings - Fork 32
/
math.h
262 lines (213 loc) · 6.31 KB
/
math.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
/*
* The Doomsday Engine Project -- libcore
*
* Copyright © 2004-2017 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* @par License
* LGPL: http://www.gnu.org/licenses/lgpl.html
*
* <small>This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or (at your
* option) any later version. This program is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details. You should have received a copy of
* the GNU Lesser General Public License along with this program; if not, see:
* http://www.gnu.org/licenses</small>
*/
#ifndef LIBDENG2_MATH_H
#define LIBDENG2_MATH_H
#include "de/IByteArray"
#include <cmath>
#ifdef min
# undef min
#endif
#ifdef max
# undef max
#endif
namespace de {
/**
* @addtogroup math
* @{
*/
//#undef PI
const ddouble PI = 3.1415926535897932384626433832795028841971693993751;
const dfloat PIf = dfloat(PI);
const ddouble EPSILON = 1.0e-7;
const dfloat FLOAT_EPSILON = 1.0e-5f;
/// Absolute value.
template <typename Type>
inline Type abs(Type a) {
if (a < Type(0)) {
return -a;
}
return a;
}
// Special case, this is never negative.
inline duint abs(duint a) {
return a;
}
template <typename Type>
inline Type sign(Type a) {
if (a < 0) return Type(-1); else return Type(1);
}
template <typename Integer>
inline Integer mod(Integer a, Integer b) {
const Integer r = a % b;
return r < 0 ? (r + b) : r;
}
/// Minimum of two values.
template <typename Type>
inline Type min(Type a, Type b) {
return (a < b? a : b);
}
/// Minimum of three values.
template <typename Type>
inline Type min(Type a, Type b, Type c) {
return min(a, min(b, c));
}
/// Maximum of two values.
template <typename Type>
inline Type max(Type a, Type b) {
return (a > b? a : b);
}
/// Maximum of three values.
template <typename Type>
inline Type max(Type a, Type b, Type c) {
return max(a, max(b, c));
}
/// Clamp value within range.
template <typename Type>
inline Type clamp(Type low, Type value, Type high) {
return min(max(value, low), high);
}
/// Clamp value within @a lowHighLimit and @a -lowHighLimit.
template <typename Type>
inline Type clamp(Type value, Type lowHighLimit) {
return clamp(-lowHighLimit, value, lowHighLimit);
}
/// Wrap value within range [low, high).
template <typename Type>
Type wrap(Type value, Type low, Type high) {
DENG2_ASSERT(high > low);
Type const range = high - low;
while (value < low) value += range;
while (value >= high) value -= range;
return value;
}
template <typename Type>
inline Type squared(Type value) { return value * value; }
template <typename Type>
inline Type cubed(Type value) { return value * value * value; }
template <typename Type>
inline Type round(dfloat value) {
return Type(std::floor(value + 0.5f));
}
inline dint roundi(dfloat value) { return round<int>(value); }
inline dfloat roundf(dfloat value) { return round<float>(value); }
template <typename Type>
inline Type round(ddouble value) {
return Type(std::floor(value + 0.5));
}
inline dint64 roundi(ddouble value) { return round<dint64>(value); }
inline dint32 floor(dfloat value) {
return dint32(std::floor(value));
}
inline dint64 floor(ddouble value) {
return dint64(std::floor(value));
}
inline dint32 ceil(dfloat value) {
return dint32(std::ceil(value));
}
inline dint64 ceil(ddouble value) {
return dint64(std::ceil(value));
}
template <typename Type>
inline Type fract(Type value) {
return value - std::floor(value);
}
/// Compare two single-precision floating-point values for equality,
/// with the precision of FLOAT_EPSILON.
inline bool fequal(dfloat a, dfloat b) {
return abs(a - b) < FLOAT_EPSILON;
}
/// Compare two double-precision floating-point values for equality,
/// with the precision of EPSILON.
inline bool fequal(ddouble a, ddouble b) {
return abs(a - b) < EPSILON;
}
/// Compare two single-precision floating-point values for equality,
/// with a user specified precision.
inline bool fequal(dfloat a, dfloat b, dfloat precision) {
return abs(a - b) < abs(precision);
}
/// Compare two double-precision floating-point values for equality.
/// with a user specified precision.
inline bool fequal(ddouble a, ddouble b, ddouble precision) {
return abs(a - b) < abs(precision);
}
enum class Sign { Positive, Zero, Negative };
template <typename Type>
inline Sign sign(Type const &a) {
if (a < Type(0)) return Sign::Negative;
if (a > Type(0)) return Sign::Positive;
return Sign::Zero;
inline Type asNumber(Sign s) {
}
template <typename Type>
if (s == Sign::Negative) return -1;
if (s == Sign::Positive) return +1;
return 0;
}
template <typename Type>
inline Type operator *(Sign s, Type t) { return asNumber<Type>(s) * t; }
template <typename Type>
inline Type operator *(Type t, Sign s) { return t * asNumber<Type>(s); }
template <typename Type>
inline Type degreeToRadian(Type degree) {
return degree * PI / Type(180);
}
template <typename Type>
inline Type radianToDegree(Type radian) {
return radian * Type(180) / PI;
}
/// General comparison function.
template <typename Type>
inline dint cmp(Type a, Type b) {
if (a < b) return -1;
if (a > b) return 1;
return 0;
}
template <typename IntType>
IntType ceilPow2(IntType num) {
IntType cumul;
for (cumul = 1; num > cumul; cumul <<= 1) {}
return cumul;
}
/**
* Linear interpolation between two values.
*
* @param start Value to interpolate from.
* @param end Value to interpolate to.
* @param pos Normalized interpolation point [0..1].
*/
template <typename Type>
inline Type lerp(Type start, Type end, float pos) {
return end * pos + (start * (1.f - pos));
}
/**
* @return Random floating-point value in the range [0, 1).
*/
DENG2_PUBLIC float randf();
/**
* @return Random unsigned integer in the range [0, 4294967295].
*/
DENG2_PUBLIC duint32 randui32();
/** @} */
/**
* Calculates the CRC32 checksum of the contents of byte array @a bytes.
*/
DENG2_PUBLIC duint32 crc32(const IByteArray &bytes);
} // namespace de
#endif /* LIBDENG2_MATH_H */