diff --git a/pac_encoder.hh b/pac_encoder.hh index b358391..a9b0594 100644 --- a/pac_encoder.hh +++ b/pac_encoder.hh @@ -18,13 +18,22 @@ class PACEncoder { return (bits[idx/32] >> (idx%32)) & 1; } + static bool conv(int *state, bool input) + { + bool s1 = *state & 1; + bool s2 = *state & 2; + bool output = input ^ s1 ^ s2; + *state = (s1 << 1) | output; + return output; + } public: void operator()(TYPE *codeword, const TYPE *message, const uint32_t *frozen, int level) { int length = 1 << level; + int state = 0; for (int i = 0; i < length; i += 2) { - TYPE msg0 = get(frozen, i) ? PH::one() : *message++; - TYPE msg1 = get(frozen, i+1) ? PH::one() : *message++; + TYPE msg0 = get(frozen, i) ? PH::one() : 1 - 2 * conv(&state, *message++ < 0); + TYPE msg1 = get(frozen, i+1) ? PH::one() : 1 - 2 * conv(&state, *message++ < 0); codeword[i] = PH::qmul(msg0, msg1); codeword[i+1] = msg1; } diff --git a/pac_list_decoder.hh b/pac_list_decoder.hh index 29b3720..3630120 100644 --- a/pac_list_decoder.hh +++ b/pac_list_decoder.hh @@ -39,6 +39,14 @@ struct PACListNode typedef PolarHelper PH; typedef typename PH::PATH PATH; typedef typename PH::MAP MAP; + static bool conv(int *state, bool input) + { + bool s1 = *state & 1; + bool s2 = *state & 2; + bool output = input ^ s1 ^ s2; + *state = (s1 << 1) | output; + return output; + } static MAP rate0(PATH *metric, TYPE *hard, TYPE *soft) { *hard = PH::one(); @@ -50,28 +58,34 @@ struct PACListNode map.v[k] = k; return map; } - static MAP rate1(PATH *metric, TYPE *message, MAP *maps, int *count, TYPE *hard, TYPE *soft) + static MAP rate1(PATH *metric, TYPE *message, MAP *maps, int *count, int *state, TYPE *hard, TYPE *soft) { TYPE sft = soft[1]; - PATH fork[2*TYPE::SIZE]; + PATH mfork[2*TYPE::SIZE]; for (int k = 0; k < TYPE::SIZE; ++k) - fork[2*k] = fork[2*k+1] = metric[k]; + mfork[2*k] = mfork[2*k+1] = metric[k]; + int sfork[2*TYPE::SIZE]; for (int k = 0; k < TYPE::SIZE; ++k) - if (sft.v[k] < 0) - fork[2*k] -= sft.v[k]; - else - fork[2*k+1] += sft.v[k]; + sfork[2*k] = sfork[2*k+1] = state[k]; + for (int k = 0; k < 2*TYPE::SIZE; ++k) + if (conv(sfork+k, k&1) != sft.v[k>>1] < 0) + mfork[k] += std::abs(sft.v[k>>1]); int perm[2*TYPE::SIZE]; - CODE::insertion_sort(perm, fork, 2*TYPE::SIZE); + CODE::insertion_sort(perm, mfork, 2*TYPE::SIZE); for (int k = 0; k < TYPE::SIZE; ++k) - metric[k] = fork[k]; + metric[k] = mfork[k]; MAP map; for (int k = 0; k < TYPE::SIZE; ++k) map.v[k] = perm[k] >> 1; + TYPE msg; + for (int k = 0; k < TYPE::SIZE; ++k) + msg.v[k] = 1 - 2 * (perm[k] & 1); + for (int k = 0; k < TYPE::SIZE; ++k) + state[k] = sfork[perm[k]]; TYPE hrd; for (int k = 0; k < TYPE::SIZE; ++k) - hrd.v[k] = 1 - 2 * (perm[k] & 1); - message[*count] = hrd; + hrd.v[k] = 1 - 2 * (state[k] & 1); + message[*count] = msg; maps[*count] = map; ++*count; *hard = hrd; @@ -86,14 +100,14 @@ struct PACListTree typedef typename PH::PATH PATH; typedef typename PH::MAP MAP; static const int N = 1 << M; - static MAP decode(PATH *metric, TYPE *message, MAP *maps, int *count, TYPE *hard, TYPE *soft, const uint32_t *frozen) + static MAP decode(PATH *metric, TYPE *message, MAP *maps, int *count, int *state, TYPE *hard, TYPE *soft, const uint32_t *frozen) { for (int i = 0; i < N/2; ++i) soft[i+N/2] = PH::prod(soft[i+N], soft[i+N/2+N]); - MAP lmap = PACListTree::decode(metric, message, maps, count, hard, soft, frozen); + MAP lmap = PACListTree::decode(metric, message, maps, count, state, hard, soft, frozen); for (int i = 0; i < N/2; ++i) soft[i+N/2] = PH::madd(hard[i], vshuf(soft[i+N], lmap), vshuf(soft[i+N/2+N], lmap)); - MAP rmap = PACListTree::decode(metric, message, maps, count, hard+N/2, soft, frozen+N/2/32); + MAP rmap = PACListTree::decode(metric, message, maps, count, state, hard+N/2, soft, frozen+N/2/32); for (int i = 0; i < N/2; ++i) hard[i] = PH::qmul(vshuf(hard[i], rmap), hard[i+N/2]); return vshuf(lmap, rmap); @@ -108,7 +122,7 @@ struct PACListTree typedef typename PH::MAP MAP; static const int M = 6; static const int N = 1 << M; - static MAP decode(PATH *metric, TYPE *message, MAP *maps, int *count, TYPE *hard, TYPE *soft, const uint32_t *frozen) + static MAP decode(PATH *metric, TYPE *message, MAP *maps, int *count, int *state, TYPE *hard, TYPE *soft, const uint32_t *frozen) { for (int i = 0; i < N/2; ++i) soft[i+N/2] = PH::prod(soft[i+N], soft[i+N/2+N]); @@ -116,13 +130,13 @@ struct PACListTree if (frozen[0] == 0xffffffff) lmap = PACListNode::rate0(metric, hard, soft); else - lmap = PACListTree::decode(metric, message, maps, count, hard, soft, frozen[0]); + lmap = PACListTree::decode(metric, message, maps, count, state, hard, soft, frozen[0]); for (int i = 0; i < N/2; ++i) soft[i+N/2] = PH::madd(hard[i], vshuf(soft[i+N], lmap), vshuf(soft[i+N/2+N], lmap)); if (frozen[1] == 0xffffffff) rmap = PACListNode::rate0(metric, hard+N/2, soft); else - rmap = PACListTree::decode(metric, message, maps, count, hard+N/2, soft, frozen[1]); + rmap = PACListTree::decode(metric, message, maps, count, state, hard+N/2, soft, frozen[1]); for (int i = 0; i < N/2; ++i) hard[i] = PH::qmul(vshuf(hard[i], rmap), hard[i+N/2]); return vshuf(lmap, rmap); @@ -137,7 +151,7 @@ struct PACListTree typedef typename PH::MAP MAP; static const int M = 5; static const int N = 1 << M; - static MAP decode(PATH *metric, TYPE *message, MAP *maps, int *count, TYPE *hard, TYPE *soft, uint32_t frozen) + static MAP decode(PATH *metric, TYPE *message, MAP *maps, int *count, int *state, TYPE *hard, TYPE *soft, uint32_t frozen) { for (int i = 0; i < N/2; ++i) soft[i+N/2] = PH::prod(soft[i+N], soft[i+N/2+N]); @@ -145,13 +159,13 @@ struct PACListTree if ((frozen & ((1<<(1<<(M-1)))-1)) == ((1<<(1<<(M-1)))-1)) lmap = PACListNode::rate0(metric, hard, soft); else - lmap = PACListTree::decode(metric, message, maps, count, hard, soft, frozen & ((1<<(1<<(M-1)))-1)); + lmap = PACListTree::decode(metric, message, maps, count, state, hard, soft, frozen & ((1<<(1<<(M-1)))-1)); for (int i = 0; i < N/2; ++i) soft[i+N/2] = PH::madd(hard[i], vshuf(soft[i+N], lmap), vshuf(soft[i+N/2+N], lmap)); if (frozen >> (N/2) == ((1<<(1<<(M-1)))-1)) rmap = PACListNode::rate0(metric, hard+N/2, soft); else - rmap = PACListTree::decode(metric, message, maps, count, hard+N/2, soft, frozen >> (N/2)); + rmap = PACListTree::decode(metric, message, maps, count, state, hard+N/2, soft, frozen >> (N/2)); for (int i = 0; i < N/2; ++i) hard[i] = PH::qmul(vshuf(hard[i], rmap), hard[i+N/2]); return vshuf(lmap, rmap); @@ -166,7 +180,7 @@ struct PACListTree typedef typename PH::MAP MAP; static const int M = 4; static const int N = 1 << M; - static MAP decode(PATH *metric, TYPE *message, MAP *maps, int *count, TYPE *hard, TYPE *soft, uint32_t frozen) + static MAP decode(PATH *metric, TYPE *message, MAP *maps, int *count, int *state, TYPE *hard, TYPE *soft, uint32_t frozen) { for (int i = 0; i < N/2; ++i) soft[i+N/2] = PH::prod(soft[i+N], soft[i+N/2+N]); @@ -174,13 +188,13 @@ struct PACListTree if ((frozen & ((1<<(1<<(M-1)))-1)) == ((1<<(1<<(M-1)))-1)) lmap = PACListNode::rate0(metric, hard, soft); else - lmap = PACListTree::decode(metric, message, maps, count, hard, soft, frozen & ((1<<(1<<(M-1)))-1)); + lmap = PACListTree::decode(metric, message, maps, count, state, hard, soft, frozen & ((1<<(1<<(M-1)))-1)); for (int i = 0; i < N/2; ++i) soft[i+N/2] = PH::madd(hard[i], vshuf(soft[i+N], lmap), vshuf(soft[i+N/2+N], lmap)); if (frozen >> (N/2) == ((1<<(1<<(M-1)))-1)) rmap = PACListNode::rate0(metric, hard+N/2, soft); else - rmap = PACListTree::decode(metric, message, maps, count, hard+N/2, soft, frozen >> (N/2)); + rmap = PACListTree::decode(metric, message, maps, count, state, hard+N/2, soft, frozen >> (N/2)); for (int i = 0; i < N/2; ++i) hard[i] = PH::qmul(vshuf(hard[i], rmap), hard[i+N/2]); return vshuf(lmap, rmap); @@ -195,7 +209,7 @@ struct PACListTree typedef typename PH::MAP MAP; static const int M = 3; static const int N = 1 << M; - static MAP decode(PATH *metric, TYPE *message, MAP *maps, int *count, TYPE *hard, TYPE *soft, uint32_t frozen) + static MAP decode(PATH *metric, TYPE *message, MAP *maps, int *count, int *state, TYPE *hard, TYPE *soft, uint32_t frozen) { for (int i = 0; i < N/2; ++i) soft[i+N/2] = PH::prod(soft[i+N], soft[i+N/2+N]); @@ -203,13 +217,13 @@ struct PACListTree if ((frozen & ((1<<(1<<(M-1)))-1)) == ((1<<(1<<(M-1)))-1)) lmap = PACListNode::rate0(metric, hard, soft); else - lmap = PACListTree::decode(metric, message, maps, count, hard, soft, frozen & ((1<<(1<<(M-1)))-1)); + lmap = PACListTree::decode(metric, message, maps, count, state, hard, soft, frozen & ((1<<(1<<(M-1)))-1)); for (int i = 0; i < N/2; ++i) soft[i+N/2] = PH::madd(hard[i], vshuf(soft[i+N], lmap), vshuf(soft[i+N/2+N], lmap)); if (frozen >> (N/2) == ((1<<(1<<(M-1)))-1)) rmap = PACListNode::rate0(metric, hard+N/2, soft); else - rmap = PACListTree::decode(metric, message, maps, count, hard+N/2, soft, frozen >> (N/2)); + rmap = PACListTree::decode(metric, message, maps, count, state, hard+N/2, soft, frozen >> (N/2)); for (int i = 0; i < N/2; ++i) hard[i] = PH::qmul(vshuf(hard[i], rmap), hard[i+N/2]); return vshuf(lmap, rmap); @@ -224,7 +238,7 @@ struct PACListTree typedef typename PH::MAP MAP; static const int M = 2; static const int N = 1 << M; - static MAP decode(PATH *metric, TYPE *message, MAP *maps, int *count, TYPE *hard, TYPE *soft, uint32_t frozen) + static MAP decode(PATH *metric, TYPE *message, MAP *maps, int *count, int *state, TYPE *hard, TYPE *soft, uint32_t frozen) { for (int i = 0; i < N/2; ++i) soft[i+N/2] = PH::prod(soft[i+N], soft[i+N/2+N]); @@ -232,13 +246,13 @@ struct PACListTree if ((frozen & ((1<<(1<<(M-1)))-1)) == ((1<<(1<<(M-1)))-1)) lmap = PACListNode::rate0(metric, hard, soft); else - lmap = PACListTree::decode(metric, message, maps, count, hard, soft, frozen & ((1<<(1<<(M-1)))-1)); + lmap = PACListTree::decode(metric, message, maps, count, state, hard, soft, frozen & ((1<<(1<<(M-1)))-1)); for (int i = 0; i < N/2; ++i) soft[i+N/2] = PH::madd(hard[i], vshuf(soft[i+N], lmap), vshuf(soft[i+N/2+N], lmap)); if (frozen >> (N/2) == ((1<<(1<<(M-1)))-1)) rmap = PACListNode::rate0(metric, hard+N/2, soft); else - rmap = PACListTree::decode(metric, message, maps, count, hard+N/2, soft, frozen >> (N/2)); + rmap = PACListTree::decode(metric, message, maps, count, state, hard+N/2, soft, frozen >> (N/2)); for (int i = 0; i < N/2; ++i) hard[i] = PH::qmul(vshuf(hard[i], rmap), hard[i+N/2]); return vshuf(lmap, rmap); @@ -251,19 +265,19 @@ struct PACListTree typedef PolarHelper PH; typedef typename PH::PATH PATH; typedef typename PH::MAP MAP; - static MAP decode(PATH *metric, TYPE *message, MAP *maps, int *count, TYPE *hard, TYPE *soft, uint32_t frozen) + static MAP decode(PATH *metric, TYPE *message, MAP *maps, int *count, int *state, TYPE *hard, TYPE *soft, uint32_t frozen) { soft[1] = PH::prod(soft[2], soft[3]); MAP lmap, rmap; if (frozen & 1) lmap = PACListNode::rate0(metric, hard, soft); else - lmap = PACListNode::rate1(metric, message, maps, count, hard, soft); + lmap = PACListNode::rate1(metric, message, maps, count, state, hard, soft); soft[1] = PH::madd(hard[0], vshuf(soft[2], lmap), vshuf(soft[3], lmap)); if (frozen >> 1) rmap = PACListNode::rate0(metric, hard+1, soft); else - rmap = PACListNode::rate1(metric, message, maps, count, hard+1, soft); + rmap = PACListNode::rate1(metric, message, maps, count, state, hard+1, soft); hard[0] = PH::qmul(vshuf(hard[0], rmap), hard[1]); return vshuf(lmap, rmap); } @@ -293,20 +307,23 @@ public: 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[i] = 0; switch (level) { - case 5: PACListTree::decode(metric, message, maps, &count, hard, soft, *frozen); break; - case 6: PACListTree::decode(metric, message, maps, &count, hard, soft, frozen); break; - case 7: PACListTree::decode(metric, message, maps, &count, hard, soft, frozen); break; - case 8: PACListTree::decode(metric, message, maps, &count, hard, soft, frozen); break; - case 9: PACListTree::decode(metric, message, maps, &count, hard, soft, frozen); break; - case 10: PACListTree::decode(metric, message, maps, &count, hard, soft, frozen); break; - case 11: PACListTree::decode(metric, message, maps, &count, hard, soft, frozen); break; - case 12: PACListTree::decode(metric, message, maps, &count, hard, soft, frozen); break; - case 13: PACListTree::decode(metric, message, maps, &count, hard, soft, frozen); break; - case 14: PACListTree::decode(metric, message, maps, &count, hard, soft, frozen); break; - case 15: PACListTree::decode(metric, message, maps, &count, hard, soft, frozen); break; - case 16: PACListTree::decode(metric, message, maps, &count, hard, soft, frozen); break; + case 5: PACListTree::decode(metric, message, maps, &count, state, hard, soft, *frozen); break; + case 6: PACListTree::decode(metric, message, maps, &count, state, hard, soft, frozen); break; + case 7: PACListTree::decode(metric, message, maps, &count, state, hard, soft, frozen); break; + case 8: PACListTree::decode(metric, message, maps, &count, state, hard, soft, frozen); break; + case 9: PACListTree::decode(metric, message, maps, &count, state, hard, soft, frozen); break; + case 10: PACListTree::decode(metric, message, maps, &count, state, hard, soft, frozen); break; + case 11: PACListTree::decode(metric, message, maps, &count, state, hard, soft, frozen); break; + case 12: PACListTree::decode(metric, message, maps, &count, state, hard, soft, frozen); break; + case 13: PACListTree::decode(metric, message, maps, &count, state, hard, soft, frozen); break; + case 14: PACListTree::decode(metric, message, maps, &count, state, hard, soft, frozen); break; + case 15: PACListTree::decode(metric, message, maps, &count, state, hard, soft, frozen); break; + case 16: PACListTree::decode(metric, message, maps, &count, state, hard, soft, frozen); break; default: assert(false); }