libdragon
Macros | Functions
fmath.h File Reference

Fast math routines, optimized for 3D graphics calculations. More...

Go to the source code of this file.

Macros

#define BITCAST_F2I(f)   ({ int32_t i; memcpy(&i, &f, 4); i; })
 Reinterpret the bits composing a float as a int32. More...
 
#define BITCAST_I2F(i)   ({ float f; memcpy(&f, &i, 4); f; })
 Reinterpret the bits composing a int32 as a float. More...
 

Functions

float fm_sinf (float x)
 Faster version of sinf. More...
 
float fm_sinf_approx (float x, int approx)
 Faster version of sinf, with tunable approximation level. More...
 
float fm_cosf (float x)
 Faster version of cosf. More...
 
void fm_sincosf (float x, float *sin, float *cos)
 Faster version of sincosf. More...
 
float fm_atan2f (float y, float x)
 Faster version of atan2f. More...
 

Detailed Description

Fast math routines, optimized for 3D graphics calculations.

Macro Definition Documentation

◆ BITCAST_F2I

#define BITCAST_F2I (   f)    ({ int32_t i; memcpy(&i, &f, 4); i; })

Reinterpret the bits composing a float as a int32.

This version is type-punning safe and produces optimal code when optimizing.

◆ BITCAST_I2F

#define BITCAST_I2F (   i)    ({ float f; memcpy(&f, &i, 4); f; })

Reinterpret the bits composing a int32 as a float.

This version is type-punning safe and produces optimal code when optimizing.

Function Documentation

◆ fm_sinf()

float fm_sinf ( float  x)

Faster version of sinf.

This function computes a very accurate approximation of the sine of a floating point number, as long as the argument as a small magnitude. Do not use this function with very large (positive or negative) numbers as the accuracy decreases. Normally, it is not necessary in graphics programming to compute trigonometric functions on angles of unbounded magnitude.

The functions runs in about ~50 ticks, versus ~800 ticks of the newlib version. The accuracy in the range [-π, +π] is within 5 ULP of the correct result, but the argument reduction to bring the argument in that range introduces errors which increase with the magnitude of the operand.

◆ fm_sinf_approx()

float fm_sinf_approx ( float  x,
int  approx 
)

Faster version of sinf, with tunable approximation level.

This function is similar to fm_sinf, but allows to further speedup the approximation by reducing the number of calculated terms. fm_sinf in fact is pretty accurate (~ 5 ULP) but some times much less precision is required.

The approximation level is a number between 0 and 5, where 0 is the most accurate version (identical to fm_sinf) and 5 is the fastest one. We do not give mathematical guarantees on the accuracy of the approximation, and we suggest on holistic approach (try and see if it works for you).

This function is suggested in all cases in which you need to visually reproduce a "sinewave" effect, but you do not care about the exact numbers behind it. For trigonemetric formulas that includes a sine (eg: matrix rotations), it is suggested to use fm_sinf instead.

Parameters
xThe angle in radians
approxThe approximation level, between 0 and 5

◆ fm_cosf()

float fm_cosf ( float  x)

Faster version of cosf.

See also
fm_sinf for considerations on why and how to use this functions instead of the standard sinf.

◆ fm_sincosf()

void fm_sincosf ( float  x,
float *  sin,
float *  cos 
)

Faster version of sincosf.

Similar to fm_sinf and fm_cosf, but calculates both sinf and cosf for the same angle.

Parameters
xThe angle in radians
sinThe pointer to the variable that will contain the sine
cosThe pointer to the variable that will contain the cosine

◆ fm_atan2f()

float fm_atan2f ( float  y,
float  x 
)

Faster version of atan2f.

Given a point (x,y), return the angle in radians that the vector (x,y) forms with the X axis. This is the same of arctan(y/x).

This function runs in about ~XX ticks, versus ~YY ticks of the newlib version. The maximum measured error is ~6.14e-4, which is usually more than enough in the context of angles.