diff --git a/lib/qra/qra65/main.c b/lib/qra/qra65/main.c
new file mode 100644
index 000000000..8205ff508
--- /dev/null
+++ b/lib/qra/qra65/main.c
@@ -0,0 +1,436 @@
+// main.c
+// QRA65 mode encode/decode test
+//
+// (c) 2016 - Nico Palermo, IV3NWV
+//
+// Thanks to Andrea Montefusco IW0HDV for his help on adapting the sources
+// to OSs other than MS Windows
+//
+// ------------------------------------------------------------------------------
+// This file is part of the qracodes project, a Forward Error Control
+// encoding/decoding package based on Q-ary RA (Repeat and Accumulate) LDPC codes.
+//
+// Files in this package:
+// main.c - this file
+// qra65.c/.h - qra65 mode encode/decoding functions
+//
+// ..\qracodes\normrnd.c/.h - random gaussian number generator
+// ..\qracodes\npfwht.c/.h - Fast Walsh-Hadamard Transforms
+// ..\qracodes\pdmath.c/.h - Elementary math on probability distributions
+// ..\qracodes\qra12_63_64_irr_b.c/.h - Tables for a QRA(12,63) irregular RA code over GF(64)
+// ..\qracodes\qra13_64_64_irr_e.c/.h - Tables for a QRA(13,64) irregular RA code " "
+// ..\qracodes\qracodes.c/.h - QRA codes encoding/decoding functions
+//
+// -------------------------------------------------------------------------------
+//
+// qracodes is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+// qracodes is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with qracodes source distribution.
+// If not, see .
+
+// -----------------------------------------------------------------------------
+
+// The code used by the QRA65 mode is the code:
+// QRA13_64_64_IRR_E: K=13 N=64 Q=64 irregular QRA code (defined in qra13_64_64_irr_e.h /.c)
+// This code has been designed to include a CRC as the 13th information symbol
+// and improve the code UER (Undetected Error Rate).
+// The CRC symbol is not sent along the channel (the codes are punctured) and the
+// resulting code is still a (12,63) code with an effective code rate of R = 12/63.
+
+// ------------------------------------------------------------------------------
+
+// OS dependent defines and includes --------------------------------------------
+
+#if _WIN32 // note the underscore: without it, it's not msdn official!
+ // Windows (x64 and x86)
+ #include // required only for GetTickCount(...)
+ #include // _beginthread
+#endif
+
+#if __linux__
+#include
+#include
+
+unsigned GetTickCount(void) {
+ struct timespec ts;
+ unsigned theTick = 0U;
+ clock_gettime( CLOCK_REALTIME, &ts );
+ theTick = ts.tv_nsec / 1000000;
+ theTick += ts.tv_sec * 1000;
+ return theTick;
+}
+#endif
+
+#if __APPLE__
+#endif
+
+#include
+#include
+
+#include "qra65.h"
+#include "..\qracodes\normrnd.h" // gaussian numbers generator
+
+// -----------------------------------------------------------------------------------
+
+// channel types
+#define CHANNEL_AWGN 0
+#define CHANNEL_RAYLEIGH 1
+
+void printwordd(char *msg, int *x, int size)
+{
+ int k;
+ printf("\n%s ",msg);
+ for (k=0;k=0) { // decoded
+ printf("K1JT rx: received with apcode=%d %s\n",rc, decode_type[rc]);
+ // K1JT replies to IV3NWV (with no grid)
+ printf("K1JT tx: IV3NWV K1JT\n");
+ encodemsg_jt65(x,CALL_IV3NWV,CALL_K1JT, GRID_BLANK);
+ qra65_encode(codec_k1jt, y, x);
+ r = mfskchannel(y,channel_type,EbNodB);
+
+ // IV3NWV attempts to decode
+ rc = qra65_decode(codec_iv3nwv, xdec,r);
+ if (rc>=0) { // decoded
+ printf("IV3NWV rx: received with apcode=%d %s\n",rc, decode_type[rc]);
+ // IV3NWV replies to K1JT with a 73
+ printf("IV3NWV tx: K1JT IV3NWV 73\n");
+ encodemsg_jt65(x,CALL_K1JT,CALL_IV3NWV, GRID_73);
+ qra65_encode(codec_iv3nwv, y, x);
+ r = mfskchannel(y,channel_type,EbNodB);
+
+ // K1JT attempts to decode
+ rc = qra65_decode(codec_k1jt, xdec,r);
+ if (rc>=0) { // decoded
+ printf("K1JT rx: received with apcode=%d %s\n",rc, decode_type[rc]);
+ // K1JT replies to IV3NWV with a 73
+ printf("K1JT tx: IV3NWV K1JT 73\n");
+ encodemsg_jt65(x,CALL_IV3NWV,CALL_K1JT, GRID_73);
+ qra65_encode(codec_k1jt, y, x);
+ r = mfskchannel(y,channel_type,EbNodB);
+
+ // IV3NWV attempts to decode
+ rc = qra65_decode(codec_iv3nwv, xdec,r);
+ if (rc>=0) { // decoded
+ printf("IV3NWV rx: received with apcode=%d %s\n",rc, decode_type[rc]);
+ return 0;
+ }
+ }
+ }
+ }
+ printf("the other party did not decode\n");
+ return -1;
+}
+
+int test_proc_2(int channel_type, float EbNodB, int mode)
+{
+
+ // Here we simulate the decoder of K1JT after K1JT has sent a msg [IV3NWV K1JT]
+ // and IV3NWV sends him the msg [K1JT IV3NWV JN66]
+ // If mode=QRA_NOAP, K1JT decoder attempts to decode only msgs of type [? ? ?].
+ // If mode=QRA_AUTOP, K1JT decoder will attempt to decode also the msgs [K1JT IV3NWV] and
+ // [K1JT IV3NWV ?].
+
+ // In the case a decode is successful the return code of the qra65_decode function
+ // indicates the amount of a-priori information required to decode the received message
+ // accordingly to this table:
+ // rc=0 [? ? ?] AP0
+ // rc=1 [CQ ? ?] AP27
+ // rc=2 [CQ ? ] AP44
+ // rc=3 [CALL ? ?] AP29
+ // rc=4 [CALL ? ] AP45
+ // rc=5 [CALL CALL ?] AP57
+ // The return code is <0 when decoding is unsuccessful
+
+ // This test simulates the situation ntx times and reports how many times
+ // a particular type decode among the above 6 cases succeded.
+
+ int x[QRA65_K], xdec[QRA65_K];
+ int y[QRA65_N];
+ float *r;
+ int rc,k;
+
+ int ndecok[6] = { 0, 0, 0, 0, 0, 0};
+ int ntx = 100,ndec=0;
+
+ qra65codec *codec_iv3nwv = qra65_init(mode,CALL_IV3NWV); // codec for IV3NWV
+ qra65codec *codec_k1jt = qra65_init(mode,CALL_K1JT); // codec for K1JT
+
+ // this will enable k1jt's decoder to look for iv3nwv calls
+ encodemsg_jt65(x,CALL_IV3NWV,CALL_K1JT,GRID_BLANK);
+ qra65_encode(codec_k1jt, y, x);
+ printf("K1JT tx: IV3NWV K1JT\n");
+
+ // iv3nwv reply to k1jt
+ printf("IV3NWV tx: K1JT IV3NWV JN66\n");
+ encodemsg_jt65(x,CALL_K1JT,CALL_IV3NWV,GRID_JN66);
+ qra65_encode(codec_iv3nwv, y, x);
+
+ printf("Simulating decodes by K1JT up to AP56 ...");
+
+ for (k=0;k=0)
+ ndecok[rc]++;
+ }
+ printf("\n");
+
+ printf("Transimtted:%d - Decoded:\n",ntx);
+ for (k=0;k<6;k++) {
+ printf("%3d with %s\n",ndecok[k],decode_type[k]);
+ ndec += ndecok[k];
+ }
+ printf("Total: %d/%d\n",ndec,ntx);
+ printf("\n");
+
+ return 0;
+}
+
+void syntax(void)
+{
+ printf("\nQRA65 Mode Tests\n");
+ printf("2016, Nico Palermo - IV3NWV\n\n");
+ printf("---------------------------\n\n");
+ printf("Syntax: qra65 [-s] [-c] [-a] [-t] [-h]\n");
+ printf("Options: \n");
+ printf(" -s : set simulation SNR in 2500 Hz BW (default:-27.5 dB)\n");
+ printf(" -c : set channel type 0=AWGN (default) 1=Rayleigh\n");
+ printf(" -a : set decode type 0=NO_AP 1=AUTO_AP (default)\n");
+ printf(" -t: 0=simulate seq of msgs between IV3NWV and K1JT (default)\n");
+ printf(" 1=simulate K1JT receiving K1JT IV3NWV JN66\n");
+ printf(" -h: this help\n");
+}
+
+int main(int argc, char* argv[])
+{
+ int k, rc, nok=0;
+
+ float SNRdB = -27.5f;
+ unsigned int channel = CHANNEL_AWGN;
+ unsigned int mode = QRA_AUTOAP;
+ unsigned int testtype=0;
+ int nqso = 100;
+
+ float EbNodB;
+
+ // parse command line
+ while(--argc) {
+ argv++;
+ if (strncmp(*argv,"-h",2)==0) {
+ syntax();
+ return 0;
+ }
+ else
+ if (strncmp(*argv,"-a",2)==0) {
+ mode = (unsigned int)atoi((*argv)+2);
+ if (mode>1) {
+ printf("Invalid decoding mode\n");
+ syntax();
+ return -1;
+ }
+ }
+ else
+ if (strncmp(*argv,"-s",2)==0) {
+ SNRdB = (float)atof((*argv)+2);
+ if (SNRdB>0 || SNRdB<-40) {
+ printf("SNR should be in the range [-40..0]\n");
+ syntax();
+ return -1;
+ }
+ }
+ else
+ if (strncmp(*argv,"-t",2)==0) {
+ testtype = (unsigned int)atoi((*argv)+2);
+ if (testtype>1) {
+ printf("Invalid test type\n");
+ syntax();
+ return -1;
+ }
+ }
+ else
+ if (strncmp(*argv,"-c",2)==0) {
+ channel = (unsigned int)atoi((*argv)+2);
+ if (channel>CHANNEL_RAYLEIGH) {
+ printf("Invalid channel type\n");
+ syntax();
+ return -1;
+ }
+ }
+ else {
+ printf("Invalid option\n");
+ syntax();
+ return -1;
+ }
+ }
+
+ EbNodB = SNRdB+29.1f;
+
+ if (testtype==0) {
+ for (k=0;k.
+
+// -----------------------------------------------------------------------------
+
+// Code used in this sowftware release:
+
+// QRA13_64_64_IRR_E: K=13 N=64 Q=64 irregular QRA code (defined in qra13_64_64_irr_e.h /.c)
+
+// Codes with K=13 are designed to include a CRC as the 13th information symbol
+// and improve the code UER (Undetected Error Rate).
+// The CRC symbol is not sent along the channel (the codes are punctured) and the
+// resulting code is a (12,63) code
+
+// ------------------------------------------------------------------------------
+
+#include
+#include
+
+#include "qra65.h"
+#include "..\qracodes\qracodes.h"
+#include "..\qracodes\qra13_64_64_irr_e.h"
+#include "..\qracodes\pdmath.h"
+
+// Code parameters of the QRA65 mode
+#define QRA65_CODE qra_13_64_64_irr_e
+#define QRA65_NMSG 218 // this must much the value indicated in QRA65_CODE.NMSG
+
+#define QRA65_KC (QRA65_K+1) // information symbols crc included (as defined in the code)
+#define QRA65_NC (QRA65_N+1) // codeword length (as defined in the code)
+#define QRA65_NITER 100 // max number of iterations per decode
+
+
+
+// static functions declarations -------------------------------------------------
+static int calc_crc6(const int *x, int sz);
+static void ix_mask(float *dst, const float *src, const int *mask, const int *x);
+static int qra65_do_decode(int *x, const float *pix, const int *ap_mask, const int *ap_x);
+
+// a-priori information masks for fields in jt65-like msgs -----------------------
+
+#define MASK_CQQRZ 0xFFFFFFC // CQ/QRZ calls common bits
+#define MASK_CALL1 0xFFFFFFF
+#define MASK_CALL2 0xFFFFFFF
+#define MASK_GRIDFULL 0xFFFF
+#define MASK_GRIDBIT 0x8000 // b[15] is 0 for all the messages which are not text
+
+// -------------------------------------------------------------------------------
+
+qra65codec *qra65_init(int flags, const int mycall)
+{
+
+ // Eb/No value for which we optimize the decoder metric
+ const float EbNodBMetric = 2.8f;
+ const float EbNoMetric = (float)pow(10,EbNodBMetric/10);
+ const float R = 1.0f*(QRA65_KC)/(QRA65_NC);
+
+ qra65codec *pcodec = (qra65codec*)malloc(sizeof(qra65codec));
+
+ if (!pcodec)
+ return 0; // can't allocate memory
+
+ pcodec->decEsNoMetric = 1.0f*QRA65_m*R*EbNoMetric;
+ pcodec->apflags = flags;
+
+ if (flags!=QRA_AUTOAP)
+ return pcodec;
+
+ // initialize messages and mask for decoding with a-priori information
+
+ pcodec->apmycall = mycall;
+ pcodec->apsrccall = 0;
+
+ // encode CQ/QRZ messages and masks
+ // NOTE: Here we handle only CQ and QRZ msgs
+ // 'CQ nnn', 'CQ DX' and 'DE' msgs
+ // will be handled by the decoder as messages with no a-priori knowledge
+ encodemsg_jt65(pcodec->apmsg_cqqrz, CALL_CQ, 0, GRID_BLANK);
+ encodemsg_jt65(pcodec->apmask_cqqrz, MASK_CQQRZ,0, MASK_GRIDBIT); // AP27 (26+1)
+ encodemsg_jt65(pcodec->apmask_cqqrz_ooo, MASK_CQQRZ,0, MASK_GRIDFULL); // AP42 (26+16)
+
+ // encode [mycall ? x] messages and set masks
+ encodemsg_jt65(pcodec->apmsg_call1, mycall, 0, GRID_BLANK);
+ encodemsg_jt65(pcodec->apmask_call1, MASK_CALL1, 0, MASK_GRIDBIT); // AP29 (28+1)
+ encodemsg_jt65(pcodec->apmask_call1_ooo, MASK_CALL1, 0, MASK_GRIDFULL); // AP44 (28+16)
+
+ // set mask for [mycall srccall ?] messages
+ encodemsg_jt65(pcodec->apmask_call1_call2,MASK_CALL1, MASK_CALL2, MASK_GRIDBIT); // AP56 (28+28)
+
+ return pcodec;
+}
+
+void qra65_encode(qra65codec *pcodec, int *y, const int *x)
+{
+ int encx[QRA65_KC]; // encoder input buffer
+ int ency[QRA65_NC]; // encoder output buffer
+
+ int call1,call2,grid;
+
+ memcpy(encx,x,QRA65_K*sizeof(int)); // copy input to the encoder buffer
+ encx[QRA65_K]=calc_crc6(encx,QRA65_K); // compute and add the crc symbol
+
+ qra_encode(&QRA65_CODE, ency, encx); // encode msg+crc using the given QRA code
+
+ // copy codeword to output puncturing the crc symbol
+ memcpy(y,ency,QRA65_K*sizeof(int)); // copy the information symbols
+ memcpy(y+QRA65_K,ency+QRA65_KC,QRA65_C*sizeof(int)); // copy the parity check symbols
+
+ if (pcodec->apflags!=QRA_AUTOAP)
+ return;
+
+ // look if the msg sent is a std type message (bit15 of grid field = 0)
+ if ((x[9]&0x80)==1)
+ return; // no, it's a text message
+
+ // it's a [call1 call2 grid] message
+
+ // we assume that call2 is our call (but we don't check it)
+ // call1 the station callsign we are calling or indicates a general call (CQ/QRZ/etc..)
+ decodemsg_jt65(&call1,&call2,&grid,x);
+
+ if ((call1>=CALL_CQ && call1<=CALL_CQ999) || call1==CALL_CQDX || call1==CALL_DE) {
+ // we are making a general call, so we still don't know who can reply us (srccall)
+ // reset apsrccall to 0 so that the decoder won't look for [mycall srccall ?] msgs
+ pcodec->apsrccall = 0;
+ }
+ else {
+ // we are replying someone named call1
+ // set apmsg_call1_call2 so that the decoder will attempt to decode [mycall call1 ?] msgs
+ pcodec->apsrccall = call1;
+ encodemsg_jt65(pcodec->apmsg_call1_call2, pcodec->apmycall, pcodec->apsrccall, 0);
+ }
+
+}
+
+int qra65_decode(qra65codec *pcodec, int *x, const float *rxen)
+{
+ uint k;
+ float *srctmp, *dsttmp;
+ float ix[QRA65_NC*QRA65_M]; // (depunctured) intrisic information to the decoder
+ int rc;
+
+ // sanity check
+ if (QRA65_NMSG!=QRA65_CODE.NMSG)
+ return -16; // QRA65_NMSG define is wrong
+
+ // compute symbols intrinsic probabilities from received energy observations
+ qra_mfskbesselmetric(ix, rxen, QRA65_m, QRA65_N,pcodec->decEsNoMetric);
+
+ // de-puncture observations adding a uniform distribution for the crc symbol ----------
+
+ // move check symbols distributions one symbol towards the end
+ dsttmp = PD_ROWADDR(ix,QRA65_M, QRA65_NC-1); // point to the last symbol prob dist
+ srctmp = dsttmp-QRA65_M; // source is the previous pd
+ for (k=0;k=0) return 0; // successfull decode with 0 ap
+
+ if (pcodec->apflags!=QRA_AUTOAP) return rc; // rc<0 = unsuccessful decode
+
+ // attempt to decode CQ calls
+ rc = qra65_do_decode(x, ix, pcodec->apmask_cqqrz, pcodec->apmsg_cqqrz); // 27 bit AP
+ if (rc>=0) return 1; // decoded [cq/qrz ? ?]
+ rc = qra65_do_decode(x, ix, pcodec->apmask_cqqrz_ooo, pcodec->apmsg_cqqrz); // 44 bit AP
+ if (rc>=0) return 2; // decoded [cq ? ooo]
+
+ // attempt to decode calls directed to us (mycall)
+ rc = qra65_do_decode(x, ix, pcodec->apmask_call1, pcodec->apmsg_call1); // 29 bit AP
+ if (rc>=0) return 3; // decoded [mycall ? ?]
+ rc = qra65_do_decode(x, ix, pcodec->apmask_call1_ooo, pcodec->apmsg_call1); // 45 bit AP
+ if (rc>=0) return 4; // decoded [mycall ? ooo]
+
+ // if apsrccall is set attempt to decode [mycall srccall ?] msgs
+ if (pcodec->apsrccall==0) return rc; // nothing more to do
+
+ rc = qra65_do_decode(x, ix, pcodec->apmask_call1_call2, pcodec->apmsg_call1_call2); // 57 bit AP
+ if (rc>=0) return 5; // decoded [mycall srccall ?]
+
+ return rc;
+}
+
+// static functions definitions ----------------------------------------------------------------
+
+// decode with given a-priori information
+static int qra65_do_decode(int *x, const float *pix, const int *ap_mask, const int *ap_x)
+{
+ int rc;
+ const float *ixsrc;
+ float ix_masked[QRA65_NC*QRA65_M]; // (masked) intrinsic information to the decoder
+ float ex[QRA65_NC*QRA65_M]; // extrinsic information from the decoder
+
+ float v2cmsg[QRA65_NMSG*QRA65_M]; // buffers for the decoder messages
+ float c2vmsg[QRA65_NMSG*QRA65_M];
+ int xdec[QRA65_KC];
+
+ if (ap_mask==NULL) { // no a-priori information
+ ixsrc = pix; // intrinsic source is what passed as argument
+ }
+ else { // a-priori information provided
+ // mask channel observations with a-priori
+ ix_mask(ix_masked,pix,ap_mask,ap_x);
+ ixsrc = ix_masked; // intrinsic source is the masked version
+ }
+
+ // run the decoding algorithm
+ rc = qra_extrinsic(&QRA65_CODE,ex,ixsrc,QRA65_NITER,v2cmsg,c2vmsg);
+ if (rc<0)
+ return -1; // no convergence in given iterations
+
+ // decode
+ qra_mapdecode(&QRA65_CODE,xdec,ex,ixsrc);
+
+ // verify crc
+ if (calc_crc6(xdec,QRA65_K)!=xdec[QRA65_K]) // crc doesn't match (detected error)
+ return -2; // decoding was succesfull but crc doesn't match
+
+ // success. copy decoded message to output buffer
+ memcpy(x,xdec,QRA65_K*sizeof(int));
+
+ return 0;
+
+}
+// crc functions -------------------------------------------------------------------------------
+// crc-6 generator polynomial
+// g(x) = x^6 + a5*x^5 + ... + a1*x + a0
+
+// g(x) = x^6 + x + 1
+#define CRC6_GEN_POL 0x30 // MSB=a0 LSB=a5
+
+// g(x) = x^6 + x^2 + x + 1 (as suggested by Joe. See: https://users.ece.cmu.edu/~koopman/crc/)
+// #define CRC6_GEN_POL 0x38 // MSB=a0 LSB=a5. Simulation results are similar
+
+static int calc_crc6(const int *x, int sz)
+{
+ // todo: compute it faster using a look up table
+ int k,j,t,sr = 0;
+ for (k=0;k>1) ^ CRC6_GEN_POL;
+ else
+ sr = (sr>>1);
+ t>>=1;
+ }
+ }
+ return sr;
+}
+
+static void ix_mask(float *dst, const float *src, const int *mask, const int *x)
+{
+ // mask intrinsic information (channel observations) with a priori knowledge
+
+ uint k,kk, smask;
+ float *row;
+
+ memcpy(dst,src,(QRA65_NC*QRA65_M)*sizeof(float));
+
+ for (k=0;k>22)&0x3F;
+ y[1]= (call1>>16)&0x3F;
+ y[2]= (call1>>10)&0x3F;
+ y[3]= (call1>>4)&0x3F;
+ y[4]= (call1<<2)&0x3F;
+
+ y[4] |= (call2>>26)&0x3F;
+ y[5]= (call2>>20)&0x3F;
+ y[6]= (call2>>14)&0x3F;
+ y[7]= (call2>>8)&0x3F;
+ y[8]= (call2>>2)&0x3F;
+ y[9]= (call2<<4)&0x3F;
+
+ y[9] |= (grid>>12)&0x3F;
+ y[10]= (grid>>6)&0x3F;
+ y[11]= (grid)&0x3F;
+
+}
+void decodemsg_jt65(int *call1, int *call2, int *grid, const int *x)
+{
+ int nc1, nc2, ng;
+
+ nc1 = x[4]>>2;
+ nc1 |= x[3]<<4;
+ nc1 |= x[2]<<10;
+ nc1 |= x[1]<<16;
+ nc1 |= x[0]<<22;
+
+ nc2 = x[9]>>4;
+ nc2 |= x[8]<<2;
+ nc2 |= x[7]<<8;
+ nc2 |= x[6]<<14;
+ nc2 |= x[5]<<20;
+ nc2 |= (x[4]&0x03)<<26;
+
+ ng = x[11];
+ ng |= x[10]<<6;
+ ng |= (x[9]&0x0F)<<12;
+
+ *call1 = nc1;
+ *call2 = nc2;
+ *grid = ng;
+}
+
+
diff --git a/lib/qra/qra65/qra65.h b/lib/qra/qra65/qra65.h
new file mode 100644
index 000000000..25b4b4402
--- /dev/null
+++ b/lib/qra/qra65/qra65.h
@@ -0,0 +1,123 @@
+// qra65.h
+// Encoding/decoding functions for the QRA65 mode
+//
+// (c) 2016 - Nico Palermo, IV3NWV
+// ------------------------------------------------------------------------------
+// This file is part of the qracodes project, a Forward Error Control
+// encoding/decoding package based on Q-ary RA (Repeat and Accumulate) LDPC codes.
+//
+// qracodes is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+// qracodes is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with qracodes source distribution.
+// If not, see .
+
+#ifndef _qra65_h_
+#define _qra65_h_
+
+// qra65_init(...) initialization flags
+#define QRA_NOAP 0 // don't use a-priori knowledge
+#define QRA_AUTOAP 1 // use auto a-priori knowledge
+
+// QRA code parameters
+#define QRA65_K 12 // information symbols
+#define QRA65_N 63 // codeword length
+#define QRA65_C 51 // (number of parity checks C=(N-K))
+#define QRA65_M 64 // code alphabet size
+#define QRA65_m 6 // bits per symbol
+
+// packed predefined callsigns and fields as defined in JT65
+#define CALL_CQ 0xFA08319
+#define CALL_QRZ 0xFA0831A
+#define CALL_CQ000 0xFA0831B
+#define CALL_CQ999 0xFA08702
+#define CALL_CQDX 0x5624C39
+#define CALL_DE 0xFF641D1
+#define GRID_BLANK 0x7E91
+
+typedef struct {
+ float decEsNoMetric;
+ int apflags;
+ int apmycall;
+ int apsrccall;
+ int apmsg_cqqrz[12]; // [cq/qrz ? blank]
+ int apmsg_call1[12]; // [mycall ? blank]
+ int apmsg_call1_call2[12]; // [mycall srccall ?]
+ int apmask_cqqrz[12];
+ int apmask_cqqrz_ooo[12];
+ int apmask_call1[12];
+ int apmask_call1_ooo[12];
+ int apmask_call1_call2[12];
+} qra65codec;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+qra65codec *qra65_init(int flags, const int mycall);
+// QRA65 mode initialization function
+// arguments:
+// flags: set the decoder mode
+// When flags = QRA_NOAP no a-priori information will be used by the decoder
+// When flags = QRA_AUTOAP the decoder will attempt to decode with the amount
+// of available a-priori information
+// mycall: 28-bit packed callsign of the user (as computed by JT65)
+// returns:
+// Pointer to the qra65codec data structure allocated and inizialized by the function
+// this handle should be passed to the encoding/decoding functions
+//
+// 0 if unsuccessful (can't allocate memory)
+// -------------------------------------------------------------------------------------------
+
+void qra65_encode(qra65codec *pcodec, int *y, const int *x);
+// QRA65 mode encoder
+// arguments:
+// pcodec = pointer to a qra65codec data structure as returned by qra65_init
+// x = pointer to the message to encode
+// x must point to an array of integers (i.e. defined as int x[12])
+// y = pointer to the encoded message
+// y must point to an array of integers of lenght 63 (i.e. defined as int y[63])
+// -------------------------------------------------------------------------------------------
+
+int qra65_decode(qra65codec *pcodec, int *x, const float *r);
+// QRA65 mode decoder
+// arguments:
+// pcodec = pointer to a qra65codec data structure as returned by qra65_init
+// x = pointer to the array of integers where the decoded message will be stored
+// x must point to an array of integers (i.e. defined as int x[12])
+// r = pointer to the received symbols energies (squared amplitudes)
+// r must point to an array of QRA65_M*QRA65_N (=64*63=4032) float numbers.
+// The first QRA_M entries should be the energies of the first symbol in the codeword
+// The last QRA_M entries should be the energies of the last symbol in the codeword
+//
+// return code:
+//
+// The return code is <0 when decoding is unsuccessful
+// -16 indicates that the definition of QRA65_NMSG does not match what required by the code
+// If the decoding process is successfull the return code is accordingly to the following table
+// rc=0 [? ? ?] AP0 (decoding with no a-priori)
+// rc=1 [CQ ? ?] AP27
+// rc=2 [CQ ? ] AP44
+// rc=3 [CALL ? ?] AP29
+// rc=4 [CALL ? ] AP45
+// rc=5 [CALL CALL ?] AP57
+// return codes in the range 1-5 indicate the amount of a-priori information which was required
+// to decode the received message and are possible only when the QRA_AUTOAP mode has been enabled.
+// -------------------------------------------------------------------------------------------
+
+// encode/decode std msgs in 12 symbols as done in jt65
+void encodemsg_jt65(int *y, const int call1, const int call2, const int grid);
+void decodemsg_jt65(int *call1, int *call2, int *grid, const int *x);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _qra65_h_
diff --git a/lib/qra/qra65/qra65.vcproj b/lib/qra/qra65/qra65.vcproj
new file mode 100644
index 000000000..64072809a
--- /dev/null
+++ b/lib/qra/qra65/qra65.vcproj
@@ -0,0 +1,245 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/qra/qracodes/ebno10000.txt b/lib/qra/qracodes/ebno10000.txt
new file mode 100644
index 000000000..c41174b93
--- /dev/null
+++ b/lib/qra/qracodes/ebno10000.txt
@@ -0,0 +1,7 @@
+# Eb/No Values to be used during the code simulation
+# Each line of this file indicates the Eb/No value to be simulated (in dB)
+# and the number of errors to be detected by the decoder
+0.6 10000
+1.1 10000
+1.6 10000
+2.1 10000
diff --git a/lib/qra/qracodes/ebnovalues.txt b/lib/qra/qracodes/ebnovalues.txt
new file mode 100644
index 000000000..7dba138f0
--- /dev/null
+++ b/lib/qra/qracodes/ebnovalues.txt
@@ -0,0 +1,15 @@
+# Eb/No Values to be used during the code simulation
+# Each line of this file indicates the Eb/No value to be simulated (in dB)
+# and the number of errors to be detected by the decoder
+1.1 1000
+1.6 1000
+2.1 1000
+2.6 1000
+3.1 1000
+3.6 1000
+4.1 1000
+4.6 1000
+5.1 500
+5.6 200
+6.1 100
+6.6 50
\ No newline at end of file
diff --git a/lib/qra/qracodes/ebnovaluesfast.txt b/lib/qra/qracodes/ebnovaluesfast.txt
new file mode 100644
index 000000000..b057b312d
--- /dev/null
+++ b/lib/qra/qracodes/ebnovaluesfast.txt
@@ -0,0 +1,11 @@
+# Eb/No Values to be used during the code simulation
+# Each line of this file indicates the Eb/No value to be simulated (in dB)
+# and the number of errors to be detected by the decoder
+1.1 500
+1.6 500
+2.1 500
+2.6 500
+3.1 500
+3.6 500
+4.1 200
+4.6 50
diff --git a/lib/qra/qracodes/main.c b/lib/qra/qracodes/main.c
new file mode 100644
index 000000000..0e0861b2c
--- /dev/null
+++ b/lib/qra/qracodes/main.c
@@ -0,0 +1,687 @@
+// main.c
+// Word Error Rate test example for Q-ary RA codes over GF(64)
+//
+// (c) 2016 - Nico Palermo, IV3NWV
+//
+// Thanks to Andrea Montefusco IW0HDV for his help on adapting the sources
+// to OSs other than MS Windows
+//
+// ------------------------------------------------------------------------------
+// This file is part of the qracodes project, a Forward Error Control
+// encoding/decoding package based on Q-ary RA (Repeat and Accumulate) LDPC codes.
+//
+// Files in this package:
+// main.c - this file
+// normrnd.c/.h - random gaussian number generator
+// npfwht.c/.h - Fast Walsh-Hadamard Transforms
+// pdmath.c/.h - Elementary math on probability distributions
+// qra12_63_64_irr_b.c/.h - Tables for a QRA(12,63) irregular RA code over GF(64)
+// qra13_64_64_irr_e.c/.h - Tables for a QRA(13,64) irregular RA code " "
+// qracodes.c/.h - QRA codes encoding/decoding functions
+//
+// -------------------------------------------------------------------------------
+//
+// qracodes is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+// qracodes is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with qracodes source distribution.
+// If not, see .
+
+// -----------------------------------------------------------------------------
+
+// Two codes are available for simulations in this sowftware release:
+
+// QRA12_63_64_IRR_B: K=12 N=63 Q=64 irregular QRA code (defined in qra12_63_64_irr_b.h /.c)
+// QRA13_64_64_IRR_E: K=13 N=64 Q=64 irregular QRA code (defined in qra13_64_64_irr_b.h /.c)
+
+// Codes with K=13 are designed to include a CRC as the 13th information symbol
+// and improve the code UER (Undetected Error Rate).
+// The CRC symbol is not sent along the channel (the codes are punctured) and the
+// resulting code is still a (12,63) code with an effective code rate of R = 12/63.
+
+// ------------------------------------------------------------------------------
+
+// OS dependent defines and includes --------------------------------------------
+
+#if _WIN32 // note the underscore: without it, it's not msdn official!
+ // Windows (x64 and x86)
+ #include // required only for GetTickCount(...)
+ #include // _beginthread
+#endif
+
+#if __linux__
+#include
+#include
+
+unsigned GetTickCount(void) {
+ struct timespec ts;
+ unsigned theTick = 0U;
+ clock_gettime( CLOCK_REALTIME, &ts );
+ theTick = ts.tv_nsec / 1000000;
+ theTick += ts.tv_sec * 1000;
+ return theTick;
+}
+#endif
+
+#if __APPLE__
+#endif
+
+#include
+#include
+
+#include "qracodes.h"
+#include "normrnd.h" // gaussian numbers generator
+#include "pdmath.h" // operations on probability distributions
+
+// defined codes
+#include "qra12_63_64_irr_b.h"
+#include "qra13_64_64_irr_e.h"
+
+// -----------------------------------------------------------------------------------
+
+#define NTHREADS_MAX 24
+
+// channel types
+#define CHANNEL_AWGN 0
+#define CHANNEL_RAYLEIGH 1
+
+// amount of a-priori information provided to the decoder
+#define AP_NONE 0
+#define AP_28 1
+#define AP_44 2
+#define AP_56 3
+
+const char ap_str[4][16] = {
+ "None",
+ "28 bit",
+ "44 bit",
+ "56 bit"
+};
+
+const char fnameout_pfx[2][64] = {
+ "wer-awgn-",
+ "wer-rayleigh-"
+};
+const char fnameout_sfx[4][64] = {
+ "-ap00.txt",
+ "-ap28.txt",
+ "-ap44.txt",
+ "-ap56.txt"
+};
+
+const uint ap_masks_jt65[4][13] = {
+// Each row must be 13 entries long (to handle puntc. codes 13,64)
+// The mask of 13th symbol (crc) is alway initializated to 0
+ // AP0 - no a-priori knowledge
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ // AP28 - 1st field known [cq ? ?] or [dst ? ?]
+ {0x3F,0x3F,0x3F,0x3F,0x3C, 0, 0, 0, 0, 0, 0, 0},
+ // AP44 - 1st and 3rd fields known [cq ? 0] or [dst ? 0]
+ {0x3F,0x3F,0x3F,0x3F,0x3C, 0, 0, 0, 0,0x0F,0x3F,0x3F},
+ // AP56 - 1st and 2nd fields known [dst src ?]
+ {0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x30, 0, 0}
+};
+
+void ix_mask(const qracode *pcode, float *r, const int *mask, const int *x);
+
+void printword(char *msg, int *x, int size)
+{
+ int k;
+ printf("\n%s ",msg);
+ for (k=0;kc msg buffer
+ float *qra_c2vmsg; //[qra_NMSG*qra_M]; MP decoder c->v msg buffer
+ float *rp; // [qra_N*qra_M]; received samples (real component) buffer
+ float *rq; // [qra_N*qra_M]; received samples (imag component) buffer
+ float *chp; //[qra_N]; channel gains (real component) buffer
+ float *chq; //[qra_N]; channel gains (imag component) buffer
+ float *r; //[qra_N*qra_M]; received samples (amplitude) buffer
+ float *ix; // [qra_N*qra_M]; // intrinsic information to the MP algorithm
+ float *ex; // [qra_N*qra_M]; // extrinsic information from the MP algorithm
+
+} wer_test_ds;
+
+typedef void( __cdecl *pwer_test_thread)(wer_test_ds*);
+
+// crc-6 generator polynomial
+// g(x) = x^6 + a5*x^5 + ... + a1*x + a0
+
+// g(x) = x^6 + x + 1
+#define CRC6_GEN_POL 0x30 // MSB=a0 LSB=a5
+
+// g(x) = x^6 + x^2 + x + 1 (as suggested by Joe. See: https://users.ece.cmu.edu/~koopman/crc/)
+// #define CRC6_GEN_POL 0x38 // MSB=a0 LSB=a5. Simulation results are similar
+
+int calc_crc6(int *x, int sz)
+{
+ int k,j,t,sr = 0;
+ for (k=0;k>1) ^ CRC6_GEN_POL;
+ else
+ sr = (sr>>1);
+ t>>=1;
+ }
+ }
+ return sr;
+}
+
+void wer_test_thread(wer_test_ds *pdata)
+{
+ const qracode *pcode=pdata->pcode;
+ const uint qra_K = pcode->K;
+ const uint qra_N = pcode->N;
+ const uint qra_M = pcode->M;
+ const uint qra_m = pcode->m;
+ const uint NSAMPLES = pcode->N*pcode->M;
+
+ const float No = 1.0f; // noise spectral density
+ const float sigma = (float)sqrt(No/2.0f); // std dev of noise I/Q components
+ const float sigmach = (float)sqrt(1/2.0f); // std dev of channel I/Q gains
+
+ // Eb/No value for which we optimize the bessel metric
+ const float EbNodBMetric = 2.8f;
+ const float EbNoMetric = (float)pow(10,EbNodBMetric/10);
+
+ uint k,t,j,diff;
+ float R;
+ float EsNoMetric;
+ float EbNo, EsNo, Es, A;
+ int channel_type, code_type;
+ int nt=0; // transmitted codewords
+ int nerrs = 0; // total number of errors
+ int nerrsu = 0; // number of undetected errors
+ int rc;
+
+
+ // inizialize pointer to required buffers
+ uint *x=pdata->x; // message buffer
+ uint *y=pdata->y, *ydec=pdata->ydec; // encoded/decoded codeword buffers
+ float *qra_v2cmsg=pdata->qra_v2cmsg; // table of the v->c messages
+ float *qra_c2vmsg=pdata->qra_c2vmsg; // table of the c->v messages
+ float *rp=pdata->rp; // received samples (real component)
+ float *rq=pdata->rq; // received samples (imag component)
+ float *chp=pdata->chp; // channel gains (real component)
+ float *chq=pdata->chq; // channel gains (imag component)
+ float *r=pdata->r; // received samples amplitudes
+ float *ix=pdata->ix; // intrinsic information to the MP algorithm
+ float *ex=pdata->ex; // extrinsic information from the MP algorithm
+
+ channel_type = pdata->channel_type;
+ code_type = pcode->type;
+
+ // define the (true) code rate accordingly to the code type
+ switch(code_type) {
+ case QRATYPE_CRC:
+ R = 1.0f*(qra_K-1)/qra_N;
+ break;
+ case QRATYPE_CRCPUNCTURED:
+ R = 1.0f*(qra_K-1)/(qra_N-1);
+ break;
+ case QRATYPE_NORMAL:
+ default:
+ R = 1.0f*(qra_K)/(qra_N);
+ }
+
+ EsNoMetric = 1.0f*qra_m*R*EbNoMetric;
+
+ EbNo = (float)pow(10,pdata->EbNodB/10);
+ EsNo = 1.0f*qra_m*R*EbNo;
+ Es = EsNo*No;
+ A = (float)sqrt(Es);
+
+
+ // encode the input
+ if (code_type==QRATYPE_CRC || code_type==QRATYPE_CRCPUNCTURED) {
+ // compute the information message symbol check as the (negated) xor of all the
+ // information message symbols
+ for (k=0;k<(qra_K-1);k++)
+ x[k]=k%qra_M;
+ x[k]=calc_crc6(x,qra_K-1);
+ }
+ else
+ for (k=0;kstop==0) {
+
+ // simulate the channel
+ // NOTE: in the case that the code is punctured, for simplicity
+ // we compute the channel outputs and the metric also for the crc symbol
+ // then we ignore its observation.
+ normrnd_s(rp,NSAMPLES,0,sigma);
+ normrnd_s(rq,NSAMPLES,0,sigma);
+
+ if (channel_type == CHANNEL_AWGN) {
+ for (k=0;kdone = 1;
+ return; // unknown channel type
+ }
+
+ // compute the squares of the amplitudes of the received samples
+ for (k=0;km,pcode->N,EsNoMetric);
+
+ if (code_type==QRATYPE_CRCPUNCTURED) {
+ // ignore observations of the CRC symbol as it is not actually sent
+ // over the channel
+ pd_init(PD_ROWADDR(ix,qra_M,qra_K),pd_uniform(qra_m),qra_M);
+ }
+
+
+ if (pdata->ap_index!=0)
+ // mask channel observations with a priori knowledge
+ ix_mask(pcode,ix,ap_masks_jt65[pdata->ap_index],x);
+
+
+ // compute the extrinsic symbols probabilities with the message-passing algorithm
+ // stop if extrinsic information does not converges to 1 within the given number of iterations
+ rc = qra_extrinsic(pcode,ex,ix,100,qra_v2cmsg,qra_c2vmsg);
+
+ if (rc>=0) { // the MP algorithm converged to Iex~1 in rc iterations
+
+ // decode the codeword
+ qra_mapdecode(pcode,ydec,ex,ix);
+
+ // look for undetected errors
+ if (code_type==QRATYPE_CRC || code_type==QRATYPE_CRCPUNCTURED) {
+
+ j = 0; diff = 0;
+ for (k=0;k<(qra_K-1);k++)
+ diff |= (ydec[k]!=x[k]);
+ t = calc_crc6(ydec,qra_K-1);
+ if (t!=ydec[k]) // error detected - crc doesn't matches
+ nerrs += 1;
+ else
+ if (diff) { // decoded message is not equal to the transmitted one but
+ // the crc test passed
+ // add as undetected error
+ nerrsu += 1;
+ nerrs += 1;
+ // uncomment to see what the undetected error pattern looks like
+ //printword("U", ydec);
+ }
+ }
+ else
+ for (k=0;knt=nt;
+ pdata->nerrs=nerrs;
+ pdata->nerrsu=nerrsu;
+
+ }
+
+ pdata->done=1;
+
+ _endthread();
+}
+
+void ix_mask(const qracode *pcode, float *r, const int *mask, const int *x)
+{
+ // mask intrinsic information (channel observations) with a priori knowledge
+
+ uint k,kk, smask;
+ const uint qra_K=pcode->K;
+ const uint qra_M=pcode->M;
+ const uint qra_m=pcode->m;
+
+ for (k=0;kNTHREADS_MAX) {
+ printf("Error: nthreads should be <=%d\n",NTHREADS_MAX);
+ return -1;
+ }
+
+ sprintf(fnameout,"%s%s%s",
+ fnameout_pfx[chtype],
+ pcode->name,
+ fnameout_sfx[ap_index]);
+
+ fout = fopen(fnameout,"w");
+ fprintf(fout,"# Channel (0=AWGN,1=Rayleigh), Eb/No (dB), Transmitted codewords, Errors, Undetected Errors, Avg dec. time (ms), WER\n");
+
+ printf("\nTesting the code %s over the %s channel\nSimulation data will be saved to %s\n",
+ pcode->name,
+ chtype==CHANNEL_AWGN?"AWGN":"Rayleigh",
+ fnameout);
+ fflush (stdout);
+
+ // init fixed thread parameters and preallocate buffers
+ for (j=0;jK*sizeof(uint));
+ wt[j].y = (uint*)malloc(pcode->N*sizeof(uint));
+ wt[j].ydec = (uint*)malloc(pcode->N*sizeof(uint));
+ wt[j].qra_v2cmsg = (float*)malloc(pcode->NMSG*pcode->M*sizeof(float));
+ wt[j].qra_c2vmsg = (float*)malloc(pcode->NMSG*pcode->M*sizeof(float));
+ wt[j].rp = (float*)malloc(pcode->N*pcode->M*sizeof(float));
+ wt[j].rq = (float*)malloc(pcode->N*pcode->M*sizeof(float));
+ wt[j].chp = (float*)malloc(pcode->N*sizeof(float));
+ wt[j].chq = (float*)malloc(pcode->N*sizeof(float));
+ wt[j].r = (float*)malloc(pcode->N*pcode->M*sizeof(float));
+ wt[j].ix = (float*)malloc(pcode->N*pcode->M*sizeof(float));
+ wt[j].ex = (float*)malloc(pcode->N*pcode->M*sizeof(float));
+ }
+
+
+ for (k=0;k=nerrstgt[k]) {
+ for (j=0;j] [-t] [-c] [-a] [-f[-h]\n");
+ printf("Options: \n");
+ printf(" -q: code to simulate. 0=qra_12_63_64_irr_b\n");
+ printf(" 1=qra_13_64_64_irr_e (default)\n");
+ printf(" -t : number of threads to be used for the simulation [1..24]\n");
+ printf(" (default=8)\n");
+ printf(" -c : channel_type. 0=AWGN 1=Rayleigh \n");
+ printf(" (default=AWGN)\n");
+ printf(" -a : amount of a-priori information provided to decoder. \n");
+ printf(" 0= No a-priori (default)\n");
+ printf(" 1= 28 bit \n");
+ printf(" 2= 44 bit \n");
+ printf(" 3= 56 bit \n");
+ printf(" -f : name of the file containing the Eb/No values to be simulated\n");
+ printf(" (default=ebnovalues.txt)\n");
+ printf(" This file should contain lines in this format:\n");
+ printf(" # Eb/No(dB) Target Errors\n");
+ printf(" 0.1 5000\n");
+ printf(" 0.6 5000\n");
+ printf(" 1.1 1000\n");
+ printf(" 1.6 1000\n");
+ printf(" ...\n");
+ printf(" (lines beginning with a # are treated as comments\n\n");
+}
+
+#define SIM_POINTS_MAX 20
+
+int main(int argc, char* argv[])
+{
+
+ float EbNodB[SIM_POINTS_MAX];
+ uint nerrstgt[SIM_POINTS_MAX];
+ FILE *fin;
+
+ char fnamein[128]= "ebnovalues.txt";
+ char buf[128];
+
+ uint nitems = 0;
+ uint code_idx = 1;
+ uint nthreads = 8;
+ uint ch_type = CHANNEL_AWGN;
+ uint ap_index = AP_NONE;
+
+ // parse command line
+ while(--argc) {
+ argv++;
+ if (strncmp(*argv,"-h",2)==0) {
+ syntax();
+ return 0;
+ }
+ else
+ if (strncmp(*argv,"-q",2)==0) {
+ code_idx = (uint)atoi((*argv)+2);
+ if (code_idx>1) {
+ printf("Invalid code index\n");
+ syntax();
+ return -1;
+ }
+ }
+ else
+ if (strncmp(*argv,"-t",2)==0) {
+ nthreads = (uint)atoi((*argv)+2);
+ if (nthreads>NTHREADS_MAX) {
+ printf("Invalid number of threads\n");
+ syntax();
+ return -1;
+ }
+ }
+ else
+ if (strncmp(*argv,"-c",2)==0) {
+ ch_type = (uint)atoi((*argv)+2);
+ if (ch_type>CHANNEL_RAYLEIGH) {
+ printf("Invalid channel type\n");
+ syntax();
+ return -1;
+ }
+ }
+ else
+ if (strncmp(*argv,"-a",2)==0) {
+ ap_index = (uint)atoi((*argv)+2);
+ if (ap_index>AP_56) {
+ printf("Invalid a-priori information index\n");
+ syntax();
+ return -1;
+ }
+ }
+ else
+ if (strncmp(*argv,"-f",2)==0) {
+ strncpy(fnamein,(*argv)+2,127);
+ }
+ else
+ if (strncmp(*argv,"-h",2)==0) {
+ syntax();
+ return -1;
+ }
+ else {
+ printf("Invalid option\n");
+ syntax();
+ return -1;
+ }
+ }
+
+ // parse points to be simulated from the input file
+ fin = fopen(fnamein,"r");
+ if (!fin) {
+ printf("Can't open file: %s\n",fnamein);
+ syntax();
+ }
+
+ while (fgets(buf,128,fin)!=0)
+ if (*buf=='#' || *buf=='\n' )
+ continue;
+ else
+ if (nitems==SIM_POINTS_MAX)
+ break;
+ else
+ if (sscanf(buf,"%f %u",&EbNodB[nitems],&nerrstgt[nitems])!=2) {
+ printf("Invalid input file format\n");
+ syntax();
+ return -1;
+ }
+ else
+ nitems++;
+
+ fclose(fin);
+
+ if (nitems==0) {
+ printf("No Eb/No point specified in file %s\n",fnamein);
+ syntax();
+ return -1;
+ }
+
+ printf("\nQ-ary Repeat-Accumulate Code Word Error Rate Simulator\n");
+ printf("2016, Nico Palermo - IV3NWV\n\n");
+
+ printf("Nthreads = %d\n",nthreads);
+ printf("Channel = %s\n",ch_type==CHANNEL_AWGN?"AWGN":"Rayleigh");
+ printf("Codename = %s\n",codetotest[code_idx]->name);
+ printf("A-priori = %s\n",ap_str[ap_index]);
+ printf("Eb/No input file = %s\n\n",fnamein);
+
+ wer_test_proc(codetotest[code_idx], nthreads, ch_type, ap_index, EbNodB, nerrstgt, nitems);
+
+ return 0;
+}
+
diff --git a/lib/qra/qracodes/normrnd.c b/lib/qra/qracodes/normrnd.c
new file mode 100644
index 000000000..e6b62b1f2
--- /dev/null
+++ b/lib/qra/qracodes/normrnd.c
@@ -0,0 +1,83 @@
+// normrnd.c
+// functions to generate gaussian distributed numbers
+//
+// (c) 2016 - Nico Palermo, IV3NWV - Microtelecom Srl, Italy
+//
+// Credits to Andrea Montefusco - IW0HDV for his help on adapting the sources
+// to OSs other than MS Windows
+//
+// ------------------------------------------------------------------------------
+// This file is part of the qracodes project, a Forward Error Control
+// encoding/decoding package based on Q-ary RA (Repeat and Accumulate) LDPC codes.
+//
+// qracodes is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+// qracodes is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with qracodes source distribution.
+// If not, see .
+
+
+#include "normrnd.h"
+
+#if _WIN32 // note the underscore: without it, it's not msdn official!
+ // Windows (x64 and x86)
+ #include // required only for GetTickCount(...)
+#elif __unix__ // all unices, not all compilers
+ #define rand_s rand_r
+ #include
+ #include // for UINT_MAX
+ // Unix
+#elif __linux__
+ // linux
+#elif __APPLE__
+ // Mac OS, not sure if this is covered by __posix__ and/or __unix__ though...
+#endif
+
+
+
+// use MS rand_s(...) function
+void normrnd_s(float *dst, int nitems, float mean, float stdev)
+{
+ unsigned int r;
+ float phi=0, u=0;
+ int set = 0;
+
+ while (nitems--)
+ if (set==1) {
+ *dst++ = (float)sin(phi)*u*stdev+mean;
+ set = 0;
+ }
+ else {
+ rand_s(&r); phi = (M_2PI/(1.0f+UINT_MAX))*r;
+ rand_s(&r); u = (float)sqrt(-2.0f* log( (1.0f/(1.0f+UINT_MAX))*(1.0f+r) ) );
+ *dst++ = (float)cos(phi)*u*stdev+mean;
+ set=1;
+ }
+}
+
+// use MS rand() function
+void normrnd(float *dst, int nitems, float mean, float stdev)
+{
+ float phi=0, u=0;
+ int set = 0;
+
+ while (nitems--)
+ if (set==1) {
+ *dst++ = (float)sin(phi)*u*stdev+mean;
+ set = 0;
+ }
+ else {
+ phi = (M_2PI/(1.0f+RAND_MAX))*rand();
+ u = (float)sqrt(-2.0f* log( (1.0f/(1.0f+RAND_MAX))*(1.0f+rand()) ) );
+ *dst++ = (float)cos(phi)*u*stdev+mean;
+ set=1;
+ }
+}
+
diff --git a/lib/qra/qracodes/normrnd.h b/lib/qra/qracodes/normrnd.h
new file mode 100644
index 000000000..6f4006fab
--- /dev/null
+++ b/lib/qra/qracodes/normrnd.h
@@ -0,0 +1,49 @@
+// normrnd.h
+// Functions to generate gaussian distributed numbers
+//
+// (c) 2016 - Nico Palermo, IV3NWV - Microtelecom Srl, Italy
+// ------------------------------------------------------------------------------
+// This file is part of the qracodes project, a Forward Error Control
+// encoding/decoding package based on Q-ary RA (Repeat and Accumulate) LDPC codes.
+//
+// qracodes is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+// qracodes is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with qracodes source distribution.
+// If not, see .
+
+#ifndef _normrnd_h_
+#define _normrnd_h_
+
+#define _CRT_RAND_S
+#include
+
+#define _USE_MATH_DEFINES
+#include
+#define M_2PI (2.0f*(float)M_PI)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void normrnd_s(float *dst, int nitems, float mean, float stdev);
+// generate a random array of numbers with a gaussian distribution of given mean and stdev
+// use MS rand_s(...) function
+
+void normrnd(float *dst, int nitems, float mean, float stdev);
+// generate a random array of numbers with a gaussian distribution of given mean and stdev
+// use MS rand() function
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _normrnd_h_
+
diff --git a/lib/qra/qracodes/npfwht.c b/lib/qra/qracodes/npfwht.c
new file mode 100644
index 000000000..5732ce913
--- /dev/null
+++ b/lib/qra/qracodes/npfwht.c
@@ -0,0 +1,216 @@
+// npfwht.c
+// Basic implementation of the Fast Walsh-Hadamard Transforms
+//
+// (c) 2016 - Nico Palermo, IV3NWV - Microtelecom Srl, Italy
+// ------------------------------------------------------------------------------
+// This file is part of the qracodes project, a Forward Error Control
+// encoding/decoding package based on Q-ary RA (repeat and accumulate) LDPC codes.
+//
+// qracodes is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+// qracodes is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with qracodes source distribution.
+// If not, see .
+
+#include "npfwht.h"
+
+#define WHBFY(dst,src,base,offs,dist) { dst[base+offs]=src[base+offs]+src[base+offs+dist]; dst[base+offs+dist]=src[base+offs]-src[base+offs+dist]; }
+
+typedef void (*pnp_fwht)(float*,float*);
+
+static void np_fwht2(float *dst, float *src);
+
+static void np_fwht1(float *dst, float *src);
+static void np_fwht2(float *dst, float *src);
+static void np_fwht4(float *dst, float *src);
+static void np_fwht8(float *dst, float *src);
+static void np_fwht16(float *dst, float *src);
+static void np_fwht32(float *dst, float *src);
+static void np_fwht64(float *dst, float *src);
+
+static pnp_fwht np_fwht_tab[7] = {
+ np_fwht1,
+ np_fwht2,
+ np_fwht4,
+ np_fwht8,
+ np_fwht16,
+ np_fwht32,
+ np_fwht64
+};
+
+void np_fwht(int nlogdim, float *dst, float *src)
+{
+ np_fwht_tab[nlogdim](dst,src);
+}
+
+static void np_fwht1(float *dst, float *src)
+{
+ dst[0] = src[0];
+}
+
+
+static void np_fwht2(float *dst, float *src)
+{
+ float t[2];
+
+ WHBFY(t,src,0,0,1);
+ dst[0]= t[0];
+ dst[1]= t[1];
+}
+
+static void np_fwht4(float *dst, float *src)
+{
+ float t[4];
+
+ // group 1
+ WHBFY(t,src,0,0,2); WHBFY(t,src,0,1,2);
+ // group 2
+ WHBFY(dst,t,0,0,1); WHBFY(dst,t,2,0,1);
+};
+
+
+static void np_fwht8(float *dst, float *src)
+{
+ float t[16];
+ float *t1=t, *t2=t+8;
+
+ // group 1
+ WHBFY(t1,src,0,0,4); WHBFY(t1,src,0,1,4); WHBFY(t1,src,0,2,4); WHBFY(t1,src,0,3,4);
+ // group 2
+ WHBFY(t2,t1,0,0,2); WHBFY(t2,t1,0,1,2); WHBFY(t2,t1,4,0,2); WHBFY(t2,t1,4,1,2);
+ // group 3
+ WHBFY(dst,t2,0,0,1); WHBFY(dst,t2,2,0,1); WHBFY(dst,t2,4,0,1); WHBFY(dst,t2,6,0,1);
+};
+
+
+static void np_fwht16(float *dst, float *src)
+{
+ float t[32];
+ float *t1=t, *t2=t+16;
+
+ // group 1
+ WHBFY(t1,src,0,0,8); WHBFY(t1,src,0,1,8); WHBFY(t1,src,0,2,8); WHBFY(t1,src,0,3,8);
+ WHBFY(t1,src,0,4,8); WHBFY(t1,src,0,5,8); WHBFY(t1,src,0,6,8); WHBFY(t1,src,0,7,8);
+ // group 2
+ WHBFY(t2,t1,0,0,4); WHBFY(t2,t1,0,1,4); WHBFY(t2,t1,0,2,4); WHBFY(t2,t1,0,3,4);
+ WHBFY(t2,t1,8,0,4); WHBFY(t2,t1,8,1,4); WHBFY(t2,t1,8,2,4); WHBFY(t2,t1,8,3,4);
+ // group 3
+ WHBFY(t1,t2,0,0,2); WHBFY(t1,t2,0,1,2); WHBFY(t1,t2,4,0,2); WHBFY(t1,t2,4,1,2);
+ WHBFY(t1,t2,8,0,2); WHBFY(t1,t2,8,1,2); WHBFY(t1,t2,12,0,2); WHBFY(t1,t2,12,1,2);
+ // group 4
+ WHBFY(dst,t1,0,0,1); WHBFY(dst,t1,2,0,1); WHBFY(dst,t1,4,0,1); WHBFY(dst,t1,6,0,1);
+ WHBFY(dst,t1,8,0,1); WHBFY(dst,t1,10,0,1); WHBFY(dst,t1,12,0,1); WHBFY(dst,t1,14,0,1);
+
+}
+
+static void np_fwht32(float *dst, float *src)
+{
+ float t[64];
+ float *t1=t, *t2=t+32;
+
+ // group 1
+ WHBFY(t1,src,0,0,16); WHBFY(t1,src,0,1,16); WHBFY(t1,src,0,2,16); WHBFY(t1,src,0,3,16);
+ WHBFY(t1,src,0,4,16); WHBFY(t1,src,0,5,16); WHBFY(t1,src,0,6,16); WHBFY(t1,src,0,7,16);
+ WHBFY(t1,src,0,8,16); WHBFY(t1,src,0,9,16); WHBFY(t1,src,0,10,16); WHBFY(t1,src,0,11,16);
+ WHBFY(t1,src,0,12,16); WHBFY(t1,src,0,13,16); WHBFY(t1,src,0,14,16); WHBFY(t1,src,0,15,16);
+
+ // group 2
+ WHBFY(t2,t1,0,0,8); WHBFY(t2,t1,0,1,8); WHBFY(t2,t1,0,2,8); WHBFY(t2,t1,0,3,8);
+ WHBFY(t2,t1,0,4,8); WHBFY(t2,t1,0,5,8); WHBFY(t2,t1,0,6,8); WHBFY(t2,t1,0,7,8);
+ WHBFY(t2,t1,16,0,8); WHBFY(t2,t1,16,1,8); WHBFY(t2,t1,16,2,8); WHBFY(t2,t1,16,3,8);
+ WHBFY(t2,t1,16,4,8); WHBFY(t2,t1,16,5,8); WHBFY(t2,t1,16,6,8); WHBFY(t2,t1,16,7,8);
+
+ // group 3
+ WHBFY(t1,t2,0,0,4); WHBFY(t1,t2,0,1,4); WHBFY(t1,t2,0,2,4); WHBFY(t1,t2,0,3,4);
+ WHBFY(t1,t2,8,0,4); WHBFY(t1,t2,8,1,4); WHBFY(t1,t2,8,2,4); WHBFY(t1,t2,8,3,4);
+ WHBFY(t1,t2,16,0,4); WHBFY(t1,t2,16,1,4); WHBFY(t1,t2,16,2,4); WHBFY(t1,t2,16,3,4);
+ WHBFY(t1,t2,24,0,4); WHBFY(t1,t2,24,1,4); WHBFY(t1,t2,24,2,4); WHBFY(t1,t2,24,3,4);
+
+ // group 4
+ WHBFY(t2,t1,0,0,2); WHBFY(t2,t1,0,1,2); WHBFY(t2,t1,4,0,2); WHBFY(t2,t1,4,1,2);
+ WHBFY(t2,t1,8,0,2); WHBFY(t2,t1,8,1,2); WHBFY(t2,t1,12,0,2); WHBFY(t2,t1,12,1,2);
+ WHBFY(t2,t1,16,0,2); WHBFY(t2,t1,16,1,2); WHBFY(t2,t1,20,0,2); WHBFY(t2,t1,20,1,2);
+ WHBFY(t2,t1,24,0,2); WHBFY(t2,t1,24,1,2); WHBFY(t2,t1,28,0,2); WHBFY(t2,t1,28,1,2);
+
+ // group 5
+ WHBFY(dst,t2,0,0,1); WHBFY(dst,t2,2,0,1); WHBFY(dst,t2,4,0,1); WHBFY(dst,t2,6,0,1);
+ WHBFY(dst,t2,8,0,1); WHBFY(dst,t2,10,0,1); WHBFY(dst,t2,12,0,1); WHBFY(dst,t2,14,0,1);
+ WHBFY(dst,t2,16,0,1); WHBFY(dst,t2,18,0,1); WHBFY(dst,t2,20,0,1); WHBFY(dst,t2,22,0,1);
+ WHBFY(dst,t2,24,0,1); WHBFY(dst,t2,26,0,1); WHBFY(dst,t2,28,0,1); WHBFY(dst,t2,30,0,1);
+
+}
+
+static void np_fwht64(float *dst, float *src)
+{
+ float t[128];
+ float *t1=t, *t2=t+64;
+
+
+ // group 1
+ WHBFY(t1,src,0,0,32); WHBFY(t1,src,0,1,32); WHBFY(t1,src,0,2,32); WHBFY(t1,src,0,3,32);
+ WHBFY(t1,src,0,4,32); WHBFY(t1,src,0,5,32); WHBFY(t1,src,0,6,32); WHBFY(t1,src,0,7,32);
+ WHBFY(t1,src,0,8,32); WHBFY(t1,src,0,9,32); WHBFY(t1,src,0,10,32); WHBFY(t1,src,0,11,32);
+ WHBFY(t1,src,0,12,32); WHBFY(t1,src,0,13,32); WHBFY(t1,src,0,14,32); WHBFY(t1,src,0,15,32);
+ WHBFY(t1,src,0,16,32); WHBFY(t1,src,0,17,32); WHBFY(t1,src,0,18,32); WHBFY(t1,src,0,19,32);
+ WHBFY(t1,src,0,20,32); WHBFY(t1,src,0,21,32); WHBFY(t1,src,0,22,32); WHBFY(t1,src,0,23,32);
+ WHBFY(t1,src,0,24,32); WHBFY(t1,src,0,25,32); WHBFY(t1,src,0,26,32); WHBFY(t1,src,0,27,32);
+ WHBFY(t1,src,0,28,32); WHBFY(t1,src,0,29,32); WHBFY(t1,src,0,30,32); WHBFY(t1,src,0,31,32);
+
+ // group 2
+ WHBFY(t2,t1,0,0,16); WHBFY(t2,t1,0,1,16); WHBFY(t2,t1,0,2,16); WHBFY(t2,t1,0,3,16);
+ WHBFY(t2,t1,0,4,16); WHBFY(t2,t1,0,5,16); WHBFY(t2,t1,0,6,16); WHBFY(t2,t1,0,7,16);
+ WHBFY(t2,t1,0,8,16); WHBFY(t2,t1,0,9,16); WHBFY(t2,t1,0,10,16); WHBFY(t2,t1,0,11,16);
+ WHBFY(t2,t1,0,12,16); WHBFY(t2,t1,0,13,16); WHBFY(t2,t1,0,14,16); WHBFY(t2,t1,0,15,16);
+
+ WHBFY(t2,t1,32,0,16); WHBFY(t2,t1,32,1,16); WHBFY(t2,t1,32,2,16); WHBFY(t2,t1,32,3,16);
+ WHBFY(t2,t1,32,4,16); WHBFY(t2,t1,32,5,16); WHBFY(t2,t1,32,6,16); WHBFY(t2,t1,32,7,16);
+ WHBFY(t2,t1,32,8,16); WHBFY(t2,t1,32,9,16); WHBFY(t2,t1,32,10,16); WHBFY(t2,t1,32,11,16);
+ WHBFY(t2,t1,32,12,16); WHBFY(t2,t1,32,13,16); WHBFY(t2,t1,32,14,16); WHBFY(t2,t1,32,15,16);
+
+ // group 3
+ WHBFY(t1,t2,0,0,8); WHBFY(t1,t2,0,1,8); WHBFY(t1,t2,0,2,8); WHBFY(t1,t2,0,3,8);
+ WHBFY(t1,t2,0,4,8); WHBFY(t1,t2,0,5,8); WHBFY(t1,t2,0,6,8); WHBFY(t1,t2,0,7,8);
+ WHBFY(t1,t2,16,0,8); WHBFY(t1,t2,16,1,8); WHBFY(t1,t2,16,2,8); WHBFY(t1,t2,16,3,8);
+ WHBFY(t1,t2,16,4,8); WHBFY(t1,t2,16,5,8); WHBFY(t1,t2,16,6,8); WHBFY(t1,t2,16,7,8);
+ WHBFY(t1,t2,32,0,8); WHBFY(t1,t2,32,1,8); WHBFY(t1,t2,32,2,8); WHBFY(t1,t2,32,3,8);
+ WHBFY(t1,t2,32,4,8); WHBFY(t1,t2,32,5,8); WHBFY(t1,t2,32,6,8); WHBFY(t1,t2,32,7,8);
+ WHBFY(t1,t2,48,0,8); WHBFY(t1,t2,48,1,8); WHBFY(t1,t2,48,2,8); WHBFY(t1,t2,48,3,8);
+ WHBFY(t1,t2,48,4,8); WHBFY(t1,t2,48,5,8); WHBFY(t1,t2,48,6,8); WHBFY(t1,t2,48,7,8);
+
+ // group 4
+ WHBFY(t2,t1,0,0,4); WHBFY(t2,t1,0,1,4); WHBFY(t2,t1,0,2,4); WHBFY(t2,t1,0,3,4);
+ WHBFY(t2,t1,8,0,4); WHBFY(t2,t1,8,1,4); WHBFY(t2,t1,8,2,4); WHBFY(t2,t1,8,3,4);
+ WHBFY(t2,t1,16,0,4); WHBFY(t2,t1,16,1,4); WHBFY(t2,t1,16,2,4); WHBFY(t2,t1,16,3,4);
+ WHBFY(t2,t1,24,0,4); WHBFY(t2,t1,24,1,4); WHBFY(t2,t1,24,2,4); WHBFY(t2,t1,24,3,4);
+ WHBFY(t2,t1,32,0,4); WHBFY(t2,t1,32,1,4); WHBFY(t2,t1,32,2,4); WHBFY(t2,t1,32,3,4);
+ WHBFY(t2,t1,40,0,4); WHBFY(t2,t1,40,1,4); WHBFY(t2,t1,40,2,4); WHBFY(t2,t1,40,3,4);
+ WHBFY(t2,t1,48,0,4); WHBFY(t2,t1,48,1,4); WHBFY(t2,t1,48,2,4); WHBFY(t2,t1,48,3,4);
+ WHBFY(t2,t1,56,0,4); WHBFY(t2,t1,56,1,4); WHBFY(t2,t1,56,2,4); WHBFY(t2,t1,56,3,4);
+
+ // group 5
+ WHBFY(t1,t2,0,0,2); WHBFY(t1,t2,0,1,2); WHBFY(t1,t2,4,0,2); WHBFY(t1,t2,4,1,2);
+ WHBFY(t1,t2,8,0,2); WHBFY(t1,t2,8,1,2); WHBFY(t1,t2,12,0,2); WHBFY(t1,t2,12,1,2);
+ WHBFY(t1,t2,16,0,2); WHBFY(t1,t2,16,1,2); WHBFY(t1,t2,20,0,2); WHBFY(t1,t2,20,1,2);
+ WHBFY(t1,t2,24,0,2); WHBFY(t1,t2,24,1,2); WHBFY(t1,t2,28,0,2); WHBFY(t1,t2,28,1,2);
+ WHBFY(t1,t2,32,0,2); WHBFY(t1,t2,32,1,2); WHBFY(t1,t2,36,0,2); WHBFY(t1,t2,36,1,2);
+ WHBFY(t1,t2,40,0,2); WHBFY(t1,t2,40,1,2); WHBFY(t1,t2,44,0,2); WHBFY(t1,t2,44,1,2);
+ WHBFY(t1,t2,48,0,2); WHBFY(t1,t2,48,1,2); WHBFY(t1,t2,52,0,2); WHBFY(t1,t2,52,1,2);
+ WHBFY(t1,t2,56,0,2); WHBFY(t1,t2,56,1,2); WHBFY(t1,t2,60,0,2); WHBFY(t1,t2,60,1,2);
+
+ // group 6
+ WHBFY(dst,t1,0,0,1); WHBFY(dst,t1,2,0,1); WHBFY(dst,t1,4,0,1); WHBFY(dst,t1,6,0,1);
+ WHBFY(dst,t1,8,0,1); WHBFY(dst,t1,10,0,1); WHBFY(dst,t1,12,0,1); WHBFY(dst,t1,14,0,1);
+ WHBFY(dst,t1,16,0,1); WHBFY(dst,t1,18,0,1); WHBFY(dst,t1,20,0,1); WHBFY(dst,t1,22,0,1);
+ WHBFY(dst,t1,24,0,1); WHBFY(dst,t1,26,0,1); WHBFY(dst,t1,28,0,1); WHBFY(dst,t1,30,0,1);
+ WHBFY(dst,t1,32,0,1); WHBFY(dst,t1,34,0,1); WHBFY(dst,t1,36,0,1); WHBFY(dst,t1,38,0,1);
+ WHBFY(dst,t1,40,0,1); WHBFY(dst,t1,42,0,1); WHBFY(dst,t1,44,0,1); WHBFY(dst,t1,46,0,1);
+ WHBFY(dst,t1,48,0,1); WHBFY(dst,t1,50,0,1); WHBFY(dst,t1,52,0,1); WHBFY(dst,t1,54,0,1);
+ WHBFY(dst,t1,56,0,1); WHBFY(dst,t1,58,0,1); WHBFY(dst,t1,60,0,1); WHBFY(dst,t1,62,0,1);
+}
\ No newline at end of file
diff --git a/lib/qra/qracodes/npfwht.h b/lib/qra/qracodes/npfwht.h
new file mode 100644
index 000000000..9452e2077
--- /dev/null
+++ b/lib/qra/qracodes/npfwht.h
@@ -0,0 +1,45 @@
+// np_fwht.h
+// Basic implementation of the Fast Walsh-Hadamard Transforms
+//
+// (c) 2016 - Nico Palermo, IV3NWV - Microtelecom Srl, Italy
+// ------------------------------------------------------------------------------
+// This file is part of the qracodes project, a Forward Error Control
+// encoding/decoding package based on Q-ary RA (repeat and accumulate) LDPC codes.
+//
+// qracodes is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+// qracodes is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with qracodes source distribution.
+// If not, see .
+
+#ifndef _npfwht_h_
+#define _npfwht_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void np_fwht(int nlogdim, float *dst, float *src);
+// Compute the Walsh-Hadamard transform of the given data up to a
+// 64-dimensional transform
+//
+// Input parameters:
+// nlogdim: log2 of the transform size. Must be in the range [0..6]
+// src : pointer to the input data buffer.
+// dst : pointer to the output data buffer.
+//
+// src and dst must point to preallocated data buffers of size 2^nlogdim*sizeof(float)
+// src and dst buffers can overlap
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _npfwht_
diff --git a/lib/qra/qracodes/pdmath.c b/lib/qra/qracodes/pdmath.c
new file mode 100644
index 000000000..2529a0901
--- /dev/null
+++ b/lib/qra/qracodes/pdmath.c
@@ -0,0 +1,385 @@
+// pdmath.c
+// Elementary math on probability distributions
+//
+// (c) 2016 - Nico Palermo, IV3NWV - Microtelecom Srl, Italy
+// ------------------------------------------------------------------------------
+// This file is part of the qracodes project, a Forward Error Control
+// encoding/decoding package based on Q-ary RA (Repeat and Accumulate) LDPC codes.
+//
+// qracodes is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+// qracodes is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with qracodes source distribution.
+// If not, see .
+
+#include "pdmath.h"
+
+typedef const float *ppd_uniform;
+typedef void (*ppd_imul)(float*,const float*);
+typedef float (*ppd_norm)(float*);
+
+// define vector size in function of its logarithm in base 2
+static const int pd_log2dim[7] = {
+ 1,2,4,8,16,32,64
+};
+
+// define uniform distributions of given size
+static const float pd_uniform1[1] = {
+ 1.
+};
+static const float pd_uniform2[2] = {
+ 1./2., 1./2.
+};
+static const float pd_uniform4[4] = {
+ 1./4., 1./4.,1./4., 1./4.
+};
+static const float pd_uniform8[8] = {
+ 1./8., 1./8.,1./8., 1./8.,1./8., 1./8.,1./8., 1./8.
+};
+static const float pd_uniform16[16] = {
+ 1./16., 1./16., 1./16., 1./16.,1./16., 1./16.,1./16., 1./16.,
+ 1./16., 1./16., 1./16., 1./16.,1./16., 1./16.,1./16., 1./16.
+};
+static const float pd_uniform32[32] = {
+ 1./32., 1./32., 1./32., 1./32.,1./32., 1./32.,1./32., 1./32.,
+ 1./32., 1./32., 1./32., 1./32.,1./32., 1./32.,1./32., 1./32.,
+ 1./32., 1./32., 1./32., 1./32.,1./32., 1./32.,1./32., 1./32.,
+ 1./32., 1./32., 1./32., 1./32.,1./32., 1./32.,1./32., 1./32.
+};
+static const float pd_uniform64[64] = {
+ 1./64., 1./64., 1./64., 1./64.,1./64., 1./64.,1./64., 1./64.,
+ 1./64., 1./64., 1./64., 1./64.,1./64., 1./64.,1./64., 1./64.,
+ 1./64., 1./64., 1./64., 1./64.,1./64., 1./64.,1./64., 1./64.,
+ 1./64., 1./64., 1./64., 1./64.,1./64., 1./64.,1./64., 1./64.,
+ 1./64., 1./64., 1./64., 1./64.,1./64., 1./64.,1./64., 1./64.,
+ 1./64., 1./64., 1./64., 1./64.,1./64., 1./64.,1./64., 1./64.,
+ 1./64., 1./64., 1./64., 1./64.,1./64., 1./64.,1./64., 1./64.,
+ 1./64., 1./64., 1./64., 1./64.,1./64., 1./64.,1./64., 1./64.
+
+};
+
+static const ppd_uniform pd_uniform_tab[7] = {
+ pd_uniform1,
+ pd_uniform2,
+ pd_uniform4,
+ pd_uniform8,
+ pd_uniform16,
+ pd_uniform32,
+ pd_uniform64
+};
+
+// returns a pointer to the uniform distribution of the given logsize
+const float *pd_uniform(int nlogdim)
+{
+ return pd_uniform_tab[nlogdim];
+}
+
+// in-place multiplication functions
+// compute dst = dst*src for any element of the distrib
+
+static void pd_imul1(float *dst, const float *src)
+{
+ dst[0] *= src[0];
+}
+
+static void pd_imul2(float *dst, const float *src)
+{
+ dst[0] *= src[0]; dst[1] *= src[1];
+}
+static void pd_imul4(float *dst, const float *src)
+{
+ dst[0] *= src[0]; dst[1] *= src[1];
+ dst[2] *= src[2]; dst[3] *= src[3];
+}
+static void pd_imul8(float *dst, const float *src)
+{
+ dst[0] *= src[0]; dst[1] *= src[1]; dst[2] *= src[2]; dst[3] *= src[3];
+ dst[4] *= src[4]; dst[5] *= src[5]; dst[6] *= src[6]; dst[7] *= src[7];
+}
+static void pd_imul16(float *dst, const float *src)
+{
+ dst[0] *= src[0]; dst[1] *= src[1]; dst[2] *= src[2]; dst[3] *= src[3];
+ dst[4] *= src[4]; dst[5] *= src[5]; dst[6] *= src[6]; dst[7] *= src[7];
+ dst[8] *= src[8]; dst[9] *= src[9]; dst[10]*= src[10]; dst[11]*= src[11];
+ dst[12]*= src[12]; dst[13]*= src[13]; dst[14]*= src[14]; dst[15]*= src[15];
+}
+static void pd_imul32(float *dst, const float *src)
+{
+ pd_imul16(dst,src);
+ pd_imul16(dst+16,src+16);
+}
+static void pd_imul64(float *dst, const float *src)
+{
+ pd_imul16(dst, src);
+ pd_imul16(dst+16, src+16);
+ pd_imul16(dst+32, src+32);
+ pd_imul16(dst+48, src+48);
+}
+
+static const ppd_imul pd_imul_tab[7] = {
+ pd_imul1,
+ pd_imul2,
+ pd_imul4,
+ pd_imul8,
+ pd_imul16,
+ pd_imul32,
+ pd_imul64
+};
+
+// in place multiplication
+// compute dst = dst*src for any element of the distrib give their log2 size
+// arguments must be pointers to array of floats of the given size
+void pd_imul(float *dst, const float *src, int nlogdim)
+{
+ pd_imul_tab[nlogdim](dst,src);
+}
+
+static float pd_norm1(float *ppd)
+{
+ float t = ppd[0];
+ ppd[0] = 1.f;
+ return t;
+}
+
+static float pd_norm2(float *ppd)
+{
+ float t,to;
+
+ t =ppd[0]; t +=ppd[1];
+
+ if (t<=0) {
+ pd_init(ppd,pd_uniform(1),pd_log2dim[1]);
+ return t;
+ }
+
+ to = t;
+ t = 1.f/t;
+ ppd[0] *=t; ppd[1] *=t;
+ return to;
+
+}
+
+static float pd_norm4(float *ppd)
+{
+ float t,to;
+
+ t =ppd[0]; t +=ppd[1]; t +=ppd[2]; t +=ppd[3];
+
+ if (t<=0) {
+ pd_init(ppd,pd_uniform(2),pd_log2dim[2]);
+ return t;
+ }
+
+ to = t;
+ t = 1.f/t;
+ ppd[0] *=t; ppd[1] *=t; ppd[2] *=t; ppd[3] *=t;
+ return to;
+}
+
+static float pd_norm8(float *ppd)
+{
+ float t,to;
+
+ t =ppd[0]; t +=ppd[1]; t +=ppd[2]; t +=ppd[3];
+ t +=ppd[4]; t +=ppd[5]; t +=ppd[6]; t +=ppd[7];
+
+ if (t<=0) {
+ pd_init(ppd,pd_uniform(3),pd_log2dim[3]);
+ return t;
+ }
+
+ to = t;
+ t = 1.f/t;
+ ppd[0] *=t; ppd[1] *=t; ppd[2] *=t; ppd[3] *=t;
+ ppd[4] *=t; ppd[5] *=t; ppd[6] *=t; ppd[7] *=t;
+ return to;
+}
+static float pd_norm16(float *ppd)
+{
+ float t,to;
+
+ t =ppd[0]; t +=ppd[1]; t +=ppd[2]; t +=ppd[3];
+ t +=ppd[4]; t +=ppd[5]; t +=ppd[6]; t +=ppd[7];
+ t +=ppd[8]; t +=ppd[9]; t +=ppd[10]; t +=ppd[11];
+ t +=ppd[12]; t +=ppd[13]; t +=ppd[14]; t +=ppd[15];
+
+ if (t<=0) {
+ pd_init(ppd,pd_uniform(4),pd_log2dim[4]);
+ return t;
+ }
+
+ to = t;
+ t = 1.f/t;
+ ppd[0] *=t; ppd[1] *=t; ppd[2] *=t; ppd[3] *=t;
+ ppd[4] *=t; ppd[5] *=t; ppd[6] *=t; ppd[7] *=t;
+ ppd[8] *=t; ppd[9] *=t; ppd[10] *=t; ppd[11] *=t;
+ ppd[12] *=t; ppd[13] *=t; ppd[14] *=t; ppd[15] *=t;
+
+ return to;
+}
+static float pd_norm32(float *ppd)
+{
+ float t,to;
+
+ t =ppd[0]; t +=ppd[1]; t +=ppd[2]; t +=ppd[3];
+ t +=ppd[4]; t +=ppd[5]; t +=ppd[6]; t +=ppd[7];
+ t +=ppd[8]; t +=ppd[9]; t +=ppd[10]; t +=ppd[11];
+ t +=ppd[12]; t +=ppd[13]; t +=ppd[14]; t +=ppd[15];
+ t +=ppd[16]; t +=ppd[17]; t +=ppd[18]; t +=ppd[19];
+ t +=ppd[20]; t +=ppd[21]; t +=ppd[22]; t +=ppd[23];
+ t +=ppd[24]; t +=ppd[25]; t +=ppd[26]; t +=ppd[27];
+ t +=ppd[28]; t +=ppd[29]; t +=ppd[30]; t +=ppd[31];
+
+ if (t<=0) {
+ pd_init(ppd,pd_uniform(5),pd_log2dim[5]);
+ return t;
+ }
+
+ to = t;
+ t = 1.f/t;
+ ppd[0] *=t; ppd[1] *=t; ppd[2] *=t; ppd[3] *=t;
+ ppd[4] *=t; ppd[5] *=t; ppd[6] *=t; ppd[7] *=t;
+ ppd[8] *=t; ppd[9] *=t; ppd[10] *=t; ppd[11] *=t;
+ ppd[12] *=t; ppd[13] *=t; ppd[14] *=t; ppd[15] *=t;
+ ppd[16] *=t; ppd[17] *=t; ppd[18] *=t; ppd[19] *=t;
+ ppd[20] *=t; ppd[21] *=t; ppd[22] *=t; ppd[23] *=t;
+ ppd[24] *=t; ppd[25] *=t; ppd[26] *=t; ppd[27] *=t;
+ ppd[28] *=t; ppd[29] *=t; ppd[30] *=t; ppd[31] *=t;
+
+ return to;
+}
+
+static float pd_norm64(float *ppd)
+{
+ float t,to;
+
+ t =ppd[0]; t +=ppd[1]; t +=ppd[2]; t +=ppd[3];
+ t +=ppd[4]; t +=ppd[5]; t +=ppd[6]; t +=ppd[7];
+ t +=ppd[8]; t +=ppd[9]; t +=ppd[10]; t +=ppd[11];
+ t +=ppd[12]; t +=ppd[13]; t +=ppd[14]; t +=ppd[15];
+ t +=ppd[16]; t +=ppd[17]; t +=ppd[18]; t +=ppd[19];
+ t +=ppd[20]; t +=ppd[21]; t +=ppd[22]; t +=ppd[23];
+ t +=ppd[24]; t +=ppd[25]; t +=ppd[26]; t +=ppd[27];
+ t +=ppd[28]; t +=ppd[29]; t +=ppd[30]; t +=ppd[31];
+
+ t +=ppd[32]; t +=ppd[33]; t +=ppd[34]; t +=ppd[35];
+ t +=ppd[36]; t +=ppd[37]; t +=ppd[38]; t +=ppd[39];
+ t +=ppd[40]; t +=ppd[41]; t +=ppd[42]; t +=ppd[43];
+ t +=ppd[44]; t +=ppd[45]; t +=ppd[46]; t +=ppd[47];
+ t +=ppd[48]; t +=ppd[49]; t +=ppd[50]; t +=ppd[51];
+ t +=ppd[52]; t +=ppd[53]; t +=ppd[54]; t +=ppd[55];
+ t +=ppd[56]; t +=ppd[57]; t +=ppd[58]; t +=ppd[59];
+ t +=ppd[60]; t +=ppd[61]; t +=ppd[62]; t +=ppd[63];
+
+ if (t<=0) {
+ pd_init(ppd,pd_uniform(6),pd_log2dim[6]);
+ return t;
+ }
+
+ to = t;
+ t = 1.0f/t;
+ ppd[0] *=t; ppd[1] *=t; ppd[2] *=t; ppd[3] *=t;
+ ppd[4] *=t; ppd[5] *=t; ppd[6] *=t; ppd[7] *=t;
+ ppd[8] *=t; ppd[9] *=t; ppd[10] *=t; ppd[11] *=t;
+ ppd[12] *=t; ppd[13] *=t; ppd[14] *=t; ppd[15] *=t;
+ ppd[16] *=t; ppd[17] *=t; ppd[18] *=t; ppd[19] *=t;
+ ppd[20] *=t; ppd[21] *=t; ppd[22] *=t; ppd[23] *=t;
+ ppd[24] *=t; ppd[25] *=t; ppd[26] *=t; ppd[27] *=t;
+ ppd[28] *=t; ppd[29] *=t; ppd[30] *=t; ppd[31] *=t;
+
+ ppd[32] *=t; ppd[33] *=t; ppd[34] *=t; ppd[35] *=t;
+ ppd[36] *=t; ppd[37] *=t; ppd[38] *=t; ppd[39] *=t;
+ ppd[40] *=t; ppd[41] *=t; ppd[42] *=t; ppd[43] *=t;
+ ppd[44] *=t; ppd[45] *=t; ppd[46] *=t; ppd[47] *=t;
+ ppd[48] *=t; ppd[49] *=t; ppd[50] *=t; ppd[51] *=t;
+ ppd[52] *=t; ppd[53] *=t; ppd[54] *=t; ppd[55] *=t;
+ ppd[56] *=t; ppd[57] *=t; ppd[58] *=t; ppd[59] *=t;
+ ppd[60] *=t; ppd[61] *=t; ppd[62] *=t; ppd[63] *=t;
+
+ return to;
+}
+
+
+static const ppd_norm pd_norm_tab[7] = {
+ pd_norm1,
+ pd_norm2,
+ pd_norm4,
+ pd_norm8,
+ pd_norm16,
+ pd_norm32,
+ pd_norm64
+};
+
+float pd_norm(float *pd, int nlogdim)
+{
+ return pd_norm_tab[nlogdim](pd);
+}
+
+void pd_memset(float *dst, const float *src, int ndim, int nitems)
+{
+ int size = PD_SIZE(ndim);
+ while(nitems--) {
+ memcpy(dst,src,size);
+ dst +=ndim;
+ }
+}
+
+void pd_fwdperm(float *dst, float *src, const unsigned int *perm, int ndim)
+{
+ // TODO: non-loop implementation
+ while (ndim--)
+ dst[ndim] = src[perm[ndim]];
+}
+
+void pd_bwdperm(float *dst, float *src, const unsigned int *perm, int ndim)
+{
+ // TODO: non-loop implementation
+ while (ndim--)
+ dst[perm[ndim]] = src[ndim];
+}
+
+float pd_max(float *src, int ndim)
+{
+ // TODO: faster implementation
+
+ float cmax=0; // we assume that prob distributions are always positive
+ float cval;
+
+ while (ndim--) {
+ cval = src[ndim];
+ if (cval>=cmax) {
+ cmax = cval;
+ }
+ }
+
+ return cmax;
+}
+
+int pd_argmax(float *pmax, float *src, int ndim)
+{
+ // TODO: faster implementation
+
+ float cmax=0; // we assume that prob distributions are always positive
+ float cval;
+ int idxmax=-1; // indicates that all pd elements are <0
+
+ while (ndim--) {
+ cval = src[ndim];
+ if (cval>=cmax) {
+ cmax = cval;
+ idxmax = ndim;
+ }
+ }
+
+ if (pmax)
+ *pmax = cmax;
+
+ return idxmax;
+}
diff --git a/lib/qra/qracodes/pdmath.h b/lib/qra/qracodes/pdmath.h
new file mode 100644
index 000000000..b96c98b36
--- /dev/null
+++ b/lib/qra/qracodes/pdmath.h
@@ -0,0 +1,85 @@
+// pdmath.h
+// Elementary math on probability distributions
+//
+// (c) 2016 - Nico Palermo, IV3NWV - Microtelecom Srl, Italy
+// ------------------------------------------------------------------------------
+// This file is part of the qracodes project, a Forward Error Control
+// encoding/decoding package based on Q-ary RA (repeat and accumulate) LDPC codes.
+//
+// qracodes is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+// qracodes is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with qracodes source distribution.
+// If not, see .
+
+
+#ifndef _pdmath_h_
+#define _pdmath_h_
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PD_NDIM(nlogdim) ((1<<(nlogdim))
+#define PD_SIZE(ndim) ((ndim)*sizeof(float))
+#define PD_ROWADDR(fp,ndim,idx) (fp+((ndim)*(idx)))
+
+const float *pd_uniform(int nlogdim);
+// Returns a pointer to a (constant) uniform distribution of the given log2 size
+
+#define pd_init(dst,src,ndim) memcpy(dst,src,PD_SIZE(ndim))
+// Distribution copy
+
+void pd_memset(float *dst, const float *src, int ndim, int nitems);
+// Copy the distribution pointed by src to the array of distributions dst
+// src is a pointer to the input distribution (a vector of size ndim)
+// dst is a pointer to a linear array of distributions (a vector of size ndim*nitems)
+
+void pd_imul(float *dst, const float *src, int nlogdim);
+// In place multiplication
+// Compute dst = dst*src for any element of the distrib give their log2 size
+// src and dst arguments must be pointers to array of floats of the given size
+
+float pd_norm(float *pd, int nlogdim);
+// In place normalizazion
+// Normalizes the input vector so that the sum of its components are one
+// pd must be a pointer to an array of floats of the given size.
+// If the norm of the input vector is non-positive the vector components
+// are replaced with a uniform distribution
+// Returns the norm of the distribution prior to the normalization
+
+void pd_fwdperm(float *dst, float *src, const unsigned int *perm, int ndim);
+// Forward permutation of a distribution
+// Computes dst[k] = src[perm[k]] for every element in the distribution
+// perm must be a pointer to an array of integers of length ndim
+
+void pd_bwdperm(float *dst, float *src, const unsigned int *perm, int ndim);
+// Backward permutation of a distribution
+// Computes dst[perm[k]] = src[k] for every element in the distribution
+// perm must be a pointer to an array of integers of length ndim
+
+float pd_max(float *src, int ndim);
+// Return the maximum of the elements of the given distribution
+// Assumes that the input vector is a probability distribution and that each element in the
+// distribution is non negative
+
+int pd_argmax(float *pmax, float *src, int ndim);
+// Return the index of the maximum element of the given distribution
+// The maximum is stored in the variable pointed by pmax if pmax is not null
+// Same note of pd_max applies.
+// Return -1 if all the elements in the distribution are negative
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _pdmath_h_
diff --git a/lib/qra/qracodes/qra12_63_64_irr_b.c b/lib/qra/qracodes/qra12_63_64_irr_b.c
new file mode 100644
index 000000000..a192b41ab
--- /dev/null
+++ b/lib/qra/qracodes/qra12_63_64_irr_b.c
@@ -0,0 +1,534 @@
+// qra12_63_64_irr_b.c
+// Encoding/Decoding tables for Q-ary RA code (12,63) over GF(64)
+// Code Name: qra12_63_64_irr_b
+// (12,63) RA Code over GF(64) - RF=333344455567
+
+// (c) 2016 - Nico Palermo - IV3NWV - Microtelecom Srl, Italy
+
+// This file is part of the qracodes project, a Forward Error Control
+// encoding/decoding package based on Q-ary RA (Repeat and Accumulate) LDPC codes.
+//
+// qracodes is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+// qracodes is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with qracodes source distribution.
+// If not, see .
+
+#include "qra12_63_64_irr_b.h"
+
+#define qra_K 12 // number of information symbols
+#define qra_N 63 // codeword length in symbols
+#define qra_m 6 // bits/symbol
+#define qra_M 64 // Symbol alphabet cardinality
+#define qra_a 1 // grouping factor
+#define qra_NC 51 // number of check symbols (N-K)
+
+// Defines used by the message passing decoder --------
+
+#define qra_V 63 // number of variables in the code graph (N)
+#define qra_C 115 // number of factors in the code graph (N +(N-K)+1)
+#define qra_NMSG 217 // number of msgs in the code graph
+#define qra_MAXVDEG 8 // maximum variable degree
+#define qra_MAXCDEG 3 // maximum factor degree
+#define qra_R 0.19048f // code rate (K/N)
+#define CODE_NAME "qra_12_63_64_irr_b"
+
+
+// table of the systematic symbols indexes in the accumulator chain
+static const int qra_acc_input_idx[qra_NC+1] = {
+ 3, 11, 0, 1, 7, 8, 6, 5, 10, 4,
+ 11, 9, 0, 2, 6, 7, 8, 4, 11, 5,
+ 10, 2, 1, 9, 3, 8, 4, 11, 5, 7,
+ 10, 9, 6, 3, 11, 5, 8, 10, 0, 7,
+ 9, 11, 4, 2, 10, 6, 8, 1, 9, 7,
+ 11, 10
+};
+
+// table of the systematic symbols weight logarithms over GF(M)
+static const unsigned int qra_acc_input_wlog[qra_NC+1] = {
+ 39, 0, 34, 16, 25, 0, 34, 48, 19, 13,
+ 29, 56, 0, 5, 39, 42, 31, 0, 10, 0,
+ 57, 62, 33, 43, 0, 14, 22, 48, 28, 20,
+ 5, 45, 16, 43, 17, 4, 32, 0, 31, 0,
+ 0, 28, 57, 0, 18, 0, 60, 0, 10, 31,
+ 57, 27
+};
+
+// table of the logarithms of the elements of GF(M) (log(0) never used)
+static const int qra_log[qra_M] = {
+ -1, 0, 1, 6, 2, 12, 7, 26, 3, 32,
+ 13, 35, 8, 48, 27, 18, 4, 24, 33, 16,
+ 14, 52, 36, 54, 9, 45, 49, 38, 28, 41,
+ 19, 56, 5, 62, 25, 11, 34, 31, 17, 47,
+ 15, 23, 53, 51, 37, 44, 55, 40, 10, 61,
+ 46, 30, 50, 22, 39, 43, 29, 60, 42, 21,
+ 20, 59, 57, 58
+};
+
+// table of GF(M) elements given their logarithm
+static const unsigned int qra_exp[qra_M-1] = {
+ 1, 2, 4, 8, 16, 32, 3, 6, 12, 24,
+ 48, 35, 5, 10, 20, 40, 19, 38, 15, 30,
+ 60, 59, 53, 41, 17, 34, 7, 14, 28, 56,
+ 51, 37, 9, 18, 36, 11, 22, 44, 27, 54,
+ 47, 29, 58, 55, 45, 25, 50, 39, 13, 26,
+ 52, 43, 21, 42, 23, 46, 31, 62, 63, 61,
+ 57, 49, 33
+};
+
+// table of the messages weight logarithms over GF(M)
+static const unsigned int qra_msgw[qra_NMSG] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 39, 0, 34, 16, 25, 0, 34,
+ 48, 19, 13, 29, 56, 0, 5, 39, 42, 31,
+ 0, 10, 0, 57, 62, 33, 43, 0, 14, 22,
+ 48, 28, 20, 5, 45, 16, 43, 17, 4, 32,
+ 0, 31, 0, 0, 28, 57, 0, 18, 0, 60,
+ 0, 10, 31, 57, 27, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0
+};
+
+// table of the degrees of the variable nodes
+static const unsigned int qra_vdeg[qra_V] = {
+ 4, 4, 4, 4, 5, 5, 5, 6, 6, 6,
+ 7, 8, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3
+};
+
+// table of the degrees of the factor nodes
+static const unsigned int qra_cdeg[qra_C] = {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 2, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 2
+};
+
+// table (uncompressed) of the v->c message indexes (-1=unused entry)
+static const int qra_v2cmidx[qra_V*qra_MAXVDEG] = {
+ 0, 65, 75, 101, -1, -1, -1, -1,
+ 1, 66, 85, 110, -1, -1, -1, -1,
+ 2, 76, 84, 106, -1, -1, -1, -1,
+ 3, 63, 87, 96, -1, -1, -1, -1,
+ 4, 72, 80, 89, 105, -1, -1, -1,
+ 5, 70, 82, 91, 98, -1, -1, -1,
+ 6, 69, 77, 95, 108, -1, -1, -1,
+ 7, 67, 78, 92, 102, 112, -1, -1,
+ 8, 68, 79, 88, 99, 109, -1, -1,
+ 9, 74, 86, 94, 103, 111, -1, -1,
+ 10, 71, 83, 93, 100, 107, 114, -1,
+ 11, 64, 73, 81, 90, 97, 104, 113,
+ 12, 115, 116, -1, -1, -1, -1, -1,
+ 13, 117, 118, -1, -1, -1, -1, -1,
+ 14, 119, 120, -1, -1, -1, -1, -1,
+ 15, 121, 122, -1, -1, -1, -1, -1,
+ 16, 123, 124, -1, -1, -1, -1, -1,
+ 17, 125, 126, -1, -1, -1, -1, -1,
+ 18, 127, 128, -1, -1, -1, -1, -1,
+ 19, 129, 130, -1, -1, -1, -1, -1,
+ 20, 131, 132, -1, -1, -1, -1, -1,
+ 21, 133, 134, -1, -1, -1, -1, -1,
+ 22, 135, 136, -1, -1, -1, -1, -1,
+ 23, 137, 138, -1, -1, -1, -1, -1,
+ 24, 139, 140, -1, -1, -1, -1, -1,
+ 25, 141, 142, -1, -1, -1, -1, -1,
+ 26, 143, 144, -1, -1, -1, -1, -1,
+ 27, 145, 146, -1, -1, -1, -1, -1,
+ 28, 147, 148, -1, -1, -1, -1, -1,
+ 29, 149, 150, -1, -1, -1, -1, -1,
+ 30, 151, 152, -1, -1, -1, -1, -1,
+ 31, 153, 154, -1, -1, -1, -1, -1,
+ 32, 155, 156, -1, -1, -1, -1, -1,
+ 33, 157, 158, -1, -1, -1, -1, -1,
+ 34, 159, 160, -1, -1, -1, -1, -1,
+ 35, 161, 162, -1, -1, -1, -1, -1,
+ 36, 163, 164, -1, -1, -1, -1, -1,
+ 37, 165, 166, -1, -1, -1, -1, -1,
+ 38, 167, 168, -1, -1, -1, -1, -1,
+ 39, 169, 170, -1, -1, -1, -1, -1,
+ 40, 171, 172, -1, -1, -1, -1, -1,
+ 41, 173, 174, -1, -1, -1, -1, -1,
+ 42, 175, 176, -1, -1, -1, -1, -1,
+ 43, 177, 178, -1, -1, -1, -1, -1,
+ 44, 179, 180, -1, -1, -1, -1, -1,
+ 45, 181, 182, -1, -1, -1, -1, -1,
+ 46, 183, 184, -1, -1, -1, -1, -1,
+ 47, 185, 186, -1, -1, -1, -1, -1,
+ 48, 187, 188, -1, -1, -1, -1, -1,
+ 49, 189, 190, -1, -1, -1, -1, -1,
+ 50, 191, 192, -1, -1, -1, -1, -1,
+ 51, 193, 194, -1, -1, -1, -1, -1,
+ 52, 195, 196, -1, -1, -1, -1, -1,
+ 53, 197, 198, -1, -1, -1, -1, -1,
+ 54, 199, 200, -1, -1, -1, -1, -1,
+ 55, 201, 202, -1, -1, -1, -1, -1,
+ 56, 203, 204, -1, -1, -1, -1, -1,
+ 57, 205, 206, -1, -1, -1, -1, -1,
+ 58, 207, 208, -1, -1, -1, -1, -1,
+ 59, 209, 210, -1, -1, -1, -1, -1,
+ 60, 211, 212, -1, -1, -1, -1, -1,
+ 61, 213, 214, -1, -1, -1, -1, -1,
+ 62, 215, 216, -1, -1, -1, -1, -1
+};
+
+// table (uncompressed) of the c->v message indexes (-1=unused entry)
+static const int qra_c2vmidx[qra_C*qra_MAXCDEG] = {
+ 0, -1, -1, 1, -1, -1, 2, -1, -1, 3, -1, -1,
+ 4, -1, -1, 5, -1, -1, 6, -1, -1, 7, -1, -1,
+ 8, -1, -1, 9, -1, -1, 10, -1, -1, 11, -1, -1,
+ 12, -1, -1, 13, -1, -1, 14, -1, -1, 15, -1, -1,
+ 16, -1, -1, 17, -1, -1, 18, -1, -1, 19, -1, -1,
+ 20, -1, -1, 21, -1, -1, 22, -1, -1, 23, -1, -1,
+ 24, -1, -1, 25, -1, -1, 26, -1, -1, 27, -1, -1,
+ 28, -1, -1, 29, -1, -1, 30, -1, -1, 31, -1, -1,
+ 32, -1, -1, 33, -1, -1, 34, -1, -1, 35, -1, -1,
+ 36, -1, -1, 37, -1, -1, 38, -1, -1, 39, -1, -1,
+ 40, -1, -1, 41, -1, -1, 42, -1, -1, 43, -1, -1,
+ 44, -1, -1, 45, -1, -1, 46, -1, -1, 47, -1, -1,
+ 48, -1, -1, 49, -1, -1, 50, -1, -1, 51, -1, -1,
+ 52, -1, -1, 53, -1, -1, 54, -1, -1, 55, -1, -1,
+ 56, -1, -1, 57, -1, -1, 58, -1, -1, 59, -1, -1,
+ 60, -1, -1, 61, -1, -1, 62, -1, -1, 63, 115, -1,
+ 64, 116, 117, 65, 118, 119, 66, 120, 121, 67, 122, 123,
+ 68, 124, 125, 69, 126, 127, 70, 128, 129, 71, 130, 131,
+ 72, 132, 133, 73, 134, 135, 74, 136, 137, 75, 138, 139,
+ 76, 140, 141, 77, 142, 143, 78, 144, 145, 79, 146, 147,
+ 80, 148, 149, 81, 150, 151, 82, 152, 153, 83, 154, 155,
+ 84, 156, 157, 85, 158, 159, 86, 160, 161, 87, 162, 163,
+ 88, 164, 165, 89, 166, 167, 90, 168, 169, 91, 170, 171,
+ 92, 172, 173, 93, 174, 175, 94, 176, 177, 95, 178, 179,
+ 96, 180, 181, 97, 182, 183, 98, 184, 185, 99, 186, 187,
+100, 188, 189, 101, 190, 191, 102, 192, 193, 103, 194, 195,
+104, 196, 197, 105, 198, 199, 106, 200, 201, 107, 202, 203,
+108, 204, 205, 109, 206, 207, 110, 208, 209, 111, 210, 211,
+112, 212, 213, 113, 214, 215, 114, 216, -1
+};
+
+// permutation matrix to compute Prob(x*alfa^logw)
+static const unsigned int qra_pmat[qra_M*qra_M] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 33, 1, 32, 2, 35, 3, 34, 4, 37, 5, 36, 6, 39, 7, 38,
+ 8, 41, 9, 40, 10, 43, 11, 42, 12, 45, 13, 44, 14, 47, 15, 46,
+ 16, 49, 17, 48, 18, 51, 19, 50, 20, 53, 21, 52, 22, 55, 23, 54,
+ 24, 57, 25, 56, 26, 59, 27, 58, 28, 61, 29, 60, 30, 63, 31, 62,
+ 0, 49, 33, 16, 1, 48, 32, 17, 2, 51, 35, 18, 3, 50, 34, 19,
+ 4, 53, 37, 20, 5, 52, 36, 21, 6, 55, 39, 22, 7, 54, 38, 23,
+ 8, 57, 41, 24, 9, 56, 40, 25, 10, 59, 43, 26, 11, 58, 42, 27,
+ 12, 61, 45, 28, 13, 60, 44, 29, 14, 63, 47, 30, 15, 62, 46, 31,
+ 0, 57, 49, 8, 33, 24, 16, 41, 1, 56, 48, 9, 32, 25, 17, 40,
+ 2, 59, 51, 10, 35, 26, 18, 43, 3, 58, 50, 11, 34, 27, 19, 42,
+ 4, 61, 53, 12, 37, 28, 20, 45, 5, 60, 52, 13, 36, 29, 21, 44,
+ 6, 63, 55, 14, 39, 30, 22, 47, 7, 62, 54, 15, 38, 31, 23, 46,
+ 0, 61, 57, 4, 49, 12, 8, 53, 33, 28, 24, 37, 16, 45, 41, 20,
+ 1, 60, 56, 5, 48, 13, 9, 52, 32, 29, 25, 36, 17, 44, 40, 21,
+ 2, 63, 59, 6, 51, 14, 10, 55, 35, 30, 26, 39, 18, 47, 43, 22,
+ 3, 62, 58, 7, 50, 15, 11, 54, 34, 31, 27, 38, 19, 46, 42, 23,
+ 0, 63, 61, 2, 57, 6, 4, 59, 49, 14, 12, 51, 8, 55, 53, 10,
+ 33, 30, 28, 35, 24, 39, 37, 26, 16, 47, 45, 18, 41, 22, 20, 43,
+ 1, 62, 60, 3, 56, 7, 5, 58, 48, 15, 13, 50, 9, 54, 52, 11,
+ 32, 31, 29, 34, 25, 38, 36, 27, 17, 46, 44, 19, 40, 23, 21, 42,
+ 0, 62, 63, 1, 61, 3, 2, 60, 57, 7, 6, 56, 4, 58, 59, 5,
+ 49, 15, 14, 48, 12, 50, 51, 13, 8, 54, 55, 9, 53, 11, 10, 52,
+ 33, 31, 30, 32, 28, 34, 35, 29, 24, 38, 39, 25, 37, 27, 26, 36,
+ 16, 46, 47, 17, 45, 19, 18, 44, 41, 23, 22, 40, 20, 42, 43, 21,
+ 0, 31, 62, 33, 63, 32, 1, 30, 61, 34, 3, 28, 2, 29, 60, 35,
+ 57, 38, 7, 24, 6, 25, 56, 39, 4, 27, 58, 37, 59, 36, 5, 26,
+ 49, 46, 15, 16, 14, 17, 48, 47, 12, 19, 50, 45, 51, 44, 13, 18,
+ 8, 23, 54, 41, 55, 40, 9, 22, 53, 42, 11, 20, 10, 21, 52, 43,
+ 0, 46, 31, 49, 62, 16, 33, 15, 63, 17, 32, 14, 1, 47, 30, 48,
+ 61, 19, 34, 12, 3, 45, 28, 50, 2, 44, 29, 51, 60, 18, 35, 13,
+ 57, 23, 38, 8, 7, 41, 24, 54, 6, 40, 25, 55, 56, 22, 39, 9,
+ 4, 42, 27, 53, 58, 20, 37, 11, 59, 21, 36, 10, 5, 43, 26, 52,
+ 0, 23, 46, 57, 31, 8, 49, 38, 62, 41, 16, 7, 33, 54, 15, 24,
+ 63, 40, 17, 6, 32, 55, 14, 25, 1, 22, 47, 56, 30, 9, 48, 39,
+ 61, 42, 19, 4, 34, 53, 12, 27, 3, 20, 45, 58, 28, 11, 50, 37,
+ 2, 21, 44, 59, 29, 10, 51, 36, 60, 43, 18, 5, 35, 52, 13, 26,
+ 0, 42, 23, 61, 46, 4, 57, 19, 31, 53, 8, 34, 49, 27, 38, 12,
+ 62, 20, 41, 3, 16, 58, 7, 45, 33, 11, 54, 28, 15, 37, 24, 50,
+ 63, 21, 40, 2, 17, 59, 6, 44, 32, 10, 55, 29, 14, 36, 25, 51,
+ 1, 43, 22, 60, 47, 5, 56, 18, 30, 52, 9, 35, 48, 26, 39, 13,
+ 0, 21, 42, 63, 23, 2, 61, 40, 46, 59, 4, 17, 57, 44, 19, 6,
+ 31, 10, 53, 32, 8, 29, 34, 55, 49, 36, 27, 14, 38, 51, 12, 25,
+ 62, 43, 20, 1, 41, 60, 3, 22, 16, 5, 58, 47, 7, 18, 45, 56,
+ 33, 52, 11, 30, 54, 35, 28, 9, 15, 26, 37, 48, 24, 13, 50, 39,
+ 0, 43, 21, 62, 42, 1, 63, 20, 23, 60, 2, 41, 61, 22, 40, 3,
+ 46, 5, 59, 16, 4, 47, 17, 58, 57, 18, 44, 7, 19, 56, 6, 45,
+ 31, 52, 10, 33, 53, 30, 32, 11, 8, 35, 29, 54, 34, 9, 55, 28,
+ 49, 26, 36, 15, 27, 48, 14, 37, 38, 13, 51, 24, 12, 39, 25, 50,
+ 0, 52, 43, 31, 21, 33, 62, 10, 42, 30, 1, 53, 63, 11, 20, 32,
+ 23, 35, 60, 8, 2, 54, 41, 29, 61, 9, 22, 34, 40, 28, 3, 55,
+ 46, 26, 5, 49, 59, 15, 16, 36, 4, 48, 47, 27, 17, 37, 58, 14,
+ 57, 13, 18, 38, 44, 24, 7, 51, 19, 39, 56, 12, 6, 50, 45, 25,
+ 0, 26, 52, 46, 43, 49, 31, 5, 21, 15, 33, 59, 62, 36, 10, 16,
+ 42, 48, 30, 4, 1, 27, 53, 47, 63, 37, 11, 17, 20, 14, 32, 58,
+ 23, 13, 35, 57, 60, 38, 8, 18, 2, 24, 54, 44, 41, 51, 29, 7,
+ 61, 39, 9, 19, 22, 12, 34, 56, 40, 50, 28, 6, 3, 25, 55, 45,
+ 0, 13, 26, 23, 52, 57, 46, 35, 43, 38, 49, 60, 31, 18, 5, 8,
+ 21, 24, 15, 2, 33, 44, 59, 54, 62, 51, 36, 41, 10, 7, 16, 29,
+ 42, 39, 48, 61, 30, 19, 4, 9, 1, 12, 27, 22, 53, 56, 47, 34,
+ 63, 50, 37, 40, 11, 6, 17, 28, 20, 25, 14, 3, 32, 45, 58, 55,
+ 0, 39, 13, 42, 26, 61, 23, 48, 52, 19, 57, 30, 46, 9, 35, 4,
+ 43, 12, 38, 1, 49, 22, 60, 27, 31, 56, 18, 53, 5, 34, 8, 47,
+ 21, 50, 24, 63, 15, 40, 2, 37, 33, 6, 44, 11, 59, 28, 54, 17,
+ 62, 25, 51, 20, 36, 3, 41, 14, 10, 45, 7, 32, 16, 55, 29, 58,
+ 0, 50, 39, 21, 13, 63, 42, 24, 26, 40, 61, 15, 23, 37, 48, 2,
+ 52, 6, 19, 33, 57, 11, 30, 44, 46, 28, 9, 59, 35, 17, 4, 54,
+ 43, 25, 12, 62, 38, 20, 1, 51, 49, 3, 22, 36, 60, 14, 27, 41,
+ 31, 45, 56, 10, 18, 32, 53, 7, 5, 55, 34, 16, 8, 58, 47, 29,
+ 0, 25, 50, 43, 39, 62, 21, 12, 13, 20, 63, 38, 42, 51, 24, 1,
+ 26, 3, 40, 49, 61, 36, 15, 22, 23, 14, 37, 60, 48, 41, 2, 27,
+ 52, 45, 6, 31, 19, 10, 33, 56, 57, 32, 11, 18, 30, 7, 44, 53,
+ 46, 55, 28, 5, 9, 16, 59, 34, 35, 58, 17, 8, 4, 29, 54, 47,
+ 0, 45, 25, 52, 50, 31, 43, 6, 39, 10, 62, 19, 21, 56, 12, 33,
+ 13, 32, 20, 57, 63, 18, 38, 11, 42, 7, 51, 30, 24, 53, 1, 44,
+ 26, 55, 3, 46, 40, 5, 49, 28, 61, 16, 36, 9, 15, 34, 22, 59,
+ 23, 58, 14, 35, 37, 8, 60, 17, 48, 29, 41, 4, 2, 47, 27, 54,
+ 0, 55, 45, 26, 25, 46, 52, 3, 50, 5, 31, 40, 43, 28, 6, 49,
+ 39, 16, 10, 61, 62, 9, 19, 36, 21, 34, 56, 15, 12, 59, 33, 22,
+ 13, 58, 32, 23, 20, 35, 57, 14, 63, 8, 18, 37, 38, 17, 11, 60,
+ 42, 29, 7, 48, 51, 4, 30, 41, 24, 47, 53, 2, 1, 54, 44, 27,
+ 0, 58, 55, 13, 45, 23, 26, 32, 25, 35, 46, 20, 52, 14, 3, 57,
+ 50, 8, 5, 63, 31, 37, 40, 18, 43, 17, 28, 38, 6, 60, 49, 11,
+ 39, 29, 16, 42, 10, 48, 61, 7, 62, 4, 9, 51, 19, 41, 36, 30,
+ 21, 47, 34, 24, 56, 2, 15, 53, 12, 54, 59, 1, 33, 27, 22, 44,
+ 0, 29, 58, 39, 55, 42, 13, 16, 45, 48, 23, 10, 26, 7, 32, 61,
+ 25, 4, 35, 62, 46, 51, 20, 9, 52, 41, 14, 19, 3, 30, 57, 36,
+ 50, 47, 8, 21, 5, 24, 63, 34, 31, 2, 37, 56, 40, 53, 18, 15,
+ 43, 54, 17, 12, 28, 1, 38, 59, 6, 27, 60, 33, 49, 44, 11, 22,
+ 0, 47, 29, 50, 58, 21, 39, 8, 55, 24, 42, 5, 13, 34, 16, 63,
+ 45, 2, 48, 31, 23, 56, 10, 37, 26, 53, 7, 40, 32, 15, 61, 18,
+ 25, 54, 4, 43, 35, 12, 62, 17, 46, 1, 51, 28, 20, 59, 9, 38,
+ 52, 27, 41, 6, 14, 33, 19, 60, 3, 44, 30, 49, 57, 22, 36, 11,
+ 0, 54, 47, 25, 29, 43, 50, 4, 58, 12, 21, 35, 39, 17, 8, 62,
+ 55, 1, 24, 46, 42, 28, 5, 51, 13, 59, 34, 20, 16, 38, 63, 9,
+ 45, 27, 2, 52, 48, 6, 31, 41, 23, 33, 56, 14, 10, 60, 37, 19,
+ 26, 44, 53, 3, 7, 49, 40, 30, 32, 22, 15, 57, 61, 11, 18, 36,
+ 0, 27, 54, 45, 47, 52, 25, 2, 29, 6, 43, 48, 50, 41, 4, 31,
+ 58, 33, 12, 23, 21, 14, 35, 56, 39, 60, 17, 10, 8, 19, 62, 37,
+ 55, 44, 1, 26, 24, 3, 46, 53, 42, 49, 28, 7, 5, 30, 51, 40,
+ 13, 22, 59, 32, 34, 57, 20, 15, 16, 11, 38, 61, 63, 36, 9, 18,
+ 0, 44, 27, 55, 54, 26, 45, 1, 47, 3, 52, 24, 25, 53, 2, 46,
+ 29, 49, 6, 42, 43, 7, 48, 28, 50, 30, 41, 5, 4, 40, 31, 51,
+ 58, 22, 33, 13, 12, 32, 23, 59, 21, 57, 14, 34, 35, 15, 56, 20,
+ 39, 11, 60, 16, 17, 61, 10, 38, 8, 36, 19, 63, 62, 18, 37, 9,
+ 0, 22, 44, 58, 27, 13, 55, 33, 54, 32, 26, 12, 45, 59, 1, 23,
+ 47, 57, 3, 21, 52, 34, 24, 14, 25, 15, 53, 35, 2, 20, 46, 56,
+ 29, 11, 49, 39, 6, 16, 42, 60, 43, 61, 7, 17, 48, 38, 28, 10,
+ 50, 36, 30, 8, 41, 63, 5, 19, 4, 18, 40, 62, 31, 9, 51, 37,
+ 0, 11, 22, 29, 44, 39, 58, 49, 27, 16, 13, 6, 55, 60, 33, 42,
+ 54, 61, 32, 43, 26, 17, 12, 7, 45, 38, 59, 48, 1, 10, 23, 28,
+ 47, 36, 57, 50, 3, 8, 21, 30, 52, 63, 34, 41, 24, 19, 14, 5,
+ 25, 18, 15, 4, 53, 62, 35, 40, 2, 9, 20, 31, 46, 37, 56, 51,
+ 0, 36, 11, 47, 22, 50, 29, 57, 44, 8, 39, 3, 58, 30, 49, 21,
+ 27, 63, 16, 52, 13, 41, 6, 34, 55, 19, 60, 24, 33, 5, 42, 14,
+ 54, 18, 61, 25, 32, 4, 43, 15, 26, 62, 17, 53, 12, 40, 7, 35,
+ 45, 9, 38, 2, 59, 31, 48, 20, 1, 37, 10, 46, 23, 51, 28, 56,
+ 0, 18, 36, 54, 11, 25, 47, 61, 22, 4, 50, 32, 29, 15, 57, 43,
+ 44, 62, 8, 26, 39, 53, 3, 17, 58, 40, 30, 12, 49, 35, 21, 7,
+ 27, 9, 63, 45, 16, 2, 52, 38, 13, 31, 41, 59, 6, 20, 34, 48,
+ 55, 37, 19, 1, 60, 46, 24, 10, 33, 51, 5, 23, 42, 56, 14, 28,
+ 0, 9, 18, 27, 36, 45, 54, 63, 11, 2, 25, 16, 47, 38, 61, 52,
+ 22, 31, 4, 13, 50, 59, 32, 41, 29, 20, 15, 6, 57, 48, 43, 34,
+ 44, 37, 62, 55, 8, 1, 26, 19, 39, 46, 53, 60, 3, 10, 17, 24,
+ 58, 51, 40, 33, 30, 23, 12, 5, 49, 56, 35, 42, 21, 28, 7, 14,
+ 0, 37, 9, 44, 18, 55, 27, 62, 36, 1, 45, 8, 54, 19, 63, 26,
+ 11, 46, 2, 39, 25, 60, 16, 53, 47, 10, 38, 3, 61, 24, 52, 17,
+ 22, 51, 31, 58, 4, 33, 13, 40, 50, 23, 59, 30, 32, 5, 41, 12,
+ 29, 56, 20, 49, 15, 42, 6, 35, 57, 28, 48, 21, 43, 14, 34, 7,
+ 0, 51, 37, 22, 9, 58, 44, 31, 18, 33, 55, 4, 27, 40, 62, 13,
+ 36, 23, 1, 50, 45, 30, 8, 59, 54, 5, 19, 32, 63, 12, 26, 41,
+ 11, 56, 46, 29, 2, 49, 39, 20, 25, 42, 60, 15, 16, 35, 53, 6,
+ 47, 28, 10, 57, 38, 21, 3, 48, 61, 14, 24, 43, 52, 7, 17, 34,
+ 0, 56, 51, 11, 37, 29, 22, 46, 9, 49, 58, 2, 44, 20, 31, 39,
+ 18, 42, 33, 25, 55, 15, 4, 60, 27, 35, 40, 16, 62, 6, 13, 53,
+ 36, 28, 23, 47, 1, 57, 50, 10, 45, 21, 30, 38, 8, 48, 59, 3,
+ 54, 14, 5, 61, 19, 43, 32, 24, 63, 7, 12, 52, 26, 34, 41, 17,
+ 0, 28, 56, 36, 51, 47, 11, 23, 37, 57, 29, 1, 22, 10, 46, 50,
+ 9, 21, 49, 45, 58, 38, 2, 30, 44, 48, 20, 8, 31, 3, 39, 59,
+ 18, 14, 42, 54, 33, 61, 25, 5, 55, 43, 15, 19, 4, 24, 60, 32,
+ 27, 7, 35, 63, 40, 52, 16, 12, 62, 34, 6, 26, 13, 17, 53, 41,
+ 0, 14, 28, 18, 56, 54, 36, 42, 51, 61, 47, 33, 11, 5, 23, 25,
+ 37, 43, 57, 55, 29, 19, 1, 15, 22, 24, 10, 4, 46, 32, 50, 60,
+ 9, 7, 21, 27, 49, 63, 45, 35, 58, 52, 38, 40, 2, 12, 30, 16,
+ 44, 34, 48, 62, 20, 26, 8, 6, 31, 17, 3, 13, 39, 41, 59, 53,
+ 0, 7, 14, 9, 28, 27, 18, 21, 56, 63, 54, 49, 36, 35, 42, 45,
+ 51, 52, 61, 58, 47, 40, 33, 38, 11, 12, 5, 2, 23, 16, 25, 30,
+ 37, 34, 43, 44, 57, 62, 55, 48, 29, 26, 19, 20, 1, 6, 15, 8,
+ 22, 17, 24, 31, 10, 13, 4, 3, 46, 41, 32, 39, 50, 53, 60, 59,
+ 0, 34, 7, 37, 14, 44, 9, 43, 28, 62, 27, 57, 18, 48, 21, 55,
+ 56, 26, 63, 29, 54, 20, 49, 19, 36, 6, 35, 1, 42, 8, 45, 15,
+ 51, 17, 52, 22, 61, 31, 58, 24, 47, 13, 40, 10, 33, 3, 38, 4,
+ 11, 41, 12, 46, 5, 39, 2, 32, 23, 53, 16, 50, 25, 59, 30, 60,
+ 0, 17, 34, 51, 7, 22, 37, 52, 14, 31, 44, 61, 9, 24, 43, 58,
+ 28, 13, 62, 47, 27, 10, 57, 40, 18, 3, 48, 33, 21, 4, 55, 38,
+ 56, 41, 26, 11, 63, 46, 29, 12, 54, 39, 20, 5, 49, 32, 19, 2,
+ 36, 53, 6, 23, 35, 50, 1, 16, 42, 59, 8, 25, 45, 60, 15, 30,
+ 0, 41, 17, 56, 34, 11, 51, 26, 7, 46, 22, 63, 37, 12, 52, 29,
+ 14, 39, 31, 54, 44, 5, 61, 20, 9, 32, 24, 49, 43, 2, 58, 19,
+ 28, 53, 13, 36, 62, 23, 47, 6, 27, 50, 10, 35, 57, 16, 40, 1,
+ 18, 59, 3, 42, 48, 25, 33, 8, 21, 60, 4, 45, 55, 30, 38, 15,
+ 0, 53, 41, 28, 17, 36, 56, 13, 34, 23, 11, 62, 51, 6, 26, 47,
+ 7, 50, 46, 27, 22, 35, 63, 10, 37, 16, 12, 57, 52, 1, 29, 40,
+ 14, 59, 39, 18, 31, 42, 54, 3, 44, 25, 5, 48, 61, 8, 20, 33,
+ 9, 60, 32, 21, 24, 45, 49, 4, 43, 30, 2, 55, 58, 15, 19, 38,
+ 0, 59, 53, 14, 41, 18, 28, 39, 17, 42, 36, 31, 56, 3, 13, 54,
+ 34, 25, 23, 44, 11, 48, 62, 5, 51, 8, 6, 61, 26, 33, 47, 20,
+ 7, 60, 50, 9, 46, 21, 27, 32, 22, 45, 35, 24, 63, 4, 10, 49,
+ 37, 30, 16, 43, 12, 55, 57, 2, 52, 15, 1, 58, 29, 38, 40, 19,
+ 0, 60, 59, 7, 53, 9, 14, 50, 41, 21, 18, 46, 28, 32, 39, 27,
+ 17, 45, 42, 22, 36, 24, 31, 35, 56, 4, 3, 63, 13, 49, 54, 10,
+ 34, 30, 25, 37, 23, 43, 44, 16, 11, 55, 48, 12, 62, 2, 5, 57,
+ 51, 15, 8, 52, 6, 58, 61, 1, 26, 38, 33, 29, 47, 19, 20, 40,
+ 0, 30, 60, 34, 59, 37, 7, 25, 53, 43, 9, 23, 14, 16, 50, 44,
+ 41, 55, 21, 11, 18, 12, 46, 48, 28, 2, 32, 62, 39, 57, 27, 5,
+ 17, 15, 45, 51, 42, 52, 22, 8, 36, 58, 24, 6, 31, 1, 35, 61,
+ 56, 38, 4, 26, 3, 29, 63, 33, 13, 19, 49, 47, 54, 40, 10, 20,
+ 0, 15, 30, 17, 60, 51, 34, 45, 59, 52, 37, 42, 7, 8, 25, 22,
+ 53, 58, 43, 36, 9, 6, 23, 24, 14, 1, 16, 31, 50, 61, 44, 35,
+ 41, 38, 55, 56, 21, 26, 11, 4, 18, 29, 12, 3, 46, 33, 48, 63,
+ 28, 19, 2, 13, 32, 47, 62, 49, 39, 40, 57, 54, 27, 20, 5, 10,
+ 0, 38, 15, 41, 30, 56, 17, 55, 60, 26, 51, 21, 34, 4, 45, 11,
+ 59, 29, 52, 18, 37, 3, 42, 12, 7, 33, 8, 46, 25, 63, 22, 48,
+ 53, 19, 58, 28, 43, 13, 36, 2, 9, 47, 6, 32, 23, 49, 24, 62,
+ 14, 40, 1, 39, 16, 54, 31, 57, 50, 20, 61, 27, 44, 10, 35, 5,
+ 0, 19, 38, 53, 15, 28, 41, 58, 30, 13, 56, 43, 17, 2, 55, 36,
+ 60, 47, 26, 9, 51, 32, 21, 6, 34, 49, 4, 23, 45, 62, 11, 24,
+ 59, 40, 29, 14, 52, 39, 18, 1, 37, 54, 3, 16, 42, 57, 12, 31,
+ 7, 20, 33, 50, 8, 27, 46, 61, 25, 10, 63, 44, 22, 5, 48, 35,
+ 0, 40, 19, 59, 38, 14, 53, 29, 15, 39, 28, 52, 41, 1, 58, 18,
+ 30, 54, 13, 37, 56, 16, 43, 3, 17, 57, 2, 42, 55, 31, 36, 12,
+ 60, 20, 47, 7, 26, 50, 9, 33, 51, 27, 32, 8, 21, 61, 6, 46,
+ 34, 10, 49, 25, 4, 44, 23, 63, 45, 5, 62, 22, 11, 35, 24, 48,
+ 0, 20, 40, 60, 19, 7, 59, 47, 38, 50, 14, 26, 53, 33, 29, 9,
+ 15, 27, 39, 51, 28, 8, 52, 32, 41, 61, 1, 21, 58, 46, 18, 6,
+ 30, 10, 54, 34, 13, 25, 37, 49, 56, 44, 16, 4, 43, 63, 3, 23,
+ 17, 5, 57, 45, 2, 22, 42, 62, 55, 35, 31, 11, 36, 48, 12, 24,
+ 0, 10, 20, 30, 40, 34, 60, 54, 19, 25, 7, 13, 59, 49, 47, 37,
+ 38, 44, 50, 56, 14, 4, 26, 16, 53, 63, 33, 43, 29, 23, 9, 3,
+ 15, 5, 27, 17, 39, 45, 51, 57, 28, 22, 8, 2, 52, 62, 32, 42,
+ 41, 35, 61, 55, 1, 11, 21, 31, 58, 48, 46, 36, 18, 24, 6, 12,
+ 0, 5, 10, 15, 20, 17, 30, 27, 40, 45, 34, 39, 60, 57, 54, 51,
+ 19, 22, 25, 28, 7, 2, 13, 8, 59, 62, 49, 52, 47, 42, 37, 32,
+ 38, 35, 44, 41, 50, 55, 56, 61, 14, 11, 4, 1, 26, 31, 16, 21,
+ 53, 48, 63, 58, 33, 36, 43, 46, 29, 24, 23, 18, 9, 12, 3, 6,
+ 0, 35, 5, 38, 10, 41, 15, 44, 20, 55, 17, 50, 30, 61, 27, 56,
+ 40, 11, 45, 14, 34, 1, 39, 4, 60, 31, 57, 26, 54, 21, 51, 16,
+ 19, 48, 22, 53, 25, 58, 28, 63, 7, 36, 2, 33, 13, 46, 8, 43,
+ 59, 24, 62, 29, 49, 18, 52, 23, 47, 12, 42, 9, 37, 6, 32, 3,
+ 0, 48, 35, 19, 5, 53, 38, 22, 10, 58, 41, 25, 15, 63, 44, 28,
+ 20, 36, 55, 7, 17, 33, 50, 2, 30, 46, 61, 13, 27, 43, 56, 8,
+ 40, 24, 11, 59, 45, 29, 14, 62, 34, 18, 1, 49, 39, 23, 4, 52,
+ 60, 12, 31, 47, 57, 9, 26, 42, 54, 6, 21, 37, 51, 3, 16, 32,
+ 0, 24, 48, 40, 35, 59, 19, 11, 5, 29, 53, 45, 38, 62, 22, 14,
+ 10, 18, 58, 34, 41, 49, 25, 1, 15, 23, 63, 39, 44, 52, 28, 4,
+ 20, 12, 36, 60, 55, 47, 7, 31, 17, 9, 33, 57, 50, 42, 2, 26,
+ 30, 6, 46, 54, 61, 37, 13, 21, 27, 3, 43, 51, 56, 32, 8, 16,
+ 0, 12, 24, 20, 48, 60, 40, 36, 35, 47, 59, 55, 19, 31, 11, 7,
+ 5, 9, 29, 17, 53, 57, 45, 33, 38, 42, 62, 50, 22, 26, 14, 2,
+ 10, 6, 18, 30, 58, 54, 34, 46, 41, 37, 49, 61, 25, 21, 1, 13,
+ 15, 3, 23, 27, 63, 51, 39, 43, 44, 32, 52, 56, 28, 16, 4, 8,
+ 0, 6, 12, 10, 24, 30, 20, 18, 48, 54, 60, 58, 40, 46, 36, 34,
+ 35, 37, 47, 41, 59, 61, 55, 49, 19, 21, 31, 25, 11, 13, 7, 1,
+ 5, 3, 9, 15, 29, 27, 17, 23, 53, 51, 57, 63, 45, 43, 33, 39,
+ 38, 32, 42, 44, 62, 56, 50, 52, 22, 16, 26, 28, 14, 8, 2, 4,
+ 0, 3, 6, 5, 12, 15, 10, 9, 24, 27, 30, 29, 20, 23, 18, 17,
+ 48, 51, 54, 53, 60, 63, 58, 57, 40, 43, 46, 45, 36, 39, 34, 33,
+ 35, 32, 37, 38, 47, 44, 41, 42, 59, 56, 61, 62, 55, 52, 49, 50,
+ 19, 16, 21, 22, 31, 28, 25, 26, 11, 8, 13, 14, 7, 4, 1, 2,
+ 0, 32, 3, 35, 6, 38, 5, 37, 12, 44, 15, 47, 10, 42, 9, 41,
+ 24, 56, 27, 59, 30, 62, 29, 61, 20, 52, 23, 55, 18, 50, 17, 49,
+ 48, 16, 51, 19, 54, 22, 53, 21, 60, 28, 63, 31, 58, 26, 57, 25,
+ 40, 8, 43, 11, 46, 14, 45, 13, 36, 4, 39, 7, 34, 2, 33, 1,
+ 0, 16, 32, 48, 3, 19, 35, 51, 6, 22, 38, 54, 5, 21, 37, 53,
+ 12, 28, 44, 60, 15, 31, 47, 63, 10, 26, 42, 58, 9, 25, 41, 57,
+ 24, 8, 56, 40, 27, 11, 59, 43, 30, 14, 62, 46, 29, 13, 61, 45,
+ 20, 4, 52, 36, 23, 7, 55, 39, 18, 2, 50, 34, 17, 1, 49, 33,
+ 0, 8, 16, 24, 32, 40, 48, 56, 3, 11, 19, 27, 35, 43, 51, 59,
+ 6, 14, 22, 30, 38, 46, 54, 62, 5, 13, 21, 29, 37, 45, 53, 61,
+ 12, 4, 28, 20, 44, 36, 60, 52, 15, 7, 31, 23, 47, 39, 63, 55,
+ 10, 2, 26, 18, 42, 34, 58, 50, 9, 1, 25, 17, 41, 33, 57, 49,
+ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60,
+ 3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63,
+ 6, 2, 14, 10, 22, 18, 30, 26, 38, 34, 46, 42, 54, 50, 62, 58,
+ 5, 1, 13, 9, 21, 17, 29, 25, 37, 33, 45, 41, 53, 49, 61, 57,
+ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30,
+ 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62,
+ 3, 1, 7, 5, 11, 9, 15, 13, 19, 17, 23, 21, 27, 25, 31, 29,
+ 35, 33, 39, 37, 43, 41, 47, 45, 51, 49, 55, 53, 59, 57, 63, 61
+};
+
+const qracode qra_12_63_64_irr_b = {
+ qra_K,
+ qra_N,
+ qra_m,
+ qra_M,
+ qra_a,
+ qra_NC,
+ qra_V,
+ qra_C,
+ qra_NMSG,
+ qra_MAXVDEG,
+ qra_MAXCDEG,
+ QRATYPE_NORMAL,
+ qra_R,
+ CODE_NAME,
+ qra_acc_input_idx,
+ qra_acc_input_wlog,
+ qra_log,
+ qra_exp,
+ qra_msgw,
+ qra_vdeg,
+ qra_cdeg,
+ qra_v2cmidx,
+ qra_c2vmidx,
+ qra_pmat
+};
+
+#undef qra_K
+#undef qra_N
+#undef qra_m
+#undef qra_M
+#undef qra_a
+#undef qra_NC
+#undef qra_V
+#undef qra_C
+#undef qra_NMSG
+#undef qra_MAXVDEG
+#undef qra_MAXCDEG
+#undef qra_R
+#undef CODE_NAME
\ No newline at end of file
diff --git a/lib/qra/qracodes/qra12_63_64_irr_b.h b/lib/qra/qracodes/qra12_63_64_irr_b.h
new file mode 100644
index 000000000..bf70b3605
--- /dev/null
+++ b/lib/qra/qracodes/qra12_63_64_irr_b.h
@@ -0,0 +1,39 @@
+// qra12_63_64_irr_b.h
+// Code tables and defines for Q-ary RA code (12,63) over GF(64)
+// Code Name: qra12_63_64_irr_b
+// (12,63) RA Code over GF(64) - RF=333344455567
+
+// (c) 2016 - Nico Palermo - IV3NWV - Microtelecom Srl, Italy
+
+// This file is part of the qracodes project, a Forward Error Control
+// encoding/decoding package based on Q-ary RA (Repeat and Accumulate) LDPC codes.
+//
+// qracodes is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+// qracodes is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with qracodes source distribution.
+// If not, see .
+
+#ifndef _qra12_63_64_irr_b_h
+#define _qra12_63_64_irr_b_h
+
+#include "qracodes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern const qracode qra_12_63_64_irr_b;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _qra12_63_64_irr_b_h
diff --git a/lib/qra/qracodes/qra13_64_64_irr_e.c b/lib/qra/qracodes/qra13_64_64_irr_e.c
new file mode 100644
index 000000000..75d6b4884
--- /dev/null
+++ b/lib/qra/qracodes/qra13_64_64_irr_e.c
@@ -0,0 +1,534 @@
+// qra13_64_64_irr_e.c
+// Encoding/Decoding tables for Q-ary RA code (13,64) over GF(64)
+// Code Name: qra13_64_64_irr_e
+// (13,64) RA Code over GF(64) RF=[3x4 4x4 6x1 3x2 5x1 7x1]/18
+
+// (c) 2016 - Nico Palermo - IV3NWV - Microtelecom Srl, Italy
+
+// This file is part of the qracodes project, a Forward Error Control
+// encoding/decoding package based on Q-ary RA (Repeat and Accumulate) LDPC codes.
+//
+// qracodes is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+// qracodes is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with qracodes source distribution.
+// If not, see .
+
+#include "qra13_64_64_irr_e.h"
+
+#define qra_K 13 // number of information symbols
+#define qra_N 64 // codeword length in symbols
+#define qra_m 6 // bits/symbol
+#define qra_M 64 // Symbol alphabet cardinality
+#define qra_a 1 // grouping factor
+#define qra_NC 51 // number of check symbols (N-K)
+
+// Defines used by the message passing decoder --------
+
+#define qra_V 64 // number of variables in the code graph (N)
+#define qra_C 116 // number of factors in the code graph (N +(N-K)+1)
+#define qra_NMSG 218 // number of msgs in the code graph
+#define qra_MAXVDEG 8 // maximum variable degree
+#define qra_MAXCDEG 3 // maximum factor degree
+#define qra_R 0.20313f // code rate (K/N)
+#define CODE_NAME "qra_13_64_64_irr_e"
+
+// table of the systematic symbols indexes in the accumulator chain
+static const int qra_acc_input_idx[qra_NC+1] = {
+ 12, 4, 3, 9, 0, 11, 6, 8, 12, 1,
+ 2, 7, 4, 11, 3, 5, 9, 8, 12, 7,
+ 2, 4, 10, 3, 5, 11, 12, 8, 9, 6,
+ 7, 2, 5, 4, 12, 8, 11, 1, 6, 7,
+ 0, 10, 12, 8, 11, 5, 6, 1, 0, 10,
+ 12, 8
+};
+
+// table of the systematic symbols weight logarithms over GF(M)
+static const unsigned int qra_acc_input_wlog[qra_NC+1] = {
+ 0, 27, 0, 0, 0, 31, 28, 61, 31, 0,
+ 0, 52, 22, 7, 19, 47, 44, 62, 32, 50,
+ 52, 42, 48, 56, 40, 50, 51, 37, 37, 0,
+ 5, 14, 0, 0, 18, 2, 0, 45, 21, 0,
+ 62, 8, 11, 60, 36, 32, 17, 9, 5, 0,
+ 53, 0
+};
+
+// table of the logarithms of the elements of GF(M) (log(0) never used)
+static const int qra_log[qra_M] = {
+ -1, 0, 1, 6, 2, 12, 7, 26, 3, 32,
+ 13, 35, 8, 48, 27, 18, 4, 24, 33, 16,
+ 14, 52, 36, 54, 9, 45, 49, 38, 28, 41,
+ 19, 56, 5, 62, 25, 11, 34, 31, 17, 47,
+ 15, 23, 53, 51, 37, 44, 55, 40, 10, 61,
+ 46, 30, 50, 22, 39, 43, 29, 60, 42, 21,
+ 20, 59, 57, 58
+};
+
+// table of GF(M) elements given their logarithm
+static const unsigned int qra_exp[qra_M-1] = {
+ 1, 2, 4, 8, 16, 32, 3, 6, 12, 24,
+ 48, 35, 5, 10, 20, 40, 19, 38, 15, 30,
+ 60, 59, 53, 41, 17, 34, 7, 14, 28, 56,
+ 51, 37, 9, 18, 36, 11, 22, 44, 27, 54,
+ 47, 29, 58, 55, 45, 25, 50, 39, 13, 26,
+ 52, 43, 21, 42, 23, 46, 31, 62, 63, 61,
+ 57, 49, 33
+};
+
+// table of the messages weight logarithms over GF(M)
+static const unsigned int qra_msgw[qra_NMSG] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 27, 0, 0, 0, 31,
+ 28, 61, 31, 0, 0, 52, 22, 7, 19, 47,
+ 44, 62, 32, 50, 52, 42, 48, 56, 40, 50,
+ 51, 37, 37, 0, 5, 14, 0, 0, 18, 2,
+ 0, 45, 21, 0, 62, 8, 11, 60, 36, 32,
+ 17, 9, 5, 0, 53, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+// table of the degrees of the variable nodes
+static const unsigned int qra_vdeg[qra_V] = {
+ 4, 4, 4, 4, 5, 5, 5, 5, 7, 4,
+ 4, 6, 8, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3
+};
+
+// table of the degrees of the factor nodes
+static const unsigned int qra_cdeg[qra_C] = {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 2, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 2
+};
+
+// table (uncompressed) of the v->c message indexes (-1=unused entry)
+static const int qra_v2cmidx[qra_V*qra_MAXVDEG] = {
+ 0, 68, 104, 112, -1, -1, -1, -1,
+ 1, 73, 101, 111, -1, -1, -1, -1,
+ 2, 74, 84, 95, -1, -1, -1, -1,
+ 3, 66, 78, 87, -1, -1, -1, -1,
+ 4, 65, 76, 85, 97, -1, -1, -1,
+ 5, 79, 88, 96, 109, -1, -1, -1,
+ 6, 70, 93, 102, 110, -1, -1, -1,
+ 7, 75, 83, 94, 103, -1, -1, -1,
+ 8, 71, 81, 91, 99, 107, 115, -1,
+ 9, 67, 80, 92, -1, -1, -1, -1,
+ 10, 86, 105, 113, -1, -1, -1, -1,
+ 11, 69, 77, 89, 100, 108, -1, -1,
+ 12, 64, 72, 82, 90, 98, 106, 114,
+ 13, 116, 117, -1, -1, -1, -1, -1,
+ 14, 118, 119, -1, -1, -1, -1, -1,
+ 15, 120, 121, -1, -1, -1, -1, -1,
+ 16, 122, 123, -1, -1, -1, -1, -1,
+ 17, 124, 125, -1, -1, -1, -1, -1,
+ 18, 126, 127, -1, -1, -1, -1, -1,
+ 19, 128, 129, -1, -1, -1, -1, -1,
+ 20, 130, 131, -1, -1, -1, -1, -1,
+ 21, 132, 133, -1, -1, -1, -1, -1,
+ 22, 134, 135, -1, -1, -1, -1, -1,
+ 23, 136, 137, -1, -1, -1, -1, -1,
+ 24, 138, 139, -1, -1, -1, -1, -1,
+ 25, 140, 141, -1, -1, -1, -1, -1,
+ 26, 142, 143, -1, -1, -1, -1, -1,
+ 27, 144, 145, -1, -1, -1, -1, -1,
+ 28, 146, 147, -1, -1, -1, -1, -1,
+ 29, 148, 149, -1, -1, -1, -1, -1,
+ 30, 150, 151, -1, -1, -1, -1, -1,
+ 31, 152, 153, -1, -1, -1, -1, -1,
+ 32, 154, 155, -1, -1, -1, -1, -1,
+ 33, 156, 157, -1, -1, -1, -1, -1,
+ 34, 158, 159, -1, -1, -1, -1, -1,
+ 35, 160, 161, -1, -1, -1, -1, -1,
+ 36, 162, 163, -1, -1, -1, -1, -1,
+ 37, 164, 165, -1, -1, -1, -1, -1,
+ 38, 166, 167, -1, -1, -1, -1, -1,
+ 39, 168, 169, -1, -1, -1, -1, -1,
+ 40, 170, 171, -1, -1, -1, -1, -1,
+ 41, 172, 173, -1, -1, -1, -1, -1,
+ 42, 174, 175, -1, -1, -1, -1, -1,
+ 43, 176, 177, -1, -1, -1, -1, -1,
+ 44, 178, 179, -1, -1, -1, -1, -1,
+ 45, 180, 181, -1, -1, -1, -1, -1,
+ 46, 182, 183, -1, -1, -1, -1, -1,
+ 47, 184, 185, -1, -1, -1, -1, -1,
+ 48, 186, 187, -1, -1, -1, -1, -1,
+ 49, 188, 189, -1, -1, -1, -1, -1,
+ 50, 190, 191, -1, -1, -1, -1, -1,
+ 51, 192, 193, -1, -1, -1, -1, -1,
+ 52, 194, 195, -1, -1, -1, -1, -1,
+ 53, 196, 197, -1, -1, -1, -1, -1,
+ 54, 198, 199, -1, -1, -1, -1, -1,
+ 55, 200, 201, -1, -1, -1, -1, -1,
+ 56, 202, 203, -1, -1, -1, -1, -1,
+ 57, 204, 205, -1, -1, -1, -1, -1,
+ 58, 206, 207, -1, -1, -1, -1, -1,
+ 59, 208, 209, -1, -1, -1, -1, -1,
+ 60, 210, 211, -1, -1, -1, -1, -1,
+ 61, 212, 213, -1, -1, -1, -1, -1,
+ 62, 214, 215, -1, -1, -1, -1, -1,
+ 63, 216, 217, -1, -1, -1, -1, -1
+};
+
+// table (uncompressed) of the c->v message indexes (-1=unused entry)
+static const int qra_c2vmidx[qra_C*qra_MAXCDEG] = {
+ 0, -1, -1, 1, -1, -1, 2, -1, -1, 3, -1, -1,
+ 4, -1, -1, 5, -1, -1, 6, -1, -1, 7, -1, -1,
+ 8, -1, -1, 9, -1, -1, 10, -1, -1, 11, -1, -1,
+ 12, -1, -1, 13, -1, -1, 14, -1, -1, 15, -1, -1,
+ 16, -1, -1, 17, -1, -1, 18, -1, -1, 19, -1, -1,
+ 20, -1, -1, 21, -1, -1, 22, -1, -1, 23, -1, -1,
+ 24, -1, -1, 25, -1, -1, 26, -1, -1, 27, -1, -1,
+ 28, -1, -1, 29, -1, -1, 30, -1, -1, 31, -1, -1,
+ 32, -1, -1, 33, -1, -1, 34, -1, -1, 35, -1, -1,
+ 36, -1, -1, 37, -1, -1, 38, -1, -1, 39, -1, -1,
+ 40, -1, -1, 41, -1, -1, 42, -1, -1, 43, -1, -1,
+ 44, -1, -1, 45, -1, -1, 46, -1, -1, 47, -1, -1,
+ 48, -1, -1, 49, -1, -1, 50, -1, -1, 51, -1, -1,
+ 52, -1, -1, 53, -1, -1, 54, -1, -1, 55, -1, -1,
+ 56, -1, -1, 57, -1, -1, 58, -1, -1, 59, -1, -1,
+ 60, -1, -1, 61, -1, -1, 62, -1, -1, 63, -1, -1,
+ 64, 116, -1, 65, 117, 118, 66, 119, 120, 67, 121, 122,
+ 68, 123, 124, 69, 125, 126, 70, 127, 128, 71, 129, 130,
+ 72, 131, 132, 73, 133, 134, 74, 135, 136, 75, 137, 138,
+ 76, 139, 140, 77, 141, 142, 78, 143, 144, 79, 145, 146,
+ 80, 147, 148, 81, 149, 150, 82, 151, 152, 83, 153, 154,
+ 84, 155, 156, 85, 157, 158, 86, 159, 160, 87, 161, 162,
+ 88, 163, 164, 89, 165, 166, 90, 167, 168, 91, 169, 170,
+ 92, 171, 172, 93, 173, 174, 94, 175, 176, 95, 177, 178,
+ 96, 179, 180, 97, 181, 182, 98, 183, 184, 99, 185, 186,
+100, 187, 188, 101, 189, 190, 102, 191, 192, 103, 193, 194,
+104, 195, 196, 105, 197, 198, 106, 199, 200, 107, 201, 202,
+108, 203, 204, 109, 205, 206, 110, 207, 208, 111, 209, 210,
+112, 211, 212, 113, 213, 214, 114, 215, 216, 115, 217, -1
+};
+
+// permutation matrix to compute Prob(x*alfa^logw)
+static const unsigned int qra_pmat[qra_M*qra_M] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 33, 1, 32, 2, 35, 3, 34, 4, 37, 5, 36, 6, 39, 7, 38,
+ 8, 41, 9, 40, 10, 43, 11, 42, 12, 45, 13, 44, 14, 47, 15, 46,
+ 16, 49, 17, 48, 18, 51, 19, 50, 20, 53, 21, 52, 22, 55, 23, 54,
+ 24, 57, 25, 56, 26, 59, 27, 58, 28, 61, 29, 60, 30, 63, 31, 62,
+ 0, 49, 33, 16, 1, 48, 32, 17, 2, 51, 35, 18, 3, 50, 34, 19,
+ 4, 53, 37, 20, 5, 52, 36, 21, 6, 55, 39, 22, 7, 54, 38, 23,
+ 8, 57, 41, 24, 9, 56, 40, 25, 10, 59, 43, 26, 11, 58, 42, 27,
+ 12, 61, 45, 28, 13, 60, 44, 29, 14, 63, 47, 30, 15, 62, 46, 31,
+ 0, 57, 49, 8, 33, 24, 16, 41, 1, 56, 48, 9, 32, 25, 17, 40,
+ 2, 59, 51, 10, 35, 26, 18, 43, 3, 58, 50, 11, 34, 27, 19, 42,
+ 4, 61, 53, 12, 37, 28, 20, 45, 5, 60, 52, 13, 36, 29, 21, 44,
+ 6, 63, 55, 14, 39, 30, 22, 47, 7, 62, 54, 15, 38, 31, 23, 46,
+ 0, 61, 57, 4, 49, 12, 8, 53, 33, 28, 24, 37, 16, 45, 41, 20,
+ 1, 60, 56, 5, 48, 13, 9, 52, 32, 29, 25, 36, 17, 44, 40, 21,
+ 2, 63, 59, 6, 51, 14, 10, 55, 35, 30, 26, 39, 18, 47, 43, 22,
+ 3, 62, 58, 7, 50, 15, 11, 54, 34, 31, 27, 38, 19, 46, 42, 23,
+ 0, 63, 61, 2, 57, 6, 4, 59, 49, 14, 12, 51, 8, 55, 53, 10,
+ 33, 30, 28, 35, 24, 39, 37, 26, 16, 47, 45, 18, 41, 22, 20, 43,
+ 1, 62, 60, 3, 56, 7, 5, 58, 48, 15, 13, 50, 9, 54, 52, 11,
+ 32, 31, 29, 34, 25, 38, 36, 27, 17, 46, 44, 19, 40, 23, 21, 42,
+ 0, 62, 63, 1, 61, 3, 2, 60, 57, 7, 6, 56, 4, 58, 59, 5,
+ 49, 15, 14, 48, 12, 50, 51, 13, 8, 54, 55, 9, 53, 11, 10, 52,
+ 33, 31, 30, 32, 28, 34, 35, 29, 24, 38, 39, 25, 37, 27, 26, 36,
+ 16, 46, 47, 17, 45, 19, 18, 44, 41, 23, 22, 40, 20, 42, 43, 21,
+ 0, 31, 62, 33, 63, 32, 1, 30, 61, 34, 3, 28, 2, 29, 60, 35,
+ 57, 38, 7, 24, 6, 25, 56, 39, 4, 27, 58, 37, 59, 36, 5, 26,
+ 49, 46, 15, 16, 14, 17, 48, 47, 12, 19, 50, 45, 51, 44, 13, 18,
+ 8, 23, 54, 41, 55, 40, 9, 22, 53, 42, 11, 20, 10, 21, 52, 43,
+ 0, 46, 31, 49, 62, 16, 33, 15, 63, 17, 32, 14, 1, 47, 30, 48,
+ 61, 19, 34, 12, 3, 45, 28, 50, 2, 44, 29, 51, 60, 18, 35, 13,
+ 57, 23, 38, 8, 7, 41, 24, 54, 6, 40, 25, 55, 56, 22, 39, 9,
+ 4, 42, 27, 53, 58, 20, 37, 11, 59, 21, 36, 10, 5, 43, 26, 52,
+ 0, 23, 46, 57, 31, 8, 49, 38, 62, 41, 16, 7, 33, 54, 15, 24,
+ 63, 40, 17, 6, 32, 55, 14, 25, 1, 22, 47, 56, 30, 9, 48, 39,
+ 61, 42, 19, 4, 34, 53, 12, 27, 3, 20, 45, 58, 28, 11, 50, 37,
+ 2, 21, 44, 59, 29, 10, 51, 36, 60, 43, 18, 5, 35, 52, 13, 26,
+ 0, 42, 23, 61, 46, 4, 57, 19, 31, 53, 8, 34, 49, 27, 38, 12,
+ 62, 20, 41, 3, 16, 58, 7, 45, 33, 11, 54, 28, 15, 37, 24, 50,
+ 63, 21, 40, 2, 17, 59, 6, 44, 32, 10, 55, 29, 14, 36, 25, 51,
+ 1, 43, 22, 60, 47, 5, 56, 18, 30, 52, 9, 35, 48, 26, 39, 13,
+ 0, 21, 42, 63, 23, 2, 61, 40, 46, 59, 4, 17, 57, 44, 19, 6,
+ 31, 10, 53, 32, 8, 29, 34, 55, 49, 36, 27, 14, 38, 51, 12, 25,
+ 62, 43, 20, 1, 41, 60, 3, 22, 16, 5, 58, 47, 7, 18, 45, 56,
+ 33, 52, 11, 30, 54, 35, 28, 9, 15, 26, 37, 48, 24, 13, 50, 39,
+ 0, 43, 21, 62, 42, 1, 63, 20, 23, 60, 2, 41, 61, 22, 40, 3,
+ 46, 5, 59, 16, 4, 47, 17, 58, 57, 18, 44, 7, 19, 56, 6, 45,
+ 31, 52, 10, 33, 53, 30, 32, 11, 8, 35, 29, 54, 34, 9, 55, 28,
+ 49, 26, 36, 15, 27, 48, 14, 37, 38, 13, 51, 24, 12, 39, 25, 50,
+ 0, 52, 43, 31, 21, 33, 62, 10, 42, 30, 1, 53, 63, 11, 20, 32,
+ 23, 35, 60, 8, 2, 54, 41, 29, 61, 9, 22, 34, 40, 28, 3, 55,
+ 46, 26, 5, 49, 59, 15, 16, 36, 4, 48, 47, 27, 17, 37, 58, 14,
+ 57, 13, 18, 38, 44, 24, 7, 51, 19, 39, 56, 12, 6, 50, 45, 25,
+ 0, 26, 52, 46, 43, 49, 31, 5, 21, 15, 33, 59, 62, 36, 10, 16,
+ 42, 48, 30, 4, 1, 27, 53, 47, 63, 37, 11, 17, 20, 14, 32, 58,
+ 23, 13, 35, 57, 60, 38, 8, 18, 2, 24, 54, 44, 41, 51, 29, 7,
+ 61, 39, 9, 19, 22, 12, 34, 56, 40, 50, 28, 6, 3, 25, 55, 45,
+ 0, 13, 26, 23, 52, 57, 46, 35, 43, 38, 49, 60, 31, 18, 5, 8,
+ 21, 24, 15, 2, 33, 44, 59, 54, 62, 51, 36, 41, 10, 7, 16, 29,
+ 42, 39, 48, 61, 30, 19, 4, 9, 1, 12, 27, 22, 53, 56, 47, 34,
+ 63, 50, 37, 40, 11, 6, 17, 28, 20, 25, 14, 3, 32, 45, 58, 55,
+ 0, 39, 13, 42, 26, 61, 23, 48, 52, 19, 57, 30, 46, 9, 35, 4,
+ 43, 12, 38, 1, 49, 22, 60, 27, 31, 56, 18, 53, 5, 34, 8, 47,
+ 21, 50, 24, 63, 15, 40, 2, 37, 33, 6, 44, 11, 59, 28, 54, 17,
+ 62, 25, 51, 20, 36, 3, 41, 14, 10, 45, 7, 32, 16, 55, 29, 58,
+ 0, 50, 39, 21, 13, 63, 42, 24, 26, 40, 61, 15, 23, 37, 48, 2,
+ 52, 6, 19, 33, 57, 11, 30, 44, 46, 28, 9, 59, 35, 17, 4, 54,
+ 43, 25, 12, 62, 38, 20, 1, 51, 49, 3, 22, 36, 60, 14, 27, 41,
+ 31, 45, 56, 10, 18, 32, 53, 7, 5, 55, 34, 16, 8, 58, 47, 29,
+ 0, 25, 50, 43, 39, 62, 21, 12, 13, 20, 63, 38, 42, 51, 24, 1,
+ 26, 3, 40, 49, 61, 36, 15, 22, 23, 14, 37, 60, 48, 41, 2, 27,
+ 52, 45, 6, 31, 19, 10, 33, 56, 57, 32, 11, 18, 30, 7, 44, 53,
+ 46, 55, 28, 5, 9, 16, 59, 34, 35, 58, 17, 8, 4, 29, 54, 47,
+ 0, 45, 25, 52, 50, 31, 43, 6, 39, 10, 62, 19, 21, 56, 12, 33,
+ 13, 32, 20, 57, 63, 18, 38, 11, 42, 7, 51, 30, 24, 53, 1, 44,
+ 26, 55, 3, 46, 40, 5, 49, 28, 61, 16, 36, 9, 15, 34, 22, 59,
+ 23, 58, 14, 35, 37, 8, 60, 17, 48, 29, 41, 4, 2, 47, 27, 54,
+ 0, 55, 45, 26, 25, 46, 52, 3, 50, 5, 31, 40, 43, 28, 6, 49,
+ 39, 16, 10, 61, 62, 9, 19, 36, 21, 34, 56, 15, 12, 59, 33, 22,
+ 13, 58, 32, 23, 20, 35, 57, 14, 63, 8, 18, 37, 38, 17, 11, 60,
+ 42, 29, 7, 48, 51, 4, 30, 41, 24, 47, 53, 2, 1, 54, 44, 27,
+ 0, 58, 55, 13, 45, 23, 26, 32, 25, 35, 46, 20, 52, 14, 3, 57,
+ 50, 8, 5, 63, 31, 37, 40, 18, 43, 17, 28, 38, 6, 60, 49, 11,
+ 39, 29, 16, 42, 10, 48, 61, 7, 62, 4, 9, 51, 19, 41, 36, 30,
+ 21, 47, 34, 24, 56, 2, 15, 53, 12, 54, 59, 1, 33, 27, 22, 44,
+ 0, 29, 58, 39, 55, 42, 13, 16, 45, 48, 23, 10, 26, 7, 32, 61,
+ 25, 4, 35, 62, 46, 51, 20, 9, 52, 41, 14, 19, 3, 30, 57, 36,
+ 50, 47, 8, 21, 5, 24, 63, 34, 31, 2, 37, 56, 40, 53, 18, 15,
+ 43, 54, 17, 12, 28, 1, 38, 59, 6, 27, 60, 33, 49, 44, 11, 22,
+ 0, 47, 29, 50, 58, 21, 39, 8, 55, 24, 42, 5, 13, 34, 16, 63,
+ 45, 2, 48, 31, 23, 56, 10, 37, 26, 53, 7, 40, 32, 15, 61, 18,
+ 25, 54, 4, 43, 35, 12, 62, 17, 46, 1, 51, 28, 20, 59, 9, 38,
+ 52, 27, 41, 6, 14, 33, 19, 60, 3, 44, 30, 49, 57, 22, 36, 11,
+ 0, 54, 47, 25, 29, 43, 50, 4, 58, 12, 21, 35, 39, 17, 8, 62,
+ 55, 1, 24, 46, 42, 28, 5, 51, 13, 59, 34, 20, 16, 38, 63, 9,
+ 45, 27, 2, 52, 48, 6, 31, 41, 23, 33, 56, 14, 10, 60, 37, 19,
+ 26, 44, 53, 3, 7, 49, 40, 30, 32, 22, 15, 57, 61, 11, 18, 36,
+ 0, 27, 54, 45, 47, 52, 25, 2, 29, 6, 43, 48, 50, 41, 4, 31,
+ 58, 33, 12, 23, 21, 14, 35, 56, 39, 60, 17, 10, 8, 19, 62, 37,
+ 55, 44, 1, 26, 24, 3, 46, 53, 42, 49, 28, 7, 5, 30, 51, 40,
+ 13, 22, 59, 32, 34, 57, 20, 15, 16, 11, 38, 61, 63, 36, 9, 18,
+ 0, 44, 27, 55, 54, 26, 45, 1, 47, 3, 52, 24, 25, 53, 2, 46,
+ 29, 49, 6, 42, 43, 7, 48, 28, 50, 30, 41, 5, 4, 40, 31, 51,
+ 58, 22, 33, 13, 12, 32, 23, 59, 21, 57, 14, 34, 35, 15, 56, 20,
+ 39, 11, 60, 16, 17, 61, 10, 38, 8, 36, 19, 63, 62, 18, 37, 9,
+ 0, 22, 44, 58, 27, 13, 55, 33, 54, 32, 26, 12, 45, 59, 1, 23,
+ 47, 57, 3, 21, 52, 34, 24, 14, 25, 15, 53, 35, 2, 20, 46, 56,
+ 29, 11, 49, 39, 6, 16, 42, 60, 43, 61, 7, 17, 48, 38, 28, 10,
+ 50, 36, 30, 8, 41, 63, 5, 19, 4, 18, 40, 62, 31, 9, 51, 37,
+ 0, 11, 22, 29, 44, 39, 58, 49, 27, 16, 13, 6, 55, 60, 33, 42,
+ 54, 61, 32, 43, 26, 17, 12, 7, 45, 38, 59, 48, 1, 10, 23, 28,
+ 47, 36, 57, 50, 3, 8, 21, 30, 52, 63, 34, 41, 24, 19, 14, 5,
+ 25, 18, 15, 4, 53, 62, 35, 40, 2, 9, 20, 31, 46, 37, 56, 51,
+ 0, 36, 11, 47, 22, 50, 29, 57, 44, 8, 39, 3, 58, 30, 49, 21,
+ 27, 63, 16, 52, 13, 41, 6, 34, 55, 19, 60, 24, 33, 5, 42, 14,
+ 54, 18, 61, 25, 32, 4, 43, 15, 26, 62, 17, 53, 12, 40, 7, 35,
+ 45, 9, 38, 2, 59, 31, 48, 20, 1, 37, 10, 46, 23, 51, 28, 56,
+ 0, 18, 36, 54, 11, 25, 47, 61, 22, 4, 50, 32, 29, 15, 57, 43,
+ 44, 62, 8, 26, 39, 53, 3, 17, 58, 40, 30, 12, 49, 35, 21, 7,
+ 27, 9, 63, 45, 16, 2, 52, 38, 13, 31, 41, 59, 6, 20, 34, 48,
+ 55, 37, 19, 1, 60, 46, 24, 10, 33, 51, 5, 23, 42, 56, 14, 28,
+ 0, 9, 18, 27, 36, 45, 54, 63, 11, 2, 25, 16, 47, 38, 61, 52,
+ 22, 31, 4, 13, 50, 59, 32, 41, 29, 20, 15, 6, 57, 48, 43, 34,
+ 44, 37, 62, 55, 8, 1, 26, 19, 39, 46, 53, 60, 3, 10, 17, 24,
+ 58, 51, 40, 33, 30, 23, 12, 5, 49, 56, 35, 42, 21, 28, 7, 14,
+ 0, 37, 9, 44, 18, 55, 27, 62, 36, 1, 45, 8, 54, 19, 63, 26,
+ 11, 46, 2, 39, 25, 60, 16, 53, 47, 10, 38, 3, 61, 24, 52, 17,
+ 22, 51, 31, 58, 4, 33, 13, 40, 50, 23, 59, 30, 32, 5, 41, 12,
+ 29, 56, 20, 49, 15, 42, 6, 35, 57, 28, 48, 21, 43, 14, 34, 7,
+ 0, 51, 37, 22, 9, 58, 44, 31, 18, 33, 55, 4, 27, 40, 62, 13,
+ 36, 23, 1, 50, 45, 30, 8, 59, 54, 5, 19, 32, 63, 12, 26, 41,
+ 11, 56, 46, 29, 2, 49, 39, 20, 25, 42, 60, 15, 16, 35, 53, 6,
+ 47, 28, 10, 57, 38, 21, 3, 48, 61, 14, 24, 43, 52, 7, 17, 34,
+ 0, 56, 51, 11, 37, 29, 22, 46, 9, 49, 58, 2, 44, 20, 31, 39,
+ 18, 42, 33, 25, 55, 15, 4, 60, 27, 35, 40, 16, 62, 6, 13, 53,
+ 36, 28, 23, 47, 1, 57, 50, 10, 45, 21, 30, 38, 8, 48, 59, 3,
+ 54, 14, 5, 61, 19, 43, 32, 24, 63, 7, 12, 52, 26, 34, 41, 17,
+ 0, 28, 56, 36, 51, 47, 11, 23, 37, 57, 29, 1, 22, 10, 46, 50,
+ 9, 21, 49, 45, 58, 38, 2, 30, 44, 48, 20, 8, 31, 3, 39, 59,
+ 18, 14, 42, 54, 33, 61, 25, 5, 55, 43, 15, 19, 4, 24, 60, 32,
+ 27, 7, 35, 63, 40, 52, 16, 12, 62, 34, 6, 26, 13, 17, 53, 41,
+ 0, 14, 28, 18, 56, 54, 36, 42, 51, 61, 47, 33, 11, 5, 23, 25,
+ 37, 43, 57, 55, 29, 19, 1, 15, 22, 24, 10, 4, 46, 32, 50, 60,
+ 9, 7, 21, 27, 49, 63, 45, 35, 58, 52, 38, 40, 2, 12, 30, 16,
+ 44, 34, 48, 62, 20, 26, 8, 6, 31, 17, 3, 13, 39, 41, 59, 53,
+ 0, 7, 14, 9, 28, 27, 18, 21, 56, 63, 54, 49, 36, 35, 42, 45,
+ 51, 52, 61, 58, 47, 40, 33, 38, 11, 12, 5, 2, 23, 16, 25, 30,
+ 37, 34, 43, 44, 57, 62, 55, 48, 29, 26, 19, 20, 1, 6, 15, 8,
+ 22, 17, 24, 31, 10, 13, 4, 3, 46, 41, 32, 39, 50, 53, 60, 59,
+ 0, 34, 7, 37, 14, 44, 9, 43, 28, 62, 27, 57, 18, 48, 21, 55,
+ 56, 26, 63, 29, 54, 20, 49, 19, 36, 6, 35, 1, 42, 8, 45, 15,
+ 51, 17, 52, 22, 61, 31, 58, 24, 47, 13, 40, 10, 33, 3, 38, 4,
+ 11, 41, 12, 46, 5, 39, 2, 32, 23, 53, 16, 50, 25, 59, 30, 60,
+ 0, 17, 34, 51, 7, 22, 37, 52, 14, 31, 44, 61, 9, 24, 43, 58,
+ 28, 13, 62, 47, 27, 10, 57, 40, 18, 3, 48, 33, 21, 4, 55, 38,
+ 56, 41, 26, 11, 63, 46, 29, 12, 54, 39, 20, 5, 49, 32, 19, 2,
+ 36, 53, 6, 23, 35, 50, 1, 16, 42, 59, 8, 25, 45, 60, 15, 30,
+ 0, 41, 17, 56, 34, 11, 51, 26, 7, 46, 22, 63, 37, 12, 52, 29,
+ 14, 39, 31, 54, 44, 5, 61, 20, 9, 32, 24, 49, 43, 2, 58, 19,
+ 28, 53, 13, 36, 62, 23, 47, 6, 27, 50, 10, 35, 57, 16, 40, 1,
+ 18, 59, 3, 42, 48, 25, 33, 8, 21, 60, 4, 45, 55, 30, 38, 15,
+ 0, 53, 41, 28, 17, 36, 56, 13, 34, 23, 11, 62, 51, 6, 26, 47,
+ 7, 50, 46, 27, 22, 35, 63, 10, 37, 16, 12, 57, 52, 1, 29, 40,
+ 14, 59, 39, 18, 31, 42, 54, 3, 44, 25, 5, 48, 61, 8, 20, 33,
+ 9, 60, 32, 21, 24, 45, 49, 4, 43, 30, 2, 55, 58, 15, 19, 38,
+ 0, 59, 53, 14, 41, 18, 28, 39, 17, 42, 36, 31, 56, 3, 13, 54,
+ 34, 25, 23, 44, 11, 48, 62, 5, 51, 8, 6, 61, 26, 33, 47, 20,
+ 7, 60, 50, 9, 46, 21, 27, 32, 22, 45, 35, 24, 63, 4, 10, 49,
+ 37, 30, 16, 43, 12, 55, 57, 2, 52, 15, 1, 58, 29, 38, 40, 19,
+ 0, 60, 59, 7, 53, 9, 14, 50, 41, 21, 18, 46, 28, 32, 39, 27,
+ 17, 45, 42, 22, 36, 24, 31, 35, 56, 4, 3, 63, 13, 49, 54, 10,
+ 34, 30, 25, 37, 23, 43, 44, 16, 11, 55, 48, 12, 62, 2, 5, 57,
+ 51, 15, 8, 52, 6, 58, 61, 1, 26, 38, 33, 29, 47, 19, 20, 40,
+ 0, 30, 60, 34, 59, 37, 7, 25, 53, 43, 9, 23, 14, 16, 50, 44,
+ 41, 55, 21, 11, 18, 12, 46, 48, 28, 2, 32, 62, 39, 57, 27, 5,
+ 17, 15, 45, 51, 42, 52, 22, 8, 36, 58, 24, 6, 31, 1, 35, 61,
+ 56, 38, 4, 26, 3, 29, 63, 33, 13, 19, 49, 47, 54, 40, 10, 20,
+ 0, 15, 30, 17, 60, 51, 34, 45, 59, 52, 37, 42, 7, 8, 25, 22,
+ 53, 58, 43, 36, 9, 6, 23, 24, 14, 1, 16, 31, 50, 61, 44, 35,
+ 41, 38, 55, 56, 21, 26, 11, 4, 18, 29, 12, 3, 46, 33, 48, 63,
+ 28, 19, 2, 13, 32, 47, 62, 49, 39, 40, 57, 54, 27, 20, 5, 10,
+ 0, 38, 15, 41, 30, 56, 17, 55, 60, 26, 51, 21, 34, 4, 45, 11,
+ 59, 29, 52, 18, 37, 3, 42, 12, 7, 33, 8, 46, 25, 63, 22, 48,
+ 53, 19, 58, 28, 43, 13, 36, 2, 9, 47, 6, 32, 23, 49, 24, 62,
+ 14, 40, 1, 39, 16, 54, 31, 57, 50, 20, 61, 27, 44, 10, 35, 5,
+ 0, 19, 38, 53, 15, 28, 41, 58, 30, 13, 56, 43, 17, 2, 55, 36,
+ 60, 47, 26, 9, 51, 32, 21, 6, 34, 49, 4, 23, 45, 62, 11, 24,
+ 59, 40, 29, 14, 52, 39, 18, 1, 37, 54, 3, 16, 42, 57, 12, 31,
+ 7, 20, 33, 50, 8, 27, 46, 61, 25, 10, 63, 44, 22, 5, 48, 35,
+ 0, 40, 19, 59, 38, 14, 53, 29, 15, 39, 28, 52, 41, 1, 58, 18,
+ 30, 54, 13, 37, 56, 16, 43, 3, 17, 57, 2, 42, 55, 31, 36, 12,
+ 60, 20, 47, 7, 26, 50, 9, 33, 51, 27, 32, 8, 21, 61, 6, 46,
+ 34, 10, 49, 25, 4, 44, 23, 63, 45, 5, 62, 22, 11, 35, 24, 48,
+ 0, 20, 40, 60, 19, 7, 59, 47, 38, 50, 14, 26, 53, 33, 29, 9,
+ 15, 27, 39, 51, 28, 8, 52, 32, 41, 61, 1, 21, 58, 46, 18, 6,
+ 30, 10, 54, 34, 13, 25, 37, 49, 56, 44, 16, 4, 43, 63, 3, 23,
+ 17, 5, 57, 45, 2, 22, 42, 62, 55, 35, 31, 11, 36, 48, 12, 24,
+ 0, 10, 20, 30, 40, 34, 60, 54, 19, 25, 7, 13, 59, 49, 47, 37,
+ 38, 44, 50, 56, 14, 4, 26, 16, 53, 63, 33, 43, 29, 23, 9, 3,
+ 15, 5, 27, 17, 39, 45, 51, 57, 28, 22, 8, 2, 52, 62, 32, 42,
+ 41, 35, 61, 55, 1, 11, 21, 31, 58, 48, 46, 36, 18, 24, 6, 12,
+ 0, 5, 10, 15, 20, 17, 30, 27, 40, 45, 34, 39, 60, 57, 54, 51,
+ 19, 22, 25, 28, 7, 2, 13, 8, 59, 62, 49, 52, 47, 42, 37, 32,
+ 38, 35, 44, 41, 50, 55, 56, 61, 14, 11, 4, 1, 26, 31, 16, 21,
+ 53, 48, 63, 58, 33, 36, 43, 46, 29, 24, 23, 18, 9, 12, 3, 6,
+ 0, 35, 5, 38, 10, 41, 15, 44, 20, 55, 17, 50, 30, 61, 27, 56,
+ 40, 11, 45, 14, 34, 1, 39, 4, 60, 31, 57, 26, 54, 21, 51, 16,
+ 19, 48, 22, 53, 25, 58, 28, 63, 7, 36, 2, 33, 13, 46, 8, 43,
+ 59, 24, 62, 29, 49, 18, 52, 23, 47, 12, 42, 9, 37, 6, 32, 3,
+ 0, 48, 35, 19, 5, 53, 38, 22, 10, 58, 41, 25, 15, 63, 44, 28,
+ 20, 36, 55, 7, 17, 33, 50, 2, 30, 46, 61, 13, 27, 43, 56, 8,
+ 40, 24, 11, 59, 45, 29, 14, 62, 34, 18, 1, 49, 39, 23, 4, 52,
+ 60, 12, 31, 47, 57, 9, 26, 42, 54, 6, 21, 37, 51, 3, 16, 32,
+ 0, 24, 48, 40, 35, 59, 19, 11, 5, 29, 53, 45, 38, 62, 22, 14,
+ 10, 18, 58, 34, 41, 49, 25, 1, 15, 23, 63, 39, 44, 52, 28, 4,
+ 20, 12, 36, 60, 55, 47, 7, 31, 17, 9, 33, 57, 50, 42, 2, 26,
+ 30, 6, 46, 54, 61, 37, 13, 21, 27, 3, 43, 51, 56, 32, 8, 16,
+ 0, 12, 24, 20, 48, 60, 40, 36, 35, 47, 59, 55, 19, 31, 11, 7,
+ 5, 9, 29, 17, 53, 57, 45, 33, 38, 42, 62, 50, 22, 26, 14, 2,
+ 10, 6, 18, 30, 58, 54, 34, 46, 41, 37, 49, 61, 25, 21, 1, 13,
+ 15, 3, 23, 27, 63, 51, 39, 43, 44, 32, 52, 56, 28, 16, 4, 8,
+ 0, 6, 12, 10, 24, 30, 20, 18, 48, 54, 60, 58, 40, 46, 36, 34,
+ 35, 37, 47, 41, 59, 61, 55, 49, 19, 21, 31, 25, 11, 13, 7, 1,
+ 5, 3, 9, 15, 29, 27, 17, 23, 53, 51, 57, 63, 45, 43, 33, 39,
+ 38, 32, 42, 44, 62, 56, 50, 52, 22, 16, 26, 28, 14, 8, 2, 4,
+ 0, 3, 6, 5, 12, 15, 10, 9, 24, 27, 30, 29, 20, 23, 18, 17,
+ 48, 51, 54, 53, 60, 63, 58, 57, 40, 43, 46, 45, 36, 39, 34, 33,
+ 35, 32, 37, 38, 47, 44, 41, 42, 59, 56, 61, 62, 55, 52, 49, 50,
+ 19, 16, 21, 22, 31, 28, 25, 26, 11, 8, 13, 14, 7, 4, 1, 2,
+ 0, 32, 3, 35, 6, 38, 5, 37, 12, 44, 15, 47, 10, 42, 9, 41,
+ 24, 56, 27, 59, 30, 62, 29, 61, 20, 52, 23, 55, 18, 50, 17, 49,
+ 48, 16, 51, 19, 54, 22, 53, 21, 60, 28, 63, 31, 58, 26, 57, 25,
+ 40, 8, 43, 11, 46, 14, 45, 13, 36, 4, 39, 7, 34, 2, 33, 1,
+ 0, 16, 32, 48, 3, 19, 35, 51, 6, 22, 38, 54, 5, 21, 37, 53,
+ 12, 28, 44, 60, 15, 31, 47, 63, 10, 26, 42, 58, 9, 25, 41, 57,
+ 24, 8, 56, 40, 27, 11, 59, 43, 30, 14, 62, 46, 29, 13, 61, 45,
+ 20, 4, 52, 36, 23, 7, 55, 39, 18, 2, 50, 34, 17, 1, 49, 33,
+ 0, 8, 16, 24, 32, 40, 48, 56, 3, 11, 19, 27, 35, 43, 51, 59,
+ 6, 14, 22, 30, 38, 46, 54, 62, 5, 13, 21, 29, 37, 45, 53, 61,
+ 12, 4, 28, 20, 44, 36, 60, 52, 15, 7, 31, 23, 47, 39, 63, 55,
+ 10, 2, 26, 18, 42, 34, 58, 50, 9, 1, 25, 17, 41, 33, 57, 49,
+ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60,
+ 3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63,
+ 6, 2, 14, 10, 22, 18, 30, 26, 38, 34, 46, 42, 54, 50, 62, 58,
+ 5, 1, 13, 9, 21, 17, 29, 25, 37, 33, 45, 41, 53, 49, 61, 57,
+ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30,
+ 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62,
+ 3, 1, 7, 5, 11, 9, 15, 13, 19, 17, 23, 21, 27, 25, 31, 29,
+ 35, 33, 39, 37, 43, 41, 47, 45, 51, 49, 55, 53, 59, 57, 63, 61
+};
+
+const qracode qra_13_64_64_irr_e = {
+ qra_K,
+ qra_N,
+ qra_m,
+ qra_M,
+ qra_a,
+ qra_NC,
+ qra_V,
+ qra_C,
+ qra_NMSG,
+ qra_MAXVDEG,
+ qra_MAXCDEG,
+ QRATYPE_CRCPUNCTURED,
+ qra_R,
+ CODE_NAME,
+ qra_acc_input_idx,
+ qra_acc_input_wlog,
+ qra_log,
+ qra_exp,
+ qra_msgw,
+ qra_vdeg,
+ qra_cdeg,
+ qra_v2cmidx,
+ qra_c2vmidx,
+ qra_pmat
+};
+
+#undef qra_K
+#undef qra_N
+#undef qra_m
+#undef qra_M
+#undef qra_a
+#undef qra_NC
+#undef qra_V
+#undef qra_C
+#undef qra_NMSG
+#undef qra_MAXVDEG
+#undef qra_MAXCDEG
+#undef qra_R
+#undef CODE_NAME
\ No newline at end of file
diff --git a/lib/qra/qracodes/qra13_64_64_irr_e.h b/lib/qra/qracodes/qra13_64_64_irr_e.h
new file mode 100644
index 000000000..d24421d2f
--- /dev/null
+++ b/lib/qra/qracodes/qra13_64_64_irr_e.h
@@ -0,0 +1,39 @@
+// qra13_64_64_irr_e.h
+// Code tables and defines for Q-ary RA code (13,64) over GF(64)
+// Code Name: qra13_64_64_irr_e
+// (13,64) RA Code over GF(64) RF=[3x4 4x4 6x1 3x2 5x1 7x1]/18
+
+// (c) 2016 - Nico Palermo - IV3NWV - Microtelecom Srl, Italy
+
+// This file is part of the qracodes project, a Forward Error Control
+// encoding/decoding package based on Q-ary RA (Repeat and Accumulate) LDPC codes.
+//
+// qracodes is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+// qracodes is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with qracodes source distribution.
+// If not, see .
+
+#ifndef _qra13_64_64_irr_e_h
+#define _qra13_64_64_irr_e_h
+
+#include "qracodes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern const qracode qra_13_64_64_irr_e;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _qra13_64_64_irr_e_h
diff --git a/lib/qra/qracodes/qracodes.c b/lib/qra/qracodes/qracodes.c
new file mode 100644
index 000000000..253dde0fa
--- /dev/null
+++ b/lib/qra/qracodes/qracodes.c
@@ -0,0 +1,474 @@
+// qracodes.c
+// Q-ary RA codes encoding/decoding functions
+//
+// (c) 2016 - Nico Palermo, IV3NWV - Microtelecom Srl, Italy
+// ------------------------------------------------------------------------------
+// This file is part of the qracodes project, a Forward Error Control
+// encoding/decoding package based on Q-ary RA (Repeat and Accumulate) LDPC codes.
+//
+// qracodes is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+// qracodes is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with qracodes source distribution.
+// If not, see .
+
+#include
+#include
+
+#include "npfwht.h"
+#include "pdmath.h"
+
+#include "qracodes.h"
+
+#define QRA_DEBUG
+
+int qra_encode(const qracode *pcode, uint *y, const uint *x)
+{
+ uint k,j,kk,jj;
+ uint t, chk = 0;
+
+ const uint K = pcode->K;
+ const uint M = pcode->M;
+ const uint NC= pcode->NC;
+ const uint a = pcode->a;
+ const int *acc_input_idx = pcode->acc_input_idx;
+ const uint *acc_input_wlog = pcode->acc_input_wlog;
+ const int *gflog = pcode->gflog;
+ const uint *gfexp = pcode->gfexp;
+
+ // copy the systematic symbols to destination
+ memcpy(y,x,K*sizeof(uint));
+
+ y = y+K; // point to check symbols
+
+ // compute the code check symbols as a weighted accumulation of a permutated
+ // sequence of the (repeated) systematic input symbols:
+ // chk(k+1) = x(idx(k))*alfa^(logw(k)) + chk(k)
+ // (all operations performed over GF(M))
+
+ if (a==1) { // grouping factor = 1
+ for (k=0;k 1
+ for (k=0;k80.f) // avoid floating point exp() overflows
+ v=80.f;
+
+ src[nitems] = (float)exp(v);
+ }
+}
+
+
+void qra_mfskbesselmetric(float *pix, const float *rsq, const uint m, const uint N, float EsNoMetric)
+{
+ // Computes the codeword symbols intrinsic probabilities
+ // given the square of the received input amplitudes.
+
+ // The input vector rqs must be a linear array of size M*N, where M=2^m,
+ // containing the squared amplitudes (rp*rp+rq*rq) of the input samples
+
+ // First symbol amplitudes should be stored in the first M positions,
+ // second symbol amplitudes stored at positions [M ... 2*M-1], and so on.
+
+ // Output vector is the intrinsic symbol metric (the probability distribution)
+ // assuming that symbols are transmitted using a M-FSK modulation
+ // and incoherent demodulation.
+
+ // As the input Es/No is generally unknown (as it cannot be exstimated accurately
+ // when the codeword length is few tens symbols) but an exact metric requires it
+ // we simply fix it to a predefined EsNoMetric value so that the metric is what
+ // expected at that specific value.
+ // The metric computed in this way is optimal only at this predefined Es/No value,
+ // nevertheless it is usually better than a generic parameter-free metric which
+ // makes no assumptions on the input Es/No.
+
+ uint k;
+ float rsum = 0.f;
+ float sigmaest, cmetric;
+
+ const uint M = 1<M;
+ const uint qra_m = pcode->m;
+ const uint qra_V = pcode->V;
+ const uint qra_MAXVDEG = pcode->MAXVDEG;
+ const int *qra_vdeg = pcode->vdeg;
+ const uint qra_C = pcode->C;
+ const uint qra_MAXCDEG = pcode->MAXCDEG;
+ const uint *qra_cdeg = pcode->cdeg;
+ const int *qra_v2cmidx = pcode->v2cmidx;
+ const int *qra_c2vmidx = pcode->c2vmidx;
+ const int *qra_pmat = pcode->gfpmat;
+ const uint *qra_msgw = pcode->msgw;
+
+// float msgout[qra_M]; // buffer to store temporary results
+ float msgout[QRACODE_MAX_M]; // we use a fixed size in order to avoid mallocs
+
+ float totex; // total extrinsic information
+ int nit; // current iteration
+ uint nv; // current variable
+ uint nc; // current check
+ uint k,kk; // loop indexes
+
+ uint ndeg; // current node degree
+ int msgbase; // current offset in the table of msg indexes
+ int imsg; // current message index
+ int wmsg; // current message weight
+
+ int rc = -1; // rc>=0 extrinsic converged to 1 at iteration rc (rc=0..maxiter-1)
+ // rc=-1 no convergence in the given number of iterations
+ // rc=-2 error in the code tables (code checks degrees must be >1)
+ // rc=-3 M is larger than QRACODE_MAX_M
+
+
+
+ if (qra_M>QRACODE_MAX_M)
+ return -3;
+
+ // message initialization -------------------------------------------------------
+
+ // init c->v variable intrinsic msgs
+ pd_init(C2VMSG(0),pix,qra_M*qra_V);
+
+ // init the v->c messages directed to code factors (k=1..ndeg) with the intrinsic info
+ for (nv=0;nvc
+ for (k=1;kv step -----------------------------------------------------
+ // Computes messages from code checks to code variables.
+ // As the first qra_V checks are associated with intrinsic information
+ // (the code tables have been constructed in this way)
+ // we need to do this step only for code checks in the range [qra_V..qra_C)
+
+ // The convolutions of probability distributions over the alphabet of a finite field GF(qra_M)
+ // are performed with a fast convolution algorithm over the given field.
+ //
+ // I.e. given the code check x1+x2+x3 = 0 (with x1,x2,x3 in GF(2^m))
+ // and given Prob(x2) and Prob(x3), we have that:
+ // Prob(x1=X1) = Prob((x2+x3)=X1) = sum((Prob(x2=X2)*Prob(x3=(X1+X2))) for all the X2s in the field
+ // This translates to Prob(x1) = IWHT(WHT(Prob(x2))*WHT(Prob(x3)))
+ // where WHT and IWHT are the direct and inverse Walsh-Hadamard transforms of the argument.
+ // Note that the WHT and the IWHF differs only by a multiplicative coefficent and since in this step
+ // we don't need that the output distribution is normalized we use the relationship
+ // Prob(x1) =(proportional to) WH(WH(Prob(x2))*WH(Prob(x3)))
+
+ // In general given the check code x1+x2+x3+..+xm = 0
+ // the output distribution of a variable given the distributions of the other m-1 variables
+ // is the inverse WHT of the product of the WHTs of the distribution of the other m-1 variables
+ // The complexity of this algorithm scales with M*log2(M) instead of the M^2 complexity of
+ // the brute force approach (M=size of the alphabet)
+
+ for (nc=qra_V;nc1)
+ return -2; // bad code tables
+
+ msgbase = nc*qra_MAXCDEG; // base to msg index row for the current node
+
+ // transforms inputs in the Walsh-Hadamard "frequency" domain
+ // v->c -> fwht(v->c)
+ for (k=0;kv = prod(fwht(v->c))
+ // TODO: we assume that checks degrees are not larger than three but
+ // if they are larger the products can be computed more efficiently
+ for (kk=0;kkc steps when multipling
+ // small fp numbers
+ msgout[0]+=1E-7f; // TODO: define the bias accordingly to the field size
+
+ np_fwht(qra_m,msgout,msgout);
+
+ // inverse weight and output
+ imsg = qra_c2vmidx[msgbase+k]; // current output msg index
+ wmsg = qra_msgw[imsg]; // current msg weight
+
+ if (wmsg==0)
+ pd_init(C2VMSG(imsg),msgout,qra_M);
+ else
+ // output p(alfa^(-w)*x)
+ pd_bwdperm(C2VMSG(imsg),msgout, MSGPERM(wmsg), qra_M);
+
+ } // for (k=0;kc step -----------------------------------------------------
+ for (nv=0;nvc msg = prod(c->v)
+ // TODO: factor factors to reduce the number of computations for high degree nodes
+ for (kk=0;kkc are null
+ // normalize output to a probability distribution
+ if (pd_norm(msgout,qra_m)<=0) {
+ // dump msgin;
+ printf("warning: v->c pd with invalid norm. nit=%d nv=%d k=%d\n",nit,nv,k);
+ for (kk=0;kk(1.*(qra_V)-0.01)) {
+ // the total maximum extrinsic information of each symbol in the codeword
+ // is very close to one. This means that we have reached the (1,1) point in the
+ // code EXIT chart(s) and we have successfully decoded the input.
+ rc = nit;
+ break; // remove the break to evaluate the decoder speed performance as a function of the max iterations number)
+ }
+
+ } // for (nit=0;nitM;
+ const uint qra_m = pcode->m;
+ const uint qra_K = pcode->K;
+
+ uint k;
+
+ for (k=0;k.
+
+#ifndef _qracodes_h_
+#define _qracodes_h_
+
+typedef unsigned int uint;
+
+// type of codes
+#define QRATYPE_NORMAL 0x00 // normal code
+#define QRATYPE_CRC 0x01 // code with crc - last information symbol is a CRC
+#define QRATYPE_CRCPUNCTURED 0x02 // the CRC symbol is punctured (not sent along the channel)
+
+
+typedef struct {
+ // code parameters
+ const uint K; // number of information symbols
+ const uint N; // codeword length in symbols
+ const uint m; // bits/symbol
+ const uint M; // Symbol alphabet cardinality (2^m)
+ const uint a; // code grouping factor
+ const uint NC; // number of check symbols (N-K)
+ const uint V; // number of variables in the code graph (N)
+ const uint C; // number of factors in the code graph (N +(N-K)+1)
+ const uint NMSG; // number of msgs in the code graph
+ const uint MAXVDEG; // maximum variable degree
+ const uint MAXCDEG; // maximum factor degree
+ const uint type; // see QRATYPE_xx defines
+ const float R; // code rate (K/N)
+ const char name[64]; // code name
+ // tables used by the encoder
+ const int *acc_input_idx;
+ const uint *acc_input_wlog;
+ const int *gflog;
+ const uint *gfexp;
+ // tables used by the decoder -------------------------
+ const uint *msgw;
+ const uint *vdeg;
+ const uint *cdeg;
+ const int *v2cmidx;
+ const int *c2vmidx;
+ const int *gfpmat;
+} qracode;
+// Uncomment the header file of the code which needs to be tested
+
+//#include "qra12_63_64_irr_b.h" // irregular code (12,63) over GF(64)
+//#include "qra13_64_64_irr_e.h" // irregular code with good performance and best UER protection at AP56
+//#include "qra13_64_64_reg_a.h" // regular code with good UER but perf. inferior to that of code qra12_63_64_irr_b
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int qra_encode(const qracode *pcode, uint *y, const uint *x);
+void qra_mfskbesselmetric(float *pix, const float *rsq, const uint m, const uint N, float EsNoMetric);
+int qra_extrinsic(const qracode *pcode, float *pex, const float *pix, int maxiter,float *qra_v2cmsg,float *qra_c2vmsg);
+void qra_mapdecode(const qracode *pcode, uint *xdec, float *pex, const float *pix);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _qracodes_h_
diff --git a/lib/qra/qracodes/qracodes.vcproj b/lib/qra/qracodes/qracodes.vcproj
new file mode 100644
index 000000000..1094f836f
--- /dev/null
+++ b/lib/qra/qracodes/qracodes.vcproj
@@ -0,0 +1,251 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+