/* These functions compute linear preprocessing for the UE using LAPACKE and CBLAS modules of LAPACK libraries. MMSE and MMSE whitening filters are available. Functions are using RowMajor storage of the matrices, like in conventional C. Traditional Fortran functions of LAPACK employ ColumnMajor data storage. */ #include #include #include #include #include #include #include #if RHEL_RELEASE_CODE >= 1796 #include #include #else #include #include #endif //#define DEBUG_PREPROC void transpose (int N, float complex *A, float complex *Result) { // COnputes C := alpha*op(A)*op(B) + beta*C, enum CBLAS_TRANSPOSE transa = CblasTrans; enum CBLAS_TRANSPOSE transb = CblasNoTrans; int rows_opA = N; // number of rows in op(A) and in C int col_opB = N; //number of columns of op(B) and in C int col_opA = N; //number of columns in op(A) and rows in op(B) int col_B; //number of columns in B float complex alpha = 1.0+I*0; int lda = rows_opA; float complex beta = 0.0+I*0; int ldc = rows_opA; int i; float complex* B; int ldb = col_opB; if (transb == CblasNoTrans) { B = (float complex*)calloc(ldb*col_opB,sizeof(float complex)); col_B= col_opB; } else { B = (float complex*)calloc(ldb*col_opA, sizeof(float complex)); col_B = col_opA; } float complex* C = (float complex*)malloc(ldc*col_opB*sizeof(float complex)); for (i=0; i>2)*sizeof(float complex)); float complex *H1_re = malloc(n_rx*(n_tx>>2)*sizeof(float complex)); float complex *R_corr_col_n_0_re = malloc(n_rx*n_tx*sizeof(float complex)); float complex *R_corr_col_n_1_re = malloc(n_rx*n_tx*sizeof(float complex)); float complex *U_0_re = malloc(n_rx*n_tx*sizeof(float complex)); float complex *U_1_re = malloc(n_rx*n_tx*sizeof(float complex)); float complex *U_0_herm_re = malloc(n_rx*n_tx*sizeof(float complex)); float complex *U_1_herm_re = malloc(n_rx*n_tx*sizeof(float complex)); float complex *D_0_re = malloc(n_rx*n_tx*sizeof(float complex)); float complex *D_1_re = malloc(n_rx*n_tx*sizeof(float complex)); float complex *W_Wh_0_re = malloc(n_rx*n_tx*sizeof(float complex)); float complex *W_Wh_1_re = malloc(n_rx*n_tx*sizeof(float complex)); for (aatx=0; aatx>2), H1_re, sigma2, R_corr_col_n_0_re); HH_herm_plus_sigma2I(n_rx, (n_tx>>2), H0_re, sigma2, R_corr_col_n_1_re); eigen_vectors_values(n_rx, R_corr_col_n_0_re, U_0_re, D_0_re); eigen_vectors_values(n_rx, R_corr_col_n_1_re, U_1_re, D_1_re); transpose (n_rx, U_0_re, U_0_herm_re); transpose (n_rx, U_1_re, U_1_herm_re); sigma = (float)(sqrt((double)(sigma2))); /*The inverse of a diagonal matrix is obtained by replacing each element in the diagonal with its reciprocal. A square root of a diagonal matrix is given by the diagonal matrix, whose diagonal entries are just the square roots of the original matrix.*/ D_0_re_inv_sqrt[0] = sqrt_float(1/D_0_re_inv[0]); D_0_re_inv_sqrt[5] = sqrt_float(1/D_0_re_inv[5]); D_0_re_inv_sqrt[10] = sqrt_float(1/D_0_re_inv[10]); D_0_re_inv_sqrt[15] = sqrt_float(1/D_0_re_inv[15]); D_1_re_inv[0] = sqrt_float(1/D_1_re_inv[0]); D_1_re_inv[5] = sqrt_float(1/D_1_re_inv[5]); D_1_re_inv[10] = sqrt_float(1/D_1_re_inv[10]); D_1_re_inv[15] = sqrt_float(1/D_1_re_inv[15]); now only to multiply free(H0); free(H1); free(R_corr_col_n_0); free(R_corr_col_n_1); } #endif float sqrt_float(float x, float sqrt_x) { sqrt_x = (float)(sqrt((double)(x))); return sqrt_x; }