Added belief propagation decoder as per WSJT-X
This commit is contained in:
parent
db8f28dd8b
commit
a8d963cdfd
4 changed files with 214 additions and 146 deletions
|
@ -192,15 +192,15 @@ uint8_t max2(uint8_t a, uint8_t b) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t max4(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
|
uint8_t max4(uint8_t a, uint8_t b, uint8_t cand, uint8_t d) {
|
||||||
return max2(max2(a, b), max2(c, d));
|
return max2(max2(a, b), max2(cand, d));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Compute log likelihood log(p(0) / p(1)) of 174 message bits
|
// Compute log likelihood log(p(1) / p(0)) of 174 message bits
|
||||||
// for later use in soft-decision LDPC decoding
|
// for later use in soft-decision LDPC decoding
|
||||||
void extract_likelihood(const uint8_t * power, int num_bins, const Candidate & c, float * log174) {
|
void extract_likelihood(const uint8_t * power, int num_bins, const Candidate & cand, float * log174) {
|
||||||
int offset = (c.time_offset * 4 + c.time_sub * 2 + c.freq_sub) * num_bins + c.freq_offset;
|
int offset = (cand.time_offset * 4 + cand.time_sub * 2 + cand.freq_sub) * num_bins + cand.freq_offset;
|
||||||
|
|
||||||
int k = 0;
|
int k = 0;
|
||||||
// Go over FSK tones and skip Costas sync symbols
|
// Go over FSK tones and skip Costas sync symbols
|
||||||
|
@ -212,9 +212,9 @@ void extract_likelihood(const uint8_t * power, int num_bins, const Candidate & c
|
||||||
|
|
||||||
// Extract bit significance (and convert them to float)
|
// Extract bit significance (and convert them to float)
|
||||||
// 8 FSK tones = 3 bits
|
// 8 FSK tones = 3 bits
|
||||||
log174[k + 0] = -(int)max4(ps[4], ps[5], ps[6], ps[7]) + (int)max4(ps[0], ps[1], ps[2], ps[3]);
|
log174[k + 0] = (int)max4(ps[4], ps[5], ps[6], ps[7]) - (int)max4(ps[0], ps[1], ps[2], ps[3]);
|
||||||
log174[k + 1] = -(int)max4(ps[2], ps[3], ps[6], ps[7]) + (int)max4(ps[0], ps[1], ps[4], ps[5]);
|
log174[k + 1] = (int)max4(ps[2], ps[3], ps[6], ps[7]) - (int)max4(ps[0], ps[1], ps[4], ps[5]);
|
||||||
log174[k + 2] = -(int)max4(ps[1], ps[3], ps[5], ps[7]) + (int)max4(ps[0], ps[2], ps[4], ps[6]);
|
log174[k + 2] = (int)max4(ps[1], ps[3], ps[5], ps[7]) - (int)max4(ps[0], ps[2], ps[4], ps[6]);
|
||||||
// printf("%d %d %d %d %d %d %d %d : %.0f %.0f %.0f\n",
|
// printf("%d %d %d %d %d %d %d %d : %.0f %.0f %.0f\n",
|
||||||
// ps[0], ps[1], ps[2], ps[3], ps[4], ps[5], ps[6], ps[7],
|
// ps[0], ps[1], ps[2], ps[3], ps[4], ps[5], ps[6], ps[7],
|
||||||
// log174[k + 0], log174[k + 1], log174[k + 2]);
|
// log174[k + 0], log174[k + 1], log174[k + 2]);
|
||||||
|
@ -270,29 +270,31 @@ int main(int argc, char ** argv) {
|
||||||
|
|
||||||
extract_power(signal, num_blocks, num_bins, power);
|
extract_power(signal, num_blocks, num_bins, power);
|
||||||
|
|
||||||
const int num_candidates = 250;
|
int num_candidates = 250;
|
||||||
Candidate heap[num_candidates];
|
Candidate heap[num_candidates];
|
||||||
|
|
||||||
find_sync(power, num_blocks, num_bins, num_candidates, heap);
|
find_sync(power, num_blocks, num_bins, num_candidates, heap);
|
||||||
|
|
||||||
for (int i = 0; i < num_candidates; ++i) {
|
for (int idx = 0; idx < num_candidates; ++idx) {
|
||||||
float freq_hz = (heap[i].freq_offset + heap[i].freq_sub / 2.0f) * fsk_dev;
|
Candidate &cand = heap[idx];
|
||||||
float time_sec = (heap[i].time_offset + heap[i].time_sub / 2.0f) / fsk_dev;
|
float freq_hz = (cand.freq_offset + cand.freq_sub / 2.0f) * fsk_dev;
|
||||||
|
float time_sec = (cand.time_offset + cand.time_sub / 2.0f) / fsk_dev;
|
||||||
// printf("%03d: score = %d freq = %.1f time = %.2f\n", i,
|
// printf("%03d: score = %d freq = %.1f time = %.2f\n", i,
|
||||||
// heap[i].score, freq_hz, time_sec);
|
// heap[i].score, freq_hz, time_sec);
|
||||||
|
|
||||||
float log174[3 * ND];
|
float log174[3 * ND];
|
||||||
extract_likelihood(power, num_bins, heap[i], log174);
|
extract_likelihood(power, num_bins, cand, log174);
|
||||||
|
|
||||||
const int num_iters = 10;
|
const int num_iters = 20;
|
||||||
int plain[3 * ND];
|
int plain[3 * ND];
|
||||||
int ok;
|
int ok;
|
||||||
|
|
||||||
ldpc_decode(log174, num_iters, plain, &ok);
|
bp_decode(log174, num_iters, plain, &ok);
|
||||||
|
//ldpc_decode(log174, num_iters, plain, &ok);
|
||||||
//printf("ldpc_decode() = %d\n", ok);
|
//printf("ldpc_decode() = %d\n", ok);
|
||||||
if (ok == 87) {
|
if (ok == 87) {
|
||||||
printf("%03d: score = %d freq = %.1f time = %.2f\n", i,
|
printf("%03d: score = %d freq = %.1f time = %.2f\n", idx,
|
||||||
heap[i].score, freq_hz, time_sec);
|
cand.score, freq_hz, time_sec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
20
ft8/arrays.h
20
ft8/arrays.h
|
@ -1,7 +1,9 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
// LDPC(174,87) parameters from WSJT-X.
|
// LDPC(174,87) parameters from WSJT-X.
|
||||||
// this is an indirection table that moves a
|
// this is an indirection table that moves a
|
||||||
// codeword's 87 systematic (message) bits to the end.
|
// codeword's 87 systematic (message) bits to the end.
|
||||||
int colorder[] = {
|
uint8_t colorder[] = {
|
||||||
0, 1, 2, 3, 30, 4, 5, 6, 7, 8, 9, 10, 11, 32, 12, 40, 13, 14, 15, 16,
|
0, 1, 2, 3, 30, 4, 5, 6, 7, 8, 9, 10, 11, 32, 12, 40, 13, 14, 15, 16,
|
||||||
17, 18, 37, 45, 29, 19, 20, 21, 41, 22, 42, 31, 33, 34, 44, 35, 47,
|
17, 18, 37, 45, 29, 19, 20, 21, 41, 22, 42, 31, 33, 34, 44, 35, 47,
|
||||||
51, 50, 43, 36, 52, 63, 46, 25, 55, 27, 24, 23, 53, 39, 49, 59, 38,
|
51, 50, 43, 36, 52, 63, 46, 25, 55, 27, 24, 23, 53, 39, 49, 59, 38,
|
||||||
|
@ -21,7 +23,7 @@ int colorder[] = {
|
||||||
// each number is an index into the codeword (1-origin).
|
// each number is an index into the codeword (1-origin).
|
||||||
// the codeword bits mentioned in each row must xor to zero.
|
// the codeword bits mentioned in each row must xor to zero.
|
||||||
// From WSJT-X's bpdecode174.f90.
|
// From WSJT-X's bpdecode174.f90.
|
||||||
int Nm[][7] = {
|
uint8_t Nm[][7] = {
|
||||||
{1, 30, 60, 89, 118, 147, 0},
|
{1, 30, 60, 89, 118, 147, 0},
|
||||||
{2, 31, 61, 90, 119, 147, 0},
|
{2, 31, 61, 90, 119, 147, 0},
|
||||||
{3, 32, 62, 91, 120, 148, 0},
|
{3, 32, 62, 91, 120, 148, 0},
|
||||||
|
@ -116,7 +118,7 @@ int Nm[][7] = {
|
||||||
// the numbers indicate which three parity
|
// the numbers indicate which three parity
|
||||||
// checks (rows in Nm) refer to the codeword bit.
|
// checks (rows in Nm) refer to the codeword bit.
|
||||||
// 1-origin.
|
// 1-origin.
|
||||||
int Mn[][3] = {
|
uint8_t Mn[][3] = {
|
||||||
{1, 25, 69},
|
{1, 25, 69},
|
||||||
{2, 5, 73},
|
{2, 5, 73},
|
||||||
{3, 32, 68},
|
{3, 32, 68},
|
||||||
|
@ -292,3 +294,15 @@ int Mn[][3] = {
|
||||||
{54, 61, 71},
|
{54, 61, 71},
|
||||||
{46, 58, 69},
|
{46, 58, 69},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
uint8_t nrw[] = {
|
||||||
|
6,6,6,6,6,6,6,6,6,6,
|
||||||
|
6,6,6,6,6,6,6,6,6,6,
|
||||||
|
6,6,6,6,6,6,6,6,6,6,
|
||||||
|
6,6,6,6,6,6,6,6,6,7,
|
||||||
|
6,6,6,6,6,7,6,6,6,6,
|
||||||
|
6,6,6,6,6,7,6,6,6,6,
|
||||||
|
7,6,5,6,6,6,6,6,6,5,
|
||||||
|
6,6,6,6,6,6,6,6,6,6,
|
||||||
|
5,6,6,6,5,6,6
|
||||||
|
};
|
||||||
|
|
296
ft8/ldpc.cpp
296
ft8/ldpc.cpp
|
@ -16,6 +16,13 @@
|
||||||
|
|
||||||
int ldpc_check(int codeword[]);
|
int ldpc_check(int codeword[]);
|
||||||
|
|
||||||
|
const int N = 174;
|
||||||
|
const int M = 87;
|
||||||
|
|
||||||
|
// https://varietyofsound.wordpress.com/2011/02/14/efficient-tanh-computation-using-lamberts-continued-fraction/
|
||||||
|
// http://functions.wolfram.com/ElementaryFunctions/ArcTanh/10/0001/
|
||||||
|
// https://mathr.co.uk/blog/2017-09-06_approximating_hyperbolic_tangent.html
|
||||||
|
|
||||||
|
|
||||||
// thank you Douglas Bagnall
|
// thank you Douglas Bagnall
|
||||||
// https://math.stackexchange.com/a/446411
|
// https://math.stackexchange.com/a/446411
|
||||||
|
@ -27,69 +34,127 @@ float fast_tanh(float x) {
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
float x2 = x * x;
|
float x2 = x * x;
|
||||||
float a = x * (135135.0f + x2 * (17325.0f + x2 * (378.0f + x2)));
|
//float a = x * (135135.0f + x2 * (17325.0f + x2 * (378.0f + x2)));
|
||||||
float b = 135135.0f + x2 * (62370.0f + x2 * (3150.0f + x2 * 28.0f));
|
//float b = 135135.0f + x2 * (62370.0f + x2 * (3150.0f + x2 * 28.0f));
|
||||||
|
//float a = x * (10395.0f + x2 * (1260.0f + x2 * 21.0f));
|
||||||
|
//float b = 10395.0f + x2 * (4725.0f + x2 * (210.0f + x2));
|
||||||
|
float a = x * (945.0f + x2 * (105.0f + x2));
|
||||||
|
float b = 945.0f + x2 * (420.0f + x2 * 15.0f);
|
||||||
return a / b;
|
return a / b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float fast_atanh(float x) {
|
||||||
|
float x2 = x * x;
|
||||||
|
//float a = x * (-15015.0f + x2 * (19250.0f + x2 * (-5943.0f + x2 * 256.0f)));
|
||||||
|
//float b = (-15015.0f + x2 * (24255.0f + x2 * (-11025.0f + x2 * 1225.0f)));
|
||||||
|
//float a = x * (-1155.0f + x2 * (1190.0f + x2 * -231.0f));
|
||||||
|
//float b = (-1155.0f + x2 * (1575.0f + x2 * (-525.0f + x2 * 25.0f)));
|
||||||
|
float a = x * (945.0f + x2 * (-735.0f + x2 * 64.0f));
|
||||||
|
float b = (945.0f + x2 * (-1050.0f + x2 * 225.0f));
|
||||||
|
return a / b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float pltanh(float x) {
|
||||||
|
float isign = +1;
|
||||||
|
if (x < 0) {
|
||||||
|
isign = -1;
|
||||||
|
x = -x;
|
||||||
|
}
|
||||||
|
if (x < 0.8f) {
|
||||||
|
return isign * 0.83 * x;
|
||||||
|
}
|
||||||
|
if (x < 1.6f) {
|
||||||
|
return isign * (0.322f * x + 0.4064f);
|
||||||
|
}
|
||||||
|
if (x < 3.0f) {
|
||||||
|
return isign * (0.0524f * x + 0.8378f);
|
||||||
|
}
|
||||||
|
if (x < 7.0f) {
|
||||||
|
return isign * (0.0012f * x + 0.9914f);
|
||||||
|
}
|
||||||
|
return isign*0.9998f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float platanh(float x) {
|
||||||
|
float isign = +1;
|
||||||
|
if (x < 0) {
|
||||||
|
isign = -1;
|
||||||
|
x = -x;
|
||||||
|
}
|
||||||
|
if (x < 0.664f) {
|
||||||
|
return isign * x / 0.83f;
|
||||||
|
}
|
||||||
|
if (x < 0.9217f) {
|
||||||
|
return isign * (x - 0.4064f) / 0.322f;
|
||||||
|
}
|
||||||
|
if (x < 0.9951f) {
|
||||||
|
return isign * (x - 0.8378f) / 0.0524f;
|
||||||
|
}
|
||||||
|
if (x < 0.9998f) {
|
||||||
|
return isign * (x - 0.9914f) / 0.0012f;
|
||||||
|
}
|
||||||
|
return isign * 7.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// codeword is 174 log-likelihoods.
|
// codeword is 174 log-likelihoods.
|
||||||
// plain is a return value, 174 ints, to be 0 or 1.
|
// plain is a return value, 174 ints, to be 0 or 1.
|
||||||
// iters is how hard to try.
|
// max_iters is how hard to try.
|
||||||
// ok == 87 means success.
|
// ok == 87 means success.
|
||||||
void ldpc_decode(float codeword[], int iters, int plain[], int *ok) {
|
void ldpc_decode(float codeword[], int max_iters, int plain[], int *ok) {
|
||||||
float m[87][174]; // ~60 kB
|
float m[M][N]; // ~60 kB
|
||||||
float e[87][174]; // ~60 kB
|
float e[M][N]; // ~60 kB
|
||||||
int best_score = -1;
|
int best_score = -1;
|
||||||
int best_cw[174];
|
|
||||||
|
|
||||||
for (int i = 0; i < 174; i++) {
|
for (int j = 0; j < M; j++) {
|
||||||
for (int j = 0; j < 87; j++) {
|
for (int i = 0; i < N; i++) {
|
||||||
m[j][i] = codeword[i];
|
m[j][i] = codeword[i];
|
||||||
e[j][i] = 0.0f;
|
e[j][i] = 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int iter = 0; iter < iters; iter++) {
|
for (int iter = 0; iter < max_iters; iter++) {
|
||||||
for (int j = 0; j < 87; j++) {
|
for (int j = 0; j < M; j++) {
|
||||||
for (int ii1 = 0; ii1 < 7; ii1++) {
|
for (int ii1 = 0; ii1 < nrw[j]; ii1++) {
|
||||||
int i1 = Nm[j][ii1] - 1;
|
int i1 = Nm[j][ii1] - 1;
|
||||||
if (i1 < 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
float a = 1.0f;
|
float a = 1.0f;
|
||||||
for (int ii2 = 0; ii2 < 7; ii2++) {
|
for (int ii2 = 0; ii2 < nrw[j]; ii2++) {
|
||||||
int i2 = Nm[j][ii2] - 1;
|
int i2 = Nm[j][ii2] - 1;
|
||||||
if (i2 >= 0 && i2 != i1) {
|
if (i2 != i1) {
|
||||||
a *= fast_tanh(m[j][i2] / 2.0f);
|
a *= fast_tanh(-m[j][i2] / 2.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
e[j][i1] = logf((1 + a) / (1 - a));
|
e[j][i1] = logf((1 - a) / (1 + a));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int cw[174];
|
int cw[N];
|
||||||
for (int i = 0; i < 174; i++) {
|
for (int i = 0; i < N; i++) {
|
||||||
float l = codeword[i];
|
float l = codeword[i];
|
||||||
for (int j = 0; j < 3; j++)
|
for (int j = 0; j < 3; j++)
|
||||||
l += e[Mn[i][j] - 1][i];
|
l += e[Mn[i][j] - 1][i];
|
||||||
cw[i] = (l <= 0.0f);
|
cw[i] = (l > 0) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int score = ldpc_check(cw);
|
int score = ldpc_check(cw);
|
||||||
|
|
||||||
if (score > best_score) {
|
if (score > best_score) {
|
||||||
for (int i = 0; i < 174; i++) {
|
for (int i = 0; i < N; i++) {
|
||||||
best_cw[i] = cw[i];
|
plain[i] = cw[colorder[i]];
|
||||||
}
|
}
|
||||||
best_score = score;
|
best_score = score;
|
||||||
|
|
||||||
|
if (score == M) {
|
||||||
|
// Found a perfect answer
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (score == 87) {
|
|
||||||
// Found a perfect answer
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < 174; i++) {
|
for (int i = 0; i < N; i++) {
|
||||||
for (int ji1 = 0; ji1 < 3; ji1++) {
|
for (int ji1 = 0; ji1 < 3; ji1++) {
|
||||||
int j1 = Mn[i][ji1] - 1;
|
int j1 = Mn[i][ji1] - 1;
|
||||||
float l = codeword[i];
|
float l = codeword[i];
|
||||||
|
@ -104,17 +169,6 @@ void ldpc_decode(float codeword[], int iters, int plain[], int *ok) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// decode complete (perhaps partially)
|
|
||||||
#if 0
|
|
||||||
for(int i = 0; i < 87; i++) {
|
|
||||||
plain[i] = best_cw[colorder[174-87+i]];
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
for (int i = 0; i < 174; i++) {
|
|
||||||
plain[i] = best_cw[colorder[i]];
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
*ok = best_score;
|
*ok = best_score;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,108 +182,104 @@ int ldpc_check(int codeword[]) {
|
||||||
int score = 0;
|
int score = 0;
|
||||||
|
|
||||||
// Nm[87][7]
|
// Nm[87][7]
|
||||||
for (int j = 0; j < 87; j++) {
|
for (int j = 0; j < M; ++j) {
|
||||||
int x = 0;
|
int x = 0;
|
||||||
for (int ii1 = 0; ii1 < 7; ii1++) {
|
for (int ii1 = 0; ii1 < nrw[j]; ++ii1) {
|
||||||
int i1 = Nm[j][ii1] - 1;
|
x ^= codeword[Nm[j][ii1] - 1];
|
||||||
if (i1 >= 0) {
|
|
||||||
x ^= codeword[i1];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (x == 0) {
|
if (x == 0) {
|
||||||
score++;
|
++score;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return score;
|
return score;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
void bp_decode(float codeword[], int max_iters, int plain[], int *ok) {
|
||||||
def bp_decode(codeword, max_iterations = 10):
|
float tov[N][3];
|
||||||
## 174 codeword bits
|
float toc[M][7];
|
||||||
## 87 parity checks
|
|
||||||
|
|
||||||
mnx = numpy.array(Mn, dtype=numpy.int32)
|
int best_score = -1;
|
||||||
nmx = numpy.array(Nm, dtype=numpy.int32)
|
|
||||||
|
|
||||||
ncw = 3
|
int nclast = 0;
|
||||||
tov = numpy.zeros( (3, N) )
|
int ncnt = 0;
|
||||||
toc = numpy.zeros( (7, M) )
|
|
||||||
tanhtoc = numpy.zeros( (7, M) )
|
|
||||||
zn = numpy.zeros(N)
|
|
||||||
nclast = 0
|
|
||||||
ncnt = 0
|
|
||||||
|
|
||||||
# initialize messages to checks
|
// initialize messages to checks
|
||||||
for j in range(M):
|
for (int i = 0; i < M; ++i) {
|
||||||
for i in range(nrw[j]):
|
for (int j = 0; j < nrw[i]; ++j) {
|
||||||
toc[i, j] = codeword[nmx[j, i] - 1]
|
toc[i][j] = codeword[Nm[i][j] - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for iteration in range(max_iterations):
|
for (int i = 0; i < N; ++i) {
|
||||||
# Update bit log likelihood ratios (tov=0 in iteration 0).
|
for (int j = 0; j < 3; ++j) {
|
||||||
#for i in range(N):
|
tov[i][j] = 0;
|
||||||
# zn[i] = codeword[i] + numpy.sum(tov[:,i])
|
}
|
||||||
zn = codeword + numpy.sum(tov, axis = 0)
|
}
|
||||||
#print(numpy.sum(tov, axis=0))
|
|
||||||
|
|
||||||
# Check to see if we have a codeword (check before we do any iteration).
|
for (int iter = 0; iter < max_iters; ++iter) {
|
||||||
cw = numpy.zeros(N, dtype=numpy.int32)
|
float zn[N];
|
||||||
cw[zn > 0] = 1
|
int cw[N];
|
||||||
ncheck = 0
|
|
||||||
for i in range(M):
|
|
||||||
synd = numpy.sum(cw[ nmx[i, :nrw[i]]-1 ])
|
|
||||||
if synd % 2 > 0:
|
|
||||||
ncheck += 1
|
|
||||||
|
|
||||||
if ncheck == 0:
|
// Update bit log likelihood ratios (tov=0 in iter 0)
|
||||||
# we have a codeword - reorder the columns and return it
|
for (int i = 0; i < N; ++i) {
|
||||||
codeword = cw[colorder]
|
zn[i] = codeword[i] + tov[i][0] + tov[i][1] + tov[i][2];
|
||||||
#nerr = 0
|
cw[i] = (zn[i] > 0) ? 1 : 0;
|
||||||
#for i in range(N):
|
}
|
||||||
# if (2*cw[i]-1)*codeword[i] < 0:
|
|
||||||
# nerr += 1
|
|
||||||
|
|
||||||
#print("DECODED!", nerr)
|
// Check to see if we have a codeword (check before we do any iter)
|
||||||
return codeword[M:N]
|
int score = ldpc_check(cw);
|
||||||
|
|
||||||
if iter > 0:
|
if (score > best_score) {
|
||||||
# this code block implements an early stopping criterion
|
// we have a better guess - reorder the columns and store it
|
||||||
nd = ncheck - nclast
|
for (int i = 0; i < N; i++) {
|
||||||
if nd < 0: # of unsatisfied parity checks decreased
|
plain[i] = cw[colorder[i]];
|
||||||
ncnt = 0 # reset counter
|
}
|
||||||
else:
|
best_score = score;
|
||||||
ncnt += 1
|
|
||||||
|
|
||||||
if ncnt >= 5 and iter >= 10 and ncheck >= 15:
|
if (score == M) {
|
||||||
nharderror = -1
|
break;
|
||||||
#return numpy.array([])
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nclast = ncheck
|
// Send messages from bits to check nodes
|
||||||
|
for (int i = 0; i < M; ++i) {
|
||||||
|
for (int j = 0; j < nrw[i]; ++j) {
|
||||||
|
int ibj = Nm[i][j] - 1;
|
||||||
|
toc[i][j] = zn[ibj];
|
||||||
|
for (int kk = 0; kk < 3; ++kk) {
|
||||||
|
// subtract off what the bit had received from the check
|
||||||
|
if (Mn[ibj][kk] - 1 == i) {
|
||||||
|
toc[i][j] -= tov[ibj][kk];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# Send messages from bits to check nodes
|
// send messages from check nodes to variable nodes
|
||||||
for j in range(M):
|
for (int i = 0; i < M; ++i) {
|
||||||
for i in range(nrw[j]):
|
for (int j = 0; j < nrw[i]; ++j) {
|
||||||
ibj = nmx[j, i] - 1
|
//toc[i][j] = pltanh(-toc[i][j] / 2);
|
||||||
toc[i, j] = zn[ibj]
|
toc[i][j] = fast_tanh(-toc[i][j] / 2);
|
||||||
for kk in range(ncw): # subtract off what the bit had received from the check
|
//toc[i][j] = tanhf(-toc[i][j] / 2);
|
||||||
if mnx[ibj, kk] - 1 == j:
|
}
|
||||||
toc[i, j] -= tov[kk, ibj]
|
}
|
||||||
|
|
||||||
# send messages from check nodes to variable nodes
|
for (int i = 0; i < N; ++i) {
|
||||||
#for i in range(M):
|
for (int j = 0; j < 3; ++j) {
|
||||||
# tanhtoc[:,i] = numpy.tanh(-toc[:,i] / 2)
|
int ichk = Mn[i][j] - 1; // Mn(:,j) are the checks that include bit j
|
||||||
tanhtoc = numpy.tanh(-toc / 2)
|
float Tmn = 1.0f;
|
||||||
|
for (int k = 0; k < nrw[ichk]; ++k) {
|
||||||
|
if (Nm[ichk][k] - 1 != i) {
|
||||||
|
Tmn *= toc[ichk][k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//tov[i][j] = 2 * platanh(-Tmn);
|
||||||
|
tov[i][j] = 2 * fast_atanh(-Tmn);
|
||||||
|
//tov[i][j] = 2 * atanhf(-Tmn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for j in range(N):
|
*ok = best_score;
|
||||||
for i in range(ncw):
|
}
|
||||||
ichk = mnx[j, i] - 1 # Mn(:,j) are the checks that include bit j
|
|
||||||
Tmn = 1.0
|
|
||||||
for k in range(nrw[ichk]):
|
|
||||||
if nmx[ichk, k] - 1 == j: continue
|
|
||||||
Tmn *= tanhtoc[k, ichk]
|
|
||||||
y = numpy.arctanh(-Tmn)
|
|
||||||
#y = platanh(-Tmn)
|
|
||||||
tov[i, j] = 2*y
|
|
||||||
|
|
||||||
return numpy.array([])
|
|
||||||
*/
|
|
||||||
|
|
|
@ -4,4 +4,6 @@
|
||||||
// plain is a return value, 174 ints, to be 0 or 1.
|
// plain is a return value, 174 ints, to be 0 or 1.
|
||||||
// iters is how hard to try.
|
// iters is how hard to try.
|
||||||
// ok == 87 means success.
|
// ok == 87 means success.
|
||||||
void ldpc_decode(float codeword[], int iters, int plain[], int *ok);
|
void ldpc_decode(float codeword[], int max_iters, int plain[], int *ok);
|
||||||
|
|
||||||
|
void bp_decode(float codeword[], int max_iters, int plain[], int *ok);
|
||||||
|
|
Loading…
Reference in a new issue