mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-11-22 20:28:42 -05:00
Add the qra64 files.
This commit is contained in:
parent
11cc9ab579
commit
436daf17b0
30
libm65/qra64/Makefile.Win
Normal file
30
libm65/qra64/Makefile.Win
Normal file
@ -0,0 +1,30 @@
|
||||
FC = gfortran
|
||||
CC = gcc
|
||||
CFLAGS = -O2 -Wall -I. -D_WIN32
|
||||
|
||||
# Default rules
|
||||
%.o: %.c
|
||||
${CC} ${CFLAGS} -c $<
|
||||
%.o: %.f
|
||||
${FC} ${FFLAGS} -c $<
|
||||
%.o: %.F
|
||||
${FC} ${FFLAGS} -c $<
|
||||
%.o: %.f90
|
||||
${FC} ${FFLAGS} -c $<
|
||||
%.o: %.F90
|
||||
${FC} ${FFLAGS} -c $<
|
||||
|
||||
all: qra64.exe
|
||||
|
||||
OBJS1 = main.o qra64.o
|
||||
qra64.exe: $(OBJS1)
|
||||
${CC} -o qra64.exe $(OBJS1) ../qracodes/libqra64.a -lm
|
||||
|
||||
OBJS2 = qra64sim.o options.o wavhdr.o
|
||||
qra64sim.exe: $(OBJS2)
|
||||
${FC} -o qra64sim.exe $(OBJS2) ../qracodes/libqra64.a -lm
|
||||
|
||||
.PHONY : clean
|
||||
|
||||
clean:
|
||||
$(RM) *.o qra64.exe qra64sim.exe
|
302
libm65/qra64/fadengauss.c
Normal file
302
libm65/qra64/fadengauss.c
Normal file
@ -0,0 +1,302 @@
|
||||
// Gaussian energy fading tables for QRA64
|
||||
static const int glen_tab_gauss[64] = {
|
||||
2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
4, 4, 4, 4, 5, 5, 5, 6,
|
||||
6, 6, 7, 7, 8, 8, 9, 10,
|
||||
10, 11, 12, 13, 14, 15, 17, 18,
|
||||
19, 21, 23, 25, 27, 29, 32, 34,
|
||||
37, 41, 44, 48, 52, 57, 62, 65
|
||||
};
|
||||
static const float ggauss1[2] = {
|
||||
0.0296f, 0.9101f
|
||||
};
|
||||
static const float ggauss2[2] = {
|
||||
0.0350f, 0.8954f
|
||||
};
|
||||
static const float ggauss3[2] = {
|
||||
0.0411f, 0.8787f
|
||||
};
|
||||
static const float ggauss4[2] = {
|
||||
0.0483f, 0.8598f
|
||||
};
|
||||
static const float ggauss5[2] = {
|
||||
0.0566f, 0.8387f
|
||||
};
|
||||
static const float ggauss6[2] = {
|
||||
0.0660f, 0.8154f
|
||||
};
|
||||
static const float ggauss7[2] = {
|
||||
0.0767f, 0.7898f
|
||||
};
|
||||
static const float ggauss8[2] = {
|
||||
0.0886f, 0.7621f
|
||||
};
|
||||
static const float ggauss9[2] = {
|
||||
0.1017f, 0.7325f
|
||||
};
|
||||
static const float ggauss10[2] = {
|
||||
0.1159f, 0.7012f
|
||||
};
|
||||
static const float ggauss11[2] = {
|
||||
0.1310f, 0.6687f
|
||||
};
|
||||
static const float ggauss12[2] = {
|
||||
0.1465f, 0.6352f
|
||||
};
|
||||
static const float ggauss13[2] = {
|
||||
0.1621f, 0.6013f
|
||||
};
|
||||
static const float ggauss14[2] = {
|
||||
0.1771f, 0.5674f
|
||||
};
|
||||
static const float ggauss15[2] = {
|
||||
0.1911f, 0.5339f
|
||||
};
|
||||
static const float ggauss16[2] = {
|
||||
0.2034f, 0.5010f
|
||||
};
|
||||
static const float ggauss17[3] = {
|
||||
0.0299f, 0.2135f, 0.4690f
|
||||
};
|
||||
static const float ggauss18[3] = {
|
||||
0.0369f, 0.2212f, 0.4383f
|
||||
};
|
||||
static const float ggauss19[3] = {
|
||||
0.0454f, 0.2263f, 0.4088f
|
||||
};
|
||||
static const float ggauss20[3] = {
|
||||
0.0552f, 0.2286f, 0.3806f
|
||||
};
|
||||
static const float ggauss21[3] = {
|
||||
0.0658f, 0.2284f, 0.3539f
|
||||
};
|
||||
static const float ggauss22[3] = {
|
||||
0.0766f, 0.2258f, 0.3287f
|
||||
};
|
||||
static const float ggauss23[3] = {
|
||||
0.0869f, 0.2212f, 0.3049f
|
||||
};
|
||||
static const float ggauss24[3] = {
|
||||
0.0962f, 0.2148f, 0.2826f
|
||||
};
|
||||
static const float ggauss25[4] = {
|
||||
0.0351f, 0.1041f, 0.2071f, 0.2616f
|
||||
};
|
||||
static const float ggauss26[4] = {
|
||||
0.0429f, 0.1102f, 0.1984f, 0.2420f
|
||||
};
|
||||
static const float ggauss27[4] = {
|
||||
0.0508f, 0.1145f, 0.1890f, 0.2237f
|
||||
};
|
||||
static const float ggauss28[4] = {
|
||||
0.0582f, 0.1169f, 0.1791f, 0.2067f
|
||||
};
|
||||
static const float ggauss29[5] = {
|
||||
0.0289f, 0.0648f, 0.1176f, 0.1689f, 0.1908f
|
||||
};
|
||||
static const float ggauss30[5] = {
|
||||
0.0351f, 0.0703f, 0.1168f, 0.1588f, 0.1760f
|
||||
};
|
||||
static const float ggauss31[5] = {
|
||||
0.0411f, 0.0745f, 0.1146f, 0.1488f, 0.1623f
|
||||
};
|
||||
static const float ggauss32[6] = {
|
||||
0.0246f, 0.0466f, 0.0773f, 0.1115f, 0.1390f, 0.1497f
|
||||
};
|
||||
static const float ggauss33[6] = {
|
||||
0.0297f, 0.0512f, 0.0788f, 0.1075f, 0.1295f, 0.1379f
|
||||
};
|
||||
static const float ggauss34[6] = {
|
||||
0.0345f, 0.0549f, 0.0791f, 0.1029f, 0.1205f, 0.1270f
|
||||
};
|
||||
static const float ggauss35[7] = {
|
||||
0.0240f, 0.0387f, 0.0575f, 0.0784f, 0.0979f, 0.1118f, 0.1169f
|
||||
};
|
||||
static const float ggauss36[7] = {
|
||||
0.0281f, 0.0422f, 0.0590f, 0.0767f, 0.0926f, 0.1037f, 0.1076f
|
||||
};
|
||||
static const float ggauss37[8] = {
|
||||
0.0212f, 0.0318f, 0.0449f, 0.0596f, 0.0744f, 0.0872f, 0.0960f, 0.0991f
|
||||
};
|
||||
static const float ggauss38[8] = {
|
||||
0.0247f, 0.0348f, 0.0467f, 0.0593f, 0.0716f, 0.0819f, 0.0887f, 0.0911f
|
||||
};
|
||||
static const float ggauss39[9] = {
|
||||
0.0199f, 0.0278f, 0.0372f, 0.0476f, 0.0584f, 0.0684f, 0.0766f, 0.0819f,
|
||||
0.0838f
|
||||
};
|
||||
static const float ggauss40[10] = {
|
||||
0.0166f, 0.0228f, 0.0303f, 0.0388f, 0.0478f, 0.0568f, 0.0649f, 0.0714f,
|
||||
0.0756f, 0.0771f
|
||||
};
|
||||
static const float ggauss41[10] = {
|
||||
0.0193f, 0.0254f, 0.0322f, 0.0397f, 0.0474f, 0.0548f, 0.0613f, 0.0664f,
|
||||
0.0697f, 0.0709f
|
||||
};
|
||||
static const float ggauss42[11] = {
|
||||
0.0168f, 0.0217f, 0.0273f, 0.0335f, 0.0399f, 0.0464f, 0.0524f, 0.0576f,
|
||||
0.0617f, 0.0643f, 0.0651f
|
||||
};
|
||||
static const float ggauss43[12] = {
|
||||
0.0151f, 0.0191f, 0.0237f, 0.0288f, 0.0342f, 0.0396f, 0.0449f, 0.0498f,
|
||||
0.0540f, 0.0572f, 0.0592f, 0.0599f
|
||||
};
|
||||
static const float ggauss44[13] = {
|
||||
0.0138f, 0.0171f, 0.0210f, 0.0252f, 0.0297f, 0.0343f, 0.0388f, 0.0432f,
|
||||
0.0471f, 0.0504f, 0.0529f, 0.0545f, 0.0550f
|
||||
};
|
||||
static const float ggauss45[14] = {
|
||||
0.0128f, 0.0157f, 0.0189f, 0.0224f, 0.0261f, 0.0300f, 0.0339f, 0.0377f,
|
||||
0.0412f, 0.0444f, 0.0470f, 0.0489f, 0.0501f, 0.0505f
|
||||
};
|
||||
static const float ggauss46[15] = {
|
||||
0.0121f, 0.0146f, 0.0173f, 0.0202f, 0.0234f, 0.0266f, 0.0299f, 0.0332f,
|
||||
0.0363f, 0.0391f, 0.0416f, 0.0437f, 0.0452f, 0.0461f, 0.0464f
|
||||
};
|
||||
static const float ggauss47[17] = {
|
||||
0.0097f, 0.0116f, 0.0138f, 0.0161f, 0.0186f, 0.0212f, 0.0239f, 0.0267f,
|
||||
0.0294f, 0.0321f, 0.0346f, 0.0369f, 0.0389f, 0.0405f, 0.0417f, 0.0424f,
|
||||
0.0427f
|
||||
};
|
||||
static const float ggauss48[18] = {
|
||||
0.0096f, 0.0113f, 0.0131f, 0.0151f, 0.0172f, 0.0194f, 0.0217f, 0.0241f,
|
||||
0.0264f, 0.0287f, 0.0308f, 0.0329f, 0.0347f, 0.0362f, 0.0375f, 0.0384f,
|
||||
0.0390f, 0.0392f
|
||||
};
|
||||
static const float ggauss49[19] = {
|
||||
0.0095f, 0.0110f, 0.0126f, 0.0143f, 0.0161f, 0.0180f, 0.0199f, 0.0219f,
|
||||
0.0239f, 0.0258f, 0.0277f, 0.0294f, 0.0310f, 0.0325f, 0.0337f, 0.0347f,
|
||||
0.0354f, 0.0358f, 0.0360f
|
||||
};
|
||||
static const float ggauss50[21] = {
|
||||
0.0083f, 0.0095f, 0.0108f, 0.0122f, 0.0136f, 0.0152f, 0.0168f, 0.0184f,
|
||||
0.0201f, 0.0217f, 0.0234f, 0.0250f, 0.0265f, 0.0279f, 0.0292f, 0.0303f,
|
||||
0.0313f, 0.0320f, 0.0326f, 0.0329f, 0.0330f
|
||||
};
|
||||
static const float ggauss51[23] = {
|
||||
0.0074f, 0.0084f, 0.0095f, 0.0106f, 0.0118f, 0.0131f, 0.0144f, 0.0157f,
|
||||
0.0171f, 0.0185f, 0.0199f, 0.0213f, 0.0227f, 0.0240f, 0.0252f, 0.0263f,
|
||||
0.0273f, 0.0282f, 0.0290f, 0.0296f, 0.0300f, 0.0303f, 0.0303f
|
||||
};
|
||||
static const float ggauss52[25] = {
|
||||
0.0068f, 0.0076f, 0.0085f, 0.0094f, 0.0104f, 0.0115f, 0.0126f, 0.0137f,
|
||||
0.0149f, 0.0160f, 0.0172f, 0.0184f, 0.0196f, 0.0207f, 0.0218f, 0.0228f,
|
||||
0.0238f, 0.0247f, 0.0255f, 0.0262f, 0.0268f, 0.0273f, 0.0276f, 0.0278f,
|
||||
0.0279f
|
||||
};
|
||||
static const float ggauss53[27] = {
|
||||
0.0063f, 0.0070f, 0.0078f, 0.0086f, 0.0094f, 0.0103f, 0.0112f, 0.0121f,
|
||||
0.0131f, 0.0141f, 0.0151f, 0.0161f, 0.0170f, 0.0180f, 0.0190f, 0.0199f,
|
||||
0.0208f, 0.0216f, 0.0224f, 0.0231f, 0.0237f, 0.0243f, 0.0247f, 0.0251f,
|
||||
0.0254f, 0.0255f, 0.0256f
|
||||
};
|
||||
static const float ggauss54[29] = {
|
||||
0.0060f, 0.0066f, 0.0072f, 0.0079f, 0.0086f, 0.0093f, 0.0101f, 0.0109f,
|
||||
0.0117f, 0.0125f, 0.0133f, 0.0142f, 0.0150f, 0.0159f, 0.0167f, 0.0175f,
|
||||
0.0183f, 0.0190f, 0.0197f, 0.0204f, 0.0210f, 0.0216f, 0.0221f, 0.0225f,
|
||||
0.0228f, 0.0231f, 0.0233f, 0.0234f, 0.0235f
|
||||
};
|
||||
static const float ggauss55[32] = {
|
||||
0.0053f, 0.0058f, 0.0063f, 0.0068f, 0.0074f, 0.0080f, 0.0086f, 0.0093f,
|
||||
0.0099f, 0.0106f, 0.0113f, 0.0120f, 0.0127f, 0.0134f, 0.0141f, 0.0148f,
|
||||
0.0155f, 0.0162f, 0.0168f, 0.0174f, 0.0180f, 0.0186f, 0.0191f, 0.0196f,
|
||||
0.0201f, 0.0204f, 0.0208f, 0.0211f, 0.0213f, 0.0214f, 0.0215f, 0.0216f
|
||||
};
|
||||
static const float ggauss56[34] = {
|
||||
0.0052f, 0.0056f, 0.0060f, 0.0065f, 0.0070f, 0.0075f, 0.0080f, 0.0086f,
|
||||
0.0091f, 0.0097f, 0.0103f, 0.0109f, 0.0115f, 0.0121f, 0.0127f, 0.0133f,
|
||||
0.0138f, 0.0144f, 0.0150f, 0.0155f, 0.0161f, 0.0166f, 0.0170f, 0.0175f,
|
||||
0.0179f, 0.0183f, 0.0186f, 0.0189f, 0.0192f, 0.0194f, 0.0196f, 0.0197f,
|
||||
0.0198f, 0.0198f
|
||||
};
|
||||
static const float ggauss57[37] = {
|
||||
0.0047f, 0.0051f, 0.0055f, 0.0058f, 0.0063f, 0.0067f, 0.0071f, 0.0076f,
|
||||
0.0080f, 0.0085f, 0.0090f, 0.0095f, 0.0100f, 0.0105f, 0.0110f, 0.0115f,
|
||||
0.0120f, 0.0125f, 0.0130f, 0.0134f, 0.0139f, 0.0144f, 0.0148f, 0.0152f,
|
||||
0.0156f, 0.0160f, 0.0164f, 0.0167f, 0.0170f, 0.0173f, 0.0175f, 0.0177f,
|
||||
0.0179f, 0.0180f, 0.0181f, 0.0181f, 0.0182f
|
||||
};
|
||||
static const float ggauss58[41] = {
|
||||
0.0041f, 0.0044f, 0.0047f, 0.0050f, 0.0054f, 0.0057f, 0.0060f, 0.0064f,
|
||||
0.0068f, 0.0072f, 0.0076f, 0.0080f, 0.0084f, 0.0088f, 0.0092f, 0.0096f,
|
||||
0.0101f, 0.0105f, 0.0109f, 0.0113f, 0.0117f, 0.0121f, 0.0125f, 0.0129f,
|
||||
0.0133f, 0.0137f, 0.0140f, 0.0144f, 0.0147f, 0.0150f, 0.0153f, 0.0155f,
|
||||
0.0158f, 0.0160f, 0.0162f, 0.0163f, 0.0164f, 0.0165f, 0.0166f, 0.0167f,
|
||||
0.0167f
|
||||
};
|
||||
static const float ggauss59[44] = {
|
||||
0.0039f, 0.0042f, 0.0044f, 0.0047f, 0.0050f, 0.0053f, 0.0056f, 0.0059f,
|
||||
0.0062f, 0.0065f, 0.0068f, 0.0072f, 0.0075f, 0.0079f, 0.0082f, 0.0086f,
|
||||
0.0089f, 0.0093f, 0.0096f, 0.0100f, 0.0104f, 0.0107f, 0.0110f, 0.0114f,
|
||||
0.0117f, 0.0120f, 0.0124f, 0.0127f, 0.0130f, 0.0132f, 0.0135f, 0.0138f,
|
||||
0.0140f, 0.0142f, 0.0144f, 0.0146f, 0.0148f, 0.0149f, 0.0150f, 0.0151f,
|
||||
0.0152f, 0.0153f, 0.0153f, 0.0153f
|
||||
};
|
||||
static const float ggauss60[48] = {
|
||||
0.0036f, 0.0038f, 0.0040f, 0.0042f, 0.0044f, 0.0047f, 0.0049f, 0.0052f,
|
||||
0.0055f, 0.0057f, 0.0060f, 0.0063f, 0.0066f, 0.0068f, 0.0071f, 0.0074f,
|
||||
0.0077f, 0.0080f, 0.0083f, 0.0086f, 0.0089f, 0.0092f, 0.0095f, 0.0098f,
|
||||
0.0101f, 0.0104f, 0.0107f, 0.0109f, 0.0112f, 0.0115f, 0.0117f, 0.0120f,
|
||||
0.0122f, 0.0124f, 0.0126f, 0.0128f, 0.0130f, 0.0132f, 0.0134f, 0.0135f,
|
||||
0.0136f, 0.0137f, 0.0138f, 0.0139f, 0.0140f, 0.0140f, 0.0140f, 0.0140f
|
||||
};
|
||||
static const float ggauss61[52] = {
|
||||
0.0033f, 0.0035f, 0.0037f, 0.0039f, 0.0041f, 0.0043f, 0.0045f, 0.0047f,
|
||||
0.0049f, 0.0051f, 0.0053f, 0.0056f, 0.0058f, 0.0060f, 0.0063f, 0.0065f,
|
||||
0.0068f, 0.0070f, 0.0073f, 0.0075f, 0.0078f, 0.0080f, 0.0083f, 0.0085f,
|
||||
0.0088f, 0.0090f, 0.0093f, 0.0095f, 0.0098f, 0.0100f, 0.0102f, 0.0105f,
|
||||
0.0107f, 0.0109f, 0.0111f, 0.0113f, 0.0115f, 0.0116f, 0.0118f, 0.0120f,
|
||||
0.0121f, 0.0122f, 0.0124f, 0.0125f, 0.0126f, 0.0126f, 0.0127f, 0.0128f,
|
||||
0.0128f, 0.0129f, 0.0129f, 0.0129f
|
||||
};
|
||||
static const float ggauss62[57] = {
|
||||
0.0030f, 0.0031f, 0.0033f, 0.0034f, 0.0036f, 0.0038f, 0.0039f, 0.0041f,
|
||||
0.0043f, 0.0045f, 0.0047f, 0.0048f, 0.0050f, 0.0052f, 0.0054f, 0.0056f,
|
||||
0.0058f, 0.0060f, 0.0063f, 0.0065f, 0.0067f, 0.0069f, 0.0071f, 0.0073f,
|
||||
0.0075f, 0.0077f, 0.0080f, 0.0082f, 0.0084f, 0.0086f, 0.0088f, 0.0090f,
|
||||
0.0092f, 0.0094f, 0.0096f, 0.0097f, 0.0099f, 0.0101f, 0.0103f, 0.0104f,
|
||||
0.0106f, 0.0107f, 0.0108f, 0.0110f, 0.0111f, 0.0112f, 0.0113f, 0.0114f,
|
||||
0.0115f, 0.0116f, 0.0116f, 0.0117f, 0.0117f, 0.0118f, 0.0118f, 0.0118f,
|
||||
0.0118f
|
||||
};
|
||||
static const float ggauss63[62] = {
|
||||
0.0027f, 0.0029f, 0.0030f, 0.0031f, 0.0032f, 0.0034f, 0.0035f, 0.0037f,
|
||||
0.0038f, 0.0040f, 0.0041f, 0.0043f, 0.0045f, 0.0046f, 0.0048f, 0.0049f,
|
||||
0.0051f, 0.0053f, 0.0055f, 0.0056f, 0.0058f, 0.0060f, 0.0062f, 0.0063f,
|
||||
0.0065f, 0.0067f, 0.0069f, 0.0071f, 0.0072f, 0.0074f, 0.0076f, 0.0078f,
|
||||
0.0079f, 0.0081f, 0.0083f, 0.0084f, 0.0086f, 0.0088f, 0.0089f, 0.0091f,
|
||||
0.0092f, 0.0094f, 0.0095f, 0.0096f, 0.0098f, 0.0099f, 0.0100f, 0.0101f,
|
||||
0.0102f, 0.0103f, 0.0104f, 0.0105f, 0.0105f, 0.0106f, 0.0107f, 0.0107f,
|
||||
0.0108f, 0.0108f, 0.0108f, 0.0108f, 0.0109f, 0.0109f
|
||||
};
|
||||
static const float ggauss64[65] = {
|
||||
0.0028f, 0.0029f, 0.0030f, 0.0031f, 0.0032f, 0.0034f, 0.0035f, 0.0036f,
|
||||
0.0037f, 0.0039f, 0.0040f, 0.0041f, 0.0043f, 0.0044f, 0.0046f, 0.0047f,
|
||||
0.0048f, 0.0050f, 0.0051f, 0.0053f, 0.0054f, 0.0056f, 0.0057f, 0.0059f,
|
||||
0.0060f, 0.0062f, 0.0063f, 0.0065f, 0.0066f, 0.0068f, 0.0069f, 0.0071f,
|
||||
0.0072f, 0.0074f, 0.0075f, 0.0077f, 0.0078f, 0.0079f, 0.0081f, 0.0082f,
|
||||
0.0083f, 0.0084f, 0.0086f, 0.0087f, 0.0088f, 0.0089f, 0.0090f, 0.0091f,
|
||||
0.0092f, 0.0093f, 0.0094f, 0.0094f, 0.0095f, 0.0096f, 0.0097f, 0.0097f,
|
||||
0.0098f, 0.0098f, 0.0099f, 0.0099f, 0.0099f, 0.0099f, 0.0100f, 0.0100f,
|
||||
0.0100f
|
||||
};
|
||||
static const float *gptr_tab_gauss[64] = {
|
||||
ggauss1, ggauss2, ggauss3, ggauss4,
|
||||
ggauss5, ggauss6, ggauss7, ggauss8,
|
||||
ggauss9, ggauss10, ggauss11, ggauss12,
|
||||
ggauss13, ggauss14, ggauss15, ggauss16,
|
||||
ggauss17, ggauss18, ggauss19, ggauss20,
|
||||
ggauss21, ggauss22, ggauss23, ggauss24,
|
||||
ggauss25, ggauss26, ggauss27, ggauss28,
|
||||
ggauss29, ggauss30, ggauss31, ggauss32,
|
||||
ggauss33, ggauss34, ggauss35, ggauss36,
|
||||
ggauss37, ggauss38, ggauss39, ggauss40,
|
||||
ggauss41, ggauss42, ggauss43, ggauss44,
|
||||
ggauss45, ggauss46, ggauss47, ggauss48,
|
||||
ggauss49, ggauss50, ggauss51, ggauss52,
|
||||
ggauss53, ggauss54, ggauss55, ggauss56,
|
||||
ggauss57, ggauss58, ggauss59, ggauss60,
|
||||
ggauss61, ggauss62, ggauss63, ggauss64
|
||||
};
|
304
libm65/qra64/fadenlorentz.c
Normal file
304
libm65/qra64/fadenlorentz.c
Normal file
@ -0,0 +1,304 @@
|
||||
// Lorentz energy fading tables for QRA64
|
||||
static const int glen_tab_lorentz[64] = {
|
||||
2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 3, 3,
|
||||
3, 3, 3, 3, 3, 4, 4, 4,
|
||||
4, 4, 5, 5, 5, 5, 6, 6,
|
||||
7, 7, 7, 8, 8, 9, 10, 10,
|
||||
11, 12, 13, 14, 15, 16, 17, 19,
|
||||
20, 22, 23, 25, 27, 30, 32, 35,
|
||||
38, 41, 45, 49, 53, 57, 62, 65
|
||||
};
|
||||
static const float glorentz1[2] = {
|
||||
0.0214f, 0.9107f
|
||||
};
|
||||
static const float glorentz2[2] = {
|
||||
0.0244f, 0.9030f
|
||||
};
|
||||
static const float glorentz3[2] = {
|
||||
0.0280f, 0.8950f
|
||||
};
|
||||
static const float glorentz4[2] = {
|
||||
0.0314f, 0.8865f
|
||||
};
|
||||
static const float glorentz5[2] = {
|
||||
0.0349f, 0.8773f
|
||||
};
|
||||
static const float glorentz6[2] = {
|
||||
0.0388f, 0.8675f
|
||||
};
|
||||
static const float glorentz7[2] = {
|
||||
0.0426f, 0.8571f
|
||||
};
|
||||
static const float glorentz8[2] = {
|
||||
0.0463f, 0.8459f
|
||||
};
|
||||
static const float glorentz9[2] = {
|
||||
0.0500f, 0.8339f
|
||||
};
|
||||
static const float glorentz10[2] = {
|
||||
0.0538f, 0.8210f
|
||||
};
|
||||
static const float glorentz11[2] = {
|
||||
0.0579f, 0.8074f
|
||||
};
|
||||
static const float glorentz12[2] = {
|
||||
0.0622f, 0.7930f
|
||||
};
|
||||
static const float glorentz13[2] = {
|
||||
0.0668f, 0.7777f
|
||||
};
|
||||
static const float glorentz14[2] = {
|
||||
0.0715f, 0.7616f
|
||||
};
|
||||
static const float glorentz15[3] = {
|
||||
0.0196f, 0.0765f, 0.7445f
|
||||
};
|
||||
static const float glorentz16[3] = {
|
||||
0.0210f, 0.0816f, 0.7267f
|
||||
};
|
||||
static const float glorentz17[3] = {
|
||||
0.0226f, 0.0870f, 0.7080f
|
||||
};
|
||||
static const float glorentz18[3] = {
|
||||
0.0242f, 0.0925f, 0.6885f
|
||||
};
|
||||
static const float glorentz19[3] = {
|
||||
0.0259f, 0.0981f, 0.6682f
|
||||
};
|
||||
static const float glorentz20[3] = {
|
||||
0.0277f, 0.1039f, 0.6472f
|
||||
};
|
||||
static const float glorentz21[3] = {
|
||||
0.0296f, 0.1097f, 0.6255f
|
||||
};
|
||||
static const float glorentz22[4] = {
|
||||
0.0143f, 0.0316f, 0.1155f, 0.6031f
|
||||
};
|
||||
static const float glorentz23[4] = {
|
||||
0.0153f, 0.0337f, 0.1213f, 0.5803f
|
||||
};
|
||||
static const float glorentz24[4] = {
|
||||
0.0163f, 0.0358f, 0.1270f, 0.5570f
|
||||
};
|
||||
static const float glorentz25[4] = {
|
||||
0.0174f, 0.0381f, 0.1325f, 0.5333f
|
||||
};
|
||||
static const float glorentz26[4] = {
|
||||
0.0186f, 0.0405f, 0.1378f, 0.5095f
|
||||
};
|
||||
static const float glorentz27[5] = {
|
||||
0.0113f, 0.0198f, 0.0429f, 0.1428f, 0.4855f
|
||||
};
|
||||
static const float glorentz28[5] = {
|
||||
0.0120f, 0.0211f, 0.0455f, 0.1473f, 0.4615f
|
||||
};
|
||||
static const float glorentz29[5] = {
|
||||
0.0129f, 0.0225f, 0.0481f, 0.1514f, 0.4376f
|
||||
};
|
||||
static const float glorentz30[5] = {
|
||||
0.0137f, 0.0239f, 0.0508f, 0.1549f, 0.4140f
|
||||
};
|
||||
static const float glorentz31[6] = {
|
||||
0.0095f, 0.0147f, 0.0254f, 0.0536f, 0.1578f, 0.3907f
|
||||
};
|
||||
static const float glorentz32[6] = {
|
||||
0.0101f, 0.0156f, 0.0270f, 0.0564f, 0.1600f, 0.3680f
|
||||
};
|
||||
static const float glorentz33[7] = {
|
||||
0.0076f, 0.0109f, 0.0167f, 0.0287f, 0.0592f, 0.1614f, 0.3458f
|
||||
};
|
||||
static const float glorentz34[7] = {
|
||||
0.0081f, 0.0116f, 0.0178f, 0.0305f, 0.0621f, 0.1620f, 0.3243f
|
||||
};
|
||||
static const float glorentz35[7] = {
|
||||
0.0087f, 0.0124f, 0.0190f, 0.0324f, 0.0649f, 0.1618f, 0.3035f
|
||||
};
|
||||
static const float glorentz36[8] = {
|
||||
0.0069f, 0.0093f, 0.0133f, 0.0203f, 0.0343f, 0.0676f, 0.1607f, 0.2836f
|
||||
};
|
||||
static const float glorentz37[8] = {
|
||||
0.0074f, 0.0100f, 0.0142f, 0.0216f, 0.0362f, 0.0702f, 0.1588f, 0.2645f
|
||||
};
|
||||
static const float glorentz38[9] = {
|
||||
0.0061f, 0.0080f, 0.0107f, 0.0152f, 0.0230f, 0.0382f, 0.0726f, 0.1561f,
|
||||
0.2464f
|
||||
};
|
||||
static const float glorentz39[10] = {
|
||||
0.0052f, 0.0066f, 0.0086f, 0.0115f, 0.0162f, 0.0244f, 0.0402f, 0.0747f,
|
||||
0.1526f, 0.2291f
|
||||
};
|
||||
static const float glorentz40[10] = {
|
||||
0.0056f, 0.0071f, 0.0092f, 0.0123f, 0.0173f, 0.0259f, 0.0422f, 0.0766f,
|
||||
0.1484f, 0.2128f
|
||||
};
|
||||
static const float glorentz41[11] = {
|
||||
0.0049f, 0.0061f, 0.0076f, 0.0098f, 0.0132f, 0.0184f, 0.0274f, 0.0441f,
|
||||
0.0780f, 0.1437f, 0.1975f
|
||||
};
|
||||
static const float glorentz42[12] = {
|
||||
0.0044f, 0.0053f, 0.0065f, 0.0082f, 0.0106f, 0.0141f, 0.0196f, 0.0290f,
|
||||
0.0460f, 0.0791f, 0.1384f, 0.1831f
|
||||
};
|
||||
static const float glorentz43[13] = {
|
||||
0.0040f, 0.0048f, 0.0057f, 0.0070f, 0.0088f, 0.0113f, 0.0150f, 0.0209f,
|
||||
0.0305f, 0.0477f, 0.0797f, 0.1327f, 0.1695f
|
||||
};
|
||||
static const float glorentz44[14] = {
|
||||
0.0037f, 0.0043f, 0.0051f, 0.0062f, 0.0075f, 0.0094f, 0.0121f, 0.0160f,
|
||||
0.0221f, 0.0321f, 0.0493f, 0.0799f, 0.1267f, 0.1568f
|
||||
};
|
||||
static const float glorentz45[15] = {
|
||||
0.0035f, 0.0040f, 0.0047f, 0.0055f, 0.0066f, 0.0081f, 0.0101f, 0.0129f,
|
||||
0.0171f, 0.0234f, 0.0335f, 0.0506f, 0.0795f, 0.1204f, 0.1450f
|
||||
};
|
||||
static const float glorentz46[16] = {
|
||||
0.0033f, 0.0037f, 0.0043f, 0.0050f, 0.0059f, 0.0071f, 0.0087f, 0.0108f,
|
||||
0.0138f, 0.0181f, 0.0246f, 0.0349f, 0.0517f, 0.0786f, 0.1141f, 0.1340f
|
||||
};
|
||||
static const float glorentz47[17] = {
|
||||
0.0031f, 0.0035f, 0.0040f, 0.0046f, 0.0054f, 0.0064f, 0.0077f, 0.0093f,
|
||||
0.0116f, 0.0147f, 0.0192f, 0.0259f, 0.0362f, 0.0525f, 0.0773f, 0.1076f,
|
||||
0.1237f
|
||||
};
|
||||
static const float glorentz48[19] = {
|
||||
0.0027f, 0.0030f, 0.0034f, 0.0038f, 0.0043f, 0.0050f, 0.0058f, 0.0069f,
|
||||
0.0082f, 0.0100f, 0.0123f, 0.0156f, 0.0203f, 0.0271f, 0.0374f, 0.0530f,
|
||||
0.0755f, 0.1013f, 0.1141f
|
||||
};
|
||||
static const float glorentz49[20] = {
|
||||
0.0026f, 0.0029f, 0.0032f, 0.0036f, 0.0041f, 0.0047f, 0.0054f, 0.0063f,
|
||||
0.0074f, 0.0088f, 0.0107f, 0.0131f, 0.0165f, 0.0213f, 0.0282f, 0.0383f,
|
||||
0.0531f, 0.0734f, 0.0950f, 0.1053f
|
||||
};
|
||||
static const float glorentz50[22] = {
|
||||
0.0023f, 0.0025f, 0.0028f, 0.0031f, 0.0035f, 0.0039f, 0.0044f, 0.0050f,
|
||||
0.0058f, 0.0067f, 0.0079f, 0.0094f, 0.0114f, 0.0139f, 0.0175f, 0.0223f,
|
||||
0.0292f, 0.0391f, 0.0529f, 0.0709f, 0.0889f, 0.0971f
|
||||
};
|
||||
static const float glorentz51[23] = {
|
||||
0.0023f, 0.0025f, 0.0027f, 0.0030f, 0.0034f, 0.0037f, 0.0042f, 0.0048f,
|
||||
0.0054f, 0.0062f, 0.0072f, 0.0085f, 0.0100f, 0.0121f, 0.0148f, 0.0184f,
|
||||
0.0233f, 0.0301f, 0.0396f, 0.0524f, 0.0681f, 0.0829f, 0.0894f
|
||||
};
|
||||
static const float glorentz52[25] = {
|
||||
0.0021f, 0.0023f, 0.0025f, 0.0027f, 0.0030f, 0.0033f, 0.0036f, 0.0040f,
|
||||
0.0045f, 0.0051f, 0.0058f, 0.0067f, 0.0077f, 0.0090f, 0.0107f, 0.0128f,
|
||||
0.0156f, 0.0192f, 0.0242f, 0.0308f, 0.0398f, 0.0515f, 0.0650f, 0.0772f,
|
||||
0.0824f
|
||||
};
|
||||
static const float glorentz53[27] = {
|
||||
0.0019f, 0.0021f, 0.0022f, 0.0024f, 0.0027f, 0.0029f, 0.0032f, 0.0035f,
|
||||
0.0039f, 0.0044f, 0.0049f, 0.0055f, 0.0062f, 0.0072f, 0.0083f, 0.0096f,
|
||||
0.0113f, 0.0135f, 0.0164f, 0.0201f, 0.0249f, 0.0314f, 0.0398f, 0.0502f,
|
||||
0.0619f, 0.0718f, 0.0759f
|
||||
};
|
||||
static const float glorentz54[30] = {
|
||||
0.0017f, 0.0018f, 0.0019f, 0.0021f, 0.0022f, 0.0024f, 0.0026f, 0.0029f,
|
||||
0.0031f, 0.0034f, 0.0038f, 0.0042f, 0.0047f, 0.0052f, 0.0059f, 0.0067f,
|
||||
0.0076f, 0.0088f, 0.0102f, 0.0120f, 0.0143f, 0.0171f, 0.0208f, 0.0256f,
|
||||
0.0317f, 0.0395f, 0.0488f, 0.0586f, 0.0666f, 0.0698f
|
||||
};
|
||||
static const float glorentz55[32] = {
|
||||
0.0016f, 0.0017f, 0.0018f, 0.0019f, 0.0021f, 0.0022f, 0.0024f, 0.0026f,
|
||||
0.0028f, 0.0031f, 0.0034f, 0.0037f, 0.0041f, 0.0045f, 0.0050f, 0.0056f,
|
||||
0.0063f, 0.0071f, 0.0081f, 0.0094f, 0.0108f, 0.0127f, 0.0149f, 0.0178f,
|
||||
0.0214f, 0.0261f, 0.0318f, 0.0389f, 0.0470f, 0.0553f, 0.0618f, 0.0643f
|
||||
};
|
||||
static const float glorentz56[35] = {
|
||||
0.0014f, 0.0015f, 0.0016f, 0.0017f, 0.0018f, 0.0020f, 0.0021f, 0.0023f,
|
||||
0.0024f, 0.0026f, 0.0028f, 0.0031f, 0.0033f, 0.0036f, 0.0040f, 0.0044f,
|
||||
0.0049f, 0.0054f, 0.0060f, 0.0067f, 0.0076f, 0.0087f, 0.0099f, 0.0114f,
|
||||
0.0133f, 0.0156f, 0.0184f, 0.0220f, 0.0264f, 0.0318f, 0.0381f, 0.0451f,
|
||||
0.0520f, 0.0572f, 0.0591f
|
||||
};
|
||||
static const float glorentz57[38] = {
|
||||
0.0013f, 0.0014f, 0.0015f, 0.0016f, 0.0017f, 0.0018f, 0.0019f, 0.0020f,
|
||||
0.0021f, 0.0023f, 0.0024f, 0.0026f, 0.0028f, 0.0031f, 0.0033f, 0.0036f,
|
||||
0.0039f, 0.0043f, 0.0047f, 0.0052f, 0.0058f, 0.0064f, 0.0072f, 0.0081f,
|
||||
0.0092f, 0.0104f, 0.0120f, 0.0139f, 0.0162f, 0.0190f, 0.0224f, 0.0265f,
|
||||
0.0315f, 0.0371f, 0.0431f, 0.0487f, 0.0529f, 0.0544f
|
||||
};
|
||||
static const float glorentz58[41] = {
|
||||
0.0012f, 0.0013f, 0.0014f, 0.0014f, 0.0015f, 0.0016f, 0.0017f, 0.0018f,
|
||||
0.0019f, 0.0020f, 0.0022f, 0.0023f, 0.0025f, 0.0026f, 0.0028f, 0.0030f,
|
||||
0.0033f, 0.0036f, 0.0039f, 0.0042f, 0.0046f, 0.0050f, 0.0056f, 0.0061f,
|
||||
0.0068f, 0.0076f, 0.0086f, 0.0097f, 0.0110f, 0.0125f, 0.0144f, 0.0167f,
|
||||
0.0194f, 0.0226f, 0.0265f, 0.0309f, 0.0359f, 0.0409f, 0.0455f, 0.0488f,
|
||||
0.0500f
|
||||
};
|
||||
static const float glorentz59[45] = {
|
||||
0.0011f, 0.0012f, 0.0012f, 0.0013f, 0.0013f, 0.0014f, 0.0015f, 0.0016f,
|
||||
0.0016f, 0.0017f, 0.0018f, 0.0019f, 0.0021f, 0.0022f, 0.0023f, 0.0025f,
|
||||
0.0026f, 0.0028f, 0.0030f, 0.0033f, 0.0035f, 0.0038f, 0.0041f, 0.0045f,
|
||||
0.0049f, 0.0054f, 0.0059f, 0.0065f, 0.0072f, 0.0081f, 0.0090f, 0.0102f,
|
||||
0.0115f, 0.0130f, 0.0149f, 0.0171f, 0.0197f, 0.0227f, 0.0263f, 0.0302f,
|
||||
0.0345f, 0.0387f, 0.0425f, 0.0451f, 0.0460f
|
||||
};
|
||||
static const float glorentz60[49] = {
|
||||
0.0010f, 0.0011f, 0.0011f, 0.0012f, 0.0012f, 0.0013f, 0.0013f, 0.0014f,
|
||||
0.0014f, 0.0015f, 0.0016f, 0.0017f, 0.0018f, 0.0019f, 0.0020f, 0.0021f,
|
||||
0.0022f, 0.0024f, 0.0025f, 0.0027f, 0.0028f, 0.0030f, 0.0033f, 0.0035f,
|
||||
0.0038f, 0.0041f, 0.0044f, 0.0048f, 0.0052f, 0.0057f, 0.0063f, 0.0069f,
|
||||
0.0077f, 0.0085f, 0.0095f, 0.0106f, 0.0119f, 0.0135f, 0.0153f, 0.0174f,
|
||||
0.0199f, 0.0227f, 0.0259f, 0.0293f, 0.0330f, 0.0365f, 0.0395f, 0.0415f,
|
||||
0.0423f
|
||||
};
|
||||
static const float glorentz61[53] = {
|
||||
0.0009f, 0.0010f, 0.0010f, 0.0011f, 0.0011f, 0.0011f, 0.0012f, 0.0012f,
|
||||
0.0013f, 0.0014f, 0.0014f, 0.0015f, 0.0016f, 0.0016f, 0.0017f, 0.0018f,
|
||||
0.0019f, 0.0020f, 0.0021f, 0.0023f, 0.0024f, 0.0025f, 0.0027f, 0.0029f,
|
||||
0.0031f, 0.0033f, 0.0035f, 0.0038f, 0.0041f, 0.0044f, 0.0047f, 0.0051f,
|
||||
0.0056f, 0.0061f, 0.0067f, 0.0073f, 0.0081f, 0.0089f, 0.0099f, 0.0110f,
|
||||
0.0124f, 0.0139f, 0.0156f, 0.0176f, 0.0199f, 0.0225f, 0.0253f, 0.0283f,
|
||||
0.0314f, 0.0343f, 0.0367f, 0.0383f, 0.0389f
|
||||
};
|
||||
static const float glorentz62[57] = {
|
||||
0.0009f, 0.0009f, 0.0009f, 0.0010f, 0.0010f, 0.0011f, 0.0011f, 0.0011f,
|
||||
0.0012f, 0.0012f, 0.0013f, 0.0013f, 0.0014f, 0.0015f, 0.0015f, 0.0016f,
|
||||
0.0017f, 0.0018f, 0.0019f, 0.0020f, 0.0021f, 0.0022f, 0.0023f, 0.0024f,
|
||||
0.0026f, 0.0027f, 0.0029f, 0.0031f, 0.0033f, 0.0035f, 0.0038f, 0.0040f,
|
||||
0.0043f, 0.0047f, 0.0050f, 0.0055f, 0.0059f, 0.0064f, 0.0070f, 0.0077f,
|
||||
0.0085f, 0.0093f, 0.0103f, 0.0114f, 0.0127f, 0.0142f, 0.0158f, 0.0177f,
|
||||
0.0198f, 0.0221f, 0.0246f, 0.0272f, 0.0297f, 0.0321f, 0.0340f, 0.0353f,
|
||||
0.0357f
|
||||
};
|
||||
static const float glorentz63[62] = {
|
||||
0.0008f, 0.0008f, 0.0009f, 0.0009f, 0.0009f, 0.0010f, 0.0010f, 0.0010f,
|
||||
0.0011f, 0.0011f, 0.0011f, 0.0012f, 0.0012f, 0.0013f, 0.0013f, 0.0014f,
|
||||
0.0015f, 0.0015f, 0.0016f, 0.0017f, 0.0017f, 0.0018f, 0.0019f, 0.0020f,
|
||||
0.0021f, 0.0022f, 0.0023f, 0.0025f, 0.0026f, 0.0028f, 0.0029f, 0.0031f,
|
||||
0.0033f, 0.0035f, 0.0038f, 0.0040f, 0.0043f, 0.0046f, 0.0050f, 0.0053f,
|
||||
0.0058f, 0.0062f, 0.0068f, 0.0074f, 0.0081f, 0.0088f, 0.0097f, 0.0106f,
|
||||
0.0117f, 0.0130f, 0.0144f, 0.0159f, 0.0176f, 0.0195f, 0.0216f, 0.0237f,
|
||||
0.0259f, 0.0280f, 0.0299f, 0.0315f, 0.0325f, 0.0328f
|
||||
};
|
||||
static const float glorentz64[65] = {
|
||||
0.0008f, 0.0008f, 0.0008f, 0.0009f, 0.0009f, 0.0009f, 0.0010f, 0.0010f,
|
||||
0.0010f, 0.0011f, 0.0011f, 0.0012f, 0.0012f, 0.0012f, 0.0013f, 0.0013f,
|
||||
0.0014f, 0.0014f, 0.0015f, 0.0016f, 0.0016f, 0.0017f, 0.0018f, 0.0019f,
|
||||
0.0020f, 0.0021f, 0.0022f, 0.0023f, 0.0024f, 0.0025f, 0.0027f, 0.0028f,
|
||||
0.0030f, 0.0031f, 0.0033f, 0.0035f, 0.0038f, 0.0040f, 0.0043f, 0.0046f,
|
||||
0.0049f, 0.0052f, 0.0056f, 0.0061f, 0.0066f, 0.0071f, 0.0077f, 0.0084f,
|
||||
0.0091f, 0.0100f, 0.0109f, 0.0120f, 0.0132f, 0.0145f, 0.0159f, 0.0175f,
|
||||
0.0192f, 0.0209f, 0.0228f, 0.0246f, 0.0264f, 0.0279f, 0.0291f, 0.0299f,
|
||||
0.0301f
|
||||
};
|
||||
static const float *gptr_tab_lorentz[64] = {
|
||||
glorentz1, glorentz2, glorentz3, glorentz4,
|
||||
glorentz5, glorentz6, glorentz7, glorentz8,
|
||||
glorentz9, glorentz10, glorentz11, glorentz12,
|
||||
glorentz13, glorentz14, glorentz15, glorentz16,
|
||||
glorentz17, glorentz18, glorentz19, glorentz20,
|
||||
glorentz21, glorentz22, glorentz23, glorentz24,
|
||||
glorentz25, glorentz26, glorentz27, glorentz28,
|
||||
glorentz29, glorentz30, glorentz31, glorentz32,
|
||||
glorentz33, glorentz34, glorentz35, glorentz36,
|
||||
glorentz37, glorentz38, glorentz39, glorentz40,
|
||||
glorentz41, glorentz42, glorentz43, glorentz44,
|
||||
glorentz45, glorentz46, glorentz47, glorentz48,
|
||||
glorentz49, glorentz50, glorentz51, glorentz52,
|
||||
glorentz53, glorentz54, glorentz55, glorentz56,
|
||||
glorentz57, glorentz58, glorentz59, glorentz60,
|
||||
glorentz61, glorentz62, glorentz63, glorentz64
|
||||
};
|
746
libm65/qra64/main.c
Normal file
746
libm65/qra64/main.c
Normal file
@ -0,0 +1,746 @@
|
||||
/*
|
||||
main.c
|
||||
QRA64 mode encode/decode tests
|
||||
|
||||
(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
|
||||
qra64.c/.h - qra64 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 over GF(64)
|
||||
../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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
The code used by the QRA64 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 <windows.h> // required only for GetTickCount(...)
|
||||
#include <process.h> // _beginthread
|
||||
#endif
|
||||
|
||||
#if __linux__
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
|
||||
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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "qra64.h"
|
||||
#include "../qracodes/normrnd.h" // gaussian numbers generator
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// channel types
|
||||
#define CHANNEL_AWGN 0
|
||||
#define CHANNEL_RAYLEIGH 1
|
||||
#define CHANNEL_FASTFADE 2
|
||||
|
||||
#define JT65_SNR_EBNO_OFFSET 29.1f // with the synch used in JT65
|
||||
#define QRA64_SNR_EBNO_OFFSET 31.0f // with the costas array synch
|
||||
|
||||
void printwordd(char *msg, int *x, int size)
|
||||
{
|
||||
int k;
|
||||
printf("\n%s ",msg);
|
||||
for (k=0;k<size;k++)
|
||||
printf("%2d ",x[k]);
|
||||
printf("\n");
|
||||
}
|
||||
void printwordh(char *msg, int *x, int size)
|
||||
{
|
||||
int k;
|
||||
printf("\n%s ",msg);
|
||||
for (k=0;k<size;k++)
|
||||
printf("%02hx ",x[k]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
#define NSAMPLES (QRA64_N*QRA64_M)
|
||||
|
||||
static float rp[NSAMPLES];
|
||||
static float rq[NSAMPLES];
|
||||
static float chp[NSAMPLES];
|
||||
static float chq[NSAMPLES];
|
||||
static float r[NSAMPLES];
|
||||
|
||||
float *mfskchannel(int *x, int channel_type, float EbNodB)
|
||||
{
|
||||
/*
|
||||
Simulate an MFSK channel, either AWGN or Rayleigh.
|
||||
|
||||
x is a pointer to the transmitted codeword, an array of QRA64_N
|
||||
integers in the range 0..63.
|
||||
|
||||
Returns the received symbol energies (squared amplitudes) as an array of
|
||||
(QRA64_M*QRA64_N) floats. The first QRA64_M entries of this array are
|
||||
the energies of the first symbol in the codeword. The second QRA64_M
|
||||
entries are those of the second symbol, and so on up to the last codeword
|
||||
symbol.
|
||||
*/
|
||||
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
|
||||
const float R = 1.0f*QRA64_K/QRA64_N;
|
||||
|
||||
float EbNo = (float)pow(10,EbNodB/10);
|
||||
float EsNo = 1.0f*QRA64_m*R*EbNo;
|
||||
float Es = EsNo*No;
|
||||
float A = (float)sqrt(Es);
|
||||
int k;
|
||||
|
||||
normrnd_s(rp,NSAMPLES,0,sigma);
|
||||
normrnd_s(rq,NSAMPLES,0,sigma);
|
||||
|
||||
if(EbNodB>-15)
|
||||
if (channel_type == CHANNEL_AWGN)
|
||||
for (k=0;k<QRA64_N;k++)
|
||||
rp[k*QRA64_M+x[k]]+=A;
|
||||
else
|
||||
if (channel_type == CHANNEL_RAYLEIGH) {
|
||||
normrnd_s(chp,QRA64_N,0,sigmach);
|
||||
normrnd_s(chq,QRA64_N,0,sigmach);
|
||||
for (k=0;k<QRA64_N;k++) {
|
||||
rp[k*QRA64_M+x[k]]+=A*chp[k];
|
||||
rq[k*QRA64_M+x[k]]+=A*chq[k];
|
||||
}
|
||||
}
|
||||
else {
|
||||
return 0; // unknown channel type
|
||||
}
|
||||
|
||||
// compute the squares of the amplitudes of the received samples
|
||||
for (k=0;k<NSAMPLES;k++)
|
||||
r[k] = rp[k]*rp[k] + rq[k]*rq[k];
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// These defines are some packed fields as computed by JT65
|
||||
#define CALL_IV3NWV 0x7F85AE7
|
||||
#define CALL_K1JT 0xF70DDD7
|
||||
#define GRID_JN66 0x3AE4 // JN66
|
||||
#define GRID_73 0x7ED0 // 73
|
||||
|
||||
char decode_type[12][32] = {
|
||||
"[? ? ?] AP0",
|
||||
"[CQ ? ?] AP27",
|
||||
"[CQ ? ] AP42",
|
||||
"[CALL ? ?] AP29",
|
||||
"[CALL ? ] AP44",
|
||||
"[CALL CALL ?] AP57",
|
||||
"[? CALL ?] AP29",
|
||||
"[? CALL ] AP44",
|
||||
"[CALL CALL G] AP72",
|
||||
"[CQ CALL ?] AP55",
|
||||
"[CQ CALL ] AP70",
|
||||
"[CQ CALL G] AP70"
|
||||
};
|
||||
char apmode_type[3][32] = {
|
||||
"NO AP",
|
||||
"AUTO AP",
|
||||
"USER AP"
|
||||
};
|
||||
|
||||
int test_proc_1(int channel_type, float EbNodB, int mode)
|
||||
{
|
||||
/*
|
||||
Here we simulate the following (dummy) QSO:
|
||||
|
||||
1) CQ IV3NWV
|
||||
2) IV3NWV K1JT
|
||||
3) K1JT IV3NWV 73
|
||||
4) IV3NWV K1JT 73
|
||||
|
||||
No message repetition is attempted
|
||||
|
||||
The QSO is counted as successfull if IV3NWV received the last message
|
||||
When mode=QRA_AUTOAP each decoder attempts to decode the message sent
|
||||
by the other station using the a-priori information derived by what
|
||||
has been already decoded in a previous phase of the QSO if decoding
|
||||
with no a-priori information has not been successful.
|
||||
|
||||
Step 1) K1JT's decoder first attempts to decode msgs of type [? ? ?]
|
||||
and if this attempt fails, it attempts to decode [CQ/QRZ ? ?] or
|
||||
[CQ/QRZ ?] msgs
|
||||
|
||||
Step 2) if IV3NWV's decoder is unable to decode K1JT's without AP it
|
||||
attempts to decode messages of the type [IV3NWV ? ?] and [IV3NWV ?].
|
||||
|
||||
Step 3) K1JT's decoder attempts to decode [? ? ?] and [K1JT IV3NWV ?]
|
||||
(this last decode type has been enabled by K1JT's encoder at step 2)
|
||||
|
||||
Step 4) IV3NWV's decoder attempts to decode [? ? ?] and [IV3NWV K1JT
|
||||
?] (this last decode type has been enabled by IV3NWV's encoder at step
|
||||
3)
|
||||
|
||||
At each step the simulation reports if a decode was successful. In
|
||||
this case it also reports the type of decode (see table decode_type
|
||||
above)
|
||||
|
||||
When mode=QRA_NOAP, only [? ? ?] decodes are attempted and no a-priori
|
||||
information is used by the decoder
|
||||
|
||||
The function returns 0 if all of the four messages have been decoded
|
||||
by their recipients (with no retries) and -1 if any of them could not
|
||||
be decoded
|
||||
*/
|
||||
|
||||
int x[QRA64_K], xdec[QRA64_K];
|
||||
int y[QRA64_N];
|
||||
float *rx;
|
||||
int rc;
|
||||
|
||||
// Each simulated station must use its own codec since it might work with
|
||||
// different a-priori information.
|
||||
qra64codec *codec_iv3nwv = qra64_init(mode); // codec for IV3NWV
|
||||
qra64codec *codec_k1jt = qra64_init(mode); // codec for K1JT
|
||||
|
||||
// Step 1a: IV3NWV makes a CQ call (with no grid)
|
||||
printf("IV3NWV tx: CQ IV3NWV\n");
|
||||
encodemsg_jt65(x,CALL_CQ,CALL_IV3NWV,GRID_BLANK);
|
||||
qra64_encode(codec_iv3nwv, y, x);
|
||||
rx = mfskchannel(y,channel_type,EbNodB);
|
||||
|
||||
// Step 1b: K1JT attempts to decode [? ? ?], [CQ/QRZ ? ?] or [CQ/QRZ ?]
|
||||
rc = qra64_decode(codec_k1jt, 0, xdec,rx);
|
||||
if (rc>=0) { // decoded
|
||||
printf("K1JT rx: received with apcode=%d %s\n",rc, decode_type[rc]);
|
||||
|
||||
// Step 2a: K1JT replies to IV3NWV (with no grid)
|
||||
printf("K1JT tx: IV3NWV K1JT\n");
|
||||
encodemsg_jt65(x,CALL_IV3NWV,CALL_K1JT, GRID_BLANK);
|
||||
qra64_encode(codec_k1jt, y, x);
|
||||
rx = mfskchannel(y,channel_type,EbNodB);
|
||||
|
||||
// Step 2b: IV3NWV attempts to decode [? ? ?], [IV3NWV ? ?] or [IV3NWV ?]
|
||||
rc = qra64_decode(codec_iv3nwv, 0, xdec,rx);
|
||||
if (rc>=0) { // decoded
|
||||
printf("IV3NWV rx: received with apcode=%d %s\n",rc, decode_type[rc]);
|
||||
|
||||
// Step 3a: IV3NWV replies to K1JT with a 73
|
||||
printf("IV3NWV tx: K1JT IV3NWV 73\n");
|
||||
encodemsg_jt65(x,CALL_K1JT,CALL_IV3NWV, GRID_73);
|
||||
qra64_encode(codec_iv3nwv, y, x);
|
||||
rx = mfskchannel(y,channel_type,EbNodB);
|
||||
|
||||
// Step 3b: K1JT attempts to decode [? ? ?] or [K1JT IV3NWV ?]
|
||||
rc = qra64_decode(codec_k1jt, 0, xdec,rx);
|
||||
if (rc>=0) { // decoded
|
||||
printf("K1JT rx: received with apcode=%d %s\n",rc, decode_type[rc]);
|
||||
|
||||
// Step 4a: K1JT replies to IV3NWV with a 73
|
||||
printf("K1JT tx: IV3NWV K1JT 73\n");
|
||||
encodemsg_jt65(x,CALL_IV3NWV,CALL_K1JT, GRID_73);
|
||||
qra64_encode(codec_k1jt, y, x);
|
||||
rx = mfskchannel(y,channel_type,EbNodB);
|
||||
|
||||
// Step 4b: IV3NWV attempts to decode [? ? ?], [IV3NWV ? ?], or [IV3NWV ?]
|
||||
rc = qra64_decode(codec_iv3nwv, 0, xdec,rx);
|
||||
if (rc>=0) { // decoded
|
||||
printf("IV3NWV rx: received with apcode=%d %s\n",rc, decode_type[rc]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("no 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 qra64_decode function
|
||||
indicates the amount of a-priori information required to decode the received
|
||||
message according to this table:
|
||||
|
||||
rc=0 [? ? ?] AP0
|
||||
rc=1 [CQ ? ?] AP27
|
||||
rc=2 [CQ ? ] AP42
|
||||
rc=3 [CALL ? ?] AP29
|
||||
rc=4 [CALL ? ] AP44
|
||||
rc=5 [CALL CALL ?] AP57
|
||||
rc=6 [? CALL ?] AP29
|
||||
rc=7 [? CALL ] AP44
|
||||
rc=8 [CALL CALL GRID] AP72
|
||||
rc=9 [CQ CALL ?] AP55
|
||||
rc=10 [CQ CALL ] AP70
|
||||
rc=11 [CQ CALL GRID] AP70
|
||||
|
||||
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[QRA64_K], xdec[QRA64_K];
|
||||
int y[QRA64_N];
|
||||
float *rx;
|
||||
float ebnodbest, ebnodbavg=0;
|
||||
int rc,k;
|
||||
|
||||
int ndecok[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
int nundet = 0;
|
||||
int ntx = 200,ndec=0;
|
||||
|
||||
qra64codec *codec_iv3nwv = qra64_init(mode); // codec for IV3NWV
|
||||
qra64codec *codec_k1jt = qra64_init(mode); // codec for K1JT
|
||||
|
||||
printf("\nQRA64 Test #2 - Decoding with AP knowledge (SNR-Eb/No offset = %.1f dB)\n\n",
|
||||
QRA64_SNR_EBNO_OFFSET);
|
||||
|
||||
// This will enable K1JT's decoder to look for calls directed to him [K1JT ? ?/b]
|
||||
// printf("K1JT decoder enabled for [K1JT ? ?/blank]\n");
|
||||
// qra64_apset(codec_k1jt, CALL_K1JT,0,0,APTYPE_MYCALL);
|
||||
|
||||
// This will enable K1JT's decoder to look for IV3NWV calls directed to him [K1JT IV3NWV ?/b]
|
||||
// printf("K1JT decoder enabled for [K1JT IV3NWV ?]\n");
|
||||
// qra64_apset(codec_k1jt, CALL_CQ,CALL_IV3NWV,0,APTYPE_BOTHCALLS);
|
||||
|
||||
// This will enable K1JT's decoder to look for msges sent by IV3NWV [? IV3NWV ?]
|
||||
// printf("K1JT decoder enabled for [? IV3NWV ?/blank]\n");
|
||||
// qra64_apset(codec_k1jt, 0,CALL_IV3NWV,GRID_BLANK,APTYPE_HISCALL);
|
||||
|
||||
// This will enable K1JT's decoder to look for full-knowledge [K1JT IV3NWV JN66] msgs
|
||||
printf("K1JT decoder enabled for [K1JT IV3NWV JN66]\n");
|
||||
qra64_apset(codec_k1jt, CALL_K1JT,CALL_IV3NWV,GRID_JN66,APTYPE_FULL);
|
||||
|
||||
// This will enable K1JT's decoder to look for calls from IV3NWV [CQ IV3NWV ?/b] msgs
|
||||
printf("K1JT decoder enabled for [CQ IV3NWV ?/b/JN66]\n");
|
||||
qra64_apset(codec_k1jt, 0,CALL_IV3NWV,GRID_JN66,APTYPE_CQHISCALL);
|
||||
|
||||
|
||||
// Dx station IV3NWV calls
|
||||
printf("\nIV3NWV encoder sends msg: [K1JT IV3NWV JN66]\n\n");
|
||||
encodemsg_jt65(x,CALL_CQ,CALL_IV3NWV,GRID_JN66);
|
||||
|
||||
// printf("\nIV3NWV encoder sends msg: [CQ IV3NWV JN66]\n\n");
|
||||
// encodemsg_jt65(x,CALL_CQ,CALL_IV3NWV,GRID_JN66);
|
||||
|
||||
// printf("\nIV3NWV encoder sends msg: [CQ IV3NWV]\n\n");
|
||||
// encodemsg_jt65(x,CALL_CQ,CALL_IV3NWV,GRID_BLANK);
|
||||
qra64_encode(codec_iv3nwv, y, x);
|
||||
|
||||
printf("Simulating K1JT decoder up to AP72\n");
|
||||
|
||||
for (k=0;k<ntx;k++) {
|
||||
printf(".");
|
||||
rx = mfskchannel(y,channel_type,EbNodB);
|
||||
rc = qra64_decode(codec_k1jt, &ebnodbest, xdec,rx);
|
||||
if (rc>=0) {
|
||||
ebnodbavg +=ebnodbest;
|
||||
if (memcmp(xdec,x,12*sizeof(int))==0)
|
||||
ndecok[rc]++;
|
||||
else
|
||||
nundet++;
|
||||
}
|
||||
}
|
||||
printf("\n\n");
|
||||
|
||||
|
||||
printf("Transimtted msgs:%d\nDecoded msgs:\n\n",ntx);
|
||||
for (k=0;k<12;k++) {
|
||||
printf("%3d with %s\n",ndecok[k],decode_type[k]);
|
||||
ndec += ndecok[k];
|
||||
}
|
||||
printf("\nTotal: %d/%d (%d undetected errors)\n\n",ndec,ntx,nundet);
|
||||
printf("");
|
||||
|
||||
ebnodbavg/=(ndec+nundet);
|
||||
printf("Estimated SNR (average in dB) = %.2f dB\n\n",ebnodbavg-QRA64_SNR_EBNO_OFFSET);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_fastfading(float EbNodB, float B90, int fadingModel, int submode, int apmode, int olddec, int channel_type, int ntx)
|
||||
{
|
||||
int x[QRA64_K], xdec[QRA64_K];
|
||||
int y[QRA64_N];
|
||||
float *rx;
|
||||
float ebnodbest, ebnodbavg=0;
|
||||
int rc,k;
|
||||
float rxolddec[QRA64_N*QRA64_M]; // holds the energies at nominal tone freqs
|
||||
|
||||
int ndecok[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
int nundet = 0;
|
||||
int ndec=0;
|
||||
|
||||
qra64codec *codec_iv3nwv;
|
||||
qra64codec *codec_k1jt;
|
||||
|
||||
codec_iv3nwv=qra64_init(QRA_NOAP);
|
||||
codec_k1jt =qra64_init(apmode);
|
||||
|
||||
if (channel_type==2) { // fast-fading case
|
||||
printf("Simulating the fast-fading channel\n");
|
||||
printf("B90=%.2f Hz - Fading Model=%s - Submode=QRA64%c\n",B90,fadingModel?"Lorentz":"Gauss",submode+'A');
|
||||
printf("Decoder metric = %s\n",olddec?"AWGN":"Matched to fast-fading signal");
|
||||
}
|
||||
else {
|
||||
printf("Simulating the %s channel\n",channel_type?"Rayleigh block fading":"AWGN");
|
||||
printf("Decoder metric = AWGN\n");
|
||||
}
|
||||
|
||||
|
||||
printf("\nEncoding msg [K1JT IV3NWV JN66]\n");
|
||||
encodemsg_jt65(x,CALL_K1JT,CALL_IV3NWV,GRID_JN66);
|
||||
// printf("[");
|
||||
// for (k=0;k<11;k++) printf("%02hX ",x[k]); printf("%02hX]\n",x[11]);
|
||||
|
||||
qra64_encode(codec_iv3nwv, y, x);
|
||||
printf("%d transmissions will be simulated\n\n",ntx);
|
||||
|
||||
if (apmode==QRA_USERAP) {
|
||||
// This will enable K1JT's decoder to look for cq/qrz calls [CQ/QRZ ? ?/b]
|
||||
printf("K1JT decoder enabled for [CQ ? ?/blank]\n");
|
||||
qra64_apset(codec_k1jt, CALL_K1JT,0,0,APTYPE_CQQRZ);
|
||||
|
||||
// This will enable K1JT's decoder to look for calls directed to him [K1JT ? ?/b]
|
||||
printf("K1JT decoder enabled for [K1JT ? ?/blank]\n");
|
||||
qra64_apset(codec_k1jt, CALL_K1JT,0,0,APTYPE_MYCALL);
|
||||
|
||||
// This will enable K1JT's decoder to look for msges sent by IV3NWV [? IV3NWV ?]
|
||||
printf("K1JT decoder enabled for [? IV3NWV ?/blank]\n");
|
||||
qra64_apset(codec_k1jt, 0,CALL_IV3NWV,GRID_BLANK,APTYPE_HISCALL);
|
||||
|
||||
// This will enable K1JT's decoder to look for IV3NWV calls directed to him [K1JT IV3NWV ?/b]
|
||||
printf("K1JT decoder enabled for [K1JT IV3NWV ?]\n");
|
||||
qra64_apset(codec_k1jt, CALL_K1JT,CALL_IV3NWV,0,APTYPE_BOTHCALLS);
|
||||
|
||||
// This will enable K1JT's decoder to look for full-knowledge [K1JT IV3NWV JN66] msgs
|
||||
printf("K1JT decoder enabled for [K1JT IV3NWV JN66]\n");
|
||||
qra64_apset(codec_k1jt, CALL_K1JT,CALL_IV3NWV,GRID_JN66,APTYPE_FULL);
|
||||
|
||||
// This will enable K1JT's decoder to look for calls from IV3NWV [CQ IV3NWV ?/b] msgs
|
||||
printf("K1JT decoder enabled for [CQ IV3NWV ?/b/JN66]\n");
|
||||
qra64_apset(codec_k1jt, 0,CALL_IV3NWV,GRID_JN66,APTYPE_CQHISCALL);
|
||||
|
||||
}
|
||||
|
||||
printf("\nNow decoding with K1JT's decoder...\n");
|
||||
/*
|
||||
if (channel_type==2) // simulate a fast-faded signal
|
||||
printf("Simulating a fast-fading channel with given B90 and spread type\n");
|
||||
else
|
||||
printf("Simulating a %s channel\n",channel_type?"Rayleigh block fading":"AWGN");
|
||||
*/
|
||||
for (k=0;k<ntx;k++) {
|
||||
|
||||
if ((k%10)==0)
|
||||
printf(" %5.1f %%\r",100.0*k/ntx);
|
||||
// printf("."); // work in progress
|
||||
|
||||
if (channel_type==2) {
|
||||
// generate a fast-faded signal
|
||||
rc = qra64_fastfading_channel(&rx,y,submode,EbNodB,B90,fadingModel);
|
||||
if (rc<0) {
|
||||
printf("\nqra64_fastfading_channel error. rc=%d\n",rc);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else // generate a awgn or Rayleigh block fading signal
|
||||
rx = mfskchannel(y, channel_type, EbNodB);
|
||||
|
||||
|
||||
if (channel_type==2) // fast-fading case
|
||||
if (olddec==1) {
|
||||
int k, j;
|
||||
int jj = 1<<submode;
|
||||
int bps = QRA64_M*(2+jj);
|
||||
float *rxbase;
|
||||
float *out = rxolddec;
|
||||
// calc energies at nominal freqs
|
||||
for (k=0;k<QRA64_N;k++) {
|
||||
rxbase = rx + QRA64_M + k*bps;
|
||||
for (j=0;j<QRA64_M;j++) {
|
||||
*out++=*rxbase;
|
||||
rxbase+=jj;
|
||||
}
|
||||
}
|
||||
// decode with awgn decoder
|
||||
rc = qra64_decode(codec_k1jt,&ebnodbest,xdec,rxolddec);
|
||||
}
|
||||
else // use fast-fading decoder
|
||||
rc = qra64_decode_fastfading(codec_k1jt,&ebnodbest,xdec,rx,submode,B90,fadingModel);
|
||||
else // awgn or rayleigh channel. use the old decoder whatever the olddec option is
|
||||
rc = qra64_decode(codec_k1jt,&ebnodbest,xdec,rx);
|
||||
|
||||
|
||||
|
||||
if (rc>=0) {
|
||||
ebnodbavg +=ebnodbest;
|
||||
if (memcmp(xdec,x,12*sizeof(int))==0)
|
||||
ndecok[rc]++;
|
||||
else {
|
||||
fprintf(stderr,"\nUndetected error with rc=%d\n",rc);
|
||||
nundet++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
printf(" %5.1f %%\r",100.0*k/ntx);
|
||||
|
||||
printf("\n\n");
|
||||
|
||||
printf("Msgs transmitted:%d\nMsg decoded:\n\n",ntx);
|
||||
for (k=0;k<12;k++) {
|
||||
printf("rc=%2d %3d with %s\n",k,ndecok[k],decode_type[k]);
|
||||
ndec += ndecok[k];
|
||||
}
|
||||
printf("\nTotal: %d/%d (%d undetected errors)\n\n",ndec,ntx,nundet);
|
||||
printf("");
|
||||
|
||||
if (ndec>0) {
|
||||
ebnodbavg/=(ndec+nundet);
|
||||
printf("Estimated SNR (average in dB) = %.2f dB\n\n",ebnodbavg-QRA64_SNR_EBNO_OFFSET);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void syntax(void)
|
||||
{
|
||||
|
||||
printf("\nQRA64 Mode Tests\n");
|
||||
printf("2016, Nico Palermo - IV3NWV\n\n");
|
||||
printf("---------------------------\n\n");
|
||||
printf("Syntax: qra64 [-s<snrdb>] [-c<channel>] [-a<ap-type>] [-t<testtype>] [-h]\n");
|
||||
printf("Options: \n");
|
||||
printf(" -s<snrdb> : set simulation SNR in 2500 Hz BW (default:-27.5 dB)\n");
|
||||
printf(" -c<channel> : set channel type 0=AWGN (default) 1=Rayleigh 2=Fast-fading\n");
|
||||
printf(" -a<ap-type> : set decode type 0=NOAP 1=AUTOAP (default) 2=USERAP\n");
|
||||
printf(" -t<testtype>: 0=simulate seq of msgs between IV3NWV and K1JT (default)\n");
|
||||
printf(" 1=simulate K1JT receiving K1JT IV3NWV JN66\n");
|
||||
printf(" 2=simulate fast-fading/awgn/rayliegh decoders performance\n");
|
||||
printf(" -n<ntx> : simulate the transmission of ntx codewords (default=100)\n");
|
||||
|
||||
printf("Options used only for fast-fading simulations (-c2):\n");
|
||||
printf(" -b : 90%% fading bandwidth in Hz [1..230 Hz] (default = 2.5 Hz)\n");
|
||||
printf(" -m : fading model. 0=Gauss, 1=Lorentz (default = Lorentz)\n");
|
||||
printf(" -q : qra64 submode. 0=QRA64A,... 4=QRA64E (default = QRA64A)\n");
|
||||
printf(" -d : use the old awgn decoder\n");
|
||||
printf(" -h: this help\n");
|
||||
printf("Example:\n");
|
||||
printf(" qra64 -t2 -c2 -a2 -b50 -m1 -q2 -n10000 -s-26\n");
|
||||
printf(" runs the error performance test (-t2)\n");
|
||||
printf(" with USER_AP (-a2)\n");
|
||||
printf(" simulating a fast fading channel (-c2)\n");
|
||||
printf(" with B90 = 50 Hz (-b50), Lorentz Doppler (-m1), mode QRA64C (-q2)\n");
|
||||
printf(" ntx = 10000 codewords (-n10000) and SNR = -26 dB (-s-26)\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;
|
||||
float B90 = 2.5;
|
||||
int fadingModel = 1;
|
||||
int submode = 0;
|
||||
int olddec = 0;
|
||||
int ntx = 100;
|
||||
|
||||
// Parse the command line
|
||||
while(--argc) {
|
||||
argv++;
|
||||
|
||||
if (strncmp(*argv,"-h",2)==0) {
|
||||
syntax();
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
if (strncmp(*argv,"-n",2)==0) {
|
||||
ntx = ( int)atoi((*argv)+2);
|
||||
if (ntx<100 || ntx>1000000) {
|
||||
printf("Invalid -n option. ntx must be in the range [100..1000000]\n");
|
||||
syntax();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (strncmp(*argv,"-a",2)==0) {
|
||||
mode = ( int)atoi((*argv)+2);
|
||||
if (mode>2) {
|
||||
printf("Invalid decoding mode\n");
|
||||
syntax();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (strncmp(*argv,"-s",2)==0) {
|
||||
SNRdB = (float)atof((*argv)+2);
|
||||
if (SNRdB>20 || SNRdB<-50) {
|
||||
printf("SNR should be in the range [-50..20]\n");
|
||||
syntax();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (strncmp(*argv,"-t",2)==0) {
|
||||
testtype = ( int)atoi((*argv)+2);
|
||||
if (testtype>2) {
|
||||
printf("Invalid test type\n");
|
||||
syntax();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (strncmp(*argv,"-c",2)==0) {
|
||||
channel = ( int)atoi((*argv)+2);
|
||||
if (channel>CHANNEL_FASTFADE) {
|
||||
printf("Invalid channel type\n");
|
||||
syntax();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (strncmp(*argv,"-b",2)==0) {
|
||||
B90 = (float)atof((*argv)+2);
|
||||
if (B90<1 || B90>230) {
|
||||
printf("Invalid B90\n");
|
||||
syntax();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (strncmp(*argv,"-m",2)==0) {
|
||||
fadingModel = (int)atoi((*argv)+2);
|
||||
if (fadingModel<0 || fadingModel>1) {
|
||||
printf("Invalid fading model\n");
|
||||
syntax();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (strncmp(*argv,"-q",2)==0) {
|
||||
submode = (int)atoi((*argv)+2);
|
||||
if (submode<0 || submode>4) {
|
||||
printf("Invalid submode\n");
|
||||
syntax();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (strncmp(*argv,"-d",2)==0) {
|
||||
olddec = 1;
|
||||
}
|
||||
else {
|
||||
printf("Invalid option\n");
|
||||
syntax();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (testtype<2) // old tests
|
||||
if (channel==CHANNEL_FASTFADE) {
|
||||
printf("Invalid Option. Test type 0 and 1 supports only AWGN or Rayleigh Channel model\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
EbNodB = SNRdB+QRA64_SNR_EBNO_OFFSET;
|
||||
|
||||
#if defined(__linux__) || defined(__unix__)
|
||||
srand48(GetTickCount());
|
||||
#endif
|
||||
|
||||
if (testtype==0) {
|
||||
for (k=0;k<nqso;k++) {
|
||||
printf("\n\n------------------------\n");
|
||||
rc = test_proc_1(channel, EbNodB, mode);
|
||||
if (rc==0)
|
||||
nok++;
|
||||
}
|
||||
printf("\n\n%d/%d QSOs to end without repetitions\n",nok,nqso);
|
||||
printf("Input SNR = %.1fdB channel=%s ap-mode=%s\n\n",
|
||||
SNRdB,
|
||||
channel==CHANNEL_AWGN?"AWGN":"RAYLEIGH",
|
||||
apmode_type[mode]
|
||||
);
|
||||
}
|
||||
else if (testtype==1) {
|
||||
test_proc_2(channel, EbNodB, mode);
|
||||
printf("Input SNR = %.1fdB channel=%s ap-mode=%s\n\n",
|
||||
SNRdB,
|
||||
channel==CHANNEL_AWGN?"AWGN":"RAYLEIGH",
|
||||
apmode_type[mode]
|
||||
);
|
||||
}
|
||||
else {
|
||||
printf("Input SNR = %.1fdB ap-mode=%s\n\n",
|
||||
SNRdB,
|
||||
apmode_type[mode]
|
||||
);
|
||||
test_fastfading(EbNodB,B90,fadingModel,submode,mode,olddec, channel, ntx);
|
||||
}
|
||||
return 0;
|
||||
}
|
1121
libm65/qra64/qra64.c
Normal file
1121
libm65/qra64/qra64.c
Normal file
File diff suppressed because it is too large
Load Diff
269
libm65/qra64/qra64.h
Normal file
269
libm65/qra64/qra64.h
Normal file
@ -0,0 +1,269 @@
|
||||
// qra64.h
|
||||
// Encoding/decoding functions for the QRA64 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef _qra64_h_
|
||||
#define _qra64_h_
|
||||
|
||||
// qra64_init(...) initialization flags
|
||||
#define QRA_NOAP 0 // don't use a-priori knowledge
|
||||
#define QRA_AUTOAP 1 // use auto a-priori knowledge
|
||||
#define QRA_USERAP 2 // a-priori knowledge messages provided by the user
|
||||
|
||||
// QRA code parameters
|
||||
#define QRA64_K 12 // information symbols
|
||||
#define QRA64_N 63 // codeword length
|
||||
#define QRA64_C 51 // (number of parity checks C=(N-K))
|
||||
#define QRA64_M 64 // code alphabet size
|
||||
#define QRA64_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
|
||||
|
||||
// Types of a-priori knowledge messages
|
||||
#define APTYPE_CQQRZ 0 // [cq/qrz ? ?/blank]
|
||||
#define APTYPE_MYCALL 1 // [mycall ? ?/blank]
|
||||
#define APTYPE_HISCALL 2 // [? hiscall ?/blank]
|
||||
#define APTYPE_BOTHCALLS 3 // [mycall hiscall ?]
|
||||
#define APTYPE_FULL 4 // [mycall hiscall grid]
|
||||
#define APTYPE_CQHISCALL 5 // [cq/qrz hiscall ?/blank]
|
||||
#define APTYPE_SIZE (APTYPE_CQHISCALL+1)
|
||||
|
||||
typedef struct {
|
||||
float decEsNoMetric;
|
||||
int apflags;
|
||||
int apmsg_set[APTYPE_SIZE]; // indicate which ap type knowledge has
|
||||
// been set by the user
|
||||
// ap messages buffers
|
||||
int apmsg_cqqrz[12]; // [cq/qrz ? ?/blank]
|
||||
int apmsg_call1[12]; // [mycall ? ?/blank]
|
||||
int apmsg_call2[12]; // [? hiscall ?/blank]
|
||||
int apmsg_call1_call2[12]; // [mycall hiscall ?]
|
||||
int apmsg_call1_call2_grid[12]; // [mycall hiscall grid]
|
||||
int apmsg_cq_call2[12]; // [cq hiscall ?/blank]
|
||||
int apmsg_cq_call2_grid[12]; // [cq hiscall grid]
|
||||
|
||||
// ap messages masks
|
||||
int apmask_cqqrz[12];
|
||||
int apmask_cqqrz_ooo[12];
|
||||
int apmask_call1[12];
|
||||
int apmask_call1_ooo[12];
|
||||
int apmask_call2[12];
|
||||
int apmask_call2_ooo[12];
|
||||
int apmask_call1_call2[12];
|
||||
int apmask_call1_call2_grid[12];
|
||||
int apmask_cq_call2[12];
|
||||
int apmask_cq_call2_ooo[12];
|
||||
} qra64codec;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
qra64codec *qra64_init(int flags);
|
||||
// QRA64 mode initialization function
|
||||
// arguments:
|
||||
// flags: set the decoder mode
|
||||
// QRA_NOAP use no a-priori information
|
||||
// QRA_AUTOAP use any relevant previous decodes
|
||||
// QRA_USERAP use a-priori information provided via qra64_apset(...)
|
||||
// returns:
|
||||
// Pointer to initialized qra64codec data structure
|
||||
// this pointer should be passed to the encoding/decoding functions
|
||||
//
|
||||
// 0 if unsuccessful (can't allocate memory)
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void qra64_encode(qra64codec *pcodec, int *y, const int *x);
|
||||
// QRA64 encoder
|
||||
// arguments:
|
||||
// pcodec = pointer to a qra64codec data structure as returned by qra64_init
|
||||
// x = pointer to the message to be encoded, int x[12]
|
||||
// x must point to an array of integers (i.e. defined as int x[12])
|
||||
// y = pointer to encoded message, int y[63]=
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
int qra64_decode(qra64codec *pcodec, float *ebno, int *x, const float *r);
|
||||
// QRA64 mode decoder
|
||||
// arguments:
|
||||
// pcodec = pointer to a qra64codec data structure as returned by qra64_init
|
||||
// ebno = pointer to a float where the avg Eb/No (in dB) will be stored
|
||||
// in case of successfull decoding
|
||||
// (pass a null pointer if not interested)
|
||||
// x = pointer to decoded message, int x[12]
|
||||
// r = pointer to received symbol energies (squared amplitudes)
|
||||
// r must point to an array of length QRA64_M*QRA64_N (=64*63=4032)
|
||||
// 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 QRA64_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
|
||||
// rc=6 [? CALL ?] AP29
|
||||
// rc=7 [? CALL ] AP45
|
||||
// rc=8 [CALL CALL GRID] AP72 (actually a AP68 mask to reduce false decodes)
|
||||
// rc=9 [CQ CALL ?] AP55
|
||||
// rc=10 [CQ CALL ] AP70 (actaully a AP68 mask to reduce false decodes)
|
||||
|
||||
// return codes in the range 1-10 indicate the amount and the type of a-priori
|
||||
// information was required to decode the received message.
|
||||
|
||||
|
||||
// Decode a QRA64 msg using a fast-fading metric
|
||||
int qra64_decode_fastfading(
|
||||
qra64codec *pcodec, // ptr to the codec structure
|
||||
float *ebno, // ptr to where the estimated Eb/No value will be saved
|
||||
int *x, // ptr to decoded message
|
||||
const float *rxen, // ptr to received symbol energies array
|
||||
const int submode, // submode idx (0=QRA64A ... 4=QRA64E)
|
||||
const float B90, // spread bandwidth (90% fractional energy)
|
||||
const int fadingModel); // 0=Gaussian 1=Lorentzian fade model
|
||||
//
|
||||
// rxen: The array of the received bin energies
|
||||
// Bins must be spaced by integer multiples of the symbol rate (1/Ts Hz)
|
||||
// The array must be an array of total length U = L x N where:
|
||||
// L: is the number of frequency bins per message symbol (see after)
|
||||
// N: is the number of symbols in a QRA64 msg (63)
|
||||
//
|
||||
// The number of bins/symbol L depends on the selected submode accordingly to
|
||||
// the following rule:
|
||||
// L = (64+64*2^submode+64) = 64*(2+2^submode)
|
||||
// Tone 0 is always supposed to be at offset 64 in the array.
|
||||
// The m-th tone nominal frequency is located at offset 64 + m*2^submode (m=0..63)
|
||||
//
|
||||
// Submode A: (2^submode = 1)
|
||||
// L = 64*3 = 196 bins/symbol
|
||||
// Total length of the energies array: U = 192*63 = 12096 floats
|
||||
//
|
||||
// Submode B: (2^submode = 2)
|
||||
// L = 64*4 = 256 bins/symbol
|
||||
// Total length of the energies array: U = 256*63 = 16128 floats
|
||||
//
|
||||
// Submode C: (2^submode = 4)
|
||||
// L = 64*6 = 384 bins/symbol
|
||||
// Total length of the energies array: U = 384*63 = 24192 floats
|
||||
//
|
||||
// Submode D: (2^submode = 8)
|
||||
// L = 64*10 = 640 bins/symbol
|
||||
// Total length of the energies array: U = 640*63 = 40320 floats
|
||||
//
|
||||
// Submode E: (2^submode = 16)
|
||||
// L = 64*18 = 1152 bins/symbol
|
||||
// Total length of the energies array: U = 1152*63 = 72576 floats
|
||||
//
|
||||
// Note: The rxen array is modified and reused for internal calculations.
|
||||
//
|
||||
//
|
||||
// B90: spread fading bandwidth in Hz (90% fractional average energy)
|
||||
//
|
||||
// B90 should be in the range 1 Hz ... 238 Hz
|
||||
// The value passed to the call is rounded to the closest value among the
|
||||
// 64 available values:
|
||||
// B = 1.09^k Hz, with k=0,1,...,63
|
||||
//
|
||||
// I.e. B90=27 Hz will be approximated in this way:
|
||||
// k = rnd(log(27)/log(1.09)) = 38
|
||||
// B90 = 1.09^k = 1.09^38 = 26.4 Hz
|
||||
//
|
||||
// For any input value the maximum rounding error is not larger than +/- 5%
|
||||
//
|
||||
// return codes: same return codes of qra64_decode (+some additional error codes)
|
||||
|
||||
|
||||
// Simulate the fast-fading channel (to be used with qra64_decode_fastfading)
|
||||
int qra64_fastfading_channel(
|
||||
float **rxen,
|
||||
const int *xmsg,
|
||||
const int submode,
|
||||
const float EbN0dB,
|
||||
const float B90,
|
||||
const int fadingModel);
|
||||
// Simulate transmission over a fading channel with given B90, fading model and submode
|
||||
// and non coherent detection.
|
||||
// Sets rxen to point to an array of bin energies formatted as required
|
||||
// by the (fast-fading) decoding routine.
|
||||
// returns 0 on success or negative values on error conditions
|
||||
|
||||
|
||||
int qra64_apset(qra64codec *pcodec, const int mycall, const int hiscall, const int grid, const int aptype);
|
||||
// Set decoder a-priori knowledge accordingly to the type of the message to
|
||||
// look up for
|
||||
// arguments:
|
||||
// pcodec = pointer to a qra64codec data structure as returned by qra64_init
|
||||
// mycall = mycall to look for
|
||||
// hiscall = hiscall to look for
|
||||
// grid = grid to look for
|
||||
// aptype = define the type of AP to be set:
|
||||
// APTYPE_CQQRZ set [cq/qrz ? ?/blank]
|
||||
// APTYPE_MYCALL set [mycall ? ?/blank]
|
||||
// APTYPE_HISCALL set [? hiscall ?/blank]
|
||||
// APTYPE_BOTHCALLS set [mycall hiscall ?]
|
||||
// APTYPE_FULL set [mycall hiscall grid]
|
||||
// APTYPE_CQHISCALL set [cq/qrz hiscall ?/blank]
|
||||
|
||||
// returns:
|
||||
// 0 on success
|
||||
// -1 when qra64_init was called with the QRA_NOAP flag
|
||||
// -2 invalid apytpe (valid range [APTYPE_CQQRZ..APTYPE_CQHISCALL]
|
||||
// (APTYPE_CQQRZ [cq/qrz ? ?] is set by default )
|
||||
|
||||
void qra64_apdisable(qra64codec *pcodec, const int aptype);
|
||||
// disable specific AP type
|
||||
// arguments:
|
||||
// pcodec = pointer to a qra64codec data structure as returned by qra64_init
|
||||
// aptype = define the type of AP to be disabled
|
||||
// APTYPE_CQQRZ disable [cq/qrz ? ?/blank]
|
||||
// APTYPE_MYCALL disable [mycall ? ?/blank]
|
||||
// APTYPE_HISCALL disable [ ? hiscall ?/blank]
|
||||
// APTYPE_BOTHCALLS disable [mycall hiscall ? ]
|
||||
// APTYPE_FULL disable [mycall hiscall grid]
|
||||
// APTYPE_CQHISCALL set [cq/qrz hiscall ?/blank]
|
||||
|
||||
void qra64_close(qra64codec *pcodec);
|
||||
// Free memory allocated by qra64_init
|
||||
// arguments:
|
||||
// pcodec = pointer to a qra64codec data structure as returned by qra64_init
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// 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 // _qra64_h_
|
1050
libm65/qra64/qra64_all.c
Normal file
1050
libm65/qra64/qra64_all.c
Normal file
File diff suppressed because it is too large
Load Diff
65
libm65/qra64/qra64_subs.c
Normal file
65
libm65/qra64/qra64_subs.c
Normal file
@ -0,0 +1,65 @@
|
||||
// qra64_subs.c
|
||||
// Fortran interface routines for QRA64
|
||||
|
||||
#include "qra64.h"
|
||||
#include <stdio.h>
|
||||
|
||||
static qra64codec *pqra64codec = NULL;
|
||||
|
||||
void qra64_enc_(int x[], int y[])
|
||||
{
|
||||
if (pqra64codec==NULL) pqra64codec = qra64_init(QRA_USERAP);
|
||||
qra64_encode(pqra64codec, y, x);
|
||||
}
|
||||
|
||||
void qra64_dec_(float r[], int* nc1, int* nc2, int* ng2, int* APtype,
|
||||
int* iset, int* ns0, float* b0, int* nf0,
|
||||
int xdec[], float* snr, int* rc)
|
||||
{
|
||||
/*
|
||||
APtype: AP
|
||||
-----------------------------------------------------------------------
|
||||
-1 0 (no AP information)
|
||||
0 [CQ/QRZ ? ? ] 25/37
|
||||
1 [MyCall ? ? ] 25/37
|
||||
2 [ ? HisCall ? ] 25/37
|
||||
3 [MyCall HisCall ? ] 49/68
|
||||
4 [MyCall HisCall grid] 68
|
||||
5 [CQ/QRZ HisCall ? ] 49/68
|
||||
|
||||
rc Message format AP APTYPE Comments
|
||||
------------------------------------------------------------------------
|
||||
-16 Failed sanity check
|
||||
-2 Decoded but CRC failed
|
||||
-1 No decode
|
||||
0 [ ? ? ? ] 0 -1 Decode with no AP info
|
||||
1 [CQ/QRZ ? ? ] 25 0
|
||||
2 [CQ/QRZ ? _ ] 37 0
|
||||
3 [MyCall ? ? ] 25 1
|
||||
4 [MyCall ? _ ] 37 1
|
||||
5 [MyCall HisCall ? ] 49 3
|
||||
6 [ ? HisCall ? ] 25 2 Optional
|
||||
7 [ ? HisCall _ ] 37 2 Optional
|
||||
8 [MyCall HisCall Grid] 68 4
|
||||
9 [CQ/QRZ HisCall ? ] 49 5 Optional (not needed?)
|
||||
10 [CQ/QRZ HisCall _ ] 68 5 Optional
|
||||
11 [CQ/QRZ HisCall Grid] 68 ? Optional
|
||||
*/
|
||||
|
||||
float EbNodBEstimated;
|
||||
int err=0;
|
||||
int nSubmode=*ns0;
|
||||
float b90=*b0;
|
||||
int nFadingModel=*nf0;
|
||||
|
||||
if(pqra64codec==NULL) pqra64codec = qra64_init(QRA_USERAP);
|
||||
err=qra64_apset(pqra64codec,*nc1,*nc2,*ng2,*APtype);
|
||||
if(err<0) printf("ERROR: qra64_apset returned %d\n",err);
|
||||
|
||||
if(*iset==0) {
|
||||
*rc = qra64_decode_fastfading(pqra64codec,&EbNodBEstimated,xdec,r,
|
||||
nSubmode,b90,nFadingModel);
|
||||
*snr = EbNodBEstimated - 31.0;
|
||||
}
|
||||
}
|
||||
|
88
libm65/qra64/qra64example.txt
Normal file
88
libm65/qra64/qra64example.txt
Normal file
@ -0,0 +1,88 @@
|
||||
$ qra64_nico -h
|
||||
|
||||
QRA64 Mode Tests
|
||||
2016, Nico Palermo - IV3NWV
|
||||
|
||||
---------------------------
|
||||
|
||||
Syntax: qra64 [-s<snrdb>] [-c<channel>] [-a<ap-type>] [-t<testtype>] [-h]
|
||||
Options:
|
||||
-s<snrdb> : set simulation SNR in 2500 Hz BW (default:-27.5 dB)
|
||||
-c<channel> : set channel type 0=AWGN (default) 1=Rayleigh
|
||||
-a<ap-type> : set decode type 0=NOAP 1=AUTOAP (default) 2=USERAP
|
||||
-t<testtype>: 0=simulate seq of msgs between IV3NWV and K1JT (default)
|
||||
1=simulate K1JT receiving K1JT IV3NWV JN66
|
||||
2=simulate fast-fading routines (option -c ignored)
|
||||
Options used only for fast-fading simulations:
|
||||
-b : 90% fading bandwidth in Hz [1..230 Hz] (default = 2.5 Hz)
|
||||
-m : fading model. 0=Gauss, 1=Lorentz (default = Lorentz)
|
||||
-q : qra64 submode. 0=QRA64A,... 4=QRA64E (default = QRA64A)
|
||||
-h: this help
|
||||
|
||||
|
||||
#############################################################################
|
||||
Usage example:
|
||||
|
||||
qra64 -c2 -t2 -a2 -b50 -m1 -q2 -s-26.0 -n50000
|
||||
|
||||
Simulate a fast-fading channel (-c2)
|
||||
Evaluate decoder performance (-t2) with
|
||||
USER_AP (-a2)
|
||||
B90 = 50 Hz (-b50)
|
||||
Lorentz model (-m1)
|
||||
submode QRA64C (-q2)
|
||||
Input SNR = -26.0 dB (-s-26.0)
|
||||
Simulate 50000 transmissions (-n50000)
|
||||
|
||||
(type qra64 -h for command syntax)
|
||||
|
||||
Command Output:
|
||||
|
||||
Input SNR = -26.0dB ap-mode=USER AP
|
||||
|
||||
Simulating the fast-fading channel
|
||||
B90=50.00 Hz - Fading Model=Lorentz - Submode=QRA64C
|
||||
Decoder metric = Matched to fast-fading signal
|
||||
|
||||
Encoding msg [K1JT IV3NWV JN66]
|
||||
50000 transmissions will be simulated
|
||||
|
||||
K1JT decoder enabled for [CQ ? ?/blank]
|
||||
K1JT decoder enabled for [K1JT ? ?/blank]
|
||||
K1JT decoder enabled for [? IV3NWV ?/blank]
|
||||
K1JT decoder enabled for [K1JT IV3NWV ?]
|
||||
K1JT decoder enabled for [K1JT IV3NWV JN66]
|
||||
K1JT decoder enabled for [CQ IV3NWV ?/b/JN66]
|
||||
|
||||
Now decoding with K1JT's decoder...
|
||||
5.5 %
|
||||
Undetected error with rc=6
|
||||
13.1 %
|
||||
Undetected error with rc=7
|
||||
70.8 %
|
||||
Undetected error with rc=1
|
||||
75.8 %
|
||||
Undetected error with rc=9
|
||||
88.9 %
|
||||
Undetected error with rc=6
|
||||
100.0 %
|
||||
|
||||
Msgs transmitted:50000
|
||||
Msg decoded:
|
||||
|
||||
rc= 0 0 with [? ? ?] AP0
|
||||
rc= 1 0 with [CQ ? ?] AP27
|
||||
rc= 2 0 with [CQ ? ] AP42
|
||||
rc= 3 145 with [CALL ? ?] AP29
|
||||
rc= 4 0 with [CALL ? ] AP44
|
||||
rc= 5 12085 with [CALL CALL ?] AP57
|
||||
rc= 6 0 with [? CALL ?] AP29
|
||||
rc= 7 0 with [? CALL ] AP44
|
||||
rc= 8 24307 with [CALL CALL G] AP72
|
||||
rc= 9 0 with [CQ CALL ?] AP55
|
||||
rc=10 0 with [CQ CALL ] AP70
|
||||
rc=11 0 with [CQ CALL G] AP70
|
||||
|
||||
Total: 36537/50000 (5 undetected errors)
|
||||
|
||||
Estimated SNR (average in dB) = -26.26 dB
|
170
libm65/qra64/qra64sim.f90
Normal file
170
libm65/qra64/qra64sim.f90
Normal file
@ -0,0 +1,170 @@
|
||||
program qra64sim
|
||||
|
||||
! Generate simulated QRA64 data for testing the decoder.
|
||||
|
||||
use wavhdr
|
||||
use packjt
|
||||
parameter (NMAX=54*12000) ! = 648,000
|
||||
parameter (NFFT=10*65536,NH=NFFT/2)
|
||||
type(hdr) h !Header for .wav file
|
||||
integer*2 iwave(NMAX) !Generated waveform
|
||||
integer*4 itone(84) !Channel symbols (values 0-63)
|
||||
real*4 xnoise(NMAX) !Generated random noise
|
||||
real*4 dat(NMAX) !Generated real data
|
||||
complex cdat(NMAX) !Generated complex waveform
|
||||
complex cspread(0:NFFT-1) !Complex amplitude for Rayleigh fading
|
||||
complex z
|
||||
real*8 f0,dt,twopi,phi,dphi,baud,fsample,freq
|
||||
character msg*22,fname*11,csubmode*1,arg*12
|
||||
character msgsent*22
|
||||
|
||||
nargs=iargc()
|
||||
if(nargs.ne. 7) then
|
||||
print *, 'Usage: qra64sim "msg" A-E Nsigs fDop DT Nfiles SNR'
|
||||
print *, 'Example qra64sim "K1ABC W9XYZ EN37" A 10 0.2 0.0 1 0'
|
||||
go to 999
|
||||
endif
|
||||
call getarg(1,msg)
|
||||
call getarg(2,csubmode)
|
||||
mode64=2**(ichar(csubmode)-ichar('A'))
|
||||
call getarg(3,arg)
|
||||
read(arg,*) nsigs
|
||||
call getarg(4,arg)
|
||||
read(arg,*) fspread
|
||||
call getarg(5,arg)
|
||||
read(arg,*) xdt
|
||||
call getarg(6,arg)
|
||||
read(arg,*) nfiles
|
||||
call getarg(7,arg)
|
||||
read(arg,*) snrdb
|
||||
|
||||
if(mode64.ge.8) nsigs=1
|
||||
rms=100.
|
||||
fsample=12000.d0 !Sample rate (Hz)
|
||||
dt=1.d0/fsample !Sample interval (s)
|
||||
twopi=8.d0*atan(1.d0)
|
||||
npts=54*12000 !Total samples in .wav file
|
||||
nsps=6912
|
||||
baud=12000.d0/nsps !Keying rate = 1.7361111111
|
||||
nsym=84 !Number of channel symbols
|
||||
h=default_header(12000,npts)
|
||||
dfsig=2000.0/nsigs !Freq spacing between sigs in file (Hz)
|
||||
ichk=0
|
||||
|
||||
write(*,1000)
|
||||
1000 format('File Sig Freq A-E S/N DT Dop Message'/60('-'))
|
||||
|
||||
do ifile=1,nfiles !Loop over requested number of files
|
||||
write(fname,1002) ifile !Output filename
|
||||
1002 format('000000_',i4.4)
|
||||
open(10,file=fname//'.wav',access='stream',status='unknown')
|
||||
xnoise=0.
|
||||
cdat=0.
|
||||
if(snrdb.lt.90) then
|
||||
do i=1,npts
|
||||
xnoise(i)=gran() !Generate gaussian noise
|
||||
enddo
|
||||
endif
|
||||
|
||||
do isig=1,nsigs !Generate requested number of sigs
|
||||
if(mod(nsigs,2).eq.0) f0=1500.0 + dfsig*(isig-0.5-nsigs/2)
|
||||
if(mod(nsigs,2).eq.1) f0=1500.0 + dfsig*(isig-(nsigs+1)/2)
|
||||
if(nsigs.eq.1) f0=1000.0
|
||||
xsnr=snrdb
|
||||
if(snrdb.eq.0.0) xsnr=-20 - isig
|
||||
|
||||
call genqra64(msg,ichk,msgsent,itone,itype)
|
||||
|
||||
bandwidth_ratio=2500.0/6000.0
|
||||
sig=sqrt(2*bandwidth_ratio)*10.0**(0.05*xsnr)
|
||||
if(xsnr.gt.90.0) sig=1.0
|
||||
write(*,1020) ifile,isig,f0,csubmode,xsnr,xdt,fspread,msg
|
||||
1020 format(i4,i4,f10.3,2x,a1,2x,f5.1,f6.2,f6.1,1x,a22)
|
||||
|
||||
phi=0.d0
|
||||
dphi=0.d0
|
||||
k=(xdt+1.0)*12000 !Start audio at t = xdt + 1.0 s
|
||||
isym0=-99
|
||||
do i=1,npts !Add this signal into cdat()
|
||||
isym=i/nsps + 1
|
||||
if(isym.gt.nsym) exit
|
||||
if(isym.ne.isym0) then
|
||||
freq=f0 + itone(isym)*baud*mode64
|
||||
dphi=twopi*freq*dt
|
||||
isym0=isym
|
||||
endif
|
||||
phi=phi + dphi
|
||||
if(phi.gt.twopi) phi=phi-twopi
|
||||
xphi=phi
|
||||
z=cmplx(cos(xphi),sin(xphi))
|
||||
k=k+1
|
||||
if(k.ge.1) cdat(k)=cdat(k) + sig*z
|
||||
enddo
|
||||
enddo
|
||||
|
||||
if(fspread.ne.0) then !Apply specified Doppler spread
|
||||
df=12000.0/nfft
|
||||
twopi=8*atan(1.0)
|
||||
cspread(0)=1.0
|
||||
cspread(NH)=0.
|
||||
b=6.0 !Lorenzian 3/28 onward
|
||||
do i=1,NH
|
||||
f=i*df
|
||||
x=b*f/fspread
|
||||
z=0.
|
||||
a=0.
|
||||
if(x.lt.3.0) then !Cutoff beyond x=3
|
||||
a=sqrt(1.111/(1.0+x*x)-0.1) !Lorentzian
|
||||
call random_number(r1)
|
||||
phi1=twopi*r1
|
||||
z=a*cmplx(cos(phi1),sin(phi1))
|
||||
endif
|
||||
cspread(i)=z
|
||||
z=0.
|
||||
if(x.lt.50.0) then
|
||||
call random_number(r2)
|
||||
phi2=twopi*r2
|
||||
z=a*cmplx(cos(phi2),sin(phi2))
|
||||
endif
|
||||
cspread(NFFT-i)=z
|
||||
enddo
|
||||
|
||||
do i=0,NFFT-1
|
||||
f=i*df
|
||||
if(i.gt.NH) f=(i-nfft)*df
|
||||
s=real(cspread(i))**2 + aimag(cspread(i))**2
|
||||
! write(13,3000) i,f,s,cspread(i)
|
||||
!3000 format(i5,f10.3,3f12.6)
|
||||
enddo
|
||||
! s=real(cspread(0))**2 + aimag(cspread(0))**2
|
||||
! write(13,3000) 1024,0.0,s,cspread(0)
|
||||
|
||||
call four2a(cspread,NFFT,1,1,1) !Transform to time domain
|
||||
|
||||
sum=0.
|
||||
do i=0,NFFT-1
|
||||
p=real(cspread(i))**2 + aimag(cspread(i))**2
|
||||
sum=sum+p
|
||||
enddo
|
||||
avep=sum/NFFT
|
||||
fac=sqrt(1.0/avep)
|
||||
cspread=fac*cspread !Normalize to constant avg power
|
||||
cdat=cspread(1:npts)*cdat !Apply Rayleigh fading
|
||||
|
||||
! do i=0,NFFT-1
|
||||
! p=real(cspread(i))**2 + aimag(cspread(i))**2
|
||||
! write(14,3010) i,p,cspread(i)
|
||||
!3010 format(i8,3f12.6)
|
||||
! enddo
|
||||
|
||||
endif
|
||||
|
||||
dat=aimag(cdat) + xnoise !Add the generated noise
|
||||
fac=32767.0/nsigs
|
||||
if(snrdb.ge.90.0) iwave(1:npts)=nint(fac*dat(1:npts))
|
||||
if(snrdb.lt.90.0) iwave(1:npts)=nint(rms*dat(1:npts))
|
||||
write(10) h,iwave(1:npts) !Save the .wav file
|
||||
close(10)
|
||||
enddo
|
||||
|
||||
999 end program qra64sim
|
33
libm65/qracodes/Makefile.Win
Normal file
33
libm65/qracodes/Makefile.Win
Normal file
@ -0,0 +1,33 @@
|
||||
CC = gcc
|
||||
CFLAGS = -O2 -Wall -I. -D_WIN32
|
||||
|
||||
# Default rules
|
||||
%.o: %.c
|
||||
${CC} ${CFLAGS} -c $<
|
||||
%.o: %.f
|
||||
${FC} ${FFLAGS} -c $<
|
||||
%.o: %.F
|
||||
${FC} ${FFLAGS} -c $<
|
||||
%.o: %.f90
|
||||
${FC} ${FFLAGS} -c $<
|
||||
%.o: %.F90
|
||||
${FC} ${FFLAGS} -c $<
|
||||
|
||||
all: libqra64.a qracodes.exe
|
||||
|
||||
OBJS1 = normrnd.o npfwht.o pdmath.o qra12_63_64_irr_b.o \
|
||||
qra13_64_64_irr_e.o qracodes.o
|
||||
|
||||
libqra64.a: $(OBJS1)
|
||||
ar cr libqra64.a $(OBJS1)
|
||||
ranlib libqra64.a
|
||||
|
||||
OBJS2 = main.o
|
||||
|
||||
qracodes.exe: $(OBJS2)
|
||||
${CC} -o qracodes.exe $(OBJS2) libqra64.a -lm
|
||||
|
||||
.PHONY : clean
|
||||
|
||||
clean:
|
||||
$(RM) *.o libqra64.a qracodes.exe
|
7
libm65/qracodes/ebno10000.txt
Normal file
7
libm65/qracodes/ebno10000.txt
Normal file
@ -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
|
15
libm65/qracodes/ebnovalues.txt
Normal file
15
libm65/qracodes/ebnovalues.txt
Normal file
@ -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
|
11
libm65/qracodes/ebnovaluesfast.txt
Normal file
11
libm65/qracodes/ebnovaluesfast.txt
Normal file
@ -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
|
737
libm65/qracodes/main.c
Normal file
737
libm65/qracodes/main.c
Normal file
@ -0,0 +1,737 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// 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 <windows.h> // required only for GetTickCount(...)
|
||||
#include <process.h> // _beginthread
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
|
||||
// remove unwanted macros
|
||||
#define __cdecl
|
||||
|
||||
// implements Windows API
|
||||
#include <time.h>
|
||||
|
||||
unsigned int GetTickCount(void) {
|
||||
struct timespec ts;
|
||||
unsigned int theTick = 0U;
|
||||
clock_gettime( CLOCK_REALTIME, &ts );
|
||||
theTick = ts.tv_nsec / 1000000;
|
||||
theTick += ts.tv_sec * 1000;
|
||||
return theTick;
|
||||
}
|
||||
|
||||
// Convert Windows millisecond sleep
|
||||
//
|
||||
// VOID WINAPI Sleep(_In_ DWORD dwMilliseconds);
|
||||
//
|
||||
// to Posix usleep (in microseconds)
|
||||
//
|
||||
// int usleep(useconds_t usec);
|
||||
//
|
||||
#include <unistd.h>
|
||||
#define Sleep(x) usleep(x*1000)
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) || ( defined(__MINGW32__) || defined (__MIGW64__) )
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#if __APPLE__
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#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 160
|
||||
|
||||
// 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 int 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;k<size;k++)
|
||||
printf("%02hx ",x[k]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int channel_type;
|
||||
float EbNodB;
|
||||
volatile int nt;
|
||||
volatile int nerrs;
|
||||
volatile int nerrsu;
|
||||
volatile int stop;
|
||||
volatile int done;
|
||||
int ap_index; // index to the a priori knowledge mask
|
||||
const qracode *pcode; // pointer to the code descriptor
|
||||
int *x; //[qra_K]; input message buffer
|
||||
int *y, *ydec; //[qra_N]; encoded/decoded codewords buffers
|
||||
float *qra_v2cmsg; //[qra_NMSG*qra_M]; MP decoder v->c 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<sz;k++) {
|
||||
t = x[k];
|
||||
for (j=0;j<6;j++) {
|
||||
if ((t^sr)&0x01)
|
||||
sr = (sr>>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 int qra_K = pcode->K;
|
||||
const int qra_N = pcode->N;
|
||||
const int qra_M = pcode->M;
|
||||
const int qra_m = pcode->m;
|
||||
const int 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);
|
||||
|
||||
int 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
|
||||
int *x=pdata->x; // message buffer
|
||||
int *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;k<qra_K;k++)
|
||||
x[k]=k%qra_M;
|
||||
|
||||
qra_encode(pcode,y,x);
|
||||
|
||||
while (pdata->stop==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;k<qra_N;k++)
|
||||
rp[k*qra_M+y[k]]+=A;
|
||||
}
|
||||
else if (channel_type == CHANNEL_RAYLEIGH) {
|
||||
normrnd_s(chp,qra_N,0,sigmach);
|
||||
normrnd_s(chq,qra_N,0,sigmach);
|
||||
for (k=0;k<qra_N;k++) {
|
||||
rp[k*qra_M+y[k]]+=A*chp[k];
|
||||
rq[k*qra_M+y[k]]+=A*chq[k];
|
||||
}
|
||||
}
|
||||
else {
|
||||
pdata->done = 1;
|
||||
return; // unknown channel type
|
||||
}
|
||||
|
||||
// compute the squares of the amplitudes of the received samples
|
||||
for (k=0;k<NSAMPLES;k++)
|
||||
r[k] = rp[k]*rp[k] + rq[k]*rq[k];
|
||||
|
||||
// compute the intrinsic symbols probabilities
|
||||
qra_mfskbesselmetric(ix,r,pcode->m,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;k<qra_K;k++)
|
||||
if (ydec[k]!=x[k]) { // decoded msg differs from the transmitted one
|
||||
nerrsu += 1; // it's a false decode
|
||||
nerrs += 1;
|
||||
// uncomment to see what the undetected error pattern looks like
|
||||
// printword("U", ydec);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
else // failed to converge to a solution within the given number of iterations
|
||||
nerrs++;
|
||||
|
||||
nt = nt+1;
|
||||
|
||||
pdata->nt=nt;
|
||||
pdata->nerrs=nerrs;
|
||||
pdata->nerrsu=nerrsu;
|
||||
|
||||
}
|
||||
|
||||
pdata->done=1;
|
||||
|
||||
#if _WIN32
|
||||
_endthread();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(__linux__) || ( defined(__MINGW32__) || defined (__MIGW64__) )
|
||||
|
||||
void *wer_test_pthread(void *p)
|
||||
{
|
||||
wer_test_thread ((wer_test_ds *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void ix_mask(const qracode *pcode, float *r, const int *mask, const int *x)
|
||||
{
|
||||
// mask intrinsic information (channel observations) with a priori knowledge
|
||||
|
||||
int k,kk, smask;
|
||||
const int qra_K=pcode->K;
|
||||
const int qra_M=pcode->M;
|
||||
const int qra_m=pcode->m;
|
||||
|
||||
for (k=0;k<qra_K;k++) {
|
||||
smask = mask[k];
|
||||
if (smask) {
|
||||
for (kk=0;kk<qra_M;kk++)
|
||||
if (((kk^x[k])&smask)!=0)
|
||||
*(PD_ROWADDR(r,qra_M,k)+kk) = 0.f;
|
||||
|
||||
pd_norm(PD_ROWADDR(r,qra_M,k),qra_m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int wer_test_proc(const qracode *pcode, int nthreads, int chtype, int ap_index, float *EbNodB, int *nerrstgt, int nitems)
|
||||
{
|
||||
int k,nn,j,nt,nerrs,nerrsu,nd;
|
||||
int cini,cend;
|
||||
char fnameout[128];
|
||||
FILE *fout;
|
||||
wer_test_ds wt[NTHREADS_MAX];
|
||||
float pe,avgt;
|
||||
|
||||
nn = sizeof(EbNodB)/sizeof(float); // size of the EbNo array to test
|
||||
|
||||
if (nthreads>NTHREADS_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;j<nthreads;j++) {
|
||||
wt[j].channel_type=chtype;
|
||||
wt[j].ap_index = ap_index;
|
||||
wt[j].pcode = pcode;
|
||||
wt[j].x = (int*)malloc(pcode->K*sizeof(int));
|
||||
wt[j].y = (int*)malloc(pcode->N*sizeof(int));
|
||||
wt[j].ydec = (int*)malloc(pcode->N*sizeof(int));
|
||||
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<nitems;k++) {
|
||||
|
||||
printf("\nTesting at Eb/No=%4.1f dB...",EbNodB[k]);
|
||||
fflush (stdout);
|
||||
|
||||
for (j=0;j<nthreads;j++) {
|
||||
wt[j].EbNodB=EbNodB[k];
|
||||
wt[j].nt=0;
|
||||
wt[j].nerrs=0;
|
||||
wt[j].nerrsu=0;
|
||||
wt[j].done = 0;
|
||||
wt[j].stop = 0;
|
||||
#if defined(__linux__) || ( defined(__MINGW32__) || defined (__MIGW64__) )
|
||||
if (pthread_create (&wt[j].thread, 0, wer_test_pthread, &wt[j])) {
|
||||
perror ("Creating thread: ");
|
||||
exit (255);
|
||||
}
|
||||
#else
|
||||
_beginthread((void*)(void*)wer_test_thread,0,&wt[j]);
|
||||
#endif
|
||||
}
|
||||
|
||||
nd = 0;
|
||||
cini = GetTickCount();
|
||||
|
||||
while (1) {
|
||||
// count errors
|
||||
nerrs = 0;
|
||||
for (j=0;j<nthreads;j++)
|
||||
nerrs += wt[j].nerrs;
|
||||
// stop the working threads
|
||||
// if number of errors reached at this Eb/No value
|
||||
if (nerrs>=nerrstgt[k]) {
|
||||
for (j=0;j<nthreads;j++)
|
||||
wt[j].stop = 1;
|
||||
break;
|
||||
}
|
||||
else { // continue with the simulation
|
||||
Sleep(2);
|
||||
nd = (nd+1)%100;
|
||||
if (nd==0) {
|
||||
printf(".");
|
||||
fflush (stdout);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
cend = GetTickCount();
|
||||
|
||||
// wait for the working threads to exit
|
||||
for (j=0;j<nthreads;j++)
|
||||
#if defined(__linux__) || ( defined(__MINGW32__) || defined (__MIGW64__) )
|
||||
{
|
||||
void *rc;
|
||||
if (pthread_join (wt[j].thread, &rc)) {
|
||||
perror ("Waiting working threads to exit");
|
||||
exit (255);
|
||||
}
|
||||
}
|
||||
#else
|
||||
while(wt[j].done==0)
|
||||
Sleep(1);
|
||||
|
||||
#endif
|
||||
printf("\n");
|
||||
fflush (stdout);
|
||||
|
||||
// compute the total number of transmitted codewords
|
||||
// the total number of errors and the total number of undetected errors
|
||||
nt = 0;
|
||||
nerrs =0;
|
||||
nerrsu = 0;
|
||||
for (j=0;j<nthreads;j++) {
|
||||
nt += wt[j].nt;
|
||||
nerrs += wt[j].nerrs;
|
||||
nerrsu += wt[j].nerrsu;
|
||||
}
|
||||
|
||||
pe = 1.0f*nerrs/nt; // word error rate
|
||||
avgt = 1.0f*(cend-cini)/nt; // average time per decode (ms)
|
||||
|
||||
printf("Elapsed Time=%6.1fs (%5.2fms/word)\nTransmitted=%8d - Errors=%6d - Undetected=%3d - WER=%.2e\n",
|
||||
0.001f*(cend-cini),
|
||||
avgt, nt, nerrs, nerrsu, pe);
|
||||
fflush (stdout);
|
||||
|
||||
// save simulation data to output file
|
||||
fprintf(fout,"%01d %.2f %d %d %d %.2f %.2e\n",
|
||||
chtype,
|
||||
EbNodB[k],
|
||||
nt,
|
||||
nerrs,
|
||||
nerrsu,
|
||||
avgt,
|
||||
pe);
|
||||
|
||||
}
|
||||
|
||||
fclose(fout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
const qracode *codetotest[] = {
|
||||
&qra_12_63_64_irr_b,
|
||||
&qra_13_64_64_irr_e
|
||||
};
|
||||
|
||||
void syntax(void)
|
||||
{
|
||||
printf("\nQ-ary Repeat-Accumulate Code Word Error Rate Simulator\n");
|
||||
printf("2016, Nico Palermo - IV3NWV\n\n");
|
||||
printf("Syntax: qracodes [-q<code_index>] [-t<threads>] [-c<ch_type>] [-a<ap_index>] [-f<fnamein>[-h]\n");
|
||||
printf("Options: \n");
|
||||
printf(" -q<code_index>: code to simulate. 0=qra_12_63_64_irr_b\n");
|
||||
printf(" 1=qra_13_64_64_irr_e (default)\n");
|
||||
printf(" -t<threads> : number of threads to be used for the simulation [1..24]\n");
|
||||
printf(" (default=8)\n");
|
||||
printf(" -c<ch_type> : channel_type. 0=AWGN 1=Rayleigh \n");
|
||||
printf(" (default=AWGN)\n");
|
||||
printf(" -a<ap_index> : 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<fnamein> : 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];
|
||||
int nerrstgt[SIM_POINTS_MAX];
|
||||
FILE *fin;
|
||||
|
||||
char fnamein[128]= "ebnovalues.txt";
|
||||
char buf[128];
|
||||
|
||||
int nitems = 0;
|
||||
int code_idx = 1;
|
||||
int nthreads = 8;
|
||||
int ch_type = CHANNEL_AWGN;
|
||||
int 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 = (int)atoi((*argv)+2);
|
||||
if (code_idx>1) {
|
||||
printf("Invalid code index\n");
|
||||
syntax();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (strncmp(*argv,"-t",2)==0) {
|
||||
nthreads = (int)atoi((*argv)+2);
|
||||
printf("nthreads = %d\n",nthreads);
|
||||
if (nthreads>NTHREADS_MAX) {
|
||||
printf("Invalid number of threads\n");
|
||||
syntax();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (strncmp(*argv,"-c",2)==0) {
|
||||
ch_type = (int)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 = (int)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;
|
||||
}
|
||||
|
82
libm65/qracodes/normrnd.c
Normal file
82
libm65/qracodes/normrnd.c
Normal file
@ -0,0 +1,82 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#include "normrnd.h"
|
||||
|
||||
#if _WIN32 // note the underscore: without it, it's not msdn official!
|
||||
// Windows (x64 and x86)
|
||||
#include <windows.h> // required only for GetTickCount(...)
|
||||
#define K_RAND_MAX UINT_MAX
|
||||
#elif _SVID_SOURCE || _XOPEN_SOURCE || __unix__ || (defined (__APPLE__) && defined(__MACH__)) /* POSIX or Unix or Apple */
|
||||
#include <stdlib.h>
|
||||
#define rand_s(x) (*x)=(unsigned int)lrand48() // returns unsigned integers in the range 0..0x7FFFFFFF
|
||||
#define K_RAND_MAX 0x7FFFFFFF // that's the max number
|
||||
// generated by lrand48
|
||||
#else
|
||||
#error "No good quality PRNG found"
|
||||
#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((unsigned int*)&r); phi = (M_2PI/(1.0f+K_RAND_MAX))*r;
|
||||
rand_s((unsigned int*)&r); u = (float)sqrt(-2.0f* log( (1.0f/(1.0f+K_RAND_MAX))*(1.0f+r) ) );
|
||||
*dst++ = (float)cos(phi)*u*stdev+mean;
|
||||
set=1;
|
||||
}
|
||||
}
|
||||
|
||||
/* NOT USED
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
*/
|
51
libm65/qracodes/normrnd.h
Normal file
51
libm65/qracodes/normrnd.h
Normal file
@ -0,0 +1,51 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef _normrnd_h_
|
||||
#define _normrnd_h_
|
||||
|
||||
#define _CRT_RAND_S
|
||||
#include <stdlib.h>
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
#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
|
||||
|
||||
/* not used
|
||||
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_
|
||||
|
216
libm65/qracodes/npfwht.c
Normal file
216
libm65/qracodes/npfwht.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
#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);
|
||||
}
|
45
libm65/qracodes/npfwht.h
Normal file
45
libm65/qracodes/npfwht.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
#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_
|
385
libm65/qracodes/pdmath.c
Normal file
385
libm65/qracodes/pdmath.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
#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 int *perm, int ndim)
|
||||
{
|
||||
// TODO: non-loop implementation
|
||||
while (ndim--)
|
||||
dst[ndim] = src[perm[ndim]];
|
||||
}
|
||||
|
||||
void pd_bwdperm(float *dst, float *src, const 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;
|
||||
}
|
85
libm65/qracodes/pdmath.h
Normal file
85
libm65/qracodes/pdmath.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#ifndef _pdmath_h_
|
||||
#define _pdmath_h_
|
||||
|
||||
#include <memory.h>
|
||||
|
||||
#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 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 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_
|
534
libm65/qracodes/qra12_63_64_irr_b.c
Normal file
534
libm65/qracodes/qra12_63_64_irr_b.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
#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 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 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 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 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 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 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
|
39
libm65/qracodes/qra12_63_64_irr_b.h
Normal file
39
libm65/qracodes/qra12_63_64_irr_b.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
#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
|
534
libm65/qracodes/qra13_64_64_irr_e.c
Normal file
534
libm65/qracodes/qra13_64_64_irr_e.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
#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 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 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 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 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 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 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
|
39
libm65/qracodes/qra13_64_64_irr_e.h
Normal file
39
libm65/qracodes/qra13_64_64_irr_e.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
#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
|
474
libm65/qracodes/qracodes.c
Normal file
474
libm65/qracodes/qracodes.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "npfwht.h"
|
||||
#include "pdmath.h"
|
||||
|
||||
#include "qracodes.h"
|
||||
|
||||
int qra_encode(const qracode *pcode, int *y, const int *x)
|
||||
{
|
||||
int k,j,kk,jj;
|
||||
int t, chk = 0;
|
||||
|
||||
const int K = pcode->K;
|
||||
const int M = pcode->M;
|
||||
const int NC= pcode->NC;
|
||||
const int a = pcode->a;
|
||||
const int *acc_input_idx = pcode->acc_input_idx;
|
||||
const int *acc_input_wlog = pcode->acc_input_wlog;
|
||||
const int *gflog = pcode->gflog;
|
||||
const int *gfexp = pcode->gfexp;
|
||||
|
||||
// copy the systematic symbols to destination
|
||||
memcpy(y,x,K*sizeof(int));
|
||||
|
||||
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<NC;k++) {
|
||||
t = x[acc_input_idx[k]];
|
||||
if (t) {
|
||||
// multiply input by weight[k] and xor it with previous check
|
||||
t = (gflog[t] + acc_input_wlog[k])%(M-1);
|
||||
t = gfexp[t];
|
||||
chk ^=t;
|
||||
}
|
||||
y[k] = chk;
|
||||
}
|
||||
|
||||
#ifdef QRA_DEBUG
|
||||
// verify that the encoder accumulator is terminated to 0
|
||||
// (we designed the code this way so that Iex = 1 when Ia = 1)
|
||||
t = x[acc_input_idx[k]];
|
||||
if (t) {
|
||||
t = (gflog[t] + acc_input_wlog[k])%(M-1);
|
||||
t = gfexp[t];
|
||||
// accumulation
|
||||
chk ^=t;
|
||||
}
|
||||
return (chk==0);
|
||||
#else
|
||||
return 1;
|
||||
#endif // QRA_DEBUG
|
||||
}
|
||||
else { // grouping factor > 1
|
||||
for (k=0;k<NC;k++) {
|
||||
kk = a*k;
|
||||
for (j=0;j<a;j++) {
|
||||
jj = kk+j;
|
||||
// irregular grouping support
|
||||
if (acc_input_idx[jj]<0)
|
||||
continue;
|
||||
t = x[acc_input_idx[jj]];
|
||||
if (t) {
|
||||
// multiply input by weight[k] and xor it with previous check
|
||||
t = (gflog[t] + acc_input_wlog[jj])%(M-1);
|
||||
t = gfexp[t];
|
||||
chk ^=t;
|
||||
}
|
||||
}
|
||||
y[k] = chk;
|
||||
}
|
||||
#ifdef QRA_DEBUG
|
||||
// verify that the encoder accumulator is terminated to 0
|
||||
// (we designed the code this way so that Iex = 1 when Ia = 1)
|
||||
kk = a*k;
|
||||
for (j=0;j<a;j++) {
|
||||
jj = kk+j;
|
||||
if (acc_input_idx[jj]<0)
|
||||
continue;
|
||||
t = x[acc_input_idx[jj]];
|
||||
if (t) {
|
||||
// multiply input by weight[k] and xor it with previous check
|
||||
t = (gflog[t] + acc_input_wlog[jj])%(M-1);
|
||||
t = gfexp[t];
|
||||
chk ^=t;
|
||||
}
|
||||
}
|
||||
return (chk==0);
|
||||
#else
|
||||
return 1;
|
||||
#endif // QRA_DEBUG
|
||||
}
|
||||
}
|
||||
|
||||
static void qra_ioapprox(float *src, float C, int nitems)
|
||||
{
|
||||
// In place approximation of the modified bessel function I0(x*C)
|
||||
// Computes src[k] = Io(src[k]*C) where Io() is the modified Bessel function of first kind and order 0
|
||||
|
||||
float v;
|
||||
float vsq;
|
||||
|
||||
while (nitems--) {
|
||||
v = src[nitems]*C;
|
||||
|
||||
// rational approximation of log(Io(v))
|
||||
vsq = v*v;
|
||||
v = vsq*(v+0.039f)/(vsq*.9931f+v*2.6936f+0.5185f);
|
||||
|
||||
if (v>80.f) // avoid floating point exp() overflows
|
||||
v=80.f;
|
||||
|
||||
src[nitems] = (float)exp(v);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float qra_mfskbesselmetric(float *pix, const float *rsq, const int m, const int 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.
|
||||
|
||||
// returns the estimated noise standard deviation
|
||||
|
||||
int k;
|
||||
float rsum = 0.f;
|
||||
float sigmaest, cmetric;
|
||||
|
||||
const int M = 1<<m;
|
||||
const int nsamples = M*N;
|
||||
|
||||
// compute total power and modulus of input signal
|
||||
for (k=0;k<nsamples;k++) {
|
||||
rsum = rsum+rsq[k];
|
||||
pix[k] = (float)sqrt(rsq[k]);
|
||||
}
|
||||
|
||||
rsum = rsum/nsamples; // average S+N
|
||||
|
||||
// IMPORTANT NOTE: in computing the noise stdev it is assumed that
|
||||
// in the input amplitudes there's no strong interference!
|
||||
// A more robust estimation can be done evaluating the histogram of the input amplitudes
|
||||
|
||||
sigmaest = (float)sqrt(rsum/(1.0f+EsNoMetric/M)/2); // estimated noise stdev
|
||||
cmetric = (float)sqrt(2*EsNoMetric)/sigmaest;
|
||||
|
||||
for (k=0;k<N;k++) {
|
||||
// compute bessel metric for each symbol in the codeword
|
||||
qra_ioapprox(PD_ROWADDR(pix,M,k),cmetric,M);
|
||||
// normalize to a probability distribution
|
||||
pd_norm(PD_ROWADDR(pix,M,k),m);
|
||||
}
|
||||
|
||||
return sigmaest;
|
||||
}
|
||||
|
||||
|
||||
#ifdef QRA_DEBUG
|
||||
void pd_print(int imsg,float *ppd,int size)
|
||||
{
|
||||
int k;
|
||||
printf("imsg=%d\n",imsg);
|
||||
for (k=0;k<size;k++)
|
||||
printf("%7.1e ",ppd[k]);
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#define ADDRMSG(fp, msgidx) PD_ROWADDR(fp,qra_M,msgidx)
|
||||
#define C2VMSG(msgidx) PD_ROWADDR(qra_c2vmsg,qra_M,msgidx)
|
||||
#define V2CMSG(msgidx) PD_ROWADDR(qra_v2cmsg,qra_M,msgidx)
|
||||
#define MSGPERM(logw) PD_ROWADDR(qra_pmat,qra_M,logw)
|
||||
|
||||
#define QRACODE_MAX_M 256 // Maximum alphabet size handled by qra_extrinsic
|
||||
|
||||
int qra_extrinsic(const qracode *pcode,
|
||||
float *pex,
|
||||
const float *pix,
|
||||
int maxiter,
|
||||
float *qra_v2cmsg,
|
||||
float *qra_c2vmsg)
|
||||
{
|
||||
const int qra_M = pcode->M;
|
||||
const int qra_m = pcode->m;
|
||||
const int qra_V = pcode->V;
|
||||
const int qra_MAXVDEG = pcode->MAXVDEG;
|
||||
const int *qra_vdeg = pcode->vdeg;
|
||||
const int qra_C = pcode->C;
|
||||
const int qra_MAXCDEG = pcode->MAXCDEG;
|
||||
const int *qra_cdeg = pcode->cdeg;
|
||||
const int *qra_v2cmidx = pcode->v2cmidx;
|
||||
const int *qra_c2vmidx = pcode->c2vmidx;
|
||||
const int *qra_pmat = pcode->gfpmat;
|
||||
const int *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
|
||||
int nv; // current variable
|
||||
int nc; // current check
|
||||
int k,kk; // loop indexes
|
||||
|
||||
int 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;nv<qra_V;nv++) {
|
||||
|
||||
ndeg = qra_vdeg[nv]; // degree of current node
|
||||
msgbase = nv*qra_MAXVDEG; // base to msg index row for the current node
|
||||
|
||||
// copy intrinsics on v->c
|
||||
for (k=1;k<ndeg;k++) {
|
||||
imsg = qra_v2cmidx[msgbase+k];
|
||||
pd_init(V2CMSG(imsg),ADDRMSG(pix,nv),qra_M);
|
||||
}
|
||||
}
|
||||
|
||||
// message passing algorithm iterations ------------------------------
|
||||
|
||||
for (nit=0;nit<maxiter;nit++) {
|
||||
|
||||
// c->v 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;nc<qra_C;nc++) {
|
||||
|
||||
ndeg = qra_cdeg[nc]; // degree of current node
|
||||
|
||||
if (ndeg==1) // this should never happen (code factors must have deg>1)
|
||||
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;k<ndeg;k++) {
|
||||
imsg = qra_c2vmidx[msgbase+k]; // msg index
|
||||
np_fwht(qra_m,V2CMSG(imsg),V2CMSG(imsg)); // compute fwht
|
||||
}
|
||||
|
||||
// compute products and transform them back in the WH "time" domain
|
||||
for (k=0;k<ndeg;k++) {
|
||||
|
||||
// init output message to uniform distribution
|
||||
pd_init(msgout,pd_uniform(qra_m),qra_M);
|
||||
|
||||
// c->v = 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;kk<ndeg;kk++)
|
||||
if (kk!=k) {
|
||||
imsg = qra_c2vmidx[msgbase+kk];
|
||||
pd_imul(msgout,V2CMSG(imsg),qra_m);
|
||||
}
|
||||
|
||||
// transform product back in the WH "time" domain
|
||||
|
||||
// Very important trick:
|
||||
// we bias WHT[0] so that the sum of output pd components is always strictly positive
|
||||
// this helps avoiding the effects of underflows in the v->c 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;k<ndeg;k++)
|
||||
|
||||
} // for (nc=qra_V;nc<qra_C;nc++)
|
||||
|
||||
// v->c step -----------------------------------------------------
|
||||
for (nv=0;nv<qra_V;nv++) {
|
||||
|
||||
ndeg = qra_vdeg[nv]; // degree of current node
|
||||
msgbase = nv*qra_MAXVDEG; // base to msg index row for the current node
|
||||
|
||||
for (k=0;k<ndeg;k++) {
|
||||
// init output message to uniform distribution
|
||||
pd_init(msgout,pd_uniform(qra_m),qra_M);
|
||||
|
||||
// v->c msg = prod(c->v)
|
||||
// TODO: factor factors to reduce the number of computations for high degree nodes
|
||||
for (kk=0;kk<ndeg;kk++)
|
||||
if (kk!=k) {
|
||||
imsg = qra_v2cmidx[msgbase+kk];
|
||||
pd_imul(msgout,C2VMSG(imsg),qra_m);
|
||||
}
|
||||
|
||||
#ifdef QRA_DEBUG
|
||||
// normalize and check if product of messages v->c 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<ndeg;kk++) {
|
||||
imsg = qra_v2cmidx[msgbase+kk];
|
||||
pd_print(imsg,C2VMSG(imsg),qra_M);
|
||||
}
|
||||
printf("-----------------\n");
|
||||
}
|
||||
#else
|
||||
// normalize the result to a probability distribution
|
||||
pd_norm(msgout,qra_m);
|
||||
#endif
|
||||
// weight and output
|
||||
imsg = qra_v2cmidx[msgbase+k]; // current output msg index
|
||||
wmsg = qra_msgw[imsg]; // current msg weight
|
||||
|
||||
if (wmsg==0) {
|
||||
pd_init(V2CMSG(imsg),msgout,qra_M);
|
||||
}
|
||||
else {
|
||||
// output p(alfa^w*x)
|
||||
pd_fwdperm(V2CMSG(imsg),msgout, MSGPERM(wmsg), qra_M);
|
||||
}
|
||||
|
||||
} // for (k=0;k<ndeg;k++)
|
||||
} // for (nv=0;nv<qra_V;nv++)
|
||||
|
||||
// check extrinsic information ------------------------------
|
||||
// We assume that decoding is successful if each of the extrinsic
|
||||
// symbol probability is close to ej, where ej = [0 0 0 1(j-th position) 0 0 0 ]
|
||||
// Therefore, for each symbol k in the codeword we compute max(prob(Xk))
|
||||
// and we stop the iterations if sum(max(prob(xk)) is close to the codeword length
|
||||
// Note: this is a more restrictive criterium than that of computing the a
|
||||
// posteriori probability of each symbol, making a hard decision and then check
|
||||
// if the codeword syndrome is null.
|
||||
// WARNING: this is tricky and probably works only for the particular class of RA codes
|
||||
// we are coping with (we designed the code weights so that for any input symbol the
|
||||
// sum of its weigths is always 0, thus terminating the accumulator trellis to zero
|
||||
// for every combination of the systematic symbols).
|
||||
// More generally we should instead compute the max a posteriori probabilities
|
||||
// (as a product of the intrinsic and extrinsic information), make a symbol by symbol hard
|
||||
// decision and then check that the syndrome of the result is indeed null.
|
||||
|
||||
totex = 0;
|
||||
for (nv=0;nv<qra_V;nv++)
|
||||
totex += pd_max(V2CMSG(nv),qra_M);
|
||||
|
||||
if (totex>(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;nit<maxiter;nit++)
|
||||
|
||||
// copy extrinsic information to output to do the actual max a posteriori prob decoding
|
||||
pd_init(pex,V2CMSG(0),(qra_M*qra_V));
|
||||
return rc;
|
||||
}
|
||||
|
||||
void qra_mapdecode(const qracode *pcode, int *xdec, float *pex, const float *pix)
|
||||
{
|
||||
// Maximum a posteriori probability decoding.
|
||||
// Given the intrinsic information (pix) and extrinsic information (pex) (computed with qra_extrinsic(...))
|
||||
// compute pmap = pex*pix and decode each (information) symbol of the received codeword
|
||||
// as the symbol which maximizes pmap
|
||||
|
||||
// Returns:
|
||||
// xdec[k] = decoded (information) symbols k=[0..qra_K-1]
|
||||
|
||||
// Note: pex is destroyed and overwritten with mapp
|
||||
|
||||
const int qra_M = pcode->M;
|
||||
const int qra_m = pcode->m;
|
||||
const int qra_K = pcode->K;
|
||||
|
||||
int k;
|
||||
|
||||
for (k=0;k<qra_K;k++) {
|
||||
// compute a posteriori prob
|
||||
pd_imul(PD_ROWADDR(pex,qra_M,k),PD_ROWADDR(pix,qra_M,k),qra_m);
|
||||
xdec[k]=pd_argmax(NULL, PD_ROWADDR(pex,qra_M,k), qra_M);
|
||||
}
|
||||
}
|
79
libm65/qracodes/qracodes.h
Normal file
79
libm65/qracodes/qracodes.h
Normal file
@ -0,0 +1,79 @@
|
||||
// qracodes.h
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef _qracodes_h_
|
||||
#define _qracodes_h_
|
||||
|
||||
// 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 int K; // number of information symbols
|
||||
const int N; // codeword length in symbols
|
||||
const int m; // bits/symbol
|
||||
const int M; // Symbol alphabet cardinality (2^m)
|
||||
const int a; // code grouping factor
|
||||
const int NC; // number of check symbols (N-K)
|
||||
const int V; // number of variables in the code graph (N)
|
||||
const int C; // number of factors in the code graph (N +(N-K)+1)
|
||||
const int NMSG; // number of msgs in the code graph
|
||||
const int MAXVDEG; // maximum variable degree
|
||||
const int MAXCDEG; // maximum factor degree
|
||||
const int 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 int *acc_input_wlog;
|
||||
const int *gflog;
|
||||
const int *gfexp;
|
||||
// tables used by the decoder -------------------------
|
||||
const int *msgw;
|
||||
const int *vdeg;
|
||||
const int *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, int *y, const int *x);
|
||||
float qra_mfskbesselmetric(float *pix, const float *rsq, const int m, const int 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, int *xdec, float *pex, const float *pix);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _qracodes_h_
|
Loading…
Reference in New Issue
Block a user