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_dgesv.c
Go to the documentation of this file.
1 
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <math.h>
21 
22 #include <plasma.h>
23 #include <cblas.h>
24 #include <lapacke.h>
25 #include <core_blas.h>
26 #include "testing_dmain.h"
27 
30  blas_colmajor = 102 };
31 
33  blas_base = 151,
34  blas_t = 152,
35  blas_rnd = 153,
36  blas_ieee = 154,
37  blas_emin = 155,
38  blas_emax = 156,
39  blas_eps = 157,
40  blas_prec = 158,
43  blas_sfmin = 161};
44 
54 
55 static void
56 BLAS_error(char *rname, int err, int val, int x) {
57  fprintf( stderr, "%s %d %d %d\n", rname, err, val, x );
58  abort();
59 }
60 
61 static
62 void
63 BLAS_dge_norm(enum blas_order_type order, enum blas_norm_type norm,
64  int m, int n, const double *a, int lda, double *res) {
65  int i, j; float anorm, v;
66  char rname[] = "BLAS_dge_norm";
67 
68  if (order != blas_colmajor) BLAS_error( rname, -1, order, 0 );
69 
70  if (norm == blas_frobenius_norm) {
71  anorm = 0.0f;
72  for (j = n; j; --j) {
73  for (i = m; i; --i) {
74  v = a[0];
75  anorm += v * v;
76  a++;
77  }
78  a += lda - m;
79  }
80  anorm = sqrt( anorm );
81  } else if (norm == blas_inf_norm) {
82  anorm = 0.0f;
83  for (i = 0; i < m; ++i) {
84  v = 0.0f;
85  for (j = 0; j < n; ++j) {
86  v += fabs( a[i + j * lda] );
87  }
88  if (v > anorm)
89  anorm = v;
90  }
91  } else {
92  BLAS_error( rname, -2, norm, 0 );
93  return;
94  }
95 
96  if (res) *res = anorm;
97 }
98 
99 static
100 double
101 BLAS_dpow_di(double x, int n) {
102  double rv = 1.0;
103 
104  if (n < 0) {
105  n = -n;
106  x = 1.0 / x;
107  }
108 
109  for (; n; n >>= 1, x *= x) {
110  if (n & 1)
111  rv *= x;
112  }
113 
114  return rv;
115 }
116 
117 static
118 double
119 BLAS_dfpinfo(enum blas_cmach_type cmach) {
120  double eps = 1.0, r = 1.0, o = 1.0, b = 2.0;
121  int t = 53, l = 1024, m = -1021;
122  char rname[] = "BLAS_dfpinfo";
123 
124  if ((sizeof eps) == sizeof(float)) {
125  t = 24;
126  l = 128;
127  m = -125;
128  } else {
129  t = 53;
130  l = 1024;
131  m = -1021;
132  }
133 
134  /* for (i = 0; i < t; ++i) eps *= half; */
135  eps = BLAS_dpow_di( b, -t );
136  /* for (i = 0; i >= m; --i) r *= half; */
137  r = BLAS_dpow_di( b, m-1 );
138 
139  o -= eps;
140  /* for (i = 0; i < l; ++i) o *= b; */
141  o = (o * BLAS_dpow_di( b, l-1 )) * b;
142 
143  switch (cmach) {
144  case blas_eps: return eps;
145  case blas_sfmin: return r;
146  default:
147  BLAS_error( rname, -1, cmach, 0 );
148  break;
149  }
150  return 0.0;
151 }
152 
153 static int check_solution(int, int , double *, int, double *, double *, int, double);
154 
155 int testing_dgesv(int argc, char **argv)
156 {
157  /* Check for valid arguments*/
158  if (argc != 4){
159  USAGE("GESV", "N LDA NRHS LDB",
160  " - N : the size of the matrix\n"
161  " - LDA : leading dimension of the matrix A\n"
162  " - NRHS : number of RHS\n"
163  " - LDB : leading dimension of the matrix B\n");
164  return -1;
165  }
166 
167  int N = atoi(argv[0]);
168  int LDA = atoi(argv[1]);
169  int NRHS = atoi(argv[2]);
170  int LDB = atoi(argv[3]);
171  double eps;
172  int info_solution;
173  int i,j;
174  int LDAxN = LDA*N;
175  int LDBxNRHS = LDB*NRHS;
176 
177  double *A1 = (double *)malloc(LDA*N *sizeof(double));
178  double *A2 = (double *)malloc(LDA*N *sizeof(double));
179  double *B1 = (double *)malloc(LDB*NRHS*sizeof(double));
180  double *B2 = (double *)malloc(LDB*NRHS*sizeof(double));
181  int *IPIV = (int *)malloc(N*sizeof(int));
182 
183  /* Check if unable to allocate memory */
184  if ( (!A1) || (!A2)|| (!B1) || (!B2) || (!IPIV) ) {
185  printf("Out of Memory \n ");
186  return -2;
187  }
188 
189  eps = BLAS_dfpinfo(blas_eps);
190 
191  /*----------------------------------------------------------
192  * TESTING DGESV
193  */
194 
195  /* Initialize A1 and A2 Matrix */
196  LAPACKE_dlarnv_work(IONE, ISEED, LDAxN, A1);
197  for ( i = 0; i < N; i++)
198  for ( j = 0; j < N; j++)
199  A2[LDA*j+i] = A1[LDA*j+i];
200 
201  /* Initialize B1 and B2 */
202  LAPACKE_dlarnv_work(IONE, ISEED, LDBxNRHS, B1);
203  for ( i = 0; i < N; i++)
204  for ( j = 0; j < NRHS; j++)
205  B2[LDB*j+i] = B1[LDB*j+i];
206 
207  /* PLASMA DGESV */
208  PLASMA_dgesv(N, NRHS, A2, LDA, IPIV, B2, LDB);
209 
210  printf("\n");
211  printf("------ TESTS FOR PLASMA DGESV ROUTINE ------- \n");
212  printf(" Size of the Matrix %d by %d\n", N, N);
213  printf("\n");
214  printf(" The matrix A is randomly generated for each test.\n");
215  printf("============\n");
216  printf(" The relative machine precision (eps) is to be %e \n", eps);
217  printf(" Computational tests pass if scaled residuals are less than 60.\n");
218 
219  /* Check the factorization and the solution */
220  info_solution = check_solution(N, NRHS, A1, LDA, B1, B2, LDB, eps);
221 
222  if ((info_solution == 0)){
223  printf("***************************************************\n");
224  printf(" ---- TESTING DGESV ...................... PASSED !\n");
225  printf("***************************************************\n");
226  }
227  else{
228  printf("************************************************\n");
229  printf(" - TESTING DGESV ... FAILED !\n");
230  printf("************************************************\n");
231  }
232 
233  /*-------------------------------------------------------------
234  * TESTING DGETRF + DGETRS
235  */
236 
237  /* Initialize A1 and A2 */
238  LAPACKE_dlarnv_work(IONE, ISEED, LDAxN, A1);
239  for ( i = 0; i < N; i++)
240  for ( j = 0; j < N; j++)
241  A2[LDA*j+i] = A1[LDA*j+i];
242 
243  /* Initialize B1 and B2 */
244  LAPACKE_dlarnv_work(IONE, ISEED, LDBxNRHS, B1);
245  for ( i = 0; i < N; i++)
246  for ( j = 0; j < NRHS; j++)
247  B2[LDB*j+i] = B1[LDB*j+i];
248 
249  /* Plasma routines */
250  PLASMA_dgetrf(N, N, A2, LDA, IPIV);
251  PLASMA_dgetrs(PlasmaNoTrans, N, NRHS, A2, LDA, IPIV, B2, LDB);
252 
253  printf("\n");
254  printf("------ TESTS FOR PLASMA DGETRF + DGETRS ROUTINE ------- \n");
255  printf(" Size of the Matrix %d by %d\n", N, N);
256  printf("\n");
257  printf(" The matrix A is randomly generated for each test.\n");
258  printf("============\n");
259  printf(" The relative machine precision (eps) is to be %e \n", eps);
260  printf(" Computational tests pass if scaled residuals are less than 60.\n");
261 
262  /* Check the solution */
263  info_solution = check_solution(N, NRHS, A1, LDA, B1, B2, LDB, eps);
264 
265  if ((info_solution == 0)){
266  printf("***************************************************\n");
267  printf(" ---- TESTING DGETRF + DGETRS ............ PASSED !\n");
268  printf("***************************************************\n");
269  }
270  else{
271  printf("***************************************************\n");
272  printf(" - TESTING DGETRF + DGETRS ... FAILED !\n");
273  printf("***************************************************\n");
274  }
275 
276  /*-------------------------------------------------------------
277  * TESTING DGETRF + DTRSMPL + DTRSM
278  */
279 
280  /* Initialize A1 and A2 */
281  LAPACKE_dlarnv_work(IONE, ISEED, LDAxN, A1);
282  for ( i = 0; i < N; i++)
283  for ( j = 0; j < N; j++)
284  A2[LDA*j+i] = A1[LDA*j+i];
285 
286  /* Initialize B1 and B2 */
287  LAPACKE_dlarnv_work(IONE, ISEED, LDBxNRHS, B1);
288  for ( i = 0; i < N; i++)
289  for ( j = 0; j < NRHS; j++)
290  B2[LDB*j+i] = B1[LDB*j+i];
291 
292  /* PLASMA routines */
293  PLASMA_dgetrf(N, N, A2, LDA, IPIV);
294  PLASMA_dlaswp(NRHS, B2, LDB, 1, N, IPIV, 1);
296  N, NRHS, 1.0, A2, LDA, B2, LDB);
298  N, NRHS, 1.0, A2, LDA, B2, LDB);
299 
300  printf("\n");
301  printf("------ TESTS FOR PLASMA DGETRF + DLASWP + DTRSM + DTRSM ROUTINE ------- \n");
302  printf(" Size of the Matrix %d by %d\n", N, N);
303  printf("\n");
304  printf(" The matrix A is randomly generated for each test.\n");
305  printf("============\n");
306  printf(" The relative machine precision (eps) is to be %e \n", eps);
307  printf(" Computational tests pass if scaled residuals are less than 60.\n");
308 
309  /* Check the solution */
310  info_solution = check_solution(N, NRHS, A1, LDA, B1, B2, LDB, eps);
311 
312  if ((info_solution == 0)){
313  printf("***************************************************\n");
314  printf(" ---- TESTING DGETRF + DLASWP + DTRSM + DTRSM ... PASSED !\n");
315  printf("***************************************************\n");
316  }
317  else{
318  printf("**************************************************\n");
319  printf(" - TESTING DGETRF + DLASWP + DTRSM + DTRSM ... FAILED !\n");
320  printf("**************************************************\n");
321  }
322 
323  free(A1); free(A2); free(B1); free(B2); free(IPIV);
324 
325  return 0;
326 }
327 
328 /*------------------------------------------------------------------------
329  * Check the accuracy of the solution of the linear system
330  */
331 
332 static int check_solution(int N, int NRHS, double *A1, int LDA, double *B1, double *B2, int LDB, double eps )
333 {
334  int info_solution;
335  double Rnorm, Anorm, Xnorm, Bnorm, result;
336  double alpha, beta;
337  double *work = (double *)malloc(N*sizeof(double));
338 
339  alpha = 1.0;
340  beta = -1.0;
341 
342  BLAS_dge_norm( blas_colmajor, blas_inf_norm, N, NRHS, B2, LDB, &Xnorm );
343  BLAS_dge_norm( blas_colmajor, blas_inf_norm, N, N, A1, LDA, &Anorm );
344  BLAS_dge_norm( blas_colmajor, blas_inf_norm, N, NRHS, B1, LDB, &Bnorm );
345 
346  cblas_dgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, N, NRHS, N, (alpha), A1, LDA, B2, LDB, (beta), B1, LDB);
347  BLAS_dge_norm( blas_colmajor, blas_inf_norm, N, NRHS, B1, LDB, &Rnorm );
348 
349  if (getenv("PLASMA_TESTING_VERBOSE"))
350  printf( "||A||_oo=%f\n||X||_oo=%f\n||B||_oo=%f\n||A X - B||_oo=%e\n", Anorm, Xnorm, Bnorm, Rnorm );
351 
352  result = Rnorm / ( (Anorm*Xnorm+Bnorm)*N*eps ) ;
353  printf("============\n");
354  printf("Checking the Residual of the solution \n");
355  printf("-- ||Ax-B||_oo/((||A||_oo||x||_oo+||B||_oo).N.eps) = %e \n", result);
356 
357  if ( isnan(Xnorm) || isinf(Xnorm) || isnan(result) || isinf(result) || (result > 60.0) ) {
358  printf("-- The solution is suspicious ! \n");
359  info_solution = 1;
360  }
361  else{
362  printf("-- The solution is CORRECT ! \n");
363  info_solution = 0;
364  }
365  free(work);
366  return info_solution;
367 }