Files
openairinterface5g/openair1/PHY/CODING/TESTBENCH/ldpctest.c
T
Jaroslava Fiedlerova 01431a0e3f Merge remote-tracking branch 'origin/nrLDPC_coding_improvements_3' into integration_2025_w08 (!3227)
fix(nrLDPC_coding): timers in DL encoding, fix(ldpctest): Confusion in sizes

Main improvements:

1. fix(ldpctest): Confusion in sizes
   IMPORTANT: This fix makes that ldpctest now works with BG2 and K' != K!
   (Worth double checking with more cases than I did check with though)
   The variable block_length had an ambiguous role and was used as both K and
   Kprime. This was leading to arrays with wrong sizes and functions with wrong
   arguments. Now there is not anymore block_length but K and Kprime.
   Kprime can be set with the command line argument -l.
   There was also some problems with array allocation for segments with length
   not divisible by 8. A proper sizing with ((size_in_bits + 7) & ~7) / 8 was
   used.
   A proper masking of the last byte containing payload bits was also added to
   keep filler bits to 0 after random initialization.

2. fix(nrLDPC_coding): timers in DL encoding
   While timers were available for rate matching and interleaving in the new
   interface, these timers were not merged to rate matching and interleaving
   timers in nr_dlsch_coding.
2025-02-21 14:23:24 +01:00

635 lines
22 KiB
C

/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "assertions.h"
#include "SIMULATION/TOOLS/sim.h"
#include "common/config/config_userapi.h"
#include "common/utils/load_module_shlib.h"
#include "PHY/CODING/nrLDPC_extern.h"
// #include "openair1/SIMULATION/NR_PHY/nr_unitary_defs.h"
#include "openair1/PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.h"
#include "openair1/PHY/defs_nr_common.h"
#include "coding_unitary_defs.h"
#include "common/utils/LOG/log.h"
#define MAX_BLOCK_LENGTH 8448
#ifndef malloc16
#define malloc16(x) memalign(32, x)
#endif
#define NR_LDPC_PROFILER_DETAIL
#define NR_LDPC_ENABLE_PARITY_CHECK
ldpc_interface_t ldpc_orig, ldpc_toCompare;
// 4-bit quantizer
int8_t quantize4bit(double D, double x)
{
double qxd;
qxd = floor(x / D);
// printf("x=%f,qxd=%f\n",x,qxd);
if (qxd <= -8)
qxd = -8;
else if (qxd > 7)
qxd = 7;
return ((int8_t)qxd);
}
int8_t quantize8bit(double D, double x)
{
double qxd;
// int8_t maxlev;
qxd = floor(x / D);
// maxlev = 1<<(B-1);
// printf("x=%f,qxd=%f,maxlev=%d\n",x,qxd, maxlev);
if (qxd <= -128)
qxd = -128;
else if (qxd >= 128)
qxd = 127;
return ((int8_t)qxd);
}
typedef struct {
double n_iter_mean;
double n_iter_std;
int n_iter_max;
double snr;
double ber;
double bler;
} n_iter_stats_t;
typedef struct {
unsigned int errors;
unsigned int errors_bit;
double errors_bit_uncoded;
unsigned int crc_misses;
time_stats_t time_optim;
time_stats_t time_decoder;
n_iter_stats_t dec_iter;
} one_measurement_t;
one_measurement_t test_ldpc(short max_iterations,
int nom_rate,
int denom_rate,
double SNR,
unsigned char qbits,
short Kprime,
unsigned int ntrials,
int n_segments)
{
one_measurement_t ret = {0};
reset_meas(&ret.time_optim);
reset_meas(&ret.time_decoder);
// clock initiate
// time_stats_t time,time_optim,tinput,tprep,tparity,toutput, time_decoder;
time_stats_t time, tinput, tprep, tparity, toutput;
double n_iter_mean = 0;
double n_iter_std = 0;
int n_iter_max = 0;
double sigma;
sigma = 1.0 / sqrt(2 * SNR);
cpu_meas_enabled = 1;
uint8_t *test_input[MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * NR_MAX_NB_LAYERS];
uint8_t estimated_output[MAX_NUM_DLSCH_SEGMENTS][Kprime];
memset(estimated_output, 0, sizeof(estimated_output));
uint8_t *channel_input[MAX_NUM_DLSCH_SEGMENTS];
uint8_t *channel_input_optim[MAX_NUM_DLSCH_SEGMENTS];
// double channel_output[68 * 384];
double modulated_input[MAX_NUM_DLSCH_SEGMENTS][68 * 384] = {0};
int8_t channel_output_fixed[MAX_NUM_DLSCH_SEGMENTS][68 * 384] = {0};
short BG = 0, nrows = 0; //,ncols;
int i1, Kb = 0;
int R_ind = 0;
// int n_segments=1;
int code_rate_vec[8] = {15, 13, 25, 12, 23, 34, 56, 89};
// double code_rate_actual_vec[8] = {0.2, 0.33333, 0.4, 0.5, 0.66667, 0.73333, 0.81481, 0.88};
t_nrLDPC_dec_params decParams[MAX_NUM_DLSCH_SEGMENTS] = {0};
t_nrLDPC_time_stats decoder_profiler = {0};
int32_t n_iter = 0;
reset_meas(&time);
reset_meas(&tinput);
reset_meas(&tprep);
reset_meas(&tparity);
reset_meas(&toutput);
// Reset Decoder profiles
reset_meas(&decoder_profiler.llr2llrProcBuf);
reset_meas(&decoder_profiler.llr2CnProcBuf);
reset_meas(&decoder_profiler.cnProc);
reset_meas(&decoder_profiler.cnProcPc);
reset_meas(&decoder_profiler.bnProc);
reset_meas(&decoder_profiler.bnProcPc);
reset_meas(&decoder_profiler.cn2bnProcBuf);
reset_meas(&decoder_profiler.bn2cnProcBuf);
reset_meas(&decoder_profiler.llrRes2llrOut);
reset_meas(&decoder_profiler.llr2bit);
// reset_meas(&decoder_profiler.total);
// determine number of bits in codeword
if (Kprime > 3840) {
BG = 1;
Kb = 22;
nrows = 46; // parity check bits
// ncols=22; //info bits
} else {
BG = 2;
nrows = 42; // parity check bits
// ncols=10; // info bits
if (Kprime > 640)
Kb = 10;
else if (Kprime > 560)
Kb = 9;
else if (Kprime > 192)
Kb = 8;
else
Kb = 6;
}
bool error = false;
switch (nom_rate) {
case 1:
if (denom_rate == 5)
if (BG == 2)
R_ind = 0;
else
error = true;
else if (denom_rate == 3)
R_ind = 1;
else if (denom_rate == 2)
// R_ind = 3;
error = true;
else
error = true;
break;
case 2:
if (denom_rate == 5)
// R_ind = 2;
error = true;
else if (denom_rate == 3)
R_ind = 4;
else
error = true;
break;
case 22:
if (denom_rate == 25 && BG == 1)
R_ind = 7;
else
error = true;
break;
default:
error = true;
}
if (error) {
printf("Not supported: nom_rate: %d, denom_rate: %d\n", nom_rate, denom_rate);
exit(1);
}
// find minimum value in all sets of lifting size
int Zc = 0;
const short lift_size[51] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20,
22, 24, 26, 28, 30, 32, 36, 40, 44, 48, 52, 56, 60, 64, 72, 80, 88,
96, 104, 112, 120, 128, 144, 160, 176, 192, 208, 224, 240, 256, 288, 320, 352, 384};
for (i1 = 0; i1 < 51; i1++) {
if (lift_size[i1] >= (double)Kprime / Kb) {
Zc = lift_size[i1];
break;
}
}
// K: Segment size = number of columns in the parity check matrix * lifting size (number of columns of the square parity check
// sub-matrix)
int K = 0;
if (BG == 1) {
K = 22 * Zc;
} else if (BG == 2) {
K = 10 * Zc;
} else {
printf("Not supported: BG: %d\n", BG);
exit(1);
}
printf("ldpc_test: codeword_length %d, n_segments %d, Kprime %d, BG %d, Zc %d, Kb %d\n",
n_segments * K,
n_segments,
Kprime,
BG,
Zc,
Kb);
const int no_punctured_columns = (int)((nrows - 2) * Zc + K - K * (1 / ((float)nom_rate / (float)denom_rate))) / Zc;
// printf("puncture:%d\n",no_punctured_columns);
const int removed_bit = (nrows - no_punctured_columns - 2) * Zc + K - (int)(K / ((float)nom_rate / (float)denom_rate));
printf("nrows: %d\n", nrows);
printf("no_punctured_columns: %d\n", no_punctured_columns);
printf("removed_bit: %d\n", removed_bit);
printf("To: %d\n", (Kb + nrows - no_punctured_columns) * Zc - removed_bit);
printf("number of undecoded bits: %d\n", (Kb + nrows - no_punctured_columns - 2) * Zc - removed_bit);
// generate input block
for (int j = 0; j < MAX_NUM_DLSCH_SEGMENTS; j++) {
test_input[j] = malloc16(((K + 7) & ~7) / 8);
memset(test_input[j], 0, ((K + 7) & ~7) / 8);
channel_input[j] = malloc16(68 * 384);
memset(channel_input[j], 0, 68 * 384);
channel_input_optim[j] = malloc16(68 * 384);
memset(channel_input_optim[j], 0, 68 * 384);
}
// Fill input segments with random values
for (int j = 0; j < MAX_NUM_DLSCH_SEGMENTS; j++) {
int i = 0;
for (i = 0; i < ((Kprime + 7) & ~7) / 8; i++)
test_input[j][i] = (uint8_t)rand();
// Mask the last byte in order to keep filler bits to 0
if (Kprime % 8 != 0) {
uint8_t last_byte_mask = (1 << (Kprime % 8)) - 1;
test_input[j][i - 1] = test_input[j][i - 1] & last_byte_mask;
}
}
encoder_implemparams_t impp = {.Zc = Zc, .Kb = Kb, .BG = BG, .K = K};
impp.gen_code = 2;
if (ntrials == 0)
ldpc_orig.LDPCencoder(test_input, channel_input, &impp);
impp.gen_code = 0;
decode_abort_t dec_abort;
init_abort(&dec_abort);
for (int trial = 0; trial < ntrials; trial++) {
unsigned int segment_bler = 0;
//// encoder
start_meas(&time);
for (int j = 0; j < n_segments; j++) {
ldpc_orig.LDPCencoder(&test_input[j], &channel_input[j], &impp);
}
stop_meas(&time);
impp.n_segments = n_segments;
for (int j = 0; j < (n_segments / 8 + 1); j++) {
start_meas(&ret.time_optim);
impp.macro_num = j;
ldpc_toCompare.LDPCencoder(test_input, channel_input_optim, &impp);
stop_meas(&ret.time_optim);
}
if (ntrials == 1)
for (int j = 0; j < n_segments; j++)
for (int i = 0; i < K + (nrows - no_punctured_columns) * Zc - removed_bit; i++) {
if (channel_input[j][i] != channel_input_optim[j][i]) {
printf("differ in seg %d pos %d (%u,%u)\n", j, i, channel_input[j][i], channel_input_optim[j][i]);
return ret;
}
}
for (int j = 0; j < n_segments; j++) {
for (int i = 2 * Zc; i < (Kb + nrows - no_punctured_columns) * Zc - removed_bit; i++) {
#ifdef DEBUG_CODER
if ((i & 0xf) == 0)
printf("\ne %d..%d: ", i, i + 15);
#endif
if (channel_input_optim[j][i - 2 * Zc] == 0)
modulated_input[j][i] = 1.0; /// sqrt(2); //QPSK
else
modulated_input[j][i] = -1.0; /// sqrt(2);
channel_output_fixed[j][i] =
(int8_t)quantize(sigma / 4.0 / 4.0, modulated_input[j][i] + sigma * gaussdouble(0.0, 1.0), qbits);
// Uncoded BER
uint8_t channel_output_uncoded = channel_output_fixed[j][i] < 0 ? 1 /* QPSK demod */ : 0;
if (channel_output_uncoded != channel_input_optim[j][i - 2 * Zc])
ret.errors_bit_uncoded++;
}
#ifdef DEBUG_CODER
printf("\n");
exit(-1);
#endif
decParams[j].BG = BG;
decParams[j].Z = Zc;
decParams[j].R = code_rate_vec[R_ind]; // 13;
decParams[j].numMaxIter = max_iterations;
decParams[j].outMode = nrLDPC_outMode_BIT;
decParams[j].Kprime = Kprime;
ldpc_toCompare.LDPCinit();
}
for (int j = 0; j < n_segments; j++) {
start_meas(&ret.time_decoder);
set_abort(&dec_abort, false);
n_iter = ldpc_toCompare.LDPCdecoder(&decParams[j],
0,
0,
0,
(int8_t *)channel_output_fixed[j],
(int8_t *)estimated_output[j],
&decoder_profiler,
&dec_abort);
stop_meas(&ret.time_decoder);
// count errors
if (memcmp(estimated_output[j], test_input[j], ((Kprime + 7) & ~7) / 8) != 0) {
segment_bler++;
}
for (int i = 0; i < Kprime; i++) {
unsigned char estoutputbit = (estimated_output[j][i / 8] & (1 << (i & 7))) >> (i & 7);
unsigned char inputbit = (test_input[j][i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments
if (estoutputbit != inputbit)
ret.errors_bit++;
}
n_iter_mean += n_iter;
n_iter_std += pow(n_iter - 1, 2);
if (n_iter > n_iter_max)
n_iter_max = n_iter;
} // end segments
if (segment_bler != 0)
ret.errors++;
}
ret.dec_iter.n_iter_mean = n_iter_mean / (double)ntrials / (double)n_segments - 1;
ret.dec_iter.n_iter_std =
sqrt(n_iter_std / (double)ntrials / (double)n_segments - pow(n_iter_mean / (double)ntrials / (double)n_segments - 1, 2));
ret.dec_iter.n_iter_max = n_iter_max - 1;
ret.errors_bit_uncoded = ret.errors_bit_uncoded / (double)((Kb + nrows - no_punctured_columns - 2) * Zc - removed_bit);
for (int j = 0; j < MAX_NUM_DLSCH_SEGMENTS; j++) {
free(test_input[j]);
free(channel_input[j]);
free(channel_input_optim[j]);
}
print_meas(&time, "ldpc_encoder", NULL, NULL);
print_meas(&ret.time_optim, "ldpc_encoder_optim", NULL, NULL);
print_meas(&tinput, "ldpc_encoder_optim(input)", NULL, NULL);
print_meas(&tprep, "ldpc_encoder_optim(prep)", NULL, NULL);
print_meas(&tparity, "ldpc_encoder_optim(parity)", NULL, NULL);
print_meas(&toutput, "ldpc_encoder_optim(output)", NULL, NULL);
printf("\n");
print_meas(&ret.time_decoder, "ldpc_decoder", NULL, NULL);
print_meas(&decoder_profiler.llr2llrProcBuf, "llr2llrProcBuf", NULL, NULL);
print_meas(&decoder_profiler.llr2CnProcBuf, "llr2CnProcBuf", NULL, NULL);
print_meas(&decoder_profiler.cnProc, "cnProc (per iteration)", NULL, NULL);
print_meas(&decoder_profiler.cnProcPc, "cnProcPc (per iteration)", NULL, NULL);
print_meas(&decoder_profiler.bnProc, "bnProc (per iteration)", NULL, NULL);
print_meas(&decoder_profiler.bnProcPc, "bnProcPc(per iteration)", NULL, NULL);
print_meas(&decoder_profiler.cn2bnProcBuf, "cn2bnProcBuf (per iteration)", NULL, NULL);
print_meas(&decoder_profiler.bn2cnProcBuf, "bn2cnProcBuf (per iteration)", NULL, NULL);
print_meas(&decoder_profiler.llrRes2llrOut, "llrRes2llrOut", NULL, NULL);
print_meas(&decoder_profiler.llr2bit, "llr2bit", NULL, NULL);
printf("\n");
return ret;
}
configmodule_interface_t *uniqCfg = NULL;
int main(int argc, char *argv[])
{
short Kprime = 8448;
// default to check output inside ldpc, the NR version checks the outer CRC defined by 3GPP
char *ldpc_version = "";
/* version of the ldpc decoder library to use (XXX suffix to use when loading libldpc_XXX.so */
short max_iterations = 5;
int n_segments = 1;
// double rate=0.333;
int nom_rate = 1;
int denom_rate = 3;
double SNR0 = -2.0;
uint8_t qbits = 8;
unsigned int decoded_errors[10000]; // initiate the size of matrix equivalent to size of SNR
int c, i = 0;
int n_trials = 1;
double SNR_step = 0.1;
randominit(0);
int test_uncoded = 0;
n_iter_stats_t dec_iter[400] = {0};
short BG = 0, Zc;
if ((uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY)) == 0) {
exit_fun("[LDPCTEST] Error, configuration module init failed\n");
}
logInit();
while ((c = getopt(argc, argv, "--:O:q:r:s:S:l:G:n:d:i:t:u:hv:")) != -1) {
/* ignore long options starting with '--', option '-O' and their arguments that are handled by configmodule */
/* with this opstring getopt returns 1 for non-option arguments, refer to 'man 3 getopt' */
if (c == 1 || c == '-' || c == 'O')
continue;
printf("handling optarg %c\n", c);
switch (c) {
case 'q':
qbits = atoi(optarg);
break;
case 'r':
nom_rate = atoi(optarg);
break;
case 'd':
denom_rate = atoi(optarg);
break;
case 'l':
Kprime = atoi(optarg);
break;
case 'G':
ldpc_version = "_cuda";
break;
case 'n':
n_trials = atoi(optarg);
break;
case 's':
SNR0 = atof(optarg);
break;
case 'S':
n_segments = atof(optarg);
break;
case 't':
SNR_step = atof(optarg);
break;
case 'i':
max_iterations = atoi(optarg);
break;
case 'u':
test_uncoded = atoi(optarg);
break;
case 'v':
ldpc_version = strdup(optarg);
break;
case 'h':
default:
printf("CURRENTLY SUPPORTED CODE RATES: \n");
printf("BG1 (K' > 3840): 1/3, 2/3, 22/25 (8/9) \n");
printf("BG2 (K' <= 3840): 1/5, 1/3, 2/3 \n\n");
printf("-h This message\n");
printf("-q Quantization bits, Default: 8\n");
printf("-r Nominator rate, (1, 2, 22), Default: 1\n");
printf("-d Denominator rate, (3, 5, 25), Default: 1\n");
printf("-l Length of payload bits in a segment (K' in 38.212-5.2.2), [1, 8448], Default: 8448\n");
printf("-G give 1 to run cuda for LDPC, Default: 0\n");
printf("-n Number of simulation trials, Default: 1\n");
// printf("-M MCS2 for TB 2\n");
printf("-s SNR per information bit (EbNo) in dB, Default: -2\n");
printf("-S Number of segments (Maximum: 8), Default: 1\n");
printf("-t SNR simulation step, Default: 0.1\n");
printf("-i Max decoder iterations, Default: 5\n");
printf("-u Set SNR per coded bit, Default: 0\n");
printf("-v _XXX Set ldpc shared library version. libldpc_XXX.so will be used \n");
exit(1);
break;
}
}
printf("block length %d: \n", Kprime);
printf("n_trials %d: \n", n_trials);
printf("SNR0 %f: \n", SNR0);
load_LDPClib(ldpc_version, &ldpc_toCompare);
load_LDPClib("_orig", &ldpc_orig);
// find minimum value in all sets of lifting size
Zc = 0;
char fname[200];
sprintf(fname, "ldpctest_BG_%d_Zc_%d_rate_%d-%d_Kprime_%d_maxit_%d.txt", BG, Zc, nom_rate, denom_rate, Kprime, max_iterations);
FILE *fd = fopen(fname, "w");
AssertFatal(fd != NULL, "cannot open %s\n", fname);
fprintf(fd,
"SNR BLER BER UNCODED_BER ENCODER_MEAN ENCODER_STD ENCODER_MAX DECODER_TIME_MEAN DECODER_TIME_STD DECODER_TIME_MAX "
"DECODER_ITER_MEAN DECODER_ITER_STD DECODER_ITER_MAX\n");
for (double SNR = SNR0; SNR < SNR0 + 20.0; SNR += SNR_step) {
double SNR_lin;
if (test_uncoded == 1)
SNR_lin = pow(10, SNR / 10.0);
else
SNR_lin = pow(10, SNR / 10.0) * nom_rate / denom_rate;
printf("Linear SNR: %f\n", SNR_lin);
one_measurement_t res = test_ldpc(max_iterations,
nom_rate,
denom_rate,
SNR_lin, // noise standard deviation
qbits,
Kprime, // block length bytes
n_trials,
n_segments);
decoded_errors[i] = res.errors;
dec_iter[i] = res.dec_iter;
dec_iter[i].snr = SNR;
dec_iter[i].ber = (float)res.errors_bit / (float)n_trials / (float)Kprime / (double)n_segments;
dec_iter[i].bler = (float)decoded_errors[i] / (float)n_trials;
printf("SNR %f, BLER %f (%u/%d)\n", SNR, dec_iter[i].bler, decoded_errors[i], n_trials);
printf("SNR %f, BER %f (%u/%d)\n", SNR, dec_iter[i].ber, decoded_errors[i], n_trials);
printf("SNR %f, Uncoded BER %f (%u/%d)\n",
SNR,
res.errors_bit_uncoded / (float)n_trials / (double)n_segments,
decoded_errors[i],
n_trials);
printf("SNR %f, Mean iterations: %f\n", SNR, dec_iter[i].n_iter_mean);
printf("SNR %f, Std iterations: %f\n", SNR, dec_iter[i].n_iter_std);
printf("SNR %f, Max iterations: %d\n", SNR, dec_iter[i].n_iter_max);
printf("\n");
double cpu_freq = get_cpu_freq_GHz();
time_stats_t *t_optim = &res.time_optim;
printf("Encoding time mean: %15.3f us\n", (double)t_optim->diff / t_optim->trials / 1000.0 / cpu_freq);
printf("Encoding time std: %15.3f us\n",
sqrt((double)t_optim->diff_square / t_optim->trials / pow(1000, 2) / pow(cpu_freq, 2)
- pow((double)t_optim->diff / t_optim->trials / 1000.0 / cpu_freq, 2)));
printf("Encoding time max: %15.3f us\n", (double)t_optim->max / 1000.0 / cpu_freq);
printf("\n");
time_stats_t *t_decoder = &res.time_decoder;
printf("Decoding time mean: %15.3f us\n", (double)t_decoder->diff / t_decoder->trials / 1000.0 / cpu_freq);
printf("Decoding time std: %15.3f us\n",
sqrt((double)t_decoder->diff_square / t_decoder->trials / pow(1000, 2) / pow(cpu_freq, 2)
- pow((double)t_decoder->diff / t_decoder->trials / 1000.0 / cpu_freq, 2)));
printf("Decoding time max: %15.3f us\n", (double)t_decoder->max / 1000.0 / cpu_freq);
fprintf(fd,
"%f %f %f %f %f %f %f %f %f %f %f %f %d \n",
SNR,
(double)decoded_errors[i] / (double)n_trials,
(double)res.errors_bit / (double)n_trials / (double)Kprime / (double)n_segments,
res.errors_bit_uncoded / (double)n_trials / (double)n_segments,
(double)t_optim->diff / t_optim->trials / 1000.0 / cpu_freq,
sqrt((double)t_optim->diff_square / t_optim->trials / pow(1000, 2) / pow(cpu_freq, 2)
- pow((double)t_optim->diff / t_optim->trials / 1000.0 / cpu_freq, 2)),
(double)t_optim->max / 1000.0 / cpu_freq,
(double)t_decoder->diff / t_decoder->trials / 1000.0 / cpu_freq,
sqrt((double)t_decoder->diff_square / t_decoder->trials / pow(1000, 2) / pow(cpu_freq, 2)
- pow((double)t_decoder->diff / t_decoder->trials / 1000.0 / cpu_freq, 2)),
(double)t_decoder->max / 1000.0 / cpu_freq,
dec_iter[i].n_iter_mean,
dec_iter[i].n_iter_std,
dec_iter[i].n_iter_max);
i = i + 1;
if (decoded_errors[i - 1] == 0)
break;
}
fclose(fd);
LOG_M("ldpctestStats.m", "SNR", &dec_iter[0].snr, i, 1, 7);
LOG_MM("ldpctestStats.m", "BLER", &dec_iter[0].bler, i, 1, 7);
LOG_MM("ldpctestStats.m", "BER", &dec_iter[0].ber, i, 1, 7);
LOG_MM("ldpctestStats.m", "meanIter", &dec_iter[0].n_iter_mean, i, 1, 7);
loader_reset();
logTerm();
return (0);
}