cmake build system: visiblity support for clang
[supercollider.git] / SCClassLibrary / Common / Math / SimpleNumber.sc
blob7dc362fa5ca91928ec9ae9653a28115aad68fc7c
1 SimpleNumber : Number {
3         *new { ^this.shouldNotImplement(thisMethod) }
5         isValidUGenInput { ^this.isNaN.not }
6         numChannels { ^1 }
8         magnitude { ^this.abs }
9         angle { if (this >= 0, {^0.0}, {^pi} ) }
12         neg { _Neg; ^this.primitiveFailed }
13         bitNot { _BitNot; ^this.primitiveFailed }
14         abs { _Abs; ^this.primitiveFailed }
15         ceil { _Ceil; ^this.primitiveFailed }
16         floor { _Floor; ^this.primitiveFailed }
17         frac { _Frac; ^this.primitiveFailed }
18         sign { _Sign; ^this.primitiveFailed }
19         squared { _Squared; ^this.primitiveFailed }
20         cubed { _Cubed; ^this.primitiveFailed }
21         sqrt { _Sqrt; ^this.primitiveFailed }
22         exp { _Exp; ^this.primitiveFailed }
23         reciprocal { _Recip; ^this.primitiveFailed }
24         midicps { _MIDICPS; ^this.primitiveFailed }
25         cpsmidi { _CPSMIDI; ^this.primitiveFailed }
26         midiratio { _MIDIRatio; ^this.primitiveFailed }
27         ratiomidi { _RatioMIDI; ^this.primitiveFailed }
28         ampdb { _AmpDb; ^this.primitiveFailed }
29         dbamp { _DbAmp; ^this.primitiveFailed }
30         octcps { _OctCPS; ^this.primitiveFailed }
31         cpsoct { _CPSOct; ^this.primitiveFailed }
32         log { _Log; ^this.primitiveFailed }
33         log2 { _Log2; ^this.primitiveFailed }
34         log10 { _Log10; ^this.primitiveFailed }
35         sin { _Sin; ^this.primitiveFailed }
36         cos { _Cos; ^this.primitiveFailed }
37         tan { _Tan; ^this.primitiveFailed }
38         asin { _ArcSin; ^this.primitiveFailed }
39         acos { _ArcCos; ^this.primitiveFailed }
40         atan { _ArcTan; ^this.primitiveFailed }
41         sinh { _SinH; ^this.primitiveFailed }
42         cosh { _CosH; ^this.primitiveFailed }
43         tanh { _TanH; ^this.primitiveFailed }
44         rand { _Rand; ^this.primitiveFailed }
45         rand2 { _Rand2; ^this.primitiveFailed }
46         linrand { _LinRand; ^this.primitiveFailed }
47         bilinrand { _BiLinRand; ^this.primitiveFailed }
48         sum3rand { _Sum3Rand; ^this.primitiveFailed }
50         distort { _Distort; ^this.primitiveFailed }
51         softclip { _SoftClip; ^this.primitiveFailed }
52         coin { _Coin; ^this.primitiveFailed }
53         isPositive { ^this >= 0 }
54         isNegative { ^this < 0 }
55         isStrictlyPositive { ^this > 0 }
56         isNaN { ^(this >= 0 or: { this <= 0 }).not }
57         asBoolean    { ^this > 0 }
58         booleanValue { ^this > 0 } // TODO in the long-run, deprecate for asBoolean
59         binaryValue { ^this.sign.max(0) } // TODO in the long-run, deprecate for asInteger
61         rectWindow { _RectWindow; ^this.primitiveFailed }
62         hanWindow { _HanWindow; ^this.primitiveFailed }
63         welWindow { _WelchWindow; ^this.primitiveFailed }
64         triWindow { _TriWindow; ^this.primitiveFailed }
66         scurve { _SCurve; ^this.primitiveFailed }
67         ramp { _Ramp; ^this.primitiveFailed }
69         + { arg aNumber, adverb; _Add; ^aNumber.performBinaryOpOnSimpleNumber('+', this, adverb) }
70         - { arg aNumber, adverb; _Sub; ^aNumber.performBinaryOpOnSimpleNumber('-', this, adverb) }
71         * { arg aNumber, adverb; _Mul; ^aNumber.performBinaryOpOnSimpleNumber('*', this, adverb) }
72         / { arg aNumber, adverb; _FDiv; ^aNumber.performBinaryOpOnSimpleNumber('/', this, adverb) }
73         mod { arg aNumber, adverb; _Mod; ^aNumber.performBinaryOpOnSimpleNumber('mod', this, adverb) }
74         div { arg aNumber, adverb; _IDiv; ^aNumber.performBinaryOpOnSimpleNumber('div', this, adverb) }
75         pow { arg aNumber, adverb; _Pow; ^aNumber.performBinaryOpOnSimpleNumber('pow', this, adverb) }
76         min { arg aNumber, adverb; _Min; ^aNumber.performBinaryOpOnSimpleNumber('min', this, adverb) }
77         max { arg aNumber=0.0, adverb; _Max; ^aNumber.performBinaryOpOnSimpleNumber('max', this, adverb) }
78         bitAnd { arg aNumber, adverb; _BitAnd; ^aNumber.performBinaryOpOnSimpleNumber('bitAnd', this, adverb) }
79         bitOr { arg aNumber, adverb; _BitOr; ^aNumber.performBinaryOpOnSimpleNumber('bitOr', this, adverb) }
80         bitXor { arg aNumber, adverb; _BitXor; ^aNumber.performBinaryOpOnSimpleNumber('bitXor', this, adverb) }
81         bitHammingDistance { arg aNumber, adverb; _HammingDistance  ^aNumber.performBinaryOpOnSimpleNumber('hammingDistance', this, adverb) }
82         bitTest { arg bit; ^( (this & 1.leftShift(bit)) != 0) }
83         lcm { arg aNumber, adverb; _LCM; ^aNumber.performBinaryOpOnSimpleNumber('lcm', this, adverb) }
84         gcd { arg aNumber, adverb; _GCD; ^aNumber.performBinaryOpOnSimpleNumber('gcd', this, adverb) }
85         round { arg aNumber=1.0, adverb; _Round; ^aNumber.performBinaryOpOnSimpleNumber('round', this, adverb) }
86         roundUp { arg aNumber=1.0, adverb; _RoundUp; ^aNumber.performBinaryOpOnSimpleNumber('roundUp', this, adverb) }
87         trunc { arg aNumber=1.0, adverb; _Trunc; ^aNumber.performBinaryOpOnSimpleNumber('trunc', this, adverb) }
88         atan2 { arg aNumber, adverb; _Atan2; ^aNumber.performBinaryOpOnSimpleNumber('atan2', this, adverb) }
89         hypot { arg aNumber, adverb; _Hypot; ^aNumber.performBinaryOpOnSimpleNumber('hypot', this, adverb) }
90         hypotApx { arg aNumber, adverb; _HypotApx; ^aNumber.performBinaryOpOnSimpleNumber('hypotApx', this, adverb) }
91         leftShift { arg aNumber=1, adverb; _ShiftLeft; ^aNumber.performBinaryOpOnSimpleNumber('leftShift', this, adverb) }
92         rightShift { arg aNumber=1, adverb; _ShiftRight; ^aNumber.performBinaryOpOnSimpleNumber('rightShift', this, adverb) }
93         unsignedRightShift { arg aNumber, adverb; _UnsignedShift; ^aNumber.performBinaryOpOnSimpleNumber('unsignedRightShift', this, adverb) }
94         ring1 { arg aNumber, adverb; _Ring1; ^aNumber.performBinaryOpOnSimpleNumber('ring1', this, adverb) }
95         ring2 { arg aNumber, adverb; _Ring2; ^aNumber.performBinaryOpOnSimpleNumber('ring2', this, adverb) }
96         ring3 { arg aNumber, adverb; _Ring3; ^aNumber.performBinaryOpOnSimpleNumber('ring3', this, adverb) }
97         ring4 { arg aNumber, adverb; _Ring4; ^aNumber.performBinaryOpOnSimpleNumber('ring4', this, adverb) }
98         difsqr { arg aNumber, adverb; _DifSqr; ^aNumber.performBinaryOpOnSimpleNumber('difsqr', this, adverb) }
99         sumsqr { arg aNumber, adverb; _SumSqr; ^aNumber.performBinaryOpOnSimpleNumber('sumsqr', this, adverb) }
100         sqrsum { arg aNumber, adverb; _SqrSum; ^aNumber.performBinaryOpOnSimpleNumber('sqrsum', this, adverb) }
101         sqrdif { arg aNumber, adverb; _SqrDif; ^aNumber.performBinaryOpOnSimpleNumber('sqrdif', this, adverb) }
102         absdif { arg aNumber, adverb; _AbsDif; ^aNumber.performBinaryOpOnSimpleNumber('absdif', this, adverb) }
103         thresh { arg aNumber, adverb; _Thresh; ^aNumber.performBinaryOpOnSimpleNumber('thresh', this, adverb) }
104         amclip { arg aNumber, adverb; _AMClip; ^aNumber.performBinaryOpOnSimpleNumber('amclip', this, adverb) }
105         scaleneg { arg aNumber, adverb; _ScaleNeg; ^aNumber.performBinaryOpOnSimpleNumber('scaleneg', this, adverb) }
106         clip2 { arg aNumber, adverb; _Clip2; ^aNumber.performBinaryOpOnSimpleNumber('clip2', this, adverb) }
107         fold2 { arg aNumber, adverb; _Fold2; ^aNumber.performBinaryOpOnSimpleNumber('fold2', this, adverb) }
108         wrap2 { arg aNumber, adverb; _Wrap2; ^aNumber.performBinaryOpOnSimpleNumber('wrap2', this, adverb) }
110         excess { arg aNumber, adverb; _Excess; ^aNumber.performBinaryOpOnSimpleNumber('excess', this, adverb) }
111         firstArg { arg aNumber, adverb; _FirstArg; ^aNumber.performBinaryOpOnSimpleNumber('firstArg', this, adverb) }
112         rrand { arg aNumber, adverb; _RandRange; ^aNumber.performBinaryOpOnSimpleNumber('rrand', this, adverb) }
113         exprand { arg aNumber, adverb; _ExpRandRange; ^aNumber.performBinaryOpOnSimpleNumber('exprand', this, adverb) }
115         == { arg aNumber, adverb; _EQ; ^aNumber.perform('==', this, adverb) }
116         != { arg aNumber, adverb; _NE; ^aNumber.perform('!=', this, adverb) }
117         < { arg aNumber, adverb; _LT; ^aNumber.performBinaryOpOnSimpleNumber('<', this, adverb) }
118         > { arg aNumber, adverb; _GT; ^aNumber.performBinaryOpOnSimpleNumber('>', this, adverb) }
119         <= { arg aNumber, adverb; _LE; ^aNumber.performBinaryOpOnSimpleNumber('<=', this, adverb) }
120         >= { arg aNumber, adverb; _GE; ^aNumber.performBinaryOpOnSimpleNumber('>=', this, adverb) }
122         equalWithPrecision { arg that, precision=0.0001;
123                 ^absdif(this, that) < precision
124         }
126         hash { _ObjectHash; ^this.primitiveFailed }
128         asInteger { _AsInt; ^this.primitiveFailed }
129         asFloat { _AsFloat; ^this.primitiveFailed }
130         asComplex { ^Complex.new(this, 0.0) }
131         asRect { ^Rect(this, this, this, this) }
133         degrad { ^this*pi/180 }
134         raddeg { ^this*180/pi }
136         fontID { ^this }
138         performBinaryOpOnSimpleNumber { arg aSelector, aNumber; ^error("Math operation failed.\n") }
139         performBinaryOpOnComplex { arg aSelector, aComplex, adverb; ^aComplex.perform(aSelector, this.asComplex, adverb) }
140         performBinaryOpOnSignal { arg aSelector, aSignal; ^error("Math operation failed.\n") }
142         nextPowerOfTwo { ^this.nextPowerOf(2) }
143         nextPowerOf { arg base; ^pow(base, ceil(log(this) / log(base))) }
144         nextPowerOfThree { ^pow(3, ceil(log(this) / log(3))) }
145         previousPowerOf { arg base; ^pow(base, ceil(log(this) / log(base)) - 1) }
147         quantize { arg quantum = 1.0, tolerance = 0.05, strength = 1.0;
148                 var round = round(this, quantum);
149                 var diff = round - this;
150                 if (abs(diff) < tolerance) {
151                         ^this + (strength * diff)
152                 }{
153                         ^this
154                 }
155         }
158         linlin { arg inMin, inMax, outMin, outMax, clip=\minmax;
159                 // linear to linear mapping
160                 switch(clip,
161                         \minmax, {
162                                 if (this <= inMin, { ^outMin });
163                                 if (this >= inMax, { ^outMax });
164                         },
165                         \min, {
166                                 if (this <= inMin, { ^outMin });
167                         },
168                         \max, {
169                                 if (this >= inMax, { ^outMax });
170                         }
171                 );
172                 ^(this-inMin)/(inMax-inMin) * (outMax-outMin) + outMin;
173         }
175         linexp { arg inMin, inMax, outMin, outMax, clip=\minmax;
176                 // linear to exponential mapping
177                 switch(clip,
178                         \minmax, {
179                                 if (this <= inMin, { ^outMin });
180                                 if (this >= inMax, { ^outMax });
181                         },
182                         \min, {
183                                 if (this <= inMin, { ^outMin });
184                         },
185                         \max, {
186                                 if (this >= inMax, { ^outMax });
187                         }
188                 );
189                 ^pow(outMax/outMin, (this-inMin)/(inMax-inMin)) * outMin
190         }
192         explin { arg inMin, inMax, outMin, outMax, clip=\minmax;
193                 // exponential to linear mapping
194                 switch(clip,
195                         \minmax, {
196                                 if (this <= inMin, { ^outMin });
197                                 if (this >= inMax, { ^outMax });
198                         },
199                         \min, {
200                                 if (this <= inMin, { ^outMin });
201                         },
202                         \max, {
203                                 if (this >= inMax, { ^outMax });
204                         }
205                 );
206                 ^(log(this/inMin)) / (log(inMax/inMin)) * (outMax-outMin) + outMin;
207         }
209         expexp { arg inMin, inMax, outMin, outMax, clip=\minmax;
210                 // exponential to exponential mapping
211                 switch(clip,
212                         \minmax, {
213                                 if (this <= inMin, { ^outMin });
214                                 if (this >= inMax, { ^outMax });
215                         },
216                         \min, {
217                                 if (this <= inMin, { ^outMin });
218                         },
219                         \max, {
220                                 if (this >= inMax, { ^outMax });
221                         }
222                 );
223                 ^pow(outMax/outMin, log(this/inMin) / log(inMax/inMin)) * outMin;
224         }
226         lincurve { arg inMin = 0, inMax = 1, outMin = 0, outMax = 1, curve = -4, clip = \minmax;
227                 var grow, a, b, scaled;
228                 switch(clip,
229                         \minmax, {
230                                 if (this <= inMin, { ^outMin });
231                                 if (this >= inMax, { ^outMax });
232                         },
233                         \min, {
234                                 if (this <= inMin, { ^outMin });
235                         },
236                         \max, {
237                                 if (this >= inMax, { ^outMax });
238                         }
239                 );
240                 if (abs(curve) < 0.001) { ^this.linlin(inMin, inMax, outMin, outMax) };
242                 grow = exp(curve);
243                 a = outMax - outMin / (1.0 - grow);
244                 b = outMin + a;
245                 scaled = (this - inMin) / (inMax - inMin);
247                 ^b - (a * pow(grow, scaled));
248         }
250         curvelin { arg inMin = 0, inMax = 1, outMin = 0, outMax = 1, curve = -4, clip = \minmax;
251                 var grow, a, b, scaled;
252                 switch(clip,
253                         \minmax, {
254                                 if (this <= inMin, { ^outMin });
255                                 if (this >= inMax, { ^outMax });
256                         },
257                         \min, {
258                                 if (this <= inMin, { ^outMin });
259                         },
260                         \max, {
261                                 if (this >= inMax, { ^outMax });
262                         }
263                 );
264                 if (abs(curve) < 0.001) { ^this.linlin(inMin, inMax, outMin, outMax) };
266                 grow = exp(curve);
267                 a = outMax - outMin / (1.0 - grow);
268                 b = outMin + a;
269                 scaled = (this - inMin) / (inMax - inMin);
271                 ^log((b - scaled) / a) / curve
272         }
274         bilin { arg inCenter, inMin, inMax, outCenter, outMin, outMax, clip=\minmax;
275                 // triangular linear mapping
276                 switch(clip,
277                         \minmax, {
278                                 if (this <= inMin, { ^outMin });
279                                 if (this >= inMax, { ^outMax });
280                         },
281                         \min, {
282                                 if (this <= inMin, { ^outMin });
283                         },
284                         \max, {
285                                 if (this >= inMax, { ^outMax });
286                         }
287                 );
288                 ^if (this >= inCenter) {
289                         this.linlin(inCenter, inMax, outCenter, outMax, \none);
290                 } {
291                         this.linlin(inMin, inCenter, outMin, outCenter, \none);
292                 }
293         }
295         biexp { arg inCenter, inMin, inMax, outCenter, outMin, outMax, clip=\minmax;
296                 // triangular exponential mapping
297                 switch(clip,
298                         \minmax, {
299                                 if (this <= inMin, { ^outMin });
300                                 if (this >= inMax, { ^outMax });
301                         },
302                         \min, {
303                                 if (this <= inMin, { ^outMin });
304                         },
305                         \max, {
306                                 if (this >= inMax, { ^outMax });
307                         }
308                 );
309                 if (this >= inCenter) {
310                         this.explin(inCenter, inMax, outCenter, outMax, \none);
311                 } {
312                         this.explin(inMin, inCenter, outMin, outCenter, \none);
313                 }
314         }
315         lcurve { arg a = 1.0, m = 0.0, n = 1.0, tau = 1.0;
316                 var rTau, x = this.neg;
317                 ^if(tau == 1.0) {
318                         a * (m * exp(x) + 1) / (n * exp(x) + 1)
319                 } {
320                         rTau = tau.reciprocal;
321                         a * (m * exp(x) * rTau + 1) / (n * exp(x) * rTau + 1)
322                 }
323         }
324         gauss { arg standardDeviation;
325                 ^((((-2*log(1.0.rand)).sqrt * sin(2pi.rand)) * standardDeviation) + this)
326         }
327         gaussCurve { arg a = 1.0, b = 0.0, c = 1.0;
328                 ^a * (exp(squared(this - b) / (-2.0 * squared(c))))
329         }
331         asPoint { ^Point.new(this, this) }
333         asWarp { arg spec; ^CurveWarp.new(spec, this) }
335         // scheduled Routine support
336         wait { ^this.yield }
337         waitUntil { ^(this - thisThread.beats).max(0).yield }
338         sleep {
339                 var thread = thisThread;
340                 thread.clock.sched(this, { thread.next; nil });
341                 nil.yield;
342         }
344         printOn { arg stream;
345                 stream.putAll(this.asString);
346         }
347         storeOn { arg stream;
348                 stream.putAll(this.asString);
349         }
352         rate { ^'scalar' } // scalarRate constant
353         asAudioRateInput { ^if(this == 0) { Silent.ar } { DC.ar(this) } }
355         // support for writing synth defs
356         writeInputSpec { arg file, synth;
357                 var constIndex = synth.constants.at(this.asFloat);
358                 if (constIndex.isNil) {
359                         Error("SimpleNumber-writeInputSpec constant not found: " ++ this.asFloat).throw;                };
360                 //[\inpspc, this.class.name, constIndex, this].postln;
361                 file.putInt16(-1);
362                 file.putInt16(constIndex);
363         }
365         series { arg second, last;
366                 _SimpleNumberSeries
367                 ^this.primitiveFailed
368                 /* var step, size;
369                 second = second ?? { if (this < last) { this + 1 } { this - 1 } };
370                 step = second - this;
371                 size = floor((last - this) / step + 0.001).asInteger + 1;
372                 ^Array.series(size, this, step) */
373         }
374         seriesIter { arg second, last;
375                 var step, size;
376                 if (second.isNil) {
377                         last = last ? inf;
378                         step = if (this < last, 1, -1);
379                 }{
380                         last ?? { last = if (second < this, -inf, inf) };
381                         step = second - this;
382                 };
383                 ^if (step < 0) {
384                         r {
385                                 var val = this;
386                                 while {
387                                         val >= last;
388                                 }{
389                                         val.yield;
390                                         val = val + step;
391                                 };
392                         }
393                 }{
394                         r {
395                                 var val = this;
396                                 while {
397                                         val <= last;
398                                 }{
399                                         val.yield;
400                                         val = val + step;
401                                 };
402                         }
403                 }
404         }
407         degreeToKey { arg scale, stepsPerOctave = 12;
408                 var scaleDegree = this.round.asInteger;
409                 var accidental = (this - scaleDegree) * 10.0;
410                 ^scale.performDegreeToKey(scaleDegree, stepsPerOctave, accidental)
411         }
413         keyToDegree { arg scale, stepsPerOctave=12;
414                 var n = this div: stepsPerOctave * scale.size;
415                 var key = this % stepsPerOctave;
416                 ^scale.indexInBetween(key) + n
417         }
419         nearestInList { arg list;  // collection is sorted
420                 ^list.performNearestInList(this);
421         }
423         nearestInScale { arg scale, stepsPerOctave=12; // collection is sorted
424                 ^scale.performNearestInScale(this, stepsPerOctave);
425         }
427         partition { arg parts=2, min=1;
428                 // randomly partition a number into parts of at least min size :
429                 var n = this - (min - 1 * parts);
430                 ^(1..n-1).scramble.keep(parts-1).sort.add(n).differentiate + (min - 1)
431         }
433         nextTimeOnGrid { arg clock;
434                 ^clock.nextTimeOnGrid(this, 0);
435         }
437         playAndDelta {}
439         asQuant { ^Quant(this) }
441         // a clock format inspired by ISO 8601 time interval display (truncated representation)
442         // receiver is a time in seconds, returns string "ddd:hh:mm:ss:ttt" where t is milliseconds
443         // see String:asSecs for complement
445         asTimeString { arg precision = 0.001, maxDays = 365, dropDaysIfPossible = true;
446                 var decimal, days, hours, minutes, seconds, mseconds;
447                 decimal = this.asInteger;
448                 days = decimal.div(86400).min(maxDays);
449                 days = if(dropDaysIfPossible and: { days == 0 }) {
450                         days = ""
451                 } {
452                         days.asString.padLeft(3, "0").add($:);
453                 };
454                 hours = (decimal.div(3600) % 24).asString.padLeft(2, "0").add($:);
455                 minutes = (decimal.div(60) % 60).asString.padLeft(2, "0").add($:);
456                 seconds = (decimal % 60).asString.padLeft(2, "0").add($:);
457                 mseconds = (this.frac / precision).round(precision).asInteger.asString.padLeft(3, "0");
458                 ^days ++ hours ++ minutes ++ seconds ++ mseconds
459         }
461         asFraction {|denominator=100, fasterBetter=true|
462                 _AsFraction
463                 // asFraction will return a fraction that is the best approximation up to the given
464                 // denominator.
465                 // if fasterBetter is true it may find a much closer approximation and do it faster.
466                 ^this.primitiveFailed
467         }
468         prSimpleNumberSeries { arg second, last;
469                 _SimpleNumberSeries
470                 ^this.primitiveFailed
471         }
473         asBufWithValues {
474                 ^this
475         }
477         schedBundleArrayOnClock { |clock, bundleArray, lag = 0, server, latency|
478                 clock.sched(this, {
479                                         if (lag != 0) {
480                                                 SystemClock.sched(lag, {
481                                                         server.sendBundle(latency ? server.latency, *bundleArray)
482                                                 })
483                                         } {
484                                                 server.sendBundle(latency ? server.latency, *bundleArray)
485                                         }
486                 })
487         }