diff --git a/pac_encoder.hh b/pac_encoder.hh index 6b642d1..f4fdc56 100644 --- a/pac_encoder.hh +++ b/pac_encoder.hh @@ -22,7 +22,7 @@ class PACEncoder bool b4 = (*state >> 4) & 1; bool b6 = (*state >> 6) & 1; bool output = input ^ b1 ^ b3 ^ b4 ^ b6; - *state = ((*state & 126) << 1) | (input ? 2 : 0) | (output ? 1 : 0); + *state = ((*state & 62) << 1) | (input ? 2 : 0) | (output ? 1 : 0); return output; } public: @@ -31,11 +31,22 @@ public: int length = 1 << level; int state = 0; int frozen = length - mesg_bits; - for (int i = 0; i < length; i += 2) { - TYPE msg0 = rank_map[i] < frozen ? PH::one() : *message++; - TYPE msg1 = rank_map[i+1] < frozen ? PH::one() : *message++; - msg0 = 1 - 2 * conv(&state, msg0 < 0); - msg1 = 1 - 2 * conv(&state, msg1 < 0); + for (int i = 0, j = 0; i < length; i += 2) { + TYPE msg0 = rank_map[i] < frozen ? PH::one() : message[j++]; + if (j) + conv(&state, msg0 < 0); + TYPE msg1 = rank_map[i+1] < frozen ? PH::one() : message[j++]; + if (j) + conv(&state, msg1 < 0); + } + state |= (state & 126) << 7; + for (int i = 0, j = 0; i < length; i += 2) { + TYPE msg0 = rank_map[i] < frozen ? PH::one() : message[j++]; + if (j) + msg0 = 1 - 2 * conv(&state, msg0 < 0); + TYPE msg1 = rank_map[i+1] < frozen ? PH::one() : message[j++]; + if (j) + msg1 = 1 - 2 * conv(&state, msg1 < 0); codeword[i] = PH::qmul(msg0, msg1); codeword[i+1] = msg1; } diff --git a/pac_list_decoder.hh b/pac_list_decoder.hh index ec8eb60..9129ea2 100644 --- a/pac_list_decoder.hh +++ b/pac_list_decoder.hh @@ -46,19 +46,23 @@ struct PACListTree bool b4 = (*state >> 4) & 1; bool b6 = (*state >> 6) & 1; bool output = input ^ b1 ^ b3 ^ b4 ^ b6; - *state = ((*state & 126) << 1) | (input ? 2 : 0) | (output ? 1 : 0); + *state = ((*state & 62) << 1) | (input ? 2 : 0) | (output ? 1 : 0); return output; } - static MAP rate0(PATH *metric, int *state, TYPE *hard, TYPE *soft) + static MAP rate0(PATH *metric, int *count, int *state, TYPE *hard, TYPE *soft) { TYPE sft = soft[1]; - for (int k = 0; k < TYPE::SIZE; ++k) - if (conv(state+k, 0) != (sft.v[k] < 0)) - metric[k] += std::abs(sft.v[k]); - TYPE hrd; - for (int k = 0; k < TYPE::SIZE; ++k) - hrd.v[k] = 1 - 2 * (state[k] & 1); - *hard = hrd; + if (*count) { + for (int k = 0; k < TYPE::SIZE; ++k) + if (conv(state+k, 0) != (sft.v[k] < 0)) + metric[k] += std::abs(sft.v[k]); + TYPE hrd; + for (int k = 0; k < TYPE::SIZE; ++k) + hrd.v[k] = 1 - 2 * (state[k] & 1); + *hard = hrd; + } else { + *hard = PH::one(); + } MAP map; for (int k = 0; k < TYPE::SIZE; ++k) map.v[k] = k; @@ -102,12 +106,12 @@ struct PACListTree soft[1] = PH::prod(soft[2], soft[3]); MAP lmap, rmap; if (rank[0] < frozen) - lmap = rate0(metric, state, hard, soft); + lmap = rate0(metric, count, state, hard, soft); else lmap = rate1(metric, message, maps, count, state, hard, soft); soft[1] = PH::madd(hard[0], vshuf(soft[2], lmap), vshuf(soft[3], lmap)); if (rank[1] < frozen) - rmap = rate0(metric, state, hard+1, soft); + rmap = rate0(metric, count, state, hard+1, soft); else rmap = rate1(metric, message, maps, count, state, hard+1, soft); hard[0] = PH::qmul(vshuf(hard[0], rmap), hard[1]); @@ -132,17 +136,49 @@ public: { assert(level <= MAX_M); PATH metric[TYPE::SIZE]; - int count = 0; + int state[TYPE::SIZE]; + int count; + int length = 1 << level; + int frozen = length - mesg_bits; + int best_metric = 1000000; + int best_round = 0; + + for (int round = 0; round < 64; ++round) { + count = 0; + metric[0] = 0; + for (int k = 1; k < TYPE::SIZE; ++k) + metric[k] = 1000000; + for (int i = 0; i < length; ++i) + soft[length+i] = vdup(codeword[i]); + state[0] = round << 1; + for (int i = 1; i < TYPE::SIZE; ++i) + state[i] = 0; + + switch (level) { + case 5: PACListTree::decode(metric, message, maps, &count, state, hard, soft, rank_map, frozen); break; + case 6: PACListTree::decode(metric, message, maps, &count, state, hard, soft, rank_map, frozen); break; + case 7: PACListTree::decode(metric, message, maps, &count, state, hard, soft, rank_map, frozen); break; + case 8: PACListTree::decode(metric, message, maps, &count, state, hard, soft, rank_map, frozen); break; + default: assert(false); + } + + for (int i = 0; i < TYPE::SIZE; ++i) { + if (round == ((state[i] & 126) >> 1) && metric[i] < best_metric) { + best_metric = metric[i]; + best_round = round; + } + } + } + + count = 0; metric[0] = 0; for (int k = 1; k < TYPE::SIZE; ++k) metric[k] = 1000000; - int length = 1 << level; for (int i = 0; i < length; ++i) soft[length+i] = vdup(codeword[i]); - int state[TYPE::SIZE]; - for (int i = 0; i < TYPE::SIZE; ++i) + state[0] = best_round << 1; + for (int i = 1; i < TYPE::SIZE; ++i) state[i] = 0; - int frozen = length - mesg_bits; switch (level) { case 5: PACListTree::decode(metric, message, maps, &count, state, hard, soft, rank_map, frozen); break; @@ -151,13 +187,21 @@ public: case 8: PACListTree::decode(metric, message, maps, &count, state, hard, soft, rank_map, frozen); break; default: assert(false); } - + for (int i = 0; i < TYPE::SIZE; ++i) + if (best_round != ((state[i] & 126) >> 1)) + metric[i] = 1000000; + int perm[TYPE::SIZE]; + CODE::insertion_sort(perm, metric, TYPE::SIZE); for (int i = 0, r = 0; rank != nullptr && i < TYPE::SIZE; ++i) { if (i > 0 && metric[i-1] != metric[i]) ++r; rank[i] = r; } - MAP acc = maps[count-1]; + MAP acc; + for (int k = 0; k < TYPE::SIZE; ++k) + acc.v[k] = perm[k]; + message[count-1] = vshuf(message[count-1], acc); + acc = vshuf(maps[count-1], acc); for (int i = count-2; i >= 0; --i) { message[i] = vshuf(message[i], acc); acc = vshuf(maps[i], acc); diff --git a/tests/pac_list_regression_test.cc b/tests/pac_list_regression_test.cc index 5f6fac0..f831156 100644 --- a/tests/pac_list_regression_test.cc +++ b/tests/pac_list_regression_test.cc @@ -30,10 +30,10 @@ int main() const int C = 16; int K = R * N + crc_aided * C; #if 1 - const int L = 64; + const int L = 16; typedef int8_t code_type; #else - const int L = 16; + const int L = 4; typedef float code_type; #endif