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 preserved
  • y: 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 operand
  • y: 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 operand
  • y: 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 input
  • n: 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 input
  • n: 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 in log(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 the exp(x) - 1 computation

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 order
  • x: 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 order
  • x: 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 numerator
  • y: 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 value
  • y: 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 that chebychevpoly((c0,c1,...,cn)) is the sum of chebychev(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 (typically ma.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;