mirror of https://github.com/PentHertz/srsLTE.git
Split llr_approx() in three routines
This commit is contained in:
parent
3dfb1824b4
commit
de1454cf7b
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue