1SimpleNumber : Number {
2
3	*new { ^this.shouldNotImplement(thisMethod) }
4
5	isValidUGenInput { ^this.isNaN.not }
6	numChannels { ^1 }
7
8	magnitude { ^this.abs }
9	angle { ^if(this >= 0) { 0.0 } { pi } }
10
11
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 }
49
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
60
61	rectWindow { _RectWindow; ^this.primitiveFailed }
62	hanWindow { _HanWindow; ^this.primitiveFailed }
63	welWindow { _WelchWindow; ^this.primitiveFailed }
64	triWindow { _TriWindow; ^this.primitiveFailed }
65
66	scurve { _SCurve; ^this.primitiveFailed }
67	ramp { _Ramp; ^this.primitiveFailed }
68
69	+ { |aNumber, adverb| _Add; ^aNumber.performBinaryOpOnSimpleNumber('+', this, adverb) }
70	- { |aNumber, adverb| _Sub; ^aNumber.performBinaryOpOnSimpleNumber('-', this, adverb) }
71	* { |aNumber, adverb| _Mul; ^aNumber.performBinaryOpOnSimpleNumber('*', this, adverb) }
72	/ { |aNumber, adverb| _FDiv; ^aNumber.performBinaryOpOnSimpleNumber('/', this, adverb) }
73	mod { |aNumber, adverb| _Mod; ^aNumber.performBinaryOpOnSimpleNumber('mod', this, adverb) }
74	div { |aNumber, adverb| _IDiv; ^aNumber.performBinaryOpOnSimpleNumber('div', this, adverb) }
75	pow { |aNumber, adverb| _Pow; ^aNumber.performBinaryOpOnSimpleNumber('pow', this, adverb) }
76	min { |aNumber, adverb| _Min; ^aNumber.performBinaryOpOnSimpleNumber('min', this, adverb) }
77	max { |aNumber=0.0, adverb| _Max; ^aNumber.performBinaryOpOnSimpleNumber('max', this, adverb) }
78	bitAnd { |aNumber, adverb| _BitAnd; ^aNumber.performBinaryOpOnSimpleNumber('bitAnd', this, adverb) }
79	bitOr { |aNumber, adverb| _BitOr; ^aNumber.performBinaryOpOnSimpleNumber('bitOr', this, adverb) }
80	bitXor { |aNumber, adverb| _BitXor; ^aNumber.performBinaryOpOnSimpleNumber('bitXor', this, adverb) }
81	bitHammingDistance { |aNumber, adverb| _HammingDistance  ^aNumber.performBinaryOpOnSimpleNumber('hammingDistance', this, adverb) }
82	bitTest { arg bit; ^( (this.bitAnd(1.leftShift(bit))) != 0) }
83	lcm { |aNumber, adverb| _LCM; ^aNumber.performBinaryOpOnSimpleNumber('lcm', this, adverb) }
84	gcd { |aNumber, adverb| _GCD; ^aNumber.performBinaryOpOnSimpleNumber('gcd', this, adverb) }
85	round { |aNumber=1.0, adverb| _Round; ^aNumber.performBinaryOpOnSimpleNumber('round', this, adverb) }
86	roundUp { |aNumber=1.0, adverb| _RoundUp; ^aNumber.performBinaryOpOnSimpleNumber('roundUp', this, adverb) }
87	trunc { |aNumber=1.0, adverb| _Trunc; ^aNumber.performBinaryOpOnSimpleNumber('trunc', this, adverb) }
88	atan2 { |aNumber, adverb| _Atan2; ^aNumber.performBinaryOpOnSimpleNumber('atan2', this, adverb) }
89	hypot { |aNumber, adverb| _Hypot; ^aNumber.performBinaryOpOnSimpleNumber('hypot', this, adverb) }
90	hypotApx { |aNumber, adverb| _HypotApx; ^aNumber.performBinaryOpOnSimpleNumber('hypotApx', this, adverb) }
91	leftShift { |aNumber=1, adverb| _ShiftLeft; ^aNumber.performBinaryOpOnSimpleNumber('leftShift', this, adverb) }
92	rightShift { |aNumber=1, adverb| _ShiftRight; ^aNumber.performBinaryOpOnSimpleNumber('rightShift', this, adverb) }
93	unsignedRightShift { |aNumber, adverb| _UnsignedShift; ^aNumber.performBinaryOpOnSimpleNumber('unsignedRightShift', this, adverb) }
94	ring1 { |aNumber, adverb| _Ring1; ^aNumber.performBinaryOpOnSimpleNumber('ring1', this, adverb) }
95	ring2 { |aNumber, adverb| _Ring2; ^aNumber.performBinaryOpOnSimpleNumber('ring2', this, adverb) }
96	ring3 { |aNumber, adverb| _Ring3; ^aNumber.performBinaryOpOnSimpleNumber('ring3', this, adverb) }
97	ring4 { |aNumber, adverb| _Ring4; ^aNumber.performBinaryOpOnSimpleNumber('ring4', this, adverb) }
98	difsqr { |aNumber, adverb| _DifSqr; ^aNumber.performBinaryOpOnSimpleNumber('difsqr', this, adverb) }
99	sumsqr { |aNumber, adverb| _SumSqr; ^aNumber.performBinaryOpOnSimpleNumber('sumsqr', this, adverb) }
100	sqrsum { |aNumber, adverb| _SqrSum; ^aNumber.performBinaryOpOnSimpleNumber('sqrsum', this, adverb) }
101	sqrdif { |aNumber, adverb| _SqrDif; ^aNumber.performBinaryOpOnSimpleNumber('sqrdif', this, adverb) }
102	absdif { |aNumber, adverb| _AbsDif; ^aNumber.performBinaryOpOnSimpleNumber('absdif', this, adverb) }
103	thresh { |aNumber, adverb| _Thresh; ^aNumber.performBinaryOpOnSimpleNumber('thresh', this, adverb) }
104	amclip { |aNumber, adverb| _AMClip; ^aNumber.performBinaryOpOnSimpleNumber('amclip', this, adverb) }
105	scaleneg { |aNumber, adverb| _ScaleNeg; ^aNumber.performBinaryOpOnSimpleNumber('scaleneg', this, adverb) }
106	clip2 { |aNumber=1, adverb| _Clip2; ^aNumber.performBinaryOpOnSimpleNumber('clip2', this, adverb) }
107	fold2 { |aNumber=1, adverb| _Fold2; ^aNumber.performBinaryOpOnSimpleNumber('fold2', this, adverb) }
108	wrap2 { |aNumber=1, adverb| _Wrap2; ^aNumber.performBinaryOpOnSimpleNumber('wrap2', this, adverb) }
109
110	excess { |aNumber=1, adverb| _Excess; ^aNumber.performBinaryOpOnSimpleNumber('excess', this, adverb) }
111	firstArg { |aNumber, adverb| _FirstArg; ^aNumber.performBinaryOpOnSimpleNumber('firstArg', this, adverb) }
112	rrand { |aNumber, adverb| _RandRange; ^aNumber.performBinaryOpOnSimpleNumber('rrand', this, adverb) }
113	exprand { |aNumber, adverb| _ExpRandRange; ^aNumber.performBinaryOpOnSimpleNumber('exprand', this, adverb) }
114
115	== { |aNumber, adverb| _EQ; ^aNumber.perform('==', this, adverb) }
116	!= { |aNumber, adverb| _NE; ^aNumber.perform('!=', this, adverb) }
117	< { |aNumber, adverb| _LT; ^aNumber.performBinaryOpOnSimpleNumber('<', this, adverb) }
118	> { |aNumber, adverb| _GT; ^aNumber.performBinaryOpOnSimpleNumber('>', this, adverb) }
119	<= { |aNumber, adverb| _LE; ^aNumber.performBinaryOpOnSimpleNumber('<=', this, adverb) }
120	>= { |aNumber, adverb| _GE; ^aNumber.performBinaryOpOnSimpleNumber('>=', this, adverb) }
121
122	equalWithPrecision { |that, precision = 0.0001, relativePrecision = 0|
123		^if(relativePrecision > 0) {
124			absdif(this, that) < max(precision, relativePrecision * min(abs(this), abs(that)))
125		} {
126			absdif(this, that) < precision
127		}
128	}
129
130	hash { _ObjectHash; ^this.primitiveFailed }
131
132	asInteger { _AsInteger; ^this.primitiveFailed }
133	asFloat { _AsFloat; ^this.primitiveFailed }
134	asComplex { ^Complex.new(this, 0.0) }
135	asRect { ^Rect(this, this, this, this) }
136
137	degrad { ^this * pi / 180 }
138	raddeg { ^this * 180 / pi }
139
140	performBinaryOpOnSimpleNumber { |aSelector, aNumber, adverb|
141		BinaryOpFailureError(this, aSelector, [aNumber, adverb]).throw;
142	}
143	performBinaryOpOnComplex { |aSelector, aComplex, adverb| ^aComplex.perform(aSelector, this.asComplex, adverb) }
144	performBinaryOpOnSignal { |aSelector, aSignal, adverb|
145		BinaryOpFailureError(this, aSelector, [aSignal, adverb]).throw;
146	}
147
148	nextPowerOfTwo { ^this.nextPowerOf(2) }
149	nextPowerOf { |base| ^pow(base, ceil(log(this) / log(base))) }
150	nextPowerOfThree { ^pow(3, ceil(log(this) / log(3))) }
151	previousPowerOf { |base| ^pow(base, ceil(log(this) / log(base)) - 1) }
152
153
154	/*  Boost Special Functions  */
155
156	//  Number Series:
157	bernouliB2n { _BernouliB2n; ^this.primitiveFailed }
158	tangentT2n { _TangentT2n; ^this.primitiveFailed }
159
160	//  Gamma:
161	tgamma { _TGamma; ^this.primitiveFailed }
162	tgamma1pm1 { _TGamma1pm1; ^this.primitiveFailed }
163	lgamma { _LGamma; ^this.primitiveFailed }
164	digamma { _Digamma; ^this.primitiveFailed }
165	trigamma { _Trigamma; ^this.primitiveFailed }
166	polygamma { |z| _Polygamma; ^this.primitiveFailed }
167	tgammaRatio { |b| _TGammaRatio; ^this.primitiveFailed }
168	tgammaDeltaRatio { |delta| _TGammaDeltaRatio; ^this.primitiveFailed }
169	gammaP { |z| _GammaP; ^this.primitiveFailed }
170	gammaQ { |z| _GammaQ; ^this.primitiveFailed }
171	tgammaLower { |z| _TGammaLower; ^this.primitiveFailed }
172	tgammaUpper { |z| _TGammaI; ^this.primitiveFailed }
173	//  Incomplete Gamma Function Inverses
174	gammaPInv { |p| _GammaPInv; ^this.primitiveFailed }
175	gammaQInv { |q| _GammaQInv; ^this.primitiveFailed }
176	gammaPInvA { |p| _GammaPInvA; ^this.primitiveFailed }
177	gammaQInvA { |q| _GammaQInvA; ^this.primitiveFailed }
178	//  Derivatives of the Incomplete Gamma Function
179	gammaPDerivative { |x| _GammaPDerivative; ^this.primitiveFailed }
180	gammaQDerivative { |x| ^this.gammaPDerivative(x).neg }
181
182	//	Factorials and Binomial Coefficients:
183	factorial { _Factorial; ^this.primitiveFailed }
184	doubleFactorial { _DoubleFactorial; ^this.primitiveFailed }
185	risingFactorial { |i| _RisingFactorial; ^this.primitiveFailed }
186	fallingFactorial { |i| _FallingFactorial; ^this.primitiveFailed }
187	binomialCoefficient { |k| _BinomialCoefficient; ^this.primitiveFailed }
188
189	//  Beta functions:
190	beta { |b| _Beta; ^this.primitiveFailed }
191	//  Incomplete beta functions
192	ibeta { |b, x| _IBeta; ^this.primitiveFailed }
193	ibetaC { |b, x| _IBetaC; ^this.primitiveFailed }
194	betaFull { |b, x| _BetaFull; ^this.primitiveFailed }
195	betaFullC { |b, x| _BetaCFull; ^this.primitiveFailed }
196	//  Incomplete beta function inverses
197	ibetaInv { |b, p| _IBetaInv; ^this.primitiveFailed }
198	ibetaCInv { |b, q| _IBetaCInv; ^this.primitiveFailed }
199	ibetaInvA { |x, p| _IBetaInvA; ^this.primitiveFailed }
200	ibetaCInvA { |x, q| _IBetaCInvA; ^this.primitiveFailed }
201	ibetaInvB { |x, p| _IBetaInvB; ^this.primitiveFailed }
202	ibetaCInvB { |x, q| _IBetaCInvB; ^this.primitiveFailed }
203	//  Incomplete beta function derivative
204	ibetaDerivative { |b, x| _IBetaDerivative; ^this.primitiveFailed }
205
206	//  Error functions:
207	erf { _Erf; ^this.primitiveFailed }
208	erfC { _ErfC; ^this.primitiveFailed }
209	erfInv { _ErfInv; ^this.primitiveFailed }
210	erfCInv { _ErfCInv; ^this.primitiveFailed }
211
212	//  Polynomials:
213	// Legendre (and Associated), Laguerre (and Associated),
214	// Hermite, Chebyshev Polynomials (first & second kind, derivative, zero (root) finder)
215	// See boost documentation for a note about the Condon-Shortley phase term of (-1)^m
216	// "http://www.boost.org/doc/libs/1_65_1/libs/math/doc/html/math_toolkit/sf_poly/legendre.html"]
217	legendreP { |x| _LegendreP; ^this.primitiveFailed }
218	legendrePPrime { |x| _LegendrePPrime; ^this.primitiveFailed }
219	legendrePZeros { _LegendrePZeros; ^this.primitiveFailed }
220	legendrePAssoc { |m, x| _LegendrePAssoc; ^this.primitiveFailed }
221	legendreQ { |x|
222		//  Protect from l < 0. Boost won't catch this out of range value and interpreter hangs.
223		if(this < 0) {
224			format("n = %, but Legendre Polynomial of the Second Kind requires n >= 0", this).throw
225		};
226		^prLegendreQ(this, x)
227	}
228	prLegendreQ { |x| _LegendreQ; ^this.primitiveFailed }
229	laguerre { |x| _Laguerre; ^this.primitiveFailed }
230	laguerreAssoc { |m, x|
231		//  Protect from m < 0. Boost won't catch this out of range value and interpreter hangs.
232		if(this < 0) {
233			format("n = %, but Associated Laguerre Polynomial requires n >= 0", this).throw
234		};
235		^prLaguerreAssoc(this, m, x)
236	}
237	prLaguerreAssoc { |m, x| _LaguerreAssoc; ^this.primitiveFailed }
238	hermite { |x|
239		//  Protect from m < 0. Boost won't catch this out of range value and interpreter hangs.
240		if(this < 0) {
241			format("n = %, but Hermite Polynomial requires n >= 0", this).throw
242		};
243		^prHermite(this, x)
244	}
245	prHermite { |x| _Hermite; ^this.primitiveFailed }
246	chebyshevT { |x| _ChebyshevT; ^this.primitiveFailed }
247	chebyshevU { |x| _ChebyshevU; ^this.primitiveFailed }
248	chebyshevTPrime { |x| _ChebyshevTPrime; ^this.primitiveFailed }
249	//  "https://en.wikipedia.org/wiki/Chebyshev_polynomials#Roots_and_extrema"
250	//  "http://mathworld.wolfram.com/ChebyshevPolynomialoftheFirstKind.html"
251	chebyshevTZeros {
252		var n = this.asInteger;
253		^(1..n).collect { |k|
254			cos(pi * ((2 * k) - 1) / (2 * n))
255		}
256	}
257
258	//  Spherical Harmonics
259	sphericalHarmonic { |m, theta, phi| _SphericalHarmonic; ^this.primitiveFailed }
260	sphericalHarmonicR { |m, theta, phi| _SphericalHarmonicR; ^this.primitiveFailed }
261	sphericalHarmonicI { |m, theta, phi| _SphericalHarmonicI; ^this.primitiveFailed }
262
263	//	Bessel Functions:
264	//  First and second kind, zero finders, modified first and second kinds,
265	//  spherical first and second kinds, derivatives
266	cylBesselJ { |x| _CylBesselJ; ^this.primitiveFailed }
267	cylNeumann { |x| _CylNeumann; ^this.primitiveFailed }
268	cylBesselJZero { |index| _CylBesselJZero; ^this.primitiveFailed }
269	cylNeumannZero { |index| _CylNeumannZero; ^this.primitiveFailed }
270	cylBesselI { |x| _CylBesselI; ^this.primitiveFailed }
271	cylBesselK { |x| _CylBesselK; ^this.primitiveFailed }
272	sphBessel { |x| _SphBessel; ^this.primitiveFailed }
273	sphNeumann { |x| _SphNeumann; ^this.primitiveFailed }
274	cylBesselJPrime { |x| _CylBesselJPrime; ^this.primitiveFailed }
275	cylNeumannPrime { |x| _CylNeumannPrime; ^this.primitiveFailed }
276	cylBesselIPrime { |x| _CylBesselIPrime; ^this.primitiveFailed }
277	cylBesselKPrime { |x| _CylBesselKPrime; ^this.primitiveFailed }
278	sphBesselPrime { |x| _SphBesselPrime; ^this.primitiveFailed }
279	sphNeumannPrime { |x| _SphNeumannPrime; ^this.primitiveFailed }
280
281	//  Hankel Functions:
282	cylHankel1 { |x| _CylHankel1; ^this.primitiveFailed }
283	cylHankel2 { |x| _CylHankel2; ^this.primitiveFailed }
284	sphHankel1 { |x| _SphHankel1; ^this.primitiveFailed }
285	sphHankel2 { |x| _SphHankel2; ^this.primitiveFailed }
286
287	//  Airy Functions:
288	airyAi { _AiryAi; ^this.primitiveFailed }
289	airyBi { _AiryBi; ^this.primitiveFailed }
290	airyAiPrime { _AiryAiPrime; ^this.primitiveFailed }
291	airyBiPrime { _AiryBiPrime; ^this.primitiveFailed }
292	airyAiZero { _AiryAiZero; ^this.primitiveFailed }
293	airyBiZero { _AiryBiZero; ^this.primitiveFailed }
294
295	//  Elliptic Integrals:
296	//  Carlson Form
297	ellintRf { |y, z| _EllintRf; ^this.primitiveFailed }
298	ellintRd { |y, z| _EllintRd; ^this.primitiveFailed }
299	ellintRj { |y, z, p| _EllintRj; ^this.primitiveFailed }
300	ellintRc { |y| _EllintRc; ^this.primitiveFailed }
301	ellintRg { |y, z| _EllintRg; ^this.primitiveFailed }
302	//  Legendre Form - First, Second, Third Kind, D
303	ellint1 { |phi| _Ellint1; ^this.primitiveFailed }
304	ellint1C { _Ellint1C; ^this.primitiveFailed }
305	ellint2 { |phi| _Ellint2; ^this.primitiveFailed }
306	ellint2C { _Ellint2C; ^this.primitiveFailed }
307	ellint3 { |n, phi| _Ellint3; ^this.primitiveFailed	}
308	ellint3C { |n| _Ellint3C; ^this.primitiveFailed }
309	ellintD { |phi| _EllintD; ^this.primitiveFailed }
310	ellintDC { _EllintDC; ^this.primitiveFailed }
311	//  Jacobi Zeta, Heuman Lambda Functions
312	jacobiZeta { |phi| _JacobiZeta; ^this.primitiveFailed }
313	heumanLambda { |phi| _HeumanLambda; ^this.primitiveFailed }
314
315	//  Jacobi Elliptic Functions:
316	jacobiCd { |u| _JacobiCd; ^this.primitiveFailed }
317	jacobiCn { |u| _JacobiCn; ^this.primitiveFailed }
318	jacobiCs { |u| _JacobiCs; ^this.primitiveFailed }
319	jacobiDc { |u| _JacobiDc; ^this.primitiveFailed }
320	jacobiDn { |u| _JacobiDn; ^this.primitiveFailed }
321	jacobiDs { |u| _JacobiDs; ^this.primitiveFailed }
322	jacobiNc { |u| _JacobiNc; ^this.primitiveFailed }
323	jacobiNd { |u| _JacobiNd; ^this.primitiveFailed }
324	jacobiNs { |u| _JacobiNs; ^this.primitiveFailed }
325	jacobiSc { |u| _JacobiSc; ^this.primitiveFailed }
326	jacobiSd { |u| _JacobiSd; ^this.primitiveFailed }
327	jacobiSn { |u| _JacobiSn; ^this.primitiveFailed }
328
329	//  Riemann Zeta Function:
330	zeta { _Zeta; ^this.primitiveFailed }
331
332	//  Exponential Integrals:
333	expintEn { |z| _ExpintEn; ^this.primitiveFailed }
334	expintEi { _ExpintEi; ^this.primitiveFailed }
335
336	//  Basic Functions:
337	sinPi { _SinPi; ^this.primitiveFailed }
338	cosPi { _CosPi; ^this.primitiveFailed }
339	log1p { _Log1p; ^this.primitiveFailed }
340	expm1{ _ExpM1; ^this.primitiveFailed }
341	cbrt { _Cbrt; ^this.primitiveFailed }
342	sqrt1pm1 { _Sqrt1pm1; ^this.primitiveFailed }
343	powm1{ |y| _PowM1; ^this.primitiveFailed }
344	// hypot not needed... slightly slower than current implementation of hypot
345
346	//  Sinus Cardinal ("sinc") and Hyperbolic Sinus Cardinal Functions:
347	sincPi { _SincPi; ^this.primitiveFailed }
348	sinhcPi { _SinhcPi; ^this.primitiveFailed }
349
350	//  Inverse Hyperbolic Functions:
351	asinh { _Asinh; ^this.primitiveFailed }
352	acosh { _Acosh; ^this.primitiveFailed }
353	atanh { _Atanh; ^this.primitiveFailed }
354
355	//	Owen's T function:
356	owensT { |a| _OwensT; ^this.primitiveFailed }
357
358	/*  end Boost Special Functions  */
359
360
361	snap { |resolution = 1.0, margin = 0.05, strength = 1.0|
362		var round = round(this, resolution);
363		var diff = round - this;
364		^if(abs(diff) < margin) { this + (strength * diff) } { this }
365	}
366
367
368	softRound { |resolution = 1.0, margin = 0.05, strength = 1.0|
369		var round = round(this, resolution);
370		var diff = round - this;
371		^if(abs(diff) > margin) { this + (strength * diff) } { this }
372	}
373
374	linlin { |inMin, inMax, outMin, outMax, clip = \minmax|
375		// linear to linear mapping
376		switch(clip,
377			\minmax, {
378				if(this <= inMin) { ^outMin };
379				if(this >= inMax) { ^outMax };
380			},
381			\min, {
382				if(this <= inMin) { ^outMin };
383			},
384			\max, {
385				if(this >= inMax) { ^outMax };
386			}
387		);
388		^(this - inMin) / (inMax - inMin) * (outMax - outMin) + outMin
389	}
390
391	linexp { |inMin, inMax, outMin, outMax, clip=\minmax|
392		// linear to exponential mapping
393		switch(clip,
394			\minmax, {
395				if(this <= inMin) { ^outMin };
396				if(this >= inMax) { ^outMax };
397			},
398			\min, {
399				if(this <= inMin) { ^outMin };
400			},
401			\max, {
402				if(this >= inMax) { ^outMax };
403			}
404		);
405		^pow(outMax / outMin, (this - inMin) / (inMax - inMin)) * outMin
406	}
407
408	explin { |inMin, inMax, outMin, outMax, clip=\minmax|
409		// exponential to linear mapping
410		switch(clip,
411			\minmax, {
412				if(this <= inMin) { ^outMin };
413				if(this >= inMax) { ^outMax };
414			},
415			\min, {
416				if(this <= inMin) { ^outMin };
417			},
418			\max, {
419				if(this >= inMax) { ^outMax };
420			}
421		);
422		^(log(this / inMin)) / (log(inMax / inMin)) * (outMax - outMin) + outMin
423	}
424
425	expexp { |inMin, inMax, outMin, outMax, clip=\minmax|
426		// exponential to exponential mapping
427		switch(clip,
428			\minmax, {
429				if(this <= inMin) { ^outMin };
430				if(this >= inMax) { ^outMax };
431			},
432			\min, {
433				if(this <= inMin) { ^outMin };
434			},
435			\max, {
436				if(this >= inMax) { ^outMax };
437			}
438		);
439		^pow(outMax / outMin, log(this / inMin) / log(inMax / inMin)) * outMin
440	}
441
442	lincurve { |inMin = 0, inMax = 1, outMin = 0, outMax = 1, curve = -4, clip = \minmax|
443		var grow, a, b, scaled;
444		switch(clip,
445			\minmax, {
446				if(this <= inMin) { ^outMin };
447				if(this >= inMax) { ^outMax };
448			},
449			\min, {
450				if(this <= inMin) { ^outMin };
451			},
452			\max, {
453				if(this >= inMax) { ^outMax };
454			}
455		);
456		if(abs(curve) < 0.001) {
457			// If the value should be clipped, it has already been clipped (above).
458			// If we got this far, then linlin does not need to do any clipping.
459			// Inlining the formula here makes it even faster.
460			^(this - inMin) / (inMax - inMin) * (outMax - outMin) + outMin
461		};
462
463		grow = exp(curve);
464		a = outMax - outMin / (1.0 - grow);
465		b = outMin + a;
466		scaled = (this - inMin) / (inMax - inMin);
467
468		^b - (a * pow(grow, scaled))
469	}
470
471	curvelin { |inMin = 0, inMax = 1, outMin = 0, outMax = 1, curve = -4, clip = \minmax|
472		var grow, a, b, scaled;
473		switch(clip,
474			\minmax, {
475				if(this <= inMin) { ^outMin };
476				if(this >= inMax) { ^outMax };
477			},
478			\min, {
479				if(this <= inMin) { ^outMin };
480			},
481			\max, {
482				if(this >= inMax) { ^outMax };
483			}
484		);
485		if(abs(curve) < 0.001) {
486			// If the value should be clipped, it has already been clipped (above).
487			^(this - inMin) / (inMax - inMin) * (outMax - outMin) + outMin
488		};
489
490		grow = exp(curve);
491		a = inMax - inMin / (1.0 - grow);
492		b = inMin + a;
493
494		^log((b - this) / a) * (outMax - outMin) / curve + outMin
495	}
496
497	bilin { |inCenter, inMin, inMax, outCenter, outMin, outMax, clip=\minmax|
498		// triangular linear mapping
499		switch(clip,
500			\minmax, {
501				if(this <= inMin) { ^outMin };
502				if(this >= inMax) { ^outMax };
503			},
504			\min, {
505				if(this <= inMin) { ^outMin };
506			},
507			\max, {
508				if(this >= inMax) { ^outMax };
509			}
510		);
511		^if(this >= inCenter) {
512			this.linlin(inCenter, inMax, outCenter, outMax, \none)
513		} {
514			this.linlin(inMin, inCenter, outMin, outCenter, \none)
515		}
516	}
517
518	biexp { |inCenter, inMin, inMax, outCenter, outMin, outMax, clip=\minmax|
519		// triangular exponential mapping
520		switch(clip,
521			\minmax, {
522				if(this <= inMin) { ^outMin };
523				if(this >= inMax) { ^outMax };
524			},
525			\min, {
526				if(this <= inMin) { ^outMin };
527			},
528			\max, {
529				if(this >= inMax) { ^outMax };
530			}
531		);
532		^if(this >= inCenter) {
533			this.explin(inCenter, inMax, outCenter, outMax, \none)
534		} {
535			this.explin(inMin, inCenter, outMin, outCenter, \none)
536		}
537	}
538
539	moddif { |aNumber = 0.0, mod = 1.0|
540		var diff = absdif(this, aNumber) % mod;
541		var modhalf = mod * 0.5;
542		^modhalf - absdif(diff, modhalf)
543	}
544
545	lcurve { |a = 1.0, m = 0.0, n = 1.0, tau = 1.0|
546		var rTau, x = this.neg;
547		^if(tau == 1.0) {
548			a * (m * exp(x) + 1) / (n * exp(x) + 1)
549		} {
550			rTau = tau.reciprocal;
551			a * (m * exp(x) * rTau + 1) / (n * exp(x) * rTau + 1)
552		}
553	}
554	gauss { |standardDeviation|
555		^(((sqrt(-2 * log(1.0.rand)) * sin(2pi.rand)) * standardDeviation) + this)
556	}
557	gaussCurve { |a = 1.0, b = 0.0, c = 1.0|
558		^a * (exp(squared(this - b) / (-2.0 * squared(c))))
559	}
560
561	asPoint {
562		^Point.new(this, this)
563	}
564
565	asWarp { |spec|
566		^CurveWarp.new(spec, this)
567	}
568
569	// scheduled Routine support
570	wait { ^this.yield }
571	waitUntil { ^(this - thisThread.beats).max(0).yield }
572	sleep {
573		var thread = thisThread;
574		thread.clock.sched(this, { thread.next; nil });
575		nil.yield;
576	}
577
578	printOn { |stream|
579		stream.putAll(this.asString);
580	}
581	storeOn { |stream|
582		stream.putAll(this.asString);
583	}
584
585
586	rate { ^'scalar' } // scalarRate constant
587	asAudioRateInput { ^if(this == 0) { Silent.ar } { DC.ar(this) } }
588
589	madd  { |mul, add|
590		^(this * mul) + add
591	}
592
593	lag    { ^this }
594	lag2   { ^this }
595	lag3   { ^this }
596	lagud  { ^this }
597	lag2ud { ^this }
598	lag3ud { ^this }
599	varlag { ^this }
600	slew   { ^this }
601
602	poll { |trig = 10, label, trigid = -1|
603		^Poll(trig, this, label, trigid)
604	}
605
606	// support for writing synth defs
607	writeInputSpec { |file, synth|
608		var constIndex = synth.constants.at(this.asFloat);
609		if(constIndex.isNil) {
610			Error("SimpleNumber-writeInputSpec constant not found: " ++ this.asFloat).throw;
611		};
612		file.putInt32(-1);
613		file.putInt32(constIndex);
614	}
615
616	series { |second, last|
617		_SimpleNumberSeries
618		^this.primitiveFailed
619		/* var step, size;
620		second = second ?? { if(this < last) { this + 1 } { this - 1 } };
621		step = second - this;
622		size = floor((last - this) / step + 0.001).asInteger + 1;
623		^Array.series(size, this, step) */
624	}
625
626	seriesIter { |second, last|
627		var step, size;
628
629		if(second.isNil) {
630			last = last ? inf;
631			step = if(this < last, 1, -1);
632		}{
633			last ?? { last = if(second < this, -inf, inf) };
634			step = second - this;
635		};
636
637		^if(step < 0) {
638			r {
639				var val = this;
640				while {
641					val >= last;
642				} {
643					val.yield;
644					val = val + step;
645				};
646			}
647		} {
648			r {
649				var val = this;
650				while {
651					val <= last;
652				} {
653					val.yield;
654					val = val + step;
655				}
656			}
657		}
658	}
659
660
661	degreeToKey { |scale, stepsPerOctave = 12|
662		var scaleDegree = this.round.asInteger;
663		var accidental = (this - scaleDegree) * 10.0;
664		^scale.performDegreeToKey(scaleDegree, stepsPerOctave, accidental)
665	}
666
667	keyToDegree { |scale, stepsPerOctave = 12|
668		^scale.performKeyToDegree(this, stepsPerOctave)
669	}
670
671	nearestInList { |list|  // collection is sorted
672		^list.performNearestInList(this);
673	}
674
675	nearestInScale { |scale, stepsPerOctave = 12| // collection is sorted
676		^scale.performNearestInScale(this, stepsPerOctave);
677	}
678
679	partition { |parts = 2, min = 1|
680		// randomly partition a number into parts of at least min size :
681		var n = this - (min - 1 * parts);
682		^(1..n-1).scramble.keep(parts-1).sort.add(n).differentiate + (min - 1)
683	}
684
685	nextTimeOnGrid { |clock|
686		^clock.nextTimeOnGrid(this, 0)
687	}
688
689	playAndDelta {}
690
691	asQuant { ^Quant(this) }
692
693	// a clock format inspired by ISO 8601 time interval display (truncated representation)
694	// receiver is a time in seconds, returns string "ddd:hh:mm:ss.sss"
695	// see String:asSecs for complement
696
697	asTimeString { |precision = 0.001, maxDays = 365, dropDaysIfPossible = true|
698		var number, decimal, days, hours, minutes, seconds, mseconds;
699
700		// min value of precision is 0.001; this ensures that we stick to 3 decimal places in the
701		// formatted string.
702		precision = max(precision, 0.001);
703
704		number = this.round(precision);
705		decimal = number.asInteger;
706		days = decimal.div(86400).min(maxDays);
707		days = if(dropDaysIfPossible and: { days == 0 }) {
708			days = ""
709		} {
710			days.asString.padLeft(3, "0").add($:);
711		};
712		hours = (decimal.div(3600) % 24).asString.padLeft(2, "0").add($:);
713		minutes = (decimal.div(60) % 60).asString.padLeft(2, "0").add($:);
714		seconds = (decimal % 60).asString.padLeft(2, "0").add($.);
715		mseconds = number.frac * 1000;
716		mseconds = mseconds.round.asInteger.asString.padLeft(3, "0");
717		^days ++ hours ++ minutes ++ seconds ++ mseconds
718	}
719
720	asFraction { |denominator = 100, fasterBetter = true|
721		_AsFraction
722		// asFraction will return a fraction that is the best approximation up to the given
723		// denominator.
724		// if fasterBetter is true it may find a much closer approximation and do it faster.
725		^this.primitiveFailed
726	}
727
728	prSimpleNumberSeries { | second, last |
729		_SimpleNumberSeries
730		^this.primitiveFailed
731	}
732
733	asBufWithValues {
734		^this
735	}
736
737	// this method could be refactored by dispatching, but we're trying to keep the overhead low.
738
739	schedBundleArrayOnClock { |clock, bundleArray, lag = 0, server, latency|
740		var sendBundle = { server.sendBundle(latency ? server.latency, *bundleArray) };
741		// "this" is the delta time for the clock (usually in beats)
742		// "lag" is a tempo independent absolute lag time (in seconds)
743		if (lag != 0) {
744			if(this != 0) {
745				// schedule on both clocks
746				clock.sched(this, { SystemClock.sched(lag, sendBundle) })
747			} {
748				// only lag specified: schedule only on the system clock
749				SystemClock.sched(lag, sendBundle)
750			}
751		} {
752			if(this != 0) {
753				// only delta specified: schedule only on the clock passed in
754				clock.sched(this, sendBundle)
755			} {
756				// no delays: send directly
757				sendBundle.value
758			}
759		}
760
761	}
762}
763