qf_math API Reference

Complete reference for public symbols declared in src/qf_math.h.

Type

typedef float qf;

All library functions operate on IEEE-754 single-precision floats. The qf typedef makes the intent explicit and allows grepping for the API surface.

Constants

ConstantValueDescription
QF_PI3.14159265pi
QF_TWO_PI6.283185302 * pi
QF_HALF_PI1.57079632pi / 2
QF_E2.71828182Euler’s number
QF_INV_E0.367879441 / e
QF_INV_PI0.318309881 / pi
QF_DEG2RAD_K0.01745329pi / 180
QF_RAD2DEG_K57.2957795180 / pi
QF_LOG2E1.44269504log2(e)
QF_LN20.69314718ln(2)
QF_LOG2_103.32192809log2(10)
QF_LOG10_20.30102999log10(2)
QF_SQRT21.41421356sqrt(2)
QF_INV_SQRT20.707106781 / sqrt(2)
QF_SQRT31.73205080sqrt(3)
QF_INV_SQRT30.577350261 / sqrt(3)
QF_SQRT52.23606797sqrt(5)
QF_SQRT103.16227766sqrt(10)

Conversion macros

Fixed-radix bridge

#define QF_TO_FR(val, radix)      // float -> fixed-radix s32, truncating
#define QF_TO_FR_RND(val, radix)  // float -> fixed-radix s32, round-to-nearest
#define FR_TO_QF(val, radix)      // fixed-radix s32 -> float

Bridge between qf floats and fr_math-style s32 integers at system boundaries (sensor input, DAC output, protocol fields).

Integer conversions

#define QF_FROM_INT(x)   // int -> qf
#define QF_TO_INT(x)     // qf -> int32_t (truncate)
#define QF_ROUND(x)      // qf -> int32_t (round-to-nearest)

Angular conversions

#define QF_DEG_TO_RAD(x)   // degrees -> radians
#define QF_RAD_TO_DEG(x)   // radians -> degrees

BAM (Binary Angular Measure) conversions

BAM is a uint16_t where one full revolution = 65536. Natural uint16_t wraparound handles modular arithmetic.

#define QF_BAM_TO_RAD(bam)   // BAM -> radians
#define QF_RAD_TO_BAM(rad)   // radians -> BAM
#define QF_BAM_TO_DEG(bam)   // BAM -> degrees
#define QF_DEG_TO_BAM(deg)   // degrees -> BAM
BAM valueDegreesRadians
000
1638490pi/2
32768180pi
65536wraps to 0wraps to 0

Utility macros

#define QF_ABS(x)             // absolute value
#define QF_SGN(x)             // sign: -1.0, 0.0, or 1.0
#define QF_MIN(a, b)          // minimum
#define QF_MAX(a, b)          // maximum
#define QF_CLAMP(x, lo, hi)   // clamp x to [lo, hi]
#define QF_INTERP(a, b, t)    // linear interpolation, t in [0, 1]

Trigonometric functions

BAM-native

qf qf_sin_bam(uint16_t bam);
qf qf_cos_bam(uint16_t bam);
qf qf_tan_bam(uint16_t bam);

Input: BAM phase (0..65535 = one full cycle). Output: [-1, 1] for sin/cos; tangent saturates near poles to QF_TAN_MAX.

Radian input

qf qf_sin(qf rad);
qf qf_cos(qf rad);
qf qf_tan(qf rad);

Degree input

qf qf_sin_deg(qf deg);
qf qf_cos_deg(qf deg);
qf qf_tan_deg(qf deg);

Tangent pole clamp

#define QF_TAN_MAX  8388608.0f

Exact poles return QF_TAN_MAX. Near-pole values clamp to +/- QF_TAN_MAX.

Inverse trigonometric functions

qf qf_acos(qf x);   // domain [-1, 1], output [0, pi]
qf qf_asin(qf x);   // domain [-1, 1], output [-pi/2, pi/2]
qf qf_atan(qf x);   // output [-pi/2, pi/2]
qf qf_atan2(qf y, qf x);  // output [-pi, pi]

Implementation uses cubic Hermite spans for asin on [0, 3/4], atan-based fallback for (3/4, 1), and six quadratic spans for atan on [0, 1] with reciprocal reduction for x > 1. See Algorithms for details.

Logarithmic functions

qf qf_log2(qf x);    // base-2 logarithm
qf qf_ln(qf x);      // natural logarithm
qf qf_log10(qf x);   // base-10 logarithm (excluded in lean build)

Returns QF_DOMAIN_ERROR for x <= 0. ln and log10 are derived from log2 via constant multiplication.

Exponential functions

qf qf_pow2(qf x);    // 2^x
qf qf_exp(qf x);     // e^x
qf qf_pow(qf x, qf y); // x^y, positive x only
qf qf_pow10(qf x);   // 10^x (excluded in lean build)

exp and pow10 are derived from pow2 via base conversion. pow is derived from pow2(y * log2(x)) and returns QF_DOMAIN_ERROR for x <= 0.

Square root and magnitude

qf qf_sqrt(qf x);                 // sqrt(x), returns QF_DOMAIN_ERROR for x < 0
qf qf_hypot(qf x, qf y);         // sqrt(x^2 + y^2) via qf_sqrt
qf qf_hypot_fast2(qf x, qf y);   // 2-segment piecewise-linear (~1.4% peak error)
qf qf_hypot_fast8(qf x, qf y);   // 8-segment piecewise-linear (~0.10% peak error)

qf_hypot_fast8 uses the same algorithm as FR_hypot_fast8 (based on US Patent 6,567,777 B1, Chatterjee, expired). No division required.

Wave generators

All take a uint16_t BAM phase (0..65535 = one full cycle) and return qf in [-1, 1] (except tri_morph: [0, 1]). Excluded in lean build.

qf qf_wave_sqr(uint16_t phase);
qf qf_wave_pwm(uint16_t phase, uint16_t duty);
qf qf_wave_tri(uint16_t phase);
qf qf_wave_saw(uint16_t phase);
qf qf_wave_tri_morph(uint16_t phase, uint16_t break_point);
qf qf_wave_noise(uint32_t *state);

Phase increment helper

#define QF_HZ2BAM_INC(hz, sample_rate)

Compute a per-sample BAM phase increment for a given frequency and sample rate:

uint16_t phase = 0;
uint16_t inc = QF_HZ2BAM_INC(440, 48000);
for (...) { sample = qf_sin_bam(phase); phase += inc; }

ADSR envelope generator

Same lifecycle as fr_math’s fr_adsr_t but with qf levels in [0.0, 1.0]. Excluded in lean build.

typedef struct qf_adsr_s {
    uint8_t state;
    qf      level;
    qf      sustain;
    qf      attack_inc;
    qf      decay_dec;
    qf      release_dec;
} qf_adsr_t;

void qf_adsr_init(qf_adsr_t *env,
                   uint32_t attack_samples,
                   uint32_t decay_samples,
                   qf sustain_level,
                   uint32_t release_samples);
void qf_adsr_trigger(qf_adsr_t *env);
void qf_adsr_release(qf_adsr_t *env);
qf   qf_adsr_step(qf_adsr_t *env);

State constants

ConstantValue
QF_ADSR_IDLE0
QF_ADSR_ATTACK1
QF_ADSR_DECAY2
QF_ADSR_SUSTAIN3
QF_ADSR_RELEASE4

Usage

qf_adsr_t env;
qf_adsr_init(&env, 1000, 500, 0.7f, 2000);
qf_adsr_trigger(&env);
for (...) sample *= qf_adsr_step(&env);
qf_adsr_release(&env);
for (...) sample *= qf_adsr_step(&env);

Domain error sentinel

#define QF_DOMAIN_ERROR (-1.0e30f)

Returned by qf_sqrt (negative input), qf_log2 / qf_ln / qf_log10 (non-positive input). Not a NaN; compare with ==.

Lean build mode

#define QF_MATH_LEAN

Define before including qf_math.h (or pass -DQF_MATH_LEAN to the compiler) to compile the lean float core: radian trig, inverse trig, log2/ln, pow2/exp/pow, sqrt, and qf_hypot_fast8. It omits degree/BAM trig entry points, exact qf_hypot, qf_hypot_fast2, log10, pow10, wave generators, and ADSR.

The compile-time flag QF_MATH_LEAN_BUILD is set to 1 when lean mode is active, 0 otherwise.

C++ wrapper (qf_math.hpp)

src/qf_math.hpp is a header-only C++ facade over the C API. It adds no storage, allocation, exceptions, RTTI, or new runtime dependencies.

Everything lives in namespace qf_math:

#include "qf_math.hpp"

auto y = qf_math::sin(1.0f);
auto len = qf_math::hypot(dx, dy);

qf_math::adsr env(1000, 500, 0.7f, 2000);
env.trigger();
for (...) sample *= env.step();

Version macros

#define QF_MATH_VERSION      "1.0.1"
#define QF_MATH_VERSION_HEX   0x010001