PLASMA  2.4.5
PLASMA - Parallel Linear Algebra for Scalable Multi-core Architectures
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
testing_zheevd.c
Go to the documentation of this file.
1 
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <math.h>
19 
20 #include <plasma.h>
21 #include <cblas.h>
22 #include <lapacke.h>
23 #include <core_blas.h>
24 #include "testing_zmain.h"
25 
26 #undef REAL
27 #define COMPLEX
28 
29 static int check_orthogonality(int, int, PLASMA_Complex64_t*, int, double);
30 #if 0
31 static int check_reduction(int, int, int, PLASMA_Complex64_t*, PLASMA_Complex64_t*, int, PLASMA_Complex64_t*, double);
32 #endif
33 static int check_solution(int, double*, double*, double);
34 
35 int testing_zheevd(int argc, char **argv)
36 {
37  /* Check for number of arguments*/
38  if (argc != 2) {
39  USAGE("HEEVD", "N LDA",
40  " - N : size of the matrix A\n"
41  " - LDA : leading dimension of the matrix A\n");
42  return -1;
43  }
44 
45  int N = atoi(argv[0]);
46  int LDA = atoi(argv[1]);
47  int LDQ = LDA;
48  int mode = 4;
49  double eps = LAPACKE_dlamch_work('e');
50  double dmax = 1.0;
51  double rcond = 1.0e6;
52 
54  PLASMA_enum vec = PlasmaVec;
55  int info_ortho = 0;
56  int info_solution = 0;
57  int info_reduction = 0;
58  int i;
59  int LDAxN = LDA*N;
60  int LDQxN = LDQ*N;
61 
62  PLASMA_Complex64_t *A1 = NULL;
63  PLASMA_Complex64_t *A2 = (PLASMA_Complex64_t *)malloc(LDAxN*sizeof(PLASMA_Complex64_t));
64  PLASMA_Complex64_t *Q = NULL;
65  double *W1 = (double *)malloc(N*sizeof(double));
66  double *W2 = (double *)malloc(N*sizeof(double));
67  PLASMA_Complex64_t *work = (PLASMA_Complex64_t *)malloc(3*N* sizeof(PLASMA_Complex64_t));
68  PLASMA_desc *T;
69 
70  /* Check if unable to allocate memory */
71  if ( !A2 ){
72  printf("Out of Memory \n ");
73  return -2;
74  }
75 
76  /*
77  PLASMA_Disable(PLASMA_AUTOTUNING);
78  PLASMA_Set(PLASMA_TILE_SIZE, 5);
79  PLASMA_Set(PLASMA_INNER_BLOCK_SIZE, 5);
80  */
81 
83 
84  /*----------------------------------------------------------
85  * TESTING ZHEEVD
86  */
87 
88  /* Initialize A1 */
89  LAPACKE_zlatms_work( LAPACK_COL_MAJOR, N, N,
91  lapack_const(PlasmaHermGeev), W1, mode, rcond,
92  dmax, N-1, N-1,
93  lapack_const(PlasmaNoPacking), A2, LDA, work );
94 
95  /*
96  * Sort the eigenvalue because when computing the tridiag
97  * and then the eigenvalue of the DSTQR are sorted.
98  * So to avoid testing fail when having good results W1 should be sorted
99  */
100  LAPACKE_dlasrt_work( 'I', N, W1 );
101 
102  if (getenv("PLASMA_TESTING_VERBOSE"))
103  {
104  printf("Eigenvalues original\n");
105  for (i = 0; i < min(N,25); i++){
106  printf("%f \n", W1[i]);
107  }
108  printf("\n");
109  }
110 
111  if ( vec == PlasmaVec ) {
112  Q = (PLASMA_Complex64_t *)malloc(LDQxN*sizeof(PLASMA_Complex64_t));
113  A1 = (PLASMA_Complex64_t *)malloc(LDAxN*sizeof(PLASMA_Complex64_t));
114 
115  /* Copy A2 into A1 */
116  LAPACKE_zlacpy_work(LAPACK_COL_MAJOR, 'A', N, N, A2, LDA, A1, LDA);
117  }
118 
119  /* PLASMA ZHEEVD */
120  PLASMA_zheevd(vec, uplo, N, A2, LDA, W2, T, Q, LDQ);
121 
122  if (getenv("PLASMA_TESTING_VERBOSE"))
123  {
124  printf("Eigenvalues computed\n");
125  for (i = 0; i < min(N,25); i++){
126  printf("%f \n", W2[i]);
127  }
128  printf("\n");
129  }
130 
131  printf("\n");
132  printf("------ TESTS FOR PLASMA ZHEEVD ROUTINE ------- \n");
133  printf(" Size of the Matrix %d by %d\n", N, N);
134  printf("\n");
135  printf(" The matrix A is randomly generated for each test.\n");
136  printf("============\n");
137  printf(" The relative machine precision (eps) is to be %e \n",eps);
138  printf(" Computational tests pass if scaled residuals are less than 60.\n");
139 
140  /* Check the orthogonality, reduction and the eigen solutions */
141  if (vec == PlasmaVec) {
142  info_ortho = check_orthogonality(N, N, Q, LDQ, eps);
143  /*
144  * WARNING: For now, Q is associated to Band tridiagonal reduction and
145  * not to the final tridiagonal reduction, so we can not call the check
146  */
147  /*info_reduction = check_reduction(uplo, N, 1, A1, A2, LDA, Q, eps);*/
148  }
149  info_solution = check_solution(N, W1, W2, eps);
150 
151  if ( (info_solution == 0) & (info_ortho == 0) & (info_reduction == 0) ) {
152  printf("***************************************************\n");
153  printf(" ---- TESTING ZHEEVD ...................... PASSED !\n");
154  printf("***************************************************\n");
155  }
156  else {
157  printf("************************************************\n");
158  printf(" - TESTING ZHEEVD ... FAILED !\n");
159  printf("************************************************\n");
160  }
161 
162  free(A2);
163  free(W1);
164  free(W2);
165  free(work);
167  if (Q != NULL) free(Q);
168  if (A1 != NULL) free(A1);
169 
170  return 0;
171 }
172 
173 /*-------------------------------------------------------------------
174  * Check the orthogonality of Q
175  */
176 
177 static int check_orthogonality(int M, int N, PLASMA_Complex64_t *Q, int LDQ, double eps)
178 {
179  double alpha = 1.0;
180  double beta = -1.0;
181  double normQ, result;
182  int info_ortho;
183  int minMN = min(M, N);
184  double *work = (double *)malloc(minMN*sizeof(double));
185 
186  /* Build the idendity matrix */
187  PLASMA_Complex64_t *Id = (PLASMA_Complex64_t *) malloc(minMN*minMN*sizeof(PLASMA_Complex64_t));
188  LAPACKE_zlaset_work(LAPACK_COL_MAJOR, 'A', minMN, minMN, 0., 1., Id, minMN);
189 
190  /* Perform Id - Q'Q */
191  if (M >= N)
192  cblas_zherk(CblasColMajor, CblasUpper, CblasConjTrans, N, M, alpha, Q, LDQ, beta, Id, N);
193  else
194  cblas_zherk(CblasColMajor, CblasUpper, CblasNoTrans, M, N, alpha, Q, LDQ, beta, Id, M);
195 
196  normQ = LAPACKE_zlansy_work(LAPACK_COL_MAJOR, lapack_const(PlasmaInfNorm), 'U', minMN, Id, minMN, work);
197 
198  result = normQ / (minMN * eps);
199  printf("============\n");
200  printf("Checking the orthogonality of Q \n");
201  printf("||Id-Q'*Q||_oo / (minMN*eps) = %e \n", result);
202 
203  if ( isnan(result) || isinf(result) || (result > 60.0) ) {
204  printf("-- Orthogonality is suspicious ! \n");
205  info_ortho=1;
206  }
207  else {
208  printf("-- Orthogonality is CORRECT ! \n");
209  info_ortho=0;
210  }
211 
212  free(work); free(Id);
213 
214  return info_ortho;
215 }
216 
217 /*------------------------------------------------------------
218  * Check the reduction
219  */
220 #if 0
221 static int check_reduction(int uplo, int N, int bw, PLASMA_Complex64_t *A1, PLASMA_Complex64_t *A2, int LDA, PLASMA_Complex64_t *Q, double eps )
222 {
223  PLASMA_Complex64_t alpha = 1.0;
224  PLASMA_Complex64_t beta = 0.0;
225  double Anorm, Rnorm, result;
226  int info_reduction;
227  int i, j;
228 
229  PLASMA_Complex64_t *Aorig = (PLASMA_Complex64_t *)malloc(N*N*sizeof(PLASMA_Complex64_t));
230  PLASMA_Complex64_t *Residual = (PLASMA_Complex64_t *)malloc(N*N*sizeof(PLASMA_Complex64_t));
231  PLASMA_Complex64_t *T = (PLASMA_Complex64_t *)malloc(N*N*sizeof(PLASMA_Complex64_t));
232  double *work = (double *)malloc(N*sizeof(double));
233 
234  memset((void*)T, 0, N*N*sizeof(PLASMA_Complex64_t));
235 
236  /* Rebuild the T */
237  LAPACKE_zlacpy_work(LAPACK_COL_MAJOR, lapack_const(uplo), N, N, A2, LDA, T, N);
238 
239  printf("============\n");
240  printf("Checking the tridiagonal reduction \n");
241 
242  if (uplo == PlasmaLower)
243  {
244  /* Copy the lower part to the upper part to rebuild the hermitian/symmetry */
245  for (i = 0; i < N; i++)
246  for (j = max(0, i-bw); j < i; j++)
247  T[i*N+j] = conj(T[j*N+i]);
248 
249  /* Compute Aorig = Q * T * Q^H */
250  memset((void*)Aorig, 0, N*N*sizeof(PLASMA_Complex64_t));
251  cblas_zgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, N, N, N, CBLAS_SADDR(alpha), Q, LDA, T, N, CBLAS_SADDR(beta), Aorig, N);
252  cblas_zgemm(CblasColMajor, CblasNoTrans, CblasConjTrans, N, N, N, CBLAS_SADDR(alpha), Aorig, N, Q, LDA, CBLAS_SADDR(beta), T, N);
253  }
254  else
255  {
256  /* Copy the upper part to the lower part to rebuild the symmetry */
257  for (i = 0; i < N; i++)
258  for (j = i+1 ; j < min(i+bw, N); j++)
259  T[i*N+j] = conj(T[j*N+i]);
260 
261  /* Compute Aorig = Q^H * T * Q */
262  memset((void*)Aorig, 0, N*N*sizeof(PLASMA_Complex64_t));
263  cblas_zgemm(CblasColMajor, CblasConjTrans, CblasNoTrans, N, N, N, CBLAS_SADDR(alpha), Q, LDA, T, N, CBLAS_SADDR(beta), Aorig, N);
264  cblas_zgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, N, N, N, CBLAS_SADDR(alpha), Aorig, N, Q, LDA, CBLAS_SADDR(beta), T, N);
265  }
266 
267  /* Compute the Residual */
268  for (i = 0; i < N; i++)
269  for (j = 0 ; j < N; j++)
270  Residual[j*N+i] = A1[j*LDA+i] - T[j*N+i];
271 
272  Rnorm = LAPACKE_zlange_work(LAPACK_COL_MAJOR, lapack_const(PlasmaInfNorm), N, N, Residual, N, work);
273  Anorm = LAPACKE_zlange_work(LAPACK_COL_MAJOR, lapack_const(PlasmaInfNorm), N, N, A2, LDA, work);
274 
275  result = Rnorm / ( Anorm * N * eps);
276  if ( uplo == PlasmaLower )
277  printf("-- ||A-Q*T*Q'||_oo/(||A||_oo.N.eps) = %e \n", result);
278  else
279  printf("-- ||A-Q'*T*Q||_oo/(||A||_oo.N.eps) = %e \n", result);
280 
281  if ( isnan(result) || isinf(result) || (result > 60.0) ) {
282  printf("-- Reduction is suspicious ! \n");
283  info_reduction = 1;
284  }
285  else {
286  printf("-- Reduction is CORRECT ! \n");
287  info_reduction = 0;
288  }
289 
290  free(Aorig); free(Residual); free(T);
291 
292  return info_reduction;
293 }
294 #endif
295 
296 static int check_solution(int N, double *E1, double *E2, double eps)
297 {
298  int info_solution, i;
299  double resid;
300  double maxtmp;
301  double maxel = fabs( fabs(E1[0]) - fabs(E2[0]) );
302  double maxeig = max( fabs(E1[0]), fabs(E2[0]) );
303  for (i = 1; i < N; i++){
304  resid = fabs(fabs(E1[i])-fabs(E2[i]));
305  maxtmp = max(fabs(E1[i]), fabs(E2[i]));
306 
307  /* Update */
308  maxeig = max(maxtmp, maxeig);
309  maxel = max(resid, maxel );
310  }
311 
312  maxel = maxel / (maxeig * N * eps);
313  printf(" ======================================================\n");
314  printf(" | D - eigcomputed | / (|D| * N * eps) : %15.3E \n", maxel );
315  printf(" ======================================================\n");
316 
317  printf("============\n");
318  printf("Checking the eigenvalues of A\n");
319  if ( isnan(maxel) || isinf(maxel) || (maxel > 100) ) {
320  printf("-- The eigenvalues are suspicious ! \n");
321  info_solution = 1;
322  }
323  else{
324  printf("-- The eigenvalues are CORRECT ! \n");
325  info_solution = 0;
326  }
327 
328  return info_solution;
329 }