Quick Start
Include and compile
Copy src/qf_math.c and src/qf_math.h into the project. Compile qf_math.c as a single translation unit alongside application code. No external dependencies — no -lm required.
gcc -std=c99 -Os main.c qf_math.c -o main
#include "qf_math.h"
All functions take and return qf (a typedef for float).
Trigonometry
Three input conventions: radians, degrees, and BAM (Binary Angular Measure, where uint16_t 65536 = one full revolution).
/* Radians */
qf y = qf_sin(1.0f); /* 0.8415 */
qf x = qf_cos(1.0f); /* 0.5403 */
qf t = qf_tan(0.5f); /* 0.5463 */
/* Degrees */
qf s45 = qf_sin_deg(45.0f); /* 0.7071 */
qf c60 = qf_cos_deg(60.0f); /* 0.5000 */
/* BAM (16384 = 90 deg) */
qf s90 = qf_sin_bam(16384); /* 1.0000 (exact) */
Inverse trig
qf angle = qf_asin(0.5f); /* 0.5236 rad (30 deg) */
qf angle = qf_acos(0.5f); /* 1.0472 rad (60 deg) */
qf angle = qf_atan2(3.0f, 4.0f); /* 0.6435 rad */
Log, exp, pow
qf l2 = qf_log2(8.0f); /* 3.0 */
qf l = qf_ln(2.71828f); /* 1.0 */
qf l10 = qf_log10(1000.0f); /* 3.0 */
qf p2 = qf_pow2(3.0f); /* 8.0 */
qf e1 = qf_exp(1.0f); /* 2.7183 */
qf p = qf_pow(2.0f, 10.0f); /* 1024.0 */
Sqrt and hypot
qf r = qf_sqrt(2.0f); /* 1.4142 */
qf h = qf_hypot(3.0f, 4.0f); /* 5.0000 */
qf hf = qf_hypot_fast8(3.0f, 4.0f); /* 5.0015 (0.1% worst-case error, faster) */
Utility macros
qf rad = QF_DEG_TO_RAD(180.0f); /* 3.1416 */
qf deg = QF_RAD_TO_DEG(QF_PI); /* 180.0 */
qf c = QF_CLAMP(5.0f, 0.0f, 3.0f); /* 3.0 */
qf mid = QF_INTERP(0.0f, 10.0f, 0.25f); /* 2.5 */
Waveform generators
All waveforms use uint16_t BAM phase (0–65535 = one cycle) and return values in [−1, +1].
qf sq = qf_wave_sqr(8192); /* +1.0 (first half) */
qf tr = qf_wave_tri(16384); /* +1.0 (peak) */
qf sw = qf_wave_saw(32768); /* 0.0 (midpoint) */
uint32_t noise_state = 12345;
qf n = qf_wave_noise(&noise_state); /* pseudo-random in [-1, 1] */
Phase increment for a given frequency:
uint16_t inc = QF_HZ2BAM_INC(440, 48000); /* 440 Hz at 48 kHz sample rate */
ADSR envelope
qf_adsr_t env;
qf_adsr_init(&env, 1000, 500, 0.7f, 2000); /* attack, decay, sustain, release (samples) */
qf_adsr_trigger(&env);
for (int i = 0; i < num_samples; i++) {
sample[i] *= qf_adsr_step(&env);
}
qf_adsr_release(&env); /* begin release phase */
Fixed-radix bridge (qf_math ↔ fr_math)
Convert between float and fixed-radix integers at system boundaries:
int32_t fr = QF_TO_FR(1.234f, 16); /* float → Q16.16 (truncating) */
int32_t fr = QF_TO_FR_RND(1.234f, 16); /* float → Q16.16 (rounding) */
qf back = FR_TO_QF(80871, 16); /* Q16.16 → float */
Domain errors
Functions with restricted domains (qf_sqrt of negative, qf_log2 of non-positive) return QF_DOMAIN_ERROR (−1e30f).
qf bad = qf_sqrt(-1.0f);
if (bad == QF_DOMAIN_ERROR) { /* handle error */ }
Runnable example
A complete working program is in examples/quickstart/. Build with make and run ./quickstart.