File clib_common.h¶
FileList > inc > clib_common.h
Go to the source code of this file
#include <complex.h>#include <stddef.h>#include <stdint.h>#include <math.h>#include <stdlib.h>#include <string.h>#include "jm_perf.h"
Public Functions¶
| Type | Name |
|---|---|
| JM_FORCEINLINE double | dp_fmod_pos (double x, double m) x folded into[0, m) for either sign ofx . |
| double | dp_lgamma (double x) log|Gamma(x)|, reentrant the one spelling of lgamma in this library. |
Public Static Functions¶
| Type | Name |
|---|---|
| double | dp_fftfreq (size_t bin, size_t n, double fs) The frequency of an FFT bin, in the units of fs . |
| long | dp_fftfreq_index (size_t bin, size_t n) numpy.fft.fftfreq(n)[bin] * n — the SIGNED index of an FFT bin. |
| void * | dp_xcalloc (size_t nmemb, size_t size) |
| void * | dp_xmalloc (size_t n) |
| void * | dp_xnn (void * p) |
| void * | dp_xrealloc (void * p, size_t n) |
Macros¶
| Type | Name |
|---|---|
| define | CMPLXF (r, i) \_\_builtin\_complex ((float)(r), (float)(i)) |
| define | DP_ERR_CLOSED (-9) |
| define | DP_ERR_EOF (-10) |
| define | DP_ERR_INIT (-1) |
| define | DP_ERR_INTERRUPTED (-8) |
| define | DP_ERR_INVALID (-4) |
| define | DP_ERR_MEMORY (-6) |
| define | DP_ERR_RECV (-3) |
| define | DP_ERR_SEND (-2) |
| define | DP_ERR_TIMEOUT (-5) |
| define | DP_ERR_TOO_LARGE (-7) |
| define | DP_OK 0 |
Public Functions Documentation¶
function dp_fmod_pos¶
x folded into[0, m) for either sign ofx .
C's fmod() keeps the dividend's sign, so a negative x comes back in (-m, 0] and every caller that wants a phase, a frequency or an index on a periodic axis has to add m back. That fix-up had been written by hand five times in this library a code phase in chips, a harmonic into the analysed band, a table index, the DLL's replica tap and a hand-over phase before this became its one home (doppler#1249); the gate scripts/check_fmod_fold_sites.py fails on the sixth.
External inline (JM_FORCEINLINE), not static inline like its neighbours: the DLL's replica tap is an external inline in a header, and C99 6.7.4 forbids such a function from referencing one with internal linkage the compiler said so.
Parameters:
xAny real value.mThe period (> 0).
Returns:
x modulo m, in [0, m).
function dp_lgamma¶
log|Gamma(x)|, reentrant the one spelling oflgamma in this library.
C's lgamma() writes the sign of Gamma into the global signgam, so two threads calling it race on a variable neither of them reads. That is exactly what happens when a pool of receivers rebuilds their tracking chains on different threads at once: every chain sizes a detector threshold through marcum_q(), and ThreadSanitizer stopped the first multi-threaded test on it (doppler#1260). lgamma_r() takes the sign by pointer and touches no global. Declared here and defined in native/src/detection/marcum_q.c (detection_core, which every threshold links) rather than inline, because an installed header may not name libm's lgamma_r the shipped libraries do not define it, and scripts/check_installed_headers.py says so and a strict C99 dialect does not declare it. scripts/check_lgamma_sites.py fails on a bare lgamma in native/inc or native/src.
Parameters:
xAny real value.
Returns:
log|Gamma(x)|, as lgamma() returns it.
Public Static Functions Documentation¶
function dp_fftfreq¶
The frequency of an FFT bin, in the units of fs .
dp_fftfreq_index(bin, n) * fs / n — numpy's fftfreq(n, d)[bin] with the sample RATE where numpy takes the sample SPACING. That is the one deliberate difference from the numpy signature, and it is the right way round for this library: every caller here has fs in hand and would otherwise write 1.0 / fs at the call site, which is a reciprocal to get wrong for no benefit. Pass fs = 1.0 for normalised cycles/sample, which is numpy's default.
Parameters:
binBin index in[0, n).nGrid size (> 0).fsSample rate; the result is in these units.
Returns:
Bin frequency in [-fs/2, +fs/2).
function dp_fftfreq_index¶
numpy.fft.fftfreq(n)[bin] * n — the SIGNED index of an FFT bin.
0 = DC, ascending positive to (n-1)/2, then wrapping negative, so an even-length grid puts its Nyquist bin at -n/2. Multiply by the grid's bin spacing for Hz, or use dp_fftfreq() for the normalised frequency.
Named for what it is. It arrived as an acquisition-specific helper called dp_fftfreq_index, which is how it came to disagree with numpy at exactly one index: it reported +n/2 at the Nyquist bin. That is not wrong on its own +n/2 and -n/2 are the same frequency, and a search on this grid cannot tell them apart but every formula ported in from numpy then disagreed with the engine at the one bin the engine was most careful about. Following the universal convention deletes that class of surprise rather than documenting it.
What must not vary is the READER: a consumer seeded on one side of the fold while the search meant the other is off by the full span. That happened here once an acquisition's wideband search and its hand-off spelled the fold differently and it surfaced as a receiver reporting tracking == 1 while decoding noise. So this lives in the COMMON header, inline, and doppler.dsss.bin_to_signed is a thin wrapper over it, so C and Python call the same code instead of restating the arithmetic.
Parameters:
binBin index in[0, n).nGrid size.
Returns:
Signed index in [-(n/2), +((n-1)/2)].
function dp_xcalloc¶
calloc that aborts on OOM (zero-initialised trusted allocation).
function dp_xmalloc¶
malloc that aborts on OOM (for a trusted internal allocation).
function dp_xnn¶
Assert a just-constructed object / allocation is non-NULL, aborting with a diagnostic on the impossible OOM. The single check point: a sub-object create() returns NULL only on OOM once its arguments are validated, so wrap the call — x = dp_xnn (foo_create (...)) — instead of checking-and-unwinding at every call site. (Classic GNU xmalloc.)
function dp_xrealloc¶
realloc that aborts on OOM — the third member of the family.
A grow-on-demand scratch buffer is the shape that wants it: the new size scales with the caller's block, but the only way the call fails is still genuine exhaustion, so the unwind path is as uncoverable as malloc's. Passing NULL for p is a fresh allocation, exactly as realloc defines.
Macro Definition Documentation¶
define CMPLXF¶
clib_common.h — common C99 types and performance macros for doppler.
define DP_ERR_CLOSED¶
The context is draining or closed and accepts no more sends \ a state, not a transport failure.
define DP_ERR_EOF¶
The producer has finished: no more data is coming, ever. A \ state, not a failure, and distinct from DP_ERR_TIMEOUT, which \ means "not yet". Every transport spells it the same way see \ docs/design/io-termination.md.
define DP_ERR_INIT¶
Initialisation failed (context/socket).
define DP_ERR_INTERRUPTED¶
A blocking call returned because dp_stream_interrupt() was \ called a request to stop, not a failure.
define DP_ERR_INVALID¶
Invalid argument.
define DP_ERR_MEMORY¶
Memory allocation failure.
define DP_ERR_RECV¶
Receive failed or timed out (EAGAIN).
define DP_ERR_SEND¶
Send failed.
define DP_ERR_TIMEOUT¶
Operation timed out.
define DP_ERR_TOO_LARGE¶
Frame exceeds transport max payload.
define DP_OK¶
Success.
The documentation for this class was generated from the following file native/inc/clib_common.h