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