maths.lib
Maths library. Its official prefix is ma.
This library provides mathematical functions and utilities for numerical computations in Faust. It includes trigonometric, exponential, logarithmic, and statistical functions, constants, and complex-number operations used throughout Faust DSP and control code.
The Maths library is organized into 1 section:
Some functions are implemented as Faust foreign functions of math.h functions
that are not part of Faust's primitives. Defines also various constants and several
utilities.
References
Functions Reference
(ma.)SR
Current sampling rate given at init time, between 50 and 192000 Hz
(see pl.SR). Constant during program execution.
Usage
SR : _
Where:
SR: initialization-time sampling rate constant
Test
ma = library("maths.lib");
SR_test = ma.SR;
(ma.)T
Current sample duration in seconds computed from the sampling rate given at init time. Constant during program execution.
Usage
T : _
Where:
T: sample duration (1/SR) constant
Test
ma = library("maths.lib");
T_test = ma.T;
(ma.)BS
Current block-size. Can change during the execution at each block.
Usage
BS : _
Where:
BS: current processing block size
Test
ma = library("maths.lib");
BS_test = ma.BS;
(ma.)PI
Constant PI in double precision.
Usage
PI : _
Where:
PI: double-precision π constant
Test
ma = library("maths.lib");
PI_test = ma.PI;
(ma.)deg2rad
Convert degrees to radians.
Usage
deg2rad(x) : _
Where:
x: angle in degrees to convert
Test
ma = library("maths.lib");
deg2rad_test = 45.0 : ma.deg2rad;
(ma.)rad2deg
Convert radians to degrees.
Usage
rad2deg(x) : _
Where:
x: angle in radians to convert
Test
ma = library("maths.lib");
rad2deg_test = ma.PI : ma.rad2deg;
(ma.)E
Constant e in double precision.
Usage
E : _
Where:
E: double-precision Euler's number constant
Test
ma = library("maths.lib");
E_test = ma.E;
(ma.)EPSILON
Constant EPSILON available in simple/double/quad precision,
as defined in the floating-point standard
and machine epsilon,
that is smallest positive number such that 1.0 + EPSILON != 1.0.
Usage
EPSILON : _
Where:
EPSILON: machine epsilon constant for the current floating-point precision
Test
ma = library("maths.lib");
EPSILON_test = ma.EPSILON;
(ma.)MIN
Constant MIN available in simple/double/quad precision (minimal positive value).
Usage
MIN : _
Where:
MIN: minimal positive normalized value for the current precision
Test
ma = library("maths.lib");
MIN_test = ma.MIN * 1e307;
(ma.)MAX
Constant MAX available in simple/double/quad precision (maximal positive value).
Usage
MAX : _
Where:
MAX: maximal finite value for the current precision
Test
ma = library("maths.lib");
MAX_test = ma.MAX;
(ma.)INFINITY
Obsolete alias of MAX, kept for compatibility reasons. Despite its name it
is not an IEEE infinity but the maximal finite value for the current precision.
Usage
INFINITY : _
Test
ma = library("maths.lib");
INFINITY_test = ma.INFINITY == ma.MAX; // 1: ma.INFINITY is ma.MAX, in both precisions
(ma.)FTZ
Flush to zero: force samples under the "maximum subnormal number" to be zero. Usually not needed in C++ because the architecture file take care of this, but can be useful in JavaScript for instance.
Usage
FTZ(x) : _
Where:
x: input signal to flush if its magnitude is subnormal
Test
ma = library("maths.lib");
FTZ_test = ((ma.MIN * 0.5) : ma.FTZ), ((ma.MIN * 1e307) : ma.FTZ);
References
(ma.)copysign
Changes the sign of x (first input) to that of y (second input).
Usage
copysign(x,y) : _
Where:
x: value whose magnitude is preservedy: value providing the sign
Test
ma = library("maths.lib");
copysign_test = (-1.0, 2.0) : ma.copysign;
(ma.)neg
Invert the sign (-x) of a signal.
Usage
neg(x) : _
Where:
x: value to negate
Test
ma = library("maths.lib");
neg_test = 3.5 : ma.neg;
(ma.)not
Bitwise not of an integer input signal, implemented with xor as not(x) = x xor -1;.
So working regardless of the size of the integer, assuming negative numbers in two's complement.
Usage
not(x) : _
Where:
x: integer input value
Test
ma = library("maths.lib");
not_test = 5 : ma.not;
(ma.)sub
Subtracts the first input x from the second input y: the output is y - x.
Usage
sub(x,y) : _
Where:
x: first operandy: second operand
Test
ma = library("maths.lib");
sub_test = (3, 10) : ma.sub;
(ma.)inv
Compute the inverse (1/x) of the input signal x (non-zero).
Usage
inv(x) : _
Where:
x: denominator input (non-zero)
Test
ma = library("maths.lib");
inv_test = 4.0 : ma.inv;
(ma.)cbrt
Computes the cube root of of the input signal.
Usage
cbrt(x) : _
Where:
x: value whose cube root is computed
Test
ma = library("maths.lib");
cbrt_test = 8.0 : ma.cbrt;
(ma.)hypot
Computes the euclidian distance of the two input signals x and y, sqrt(xx+yy), without undue overflow or underflow.
Usage
hypot(x,y) : _
Where:
x: first operandy: second operand
Test
ma = library("maths.lib");
hypot_test = (3.0, 4.0) : ma.hypot;
(ma.)ldexp
Takes two input signals: x and n (an integer), and multiplies x by 2 to the power n.
Usage
ldexp(x,n) : _
Where:
x: significand inputn: exponent (integer) input
Test
ma = library("maths.lib");
ldexp_test = (1.5, 3) : ma.ldexp;
(ma.)scalb
Takes two input signals: x and n (an integer), and multiplies x by 2 to the power n.
Usage
scalb(x,n) : _
Where:
x: significand inputn: exponent (integer) input
Test
ma = library("maths.lib");
scalb_test = (2.0, -1) : ma.scalb;
(ma.)log1p
Computes log(1 + x) of the input signal x (greater than -1) without undue
loss of accuracy when x is nearly zero, where log(1 + x) loses all its
digits in single precision.
For |x| < 0.5 it computes 2*atanh(x/(2 + x)), which is exact since
2*atanh(z) = log((1 + z)/(1 - z)) and (1 + z)/(1 - z) = 1 + x for
z = x/(2 + x): the cancellation moves into atanh, which is accurate
near 0. Elsewhere it computes log(1 + x), which is accurate there
(1 + x is exact for x in [-1, -0.5]) while the atanh form is not
(atanh is ill-conditioned near -1 and 1). Both branches are computed.
Measured maximum relative error: 1.6e-7 in single precision, 3.3e-16 in
double, against 6e-8 and 1.3e-16 for the C log1p.
Built on atanh and log rather than on the C log1p (a foreign
function), it compiles with every backend that provides atanh:
C++, C, Rust, LLVM, WebAssembly, the interpreter, Cmajor, Codebox,
Julia, C# (not Java). The slider test reads, at run time, values where a
simpler form fails: near -1, around 0 (+-2^-30), and large (1e7, 1e30).
Usage
log1p(x) : _
Where:
x: offset used inlog(1 + x)(must be greater than -1)
Test
ma = library("maths.lib");
ba = library("basics.lib");
log1p_test = 0.5 : ma.log1p;
log1p_slider_test = par(i, 7, ma.log1p(hslider("log1p:x%i", ba.take(i+1, X), -1, 1.0e30, 0.001))) with { X = (-0.9999990463256836, -0.75, -9.313225746154785e-10, 9.313225746154785e-10, 0.25, 1.0e7, 1.0e30); };
log1p_modulated_test = ma.log1p(1000.999*tri*tri*tri - 0.999) with { P = int(ma.SR/10); tri = 1 - abs(2*ba.period(P)/P - 1); };
(ma.)logb
Return exponent of the (positive) input signal as a floating-point number.
Usage
logb(x) : _
Where:
x: positive value whose exponent part is returned
Test
ma = library("maths.lib");
logb_test = 8.0 : ma.logb;
(ma.)ilogb
Return exponent of the (positive) input signal as an integer number.
Usage
ilogb(x) : _
Where:
x: positive value whose exponent part is returned
Test
ma = library("maths.lib");
ilogb_test = 8.0 : ma.ilogb;
(ma.)log2
Returns the base 2 logarithm of the positive input signal x.
Usage
log2(x) : _
Where:
x: positive value whose base-2 logarithm is computed
Test
ma = library("maths.lib");
log2_test = 8.0 : ma.log2;
(ma.)expm1
Return exponent of the input signal x minus 1, exp(x) - 1, with better
precision near 0, where exp(x) - 1 loses all its digits in single
precision.
It computes 2*exp(x/2)*sinh(x/2), which is exact since
sinh(y) = (exp(y) - exp(-y))/2: the cancellation moves into sinh,
which is accurate near 0. The input is first clamped to -80, below which
the result is -1 in every precision and the product would overflow
(exp underflows to 0 while sinh overflows). Measured maximum relative
error: 1.6e-7 in single precision, 3.2e-16 in double, against 6e-8 and
1.1e-16 for the C expm1.
Built on exp and sinh rather than on the C expm1 (a foreign
function), it compiles with every backend that provides sinh:
C++, C, Rust, LLVM, WebAssembly, the interpreter, Cmajor, Codebox,
Julia, C# (not Java). The slider test reads, at run time, values where a
simpler form fails: below the clamp (-1e5, -200) and around 0 (+-2^-30).
Usage
expm1(x) : _
Where:
x: input value used for theexp(x) - 1computation
Test
ma = library("maths.lib");
ba = library("basics.lib");
expm1_test = 0.5 : ma.expm1;
expm1_slider_test = par(i, 6, ma.expm1(hslider("expm1:x%i", ba.take(i+1, X), -1.0e5, 10, 0.001))) with { X = (-1.0e5, -200.0, -9.313225746154785e-10, 9.313225746154785e-10, 0.5, 10.0); };
expm1_modulated_test = ma.expm1(20*tri - 10) with { P = int(ma.SR/10); tri = 1 - abs(2*ba.period(P)/P - 1); };
(ma.)acosh
Computes the principle value of the inverse hyperbolic cosine of the input signal (greater than or equal to 1).
Usage
acosh(x) : _
Where:
x: input value (greater than or equal to 1)
Test
ma = library("maths.lib");
acosh_test = 1.5 : ma.acosh;
(ma.)asinh
Computes the inverse hyperbolic sine of the input signal.
Usage
asinh(x) : _
Where:
x: input value
Test
ma = library("maths.lib");
asinh_test = 0.5 : ma.asinh;
(ma.)atanh
Computes the inverse hyperbolic tangent of the input signal, in (-1, 1).
Usage
atanh(x) : _
Where:
x: input value in (-1, 1)
Test
ma = library("maths.lib");
atanh_test = 0.5 : ma.atanh;
(ma.)sinh
Computes the hyperbolic sine of the input signal.
Usage
sinh(x) : _
Where:
x: input value
Test
ma = library("maths.lib");
sinh_test = 0.5 : ma.sinh;
(ma.)cosh
Computes the hyperbolic cosine of the input signal.
Usage
cosh(x) : _
Where:
x: input value
Test
ma = library("maths.lib");
cosh_test = 0.5 : ma.cosh;
(ma.)tanh
Computes the hyperbolic tangent of the input signal.
Usage
tanh(x) : _
Where:
x: input value
Test
ma = library("maths.lib");
tanh_test = 0.5 : ma.tanh;
(ma.)erf
Computes the error function of the input signal.
Usage
erf(x) : _
Where:
x: input value
Test
ma = library("maths.lib");
erf_test = 0.5 : ma.erf;
(ma.)erfc
Computes the complementary error function of the input signal.
Usage
erfc(x) : _
Where:
x: input value
Test
ma = library("maths.lib");
erfc_test = 0.5 : ma.erfc;
(ma.)gamma
Computes the gamma function of the positive input signal.
Usage
gamma(x) : _
Where:
x: positive input value
Test
ma = library("maths.lib");
gamma_test = 3.0 : ma.gamma;
(ma.)lgamma
Calculates the natural logorithm of the absolute value of the gamma function of the positive input signal.
Usage
lgamma(x) : _
Where:
x: positive input value
Test
ma = library("maths.lib");
lgamma_test = 3.0 : ma.lgamma;
(ma.)J0
Computes the Bessel function of the first kind of order 0 of the input signal.
Usage
J0(x) : _
Where:
x: input value
Test
ma = library("maths.lib");
J0_test = 1.0 : ma.J0;
(ma.)J1
Computes the Bessel function of the first kind of order 1 of the input signal.
Usage
J1(x) : _
Where:
x: input value
Test
ma = library("maths.lib");
J1_test = 1.0 : ma.J1;
(ma.)Jn
Computes the Bessel function of the first kind of order n (first input signal, an integer) of the second input signal x.
Usage
Jn(n,x) : _
Where:
n: integer orderx: input value
Test
ma = library("maths.lib");
Jn_test = (2, 1.0) : ma.Jn;
(ma.)Y0
Computes the linearly independent Bessel function of the second kind of order 0 of the positive input signal.
Usage
Y0(x) : _
Where:
x: positive input value
Test
ma = library("maths.lib");
Y0_test = 1.0 : ma.Y0;
(ma.)Y1
Computes the linearly independent Bessel function of the second kind of order 1 of the positive input signal.
Usage
Y1(x) : _
Where:
x: positive input value
Test
ma = library("maths.lib");
Y1_test = 1.0 : ma.Y1;
(ma.)Yn
Computes the linearly independent Bessel function of the second kind of order n (first input signal, an integer) of the second input signal x (positive).
Usage
Yn(n,x) : _
Where:
n: integer orderx: positive input value
Test
ma = library("maths.lib");
Yn_test = (2, 1.0) : ma.Yn;
(ma.)fabs, (ma.)fmax, (ma.)fmin
Aliases of the abs, max and min primitives, for compatibility with
the C math library naming: fabs = abs, fmax = max, fmin = min.
Usage
fabs(x) : _
fmax(x,y) : _
fmin(x,y) : _
Where:
x,y: input signals
(ma.)np2
Gives the next power of 2 of x.
Usage
np2(n) : _
Where:
n: an integer
Test
ma = library("maths.lib");
np2_test = 5 : ma.np2;
(ma.)frac
Gives the fractional part of n.
Usage
frac(n) : _
Where:
n: a decimal number
Test
ma = library("maths.lib");
frac_test = 3.75 : ma.frac;
(ma.)decimal
Gives the fractional part of n. Alias of frac, kept for backward
compatibility: JOS uses frac a lot in filters.lib so that name was
preferred.
Usage
decimal(n) : _
Where:
n: a decimal number
Test
ma = library("maths.lib");
decimal_test = 3.75 : ma.decimal;
(ma.)modulo
Modulus operation using the (x%y+y)%y formula to ensures the result is always non-negative, even if x is negative.
Usage
modulo(x,y) : _
Where:
x: the numeratory: the denominator
Test
ma = library("maths.lib");
modulo_test = (-3, 4) : ma.modulo;
(ma.)isnan
Return non-zero if x is a NaN.
Usage
isnan(x) : _
Where:
x: signal to analyse
Test
ma = library("maths.lib");
os = library("oscillators.lib");
isnan_test = (os.tosc(1) - 2.0) : sqrt : ma.isnan;
(ma.)isinf
Return non-zero if x is a positive or negative infinity.
Usage
isinf(x) : _
Where:
x: signal to analyse
Test
ma = library("maths.lib");
os = library("oscillators.lib");
isinf_test = (os.impulse - os.impulse) : log : ma.isinf;
(ma.)nextafter
Gives the next representable floating-point value after x (first input)
in the direction of y (second input) (the C nextafter function of math.h).
Usage
nextafter(x,y) : _
Where:
x: the starting valuey: the direction toward which the next representable value is taken
Test
ma = library("maths.lib");
nextafter_test = (1.0, 2.0) : ma.nextafter;
(ma.)chebychev
Chebychev transformation of order N.
Usage
_ : chebychev(N) : _
Where:
N: the order of the polynomial, a constant numerical expression
Semantics
T[0](x) = 1,
T[1](x) = x,
T[n](x) = 2x*T[n-1](x) - T[n-2](x)
Test
ma = library("maths.lib");
chebychev_test = 0.5 : ma.chebychev(3);
References
(ma.)chebychevpoly
Linear combination of the first Chebyshev polynomials.
Usage
_ : chebychevpoly(lcoef) : _
Where:
lcoef: the list of coefficients(c0,c1,...,cn)of the Chebychev polynomials, such thatchebychevpoly((c0,c1,...,cn))is the sum ofchebychev(i)*ci
Example
_ : chebychevpoly((1, 0, 1)) : _ // T[0](x) + T[2](x)
Test
ma = library("maths.lib");
chebychevpoly_test = 0.5 : ma.chebychevpoly((1, 0, 1));
References
(ma.)diffn
Negated first-order difference of the input signal x: x' - x.
Usage
diffn(x) : _
Where:
x: input signal
Test
ma = library("maths.lib");
os = library("oscillators.lib");
diffn_test = os.tosc(440) : ma.diffn;
(ma.)signum
The signum function signum(x) is defined as -1 for x<0, 0 for x==0, and 1 for x>0.
Usage
signum(x) : _
Where:
x: input value
Test
ma = library("maths.lib");
signum_test = (-5.0) : ma.signum;
(ma.)nextpow2
The nextpow2(x) returns the lowest integer m such that 2^m >= x.
Usage
nextpow2(n) : _
Where:
n: positive value whose next power-of-two exponent is computed
Example
Useful for allocating delay lines, 2^nextpow2(n) being the power of
two greater than or equal to n:
de.delay(2^nextpow2(maxDelayNeeded), currentDelay)
Test
ma = library("maths.lib");
nextpow2_test = 10.0 : ma.nextpow2;
(ma.)zc
Indicator function for zero-crossing of the input signal: it returns 1 if a zero-crossing occurs, 0 otherwise.
Usage
zc(x) : _
Where:
x: input signal to monitor for zero crossings
Test
ma = library("maths.lib");
os = library("oscillators.lib");
zc_test = os.tosc(440) : ma.zc;
(ma.)unwrap
Unwrap the input signal so that successive output values never differ
by more than pi, switching to a 2*pi-complementary value when needed.
Usage
_ : unwrap(pi) : _
Where:
pi: maximum discontinuity between the output values (typicallyma.PI)
Test
ma = library("maths.lib");
os = library("oscillators.lib");
unwrap_test = os.oscrc(100) : ma.unwrap(ma.PI);
Example test program
process = 0 - os.oscrc(1000) // the true phase is either -PI or +PI
: an.resonator(1,1000) : !,_ // oscillates between -PI and +PI
: ma.unwrap(ma.PI); // oscillates near +PI
(ma.)primes
Return the n-th prime using a waveform primitive, n being the (0-based) input signal. Note that primes(0) is 2, primes(1) is 3, and so on. The waveform is length 2048, so the largest precomputed prime is primes(2047) which is 17863.
Usage
primes(x) : _
Where:
x: index of the prime number sequence (0-based).
Test
ma = library("maths.lib");
primes_test = 10 : ma.primes;