]> Dogcows Code - chaz/yoink/blob - src/moof/cml/util.h
fixes for newer versions of g++
[chaz/yoink] / src / moof / cml / util.h
1 /* -*- C++ -*- ------------------------------------------------------------
2
3 Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/
4
5 The Configurable Math Library (CML) is distributed under the terms of the
6 Boost Software License, v1.0 (see cml/LICENSE for details).
7
8 *-----------------------------------------------------------------------*/
9 /** @file
10 * @brief
11 */
12
13 #ifndef cml_util_h
14 #define cml_util_h
15
16 #include <algorithm> // For std::min and std::max.
17 #include <cstdlib> // For std::rand.
18 #include <cml/constants.h>
19
20 #if defined(_MSC_VER)
21 #pragma push_macro("min")
22 #pragma push_macro("max")
23 #undef min
24 #undef max
25 #endif
26
27 namespace cml {
28
29 /** Sign of input value as double. */
30 template < typename T >
31 double sign(T value) {
32 return value < T(0) ? -1.0 : (value > T(0) ? 1.0 : 0.0);
33 }
34
35 /** Clamp input value to the range [min, max]. */
36 template < typename T >
37 T clamp(T value, T min, T max) {
38 return std::max(std::min(value, max), min);
39 }
40
41 /** Test input value for inclusion in [min, max]. */
42 template < typename T >
43 bool in_range(T value, T min, T max) {
44 return !(value < min) && !(value > max);
45 }
46
47 /** Map input value from [min1, max1] to [min2, max2]. */
48 template < typename T >
49 T map_range(T value, T min1, T max1, T min2, T max2) {
50 return min2 + ((value - min1) / (max1 - min1)) * (max2 - min2);
51 }
52
53
54 /** Wrap std::acos() and clamp argument to [-1, 1]. */
55 template < typename T >
56 T acos_safe(T theta) {
57 return T(std::acos(clamp(theta, T(-1.0), T(1.0))));
58 }
59
60 /** Wrap std::asin() and clamp argument to [-1, 1]. */
61 template < typename T >
62 T asin_safe(T theta) {
63 return T(std::asin(clamp(theta, T(-1.0), T(1.0))));
64 }
65
66 /** Wrap std::sqrt() and clamp argument to [0, inf). */
67 template < typename T >
68 T sqrt_safe(T value) {
69 return T(std::sqrt(std::max(value, T(0.0))));
70 }
71
72
73 /** Square a value. */
74 template < typename T >
75 T sqr(T value) {
76 return value * value;
77 }
78
79 /** Cube a value. */
80 template < typename T >
81 T cub(T value) {
82 return value * value * value;
83 }
84
85 /** Inverse square root. */
86 template < typename T >
87 T inv_sqrt(T value) {
88 return T(1.0 / std::sqrt(value));
89 }
90
91
92 /* The next few functions deal with indexing. next() and prev() are useful
93 * for operations involving the vertices of a polygon or other cyclic set,
94 * and cyclic_permutation() is used by various functions that deal with
95 * axes or basis vectors in a generic way. As these functions are only
96 * relevant for unsigned integer types, I've just used size_t, but there
97 * may be reasons I haven't thought of that they should be templated.
98 */
99
100 /** Return next, with cycling, in a series of N non-negative integers. */
101 inline size_t next(size_t i, size_t N) {
102 return (i + 1) % N;
103 }
104
105 /** Return previous, with cycling, in a series of N non-negative integers. */
106 inline size_t prev(size_t i, size_t N) {
107 return i ? (i - 1) : (N - 1);
108 }
109
110 /** Cyclic permutation of the set { 0, 1 }, starting with 'first'. */
111 inline void cyclic_permutation(size_t first, size_t& i, size_t& j) {
112 i = first;
113 j = next(i, 2);
114 }
115
116 /** Cyclic permutation of the set { 0, 1, 2 }, starting with 'first'. */
117 inline void cyclic_permutation(size_t first, size_t& i, size_t& j, size_t& k)
118 {
119 i = first;
120 j = next(i, 3);
121 k = next(j, 3);
122 }
123
124 /** Cyclic permutation of the set { 0, 1, 2, 3 }, starting with 'first'. */
125 inline void cyclic_permutation(
126 size_t first, size_t& i, size_t& j, size_t& k, size_t& l)
127 {
128 i = first;
129 j = next(i, 4);
130 k = next(j, 4);
131 l = next(k, 4);
132 }
133
134
135 /** Convert radians to degrees. */
136 template < typename T >
137 T deg(T theta) {
138 return theta * constants<T>::deg_per_rad();
139 }
140
141 /** Convert degrees to radians. */
142 template < typename T >
143 T rad(T theta) {
144 return theta * constants<T>::rad_per_deg();
145 }
146
147 /* Note: Moving interpolation functions to interpolation.h */
148
149 #if 0
150 /** Linear interpolation of 2 values.
151 *
152 * @note The data points are assumed to be sampled at u = 0 and u = 1, so
153 * for interpolation u must lie between 0 and 1.
154 */
155 template <typename T, typename Scalar>
156 T lerp(const T& f0, const T& f1, Scalar u) {
157 return (Scalar(1.0) - u) * f0 + u * f1;
158 }
159 #endif
160
161 #if 0
162 /** Bilinear interpolation of 4 values.
163 *
164 * @note The data points are assumed to be sampled at the corners of a unit
165 * square, so for interpolation u and v must lie between 0 and 1,
166 */
167 template <typename T, typename Scalar>
168 T bilerp(const T& f00, const T& f10,
169 const T& f01, const T& f11,
170 Scalar u, Scalar v)
171 {
172 Scalar uv = u * v;
173 return (
174 (Scalar(1.0) - u - v + uv) * f00 +
175 (u - uv) * f10 +
176 (v - uv) * f01 +
177 uv * f11
178 );
179 }
180 #endif
181
182 #if 0
183 /** Trilinear interpolation of 8 values.
184 *
185 * @note The data values are assumed to be sampled at the corners of a unit
186 * cube, so for interpolation, u, v, and w must lie between 0 and 1.
187 */
188 template <typename T, typename Scalar>
189 T trilerp(const T& f000, const T& f100,
190 const T& f010, const T& f110,
191 const T& f001, const T& f101,
192 const T& f011, const T& f111,
193 Scalar u, Scalar v, Scalar w)
194 {
195 Scalar uv = u * v;
196 Scalar vw = v * w;
197 Scalar wu = w * u;
198 Scalar uvw = uv * w;
199
200 return (
201 (Scalar(1.0) - u - v - w + uv + vw + wu - uvw) * f000 +
202 (u - uv - wu + uvw) * f100 +
203 (v - uv - vw + uvw) * f010 +
204 (uv - uvw) * f110 +
205 (w - vw - wu + uvw) * f001 +
206 (wu - uvw) * f101 +
207 (vw - uvw) * f011 +
208 uvw * f111
209 );
210 }
211 #endif
212
213 /** Random binary (0,1) value. */
214 inline size_t random_binary() {
215 return std::rand() % 2;
216 }
217
218 /** Random polar (-1,1) value. */
219 inline int random_polar() {
220 return random_binary() ? 1 : -1;
221 }
222
223 /** Random real in [0,1]. */
224 inline double random_unit() {
225 return double(std::rand()) / double(RAND_MAX);
226 }
227
228 /* Random integer in the range [min, max] */
229 inline long random_integer(long min, long max) {
230 return min + std::rand() % (max - min + 1);
231 }
232
233 /* Random real number in the range [min, max] */
234 template < typename T >
235 T random_real(T min, T max) {
236 return min + random_unit() * (max - min);
237 }
238
239 /** Squared length in R2. */
240 template < typename T >
241 T length_squared(T x, T y) {
242 return x * x + y * y;
243 }
244
245 /** Squared length in R3. */
246 template < typename T >
247 T length_squared(T x, T y, T z) {
248 return x * x + y * y + z * z;
249 }
250
251 /** Length in R2. */
252 template < typename T >
253 T length(T x, T y) {
254 return std::sqrt(length_squared(x,y));
255 }
256
257 /** Length in R3. */
258 template < typename T >
259 T length(T x, T y, T z) {
260 return std::sqrt(length_squared(x,y,z));
261 }
262
263 /** Index of maximum of 2 values. */
264 template < typename T >
265 size_t index_of_max(T a, T b) {
266 return a > b ? 0 : 1;
267 }
268
269 /** Index of maximum of 2 values by magnitude. */
270 template < typename T >
271 size_t index_of_max_abs(T a, T b) {
272 return index_of_max(std::fabs(a),std::fabs(b));
273 }
274
275 /** Index of minimum of 2 values. */
276 template < typename T >
277 size_t index_of_min(T a, T b) {
278 return a < b ? 0 : 1;
279 }
280
281 /** Index of minimum of 2 values by magnitude. */
282 template < typename T >
283 size_t index_of_min_abs(T a, T b) {
284 return index_of_min(std::fabs(a),std::fabs(b));
285 }
286
287 /** Index of maximum of 3 values. */
288 template < typename T >
289 size_t index_of_max(T a, T b, T c) {
290 return a > b ? (c > a ? 2 : 0) : (b > c ? 1 : 2);
291 }
292
293 /** Index of maximum of 3 values by magnitude. */
294 template < typename T >
295 size_t index_of_max_abs(T a, T b, T c) {
296 return index_of_max(std::fabs(a),std::fabs(b),std::fabs(c));
297 }
298
299 /** Index of minimum of 3 values. */
300 template < typename T >
301 size_t index_of_min(T a, T b, T c) {
302 return a < b ? (c < a ? 2 : 0) : (b < c ? 1 : 2);
303 }
304
305 /** Index of minimum of 3 values by magnitude. */
306 template < typename T >
307 size_t index_of_min_abs(T a, T b, T c) {
308 return index_of_min(std::fabs(a),std::fabs(b),std::fabs(c));
309 }
310
311 /** Wrap input value to the range [min,max]. */
312 template < typename T >
313 T wrap(T value, T min, T max) {
314 max -= min;
315 value = std::fmod(value - min, max);
316 if (value < T(0)) {
317 value += max;
318 }
319 return min + value;
320 }
321
322 /** Convert horizontal field of view to vertical field of view. */
323 template < typename T >
324 T xfov_to_yfov(T xfov, T aspect) {
325 return T(2.0 * std::atan(std::tan(xfov * T(.5)) / double(aspect)));
326 }
327
328 /** Convert vertical field of view to horizontal field of view. */
329 template < typename T >
330 T yfov_to_xfov(T yfov, T aspect) {
331 return T(2.0 * std::atan(std::tan(yfov * T(.5)) * double(aspect)));
332 }
333
334 /** Convert horizontal zoom to vertical zoom. */
335 template < typename T >
336 T xzoom_to_yzoom(T xzoom, T aspect) {
337 return xzoom * aspect;
338 }
339
340 /** Convert vertical zoom to horizontal zoom. */
341 template < typename T >
342 T yzoom_to_xzoom(T yzoom, T aspect) {
343 return yzoom / aspect;
344 }
345
346 /** Convert zoom factor to field of view. */
347 template < typename T >
348 T zoom_to_fov(T zoom) {
349 return T(2) * T(std::atan(T(1) / zoom));
350 }
351
352 /** Convert field of view to zoom factor. */
353 template < typename T >
354 T fov_to_zoom(T fov) {
355 return T(1) / T(std::tan(fov * T(.5)));
356 }
357
358 } // namespace cml
359
360 #if defined(_MSC_VER)
361 #pragma pop_macro("min")
362 #pragma pop_macro("max")
363 #endif
364
365 #endif
366
367 // -------------------------------------------------------------------------
368 // vim:ft=cpp
This page took 0.045927 seconds and 4 git commands to generate.