# Mathematical functions

Punctual include a whole lot of mathematical functions that can be used in different way in our expressions.

## Range between two values

`between`

`between [min1,max1...] expr`

`between`

allows you to specify one or more ranges and any other expression. It returns 1 if the expression is between the specified ranges and 0 if not.

We’ve already seen some uses of `between`

in other sections, for example, the drawing of a radius 1 circumference:

```
between [fr-px, fr+px] 1 >> add;
```

Note that the expression `fr==1 >> add;`

won’t yield any results. There isn’t any fragment that has a radius of exactly one. Due to the division of the screen in a finite number of fragments, and thus not being a continuous space, some fragments will have a radius very near to 1 (such as 1.0001 or 0.99998), but not exactly 1.

These two expressions are equivalent:

```
between [0.5,0.7] fy >> add;
hline 0.6 0.1 >> add;
```

A 45º arc:

```
fit 1 $ (between [0.4,0.42] fr) * (between [0, pi/4] ft) >> add;
```

A lot of concentric circles:

```
r << fr%0.1;
fit 1 $ between [r-2*px, r+2*px] 0.1 >> add;
```

In the next example, we use `between`

to create a mask where only fragments whose green component is in a certain range are selected.

A second mask is used to discard fragments with a lot of blue component.

Then, these two masks filter the original image, so only the selected fragments are shown at full bright, and the others are dimmed.

```
i << img "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d5/Half-timbered_mansion%2C_Zirkel%2C_East_view.jpg/1024px-Half-timbered_mansion%2C_Zirkel%2C_East_view.jpg";
o << 0.3*osc 0.015;
g<<between (o+[0.5,0.9]) $ rgbg i;
m << rgbb i < 0.6;
i*g*m >> add;
i*0.2 >> add;
```

`betweenp`

`betweenp [min1,max1...] expr`

: is the same than`between`

, but if multiple limits and expressions are provided, they are combined in a pair-wise way, while with`between`

they are combined in a combinatorial way.

See the difference between these two expressions:

```
between [0.2,0.3,-0.2,-0.3] [fy,fx] >> add;
```

```
betweenp [0.2,0.3,-0.2,-0.3] [fy,fx] >> add;
```

The first one creates four stripes, as it combines [0.2,0.3] with `fy`

and `fx`

, and `[-0.2,-0.3]`

with `fx`

and `fy`

, while the second one creates only two stripes, combining [0.2, 0.3] with `fy`

, and [-0.2, -0.3] with `fx`

.

## Sign of an expression

`abs`

`abs graph`

returns the absolute value of the provided graph, that is the same graph but ignoring the sign.`abs (-1)`

is 1 and`abs 1`

is 1.

There are a lot of examples of the use of `abs`

throughout this guide, as, alongside `unipolar`

, is a fast way to covert a -1 to 1 range to a 0 to 1 one.

```
abs fx >> add;
```

```
abs [1-fx, spin (saw 0.03) $ fx+osc 0.04, abs $ osc 0.13] >> add;
```

It is also useful to create symmetry:

```
setfx (abs fx) $ spin [0.2] $ tile [1,12] $ hline 0 0.01 >> add;
```

```
fit 1 $ setfxy (abs fxy) $ spin [0.2] $ tile [1,12] $ hline 0 0.01 >> add;
```

`sign`

`sign graph`

returns only the sign of the graph: 1 if it’s positive, -1 if it’s negative, 0 if it’s 0.

In this example, we use `sign`

as a threshold. For each color component, only fragments that have a certain amount of the component color are lit (but when they are, they are completely lit).

`i2`

is used as mask, so the brightest fragments are kept black.

Note that the same result could be achieved using a `>0`

comparison instead of `sign`

.

```
i << img "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d5/Half-timbered_mansion%2C_Zirkel%2C_East_view.jpg/1024px-Half-timbered_mansion%2C_Zirkel%2C_East_view.jpg";
i2 << rgbv i < 0.7;
r << sign $ rgbr i - (0.3~~0.7 $ osc 0.13);
g << sign $ rgbg i - (0.3~~0.7 $ osc 0.15);
b << sign $ rgbb i - (0.3~~0.7 $ osc 0.09);
i2*[r, g, b] >> add;
```

Here, we explore the same idea, but use the HSV color space, oversaturate some fragments, and apply a gradual palette change to the entire image.

```
i << img "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d5/Half-timbered_mansion%2C_Zirkel%2C_East_view.jpg/1024px-Half-timbered_mansion%2C_Zirkel%2C_East_view.jpg";
i2 << rgbv i < 0.6;
s << sign $ rgbs i - (0.3~~0.7 $ osc 0.013);
h << ((rgbh i)+(unipolar $ saw 0.01));
v << rgbv i;
hsvrgb $ i2*[h, s, v] >> add;
```

Here, `sign`

is applied to a bunch of oscillators. The resulting `o`

variable represents a series of -1, 0, or 1, depending on the sign of each oscillator at a given time.

When `o`

is used inside `move`

, we get a lot of moving lines, but that abruptly change their position whenever their associated oscillator changes its sign.

```
l << spin [fr*8] $ spin [saw 0.16] $ tile [1,8] $ hline 0 0.01;
o << sign $ osc [0.13,0.15..0.20];
fit 1 $ mono $ move [o*osc 0.03] l >> add;
0.9 * fb fxy >> add;
```

## Rounding numbers

`fract`

`fract`

returns the fractional part of numbers.

Note that here “the fractional part” is defined as the difference between the number and the whole number immediately below it, so `fract 2.3`

is `0.3`

, and `fract (-1.2)`

is `0.8`

(`-1.2 - (-2) = -1.2+2 = 0.8`

):

```
l1 << vline (fract 2.3) 0.01;
l2 << vline (fract (-1.2)) 0.01;
[0,1,0]*l1 >> add;
[1,0,0]*l2 >> add;
```

Also note that `fract x`

is equivalent to `x%1`

for any `x`

.

In this example, the image is divided in 100 vertical slices, and each slice is distorted. Within each slice, each fragment is vertically displaced based on its position within the slice. The displacement goes from no displacement on the left side to maximum displacement on the right side, resulting in a distortion effect across the image:

```
i << img "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b1/Peaceful_waterfall_%28Unsplash%29.jpg/1024px-Peaceful_waterfall_%28Unsplash%29.jpg";
move [0,((-0.5) ~~ (-0.01) $ sin 0.03)*fract (fx*100)] $ i >> add;
```

`round`

, `ceil`

, `floor`

, `trunc`

`round`

,`ceil`

,`floor`

and`trunc`

are intimately related. All four convert a number to a near integer.

`round`

rounds the number to the nearest integer. `round 3.2`

is `3`

, `round 3.7`

is 4, `round (-3.2)`

is `-3`

and `round (-3.7)`

is `-4`

. For a fractional part of exactly `0.5`

, the number is rounded to the next higher integer.

`ceil`

rounds the number to the next higher integer. `ceil 3.2`

is `4`

, `ceil 3.7`

is 4, `ceil (-3.2)`

is `-3`

and `ceil (-3.7)`

is `-3`

.

`floor`

rounds the number to the next lower integer. `floor 3.2`

is `3`

, `floor 3.7`

is `3`

, `floor (-3.2)`

is `-4`

and `floor (-3.7)`

is `-4`

.

`trunc`

truncates the number, in explain, it gets rid of the fractional part. `trunc 3.2`

is `3`

, `trunc 3.7`

is `3`

, `trunc (-3.2)`

is `-3`

and `trunc (-3.7)`

is `-3`

.

Amongst the useful applications of these functions, there is to apply a *pixelation* effect:

```
p << spin 0.25 $ unipolar fx;
setfxy [round (fxy*10)/10] p >> add;
```

In this example, the original pattern `p`

is pixelated, creating a grid of 10x10 squares, each one in a uniform color. The use of the other functions lead to slightly different results.

Next example is a reimplementation of Hydra’s function *posterize*, applied to an image:

```
i << img "https://upload.wikimedia.org/wikipedia/commons/thumb/d/da/Sonoma_chipmunk_at_Samuel_P._Taylor_State_Park.jpg/1280px-Sonoma_chipmunk_at_Samuel_P._Taylor_State_Park.jpg";
bins << 3;
gamma << 0.6;
c2 << (floor $ i ** gamma * bins)/bins;
c2 ** (1/gamma) >> add;
```

Note how the same method as in the previous example is used (multiply by a number, rounding, and dividing by the same number), in this case to reduce to number of colors in the image.

## Exponentials, logarithms, and roots

`sqrt`

`sqrt <graph>`

: Calculates the square root of the provided graph. It yields the positive square root for each value in the graph.

`cbrt`

`cbrt <graph>`

: Computes the cube root of the provided graph. The cube root is the number that, when multiplied by itself three times, results in the original number. It returns both positive and negative cube roots.

`exp`

`exp <graph>`

: Computes the exponential function, which raises the mathematical constant e to the power of the values in the provided graph. The exponential function grows rapidly for positive values and approaches zero for negative values.

`log`

`log <graph>`

: Computes the natural logarithm (base e) of the values in the provided graph. It is the inverse operation of the exponential function. It is only defined for positive numbers and grows faster than the binary and decimal logarithms.

`log2`

`log2 <graph>`

: Calculates the binary logarithm (base 2) of the values in the provided graph. It represents the power to which the base (2) must be raised to produce the values in the graph. The binary logarithm grows slower than the natural logarithm but faster than the decimal logarithm.

`log10`

`log10 <graph>`

: Computes the decimal logarithm (base 10) of the values in the provided graph. It represents the power to which the base (10) must be raised to produce the values in the graph. The decimal logarithm grows slower than both the natural and binary logarithms.

Let’s first see the graphs of these functions:

```
fit 1 $ zoom 0.5 $ circle [fx, [sqrt fx, cbrt fx, exp fx]] 0.01 >> add;
```

```
fit 1 $ zoom 0.5 $ circle [fx, [log fx, log2 fx, log10 fx]] 0.01 >> add;
```

### Exponentials, logarithms, and roots examples

In the next example, we manipulate the graph of the square root function to create a symmetrical pattern reminiscent of wings.

First step is to create a four-way symmetry of the original graph. This is done by taking the absolute value of `x`

(so we have results for both positive and negative values), and then multiplying the square root by `[-1, 1]`

, so the graph is mirrored horizontally. The result is a four-way symmetry of the original graph:

```
s << [-1,1]*(sqrt $ abs fx);
mono $ zoom 0.5 $ circle [fx, s] 0.004 >> add;
```

To complete the example, an oscillator is added to the square root, so the graphs move up and down like wings. A second oscillator is added to curve the lines in response to the incoming audio signal.

Finally, we give the result some color and add a zooming feedback effect, which increase the wings resemblance:

```
o << unipolar $ saw 0.9;
s << [-1,1]*(sqrt $ o*abs fx);
g << mono $ zoom 0.5 $ circle [fx, s] 0.004;
g*[fr,0.5, 0.5+abs fy]>> add;
zoom 0.96 $ fb fxy >> add;
```

In this example, we use the cubic root function (`cbrt`

) to manipulate the parameters of a circle pattern, resulting in a visually dynamic and intricate design.

The core of the pattern is just a `circle`

, but the coordinates that define its center are defined by the `x`

and `y`

variables, that vary with `fr`

, `fx`

and `fy`

. Here is important to remember that `circle`

does not necessary define a proper circle: a fragment `(fx, fy)`

will be considered to be inside the circle if `(x, y)`

is at a distance of the fragment of 0.8 or less.

Let’s try first a simplified version:

```
d << fr;
x << d;
y << d;
move [0,-1] $ circle [x, y] 0.8 >> add;
```

This is just a distorted circle. Now, let’s add the different parts step by step:

```
d << fr;
x << d*(saw (0.1*fy));
y << d;
move [0,-1] $ circle [x, y] 0.8 >> add;
```

This is the main pattern. The circle moves horizontally, and the movement is controlled by `fy`

, slicing the circle in multiple parts.

```
d << fr;
x << d*(saw (0.1*fy));
y << d+(0.2*fract (fx*100));
move [0,-1] $ circle [x, y] 0.8 >> add;
```

In this step, the circle is sliced vertically. Note, for example, that `fract (fx*10) >> add`

would create a vertical stripe pattern.

To create the final pattern, we first add `cbrt`

to the `d`

calculation. This has the effect of compressing the pattern vertically. Finally, we add color to the circle using the HSV color space, with hue and saturation modulated by `fx`

and `fy`

, respectively:

```
d << cbrt fr;
x << d*(saw (0.1*fy));
y << d+(0.2*fract (fx*100));
c << move [0,-1] $ circle [x, y] 0.8;
co << hsvrgb [fx+saw 0.03,fy,0.8];
c*co >> add;
```

In this example, we use the three logarithm variants to create variation in the movement of six circles.

The pattern starts by defining a circle and applying a horizontal movement to it. As `dx`

is a 3-channel signal, three circles are created. Then they are duplicated again, creating the six circles, by using `spin`

with two oscillators. The modulo operator `%1`

is used to ensure that `dx`

values are within the interval `[0,1]`

. Because we are using three variants of the logarithm, the circles move in a similar but not identical way.

The circles are colored in the HSV color space, with the hue oscillating and the saturation and value fixed. The result is then converted to RGBA by adding an alpha channel.

Finally, feedback is applied to the image, and it is moved to the left to create a trail effect that increases the movement sensation.

```
c << circle 0 0.08;
et << etime;
dx << [log et, log2 et, log10 et]%1;
cs << mono $ spin (saw [0.2,-0.2]) $ move [dx, 0] c;
cs*(hsvrgb [saw 0.9, 0.6, 0.6]++1) >> blend;
move [-0.03,0] $ fb fxy >> add;
```

## Trigonometric functions

`pi`

`pi`

: this is just the number pi, 3.14159…

`sin'`

, `cos`

, `tan`

- Basic trigonometric functions:
`sin'`

,`cos`

,`tan`

. These functions receive a graph in radians and return the sine, cosine, and tangent of that number, respectively. Note that the sine function is called`sin'`

to avoid conflicts with the`sin`

function, which is a (deprecated) synonym for`osc`

.

```
fit 1 $ zoom 0.5 $ circle [fx, [sin' fx, cos fx, tan fx]] 0.01 >> add;
```

`asin`

, `acos`

, `atan`

- Inverse trigonometric functions:
`asin`

,`acos`

,`atan`

. These functions receive a number between -1 and 1 and return the corresponding angle in radians.

```
fit 1 $ zoom 0.5 $ circle [fx, [asin fx, acos fx, atan fx]] 0.01 >> add;
```

`sinh`

, `cosh`

, `tanh`

- Hyperbolic functions:
`sinh`

,`cosh`

,`tanh`

. These functions are the hyperbolic counterparts to the basic trigonometric functions. They are useful to create smooth curves and transitions.

```
fit 1 $ zoom 0.5 $ circle [fx, [sinh fx, cosh fx, tanh fx]] 0.01 >> add;
```

`asinh`

, `acosh`

, `atanh`

- Inverse hyperbolic functions:
`asinh`

,`acosh`

,`atanh`

. These functions are the hyperbolic counterparts to the inverse trigonometric functions.

```
fit 1 $ zoom 0.5 $ circle [fx, [asinh fx, acosh fx, atanh fx]] 0.01 >> add;
```

### Trigonometric functions examples

These functions provide a range of mathematical tools to manipulate angles, curves, and transitions within your graphical patterns.

In this example, sinusoidal waves are generated from an image.

To assure a smooth transition, the image is first vertically reflected. The `setfx`

function in the second line is used to mirror the image and put the two copies side by side.

The `tiled`

variable is created by tiling the reflected image, so the two copies are repeated horizontally. Note that the `tile`

function is used with a `1`

parameter, so there is no visible change at this point, but the image will now be repeated when moved.

The next step is to create a wave that will be used to move the image. The wave is created by combining a sine wave with a cosine wave. This way, two copies of the wave are created, but displaced by 90 degrees. The `~~`

operator is used to reduce the displacement that will be applied to the image.

Finally, the image is moved by the wave, and the result is horizontally moved with a `saw`

oscillator to create the actual waves.

```
i << img "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b1/Peaceful_waterfall_%28Unsplash%29.jpg/1024px-Peaceful_waterfall_%28Unsplash%29.jpg";
reflected << setfx [fx-1, (-1)*fx-1] i;
tiled << tile 1 reflected;
wave << (-0.5) ~~ 0 $ [sin' (fx*10), cos (fx*10)];
move [saw 0.02, wave] tiled >> add;
```

The next example utilize the `tan`

function to curve a horizontal line. The tangent argument, `t`

, is defined by the multiplication of two parts. The right part, `(1-(abs fx))`

, goes from 0 on the left and right sides of the screen, to 1 on the center. The left part, `(etime%5)`

, goes from 0 to 5 and back to 0 every 5 seconds.

After applying the tangent of `t`

to the line’s y coordinate, the line starts horizontal and bends from the center upwards, reappearing from the bottom after reaching the top. This line is then colored red and tiled.

The last bit of the example is the addition of the feedback in polar coordinates. Two copies are created, mirrored vertically, and then the result is duplicated again by rotating it 180 degrees.

```
t << (etime%5)*(1-(abs fx));
tile [8,4] $ [1,0,0]*(hline (tan t) 0.08) >> add;
zoom 1.4 $ fit 1 $ spin ([0,-1]) $ mono $ fb [fr, [1,-1]*ft] >> add;
```