Split llr_approx() in three routines

This commit is contained in:
ismagom 2014-07-25 16:49:15 +01:00 committed by marojevic
parent 3dfb1824b4
commit de1454cf7b
5 changed files with 100 additions and 62 deletions

View File

@ -42,14 +42,17 @@ CHECK_FUNCTION_EXISTS_MATH(volk_32f_x2_dot_prod_32f HAVE_VOLK_DOTPROD_F_FUNCTION
CHECK_FUNCTION_EXISTS_MATH(volk_32fc_s32f_atan2_32f HAVE_VOLK_ATAN_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_32f_s32f_convert_16i HAVE_VOLK_CONVERT_FI_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_32fc_deinterleave_32f_x2 HAVE_VOLK_DEINTERLEAVE_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_32f_x2_subtract_32f HAVE_VOLK_SUB_FLOAT_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_32fc_x2_square_dist_32f HAVE_VOLK_SQUARE_DIST_FUNCTION)
SET(VOLK_DEFINITIONS "HAVE_VOLK")
IF(${HAVE_VOLK_DOTPROD_CONJ_FC_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_DOTPROD_CONJ_FC_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_SQUARE_DIST_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_SQUARE_DIST_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_SUB_FLOAT_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_SUB_FLOAT_FUNCTION")
ENDIF()

View File

@ -35,7 +35,7 @@
typedef _Complex float cf_t;
#define EXPAVERAGE(data, average, nframes) ((data + average * nframes) / (nframes + 1))
#define EXPAVERAGE(data, average, nframes) (((data) + (average) * (nframes)) / ((nframes) + 1))
/** Return the sum of all the elements */
@ -64,6 +64,9 @@ LIBLTE_API void vec_sum_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len);
/* substract two vectors z=x-y */
LIBLTE_API void vec_sub_fff(float *x, float *y, float *z, uint32_t len);
/* Square distance */
LIBLTE_API void vec_square_dist(cf_t symbol, cf_t *points, float *distance, uint32_t npoints);
/* scalar product */
LIBLTE_API void vec_sc_prod_cfc(cf_t *x, float h, cf_t *z, uint32_t len);
LIBLTE_API void vec_sc_prod_ccc(cf_t *x, cf_t h, cf_t *z, uint32_t len);

View File

@ -33,51 +33,66 @@
#include <stdint.h>
#include "soft_algs.h"
#include "liblte/phy/utils/vector.h"
#define LLR_APPROX_USE_VOLK
#ifdef LLR_APPROX_USE_VOLK
void
llr_approx(const _Complex float *in, float *out, int N, int M, int B,
_Complex float *symbols, uint32_t(*S)[6][32], float sigma2)
{
int i, s, b;
float num, den;
int change_sign = -1;
float x, y, d[64];
for (s = 0; s < N; s++) { /* recevied symbols */
/* Compute the distances squared d[i] between the received symbol and all constellation points */
for (i = 0; i < M; i++) {
x = __real__ in[s] - __real__ symbols[i];
y = __imag__ in[s] - __imag__ symbols[i];
d[i] = x * x + y * y;
}
typedef _Complex float cf_t;
float d[10000][64];
float num[10000], den[10000];
static void compute_square_dist(const cf_t *in, cf_t *symbols, int N, int M) {
int s;
float *d_ptr;
for (s = 0; s < N; s++) {
d_ptr = d[s];
vec_square_dist(in[s], symbols, d_ptr, M);
}
}
static void compute_min_dist(uint32_t (*S)[6][32], int N, int B, int M) {
int s, b, i;
for (s = 0; s < N; s++) {
for (b = 0; b < B; b++) { /* bits per symbol */
/* initiate num[b] and den[b] */
num = d[S[0][b][0]];
den = d[S[1][b][0]];
num[s * B + b] = 1e10;
den[s * B + b] = 1e10;
/* Minimum distance squared search between recevied symbol and a constellation point with a
'1' and a '0' for each bit position */
for (i = 1; i < M / 2; i++) { /* half the constellation points have '1'|'0' at any given bit position */
if (d[S[0][b][i]] < num) {
num = d[S[0][b][i]];
for (i = 0; i < M / 2; i++) {
if (d[s][S[0][b][i]] < num[s * B + b]) {
num[s * B + b] = d[s][S[0][b][i]];
}
if (d[S[1][b][i]] < den) {
den = d[S[1][b][i]];
if (d[s][S[1][b][i]] < den[s * B + b]) {
den[s * B + b] = d[s][S[1][b][i]];
}
}
/* Theoretical LLR and approximate LLR values are positive if
* symbol(s) with '0' is/are closer and negative if symbol(s)
* with '1' are closer.
* Change sign if mapping negative to '0' and positive to '1' */
out[s * B + b] = change_sign * (den - num) / sigma2;
}
}
}
static void compute_llr(int N, int B, float sigma2, float *out) {
int s, b;
for (s = 0; s < N; s++) {
for (b = 0; b < B; b++) { /* bits per symbol */
out[s * B + b] = (num[s * B + b]-den[s * B + b]) / sigma2;
}
}
}
void llr_approx(const _Complex float *in, float *out, int N, int M, int B,
_Complex float *symbols, uint32_t(*S)[6][32], float sigma2)
{
if (M <= 64) {
compute_square_dist(in, symbols, N, M);
compute_min_dist(S, N, B, M);
compute_llr(N, B, sigma2, out);
}
}
#else
@ -135,6 +150,8 @@ llr_approx(const _Complex float *in, float *out, int N, int M, int B,
* with '1' are closer.
* Change sign if mapping negative to '0' and positive to '1' */
out[s * B + b] = change_sign * (den - num) / sigma2;
if (s<10)
printf("out[%d]=%f=%f/%f\n",s*B+b,out[s*B+b], num,den);
}
}

View File

@ -100,7 +100,7 @@ float mse_threshold() {
case LTE_QAM16:
return 0.11;
case LTE_QAM64:
return 0.18;
return 0.19;
default:
return -1.0;
}
@ -159,7 +159,7 @@ int main(int argc, char **argv) {
}
/* generate random data */
srand(time(NULL));
srand(0);
int ret = -1;
double mse;
@ -187,7 +187,9 @@ int main(int argc, char **argv) {
get_time_interval(t);
/* compute exponentially averaged execution time */
mean_texec = EXPAVERAGE((float) t[0].tv_usec, mean_texec, n);
if (n > 0) {
mean_texec = EXPAVERAGE((float) t[0].tv_usec, mean_texec, n-1);
}
/* check MSE */
mse = 0.0;

View File

@ -39,7 +39,7 @@
#endif
int vec_acc_ii(int *x, uint32_t len) {
int i;
uint32_t i;
int z=0;
for (i=0;i<len;i++) {
z+=x[i];
@ -53,7 +53,7 @@ float vec_acc_ff(float *x, uint32_t len) {
volk_32f_accumulator_s32f(&result,x,len);
return result;
#else
int i;
uint32_t i;
float z=0;
for (i=0;i<len;i++) {
z+=x[i];
@ -63,7 +63,7 @@ float vec_acc_ff(float *x, uint32_t len) {
}
cf_t vec_acc_cc(cf_t *x, uint32_t len) {
int i;
uint32_t i;
cf_t z=0;
for (i=0;i<len;i++) {
z+=x[i];
@ -71,9 +71,22 @@ cf_t vec_acc_cc(cf_t *x, uint32_t len) {
return z;
}
void vec_square_dist(cf_t symbol, cf_t *points, float *distance, uint32_t npoints) {
#ifndef HAVE_VOLK_SQUARE_DIST_FUNCTION
uint32_t i;
cf_t diff;
for (i=0;i<npoints;i++) {
diff = symbol - points[i];
distance[i] = crealf(diff) * crealf(diff) + cimagf(diff) * cimagf(diff);
}
#else
volk_32fc_x2_square_dist_32f(distance,&symbol,points,npoints);
#endif
}
void vec_sub_fff(float *x, float *y, float *z, uint32_t len) {
#ifndef HAVE_VOLK_SUB_FLOAT_FUNCTION
int i;
uint32_t i;
for (i=0;i<len;i++) {
z[i] = x[i]-y[i];
}
@ -83,14 +96,14 @@ void vec_sub_fff(float *x, float *y, float *z, uint32_t len) {
}
void vec_sum_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len) {
int i;
uint32_t i;
for (i=0;i<len;i++) {
z[i] = x[i]+y[i];
}
}
void vec_sum_bbb(char *x, char *y, char *z, uint32_t len) {
int i;
uint32_t i;
for (i=0;i<len;i++) {
z[i] = x[i]+y[i];
}
@ -98,7 +111,7 @@ void vec_sum_bbb(char *x, char *y, char *z, uint32_t len) {
void vec_sc_prod_fff(float *x, float h, float *z, uint32_t len) {
#ifndef HAVE_VOLK_MULT_FLOAT_FUNCTION
int i;
uint32_t i;
for (i=0;i<len;i++) {
z[i] = x[i]*h;
}
@ -109,7 +122,7 @@ void vec_sc_prod_fff(float *x, float h, float *z, uint32_t len) {
void vec_sc_prod_cfc(cf_t *x, float h, cf_t *z, uint32_t len) {
#ifndef HAVE_VOLK_MULT_FUNCTION
int i;
uint32_t i;
for (i=0;i<len;i++) {
z[i] = x[i]*h;
}
@ -123,7 +136,7 @@ void vec_sc_prod_cfc(cf_t *x, float h, cf_t *z, uint32_t len) {
void vec_sc_prod_ccc(cf_t *x, cf_t h, cf_t *z, uint32_t len) {
#ifndef HAVE_VOLK_MULT_FUNCTION
int i;
uint32_t i;
for (i=0;i<len;i++) {
z[i] = x[i]*h;
}
@ -136,7 +149,7 @@ void vec_convert_fi(float *x, int16_t *z, float scale, uint32_t len) {
#ifdef HAVE_VOLK_CONVERT_FI_FUNCTION
volk_32f_s32f_convert_16i(z, x, scale, len);
#else
int i;
uint32_t i;
for (i=0;i<len;i++) {
z[i] = (int16_t) (x[i]*scale);
}
@ -147,7 +160,7 @@ void vec_deinterleave_cf(cf_t *x, float *real, float *imag, uint32_t len) {
#ifdef HAVE_VOLK_DEINTERLEAVE_FUNCTION
volk_32fc_deinterleave_32f_x2(real, imag, x, len);
#else
int i;
uint32_t i;
for (i=0;i<len;i++) {
real[i] = __real__ x[i];
imag[i] = __imag__ x[i];
@ -185,7 +198,7 @@ void *vec_realloc(void *ptr, uint32_t old_size, uint32_t new_size) {
void vec_fprint_c(FILE *stream, cf_t *x, uint32_t len) {
int i;
uint32_t i;
fprintf(stream, "[");
for (i=0;i<len;i++) {
fprintf(stream, "%+2.2f%+2.2fi, ", __real__ x[i], __imag__ x[i]);
@ -194,7 +207,7 @@ void vec_fprint_c(FILE *stream, cf_t *x, uint32_t len) {
}
void vec_fprint_f(FILE *stream, float *x, uint32_t len) {
int i;
uint32_t i;
fprintf(stream, "[");
for (i=0;i<len;i++) {
fprintf(stream, "%+2.2f, ", x[i]);
@ -204,7 +217,7 @@ void vec_fprint_f(FILE *stream, float *x, uint32_t len) {
void vec_fprint_b(FILE *stream, char *x, uint32_t len) {
int i;
uint32_t i;
fprintf(stream, "[");
for (i=0;i<len;i++) {
fprintf(stream, "%d, ", x[i]);
@ -213,7 +226,7 @@ void vec_fprint_b(FILE *stream, char *x, uint32_t len) {
}
void vec_fprint_i(FILE *stream, int *x, uint32_t len) {
int i;
uint32_t i;
fprintf(stream, "[");
for (i=0;i<len;i++) {
fprintf(stream, "%d, ", x[i]);
@ -249,7 +262,7 @@ void vec_save_file(char *filename, void *buffer, uint32_t len) {
void vec_conj_cc(cf_t *x, cf_t *y, uint32_t len) {
#ifndef HAVE_VOLK_CONJ_FUNCTION
int i;
uint32_t i;
for (i=0;i<len;i++) {
y[i] = conjf(x[i]);
}
@ -260,7 +273,7 @@ void vec_conj_cc(cf_t *x, cf_t *y, uint32_t len) {
void vec_prod_cfc(cf_t *x, float *y, cf_t *z, uint32_t len) {
#ifndef HAVE_VOLK_MULT_REAL_FUNCTION
int i;
uint32_t i;
for (i=0;i<len;i++) {
z[i] = x[i]*y[i];
}
@ -272,7 +285,7 @@ void vec_prod_cfc(cf_t *x, float *y, cf_t *z, uint32_t len) {
void vec_prod_ccc(cf_t *x,cf_t *y, cf_t *z, uint32_t len) {
#ifndef HAVE_VOLK_MULT2_FUNCTION
int i;
uint32_t i;
for (i=0;i<len;i++) {
z[i] = x[i]*y[i];
}
@ -284,7 +297,7 @@ void vec_prod_ccc(cf_t *x,cf_t *y, cf_t *z, uint32_t len) {
void vec_prod_conj_ccc(cf_t *x,cf_t *y, cf_t *z, uint32_t len) {
#ifndef HAVE_VOLK_MULT2_CONJ_FUNCTION
int i;
uint32_t i;
for (i=0;i<len;i++) {
z[i] = x[i]*conjf(y[i]);
}
@ -294,7 +307,7 @@ void vec_prod_conj_ccc(cf_t *x,cf_t *y, cf_t *z, uint32_t len) {
}
void vec_div_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len) {
int i;
uint32_t i;
for (i=0;i<len;i++) {
z[i] = x[i] / y[i];
}
@ -304,7 +317,7 @@ void vec_div_fff(float *x, float *y, float *z, uint32_t len) {
#ifdef HAVE_VOLK_DIVIDE_FUNCTION
volk_32f_x2_divide_32f(z, x, y, len);
#else
int i;
uint32_t i;
for (i=0;i<len;i++) {
z[i] = x[i] / y[i];
}
@ -359,7 +372,7 @@ float vec_dot_prod_fff(float *x, float *y, uint32_t len) {
float vec_avg_power_cf(cf_t *x, uint32_t len) {
int j;
uint32_t j;
float power = 0;
for (j=0;j<len;j++) {
power += crealf(x[j]*conjf(x[j]));
@ -369,7 +382,7 @@ float vec_avg_power_cf(cf_t *x, uint32_t len) {
void vec_abs_cf(cf_t *x, float *abs, uint32_t len) {
#ifndef HAVE_VOLK_MAG_FUNCTION
int i;
uint32_t i;
for (i=0;i<len;i++) {
abs[i] = cabsf(x[i]);
}
@ -382,7 +395,7 @@ void vec_abs_cf(cf_t *x, float *abs, uint32_t len) {
void vec_arg_cf(cf_t *x, float *arg, uint32_t len) {
#ifndef HAVE_VOLK_ATAN_FUNCTION
int i;
uint32_t i;
for (i=0;i<len;i++) {
arg[i] = cargf(x[i]);
}
@ -414,10 +427,10 @@ uint32_t vec_max_fi(float *x, uint32_t len) {
}
void vec_quant_fuc(float *in, unsigned char *out, float gain, float offset, float clip, uint32_t len) {
int i;
int tmp;
uint32_t i;
uint32_t tmp;
for (i=0;i<len;i++) {
tmp = (int) (offset + gain * in[i]);
tmp = (uint32_t) (offset + gain * in[i]);
if (tmp < 0)
tmp = 0;
if (tmp > clip)