1dnl Generates test code for spmv
2#include <stdlib.h>
3#include <stdio.h>
4#include <math.h>
5#include "blas_extended.h"
6#include "blas_extended_private.h"
7#include "blas_extended_test.h"
8
9/* 0 -- 1 */
10#define UPLO_START 0
11#define UPLO_END   1
12
13/* 0 -- 1 */
14#define ORDER_START  0
15#define ORDER_END    1
16
17/* 0 -- 2 */
18#define ALPHA_START  0
19#define ALPHA_END    2
20
21/* 0 -- 2 */
22#define BETA_START   0
23#define BETA_END     2
24
25/* -1 -- 1 */
26#define NORM_START   -1
27#define NORM_END     1
28
29/* 0 -- 2 */
30#define PREC_START   0
31#define PREC_END     2
32
33/* 0 -- 1 */
34#define RANDOMIZE_START 0
35#define RANDOMIZE_END   1
36
37/* -2 -- 2 (Stride) */
38#define INCX_START -2
39#define INCX_END 2
40
41/* -2 -- 2 (Stride) */
42#define INCY_START -2
43#define INCY_END 2
44
45#define NUM_DATA 7
46
47include(cblas.m4)dnl
48include(test-common.m4)dnl
49include(spmv/spmv-common.m4)dnl
50dnl
51dnl
52define(`DO_TEST_SPMV_NAME',
53  `ifelse(`$1&&$1', `$2&&$3', `do_test_$1spmv$4', `do_test_$1spmv_$2_$3$4')')
54dnl
55dnl
56define(`DO_TEST_SPMV_PARAMS',
57  `int n,
58   int ntests, int *seed, double thresh, int debug, float test_prob,
59   double *min_ratio, double *max_ratio,
60        int *num_bad_ratio, int *num_tests')
61dnl
62dnl
63define(`DO_TEST_SPMV_HEAD',
64`void DO_TEST_SPMV_NAME($1, $2, $3, $4)(
65        DO_TEST_SPMV_PARAMS($1, $2, $3, $4))')
66dnl
67dnl
68define(`DO_TEST_SPMV',
69  `DO_TEST_SPMV_HEAD($1, $2, $3, $4) {
70   DO_TEST_SPMV_BODY($1, $2, $3, $4)
71  }')
72dnl
73dnl
74dnl
75define(`TESTGEN_SPMV_NAME', `ifelse(
76       `$2&&$3', `$1&&$1', `BLAS_$1spmv_testgen', `BLAS_$1spmv_$2_$3_testgen')')
77dnl
78dnl
79define(`DO_TEST_SPMV_BODY',
80  `
81  /* Function name */
82  const char fname[] = "SPMV_NAME($1, $2, $3, $4)";
83
84  int i;
85  int yi;
86  int incyi, y_starti;
87  int test_count;
88  int bad_ratio_count;
89
90  int ri;
91  int incri;
92  int inca, incx, incy;
93
94  double ratio;
95
96  double ratio_min, ratio_max;
97
98  double eps_int;  /* internal machine epsilon     */
99  double un_int;   /* internal underflow threshold */
100
101  DECLARE(rin, $1_type)
102  DECLARE(rout, $1_type)
103  DECLARE(r_true_elem, EXTRA_TYPE($1_type))
104
105  enum blas_order_type order_type;
106  enum blas_uplo_type uplo_type;
107  enum blas_prec_type prec;
108
109  int order_val, uplo_val;
110  int incx_val, incy_val;
111  int alpha_val, beta_val;
112  int randomize_val;
113
114  ifelse(`$4', `_x', `int prec_val;', `')
115
116  int alpha_flag, beta_flag;
117  int saved_seed;
118  int norm;
119  int test_no;
120
121  int n_i;
122
123  DECLARE(alpha, $1_type)
124  DECLARE(beta, $1_type)
125  DECLARE_VECTOR(a, $2_type)
126  DECLARE_VECTOR(x, $3_type)
127  DECLARE_VECTOR(y, $1_type)
128  DECLARE_VECTOR(a_vec, $2_type)
129  DECLARE_VECTOR(x_vec, $3_type)
130
131  /* generated test values for c */
132  DECLARE_VECTOR(y_gen, $1_type)
133
134  DECLARE_VECTOR(ratios, real_D)
135
136  /* true result calculated by testgen, in double-double */
137  DECLARE_VECTOR(r_true, EXTRA_TYPE($1_type))
138
139  FPU_FIX_DECL;
140
141  if (n < 0 || ntests < 0)
142    BLAS_error(fname,  -3,  n, NULL);
143
144  /* initialization */
145  saved_seed = *seed;
146  ratio = 0.0;
147  ratio_min = 1e308;
148  ratio_max = 0.0;
149
150  *num_tests = 0;
151  *num_bad_ratio = 0;
152  *min_ratio = 0.0;
153  *max_ratio = 0.0;
154
155  if (n == 0)
156    return;
157
158  FPU_FIX_START;
159
160  n_i = n;
161
162  inca = incx = incy = 1;
163  INC_ADJUST(inca, $2_type)
164  INC_ADJUST(incx, $3_type)
165  INC_ADJUST(incy, $1_type)
166
167  /* allocate memory for arrays */
168  MALLOC_VECTOR(y, $1_type, 3 * n_i)
169  MALLOC_VECTOR(y_gen, $1_type, 3 * n_i)
170  MALLOC_VECTOR(a, $2_type, 2 * n_i * n_i * n_i)
171  MALLOC_VECTOR(x, $3_type, 3 * n_i)
172  MALLOC_VECTOR(a_vec, $2_type, n_i)
173  MALLOC_VECTOR(x_vec, $3_type, n_i)
174  MALLOC_VECTOR(r_true, EXTRA_TYPE($1_type), n_i)
175  MALLOC_VECTOR(ratios, real_D, 2 * n)
176
177  test_count = 0;
178  bad_ratio_count = 0;
179
180    /* vary alpha */
181    for (alpha_val = ALPHA_START; alpha_val <= ALPHA_END; alpha_val++) {
182
183      SET_ALPHA($1_type)
184
185      /* vary beta */
186      for (beta_val = BETA_START; beta_val <= BETA_END; beta_val++) {
187        SET_BETA($1_type)
188
189        ifelse($4, _x, `
190        /* varying extra precs */
191        for (prec_val = PREC_START; prec_val <= PREC_END; prec_val++) {')
192        SET_INTERNAL_PARAMS($1_type, $4)
193
194        /* vary norm -- underflow, approx 1, overflow */
195        for (norm = NORM_START; norm <= NORM_END; norm++) {
196
197          /* number of tests */
198          for (test_no = 0; test_no < ntests; test_no++) {
199
200
201            /* vary storage format */
202            for (order_val = ORDER_START; order_val <= ORDER_END; order_val++) {
203
204              order_type = (order_val == 0) ? blas_colmajor : blas_rowmajor;
205
206              /* vary upper / lower variation */
207              for (uplo_val = UPLO_START; uplo_val <= UPLO_END; uplo_val++) {
208
209                uplo_type = (uplo_val == 0) ? blas_upper : blas_lower;
210
211                    /* vary incx = 1, 2*/
212                    for (incx_val = INCX_START; incx_val <= INCX_END; incx_val++) {
213
214                      incx = incx_val;
215                      if (0 == incx)
216                        continue;
217
218                      /* vary incy = 1, 2 */
219                      for (incy_val = INCY_START; incy_val <= INCY_END; incy_val++) {
220
221                        incy = incy_val;
222                        if (0 == incy)
223                                continue;
224
225                        for (randomize_val = RANDOMIZE_START;
226                             randomize_val <= RANDOMIZE_END; randomize_val++) {
227
228                            saved_seed = *seed;
229                            /* For the sake of speed, we throw out this case at random */
230                            if ( xrand(seed) >= test_prob ) continue;
231
232                            /* finally we are here to generate the test case */
233                            TESTGEN_SPMV_NAME($1, $2, $3) (norm, order_type,
234                              uplo_type, n, randomize_val, &alpha,
235                              alpha_flag, &beta, beta_flag, a, x, incx,
236                              y, incy, seed, HEAD(r_true), TAIL(r_true));
237                            test_count++;
238
239                            /* copy generated y vector since this will be
240                               over written */
241                            $1copy_vector(y, n, incy, y_gen, incy);
242
243                            /* call spmv routines to be tested */
244                            FPU_FIX_STOP;
245                            SPMV_NAME($1, $2, $3, $4)(order_type,
246                              uplo_type, n, alpha, a, x, incx, beta,
247                              y, incy ifelse(`$4', `_x', `, prec'));
248                            FPU_FIX_START;
249
250                            /* now compute the ratio using test_BLAS_xdot */
251                            /* copy a row from A, use x, run
252                               dot test */
253
254                            incyi = incy;
255
256                            incri = 1;
257
258                            INC_ADJUST(incyi, $1_type)
259                            INC_ADJUST(incri, EXTRA_TYPE($1_type))
260                            if (incy < 0) {
261                                y_starti = (-n + 1) * incyi;
262                            } else {
263                                y_starti = 0;
264                            }
265
266                            for (i = 0, yi = y_starti, ri = 0;
267                                    i < n_i; i++, yi += incyi, ri += incri) {
268                              $2spmv_copy_row(order_type, uplo_type,
269                                              n_i, a, a_vec, i);
270
271                              /* just use the x vector - it was unchanged (in theory) */
272
273
274                              GET_VECTOR_ELEMENT(rin, y_gen, yi, $1_type)
275                              GET_VECTOR_ELEMENT(rout, y, yi, $1_type)
276                              GET_VECTOR_ELEMENT(r_true_elem, r_true, ri, EXTRA_TYPE($1_type))
277
278                              TEST_DOT_NAME($1, $2, $3, $4)(n_i,
279                                blas_no_conj,
280                                alpha, beta, rin, rout,
281                                HEAD(r_true)_elem, TAIL(r_true)_elem,
282                                a_vec, 1, x, incx, eps_int, un_int,
283                                &ratios[ri]);
284
285                                /* take the max ratio */
286                                if (ri == 0) {
287                                  ratio = ratios[0];
288                                /* The !<= below causes NaN errors
289                                 *  to be included.
290                                 * Note that (NaN > 0) is false */
291                                } else if (!(ratios[ri] <= ratio)) {
292                                  ratio = ratios[ri];
293                                }
294
295                            }  /* end of dot-test loop */
296                            /* The !<= below causes NaN errors
297                             *  to be included.
298                             * Note that (NaN > 0) is false */
299                            if (  !(ratio <= thresh) ) {
300
301                              if (debug == 3) {
302                                printf("\n\t\tTest # %d\n", test_count);
303                                printf("y type : $1, a type : $2, x type : $3\n");
304                                printf("Seed = %d\n", saved_seed);
305                                printf("n %d\n", n);
306                                printf("INCX %d  INCY %d\n", incx, incx);
307
308                                if (order_type == blas_rowmajor)
309                                  printf("row ");
310                                else
311                                  printf("col ");
312
313                                if (uplo_type == blas_upper)
314                                  printf("upper ");
315                                else
316                                  printf("lower");
317
318                                printf("NORM %d, ALPHA %d, BETA %d\n",
319                                       norm, alpha_val, beta_val);
320
321                                /* print out info */
322                                PRINT_VAR(alpha, $1_type);
323                                printf("   ");
324                                PRINT_VAR(beta, $1_type);
325                                printf("\n");
326
327                                printf("a\n");
328                                $2print_spmv_matrix(a, n_i,
329                                               order_type, uplo_type);
330                                $3print_vector(x, n, incx, "x");
331                                $1print_vector(y_gen, n, incy, "y_gen");
332                                $1print_vector(y, n, incy, "y");
333                                dprint_vector(HEAD(r_true), n, 1, "HEAD(r_true)");
334                                dprint_vector(ratios, n, 1, "ratios");
335                                printf("ratio = %g\n", ratio);
336                              }
337                              bad_ratio_count++;
338                              if (bad_ratio_count >= MAX_BAD_TESTS) {
339                                printf("\ntoo many failures, exiting....");
340                                printf("\nTesting and compilation");
341                                printf(" are incomplete\n\n");
342                                goto end;
343                              }
344                              if ( !(ratio <= TOTAL_FAILURE_THRESHOLD) ) {
345                                printf("\nFlagrant ratio error, exiting...");
346                                printf("\nTesting and compilation");
347                                printf(" are incomplete\n\n");
348                                goto end;
349                              }
350                            }
351                            if (!(ratio <= ratio_max))
352                              ratio_max = ratio;
353
354                            if (ratio != 0.0 && !(ratio >= ratio_min))
355                              ratio_min = ratio;
356
357                        } /* end of randmize loop */
358
359                      } /* end of incy loop */
360
361                    } /* end of incx loop */
362
363              } /* end of uplo loop */
364
365            } /* end of order loop */
366
367          } /* end of nr test loop */
368
369        } /* end of norm loop */
370
371dnl ---------------------------------------------------------
372ifelse(`$4', `_x', `
373          } /* end of prec loop */  ')
374dnl ---------------------------------------------------------
375
376      } /* end of beta loop */
377
378    } /* end of alpha loop */
379
380end:
381  FPU_FIX_STOP;
382
383  FREE_VECTOR(y, $1_type)
384  FREE_VECTOR(a, $2_type)
385  FREE_VECTOR(x, $3_type)
386  FREE_VECTOR(y_gen, $1_type)
387  FREE_VECTOR(r_true, EXTRA_TYPE($1_type))
388  FREE_VECTOR(ratios, real_D)
389  FREE_VECTOR(a_vec, $2_type)
390  FREE_VECTOR(x_vec, $3_type)
391
392  *max_ratio = ratio_max;
393  *min_ratio = ratio_min;
394  *num_tests = test_count;
395  *num_bad_ratio = bad_ratio_count;
396')
397dnl
398dnl
399dnl
400define(`CALL_DO_TEST_SPMV',
401 `fname = "SPMV_NAME($1, $2, $3, $4)";
402  printf("Testing %s...\n", fname);
403  total_tests = 0;
404  total_bad_ratios = 0;
405  total_min_ratio = 1e308;
406  total_max_ratio = 0.0;
407  for (i = 0; i < nsizes; i++) {
408    n = n_data[i][0];
409
410    DO_TEST_SPMV_NAME($1, $2, $3, $4)(n, ntests, &seed, thresh, debug,
411             test_prob, &min_ratio, &max_ratio,
412             &num_bad_ratio, &num_tests);
413
414    if (debug == 2 || (debug == 1 && num_bad_ratio > 0)) {
415      printf("   [%d %d]: ", n, n);
416      printf("bad/total = %d/%d, min_ratio = %g, max_ratio = %g\n",
417             num_bad_ratio, num_tests, min_ratio, max_ratio);
418    }
419
420    total_tests += num_tests;
421    total_bad_ratios += num_bad_ratio;
422    if (total_min_ratio > min_ratio)
423      total_min_ratio = min_ratio;
424    if (total_max_ratio < max_ratio)
425      total_max_ratio = max_ratio;
426  }
427
428  nr_routines++;
429  if (total_bad_ratios == 0)
430    printf("PASS> ");
431  else {
432    printf("FAIL> ");
433    nr_failed_routines++;
434  }
435  printf("%-24s: bad/total = %d/%d, max_ratio = %.2e\n\n",
436      fname, total_bad_ratios, total_tests, max_ratio);
437 ')
438
439FOREACH(`SPMV_ARGS', `
440DO_TEST_SPMV(arg)')dnl
441
442MAIN(`
443  int i;
444  int n_data[NUM_DATA][1] = {{4}, {2}, {3}, {8}, {10}, {1}, {7}};', `
445
446FOREACH(`SPMV_ARGS', `
447CALL_DO_TEST_SPMV(arg)')')dnl
448
449