]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ep-processor-libraries/dsplib.git/blob - ti/dsplib/src/DSPF_dp_lud_inv_cmplx/c66/DSPF_dp_lud_inv_cmplx_cn.c
DSPLIB: optimized signal processing functions for TI DSPs
[ep-processor-libraries/dsplib.git] / ti / dsplib / src / DSPF_dp_lud_inv_cmplx / c66 / DSPF_dp_lud_inv_cmplx_cn.c
1 /* ======================================================================= */
2 /* DSPF_dp_lud_inv_cmplx_cn.c - complex matrix inversion by LUD double precision*/
3 /*                 Natural C Implementation                                */
4 /*                                                                         */
5 /* Rev 1.0.0                                                               */
6 /*                                                                         */
7 /* Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/  */
8 /*                                                                         */
9 /*                                                                         */
10 /*  Redistribution and use in source and binary forms, with or without     */
11 /*  modification, are permitted provided that the following conditions     */
12 /*  are met:                                                               */
13 /*                                                                         */
14 /*    Redistributions of source code must retain the above copyright       */
15 /*    notice, this list of conditions and the following disclaimer.        */
16 /*                                                                         */
17 /*    Redistributions in binary form must reproduce the above copyright    */
18 /*    notice, this list of conditions and the following disclaimer in the  */
19 /*    documentation and/or other materials provided with the               */
20 /*    distribution.                                                        */
21 /*                                                                         */
22 /*    Neither the name of Texas Instruments Incorporated nor the names of  */
23 /*    its contributors may be used to endorse or promote products derived  */
24 /*    from this software without specific prior written permission.        */
25 /*                                                                         */
26 /*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS    */
27 /*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT      */
28 /*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR  */
29 /*  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT   */
30 /*  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,  */
31 /*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT       */
32 /*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,  */
33 /*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY  */
34 /*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT    */
35 /*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  */
36 /*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.   */
37 /*                                                                         */
38 /* ======================================================================= */\
39 #include <math.h>
40 #include <string.h>
42 #include "DSPF_dp_lud_inv_cmplx_cn.h"
44 static void complex_dp_div_cn(double x_real,double x_imag,double y_real,
45                               double y_imag,double *z_real,double *z_imag);
47 int DSPF_dp_lud_inverse_cmplx_cn(const int Nrows,unsigned short *P,double *L,
48                                  double *U,double *inv_A) {
50   int row,col,Ncols,k;
51   double factor_real,factor_imag,sum_real,sum_imag;
52   double xreal,ximag,yreal,yimag,zreal,zimag;
53   double *inv_L,*inv_U,*inv_U_x_inv_L;
55   /* set inv_A matrix to identity */
56   inv_L=&inv_A[0];
57   Ncols=2*Nrows;
58   memset(inv_L,0.0,sizeof(double)*Nrows*Ncols);
59   for (row=0;row<Nrows;row++) {
60         inv_L[2*row  +row*Ncols]=1;
61   }
63   /* use Gauss Jordan algorithm to invert L whose result is in inv_L */
64   for (col=0;col<Nrows-1;col++) {
65     for (row=col+1;row<Nrows;row++) {
66       xreal=L[2*col  +row*Ncols];
67       ximag=L[2*col+1+row*Ncols];
68       yreal=L[2*col  +col*Ncols];
69       yimag=L[2*col+1+col*Ncols];
70       complex_dp_div_cn(xreal,ximag,yreal,yimag,&zreal,&zimag);
71       factor_real=zreal;
72       factor_imag=zimag;
73           for (k=0;k<Nrows;k++) {
74                 xreal=factor_real;
75                 ximag=factor_imag;
76                 yreal=inv_L[2*k  +col*Ncols];
77                 yimag=inv_L[2*k+1+col*Ncols];
78                 inv_L[2*k  +row*Ncols]-=xreal*yreal-ximag*yimag;
79                 inv_L[2*k+1+row*Ncols]-=xreal*yimag+ximag*yreal;
80                 xreal=factor_real;
81                 ximag=factor_imag;
82                 yreal=L[2*k  +col*Ncols];
83                 yimag=L[2*k+1+col*Ncols];
84                 L[2*k  +row*Ncols]-=xreal*yreal-ximag*yimag;
85                 L[2*k+1+row*Ncols]-=xreal*yimag+ximag*yreal;
86           }
87         }
88   }
90   /* set inv_U matrix to identity */
91   inv_U=&L[0];
92   memset(inv_U,0.0,sizeof(double)*Nrows*Ncols);
93   for (row=0;row<Nrows;row++) {
94         inv_U[2*row  +row*Ncols]=1;
95   }
97   /* use Gauss Jordan algorithm to invert U whose result is in L */
98   for (col=Nrows-1;col>=1;col--) {
99         for (row=col-1;row>=0;row--) {
100       xreal=U[2*col  +row*Ncols];
101       ximag=U[2*col+1+row*Ncols];
102       yreal=U[2*col  +col*Ncols];
103       yimag=U[2*col+1+col*Ncols];
104       complex_dp_div_cn(xreal,ximag,yreal,yimag,&zreal,&zimag);
105       factor_real=zreal;
106       factor_imag=zimag;
107           for (k=0;k<Nrows;k++) {
108                 xreal=factor_real;
109                 ximag=factor_imag;
110                 yreal=inv_U[2*k  +col*Ncols];
111                 yimag=inv_U[2*k+1+col*Ncols];
112                 complex_dp_div_cn(xreal,ximag,yreal,yimag,&zreal,&zimag);
113                 inv_U[2*k  +row*Ncols]-=xreal*yreal-ximag*yimag;
114                 inv_U[2*k+1+row*Ncols]-=xreal*yimag+ximag*yreal;
115                 xreal=factor_real;
116                 ximag=factor_imag;
117                 yreal=U[2*k  +col*Ncols];
118                 yimag=U[2*k+1+col*Ncols];
119                 U[2*k  +row*Ncols]-=xreal*yreal-ximag*yimag;
120                 U[2*k+1+row*Ncols]-=xreal*yimag+ximag*yreal;
121           }
122         }
123   }
125   /* scale U & L to get identity matrix in U */
126   for (row=Nrows-1;row>=0;row--) {
127         factor_real=U[2*row  +row*Ncols];
128         factor_imag=U[2*row+1+row*Ncols];
129         for (col=0;col<Nrows;col++) {
130       xreal=L[2*col  +row*Ncols];
131       ximag=L[2*col+1+row*Ncols];
132       yreal=factor_real;
133       yimag=factor_imag;
134       complex_dp_div_cn(xreal,ximag,yreal,yimag,&zreal,&zimag);
135       L[2*col  +row*Ncols]=zreal;
136       L[2*col+1+row*Ncols]=zimag;
137       xreal=U[2*col  +row*Nrows];
138       ximag=U[2*col+1+row*Nrows];
139       yreal=factor_real;
140       yimag=factor_imag;
141       complex_dp_div_cn(xreal,ximag,yreal,yimag,&zreal,&zimag);
142       U[2*col  +row*Ncols]=zreal;
143       U[2*col+1+row*Ncols]=zimag;
144         }
145   }
147   /* compute inv_U_x_inv_L=inv(U)*inv(L) */
148   inv_U_x_inv_L=&L[0];
149   for (row=0;row<Nrows;row++) {
150     for (col=0;col<Nrows;col++) {
151     sum_real=0;
152     sum_imag=0;
153         for (k=0;k<Nrows;k++) {
154           xreal=inv_U[2*k  +row*Ncols];
155           ximag=inv_U[2*k+1+row*Ncols];
156           yreal=inv_L[2*col  +k*Ncols];
157           yimag=inv_L[2*col+1+k*Ncols];
158           sum_real+=xreal*yreal-ximag*yimag;
159           sum_imag+=xreal*yimag+ximag*yreal;
160         }
161         inv_U_x_inv_L[2*col  +row*Ncols]=sum_real;
162         inv_U_x_inv_L[2*col+1+row*Ncols]=sum_imag;
163     }
164   }
165   /* compute inv_A=inv(U)*inv(L)*P */
166   for (row=0;row<Nrows;row++) {
167     for (col=0;col<Nrows;col++) {
168     sum_real=0;
169     sum_imag=0;
170         for (k=0;k<Nrows;k++) {
171           xreal=inv_U_x_inv_L[2*k  +row*Ncols];
172           ximag=inv_U_x_inv_L[2*k+1+row*Ncols];
173           yreal=P[col+k*Nrows];
174           sum_real+=xreal*yreal;
175           sum_imag+=ximag*yreal;
176         }
177     inv_A[2*col  +row*Ncols]=sum_real;
178     inv_A[2*col+1+row*Ncols]=sum_imag;
179     }
180   }
182   return 0;
185 void complex_dp_div_cn(double x_real,double x_imag,double y_real,double y_imag,double *z_real,double *z_imag) {
187   double x_mag,y_mag,z_mag;
188   double x_angle,y_angle,z_angle;
190   /* magnitude */
191   x_mag=sqrt(x_real*x_real+x_imag*x_imag);
192   y_mag=sqrt(y_real*y_real+y_imag*y_imag);
193   z_mag=x_mag/y_mag;
195   /* angle */
196   x_angle=atan2(x_imag,x_real);
197   y_angle=atan2(y_imag,y_real);
198   z_angle=x_angle-y_angle;
200   /* results */
201   *z_real=cos(z_angle)*z_mag;
202   *z_imag=sin(z_angle)*z_mag;
206 /* ======================================================================= */
207 /*  End of file:  DSPF_dp_lud_inv_cmplx_cn.c                               */
208 /* ----------------------------------------------------------------------- */
209 /*            Copyright (c) 2013 Texas Instruments, Incorporated.          */
210 /*                           All Rights Reserved.                          */
211 /* ======================================================================= */