/* Successive cancellation decoding of polar codes Copyright 2020 Ahmet Inan */ #pragma once #include #include "polar_helper.hh" namespace CODE { template struct PolarNode { typedef PolarHelper PH; static const int N = 1 << M; static void rate0(TYPE *hard) { for (int i = 0; i < N; ++i) hard[i] = PH::one(); } }; template struct PolarTree { typedef PolarHelper PH; static const int N = 1 << M; static void decode(TYPE **message, 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]); PolarTree::decode(message, hard, soft, frozen); for (int i = 0; i < N/2; ++i) soft[i+N/2] = PH::madd(hard[i], soft[i+N], soft[i+N/2+N]); PolarTree::decode(message, hard+N/2, soft, frozen+N/2/32); for (int i = 0; i < N/2; ++i) hard[i] = PH::qmul(hard[i], hard[i+N/2]); } }; template struct PolarTree { typedef PolarHelper PH; static const int M = 6; static const int N = 1 << M; static void decode(TYPE **message, 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]); if (frozen[0] == 0xffffffff) PolarNode::rate0(hard); else PolarTree::decode(message, hard, soft, frozen[0]); for (int i = 0; i < N/2; ++i) soft[i+N/2] = PH::madd(hard[i], soft[i+N], soft[i+N/2+N]); if (frozen[1] == 0xffffffff) PolarNode::rate0(hard+N/2); else PolarTree::decode(message, hard+N/2, soft, frozen[1]); for (int i = 0; i < N/2; ++i) hard[i] = PH::qmul(hard[i], hard[i+N/2]); } }; template struct PolarTree { typedef PolarHelper PH; static const int M = 5; static const int N = 1 << M; static void decode(TYPE **message, 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]); if ((frozen & ((1<<(1<<(M-1)))-1)) == ((1<<(1<<(M-1)))-1)) PolarNode::rate0(hard); else PolarTree::decode(message, hard, soft, frozen & ((1<<(1<<(M-1)))-1)); for (int i = 0; i < N/2; ++i) soft[i+N/2] = PH::madd(hard[i], soft[i+N], soft[i+N/2+N]); if (frozen >> (N/2) == ((1<<(1<<(M-1)))-1)) PolarNode::rate0(hard+N/2); else PolarTree::decode(message, hard+N/2, soft, frozen >> (N/2)); for (int i = 0; i < N/2; ++i) hard[i] = PH::qmul(hard[i], hard[i+N/2]); } }; template struct PolarTree { typedef PolarHelper PH; static const int M = 4; static const int N = 1 << M; static void decode(TYPE **message, 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]); if ((frozen & ((1<<(1<<(M-1)))-1)) == ((1<<(1<<(M-1)))-1)) PolarNode::rate0(hard); else PolarTree::decode(message, hard, soft, frozen & ((1<<(1<<(M-1)))-1)); for (int i = 0; i < N/2; ++i) soft[i+N/2] = PH::madd(hard[i], soft[i+N], soft[i+N/2+N]); if (frozen >> (N/2) == ((1<<(1<<(M-1)))-1)) PolarNode::rate0(hard+N/2); else PolarTree::decode(message, hard+N/2, soft, frozen >> (N/2)); for (int i = 0; i < N/2; ++i) hard[i] = PH::qmul(hard[i], hard[i+N/2]); } }; template struct PolarTree { typedef PolarHelper PH; static const int M = 3; static const int N = 1 << M; static void decode(TYPE **message, 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]); if ((frozen & ((1<<(1<<(M-1)))-1)) == ((1<<(1<<(M-1)))-1)) PolarNode::rate0(hard); else PolarTree::decode(message, hard, soft, frozen & ((1<<(1<<(M-1)))-1)); for (int i = 0; i < N/2; ++i) soft[i+N/2] = PH::madd(hard[i], soft[i+N], soft[i+N/2+N]); if (frozen >> (N/2) == ((1<<(1<<(M-1)))-1)) PolarNode::rate0(hard+N/2); else PolarTree::decode(message, hard+N/2, soft, frozen >> (N/2)); for (int i = 0; i < N/2; ++i) hard[i] = PH::qmul(hard[i], hard[i+N/2]); } }; template struct PolarTree { typedef PolarHelper PH; static const int M = 2; static const int N = 1 << M; static void decode(TYPE **message, 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]); if ((frozen & ((1<<(1<<(M-1)))-1)) == ((1<<(1<<(M-1)))-1)) PolarNode::rate0(hard); else PolarTree::decode(message, hard, soft, frozen & ((1<<(1<<(M-1)))-1)); for (int i = 0; i < N/2; ++i) soft[i+N/2] = PH::madd(hard[i], soft[i+N], soft[i+N/2+N]); if (frozen >> (N/2) == ((1<<(1<<(M-1)))-1)) PolarNode::rate0(hard+N/2); else PolarTree::decode(message, hard+N/2, soft, frozen >> (N/2)); for (int i = 0; i < N/2; ++i) hard[i] = PH::qmul(hard[i], hard[i+N/2]); } }; template struct PolarTree { typedef PolarHelper PH; static void decode(TYPE **message, TYPE *hard, TYPE *soft, uint32_t frozen) { soft[1] = PH::prod(soft[2], soft[3]); if (frozen & 1) PolarNode::rate0(hard); else PolarTree::decode(message, hard, soft, 0); soft[1] = PH::madd(hard[0], soft[2], soft[3]); if (frozen >> 1) PolarNode::rate0(hard+1); else PolarTree::decode(message, hard+1, soft, 0); hard[0] = PH::qmul(hard[0], hard[1]); } }; template struct PolarTree { typedef PolarHelper PH; static void decode(TYPE **message, TYPE *hard, TYPE *soft, uint32_t frozen) { if (frozen) { *hard = PH::one(); } else { *hard = PH::signum(soft[1]); *(*message)++ = *hard; } } }; template class PolarDecoder { static_assert(MAX_M >= 5 && MAX_M <= 29); typedef PolarHelper PH; static const int MAX_N = 1 << MAX_M; TYPE soft[2*MAX_N]; TYPE hard[MAX_N]; public: void operator()(TYPE *message, const TYPE *codeword, const uint32_t *frozen, int level) { assert(level <= MAX_M); int length = 1 << level; for (int i = 0; i < length; ++i) soft[length+i] = codeword[i]; switch (level) { case 5: PolarTree::decode(&message, hard, soft, *frozen); break; case 6: PolarTree::decode(&message, hard, soft, frozen); break; case 7: PolarTree::decode(&message, hard, soft, frozen); break; case 8: PolarTree::decode(&message, hard, soft, frozen); break; case 9: PolarTree::decode(&message, hard, soft, frozen); break; case 10: PolarTree::decode(&message, hard, soft, frozen); break; case 11: PolarTree::decode(&message, hard, soft, frozen); break; case 12: PolarTree::decode(&message, hard, soft, frozen); break; case 13: PolarTree::decode(&message, hard, soft, frozen); break; case 14: PolarTree::decode(&message, hard, soft, frozen); break; case 15: PolarTree::decode(&message, hard, soft, frozen); break; case 16: PolarTree::decode(&message, hard, soft, frozen); break; case 17: PolarTree::decode(&message, hard, soft, frozen); break; case 18: PolarTree::decode(&message, hard, soft, frozen); break; case 19: PolarTree::decode(&message, hard, soft, frozen); break; case 20: PolarTree::decode(&message, hard, soft, frozen); break; case 21: PolarTree::decode(&message, hard, soft, frozen); break; case 22: PolarTree::decode(&message, hard, soft, frozen); break; case 23: PolarTree::decode(&message, hard, soft, frozen); break; case 24: PolarTree::decode(&message, hard, soft, frozen); break; case 25: PolarTree::decode(&message, hard, soft, frozen); break; case 26: PolarTree::decode(&message, hard, soft, frozen); break; case 27: PolarTree::decode(&message, hard, soft, frozen); break; case 28: PolarTree::decode(&message, hard, soft, frozen); break; case 29: PolarTree::decode(&message, hard, soft, frozen); break; default: assert(false); } } }; }