Skip to content

File clib_common.h

File List > inc > clib_common.h

Go to the documentation of this file

#ifndef DOPPLER_CLIB_COMMON_H
#define DOPPLER_CLIB_COMMON_H

#include <complex.h>
#include <stddef.h>
#include <stdint.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>

/* CMPLXF is C11 but missing on MinGW/ucrt64.  __builtin_complex is
 * the GCC-portable way to construct a complex value without relying
 * on _Complex_I (which can propagate NaN in some implementations). */
#ifndef CMPLXF
#  define CMPLXF(r, i) __builtin_complex ((float)(r), (float)(i))
#endif

/* ------------------------------------------------------------------ */
/* Return-code convention                                              */
/*                                                                     */
/* int-returning functions use these codes.  0 is always success.     */
/* size_t-returning functions return a sample/byte count; they        */
/* operate on already-created objects and cannot fail.                */
/* Pointer-returning functions return NULL on failure.                */
/*                                                                     */
/* This is the single, doppler-wide error vocabulary.  The streaming   */
/* API (stream/stream.h) includes this header for the same codes — one */
/* scheme everywhere, so a value never means two things in one TU.     */
/* Not every code is meaningful to every subsystem (the core DSP path  */
/* only ever returns DP_OK / DP_ERR_MEMORY / DP_ERR_INVALID).          */
/* ------------------------------------------------------------------ */
#define DP_OK 0             
#define DP_ERR_INIT (-1)    
#define DP_ERR_SEND (-2)    
#define DP_ERR_RECV (-3)    
#define DP_ERR_INVALID (-4) 
#define DP_ERR_TIMEOUT (-5) 
#define DP_ERR_MEMORY (-6)  
#define DP_ERR_TOO_LARGE (-7) 
#define DP_ERR_INTERRUPTED                                                    \
  (-8) 
#define DP_ERR_CLOSED                                                         \
  (-9) 
#define DP_ERR_EOF                                                            \
  (-10) 
#include "jm_perf.h"

/* ------------------------------------------------------------------ */
/* Trusted allocation                                                  */
/*                                                                     */
/* A small, fixed-size, internally-sized allocation with already-      */
/* validated arguments cannot fail in practice; the only way malloc /  */
/* a sub-object create() returns NULL is genuine OOM, an unrecoverable  */
/* condition for a compute kernel. Rather than thread a per-call unwind */
/* path no test can reach (and that inflates every create() with        */
/* uncoverable cleanup), route such allocations through these helpers:  */
/* they abort() immediately on the impossible failure. This is the      */
/* doppler-wide convention for trusted internal allocations — see the   */
/* "trust internal guarantees" rule. (Reachable failures — invalid      */
/* user arguments — still return NULL / DP_ERR_INVALID as before; only  */
/* the OOM path aborts.)                                                 */
/* ------------------------------------------------------------------ */

static inline void *
dp_xnn (void *p)
{
  if (!p)
    abort ();
  return p;
}

static inline void *
dp_xmalloc (size_t n)
{
  return dp_xnn (malloc (n));
}

static inline void *
dp_xcalloc (size_t nmemb, size_t size)
{
  return dp_xnn (calloc (nmemb, size));
}

static inline void *
dp_xrealloc (void *p, size_t n)
{
  return dp_xnn (realloc (p, n));
}

static inline long
dp_fftfreq_index (size_t bin, size_t n)
{
  return (bin <= (n - 1) / 2) ? (long)bin : (long)bin - (long)n;
}

static inline double
dp_fftfreq (size_t bin, size_t n, double fs)
{
  return (n == 0) ? 0.0 : (double)dp_fftfreq_index (bin, n) * fs / (double)n;
}

JM_FORCEINLINE double
dp_fmod_pos (double x, double m)
{
  double r = fmod (x, m);
  return r < 0.0 ? r + m : r;
}

double dp_lgamma (double x);

#endif /* DOPPLER_CLIB_COMMON_H */