Merge pull request #506 from andrewcsmith/patch-2
[supercollider.git] / server / supernova / utilities / template_functions.hpp
blobebb1c03b411078343bc1c927a13ee7ac2adb9cbe
1 // basic arithmetic objects
2 // Copyright (C) 2005, 2006, 2007, 2008 Tim Blechmann
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; see the file COPYING. If not, write to
16 // the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 // Boston, MA 02111-1307, USA.
19 #ifndef TEMPLATE_FUNCTIONS_HPP
20 #define TEMPLATE_FUNCTIONS_HPP
22 #include <cmath>
23 #include <algorithm> // for std::min & std::max
25 #include <boost/math/special_functions/fpclassify.hpp>
27 #include "force_inline.hpp"
29 namespace nova
31 template <typename T>
32 always_inline T identity(T arg)
34 return arg;
37 template <typename T>
38 always_inline T plus(T lhs, T rhs)
40 return lhs + rhs;
43 template <typename T>
44 always_inline T minus(T lhs, T rhs)
46 return lhs - rhs;
49 template <typename F>
50 always_inline F inv_minus(F lhs, F rhs)
52 return rhs - lhs;
55 template <typename T>
56 always_inline T times(T lhs, T rhs)
58 return lhs * rhs;
61 template <typename T>
62 always_inline T over(T lhs, T rhs)
64 return lhs / rhs;
67 template <typename F>
68 always_inline F inv_over(F lhs, F rhs)
70 return rhs / lhs;
73 template <typename F>
74 always_inline F fmod(F lhs, F rhs)
76 return std::fmod(lhs, rhs);
80 template <typename F>
81 always_inline F less(F lhs, F rhs)
83 return F(lhs < rhs);
86 template <typename F>
87 always_inline F less_equal(F lhs, F rhs)
89 return F(lhs <= rhs);
92 template <typename F>
93 always_inline F equal(F lhs, F rhs)
95 return F(lhs == rhs);
98 template <typename F>
99 always_inline F notequal(F lhs, F rhs)
101 return F(lhs != rhs);
104 template <typename F>
105 always_inline F greater(F lhs, F rhs)
107 return F(lhs > rhs);
110 template <typename F>
111 always_inline F greater_equal(F lhs, F rhs)
113 return F(lhs >= rhs);
116 using std::max;
117 using std::min;
120 template <typename F>
121 always_inline F nova_max(F lhs, F rhs)
123 return max(lhs, rhs);
126 template <typename F>
127 always_inline F nova_min(F lhs, F rhs)
129 return min(lhs, rhs);
132 template <typename F>
133 always_inline F sign(F arg)
135 if (arg > 0)
136 return F(1);
137 if (arg < 0)
138 return F(-1);
139 return F(0);
142 template <typename F>
143 always_inline F and_bool(F lhs, F rhs)
145 return F(bool(lhs) and bool(rhs));
148 template <typename F>
149 always_inline F and_bitwise(F lhs, F rhs)
151 return F(long(lhs) & long(rhs));
154 template <typename F>
155 always_inline F or_bool(F lhs, F rhs)
157 return F(bool(lhs) or bool(rhs));
160 template <typename F>
161 always_inline F or_bitwise(F lhs, F rhs)
163 return F(long(lhs) | long(rhs));
166 template <typename F>
167 always_inline F shift_left(F lhs, F rhs)
169 return F(long(lhs) << long(rhs));
172 template <typename F>
173 always_inline F shift_right(F lhs, F rhs)
175 return F(long(lhs) >> long(rhs));
178 template <typename F>
179 always_inline F inv_pow(F lhs, F rhs)
181 return std::pow(rhs, lhs);
184 template <typename F>
185 always_inline F square(F arg)
187 return arg * arg;
190 template <typename T>
191 always_inline T pow2(T const & arg)
193 return square(arg);
196 template <typename T>
197 always_inline T cube(T arg)
199 return arg * arg * arg;
202 template <typename T>
203 always_inline T pow3(T const & arg)
205 return cube(arg);
208 using std::sqrt;
210 template <typename F>
211 always_inline F rsqrt(F arg)
213 return F(1) / std::sqrt(arg);
216 template <typename F>
217 always_inline F rcp(F arg)
219 return F(1) / arg;
222 using std::abs;
225 template <typename F>
226 always_inline F isnormal(F arg)
228 #ifdef __INTEL_COMPILER /* intel compiler workaround */
229 return boost::math::isnormal(arg);
230 #else
231 return std::isnormal(arg);
232 #endif
236 template <typename F1, typename F2, typename F3>
237 always_inline F1 clip(F1 t, F2 low, F3 hi)
239 if (t < low)
240 return low;
241 else if (t > hi)
242 return hi;
243 else
244 return t;
247 template <typename F>
248 always_inline F modulo(F lhs, F rhs)
250 F ret = fmod(lhs, rhs);
251 if (ret < 0)
252 ret += rhs;
253 return ret;
256 template <typename I>
257 always_inline I wrap_optimistic(I val, const I mod)
259 if (unlikely(val >= mod))
261 val -= mod;
262 while (unlikely(val >= mod));
263 else
264 while (unlikely(val < I(0)))
265 val += mod;
267 return val;
270 template <typename I>
271 always_inline I scale_linear(I in,
272 I const & low_in, I const & high_in,
273 I const & low_out, I const & high_out)
275 return (in-low_in) / (high_in-low_in) * (high_out-low_out) + low_out;
278 template <typename I>
279 always_inline I scale_linear_clipped(I in,
280 I const & low_in, I const & high_in,
281 I const & low_out, I const & high_out)
283 return (in-low_in) / (high_in-low_in) * (high_out-low_out) + low_out;
287 } /* namespace nova */
289 #endif /* TEMPLATE_FUNCTIONS_HPP */