File dp_syncword.h¶
File List > inc > dp_syncword.h
Go to the documentation of this file
#ifndef DP_SYNCWORD_H
#define DP_SYNCWORD_H
#include <math.h>
#include "clib_common.h"
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
size_t offset;
int inverted;
unsigned errors;
} dp_syncword_hit_t;
static inline int
dp_syncword_find (const uint8_t *bits, size_t n_bits, const uint8_t *marker,
size_t n_marker, unsigned max_errors,
dp_syncword_hit_t *hit)
{
if (n_marker == 0u || n_bits < n_marker)
return 0;
const size_t last = n_bits - n_marker;
for (size_t off = 0; off <= last; off++)
{
/* Both polarities in one pass: a bit that disagrees with the marker
agrees with its complement, so the two distances sum to the marker
length and one comparison yields both. */
unsigned d = 0;
for (size_t i = 0; i < n_marker; i++)
d += (unsigned)((bits[off + i] & 1u) ^ (marker[i] & 1u));
const unsigned dinv = (unsigned)n_marker - d;
if (d <= max_errors || dinv <= max_errors)
{
const int inv = dinv < d;
hit->offset = off;
hit->inverted = inv;
hit->errors = inv ? dinv : d;
return 1;
}
}
return 0;
}
static inline double
dp_syncword_pfa (size_t n_marker, unsigned max_errors)
{
if (n_marker == 0u)
return 0.0;
const double n = (double)n_marker;
const double lgn1 = dp_lgamma (n + 1.0);
const double lg2 = n * log (2.0);
const size_t t_max = (size_t)max_errors < n_marker ? (size_t)max_errors
: n_marker;
double s = 0.0;
for (size_t i = 0; i <= t_max; i++)
s += exp (lgn1 - dp_lgamma ((double)i + 1.0)
- dp_lgamma (n - (double)i + 1.0) - lg2);
const double p = 2.0 * s;
return p > 1.0 ? 1.0 : p;
}
static inline int
dp_syncword_max_errors (size_t n_marker, size_t window_bits, double pfa)
{
int best = -1;
for (size_t t = 0; t <= n_marker; t++)
{
const double p = dp_syncword_pfa (n_marker, (unsigned)t);
/* -expm1(W log1p(-p)) is 1 - (1-p)^W without cancelling to zero at
the small p that a usable threshold actually produces. */
const double win = -expm1 ((double)window_bits * log1p (-p));
if (win > pfa)
break;
best = (int)t;
}
return best;
}
#ifdef __cplusplus
}
#endif
#endif /* DP_SYNCWORD_H */