HelpBrowser: path box becomes a more conventional search box
[supercollider.git] / SCClassLibrary / Common / Core / AbstractFunction.sc
blobbffe8d2f2a08b7457d7866229b2450cae81f3a28
1 AbstractFunction {
3         // function compositions
4         // override these in subclasses to perform different kinds of function compositions
5         composeUnaryOp { arg aSelector;
6                 ^UnaryOpFunction.new(aSelector, this)
7         }
8         composeBinaryOp { arg aSelector, something, adverb;
9                 ^BinaryOpFunction.new(aSelector, this, something, adverb);
10         }
11         reverseComposeBinaryOp { arg aSelector, something, adverb;
12                 ^BinaryOpFunction.new(aSelector, something, this, adverb);
13         }
14         composeNAryOp { arg aSelector, anArgList;
15                 ^NAryOpFunction.new(aSelector, this, anArgList)
16         }
18         // double dispatch for mixed operations
19         performBinaryOpOnSimpleNumber { arg aSelector, aNumber, adverb;
20                 ^this.reverseComposeBinaryOp(aSelector, aNumber, adverb)
21         }
22         performBinaryOpOnSignal { arg aSelector, aSignal, adverb;
23                 ^this.reverseComposeBinaryOp(aSelector, aSignal, adverb)
24         }
25         performBinaryOpOnComplex { arg aSelector, aComplex, adverb;
26                 ^this.reverseComposeBinaryOp(aSelector, aComplex, adverb)
27         }
28         performBinaryOpOnSeqColl { arg aSelector, aSeqColl, adverb;
29                 ^this.reverseComposeBinaryOp(aSelector, aSeqColl, adverb)
30         }
32         // respond to math operators
33         neg { ^this.composeUnaryOp('neg') }
34         reciprocal { ^this.composeUnaryOp('reciprocal') }
35         bitNot { ^this.composeUnaryOp('bitNot') }
36         abs { ^this.composeUnaryOp('abs') }
37         asFloat { ^this.composeUnaryOp('asFloat') }
38         asInteger { ^this.composeUnaryOp('asInteger') }
39         ceil { ^this.composeUnaryOp('ceil') }
40         floor { ^this.composeUnaryOp('floor') }
41         frac { ^this.composeUnaryOp('frac') }
42         sign { ^this.composeUnaryOp('sign') }
43         squared { ^this.composeUnaryOp('squared') }
44         cubed { ^this.composeUnaryOp('cubed') }
45         sqrt { ^this.composeUnaryOp('sqrt') }
46         exp { ^this.composeUnaryOp('exp') }
47         midicps { ^this.composeUnaryOp('midicps') }
48         cpsmidi { ^this.composeUnaryOp('cpsmidi') }
49         midiratio { ^this.composeUnaryOp('midiratio') }
50         ratiomidi { ^this.composeUnaryOp('ratiomidi') }
51         ampdb { ^this.composeUnaryOp('ampdb') }
52         dbamp { ^this.composeUnaryOp('dbamp') }
53         octcps { ^this.composeUnaryOp('octcps') }
54         cpsoct { ^this.composeUnaryOp('cpsoct') }
55         log { ^this.composeUnaryOp('log') }
56         log2 { ^this.composeUnaryOp('log2') }
57         log10 { ^this.composeUnaryOp('log10') }
58         sin { ^this.composeUnaryOp('sin') }
59         cos { ^this.composeUnaryOp('cos') }
60         tan { ^this.composeUnaryOp('tan') }
61         asin { ^this.composeUnaryOp('asin') }
62         acos { ^this.composeUnaryOp('acos') }
63         atan { ^this.composeUnaryOp('atan') }
64         sinh { ^this.composeUnaryOp('sinh') }
65         cosh { ^this.composeUnaryOp('cosh') }
66         tanh { ^this.composeUnaryOp('tanh') }
67         rand { ^this.composeUnaryOp('rand') }
68         rand2 { ^this.composeUnaryOp('rand2') }
69         linrand { ^this.composeUnaryOp('linrand') }
70         bilinrand { ^this.composeUnaryOp('bilinrand') }
71         sum3rand { ^this.composeUnaryOp('sum3rand') }
73         distort { ^this.composeUnaryOp('distort') }
74         softclip { ^this.composeUnaryOp('softclip') }
75         coin { ^this.composeUnaryOp('coin') }
76         even { ^this.composeUnaryOp('even') }
77         odd { ^this.composeUnaryOp('odd') }
79         rectWindow { ^this.composeUnaryOp('rectWindow') }
80         hanWindow { ^this.composeUnaryOp('hanWindow') }
81         welWindow { ^this.composeUnaryOp('welWindow') }
82         triWindow { ^this.composeUnaryOp('triWindow') }
84         scurve { ^this.composeUnaryOp('scurve') }
85         ramp { ^this.composeUnaryOp('ramp') }
87         isPositive { ^this.composeUnaryOp('isPositive') }
88         isNegative { ^this.composeUnaryOp('isNegative') }
89         isStrictlyPositive { ^this.composeUnaryOp('isStrictlyPositive') }
91         rho {  ^this.composeUnaryOp('rho') }
92         theta {  ^this.composeUnaryOp('theta') }
93         rotate { arg function; ^this.composeBinaryOp('rotate', function) }
94         dist { arg function; ^this.composeBinaryOp('dist', function) }
96         + { arg function, adverb; ^this.composeBinaryOp('+', function, adverb) }
97         - { arg function, adverb; ^this.composeBinaryOp('-', function, adverb) }
98         * { arg function, adverb; ^this.composeBinaryOp('*', function, adverb) }
99         / { arg function, adverb; ^this.composeBinaryOp('/', function, adverb) }
100         div { arg function, adverb; ^this.composeBinaryOp('div', function, adverb) }
101         mod { arg function, adverb; ^this.composeBinaryOp('mod', function, adverb) }
102         pow { arg function, adverb; ^this.composeBinaryOp('pow', function, adverb) }
103         min { arg function, adverb; ^this.composeBinaryOp('min', function, adverb) }
104         max { arg function=0, adverb; ^this.composeBinaryOp('max', function, adverb) }
106         <  { arg function, adverb; ^this.composeBinaryOp('<',  function, adverb) }
107         <= { arg function, adverb; ^this.composeBinaryOp('<=', function, adverb) }
108         >  { arg function, adverb; ^this.composeBinaryOp('>',  function, adverb) }
109         >= { arg function, adverb; ^this.composeBinaryOp('>=', function, adverb) }
111         bitAnd { arg function, adverb; ^this.composeBinaryOp('bitAnd', function, adverb) }
112         bitOr { arg function, adverb; ^this.composeBinaryOp('bitOr', function, adverb) }
113         bitXor { arg function, adverb; ^this.composeBinaryOp('bitXor', function, adverb) }      bitHammingDistance { arg function, adverb; ^this.composeBinaryOp('hammingDistance', function, adverb) }
115         lcm { arg function, adverb; ^this.composeBinaryOp('lcm', function, adverb) }
116         gcd { arg function, adverb; ^this.composeBinaryOp('gcd', function, adverb) }
117         round { arg function=1, adverb; ^this.composeBinaryOp('round', function, adverb) }
118         roundUp { arg function=1, adverb; ^this.composeBinaryOp('roundUp', function, adverb) }
119         trunc { arg function=1, adverb; ^this.composeBinaryOp('trunc', function, adverb) }
120         atan2 { arg function, adverb; ^this.composeBinaryOp('atan2', function, adverb) }
121         hypot { arg function, adverb; ^this.composeBinaryOp('hypot', function, adverb) }
122         hypotApx { arg function, adverb; ^this.composeBinaryOp('hypotApx', function, adverb) }
123         leftShift { arg function, adverb; ^this.composeBinaryOp('leftShift', function, adverb) }
124         rightShift { arg function, adverb; ^this.composeBinaryOp('rightShift', function, adverb) }
125         unsignedRightShift { arg function, adverb; ^this.composeBinaryOp('unsignedRightShift', function, adverb) }
126         ring1 { arg function, adverb; ^this.composeBinaryOp('ring1', function, adverb) }
127         ring2 { arg function, adverb; ^this.composeBinaryOp('ring2', function, adverb) }
128         ring3 { arg function, adverb; ^this.composeBinaryOp('ring3', function, adverb) }
129         ring4 { arg function, adverb; ^this.composeBinaryOp('ring4', function, adverb) }
130         difsqr { arg function, adverb; ^this.composeBinaryOp('difsqr', function, adverb) }
131         sumsqr { arg function, adverb; ^this.composeBinaryOp('sumsqr', function, adverb) }
132         sqrsum { arg function, adverb; ^this.composeBinaryOp('sqrsum', function, adverb) }
133         sqrdif { arg function, adverb; ^this.composeBinaryOp('sqrdif', function, adverb) }
134         absdif { arg function, adverb; ^this.composeBinaryOp('absdif', function, adverb) }
135         thresh { arg function, adverb; ^this.composeBinaryOp('thresh', function, adverb) }
136         amclip { arg function, adverb; ^this.composeBinaryOp('amclip', function, adverb) }
137         scaleneg { arg function, adverb; ^this.composeBinaryOp('scaleneg', function, adverb) }
138         clip2 { arg function=1, adverb; ^this.composeBinaryOp('clip2', function, adverb) }
139         fold2 { arg function=1, adverb; ^this.composeBinaryOp('fold2', function, adverb) }
140         wrap2 { arg function=1, adverb; ^this.composeBinaryOp('wrap2', function, adverb) }
141         excess { arg function=1, adverb; ^this.composeBinaryOp('excess', function, adverb) }
142         firstArg { arg function, adverb; ^this.composeBinaryOp('firstArg', function, adverb) }
143         rrand { arg function, adverb; ^this.composeBinaryOp('rrand', function, adverb) }
144         exprand { arg function, adverb; ^this.composeBinaryOp('exprand', function, adverb) }
145         @ { arg function, adverb; ^this.composeBinaryOp('@', function, adverb) }
147         // complex support
148         real { ^this }
149         imag { ^0.0 }
152         || { arg function, adverb; ^this.composeBinaryOp('||', function, adverb) }
153         && { arg function, adverb; ^this.composeBinaryOp('&&', function, adverb) }
154         xor { arg function, adverb; ^this.composeBinaryOp('xor', function, adverb) }
155         nand { arg function, adverb; ^this.composeBinaryOp('nand', function, adverb) }
156         not { ^this.composeUnaryOp('not') }
157         ref { ^this.composeUnaryOp('asRef') }
159         // nary operators
160         clip { arg lo, hi; ^this.composeNAryOp('clip', [lo,hi]) }
161         wrap { arg lo, hi; ^this.composeNAryOp('wrap', [lo,hi])  }
162         fold { arg lo, hi; ^this.composeNAryOp('fold', [lo,hi])  }
163         blend { arg that, blendFrac = 0.5; ^this.composeNAryOp('blend', [that, blendFrac]) }
165         linlin { arg inMin, inMax, outMin, outMax, clip=\minmax;
166                 ^this.composeNAryOp('linlin', [inMin, inMax, outMin, outMax, clip])
167         }
168         linexp { arg inMin, inMax, outMin, outMax, clip=\minmax;
169                 ^this.composeNAryOp('linexp', [inMin, inMax, outMin, outMax, clip])
170         }
171         explin { arg inMin, inMax, outMin, outMax, clip=\minmax;
172                 ^this.composeNAryOp('explin', [inMin, inMax, outMin, outMax, clip])
173         }
174         expexp { arg inMin, inMax, outMin, outMax, clip=\minmax;
175                 ^this.composeNAryOp('expexp', [inMin, inMax, outMin, outMax, clip])
176         }
178         degreeToKey { arg scale, stepsPerOctave=12;
179                 ^this.composeNAryOp('degreeToKey', [scale, stepsPerOctave])
180         }
182         degrad { ^this.composeUnaryOp('degrad') }
183         raddeg { ^this.composeUnaryOp('raddeg') }
185         applyTo { arg ... args;
186                 ^this.valueArray(args)
187         }
189         <> { arg that;
190                 // function composition
191                 ^{|...args| this.value(that.value(*args)) }
192         }
194         sampled{ |n=80,from=0.0,to=1.0|
195                 var valueArray;
196                 valueArray = (from,(to-from)/(n-1) .. to).collect{|x| this.value(x) };
197                 ^{ |x| valueArray.blendAt( ((x.clip(from,to)-from)/(to-from))*(n-1) ) }
198         }
200         // embed in ugen graph
201         asUGenInput { arg for; ^this.value(for) }
202         asAudioRateInput { |for|
203                 var result = this.value(for);
204                 ^if(result.rate != \audio) { K2A.ar(result) } { result }
205         }
206         // convert to control input
207         asControlInput { ^this.value }
208         isValidUGenInput { ^true }
212 UnaryOpFunction : AbstractFunction {
213         var selector, a;
215         *new { arg selector, a;
216                 ^super.newCopyArgs(selector, a)
217         }
218         value { arg ... args;
219                 ^a.valueArray(args).perform(selector)
220         }
221         valueArray { arg args;
222                 ^a.valueArray(args).perform(selector)
223         }
224         valueEnvir { arg ... args;
225                 ^a.valueArrayEnvir(args).perform(selector)
226         }
227         valueArrayEnvir { arg ... args;
228                 ^a.valueArrayEnvir(args).perform(selector)
229         }
230         functionPerformList { arg selector, arglist;
231                 ^this.performList(selector, arglist)
232         }
233         storeOn { arg stream;
234                 stream <<< a << "." << selector;
235         }
240 BinaryOpFunction : AbstractFunction {
241         var selector, a, b, adverb;
243         *new { arg selector, a, b, adverb;
244                 ^super.newCopyArgs(selector, a, b, adverb)
245         }
246         value { arg ... args;
247                 ^a.valueArray(args).perform(selector, b.valueArray(args), adverb)
248         }
249         valueArray { arg args;
250                 ^a.valueArray(args).perform(selector, b.valueArray(args), adverb)
251         }
252         valueEnvir { arg ... args;
253                 ^a.valueArrayEnvir(args).perform(selector, b.valueArrayEnvir(args), adverb)
254         }
255         valueArrayEnvir { arg ... args;
256                 ^a.valueArrayEnvir(args).perform(selector, b.valueArrayEnvir(args), adverb)
257         }
258         functionPerformList { arg selector, arglist;
259                 ^this.performList(selector, arglist)
260         }
261         storeOn { arg stream;
262                 stream << "(" <<< a << " " << selector.asBinOpString;
263                 if(adverb.notNil) { stream << "." << adverb };
264                 stream << " " <<< b << ")"
266         }
269 NAryOpFunction : AbstractFunction {
270         var selector, a, arglist;
272         *new { arg selector, a, arglist;
273                 ^super.newCopyArgs(selector, a, arglist)
274         }
275         value { arg ... args;
276                 ^a.valueArray(args).performList(selector, arglist.collect(_.valueArray(args)))
277         }
278         valueArray { arg args;
279                 ^a.valueArray(args).performList(selector, arglist.collect(_.valueArray(args)))
280         }
281         valueEnvir { arg ... args;
282                 ^a.valueArrayEnvir(args).performList(selector, arglist.collect(_.valueArrayEnvir(args)))
283         }
284         valueArrayEnvir { arg ... args;
285                 ^a.valueArrayEnvir(args).performList(selector, arglist.collect(_.valueArrayEnvir(args)))
286         }
287         functionPerformList { arg selector, arglist;
288                 ^this.performList(selector, arglist)
289         }
290         storeOn { arg stream;
291                 stream <<< a << "." << selector << "(" <<<* arglist << ")"
293         }
297 FunctionList : AbstractFunction {
298         var <>array, <flopped=false;
300         *new { arg functions;
301                 ^super.newCopyArgs(functions)
302         }
303         addFunc { arg ... functions;
304                 if(flopped) { Error("cannot add a function to a flopped FunctionList").throw };
305                 array = array.addAll(functions)
306         }
307         removeFunc { arg function;
308                 array.remove(function);
309                 if(array.size < 2) { ^array[0] };
310         }
311         
312         replaceFunc { arg find, replace;
313                 array = array.replace(find, replace);
314         }
316         value { arg ... args;
317                 var res = array.collect(_.valueArray(args));
318                 ^if(flopped) { res.flop } { res }
319         }
320         valueArray { arg args;
321                 var res = array.collect(_.valueArray(args));
322                 ^if(flopped) { res.flop } { res }
323         }
324         valueEnvir { arg ... args;
325                 var res = array.collect(_.valueArrayEnvir(args));
326                 ^if(flopped) { res.flop } { res }
327         }
328         valueArrayEnvir { arg args;
329                 var res = array.collect(_.valueArrayEnvir(args));
330                 ^if(flopped) { res.flop } { res }
331         }
332         do { arg function;
333                 array.do(function)
334         }
335         flop {
336                 if(flopped.not) {array = array.collect(_.flop) }; flopped = true;
337         }
338         envirFlop {
339                 if(flopped.not) {array = array.collect(_.envirFlop) }; flopped = true;
340         }
341         storeArgs { ^[array] }