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_dgetri.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_dmain.h"
25 
26 static int check_factorization(int, double*, double*, int, int*, double);
27 static int check_inverse(int, double *, double *, int, int*, double);
28 
29 int testing_dgetri(int argc, char **argv)
30 {
31 
32  /* Check for number of arguments*/
33  if (argc != 2){
34  USAGE("GETRI", "N LDA",
35  " - N : the size of the matrix\n"
36  " - LDA : leading dimension of the matrix A\n");
37  return -1;
38  }
39 
40  int N = atoi(argv[0]);
41  int LDA = atoi(argv[1]);
42  double eps;
43  int info_inverse, info_factorization;
44  int i, j;
45 
46  double *A1 = (double *)malloc(LDA*N*sizeof(double));
47  double *A2 = (double *)malloc(LDA*N*sizeof(double));
48  double *WORK = (double *)malloc(2*LDA*sizeof(double));
49  double *D = (double *)malloc(LDA*sizeof(double));
50  int *IPIV = (int *)malloc(N*sizeof(int));
51 
52  /* Check if unable to allocate memory */
53  if ( (!A1) || (!A2) || (!IPIV) ){
54  printf("Out of Memory \n ");
55  return -2;
56  }
57 
58  eps = LAPACKE_dlamch_work('e');
59 
60  /*-------------------------------------------------------------
61  * TESTING DGETRI
62  */
63 
64  /* Initialize A1 and A2 Matrix */
65  PLASMA_dplrnt(N, N, A1, LDA, 3453);
66  for ( i = 0; i < N; i++)
67  for ( j = 0; j < N; j++)
68  A2[LDA*j+i] = A1[LDA*j+i];
69 
70  printf("\n");
71  printf("------ TESTS FOR PLASMA DGETRI ROUTINE ------- \n");
72  printf(" Size of the Matrix %d by %d\n", N, N);
73  printf("\n");
74  printf(" The matrix A is randomly generated for each test.\n");
75  printf("============\n");
76  printf(" The relative machine precision (eps) is to be %e \n", eps);
77  printf(" Computational tests pass if scaled residuals are less than 60.\n");
78 
79  /* PLASMA DGETRF */
80  PLASMA_dgetrf(N, N, A2, LDA, IPIV);
81 
82  /* Check the factorization */
83  info_factorization = check_factorization( N, A1, A2, LDA, IPIV, eps);
84 
85  /* PLASMA DGETRI */
86  PLASMA_dgetri(N, A2, LDA, IPIV);
87 
88  /* Check the inverse */
89  info_inverse = check_inverse(N, A1, A2, LDA, IPIV, eps);
90 
91  if ( (info_inverse == 0) && (info_factorization == 0) ) {
92  printf("***************************************************\n");
93  printf(" ---- TESTING DGETRI ..................... PASSED !\n");
94  printf("***************************************************\n");
95  }
96  else {
97  printf("***************************************************\n");
98  printf(" - TESTING DGETRI ... FAILED !\n");
99  printf("***************************************************\n");
100  }
101 
102  free(A1); free(A2); free(IPIV); free(WORK); free(D);
103 
104  return 0;
105 }
106 
107 
108 /*------------------------------------------------------------------------
109  * Check the factorization of the matrix A2
110  */
111 static int check_factorization(int N, double *A1, double *A2, int LDA, int *IPIV, double eps)
112 {
113  int info_factorization;
114  double Rnorm, Anorm, Xnorm, Bnorm, result;
115  double alpha, beta;
116  double *work = (double *)malloc(N*sizeof(double));
117 
118  alpha = 1.0;
119  beta = -1.0;
120 
121  double *b = (double *)malloc(LDA*sizeof(double));
122  double *x = (double *)malloc(LDA*sizeof(double));
123 
124  LAPACKE_dlarnv_work(1, ISEED, LDA, x);
125  LAPACKE_dlacpy_work(LAPACK_COL_MAJOR, 'A', N, 1, x, LDA, b, LDA);
126 
127  PLASMA_dgetrs( PlasmaNoTrans, N, 1, A2, LDA, IPIV, x, LDA );
128 
129  Xnorm = PLASMA_dlange(PlasmaInfNorm, N, 1, x, LDA, work);
130  Anorm = PLASMA_dlange(PlasmaInfNorm, N, N, A1, LDA, work);
131  Bnorm = PLASMA_dlange(PlasmaInfNorm, N, 1, b, LDA, work);
132 
134  alpha, A1, LDA, x, LDA, beta, b, LDA);
135 
136  Rnorm = PLASMA_dlange(PlasmaInfNorm, N, 1, b, LDA, work);
137 
138  if (getenv("PLASMA_TESTING_VERBOSE"))
139  printf( "||A||_oo=%f\n||X||_oo=%f\n||B||_oo=%f\n||A X - B||_oo=%e\n", Anorm, Xnorm, Bnorm, Rnorm );
140 
141  result = Rnorm / ( (Anorm*Xnorm+Bnorm)*N*eps ) ;
142  printf("============\n");
143  printf("Checking the Residual of the solution \n");
144  printf("-- ||Ax-B||_oo/((||A||_oo||x||_oo+||B||_oo).N.eps) = %e \n", result);
145 
146  if ( isnan(Xnorm) || isinf(Xnorm) || isnan(result) || isinf(result) || (result > 60.0) ) {
147  printf("-- The factorization is suspicious ! \n");
148  info_factorization = 1;
149  }
150  else{
151  printf("-- The factorization is CORRECT ! \n");
152  info_factorization = 0;
153  }
154  free(x); free(b); free(work);
155 
156  return info_factorization;
157 }
158 
159 
160 /*------------------------------------------------------------------------
161  * Check the accuracy of the computed inverse
162  */
163 
164 static int check_inverse(int N, double *A1, double *A2, int LDA, int *IPIV, double eps )
165 {
166  int info_inverse;
167  int i;
168  double Rnorm, Anorm, Ainvnorm, result;
169  double alpha, beta, zone;
170  double *W = (double *)malloc(N*sizeof(double));
171  double *work = (double *)malloc(N*N*sizeof(double));
172 
173  alpha = -1.0;
174  beta = 0.0;
175  zone = 1.0;
176 
177  PLASMA_dgemm( PlasmaNoTrans, PlasmaNoTrans, N, N, N, alpha, A2, LDA, A1, LDA, beta, work, N);
178 
179  /* Add the identity matrix to work */
180  for(i=0; i<N; i++)
181  *(work+i+i*N) = *(work+i+i*N) + zone;
182 
183  Rnorm = PLASMA_dlange(PlasmaInfNorm, N, N, work, N, W);
184  Anorm = PLASMA_dlange(PlasmaInfNorm, N, N, A1, LDA, W);
185  Ainvnorm = PLASMA_dlange(PlasmaInfNorm, N, N, A2, LDA, W);
186 
187  if (getenv("PLASMA_TESTING_VERBOSE"))
188  printf( "||A||_1=%f\n||Ainv||_1=%f\n||Id - A*Ainv||_1=%e\n", Anorm, Ainvnorm, Rnorm );
189 
190  result = Rnorm / ( (Anorm*Ainvnorm)*N*eps ) ;
191  printf("============\n");
192  printf("Checking the Residual of the inverse \n");
193  printf("-- ||Id - A*Ainv||_1/((||A||_1||Ainv||_1).N.eps) = %e \n", result);
194 
195  if ( isnan(Ainvnorm) || isinf(Ainvnorm) || isnan(result) || isinf(result) || (result > 60.0) ) {
196  printf("-- The inverse is suspicious ! \n");
197  info_inverse = 1;
198  }
199  else{
200  printf("-- The inverse is CORRECT ! \n");
201  info_inverse = 0;
202  }
203 
204  free(W);
205  free(work);
206 
207  return info_inverse;
208 }