# Chapter 17. Math library

Rax contains a large number of built-in math constants and functions. Most of them will be familiar to C programmers who have used the C math library. The table below summarizes the built-in math constants in Rax.

Table 17.1. Built-in math constants in Rax

Constant
type
Constant nameMath symbolValue in Rax
`&``M_E:`e2.7182818284590452353602874713526625
`&``M_LOG2E``log2(e)`1.4426950408889634073599246810018922
`&``M_LOG10E`log10(e)0.4342944819032518276511289189166051
`&``M_LN2`ln(2)0.6931471805599453094172321214581766
`&``M_LN10`ln(10)2.3025850929940456840179914546843642
`&``M_PI`π3.1415926535897932384626433832795029
`&``M_PI_2`π/21.5707963267948966192313216916397514
`&``M_PI_4`π/40.7853981633974483096156608458198757
`&``M_1_PI`1/π0.3183098861837906715377675267450287
`&``M_2_PI`2/π0.6366197723675813430755350534900574
`&``M_2_SQRTPI`2/sqrt(π)1.1283791670955125738961589031215452
`&``M_SQRT2`sqrt(2)1.4142135623730950488016887242096981
`&``M_SQRT1_2`sqrt(1/2) or 1/sqrt(2)0.7071067811865475244008443621048490

The built-in functions in Rax are not regular functions, they are in fact operators. For that reason, they feature a ':' at the end of their name. The built-in functions with their input and output parameters are summarized in the table below.

Table 17.2. Built-in math functions in Rax

 Real functions `& <- [&:mag, &:sign]: copysign:` Return the combination of the `mag`(nitude) of the left value with the `sign` of the right value. `& <- [&:value, &:dir]: nextafter:` Return the next floating-point number after the given `value` towards the given `dir`(ection) argument.
Function signatureUsageExplanation
Trigonometric functions
`& <- &: cos:``cos(x)`Compute cosine of `x`
`& <- &: sin:``sin(x)`Compute sine of `x`
`& <- &: tan:``tan(x)`Compute tangent of `x`
`& <- &: acos:``acos(x)`Compute arc cosine of `x`
`& <- &: asin:``asin(x)`Compute arc sine of `x`
`& <- &: atan:``atan(x)`Compute arc tangent of `x`
`& <- [&,&]: atan2:``atan2(x,y)`Compute arc tangent with two parameters
Trigonometric functions
`& <- &: cosh:``cosh(x)`Compute hyperbolic cosine of `x`.
`& <- &: sinh:``sinh(x)`Compute hyperbolic sine of `x`.
`& <- &: tanh:``tanh(x)`Compute hyperbolic tangent of `x`.
`& <- &: acosh:``acosh(x)`Compute arc hyperbolic cosine of `x`.
`& <- &: asinh:``asinh(x)`Compute arc hyperbolic sine of `x`.
`& <- &: atanh:``atanh(x)`Compute arc hyperbolic tangent of `x`.
Exponential and logarithmic functions
`& <- &: exp:``exp(x)`Compute exponential function: `ex`.
`& <- &: exp2:``exp2(x)`Compute exponential function: `2x`.
`[&:sig, #:exp] <- &: frexp:``frexp_man(x)`Get (sig)nificand and exp(onent), such that ```x = sig * 2exp```.
`& <- [&:sig,#:exp]: ldexp:``ldexp(sig,exp)`Generate value from sig(nificand) and exp(onent): ```sig * 2exp```.
`& <- &: log:``log(x)`Compute natural logarithm of `x`.
`& <- &: log10:``log10(x)`Compute common (base-10) logarithm of `x`.
`[&:int, &:frac] <- &: modf:``modf(x)`Break `x` into an int(egral) and a frac(tional) part.
`& <- &: expm1:``expm1(x)`Compute exponential minus one: `ex-1`.
`& <- &: log1p:``log1p(x)`Compute the natural logarithm of `1+x`.
`& <- &: log2:``log2(x)`Compute binary logarithm of `x`.
Power functions
`& <- [&,&]: pow:``pow(sig,exp)`Raise `sig` to power of `exp`.
`& <- &: sqrt:``sqrt(x)`Compute square root of `x`.
`& <- &: cbrt:``cbrt(x)`Compute cubic root of `x`.
`& <- [&:x,&:y]: hypot:``hypot(x,y)`Compute the hypot(enuse) of a right-angled triangle whose legs are `x` and `y`. The function returns in ```sqrt(x2 + y2)``` but with greater accuracy.
Error and gamma functions
`& <- &: erf:``erf(x)`Compute error function value for `x`.
`& <- &: erfc:``erfc(x)`Compute complementary error function value for `x` that is `1.0 - erf(x)`, but without loss of precision for sizable x.
`& <- &: gamma:``gamma(x)`Compute the gamma function of `x`.
`& <- &: lngamma:``lngamma(x)`Compute the natural log-gamma function of `x`.
Rounding functions
`& <- &: round:``round(x)`Return the integral value nearest to `x`.
`& <- &: trunc:``trunc(x)`Round to greatest integral value not greater than `x`.
Bessel functions
`& <- &: j0:``J0(x)`Compute Bessel function of the first kind of the order 0.
`& <- &: j1``J1(x)`Compute Bessel function of the first kind of the order 1.
`& <- [&,&]: jn:``Jn(x, n)`Compute Bessel function of the first kind of the order `n`.
`& <- &: y0:``Y0(x)`Compute Bessel function of the second kind of the order 0.
`& <- &: y1:``Y1(x)`Compute Bessel function of the second kind of the order 1.
`& <- [&,&]: yn:``Yn(x,n)`Compute Bessel function of the second kind of the order `n`.
Other functions
`& <- &: remainder:``remainder(x)`Compute remainder: a value `r` such as ```r = x - n*y```, where `n` is the integer nearest the exact value of `x/y`
`& <- [&,&,&]: logistic:``logistic(l,s,x)`Compute the logistic function: logisticlimit,speed(x) =
limit(-1+2/(1+e-speed x))

Note to the readers that wonder about `expm1:(x)`. If x is nearly zero, then the expression `exp:(x) - 1.0` will suffer from catastrophic cancellation [12]. The expm1() function provides an alternative means to do this calculation without this significant loss of precision. Note that computations numerically equivalent to exp(x) - 1.0 are often hidden in more complicated expressions. Consider the example code below.

```    &: q := 1e-5;

`print exp:(-q) * (q*q + 2*q + 2) - 2;

//                            assume: e is exp:(-q)
//   e * (qq + 2q + 2) - 2    <=>
//   eqq + e2q + eE -2        <=>
//   2e - 2 + eq(q + 2)       <=>
//                            assume: e' is e - 1
//   2e' + (e'+1)q(q + 2)

&: e' := expm1:(-q);
`print (2 * e') + (e' + 1) * q * (q + 2);
```

When `q` nears zero the two values printed will divert. It is not always easy to spot this problem. Also rewriting expressions to use `expm1:()` won't always solve all precision problems. For similar reasons there is also a `log1p:()` build-in function to perform `log(1 + q)` when `q` is quite small.

[12] Catastrophic cancellation occurs when an operation on two numbers increases relative error substantially more than it increases absolute error, for example, subtracting `1` from `exp:(`ϵ`)` where ϵ is very close to (positive) zero. The effect is that the number of accurate (significant) digits in the result is reduced unacceptably, leaving the result very imprecise.