Merge pull request #506 from andrewcsmith/patch-2
[supercollider.git] / include / plugin_interface / SC_InlineBinaryOp.h
blob987ca6766d8ab73b5ae7b02234b066a25d473e56
1 /*
2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #ifndef _BinaryOpUGen_
22 #define _BinaryOpUGen_
24 #include "SC_BoundsMacros.h"
25 #include "SC_InlineUnaryOp.h"
26 #include <cmath>
28 inline float sc_mod(float in, float hi)
30 // avoid the divide if possible
31 const float lo = (float)0.;
32 if (in >= hi) {
33 in -= hi;
34 if (in < hi) return in;
35 } else if (in < lo) {
36 in += hi;
37 if (in >= lo) return in;
38 } else return in;
40 if (hi == lo) return lo;
41 return in - hi*sc_floor(in/hi);
44 inline double sc_mod(double in, double hi)
46 // avoid the divide if possible
47 const double lo = (double)0.;
48 if (in >= hi) {
49 in -= hi;
50 if (in < hi) return in;
51 } else if (in < lo) {
52 in += hi;
53 if (in >= lo) return in;
54 } else return in;
56 if (hi == lo) return lo;
57 return in - hi*sc_floor(in/hi);
60 inline float sc_wrap(float in, float lo, float hi)
62 float range;
63 // avoid the divide if possible
64 if (in >= hi) {
65 range = hi - lo;
66 in -= range;
67 if (in < hi) return in;
68 } else if (in < lo) {
69 range = hi - lo;
70 in += range;
71 if (in >= lo) return in;
72 } else return in;
74 if (hi == lo) return lo;
75 return in - range * sc_floor((in - lo)/range);
78 inline double sc_wrap(double in, double lo, double hi)
80 double range;
81 // avoid the divide if possible
82 if (in >= hi) {
83 range = hi - lo;
84 in -= range;
85 if (in < hi) return in;
86 } else if (in < lo) {
87 range = hi - lo;
88 in += range;
89 if (in >= lo) return in;
90 } else return in;
92 if (hi == lo) return lo;
93 return in - range * sc_floor((in - lo)/range);
96 inline double sc_wrap(double in, double lo, double hi, double range)
98 // avoid the divide if possible
99 if (in >= hi) {
100 in -= range;
101 if (in < hi) return in;
102 } else if (in < lo) {
103 in += range;
104 if (in >= lo) return in;
105 } else return in;
107 if (hi == lo) return lo;
108 return in - range * sc_floor((in - lo)/range);
111 inline double sc_wrap(float in, float lo, float hi, float range)
113 // avoid the divide if possible
114 if (in >= hi) {
115 in -= range;
116 if (in < hi) return in;
117 } else if (in < lo) {
118 in += range;
119 if (in >= lo) return in;
120 } else return in;
122 if (hi == lo) return lo;
123 return in - range * sc_floor((in - lo)/range);
126 inline float sc_fold(float in, float lo, float hi)
128 float x, c, range, range2;
129 x = in - lo;
131 // avoid the divide if possible
132 if (in >= hi) {
133 in = hi + hi - in;
134 if (in >= lo) return in;
135 } else if (in < lo) {
136 in = lo + lo - in;
137 if (in < hi) return in;
138 } else return in;
140 if (hi == lo) return lo;
141 // ok do the divide
142 range = hi - lo;
143 range2 = range + range;
144 c = x - range2 * sc_floor(x / range2);
145 if (c>=range) c = range2 - c;
146 return c + lo;
149 inline double sc_fold(double in, double lo, double hi)
151 double x, c, range, range2;
152 x = in - lo;
154 // avoid the divide if possible
155 if (in >= hi) {
156 in = hi + hi - in;
157 if (in >= lo) return in;
158 } else if (in < lo) {
159 in = lo + lo - in;
160 if (in < hi) return in;
161 } else return in;
163 if (hi == lo) return lo;
164 // ok do the divide
165 range = hi - lo;
166 range2 = range + range;
167 c = x - range2 * sc_floor(x / range2);
168 if (c>=range) c = range2 - c;
169 return c + lo;
172 inline double sc_fold(float in, float lo, float hi, float range, float range2)
174 float x, c;
175 x = in - lo;
177 // avoid the divide if possible
178 if (in >= hi) {
179 in = hi + hi - in;
180 if (in >= lo) return in;
181 } else if (in < lo) {
182 in = lo + lo - in;
183 if (in < hi) return in;
184 } else return in;
186 if (hi == lo) return lo;
187 // ok do the divide
188 c = x - range2 * sc_floor(x / range2);
189 if (c>=range) c = range2 - c;
190 return c + lo;
193 inline double sc_fold(double in, double lo, double hi, double range, double range2)
195 double x, c;
196 x = in - lo;
198 // avoid the divide if possible
199 if (in >= hi) {
200 in = hi + hi - in;
201 if (in >= lo) return in;
202 } else if (in < lo) {
203 in = lo + lo - in;
204 if (in < hi) return in;
205 } else return in;
207 if (hi == lo) return lo;
208 // ok do the divide
209 c = x - range2 * sc_floor(x / range2);
210 if (c>=range) c = range2 - c;
211 return c + lo;
214 inline float sc_pow(float a, float b)
216 return a >= 0.f ? std::pow(a, b) : -std::pow(-a, b);
219 inline double sc_pow(double a, double b)
221 return a >= 0.f ? std::pow(a, b) : -std::pow(-a, b);
224 inline float sc_round(float x, float quant)
226 return quant==0. ? x : sc_floor(x/quant + .5f) * quant;
229 inline double sc_round(double x, double quant)
231 return quant==0. ? x : sc_floor(x/quant + .5) * quant;
234 inline float sc_roundUp(float x, float quant)
236 return quant==0. ? x : sc_ceil(x/quant) * quant;
239 inline double sc_roundUp(double x, double quant)
241 return quant==0. ? x : sc_ceil(x/quant) * quant;
244 inline float sc_trunc(float x, float quant)
246 return quant==0. ? x : sc_floor(x/quant) * quant;
249 inline double sc_trunc(double x, double quant)
251 return quant==0. ? x : sc_floor(x/quant) * quant;
254 inline float sc_atan2(float a, float b)
256 return std::atan2(a, b);
259 const float kFSQRT2M1 = static_cast<float32>(sqrt(2.) - 1.);
260 const double kDSQRT2M1 = sqrt(2.) - 1.;
262 inline float sc_hypotx(float x, float y)
264 float minxy;
266 x = std::abs(x);
267 y = std::abs(y);
269 minxy = sc_min(x,y);
271 return x + y - kFSQRT2M1 * minxy;
274 inline double sc_hypotx(double x, double y)
276 double minxy;
278 x = std::abs(x);
279 y = std::abs(y);
281 minxy = sc_min(x,y);
283 return x + y - kDSQRT2M1 * minxy;
286 #ifndef _WIN32
287 #pragma mark -
288 #endif //_WIN32
291 inline int sc_div(int a, int b)
293 int c;
294 if (b) {
295 if (a<0) c = (a+1)/b - 1;
296 else c = a/b;
297 } else c = a;
298 return c;
302 inline int sc_mod(int a, int b)
304 long c;
305 c = a % b;
306 if (c<0) c += b;
307 return c;
311 inline int sc_mod(int in, int hi)
313 // avoid the divide if possible
314 const int lo = 0;
315 if (in >= hi) {
316 in -= hi;
317 if (in < hi) return in;
318 } else if (in < lo) {
319 in += hi;
320 if (in >= lo) return in;
321 } else return in;
323 if (hi == lo) return lo;
325 int c;
326 c = in % hi;
327 if (c<0) c += hi;
328 return c;
331 inline int sc_wrap(int in, int lo, int hi)
333 return sc_mod(in - lo, hi - lo + 1) + lo;
336 inline int sc_fold(int in, int lo, int hi)
338 int b = hi - lo;
339 int b2 = b+b;
340 int c = sc_mod(in - lo, b2);
341 if (c>b) c = b2-c;
342 return c + lo;
345 inline int sc_gcd(int u, int v)
347 int t;
348 u = sc_abs(u);
349 v = sc_abs(v);
350 if (u <= 1 || v <= 1) return 1;
351 while (u>0) {
352 if (u<v) { t=u; u=v; v=t; }
353 u = u % v;
355 return v;
358 inline int sc_lcm(int u, int v)
360 return (u * v)/sc_gcd(u,v);
363 inline int sc_bitAnd(int a, int b)
365 return a & b;
368 inline int sc_bitOr(int a, int b)
370 return a | b;
373 inline int sc_leftShift(int a, int b)
375 return a << b;
378 inline int sc_rightShift(int a, int b)
380 return a >> b;
383 inline int sc_unsignedRightShift(int a, int b)
385 return (uint32)a >> b;
388 inline int sc_round(int x, int quant)
390 return quant==0 ? x : sc_div(x + quant/2, quant) * quant;
394 inline int sc_roundUp(int x, int quant)
396 return quant==0 ? x : sc_div(x + quant - 1, quant) * quant;
399 inline int sc_trunc(int x, int quant)
401 return quant==0 ? x : sc_div(x, quant) * quant;
404 template <typename F>
405 inline F sc_powi (F x, unsigned int n)
407 F z = 1;
408 while (n != 0)
410 if ((n & 1) != 0)
412 z *= x;
414 n >>= 1;
415 x *= x;
418 return z;
421 template <typename T, typename U>
422 inline T sc_thresh(T a, U b)
424 return a < b ? (T)0 : a;
427 template <typename T>
428 inline T sc_clip2(T a, T b)
430 return sc_clip(a, -b, b);
433 template <typename T>
434 inline T sc_wrap2(T a, T b)
436 return sc_wrap(a, -b, b);
439 template <typename T>
440 inline T sc_fold2(T a, T b)
442 return sc_fold(a, -b, b);
445 template <typename T>
446 inline T sc_excess(T a, T b)
448 return a - sc_clip(a, -b, b);
451 template <typename T>
452 inline T sc_scaleneg(T a, T b)
454 if (a < 0)
455 return a*b;
456 else
457 return a;
460 template <>
461 inline float sc_scaleneg<float>(float a, float b)
463 b = 0.5f * b + 0.5f;
464 return (std::abs(a) - a) * b + a;
467 template <>
468 inline double sc_scaleneg<double>(double a, double b)
470 b = 0.5 * b + 0.5;
471 return (std::abs(a) - a) * b + a;
474 template <typename T>
475 inline T sc_amclip(T a, T b)
477 if (b < 0)
478 return 0;
479 else
480 return a*b;
483 template <>
484 inline float sc_amclip<float>(float a, float b)
486 return a * 0.5f * (b + std::abs(b));
489 template <>
490 inline double sc_amclip<double>(double a, double b)
492 return a * 0.5 * (b + std::abs(b));
495 template <typename T>
496 inline T sc_ring1(T a, T b)
498 return a *b + a;
501 template <typename T>
502 inline T sc_ring2(T a, T b)
504 return a*b + a + b;
507 template <typename T>
508 inline T sc_ring3(T a, T b)
510 return a*a*b;
513 template <typename T>
514 inline T sc_ring4(T a, T b)
516 return a*a*b - a*b*b;
519 template <typename T>
520 inline T sc_difsqr(T a, T b)
522 return a*a - b*b;
525 template <typename T>
526 inline T sc_sumsqr(T a, T b)
528 return a*a + b*b;
531 template <typename T>
532 inline T sc_sqrsum(T a, T b)
534 T z = a+b;
535 return z*z;
538 template <typename T>
539 inline T sc_sqrdif(T a, T b)
541 T z = a-b;
542 return z*z;
545 #ifndef _WIN32
546 #pragma mark -
547 #endif //_WIN32
549 #if 0
551 inline long sc_div(long a, long b)
553 int c;
554 if (b) {
555 if (a<0) c = (a+1)/b - 1;
556 else c = a/b;
557 } else c = a;
558 return c;
562 inline long sc_wrap(long in, long lo, long hi)
564 return sc_mod(in - lo, hi - lo + 1) + lo;
567 inline long sc_fold(long in, long lo, long hi)
569 long b = hi - lo;
570 int b2 = b+b;
571 long c = sc_mod(in - lo, b2);
572 if (c>b) c = b2-c;
573 return c + lo;
576 inline long sc_bitAnd(long a, long b)
578 return a & b;
581 inline long sc_bitOr(long a, long b)
583 return a | b;
586 inline long sc_leftShift(long a, long b)
588 return a << b;
591 inline long sc_rightShift(long a, long b)
593 return a >> b;
596 inline long sc_unsignedRightShift(long a, long b)
598 return (unsigned long)a >> b;
601 inline long sc_gcd(long u, long v)
603 long t;
604 u = sc_abs(u);
605 v = sc_abs(v);
606 if (u <= 1 || v <= 1) return 1;
607 while (u>0) {
608 if (u<v) { t=u; u=v; v=t; }
609 u = u % v;
611 return v;
614 inline long sc_lcm(long u, long v)
616 return (u * v)/sc_gcd(u,v);
619 inline long sc_round(long x, long quant)
621 return quant==0 ? x : sc_div(x + quant/2, quant) * quant;
624 #endif
626 #endif