mirror of
https://github.com/aicodix/code.git
synced 2026-04-27 14:30:36 +00:00
Compare commits
1 commit
master
...
reliabilit
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed4fe54ee9 |
1 changed files with 35 additions and 80 deletions
|
|
@ -15,7 +15,6 @@ Copyright 2020 Ahmet Inan <inan@aicodix.de>
|
||||||
#include "polar_helper.hh"
|
#include "polar_helper.hh"
|
||||||
#include "polar_decoder.hh"
|
#include "polar_decoder.hh"
|
||||||
#include "polar_encoder.hh"
|
#include "polar_encoder.hh"
|
||||||
#include "polar_freezer.hh"
|
|
||||||
#include "polar_sequence.hh"
|
#include "polar_sequence.hh"
|
||||||
|
|
||||||
bool get_bit(const uint32_t *bits, int idx)
|
bool get_bit(const uint32_t *bits, int idx)
|
||||||
|
|
@ -27,8 +26,8 @@ int main()
|
||||||
{
|
{
|
||||||
const int M = 20;
|
const int M = 20;
|
||||||
const int N = 1 << M;
|
const int N = 1 << M;
|
||||||
const bool systematic = true;
|
const bool systematic = false;
|
||||||
#if 1
|
#if 0
|
||||||
typedef int8_t code_type;
|
typedef int8_t code_type;
|
||||||
double SCALE = 2;
|
double SCALE = 2;
|
||||||
#else
|
#else
|
||||||
|
|
@ -44,29 +43,35 @@ int main()
|
||||||
auto codeword = new code_type[N];
|
auto codeword = new code_type[N];
|
||||||
auto temp = new code_type[N];
|
auto temp = new code_type[N];
|
||||||
|
|
||||||
double erasure_probability = 1. / 3.;
|
double erasure_probability = 1. / 2.;
|
||||||
int K = (1 - erasure_probability) * N;
|
int K = (1 - erasure_probability) * N;
|
||||||
double design_SNR = 10 * std::log10(-std::log(erasure_probability));
|
double design_SNR = 10 * std::log10(-std::log(erasure_probability));
|
||||||
std::cerr << "design SNR: " << design_SNR << std::endl;
|
std::cerr << "design SNR: " << design_SNR << std::endl;
|
||||||
double better_SNR = design_SNR + 0.5;//1.59175;
|
double better_SNR = design_SNR + 0.5;//1.59175;
|
||||||
std::cerr << "better SNR: " << better_SNR << std::endl;
|
std::cerr << "better SNR: " << better_SNR << std::endl;
|
||||||
double probability = std::exp(-pow(10.0, better_SNR / 10));
|
double probability = std::exp(-pow(10.0, better_SNR / 10));
|
||||||
if (1) {
|
auto sequence = new int[N];
|
||||||
auto freeze = new CODE::PolarCodeConst0<M>;
|
auto construct = new CODE::PolarSeqConst0<M>;
|
||||||
std::cerr << "sizeof(PolarCodeConst0<M>) = " << sizeof(CODE::PolarCodeConst0<M>) << std::endl;
|
std::cerr << "sizeof(PolarSeqConst0<M>) = " << sizeof(CODE::PolarSeqConst0<M>) << std::endl;
|
||||||
(*freeze)(frozen, M, K, probability);
|
(*construct)(sequence, M, probability);
|
||||||
delete freeze;
|
delete construct;
|
||||||
|
for (int i = 0; i < N / 32; ++i)
|
||||||
|
frozen[i] = 0;
|
||||||
|
for (int i = 0; i < N - K; ++i)
|
||||||
|
frozen[sequence[i]/32] |= 1 << (sequence[i]%32);
|
||||||
|
const int segments = 4;
|
||||||
|
auto segment_mapping = new char[N];
|
||||||
|
for (int i = 0; i < N; ++i)
|
||||||
|
segment_mapping[i] = -1;
|
||||||
|
if (0) {
|
||||||
|
for (int i = 0; i < K; ++i)
|
||||||
|
segment_mapping[sequence[N-1-i]] = std::min(i / (K / segments), segments - 1);
|
||||||
|
for (int i = 0, j = 0; i < N; ++i)
|
||||||
|
if (segment_mapping[i] >= 0)
|
||||||
|
segment_mapping[j++] = segment_mapping[i];
|
||||||
} else {
|
} else {
|
||||||
auto sequence = new int[N];
|
for (int i = 0; i < K; ++i)
|
||||||
auto construct = new CODE::PolarSeqConst0<M>;
|
segment_mapping[i] = std::min(i / (K / segments), segments - 1);
|
||||||
std::cerr << "sizeof(PolarSeqConst0<M>) = " << sizeof(CODE::PolarSeqConst0<M>) << std::endl;
|
|
||||||
(*construct)(sequence, M, probability);
|
|
||||||
delete construct;
|
|
||||||
for (int i = 0; i < N / 32; ++i)
|
|
||||||
frozen[i] = 0;
|
|
||||||
for (int i = 0; i < N - K; ++i)
|
|
||||||
frozen[sequence[i]/32] |= 1 << (sequence[i]%32);
|
|
||||||
delete[] sequence;
|
|
||||||
}
|
}
|
||||||
std::cerr << "Polar(" << N << ", " << K << ")" << std::endl;
|
std::cerr << "Polar(" << N << ", " << K << ")" << std::endl;
|
||||||
auto message = new code_type[K];
|
auto message = new code_type[K];
|
||||||
|
|
@ -74,15 +79,10 @@ int main()
|
||||||
std::cerr << "sizeof(PolarDecoder<code_type, M>) = " << sizeof(CODE::PolarDecoder<code_type, M>) << std::endl;
|
std::cerr << "sizeof(PolarDecoder<code_type, M>) = " << sizeof(CODE::PolarDecoder<code_type, M>) << std::endl;
|
||||||
auto decode = new CODE::PolarDecoder<code_type, M>;
|
auto decode = new CODE::PolarDecoder<code_type, M>;
|
||||||
|
|
||||||
auto orig = new code_type[N];
|
|
||||||
auto noisy = new code_type[N];
|
|
||||||
auto symb = new double[N];
|
auto symb = new double[N];
|
||||||
double low_SNR = std::floor(design_SNR-3);
|
double low_SNR = std::floor(design_SNR-3);
|
||||||
double high_SNR = std::ceil(design_SNR+5);
|
double high_SNR = std::ceil(design_SNR+.5);
|
||||||
double min_SNR = high_SNR, max_mbs = 0;
|
for (double SNR = low_SNR; SNR <= high_SNR; SNR += 0.1) {
|
||||||
int count = 0;
|
|
||||||
std::cerr << "SNR BER Mbit/s Eb/N0" << std::endl;
|
|
||||||
for (double SNR = low_SNR; count <= 3 && SNR <= high_SNR; SNR += 0.1, ++count) {
|
|
||||||
//double mean_signal = 0;
|
//double mean_signal = 0;
|
||||||
double sigma_signal = 1;
|
double sigma_signal = 1;
|
||||||
double mean_noise = 0;
|
double mean_noise = 0;
|
||||||
|
|
@ -91,13 +91,9 @@ int main()
|
||||||
typedef std::normal_distribution<double> normal;
|
typedef std::normal_distribution<double> normal;
|
||||||
auto awgn = std::bind(normal(mean_noise, sigma_noise), generator(rd()));
|
auto awgn = std::bind(normal(mean_noise, sigma_noise), generator(rd()));
|
||||||
|
|
||||||
int64_t awgn_errors = 0;
|
int64_t segment_errors[segments] = { 0 };
|
||||||
int64_t quantization_erasures = 0;
|
|
||||||
int64_t uncorrected_errors = 0;
|
|
||||||
int64_t ambiguity_erasures = 0;
|
|
||||||
double avg_mbs = 0;
|
|
||||||
int64_t loops = 0;
|
int64_t loops = 0;
|
||||||
while (uncorrected_errors < 1000 && ++loops < 100) {
|
while (segment_errors[0] < 100000 && ++loops < 10000) {
|
||||||
for (int i = 0; i < K; ++i)
|
for (int i = 0; i < K; ++i)
|
||||||
message[i] = 1 - 2 * data();
|
message[i] = 1 - 2 * data();
|
||||||
|
|
||||||
|
|
@ -112,9 +108,6 @@ int main()
|
||||||
encode(codeword, message, frozen, M);
|
encode(codeword, message, frozen, M);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < N; ++i)
|
|
||||||
orig[i] = codeword[i];
|
|
||||||
|
|
||||||
for (int i = 0; i < N; ++i)
|
for (int i = 0; i < N; ++i)
|
||||||
symb[i] = codeword[i];
|
symb[i] = codeword[i];
|
||||||
|
|
||||||
|
|
@ -128,15 +121,7 @@ int main()
|
||||||
for (int i = 0; i < N; ++i)
|
for (int i = 0; i < N; ++i)
|
||||||
codeword[i] = CODE::PolarHelper<code_type>::quant(fact * symb[i]);
|
codeword[i] = CODE::PolarHelper<code_type>::quant(fact * symb[i]);
|
||||||
|
|
||||||
for (int i = 0; i < N; ++i)
|
|
||||||
noisy[i] = codeword[i];
|
|
||||||
|
|
||||||
auto start = std::chrono::system_clock::now();
|
|
||||||
(*decode)(decoded, codeword, frozen, M);
|
(*decode)(decoded, codeword, frozen, M);
|
||||||
auto end = std::chrono::system_clock::now();
|
|
||||||
auto usec = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
|
|
||||||
double mbs = (double)K / usec.count();
|
|
||||||
avg_mbs += mbs;
|
|
||||||
|
|
||||||
if (systematic) {
|
if (systematic) {
|
||||||
CODE::PolarEncoder<code_type> encode;
|
CODE::PolarEncoder<code_type> encode;
|
||||||
|
|
@ -146,46 +131,16 @@ int main()
|
||||||
decoded[j++] = temp[i];
|
decoded[j++] = temp[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < N; ++i)
|
|
||||||
awgn_errors += noisy[i] * (orig[i] < 0);
|
|
||||||
for (int i = 0; i < N; ++i)
|
|
||||||
quantization_erasures += !noisy[i];
|
|
||||||
for (int i = 0; i < K; ++i)
|
for (int i = 0; i < K; ++i)
|
||||||
uncorrected_errors += decoded[i] * message[i] <= 0;
|
segment_errors[(int)segment_mapping[i]] += decoded[i] * message[i] <= 0;
|
||||||
for (int i = 0; i < K; ++i)
|
|
||||||
ambiguity_erasures += !decoded[i];
|
|
||||||
}
|
}
|
||||||
|
for (int i = 0; i < segments - 1; ++i)
|
||||||
|
segment_errors[i + 1] += segment_errors[i];
|
||||||
|
|
||||||
avg_mbs /= loops;
|
std::cout << SNR;
|
||||||
|
for (int i = 0; i < segments; ++i)
|
||||||
max_mbs = std::max(max_mbs, avg_mbs);
|
std::cout << " " << double(segments * segment_errors[i]) / double(K * loops * (i + 1));
|
||||||
double bit_error_rate = (double)uncorrected_errors / (double)(K * loops);
|
std::cout << std::endl;
|
||||||
if (!uncorrected_errors)
|
|
||||||
min_SNR = std::min(min_SNR, SNR);
|
|
||||||
else
|
|
||||||
count = 0;
|
|
||||||
|
|
||||||
int MOD_BITS = 1; // BPSK
|
|
||||||
double code_rate = (double)K / (double)N;
|
|
||||||
double spectral_efficiency = code_rate * MOD_BITS;
|
|
||||||
double EbN0 = 10 * std::log10(sigma_signal * sigma_signal / (spectral_efficiency * 2 * sigma_noise * sigma_noise));
|
|
||||||
|
|
||||||
if (0) {
|
|
||||||
std::cerr << SNR << " Es/N0 => AWGN with standard deviation of " << sigma_noise << " and mean " << mean_noise << std::endl;
|
|
||||||
std::cerr << EbN0 << " Eb/N0, using spectral efficiency of " << spectral_efficiency << " from " << code_rate << " code rate and " << MOD_BITS << " bits per symbol." << std::endl;
|
|
||||||
std::cerr << awgn_errors << " errors caused by AWGN." << std::endl;
|
|
||||||
std::cerr << quantization_erasures << " erasures caused by quantization." << std::endl;
|
|
||||||
std::cerr << uncorrected_errors << " errors uncorrected." << std::endl;
|
|
||||||
std::cerr << ambiguity_erasures << " ambiguity erasures." << std::endl;
|
|
||||||
std::cerr << bit_error_rate << " bit error rate." << std::endl;
|
|
||||||
std::cerr << avg_mbs << " megabit per second." << std::endl;
|
|
||||||
} else {
|
|
||||||
std::cout << SNR << " " << bit_error_rate << " " << avg_mbs << " " << EbN0 << std::endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
std::cerr << "QEF at: " << min_SNR << " SNR, speed: " << max_mbs << " Mb/s." << std::endl;
|
|
||||||
double QEF_SNR = design_SNR + 0.2;
|
|
||||||
assert(min_SNR < QEF_SNR);
|
|
||||||
std::cerr << "Polar regression test passed!" << std::endl;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue