accelerInt  v0.1
complexInverse.c
Go to the documentation of this file.
1 
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <math.h>
11 #include <float.h>
12 #include <complex.h>
13 #include <string.h>
14 #include "solver_props.h"
15 #include "lapack_dfns.h"
16 
34 static inline
35 int getHessenbergLU(const int n, double complex* __restrict__ A,
36  int* __restrict__ indPivot)
37 {
38  int last_pivot = 0;
39  for (int i = 0; i < n - 1; i ++)
40  {
41  if (cabs(A[i * STRIDE + i]) < cabs(A[i * STRIDE + i + 1]))
42  {
43  //swap rows
44  for(int k = last_pivot; k < n; ++k)
45  {
46  double complex temp = A[k * STRIDE + i];
47  A[k * STRIDE + i] = A[k * STRIDE + i + 1];
48  A[k * STRIDE + i + 1] = temp;
49  }
50  indPivot[i] = i + 1;
51  }
52  else
53  {
54  indPivot[i] = i;
55  last_pivot = i;
56  }
57  if (cabs(A[i * STRIDE + i]) > 0.0)
58  {
59  double complex tau = A[i * STRIDE + i + 1] / A[i * STRIDE + i];
60  for (int j = i + 1; j < n; j++)
61  {
62  A[j * STRIDE + i + 1] -= tau * A[j * STRIDE + i];
63  }
64  A[i * STRIDE + i + 1] = tau;
65  }
66  else
67  {
68  return i;
69  }
70  }
71  //last index is not pivoted
72  indPivot[n - 1] = n - 1;
73  return 0;
74 }
75 
83 void scaleComplex (const int n, const double complex val, double complex* __restrict__ arrX) {
84 
85  for (int i = 0; i < n; ++i) {
86  arrX[i] *= val;
87  }
88 
89 }
90 
108 void multiplyComplexUpperMV (const int n, double complex* x, const int lda,
109  const double complex* A) {
110 
111  for (int j = 0; j < n; ++j) {
112  if (cabs(x[j]) > 0.0) {
113  double complex temp = x[j];
114  for (int i = 0; i < j; ++i) {
115  x[i] += temp * A[i + (lda * j)];
116  //x[INDEX(i)] = cuCfma(temp, A[INDEX(i + (lda * j))], x[INDEX(i)]);
117  }
118  x[j] *= A[j + (lda * j)];
119  //x[INDEX(j)] = cuCmul(x[INDEX(j)], A[INDEX(j + (lda * j))]);
120  }
121  }
122 
123 }
124 
126 
146 void complexGEMV (const int m, const int n, const int lda, const double alpha, const double complex* __restrict__ A,
147  const double complex* arrX, double complex* arrY) {
148 
149  // first: y = beta*y
150  // beta = 1, so nothing
151 
152  // second: y = alpha*A*x + y
153 
154  for (int j = 0; j < n - 1; ++j) {
155 
156  if (cabs(arrX[j]) > 0.0) {
157  double complex temp = alpha * arrX[j];
158  for (int i = 0; i < m; ++i) {
159  arrY[i] += temp * A[i + (lda * j)];
160  //arrY[INDEX(i)] = cuCfma(temp, A[INDEX(i + (lda * j))], arrY[INDEX(i)]);
161  }
162  }
163  }
164 }
165 
178 int getComplexInverseHessenbergLU (const int n, double complex* __restrict__ A,
179  const int* __restrict__ indPivot) {
180 
181  double complex work[STRIDE] = {0};
182 
183  // form inv(U)
184  for (int j = 0; j < n; ++j) {
185  if (cabs(A[j + (STRIDE * j)]) == 0)
186  return j;
187  A[j + (STRIDE * j)] = 1.0 / A[j + (STRIDE * j)];
188  double complex Ajj = -A[j + (STRIDE * j)];
189 
190  // compute elements 0:j-1 of jth column
191  multiplyComplexUpperMV (j, &A[STRIDE * j], STRIDE, A);
192 
193  // scale
194  scaleComplex (j, Ajj, &A[STRIDE * j]);
195  }
196 
197  // solve equation inv(A)*L = inv(U) for inv(A)
198 
199  for (int j = n - 1; j >= 0; --j) {
200 
201  // copy current column of L to work and replace with 0.0s
202  for (int i = j + 1; i < n; ++i) {
203  work[i] = A[i + STRIDE * j];
204  A[i + (STRIDE * j)] = 0;
205  }
206 
207  // compute current column of inv(A)
208  if (j < n - 1)
209  complexGEMV (n, n - j, STRIDE, -1, &A[STRIDE * (j + 1)], &work[j + 1], &A[STRIDE * j]);
210 
211  }
212 
213  // apply column interchanges
214 
215  for (int j = n - 2; j >= 0; --j) {
216 
217  if (indPivot[j] != j)
218  {
219  for (int i = 0; i < n; ++i) {
220  double complex temp = A[STRIDE * j + i];
221  A[STRIDE * j + i] = A[STRIDE * indPivot[j] + i];
222  A[STRIDE * indPivot[j] + i] = temp;
223  }
224  }
225  }
226  return 0;
227 }
228 
238 void getComplexInverseHessenberg (const int n, double complex* __restrict__ A,
239  int* __restrict__ ipiv, int* __restrict__ info)
240 {
241  // first get LU factorization
242  *info = getHessenbergLU (n, A, ipiv);
243 
244  if (*info != 0)
245  return;
246 
247  // now get inverse
248  *info = getComplexInverseHessenbergLU(n, A, ipiv);
249 }
void getComplexInverseHessenberg(const int n, double complex *__restrict__ A, int *__restrict__ ipiv, int *__restrict__ info)
getComplexInverseHessenberg computes the inverse of an upper Hessenberg matrix A using a LU factoriza...
int getComplexInverseHessenbergLU(const int n, double complex *__restrict__ A, const int *__restrict__ indPivot)
getComplexInverseHessenbergLU computes the inverse of a matrix using the LU factorization computed by...
#define STRIDE
the matrix dimensions
void multiplyComplexUpperMV(const int n, double complex *x, const int lda, const double complex *A)
Performs the matrix-vector operation .
External lapack routine definitions.
simple convenience file to include the correct solver properties file
void complexGEMV(const int m, const int n, const int lda, const double alpha, const double complex *__restrict__ A, const double complex *arrX, double complex *arrY)
Computes the matrix-vector operation where alpha is a scalar, x and y are vectors and A is an m by n...
void scaleComplex(const int n, const double complex val, double complex *__restrict__ arrX)
scaleComplex scales a vector (with increment equal to one) by a constant val.
static int getHessenbergLU(const int n, double complex *__restrict__ A, int *__restrict__ indPivot)
Computes the LU factorization of a (n x STRIDE) Hessenberg Matrix using partial pivoting with row int...