17 #ifndef LEANSDR_LDPC_H 18 #define LEANSDR_LDPC_H 20 #define lfprintf(...) \ 30 template <
typename Taddr>
51 template <
typename SOFTBIT,
typename SOFTWORD,
int SWSIZE,
typename Taddr>
56 : vnodes(NULL), cnodes(NULL)
70 static const int CHUNK = 4;
73 if (nedges % CHUNK == 0)
75 edges = (Taddr *)realloc(edges, (nedges + CHUNK) *
sizeof(Taddr));
93 fatal(
"Bad LDPC word size");
98 if (k != table->
nrows * 360)
101 if (table->
q * 360 != n_k)
104 vnodes =
new node[k];
105 memset(vnodes, 0,
sizeof(
node) * k);
106 cnodes =
new node[n_k];
107 memset(cnodes, 0,
sizeof(
node) * n_k);
120 for (
int mw = 360; mw--; ++m, qoffs +=
q)
122 const Taddr *pa = prow->cols;
123 for (
int nc = prow->ncols; nc--; ++pa)
125 int a = (int)*pa + qoffs;
129 fail(
"Invalid LDPC table");
139 int nedges = count_edges(vnodes, k);
140 fprintf(stderr,
"LDPC(%5d,%5d)(%.2f)" 141 " %5.2f edges/vnode, %5.2f edges/cnode\n",
142 k, n - k, (
float)k / n, (
float)nedges / k, (
float)nedges / (n - k));
148 for (
int i = 0;
i < nnodes; ++
i)
149 c += nodes[
i].nedges;
161 if ( 360 % SWSIZE )
fatal(
"Bad LDPC word size");
162 if ( k % SWSIZE )
fatal(
"Bad LDPC k");
163 if ( n % SWSIZE )
fatal(
"Bad LDPC n");
164 if ( k != table->
nrows*360 )
fatal(
"Bad table");
166 if ( table->
q*360 != n_k )
fatal(
"Bad q");
177 for (
int mw=360/SWSIZE; mw--; ++msg ) {
178 SOFTWORD msgword = *msg;
179 for (
int wbit=0; wbit<SWSIZE; ++wbit,qoffs+=
q ) {
181 if ( ! msgbit )
continue;
182 const Taddr *pa = prow->cols;
183 for (
int nc=prow->ncols; nc--; ++pa ) {
185 int a = (int)*pa + qoffs;
187 if ( a >= n_k ) a -= n_k;
195 integrate_bits(parity, parity, n_k/SWSIZE);
200 int k,
int n, SOFTWORD *parity,
int integrate =
true)
204 fatal(
"Bad LDPC word size");
209 if (k != table->
nrows * 360)
212 if (table->
q * 360 != n_k)
215 for (
int i = 0;
i < n_k / SWSIZE; ++
i)
226 for (
int mw = 360 / SWSIZE; mw--; ++msg)
228 SOFTWORD msgword = *msg;
229 for (
int wbit = 0; wbit < SWSIZE; ++wbit, qoffs +=
q)
234 const Taddr *pa = prow->cols;
235 for (
int nc = prow->ncols; nc--; ++pa)
237 int a = (int)*pa + qoffs;
248 integrate_bits(parity, parity, n_k / SWSIZE);
256 static const int PPCM = 39;
261 score_t *score,
int k)
264 memset(score, 0, k *
sizeof(*score));
265 for (
int c = 0; c < nc; ++c)
270 Taddr *pe = cnodes[c].
edges;
271 for (
int e = cnodes[c].nedges; e--; ++pe)
274 int s = err * softwords_weight<SOFTBIT, SOFTWORD>(m, v) * PPCM / vnodes[v].nedges;
290 fail(
"LDPC graph not initialized");
294 SOFTWORD *expected =
new SOFTWORD[n_k / SWSIZE];
295 encode(table, cw, k, n, expected,
false);
297 SOFTWORD *received =
new SOFTWORD[n_k / SWSIZE];
298 diff_bits(cw + k / SWSIZE, received, n_k / SWSIZE);
301 score_t *score =
new score_t[k];
302 score_t tots = compute_scores(cw, expected, received, n_k, score, k);
303 lfprintf(stderr,
"Initial score %d\n", (
int)tots);
307 score_t score_threshold;
311 score_threshold = (int)one * 2;
314 bool progress =
true;
315 while (progress && nflipped < max_bitflips)
321 for (
int b = 0; b < n - k - 1; ++b)
327 lfprintf(stderr,
"flip parity %d\n", b);
335 Taddr *pe = cnodes[b].
edges;
336 for (
int e = cnodes[b].nedges; e--; ++pe)
338 int d = prev_err * softwords_weight<SOFTBIT, SOFTWORD>(cw, *pe) * PPCM / vnodes[*pe].nedges;
344 Taddr *pe = cnodes[b + 1].
edges;
345 for (
int e = cnodes[b + 1].nedges; e--; ++pe)
347 int d = err * softwords_weight<SOFTBIT, SOFTWORD>(cw, *pe) * PPCM / vnodes[*pe].nedges;
362 score_t maxs = -(1 << 30);
363 for (
int v = 0; v < k; ++v)
368 lfprintf(stderr,
"maxs %d\n", (
int)maxs);
370 for (
int v = 0; v < k; ++v)
372 if (score[v] < score_threshold)
375 if (score[v] < maxs - 4)
377 lfprintf(stderr,
" flip %d score=%d\n", (
int)v, (
int)score[v]);
380 for (
int commit = 0; commit <= 1; ++commit)
382 Taddr *pe = vnodes[v].
edges;
383 for (
int e = vnodes[v].nedges; e--; ++pe)
389 Taddr *pe = cnodes[c].
edges;
390 for (
int e = cnodes[c].nedges; e--; ++pe)
392 int d = was_bad * softwords_weight<SOFTBIT, SOFTWORD>(cw, *pe) * PPCM / vnodes[*pe].nedges;
403 Taddr *pe = cnodes[c].
edges;
404 for (
int e = cnodes[c].nedges; e--; ++pe)
406 int d = is_bad * softwords_weight<SOFTBIT, SOFTWORD>(cw, *pe) * PPCM / vnodes[*pe].nedges;
434 lfprintf(stderr,
"progress %d\n", progress);
436 fprintf(stderr,
"CHECKING TOTS INCREMENT (slow) %d\n", tots);
437 score_t tots2 = compute_scores(cw, expected, received, n_k, score, k);
438 if ( tots2 != tots )
fail(
"bad tots update");
457 for (
int i = 0;
i < nwords; ++
i)
460 for (
int b = 0; b < SWSIZE; ++b)
470 static void integrate_bits(
const uint8_t *in,
uint8_t *out,
int nwords)
474 for (
int i = 0;
i < nwords; ++
i)
477 for (
int j = SWSIZE; j--;)
491 static void diff_bits(
const SOFTWORD *in, SOFTWORD *out,
int nwords)
495 for (
int i = 0;
i < nwords; ++
i, ++in, ++out)
498 for (
int b = 0; b < SWSIZE; ++b)
509 static void diff_bits(
const uint8_t *in,
uint8_t *out,
int nwords)
512 for (
int i = 0;
i < nwords; ++
i)
515 out[
i] = c ^ (prev | (c >> 1));
516 prev = (c & 1) << (SWSIZE - 1);
525 #endif // LEANSDR_LDPC_H
void softword_write(hard_sb &p, int b, bool v)
bool softwords_xor(const hard_sb p1[], const hard_sb p2[], int b)
score_t compute_scores(SOFTWORD *m, SOFTWORD *p, SOFTWORD *q, int nc, score_t *score, int k)
bool softbit_harden(bool b)
ldpc_engine(const ldpc_table< Taddr > *table, int _k, int _n)
static void integrate_bits(const SOFTWORD *in, SOFTWORD *out, int nwords)
void softwords_flip(hard_sb p[], int b)
void softbit_clear(bool *p)
void encode(const ldpc_table< Taddr > *table, const SOFTWORD *msg, int k, int n, SOFTWORD *parity, int integrate=true)
static const int MAX_ROWS
static const int MAX_COLS
int count_edges(node *nodes, int nnodes)
void fatal(const char *s)
void softword_zero(hard_sb *p)
int decode_bitflip(const ldpc_table< Taddr > *table, SOFTWORD *cw, int k, int n, int max_bitflips)
struct leansdr::ldpc_table::row rows[MAX_ROWS]
unsigned char parity(uint8_t x)
bool softbit_xor(bool x, bool y)
static void diff_bits(const SOFTWORD *in, SOFTWORD *out, int nwords)
void softbit_set(bool *p, bool v)
bool softword_get(const hard_sb &p, int b)