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"
28 inline float sc_mod(float in
, float hi
)
30 // avoid the divide if possible
31 const float lo
= (float)0.;
34 if (in
< hi
) return in
;
37 if (in
>= lo
) 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.;
50 if (in
< hi
) return in
;
53 if (in
>= lo
) 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
)
63 // avoid the divide if possible
67 if (in
< hi
) return in
;
71 if (in
>= lo
) 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
)
81 // avoid the divide if possible
85 if (in
< hi
) return in
;
89 if (in
>= lo
) 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
101 if (in
< hi
) return in
;
102 } else if (in
< lo
) {
104 if (in
>= lo
) 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
116 if (in
< hi
) return in
;
117 } else if (in
< lo
) {
119 if (in
>= lo
) 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
;
131 // avoid the divide if possible
134 if (in
>= lo
) return in
;
135 } else if (in
< lo
) {
137 if (in
< hi
) return in
;
140 if (hi
== lo
) return lo
;
143 range2
= range
+ range
;
144 c
= x
- range2
* sc_floor(x
/ range2
);
145 if (c
>=range
) c
= range2
- c
;
149 inline double sc_fold(double in
, double lo
, double hi
)
151 double x
, c
, range
, range2
;
154 // avoid the divide if possible
157 if (in
>= lo
) return in
;
158 } else if (in
< lo
) {
160 if (in
< hi
) return in
;
163 if (hi
== lo
) return lo
;
166 range2
= range
+ range
;
167 c
= x
- range2
* sc_floor(x
/ range2
);
168 if (c
>=range
) c
= range2
- c
;
172 inline double sc_fold(float in
, float lo
, float hi
, float range
, float range2
)
177 // avoid the divide if possible
180 if (in
>= lo
) return in
;
181 } else if (in
< lo
) {
183 if (in
< hi
) return in
;
186 if (hi
== lo
) return lo
;
188 c
= x
- range2
* sc_floor(x
/ range2
);
189 if (c
>=range
) c
= range2
- c
;
193 inline double sc_fold(double in
, double lo
, double hi
, double range
, double range2
)
198 // avoid the divide if possible
201 if (in
>= lo
) return in
;
202 } else if (in
< lo
) {
204 if (in
< hi
) return in
;
207 if (hi
== lo
) return lo
;
209 c
= x
- range2
* sc_floor(x
/ range2
);
210 if (c
>=range
) c
= range2
- c
;
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
)
271 return x
+ y
- kFSQRT2M1
* minxy
;
274 inline double sc_hypotx(double x
, double y
)
283 return x
+ y
- kDSQRT2M1
* minxy
;
291 inline int sc_div(int a
, int b
)
295 if (a
<0) c
= (a
+1)/b
- 1;
302 inline int sc_mod(int a, int b)
311 inline int sc_mod(int in
, int hi
)
313 // avoid the divide if possible
317 if (in
< hi
) return in
;
318 } else if (in
< lo
) {
320 if (in
>= lo
) return in
;
323 if (hi
== lo
) return lo
;
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
)
340 int c
= sc_mod(in
- lo
, b2
);
345 inline int sc_gcd(int u
, int v
)
350 if (u
<= 1 || v
<= 1) return 1;
352 if (u
<v
) { t
=u
; u
=v
; v
=t
; }
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
)
368 inline int sc_bitOr(int a
, int b
)
373 inline int sc_leftShift(int a
, int b
)
378 inline int sc_rightShift(int a
, int 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
)
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
)
461 inline float sc_scaleneg
<float>(float a
, float b
)
464 return (std::abs(a
) - a
) * b
+ a
;
468 inline double sc_scaleneg
<double>(double a
, double b
)
471 return (std::abs(a
) - a
) * b
+ a
;
474 template <typename T
>
475 inline T
sc_amclip(T a
, T b
)
484 inline float sc_amclip
<float>(float a
, float b
)
486 return a
* 0.5f
* (b
+ std::abs(b
));
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
)
501 template <typename T
>
502 inline T
sc_ring2(T a
, T b
)
507 template <typename T
>
508 inline T
sc_ring3(T a
, T 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
)
525 template <typename T
>
526 inline T
sc_sumsqr(T a
, T b
)
531 template <typename T
>
532 inline T
sc_sqrsum(T a
, T b
)
538 template <typename T
>
539 inline T
sc_sqrdif(T a
, T b
)
551 inline long sc_div(long a
, long b
)
555 if (a
<0) c
= (a
+1)/b
- 1;
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
)
571 long c
= sc_mod(in
- lo
, b2
);
576 inline long sc_bitAnd(long a
, long b
)
581 inline long sc_bitOr(long a
, long b
)
586 inline long sc_leftShift(long a
, long b
)
591 inline long sc_rightShift(long a
, long 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
)
606 if (u
<= 1 || v
<= 1) return 1;
608 if (u
<v
) { t
=u
; u
=v
; v
=t
; }
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
;