# ACSUtils Wiki

An ACS library for ZDoom-based ports

math

# Math

ACSUtils provides a rich math library and covers for several missing ZDoom functions.

### What is "num"?

`num` means “any numeric type” (either int or fixed). Functions accepting `num` accept both ints and fixeds, e.g:

`num max(num a, num b)`

translates to:

“The function `max` accepts two numbers and returns a number. If both arguments are ints, it returns an int, and if both arguments are fixeds, it returns a fixed”.

This allows `max` to be used both ways:

```max(2, 5) == 5
max(2.0, 5.0) == 5.0```
Don't mix ints and fixeds when using `num`. `num`s in a function signature are either all int or all fixed! E.g., this is incorrect:
`max(5, 2.0)`

It will return `2.0` because `max` uses a simple `a > b` comparison that only works correctly if both numbers are ints or both numbers are fixeds. `2.0` (65536) is greater than 5.

However, not all arguments of a function may be `num`. Some arguments may be required to be int or fixed, or the function may always return int or fixed:

```num OneOfTheArgumentsIsRequiredToBeInt(num a, int b)
fixed ThisFunctionAlwaysReturnsFixed(num a, num b)```

### Angles

All angles throughout ACSUtils are fixed-point angles (turns), and they are allowed to be outside the `0.0`..`1.0` range. All such cases are handled correctly by both ZDoom and ACSUtils.

Also, ZDoom expects inverted actor pitch (positive = looking down) in GetActorPitch and SetActorPitch. ACSUtils doesn't invert pitch angles, so remember to invert pitch when retrieving it with `GetActorPitch` and when setting it with `SetActorPitch`.

## Constants

ACSUtils provides a set of mathematical constants. All fixed-point constants have a lot of digits after the point to maximize precision. Actually more digits than needed.

### Pi and Tau

• `#define PI 3.1415926535897932384626433832795`
• `#define TAU 6.2831853071795864769252867665590`

The numbers Pi and Tau.

### e

`#define MATH_E 2.7182818284590452353602874713526624977572470937`

The number e. Called `MATH_E` to avoid conflicts with variable name `e`.

### Significant square roots and logarithms

Precalculated to maximum precision. The precalculated logarithms are used to implement `ln` and `log10`.

• `#define SQRT_2 1.41421356237` – sqrt(2)
• `#define LOG2_E 1.44269504089` – log2(e)
• `#define LOG2_10 3.32192809489` – log2(10)

## Generic math functions

### abs

`num abs(num x)`

Returns the absolute value of X:

• If X is zero or positive, returns X.
• If X is negative, returns -X.
Beware of using this function with `INT_MIN`.

`abs(INT_MIN) == INT_MIN` because `-INT_MIN == INT_MIN`. This is the only case when `abs` returns a negative number.

### sgn

`int sgn(int x)`

Returns the sign of X:

• If X is positive, returns `1`.
• If X is negative, returns `-1`.
• If X is zero, returns `0`.

#### Example usage

```// Make X velocity 15.0, but with the same sign as foo
int xvel = sgn(foo) * 15.0;```

### min

`num min(num a, num b)`

Returns the lesser of two numbers.

### max

`num max(num a, num b)`

Returns the greater of two numbers.

### clamp

`num clamp(num x, num mininum, num maximum)`

Limits X to the specified range:

• If X < mininum, returns the minumum.
• If X is between mininum and maximum, returns X.
• If X > maximum, returns the maximum.

### lerp

`fixed lerp(fixed a, fixed b, fixed alpha)`

Linear interpolation function commonly used in game development. Performs linear interpolation (or extrapolation) between A and B and returns the result.

Alpha can be outside of `0.0`..`1.0` range. In that case, it's linear extrapolation.

#### example usage

Simple movement animation between two points:

```for (int time = 0; time < 1.0; time += 0.05)
{
int x = lerp(x1, x2, time);
int y = lerp(y1, y2, time);
DrawSomething(x, y);
Delay(1);
}```

### IntDiv

`fixed IntDiv(int a, int b)`

An equivalent of FixedDiv for integers that works for any two integers as long as the result fits into a fixed-point number. Divides integer A by integer B and returns the result as a fixed-point number.

If the result is greater than 32767, the function returns 0.

Can also be used as a more readable alternative to `FixedDiv(a<<16, b<<16)`.

### cmp

`int cmp(num a, num b)`

Compares two numbers and returns the result:

• If A > B, returns `1`.
• If A = B, returns `0`.
• If A < B, returns `-1`.

### fract

`fixed fract(fixed x)`

Returns the fractional part of X, e.g `fract(12.345) == 0.345`.

The result is not affected by the sign of the number, e.g. `fract(-12.345) == 0.345`. The result is always between `0.0` and `1.0`.

### ipow

`int ipow(int x, int y)`

Returns xy. Uses a simple multiplication loop.

### fpow

`fixed fpow(fixed x, fixed y)`

returns xy. Supports powers below `1.0`. Uses a simple loop with `FixedMul` or `FixedDiv`, depending on whether the power is below `1.0`.

## Trigonometry

ACSUtils provides a full set of trigonometric functions:

• sin is already built into ZDoom.
• cos is already built into ZDoom.
• `fixed tan(fixed angle)` – implemented as `FixedDiv(sin(x), cos(x))`.
• `fixed cot(fixed angle)` – implemented as `FixedDiv(cos(x), sin(x))`.
• `fixed sec(fixed angle)` – implemented as `FixedDiv(1.0, sin(x))`.
• `fixed cosec(fixed angle)` – implemented as `FixedDiv(1.0, cos(x))`.

Inverse trigonometric functions:

• `fixed atan(fixed x)` – implemented as `VectorAngle(1.0, x)`.
• `fixed acot(fixed x)` – implemented as `0.25 - atan(x)`.
• `fixed asin(fixed x)` – implemented as `atan(FixedDiv(x, FixedSqrt(1.0 - FixedMul(x, x))))`.
• `fixed acos(fixed x)` – implemented as `ang(2 * atan(FixedSqrt(FixedDiv(1.0 - x, 1.0 + x))))`.
• `fixed asec(fixed x)` – implemented as `acos(FixedDiv(1.0, x))`.
• `fixed acosec(fixed x)` – implemented as `asin(FixedDiv(1.0, x))`.

## Vector math

Vector math functions come in 2D and 3D versions. All vector math functions operate only on fixed-point vectors. No integer versions are available.

Vectors are passed as arguments named `x`, `y`, `z`.

If a function returns a vector, it uses Multiple return values, returning vector components in the same XYZ order, so `r1` is X, `r2` is Y and `r3` is Z.

If a function accepts more than one vector, the first vector is passed as `x1`, `y1`, `z1`, and the second one as `x2`, `y2`, `z2`.

### Length

• 2D: VectorLength – already built into ZDoom.
• 3D: `fixed VectorLength3D(fixed x, fixed y, fixed Z)`

These functions return the length of the input vector. `VectorLength3D` is implemented efficiently as `VectorLength(VectorLength(x, y), z)`.

### Dot product

• 2D: `fixed dot2(fixed x1, fixed y1, fixed x2, fixed y2)`
• 3D: `fixed dot3(fixed x1, fixed y1, fixed z1, fixed x2, fixed y2, fixed z2)`

These functions return the sum of components of a vector obtained by componentwise multiplication of the two input vectors, also known as the dot product. They are shorthands for writing out `FixedMul(x1, x2) + FixedMul(y1, y2) + …`.

### Normalization

• 2D: `fixed, fixed normalize2d(fixed x, fixed y)`
• 3D: `fixed, fixed, fixed normalize3d(fixed x, fixed y, fixed z)`

These functions return the input vector scaled to have length `1.0`, also known as normalizing the input vector, and return the result using Multiple return values.

#### Examples

```normalize3d(x, y, z);
x = r1;
y = r2;
z = r2;```
```normalize2d(x, y);
int normalizedX = r1;
int normalziedY = r2;```

### RotateVector

`fixed, fixed RotateVector(fixed x, fixed y, fixed angle)`

Rotates the vector by the angle and returns the result using Multiple return values.

#### Example usage

```RotateVector(x, y, angle);
int newX = r1;
int newY = r2;```
```// Rotate a point around the origin
// Use RotatePoint instead of this example code
RotateVector(x - originX, y - originY, angle);
int newX = r1 + originX;
int newY = r2 + originY;```

### RotateVectorCS

`fixed, fixed RotateVector(fixed x, fixed y, fixed cos, fixed sin)`

A faster version of RotateVector that accepts cos(angle) and sin(angle) instead of computing them.

#### Example usage

```int c = cos(angle);
int s = sin(angle);

// Rotate first vector
RotateVectorCS(x1, y1, c, s);
x1 = r1;
y1 = r2;

// Rotate second vector without recalculating sine and cosine
RotateVectorCS(x2, y2, c, s);
x2 = r1;
y2 = r2;```

### RotatePoint

`fixed, fixed RotatePoint(fixed x, fixed y, fixed originX, fixed originY, fixed angle)`

Rotates the point around the specified origin by the angle and returns the result using Multiple return values.

#### Example usage

```RotatePoint(x, y, originX, originY, angle);
int newX = r1;
int newY = r2;```

### SqVectorLength

• `fixed SqVectorLength(fixed x, fixed y)`
• `fixed SqVectorLength3D(fixed x, fixed y, fixed z)`

Returns vector length squared.

Because this function returns a fixed, it won't work correctly for vectors longer than `256.0`.

### VectorToAngles

`fixed, fixed VectorToAngles(fixed x, fixed y, fixed z)`

Converts the vector's direction to a pair of angles (angle, pitch) and returns them using Multiple return values.

Remember that ZDoom uses negated pitch angles on actors. ACSUtils functions don't use negated pitches.

#### Example usage

```// This function makes the actor look in the direction
// specified as a 3D vector.
function void LookInDirection(int tid, int x, int y, int z)
{
VectorToAngles(x, y, z);
int angle = r1;
int pitch = r2;
SetActorAngle(tid, angle);
SetActorPitch(tid, -pitch); // SetActorPitch expects negated pitch.
}```

### AnglesToVector

`fixed, fixed, fixed AnglesToVector(fixed angle, fixed pitch)`

Converts a pair of angles (angle, pitch) to a 3D vector of length `1.0`, which points in the same direction, and returns it using Multiple return values.

Remember that ZDoom uses negated pitch angles on actors. ACSUtils functions don't use negated pitches.

#### Example usage

```AnglesToVector(GetActorAngle(0), -GetActorPitch(0)); // Un-negate actor pitch
int dirX = r1;
int dirY = r2;
int dirZ = r3;```

## Logarithms

Base-2 logarithms are the fundamental algorithm. All other bases are implemented using the property “`log_b(x) = log_2(x) / log_2(b)` if b > 1”.

All logarithm functions return a fixed, but there are two versions of every logarithm function: one accepting an integer X and one accepting a fixed-point X. The integer-accepting functions have the `i` prefix.

### log2

• `fixed log2(fixed x)`
• `fixed ilog2(int x)`

Returns the base-2 logarithm of X.

### log10

• `fixed log10(fixed x)`
• `fixed ilog10(int x)`

Returns the base-10 logarithm of X. Implemented by dividing log2(X) by the precalculated constant `LOG2_10`.

### ln

• `fixed ln(fixed x)`
• `fixed iln(int x)`

Returns the natual (base-e) logarithm of X. Implemented by dividing log2(X) by the precalculated constant `LOG2_E`.

### logb

• `fixed logb(fixed x, fixed base)`
• `fixed ilogb(int x, fixed base)`

Returns an arbitrary-base logarithm of X. Calculates `FixedDiv(log2(x), log2(base))`.

Only bases higher than `1.0` are supported.
Using these functions with bases very close to `1.0` may produce a result that doesn't fit into a fixed.

Note that even the integer version has a fixed-point base.

### Page Tools 