File syn_qmath.h¶
File List > src > syntropic > util > syn_qmath.h
Go to the documentation of this file
#ifndef SYN_QMATH_H
#define SYN_QMATH_H
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/* ── Q16.16 type ────────────────────────────────────────────────────────── */
typedef int32_t q16_t;
#define Q16_SHIFT 16
#define Q16_ONE ((q16_t)(1L << Q16_SHIFT))
#define Q16_HALF ((q16_t)(1L << (Q16_SHIFT - 1)))
/* ── Constants ──────────────────────────────────────────────────────────── */
#define Q16_PI 205887
#define Q16_PI_2 102944
#define Q16_2_PI 411775
#define Q16_E 178145
#define Q16_LN2 45426
#define Q16_SQRT2 92682
/* ── Conversion macros ──────────────────────────────────────────────────── */
#define Q16_FROM_INT(n) ((q16_t)((int32_t)(n) * Q16_ONE))
#define Q16_FROM_FRAC(num, den) \
((q16_t)(((int64_t)((uint64_t)(int64_t)(num) << Q16_SHIFT)) / (den)))
#define Q16_FROM_FLOAT(f) ((q16_t)((f) * (1L << Q16_SHIFT)))
#define Q16_TO_INT(q) ((int32_t)((q) >> Q16_SHIFT))
#define Q16_TO_INT_ROUND(q) ((int32_t)(((q) + Q16_HALF) >> Q16_SHIFT))
#define Q16_FRAC_1000(q) ((int32_t)((((q) & 0xFFFF) * 1000L) >> Q16_SHIFT))
#define Q16_FRAC_10000(q) ((int32_t)((((q) & 0xFFFF) * 10000L) >> Q16_SHIFT))
/* ── Inline arithmetic ──────────────────────────────────────────────────── */
static inline q16_t q16_mul(q16_t a, q16_t b)
{
#if defined(__arm__) && defined(__GNUC__) && !defined(__SOFTFP__)
int32_t res_lo, res_hi;
__asm__("smull %0, %1, %2, %3" : "=r"(res_lo), "=r"(res_hi) : "r"(a), "r"(b));
return (q16_t)(((uint32_t)res_lo >> 16) | ((uint32_t)res_hi << 16));
#else
return (q16_t)(((int64_t)a * b) >> Q16_SHIFT);
#endif
}
static inline q16_t q16_div(q16_t a, q16_t b)
{
if (b == 0) {
return (a >= 0) ? INT32_MAX : INT32_MIN;
}
return (q16_t)(((int64_t)((uint64_t)(int64_t)a << Q16_SHIFT)) / b);
}
static inline q16_t q16_add(q16_t a, q16_t b)
{
return a + b;
}
static inline q16_t q16_sub(q16_t a, q16_t b)
{
return a - b;
}
static inline q16_t q16_abs(q16_t a)
{
return (a < 0) ? -a : a;
}
static inline q16_t q16_add_sat(q16_t a, q16_t b)
{
int64_t r = (int64_t)a + b;
if (r > INT32_MAX)
return INT32_MAX;
if (r < INT32_MIN)
return INT32_MIN;
return (q16_t)r;
}
static inline q16_t q16_sub_sat(q16_t a, q16_t b)
{
int64_t r = (int64_t)a - b;
if (r > INT32_MAX)
return INT32_MAX;
if (r < INT32_MIN)
return INT32_MIN;
return (q16_t)r;
}
static inline q16_t q16_mul_sat(q16_t a, q16_t b)
{
int64_t r = ((int64_t)a * b) >> Q16_SHIFT;
if (r > INT32_MAX)
return INT32_MAX;
if (r < INT32_MIN)
return INT32_MIN;
return (q16_t)r;
}
static inline q16_t q16_lerp(q16_t a, q16_t b, q16_t t)
{
return a + q16_mul(b - a, t);
}
static inline q16_t q16_clamp(q16_t val, q16_t lo, q16_t hi)
{
if (val < lo)
return lo;
if (val > hi)
return hi;
return val;
}
/* ── Transcendental functions (compiled in syn_qmath.c) ─────────────────── */
uint32_t syn_isqrt32(uint32_t n);
uint64_t syn_isqrt64(uint64_t n);
q16_t q16_sin(q16_t x);
q16_t q16_cos(q16_t x);
q16_t q16_sin_fast(q16_t x);
q16_t q16_cos_fast(q16_t x);
void q16_sincos_fast(q16_t x, q16_t *sin_out, q16_t *cos_out);
q16_t q16_tan(q16_t x);
q16_t q16_atan2(q16_t y, q16_t x);
q16_t q16_asin(q16_t x);
q16_t q16_acos(q16_t x);
q16_t q16_sqrt(q16_t x);
q16_t q16_inv(q16_t x);
q16_t q16_rsqrt(q16_t x);
q16_t q16_hypot(q16_t x, q16_t y);
q16_t q16_exp(q16_t x);
q16_t q16_exp_fast(q16_t x);
q16_t q16_log(q16_t x);
q16_t q16_log_fast(q16_t x);
q16_t q16_pow(q16_t base, q16_t exp);
q16_t q16_floor(q16_t x);
q16_t q16_ceil(q16_t x);
q16_t q16_round(q16_t x);
q16_t q16_poly_eval(const q16_t *coeffs, uint8_t n, q16_t x);
/* ── String I/O (compiled in syn_qmath.c) ───────────────────────────────── */
size_t q16_to_str(q16_t val, char *buf, size_t buf_len, uint8_t decimals);
size_t q16_from_str(const char *str, q16_t *out);
#ifdef __cplusplus
}
#endif
#endif /* SYN_QMATH_H */