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