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