1 /*
2 
3     Copyright (C) 2014, The University of Texas at Austin
4 
5     This file is part of libflame and is available under the 3-Clause
6     BSD license, which can be found in the LICENSE file at the top-level
7     directory, or at http://opensource.org/licenses/BSD-3-Clause
8 
9 */
10 
11 #include "FLAME.h"
12 
13 #include "test_libflame.h"
14 
15 // Operation modules.
16 #include "test_gemm.h"
17 #include "test_hemm.h"
18 #include "test_herk.h"
19 #include "test_her2k.h"
20 #include "test_symm.h"
21 #include "test_syrk.h"
22 #include "test_syr2k.h"
23 #include "test_trmm.h"
24 #include "test_trsm.h"
25 #include "test_chol.h"
26 #include "test_lu_nopiv.h"
27 #include "test_lu_piv.h"
28 #include "test_lu_incpiv.h"
29 #include "test_qrut.h"
30 #include "test_qrutinc.h"
31 #include "test_lqut.h"
32 #include "test_apqut.h"
33 #include "test_apqutinc.h"
34 #include "test_caqrutinc.h"
35 #include "test_apcaqutinc.h"
36 #include "test_uddateut.h"
37 #include "test_uddateutinc.h"
38 #include "test_apqudut.h"
39 #include "test_apqudutinc.h"
40 #include "test_hessut.h"
41 #include "test_tridiagut.h"
42 #include "test_bidiagut.h"
43 #include "test_eig_gest.h"
44 #include "test_trinv.h"
45 #include "test_spdinv.h"
46 #include "test_sylv.h"
47 #include "test_lyap.h"
48 
49 
50 // Global variables.
51 char libfla_test_binary_name[ MAX_BINARY_NAME_LENGTH + 1 ];
52 char libfla_test_pass_string[ MAX_PASS_STRING_LENGTH + 1 ];
53 char libfla_test_warn_string[ MAX_PASS_STRING_LENGTH + 1 ];
54 char libfla_test_fail_string[ MAX_PASS_STRING_LENGTH + 1 ];
55 
56 char libfla_test_stor_chars[ NUM_STORAGE_CHARS + 1 ];
57 
main(int argc,char ** argv)58 int main( int argc, char** argv )
59 {
60 	test_params_t params;
61 	test_ops_t    ops;
62 
63 	// Initialize libflame.
64 	FLA_Init();
65 
66 	// Initialize some strings.
67 	libfla_test_init_strings();
68 
69 	// Parse the command line parameters.
70 	libfla_test_parse_command_line( argc, argv );
71 
72 	// Read the main test suite parameters.
73 	libfla_test_read_parameter_file( PARAMETERS_FILENAME, &params );
74 
75 	// Read which operations we're going to test.
76 	libfla_test_read_operation_file( OPERATIONS_FILENAME, &ops );
77 
78 	// Test the BLAS level-3 operations.
79 	libfla_test_blas3_suite( stdout, params, ops );
80 
81 	// Test the LAPACK-level operations.
82 	libfla_test_lapack_suite( stdout, params, ops );
83 
84 	// Finalize libflame.
85 	FLA_Finalize();
86 
87 	// Return peacefully.
88 	return 0;
89 }
90 
91 
92 
libfla_test_blas3_suite(FILE * output_stream,test_params_t params,test_ops_t ops)93 void libfla_test_blas3_suite( FILE* output_stream, test_params_t params, test_ops_t ops )
94 {
95 	// Run the individual test modules.
96 
97 	libfla_test_output_info( "\n" );
98 	libfla_test_output_info( "--- BLAS level-3 operation tests ---------------------\n" );
99 	libfla_test_output_info( "\n" );
100 
101 	// General matrix-matrix multiply.
102 	libfla_test_gemm( output_stream, params, ops.gemm );
103 
104 	// Hermitian matrix-matrix multiply.
105 	libfla_test_hemm( output_stream, params, ops.hemm );
106 
107 	// Hermitian rank-k update.
108 	libfla_test_herk( output_stream, params, ops.herk );
109 
110 	// Hermitian rank-2k update.
111 	libfla_test_her2k( output_stream, params, ops.her2k );
112 
113 	// Symmetric matrix-matrix multiply.
114 	libfla_test_symm( output_stream, params, ops.symm );
115 
116 	// Symmetric rank-k update.
117 	libfla_test_syrk( output_stream, params, ops.syrk );
118 
119 	// Symmetric rank-2k update.
120 	libfla_test_syr2k( output_stream, params, ops.syr2k );
121 
122 	// Triangular matrix-matrix multiply.
123 	libfla_test_trmm( output_stream, params, ops.trmm );
124 
125 	// Triangular solve with multiple rhs.
126 	libfla_test_trsm( output_stream, params, ops.trsm );
127 }
128 
129 
130 
libfla_test_lapack_suite(FILE * output_stream,test_params_t params,test_ops_t ops)131 void libfla_test_lapack_suite( FILE* output_stream, test_params_t params, test_ops_t ops )
132 {
133 	// Run the individual test modules.
134 
135 	libfla_test_output_info( "\n" );
136 	libfla_test_output_info( "--- LAPACK-level operation tests ---------------------\n" );
137 	libfla_test_output_info( "\n" );
138 
139 	// Cholesky factorization.
140 	libfla_test_chol( output_stream, params, ops.chol );
141 
142 	// LU factorization without pivoting.
143 	libfla_test_lu_nopiv( output_stream, params, ops.lu_nopiv );
144 
145 	// LU factorization with partial pivoting.
146 	libfla_test_lu_piv( output_stream, params, ops.lu_piv );
147 
148 	// LU factorization with incremental pivoting.
149 	libfla_test_lu_incpiv( output_stream, params, ops.lu_incpiv );
150 
151 	// QR factorization via the UT transform.
152 	libfla_test_qrut( output_stream, params, ops.qrut );
153 
154 	// QR factorization via the UT transform (incremental).
155 	libfla_test_qrutinc( output_stream, params, ops.qrutinc );
156 
157 	// LQ factorization via the UT transform.
158 	libfla_test_lqut( output_stream, params, ops.lqut );
159 
160 	// Apply Q via the UT transform.
161 	libfla_test_apqut( output_stream, params, ops.apqut );
162 
163 	// Apply Q via the UT transform (incremental).
164 	libfla_test_apqutinc( output_stream, params, ops.apqutinc );
165 
166 	// Communication-avoiding QR factorization via the UT transform (incremental).
167 	libfla_test_caqrutinc( output_stream, params, ops.caqrutinc );
168 
169 	// Apply communication-avoiding Q via the UT transform (incremental).
170 	libfla_test_apcaqutinc( output_stream, params, ops.apcaqutinc );
171 
172 	// Up/downdating via the UT transform.
173 	libfla_test_uddateut( output_stream, params, ops.uddateut );
174 
175 	// Up/downdating via the UT transform (incremental).
176 	libfla_test_uddateutinc( output_stream, params, ops.uddateutinc );
177 
178 	// Apply up/downdating Q via the UD UT transform.
179 	libfla_test_apqudut( output_stream, params, ops.apqudut );
180 
181 	// Apply up/downdating Q via the UD UT transform (incremental).
182 	libfla_test_apqudutinc( output_stream, params, ops.apqudutinc );
183 
184 	// Reduction to upper Hessenberg form via the UT transform.
185 	libfla_test_hessut( output_stream, params, ops.hessut );
186 
187 	// Reduction to tridiagonal form via the UT transform.
188 	libfla_test_tridiagut( output_stream, params, ops.tridiagut );
189 
190 	// Reduction to bidiagonal form via the UT transform.
191 	libfla_test_bidiagut( output_stream, params, ops.bidiagut );
192 
193 	// Reduction of Hermitian-definite eigenproblem to standard form.
194 	libfla_test_eig_gest( output_stream, params, ops.eig_gest );
195 
196 	// Triangular matrix inversion.
197 	libfla_test_trinv( output_stream, params, ops.trinv );
198 
199 	// Hermitian positive-definite matrix inversion.
200 	libfla_test_spdinv( output_stream, params, ops.spdinv );
201 
202 	// Triangular Sylvester equation solve.
203 	libfla_test_sylv( output_stream, params, ops.sylv );
204 
205 	// Triangular Lyapunov equation solve.
206 	libfla_test_lyap( output_stream, params, ops.lyap );
207 }
208 
209 
210 
libfla_test_read_operation_file(char * input_filename,test_ops_t * ops)211 void libfla_test_read_operation_file( char* input_filename, test_ops_t* ops )
212 {
213 	FILE* input_stream;
214 
215 	// Attempt to open input file corresponding to input_filename as
216 	// read-only/binary.
217 	input_stream = fopen( input_filename, "rb" );
218 
219 	// Check for success.
220 	if ( input_stream == NULL )
221 	{
222 		libfla_test_output_error( "Failed to open input file %s. Check existence and permissions.\n",
223 		                          input_filename );
224 	}
225 
226 	libfla_test_output_info( "\n" );
227 	libfla_test_output_info( "--- operations to test -------------------------------\n" );
228 	libfla_test_output_info( "\n" );
229 
230 	// Read the operation tests for general matrix-matrix multiply.
231 	libfla_test_read_tests_for_op_blas3( input_stream, &(ops->gemm) );
232 	libfla_test_output_op_struct_blas3( "gemm", ops->gemm );
233 
234 	// Read the operation tests for Hermitian matrix-matrix multiply.
235 	libfla_test_read_tests_for_op_blas3( input_stream, &(ops->hemm) );
236 	libfla_test_output_op_struct_blas3( "hemm", ops->hemm );
237 
238 	// Read the operation tests for Hermitian rank-k update.
239 	libfla_test_read_tests_for_op_blas3( input_stream, &(ops->herk) );
240 	libfla_test_output_op_struct_blas3( "herk", ops->herk );
241 
242 	// Read the operation tests for Hermitian rank-2k update.
243 	libfla_test_read_tests_for_op_blas3( input_stream, &(ops->her2k) );
244 	libfla_test_output_op_struct_blas3( "her2k", ops->her2k );
245 
246 	// Read the operation tests for Symmetric matrix-matrix multiply.
247 	libfla_test_read_tests_for_op_blas3( input_stream, &(ops->symm) );
248 	libfla_test_output_op_struct_blas3( "symm", ops->symm );
249 
250 	// Read the operation tests for Symmetric rank-k update.
251 	libfla_test_read_tests_for_op_blas3( input_stream, &(ops->syrk) );
252 	libfla_test_output_op_struct_blas3( "syrk", ops->syrk );
253 
254 	// Read the operation tests for Symmetric rank-2k update.
255 	libfla_test_read_tests_for_op_blas3( input_stream, &(ops->syr2k) );
256 	libfla_test_output_op_struct_blas3( "syr2k", ops->syr2k );
257 
258 	// Read the operation tests for Triangular matrix-matrix multiply.
259 	libfla_test_read_tests_for_op_blas3( input_stream, &(ops->trmm) );
260 	libfla_test_output_op_struct_blas3( "trmm", ops->trmm );
261 
262 	// Read the operation tests for Triangular solve with multiple rhs.
263 	libfla_test_read_tests_for_op_blas3( input_stream, &(ops->trsm) );
264 	libfla_test_output_op_struct_blas3( "trsm", ops->trsm );
265 
266 	// Read the operation tests for Cholesky factorization.
267 	libfla_test_read_tests_for_op( input_stream, &(ops->chol) );
268 	libfla_test_output_op_struct( "chol", ops->chol );
269 
270 	// Read the operation tests for LU_nopiv factorization.
271 	libfla_test_read_tests_for_op( input_stream, &(ops->lu_nopiv) );
272 	libfla_test_output_op_struct( "lu_nopiv", ops->lu_nopiv );
273 
274 	// Read the operation tests for LU_piv factorization.
275 	libfla_test_read_tests_for_op( input_stream, &(ops->lu_piv) );
276 	libfla_test_output_op_struct( "lu_piv", ops->lu_piv );
277 
278 	// Read the operation tests for LU_incpiv factorization.
279 	libfla_test_read_tests_for_op_flash_only( input_stream, &(ops->lu_incpiv) );
280 	libfla_test_output_op_struct_flash_only( "lu_incpiv", ops->lu_incpiv );
281 
282 	// Read the operation tests for QR_UT factorization.
283 	libfla_test_read_tests_for_op( input_stream, &(ops->qrut) );
284 	libfla_test_output_op_struct( "qrut", ops->qrut );
285 
286 	// Read the operation tests for QR_UT_inc factorization.
287 	libfla_test_read_tests_for_op_flash_only( input_stream, &(ops->qrutinc) );
288 	libfla_test_output_op_struct_flash_only( "qrutinc", ops->qrutinc );
289 
290 	// Read the operation tests for LQ_UT factorization.
291 	libfla_test_read_tests_for_op( input_stream, &(ops->lqut) );
292 	libfla_test_output_op_struct( "lqut", ops->lqut );
293 
294 	// Read the operation tests for Apply_Q_UT.
295 	libfla_test_read_tests_for_op_front_only( input_stream, &(ops->apqut) );
296 	libfla_test_output_op_struct_front_only( "apqut", ops->apqut );
297 
298 	// Read the operation tests for Apply_Q_UT_inc.
299 	libfla_test_read_tests_for_op_flash_only( input_stream, &(ops->apqutinc) );
300 	libfla_test_output_op_struct_flash_only( "apqutinc", ops->apqutinc );
301 
302 	// Read the operation tests for CAQR_UT_inc factorization.
303 	libfla_test_read_tests_for_op_flash_only( input_stream, &(ops->caqrutinc) );
304 	libfla_test_output_op_struct_flash_only( "caqrutinc", ops->caqrutinc );
305 
306 	// Read the operation tests for Apply_CAQ_UT_inc.
307 	libfla_test_read_tests_for_op_flash_only( input_stream, &(ops->apcaqutinc) );
308 	libfla_test_output_op_struct_flash_only( "apcaqutinc", ops->apcaqutinc );
309 
310 	// Read the operation tests for UDdate_UT.
311 	libfla_test_read_tests_for_op_fla_only( input_stream, &(ops->uddateut) );
312 	libfla_test_output_op_struct_fla_only( "uddateut", ops->uddateut );
313 
314 	// Read the operation tests for UDdate_UT_inc.
315 	libfla_test_read_tests_for_op_flash_only( input_stream, &(ops->uddateutinc) );
316 	libfla_test_output_op_struct_flash_only( "uddateutinc", ops->uddateutinc );
317 
318 	// Read the operation tests for Apply_QUD_UT.
319 	libfla_test_read_tests_for_op_front_fla_only( input_stream, &(ops->apqudut) );
320 	libfla_test_output_op_struct_front_fla_only( "apqudut", ops->apqudut );
321 
322 	// Read the operation tests for Apply_QUD_UT_inc.
323 	libfla_test_read_tests_for_op_flash_only( input_stream, &(ops->apqudutinc) );
324 	libfla_test_output_op_struct_flash_only( "apqudutinc", ops->apqudutinc );
325 
326 	// Read the operation tests for Hess_UT reduction.
327 	libfla_test_read_tests_for_op_fla_only( input_stream, &(ops->hessut) );
328 	libfla_test_output_op_struct_fla_only( "hessut", ops->hessut );
329 
330 	// Read the operation tests for Tridiag_UT reduction.
331 	libfla_test_read_tests_for_op_fla_only( input_stream, &(ops->tridiagut) );
332 	libfla_test_output_op_struct_fla_only( "tridiagut", ops->tridiagut );
333 
334 	// Read the operation tests for Bidiag_UT reduction.
335 	libfla_test_read_tests_for_op_fla_only( input_stream, &(ops->bidiagut) );
336 	libfla_test_output_op_struct_fla_only( "bidiagut", ops->bidiagut );
337 
338 	// Read the operation tests for Eig_gest.
339 	libfla_test_read_tests_for_op( input_stream, &(ops->eig_gest) );
340 	libfla_test_output_op_struct( "eig_gest", ops->eig_gest );
341 
342 	// Read the operation tests for triangular matrix inversion.
343 	libfla_test_read_tests_for_op( input_stream, &(ops->trinv) );
344 	libfla_test_output_op_struct( "trinv", ops->trinv );
345 
346 	// Read the operation tests for SPD/HPD matrix inversion.
347 	libfla_test_read_tests_for_op_front_only( input_stream, &(ops->spdinv) );
348 	libfla_test_output_op_struct_front_only( "spdinv", ops->spdinv );
349 
350 	// Read the operation tests for triangular Sylvester equation solve.
351 	libfla_test_read_tests_for_op( input_stream, &(ops->sylv) );
352 	libfla_test_output_op_struct( "sylv", ops->sylv );
353 
354 	// Read the operation tests for triangular Lyapunov equation solve.
355 	libfla_test_read_tests_for_op( input_stream, &(ops->lyap) );
356 	libfla_test_output_op_struct( "lyap", ops->lyap );
357 
358 	// Close the file.
359 	fclose( input_stream );
360 
361 }
362 
363 
364 
libfla_test_output_op_struct(char * op_str,test_op_t op)365 void libfla_test_output_op_struct( char* op_str, test_op_t op )
366 {
367 	libfla_test_output_info( "%s flash_front  %d\n", op_str, op.flash_front );
368 	libfla_test_output_info( "%s fla_front    %d\n", op_str, op.fla_front );
369 	libfla_test_output_info( "%s fla_unb_vars %d\n", op_str, op.fla_unb_vars );
370 	libfla_test_output_info( "%s fla_opt_vars %d\n", op_str, op.fla_opt_vars );
371 	libfla_test_output_info( "%s fla_blk_vars %d\n", op_str, op.fla_blk_vars );
372 }
373 
374 
375 
libfla_test_output_op_struct_flash_only(char * op_str,test_op_t op)376 void libfla_test_output_op_struct_flash_only( char* op_str, test_op_t op )
377 {
378 	libfla_test_output_info( "%s flash_front  %d\n", op_str, op.flash_front );
379 }
380 
381 
382 
libfla_test_output_op_struct_front_only(char * op_str,test_op_t op)383 void libfla_test_output_op_struct_front_only( char* op_str, test_op_t op )
384 {
385 	libfla_test_output_info( "%s flash_front  %d\n", op_str, op.flash_front );
386 	libfla_test_output_info( "%s fla_front    %d\n", op_str, op.fla_front );
387 }
388 
389 
390 
libfla_test_output_op_struct_front_fla_only(char * op_str,test_op_t op)391 void libfla_test_output_op_struct_front_fla_only( char* op_str, test_op_t op )
392 {
393 	libfla_test_output_info( "%s fla_front    %d\n", op_str, op.fla_front );
394 }
395 
396 
397 
libfla_test_output_op_struct_fla_only(char * op_str,test_op_t op)398 void libfla_test_output_op_struct_fla_only( char* op_str, test_op_t op )
399 {
400 	libfla_test_output_info( "%s fla_front    %d\n", op_str, op.fla_front );
401 	libfla_test_output_info( "%s fla_unb_vars %d\n", op_str, op.fla_unb_vars );
402 	libfla_test_output_info( "%s fla_opt_vars %d\n", op_str, op.fla_opt_vars );
403 	libfla_test_output_info( "%s fla_blk_vars %d\n", op_str, op.fla_blk_vars );
404 }
405 
406 
407 
libfla_test_output_op_struct_blas3(char * op_str,test_op_t op)408 void libfla_test_output_op_struct_blas3( char* op_str, test_op_t op )
409 {
410 	libfla_test_output_info( "%s flash_front  %d\n", op_str, op.flash_front );
411 	libfla_test_output_info( "%s fla_front    %d\n", op_str, op.fla_front );
412 	libfla_test_output_info( "%s fla_unb_vars %d\n", op_str, op.fla_unb_vars );
413 	libfla_test_output_info( "%s fla_blk_vars %d\n", op_str, op.fla_blk_vars );
414 	libfla_test_output_info( "%s fla_unb_ext  %d\n", op_str, op.fla_unb_ext );
415 }
416 
417 
418 
libfla_test_read_tests_for_op(FILE * input_stream,test_op_t * op)419 void libfla_test_read_tests_for_op( FILE* input_stream, test_op_t* op )
420 {
421 	char buffer[ INPUT_BUFFER_SIZE ];
422 	int  op_switch;
423 	int  flash_front;
424 	int  fla_front;
425 	int  fla_unb_vars;
426 	int  fla_opt_vars;
427 	int  fla_blk_vars;
428 
429 	// Read the line for the overall operation switch.
430 	libfla_test_read_next_line( buffer, input_stream );
431 	sscanf( buffer, "%d ", &op_switch );
432 
433 	// Read the line for the FLASH front-end.
434 	libfla_test_read_next_line( buffer, input_stream );
435 	sscanf( buffer, "%d ", &flash_front );
436 
437 	// Read the line for the FLA front-end.
438 	libfla_test_read_next_line( buffer, input_stream );
439 	sscanf( buffer, "%d ", &fla_front );
440 
441 	// Read the line for the unblocked variants.
442 	libfla_test_read_next_line( buffer, input_stream );
443 	sscanf( buffer, "%d ", &fla_unb_vars );
444 
445 	// Read the line for the optimized unblocked variants.
446 	libfla_test_read_next_line( buffer, input_stream );
447 	sscanf( buffer, "%d ", &fla_opt_vars );
448 
449 	// Read the line for the blocked variants.
450 	libfla_test_read_next_line( buffer, input_stream );
451 	sscanf( buffer, "%d ", &fla_blk_vars );
452 
453 	if ( op_switch == DISABLE_ALL )
454 	{
455 		op->flash_front  = DISABLE;
456 		op->fla_front    = DISABLE;
457 		op->fla_unb_vars = DISABLE;
458 		op->fla_opt_vars = DISABLE;
459 		op->fla_blk_vars = DISABLE;
460 	}
461 	else
462 	{
463 		op->flash_front  = flash_front;
464 		op->fla_front    = fla_front;
465 		op->fla_unb_vars = fla_unb_vars;
466 		op->fla_opt_vars = fla_opt_vars;
467 		op->fla_blk_vars = fla_blk_vars;
468 	}
469 }
470 
471 
472 
libfla_test_read_tests_for_op_flash_only(FILE * input_stream,test_op_t * op)473 void libfla_test_read_tests_for_op_flash_only( FILE* input_stream, test_op_t* op )
474 {
475 	char buffer[ INPUT_BUFFER_SIZE ];
476 	int  op_switch;
477 	int  flash_front;
478 
479 	// Read the line for the overall operation switch.
480 	libfla_test_read_next_line( buffer, input_stream );
481 	sscanf( buffer, "%d ", &op_switch );
482 
483 	// Read the line for the FLASH front-end.
484 	libfla_test_read_next_line( buffer, input_stream );
485 	sscanf( buffer, "%d ", &flash_front );
486 
487 	if ( op_switch == DISABLE_ALL )
488 	{
489 		op->flash_front  = DISABLE;
490 	}
491 	else
492 	{
493 		op->flash_front  = flash_front;
494 	}
495 
496 	op->fla_front    = DISABLE; // not used
497 	op->fla_unb_vars = DISABLE; // not used
498 	op->fla_opt_vars = DISABLE; // not used
499 	op->fla_blk_vars = DISABLE; // not used
500 }
501 
502 
503 
libfla_test_read_tests_for_op_fla_only(FILE * input_stream,test_op_t * op)504 void libfla_test_read_tests_for_op_fla_only( FILE* input_stream, test_op_t* op )
505 {
506 	char buffer[ INPUT_BUFFER_SIZE ];
507 	int  op_switch;
508 	int  fla_front;
509 	int  fla_unb_vars;
510 	int  fla_opt_vars;
511 	int  fla_blk_vars;
512 
513 	// Read the line for the overall operation switch.
514 	libfla_test_read_next_line( buffer, input_stream );
515 	sscanf( buffer, "%d ", &op_switch );
516 
517 	// Read the line for the FLA front-end.
518 	libfla_test_read_next_line( buffer, input_stream );
519 	sscanf( buffer, "%d ", &fla_front );
520 
521 	// Read the line for the unblocked variants.
522 	libfla_test_read_next_line( buffer, input_stream );
523 	sscanf( buffer, "%d ", &fla_unb_vars );
524 
525 	// Read the line for the optimized unblocked variants.
526 	libfla_test_read_next_line( buffer, input_stream );
527 	sscanf( buffer, "%d ", &fla_opt_vars );
528 
529 	// Read the line for the blocked variants.
530 	libfla_test_read_next_line( buffer, input_stream );
531 	sscanf( buffer, "%d ", &fla_blk_vars );
532 
533 	if ( op_switch == DISABLE_ALL )
534 	{
535 		op->fla_front    = DISABLE;
536 		op->fla_unb_vars = DISABLE;
537 		op->fla_opt_vars = DISABLE;
538 		op->fla_blk_vars = DISABLE;
539 	}
540 	else
541 	{
542 		op->fla_front    = fla_front;
543 		op->fla_unb_vars = fla_unb_vars;
544 		op->fla_opt_vars = fla_opt_vars;
545 		op->fla_blk_vars = fla_blk_vars;
546 	}
547 
548 	op->flash_front  = DISABLE; // not used
549 }
550 
551 
552 
libfla_test_read_tests_for_op_front_only(FILE * input_stream,test_op_t * op)553 void libfla_test_read_tests_for_op_front_only( FILE* input_stream, test_op_t* op )
554 {
555 	char buffer[ INPUT_BUFFER_SIZE ];
556 	int  op_switch;
557 	int  flash_front;
558 	int  fla_front;
559 
560 	// Read the line for the overall operation switch.
561 	libfla_test_read_next_line( buffer, input_stream );
562 	sscanf( buffer, "%d ", &op_switch );
563 
564 	// Read the line for the FLASH front-end.
565 	libfla_test_read_next_line( buffer, input_stream );
566 	sscanf( buffer, "%d ", &flash_front );
567 
568 	// Read the line for the FLA front-end.
569 	libfla_test_read_next_line( buffer, input_stream );
570 	sscanf( buffer, "%d ", &fla_front );
571 
572 	if ( op_switch == DISABLE_ALL )
573 	{
574 		op->flash_front  = DISABLE;
575 		op->fla_front    = DISABLE;
576 	}
577 	else
578 	{
579 		op->flash_front  = flash_front;
580 		op->fla_front    = fla_front;
581 	}
582 
583 	op->fla_unb_vars = DISABLE; // not used
584 	op->fla_opt_vars = DISABLE; // not used
585 	op->fla_blk_vars = DISABLE; // not used
586 }
587 
588 
589 
libfla_test_read_tests_for_op_front_fla_only(FILE * input_stream,test_op_t * op)590 void libfla_test_read_tests_for_op_front_fla_only( FILE* input_stream, test_op_t* op )
591 {
592 	char buffer[ INPUT_BUFFER_SIZE ];
593 	int  op_switch;
594 	int  fla_front;
595 
596 	// Read the line for the overall operation switch.
597 	libfla_test_read_next_line( buffer, input_stream );
598 	sscanf( buffer, "%d ", &op_switch );
599 
600 	// Read the line for the FLA front-end.
601 	libfla_test_read_next_line( buffer, input_stream );
602 	sscanf( buffer, "%d ", &fla_front );
603 
604 	if ( op_switch == DISABLE_ALL )
605 	{
606 		op->fla_front    = DISABLE;
607 	}
608 	else
609 	{
610 		op->fla_front    = fla_front;
611 	}
612 
613 	op->flash_front  = DISABLE; // not used
614 	op->fla_unb_vars = DISABLE; // not used
615 	op->fla_opt_vars = DISABLE; // not used
616 	op->fla_blk_vars = DISABLE; // not used
617 }
618 
619 
620 
libfla_test_read_tests_for_op_blas3(FILE * input_stream,test_op_t * op)621 void libfla_test_read_tests_for_op_blas3( FILE* input_stream, test_op_t* op )
622 {
623 	char buffer[ INPUT_BUFFER_SIZE ];
624 	int  op_switch;
625 	int  flash_front;
626 	int  fla_front;
627 	int  fla_unb_vars;
628 	int  fla_blk_vars;
629 	int  fla_unb_ext;
630 
631 	// Read the line for the overall operation switch.
632 	libfla_test_read_next_line( buffer, input_stream );
633 	sscanf( buffer, "%d ", &op_switch );
634 
635 	// Read the line for the FLASH front-end.
636 	libfla_test_read_next_line( buffer, input_stream );
637 	sscanf( buffer, "%d ", &flash_front );
638 
639 	// Read the line for the FLA front-end.
640 	libfla_test_read_next_line( buffer, input_stream );
641 	sscanf( buffer, "%d ", &fla_front );
642 
643 	// Read the line for the unblocked variants.
644 	libfla_test_read_next_line( buffer, input_stream );
645 	sscanf( buffer, "%d ", &fla_unb_vars );
646 
647 	// Read the line for the blocked variants.
648 	libfla_test_read_next_line( buffer, input_stream );
649 	sscanf( buffer, "%d ", &fla_blk_vars );
650 
651 	// Read the line for the unblocked external implementation.
652 	libfla_test_read_next_line( buffer, input_stream );
653 	sscanf( buffer, "%d ", &fla_unb_ext );
654 
655 	if ( op_switch == DISABLE_ALL )
656 	{
657 		op->flash_front  = DISABLE;
658 		op->fla_front    = DISABLE;
659 		op->fla_unb_vars = DISABLE;
660 		op->fla_blk_vars = DISABLE;
661 		op->fla_unb_ext  = DISABLE;
662 	}
663 	else
664 	{
665 		op->flash_front  = flash_front;
666 		op->fla_front    = fla_front;
667 		op->fla_unb_vars = fla_unb_vars;
668 		op->fla_blk_vars = fla_blk_vars;
669 		op->fla_unb_ext  = fla_unb_ext ;
670 	}
671 
672 	op->fla_opt_vars = DISABLE; // not used
673 	op->fla_blk_ext  = DISABLE; // not used
674 }
675 
676 
677 
libfla_test_read_parameter_file(char * input_filename,test_params_t * params)678 void libfla_test_read_parameter_file( char* input_filename, test_params_t* params )
679 {
680 	FILE* input_stream;
681 	char  buffer[ INPUT_BUFFER_SIZE ];
682 	char  temp[ INPUT_BUFFER_SIZE ];
683 	int   i;
684 
685 	// Attempt to open input file corresponding to input_filename as
686 	// read-only/binary.
687 	input_stream = fopen( input_filename, "rb" );
688 
689 	// Check for success.
690 	if ( input_stream == NULL )
691 	{
692 		libfla_test_output_error( "Failed to open input file %s. Check existence and permissions.\n",
693 		                          input_filename );
694 	}
695 
696 	// Read the number of repeats.
697 	libfla_test_read_next_line( buffer, input_stream );
698 	sscanf( buffer, "%u ", &(params->n_repeats) );
699 
700 	// Read the storage schemes to test. We should have at most three: 'r' for
701 	// row-major, 'c' for column-major, and 'g' for general strides, OR just
702 	// 'm' for mixed storage.
703 	libfla_test_read_next_line( buffer, input_stream );
704 	sscanf( buffer, "%s ", temp );
705 
706 	params->n_storage = strlen( temp );
707 	if ( params->n_storage > MAX_NUM_STORAGE )
708 	{
709 		libfla_test_output_error( "Detected too many storage schemes (%u) in input file.\n",
710 		                          params->n_storage );
711 	}
712 	strcpy( params->storage, temp );
713 
714 	// If 'm' is in the string, then remove all other chars.
715 	for ( i = 0; i < params->n_storage; ++i )
716 	{
717 		if ( params->storage[i] == 'm' )
718 		{
719 			sprintf( params->storage, "m" );
720 			break;
721 		}
722 	}
723 
724 	// Read the datatypes to test. We should have at most four: 's', 'd', 'c',
725 	// and 'z'.
726 	libfla_test_read_next_line( buffer, input_stream );
727 	sscanf( buffer, "%s ", temp );
728 
729 	params->n_datatypes = strlen( temp );
730 	if ( params->n_datatypes > MAX_NUM_DATATYPES )
731 	{
732 		libfla_test_output_error( "Detected too many datatype requests (%u) in input file.\n",
733 		                          params->n_datatypes );
734 	}
735 
736 	for( i = 0; i < params->n_datatypes; ++i )
737 	{
738 		if      ( temp[i] == 's' ) params->datatype[i] = FLA_FLOAT;
739 		else if ( temp[i] == 'd' ) params->datatype[i] = FLA_DOUBLE;
740 		else if ( temp[i] == 'c' ) params->datatype[i] = FLA_COMPLEX;
741 		else if ( temp[i] == 'z' ) params->datatype[i] = FLA_DOUBLE_COMPLEX;
742 
743 		params->datatype_char[i] = temp[i];
744 	}
745 
746 	// Read the blocksize to use for blocked algorithms on flat matrices.
747 	libfla_test_read_next_line( buffer, input_stream );
748 	sscanf( buffer, "%lu ", &(params->b_alg_flat) );
749 
750 	// Read the algorithmic blocksize to use for algorithms-by-blocks.
751 	libfla_test_read_next_line( buffer, input_stream );
752 	sscanf( buffer, "%lu ", &(params->b_alg_hier) );
753 
754 	// Read the storage (FLASH) blocksize to use for algorithms-by-blocks.
755 	libfla_test_read_next_line( buffer, input_stream );
756 	sscanf( buffer, "%lu ", &(params->b_flash) );
757 
758 	// Read the initial problem size to test.
759 	libfla_test_read_next_line( buffer, input_stream );
760 	sscanf( buffer, "%lu ", &(params->p_first) );
761 
762 	// Read the maximum problem size to test.
763 	libfla_test_read_next_line( buffer, input_stream );
764 	sscanf( buffer, "%lu ", &(params->p_max) );
765 
766 	// Read the problem size increment to test.
767 	libfla_test_read_next_line( buffer, input_stream );
768 	sscanf( buffer, "%lu ", &(params->p_inc) );
769 
770 	// Read the number of SuperMatrix threads to test with.
771 	libfla_test_read_next_line( buffer, input_stream );
772 	sscanf( buffer, "%u ", &(params->n_threads) );
773 
774 	// Read the requested course of action if a test fails.
775 	libfla_test_read_next_line( buffer, input_stream );
776 	sscanf( buffer, "%c ", &(params->reaction_to_failure) );
777 
778 	if ( params->reaction_to_failure != ON_FAILURE_IGNORE_CHAR &&
779 	     params->reaction_to_failure != ON_FAILURE_SLEEP_CHAR  &&
780 	     params->reaction_to_failure != ON_FAILURE_ABORT_CHAR  )
781 	{
782 		libfla_test_output_error( "Invalid reaction-to-failure character code (%c) in input file.\n",
783 		                          params->reaction_to_failure );
784 	}
785 
786 	// Close the file.
787 	fclose( input_stream );
788 
789 	libfla_test_output_info( "\n" );
790 	libfla_test_output_info( "--- test suite parameters ----------------------------\n" );
791 	libfla_test_output_info( "\n" );
792 	libfla_test_output_info( "n_repeats            %u\n", params->n_repeats );
793 	libfla_test_output_info( "n_storage            %u\n", params->n_storage );
794 	libfla_test_output_info( "storage              %s\n", params->storage );
795 	libfla_test_output_info( "n_datatypes          %u\n", params->n_datatypes );
796 	libfla_test_output_info( "datatype[0]          %d (%c)\n", params->datatype[0],
797 	                                                         params->datatype_char[0] );
798 	for( i = 1; i < params->n_datatypes; ++i )
799 	libfla_test_output_info( "        [%d]          %d (%c)\n", i, params->datatype[i],
800 	                                                             params->datatype_char[i] );
801 	libfla_test_output_info( "b_alg_flat           %u\n", params->b_alg_flat );
802 	libfla_test_output_info( "b_alg_hier           %u\n", params->b_alg_hier );
803 	libfla_test_output_info( "b_flash              %u\n", params->b_flash );
804 	libfla_test_output_info( "p_first              %u\n", params->p_first );
805 	libfla_test_output_info( "p_max                %u\n", params->p_max );
806 	libfla_test_output_info( "p_inc                %u\n", params->p_inc );
807 	libfla_test_output_info( "n_threads            %u\n", params->n_threads );
808 	libfla_test_output_info( "reaction_to_failure  %c\n", params->reaction_to_failure );
809 }
810 
811 
812 
libfla_test_read_next_line(char * buffer,FILE * input_stream)813 void libfla_test_read_next_line( char* buffer, FILE* input_stream )
814 {
815 	char temp[ INPUT_BUFFER_SIZE ];
816 
817 	// We want to read at least one line, so we use a do-while loop.
818 	do
819 	{
820 		// Read the next line into a temporary buffer and check success.
821 		if ( fgets( temp, INPUT_BUFFER_SIZE-1, input_stream ) == NULL )
822 		{
823 			if ( feof( input_stream ) )
824 				libfla_test_output_error( "Error reading input file: encountered unexpected EOF." );
825 			else
826 				libfla_test_output_error( "Error (non-EOF) reading input file." );
827 		}
828 	}
829     // We continue to read lines into buffer until the line is neither
830 	// commented nor blank.
831 	while ( temp[0] == COMMENT_CHAR || temp[0] == '\n' ||
832 	        temp[0] == ' '          || temp[0] == '\t' );
833 
834 
835 	// Save the string in temp, up to first white space character, into buffer.
836 	sscanf( temp, "%s ", buffer );
837 }
838 
839 
840 
libfla_test_output_info(char * message,...)841 void libfla_test_output_info( char* message, ... )
842 {
843 	FILE* output_stream = stdout;
844     va_list args;
845 
846     //fprintf( output_stream, "%s: ", libfla_test_binary_name );
847 
848     // Initialize variable argument environment.
849     va_start( args, message );
850 
851     // Parse the received message and print its components.
852     libfla_test_parse_message( output_stream, message, args );
853 
854     // Shutdown variable argument environment and clean up stack.
855     va_end( args );
856 
857 	// Flush the output stream.
858     fflush( output_stream );
859 }
860 
861 
862 
libfla_test_output_error(char * message,...)863 void libfla_test_output_error( char* message, ... )
864 {
865 	FILE*   output_stream = stderr;
866     va_list args;
867 
868     fprintf( output_stream, "%s: *** error ***: ", libfla_test_binary_name );
869 
870     // Initialize variable argument environment.
871     va_start( args, message );
872 
873     // Parse the received message and print its components.
874     libfla_test_parse_message( output_stream, message, args );
875 
876     // Shutdown variable argument environment and clean up stack.
877     va_end( args );
878 
879 	// Flush the output stream.
880     fflush( output_stream );
881 
882 	// Exit.
883 	exit(1);
884 }
885 
886 
887 
libfla_test_parse_message(FILE * output_stream,char * message,va_list args)888 void libfla_test_parse_message( FILE* output_stream, char* message, va_list args )
889 {
890 	int           c, cf;
891 	char          format_spec[8];
892 	unsigned int  the_uint;
893 	int           the_int;
894 	double        the_double;
895 	char*         the_string;
896 	char          the_char;
897 
898 	// Begin looping over message to insert variables wherever there are
899 	// format specifiers.
900 	for ( c = 0; message[c] != '\0'; )
901 	{
902 		if ( message[c] != '%' )
903 		{
904 			fprintf( output_stream, "%c", message[c] );
905 			c += 1;
906 		}
907 		else if ( message[c] == '%' && message[c+1] == '%' ) // handle escaped '%' chars.
908 		{
909 			fprintf( output_stream, "%c", message[c] );
910 			c += 2;
911 		}
912 		else
913 		{
914 			// Save the format string if there is one.
915 			format_spec[0] = '%';
916 			for ( c += 1, cf = 1; strchr( "udefsc", message[c] ) == NULL; ++c, ++cf )
917 			{
918 				format_spec[cf] = message[c];
919 			}
920 
921 			// Add the final type specifier, and null-terminate the string.
922 			format_spec[cf] = message[c];
923 			format_spec[cf+1] = '\0';
924 
925 			// Switch based on type, since we can't predict what will
926 			// va_args() will return.
927 			switch ( message[c] )
928 			{
929 				case 'u':
930 				the_uint = va_arg( args, unsigned int );
931 				fprintf( output_stream, format_spec, the_uint );
932 				break;
933 
934 				case 'd':
935 				the_int = va_arg( args, int );
936 				fprintf( output_stream, format_spec, the_int );
937 				break;
938 
939 				case 'e':
940 				the_double = va_arg( args, double );
941 				fprintf( output_stream, format_spec, the_double );
942 				break;
943 
944 				case 'f':
945 				the_double = va_arg( args, double );
946 				fprintf( output_stream, format_spec, the_double );
947 				break;
948 
949 				case 's':
950 				the_string = va_arg( args, char* );
951 				//fprintf( output_stream, "%s", the_string );
952 				fprintf( output_stream, format_spec, the_string );
953 				break;
954 
955 				case 'c':
956 				the_char = va_arg( args, int );
957 				fprintf( output_stream, "%c", the_char );
958 				break;
959 			}
960 
961 			// Move to next character past type specifier.
962 			c += 1;
963 		}
964 	}
965 }
966 
967 
968 
libfla_test_parse_command_line(int argc,char ** argv)969 void libfla_test_parse_command_line( int argc, char** argv )
970 {
971 	if ( argc > 1 )
972 	{
973 		fprintf( stderr, "Too many command line arguments.\n" );
974 		exit(1);
975 	}
976 
977 	// Copy the binary name to a global string so we can use it later.
978 	strncpy( libfla_test_binary_name, argv[0], MAX_BINARY_NAME_LENGTH );
979 }
980 
981 
982 
libfla_test_get_string_for_result(double residual,FLA_Datatype datatype,test_thresh_t * thresh)983 char* libfla_test_get_string_for_result( double         residual,
984                                          FLA_Datatype   datatype,
985                                          test_thresh_t* thresh )
986 {
987 	char* r_val;
988 
989 	if      ( datatype == FLA_FLOAT )
990 	{
991 		if      ( residual > thresh->failwarn_s ) r_val = libfla_test_fail_string;
992 		else if ( residual > thresh->warnpass_s ) r_val = libfla_test_warn_string;
993 		else                                      r_val = libfla_test_pass_string;
994 	}
995 	else if ( datatype == FLA_DOUBLE )
996 	{
997 		if      ( residual > thresh->failwarn_d ) r_val = libfla_test_fail_string;
998 		else if ( residual > thresh->warnpass_d ) r_val = libfla_test_warn_string;
999 		else                                      r_val = libfla_test_pass_string;
1000 	}
1001 	else if ( datatype == FLA_COMPLEX )
1002 	{
1003 		if      ( residual > thresh->failwarn_c ) r_val = libfla_test_fail_string;
1004 		else if ( residual > thresh->warnpass_c ) r_val = libfla_test_warn_string;
1005 		else                                      r_val = libfla_test_pass_string;
1006 	}
1007 	else // if ( datatype == FLA_DOUBLE_COMPLEX )
1008 	{
1009 		if      ( residual > thresh->failwarn_z ) r_val = libfla_test_fail_string;
1010 		else if ( residual > thresh->warnpass_z ) r_val = libfla_test_warn_string;
1011 		else                                      r_val = libfla_test_pass_string;
1012 	}
1013 
1014 	return r_val;
1015 }
1016 
1017 
1018 
libfla_test_init_strings(void)1019 void libfla_test_init_strings( void )
1020 {
1021 	sprintf( libfla_test_pass_string, "PASS" );
1022 	sprintf( libfla_test_warn_string, "MARGINAL" );
1023 	sprintf( libfla_test_fail_string, "FAILURE" );
1024 
1025 	sprintf( libfla_test_stor_chars, STORAGE_SCHEME_CHARS );
1026 }
1027 
1028 
1029 
libfla_test_fill_storage_strings(char ** sc_str,unsigned int n_storage_run,unsigned int n_matrices)1030 void libfla_test_fill_storage_strings( char** sc_str, unsigned int n_storage_run,
1031                                                       unsigned int n_matrices )
1032 {
1033 	unsigned int  sci, mi, i;
1034 	unsigned int* c;
1035 
1036 	// Allocate an array with one element per matrix argument. We will use
1037 	// this array to keep track of our progress as we canonically move
1038 	// though all possible storage combinations.
1039 	c = ( unsigned int* ) malloc( n_matrices * sizeof( unsigned int ) );
1040 
1041 	// Initialize all values in c to zero.
1042 	for ( i = 0; i < n_matrices; ++i ) c[i] = 0;
1043 
1044 	for ( sci = 0; sci < n_storage_run; ++sci )
1045 	{
1046 		// Iterate backwards since we want to form (for example):
1047 		// (1) ccc, (2) ccr, (3) crc, (4) crr, etc.
1048 		for ( i = 0, mi = n_matrices - 1; i < n_matrices; --mi, ++i )
1049 		{
1050 			// Map the current values in c to storage characters.
1051 			sc_str[sci][mi] = libfla_test_stor_chars[ c[mi] ];
1052 		}
1053 
1054 		// Terminate the string.
1055 		sc_str[sci][n_matrices] = '\0';
1056 
1057 		// Only try to increment/carryover if this is NOT the last storage
1058 		// run/combo.
1059 		if ( sci < n_storage_run - 1 )
1060 		{
1061 			// Increment the least-most significant counter.
1062 			c[ n_matrices - 1 ]++;
1063 
1064 			// Perform "carryover" if needed.
1065 			carryover( &c[ n_matrices - 1 ], n_matrices );
1066 		}
1067 	}
1068 
1069 /*
1070 printf( "\n" );
1071 for ( i = 0; i < n_storage_run; ++i )
1072   printf( "%s\n", sc_str[i] );
1073 printf( "\n" );
1074 abort();
1075 */
1076 
1077 	// Free the array.
1078 	free( c );
1079 }
1080 
1081 
carryover(unsigned int * c,unsigned int n_matrices)1082 void carryover( unsigned int* c, unsigned int n_matrices )
1083 {
1084 	if ( n_matrices == 1 ) return;
1085 	else
1086 	{
1087 		if ( *c == NUM_STORAGE_CHARS )
1088 		{
1089 			*c = 0;
1090 			*(c-1) += 1;
1091 			carryover( c-1, n_matrices-1 );
1092 		}
1093 	}
1094 }
1095 
1096 
libfla_test_op_driver(char * func_str,char * impl_var_str,unsigned int first_var,unsigned int last_var,unsigned int n_pc,char ** pc_str,unsigned int n_matrices,signed int impl,test_params_t params,test_thresh_t thresh,void (* f_exp)(test_params_t,unsigned int,char *,FLA_Datatype,unsigned int,unsigned int,unsigned int,signed int,double *,double *))1097 void libfla_test_op_driver( char*         func_str,
1098                             char*         impl_var_str,
1099                             unsigned int  first_var,
1100                             unsigned int  last_var,
1101                             unsigned int  n_pc,
1102                             char**        pc_str,
1103                             unsigned int  n_matrices,
1104                             signed int    impl,
1105                             test_params_t params,
1106                             test_thresh_t thresh,
1107                             void (*f_exp) (test_params_t, // params
1108                                            unsigned int,  // var
1109                                            char*,         // sc_cur_str (current storage string)
1110                                            FLA_Datatype,  // datatype
1111                                            unsigned int,  // p_cur
1112                                            unsigned int,  // pci (param combo counter)
1113                                            unsigned int,  // n_repeats
1114                                            signed int,    // impl
1115                                            double*,       // perf
1116                                            double* ) )    // residual
1117 {
1118 	unsigned int n_threads           = params.n_threads;
1119 	unsigned int n_storage           = params.n_storage;
1120 	unsigned int n_datatypes         = params.n_datatypes;
1121 	unsigned int p_first             = params.p_first;
1122 	unsigned int p_max               = params.p_max;
1123 	unsigned int p_inc               = params.p_inc;
1124 	unsigned int n_repeats           = params.n_repeats;
1125 	unsigned int reaction_to_failure = params.reaction_to_failure;
1126 	unsigned int sci, dt, p_cur, mat, pci, var;
1127 	char         datatype_char;
1128 	FLA_Datatype datatype;
1129 	double       perf, residual;
1130 	char*        pass_str;
1131 	char         blank_str[32];
1132 	char         func_param_str[64];
1133 	unsigned int n_spaces;
1134 	unsigned int n_storage_run;
1135 	char**       sc_str;
1136 
1137 	// Set the number of threads and/or disable SuperMatrix.
1138 	if ( n_threads == 0 ) FLASH_Queue_disable();
1139 	else                  FLASH_Queue_set_num_threads( n_threads );
1140 
1141 	// Execute the variant loop only once if we're runing a front-end test.
1142 	if ( impl == FLA_TEST_HIER_FRONT_END ||
1143 	     impl == FLA_TEST_FLAT_FRONT_END ||
1144 	     impl == FLA_TEST_FLAT_UNB_EXT   ||
1145 	     impl == FLA_TEST_FLAT_BLK_EXT )
1146 	{
1147 		first_var = 0;
1148 		last_var  = 0;
1149 	}
1150 
1151 	// Determine the total number of storage schemes.
1152 	if ( params.storage[0] == 'm' )
1153 	{
1154 		// Prepare to run all NUM_STORAGE_SCHEMES combinations for each
1155 		// matrix argument.
1156 		n_storage_run = ( unsigned int ) pow( ( double ) NUM_STORAGE_CHARS,
1157 		                                      ( double ) n_matrices );
1158 
1159 		sc_str = ( char** ) malloc( n_storage_run * sizeof( char* ) );
1160 		for ( sci = 0; sci < n_storage_run; ++sci )
1161 			sc_str[sci] = ( char* ) malloc( ( n_matrices + 1 ) * sizeof( char ) );
1162 
1163 		libfla_test_fill_storage_strings( sc_str, n_storage_run, n_matrices );
1164 	}
1165 	else // if ( params.storage[0] == 'c' ||
1166 	     //      params.storage[0] == 'r' ||
1167 	     //      params.storage[0] == 'g' )
1168 	{
1169 		// Only run combinations where all matrices are stored in one
1170 		// storage scheme or another (no mixed storage).
1171 		n_storage_run = n_storage;
1172 
1173 		sc_str = ( char** ) malloc( n_storage_run * sizeof( char* ) );
1174 		for ( sci = 0; sci < n_storage_run; ++sci )
1175 		{
1176 			// Allocate a string for a storage combination.
1177 			sc_str[sci] = ( char* ) malloc( ( n_matrices + 1 ) * sizeof( char ) );
1178 
1179 			// Fill the string with the current storage scheme character
1180 			// for each matrix operand.
1181 			for ( mat = 0; mat < n_matrices; ++mat )
1182 				sc_str[sci][mat] = params.storage[sci];
1183 			sc_str[sci][n_matrices] = '\0';
1184 		}
1185 	}
1186 
1187 	// Loop over variant, if applicable.
1188 	for ( var = first_var; var <= last_var; ++var )
1189 	{
1190 		// Loop over the requested storage schemes.
1191 		for ( sci = 0; sci < n_storage_run; ++sci )
1192 		{
1193 			// Loop over the requested datatypes.
1194 			for ( dt = 0; dt < n_datatypes; ++dt )
1195 			{
1196 				datatype      = params.datatype[dt];
1197 				datatype_char = params.datatype_char[dt];
1198 
1199 				// Loop over the requested problem sizes.
1200 				for ( p_cur = p_first; p_cur <= p_max; p_cur += p_inc )
1201 				{
1202 					// Loop over the operation's parameter combinations.
1203 					for ( pci = 0; pci < n_pc; ++pci )
1204 					{
1205 						f_exp( params,
1206 						       var,
1207 						       sc_str[sci],
1208 						       datatype,
1209 						       p_cur, pci, n_repeats, impl,
1210 						       &perf, &residual );
1211 
1212 						pass_str = libfla_test_get_string_for_result( residual,
1213 						                                              datatype,
1214 						                                              &thresh );
1215 
1216 						// Output the results. Use different formats depending on
1217 						// whether the results are from a front-end or variant.
1218 						libfla_test_build_function_string( func_str, impl,
1219 						                                   impl_var_str, var,
1220 						                                   n_pc, pc_str[pci],
1221 						                                   func_param_str );
1222 
1223 						n_spaces = MAX_FUNC_STRING_LENGTH - strlen( func_param_str );
1224 						fill_string_with_n_spaces( blank_str, n_spaces );
1225 
1226 						libfla_test_output_info( "   %s%s  %c|%-6s  %5u  %6.3lf  %9.2le   %s\n",
1227 						                         func_param_str, blank_str,
1228 						                         datatype_char, sc_str[sci],
1229 						                         p_cur, perf, residual, pass_str );
1230 
1231 						// If we need to check whether to do something on failure,
1232 						// do so now.
1233 						if ( reaction_to_failure == ON_FAILURE_SLEEP_CHAR )
1234 						{
1235 							if ( strstr( pass_str, FLA_TEST_FAIL_STRING ) == pass_str )
1236 								libfla_test_sleep();
1237 						}
1238 						else if ( reaction_to_failure == ON_FAILURE_ABORT_CHAR )
1239 						{
1240 							if ( strstr( pass_str, FLA_TEST_FAIL_STRING ) == pass_str )
1241 								libfla_test_abort();
1242 						}
1243 					}
1244 				}
1245 
1246 				libfla_test_output_info( "\n" );
1247 			}
1248 		}
1249 	}
1250 
1251 	for ( sci = 0; sci < n_storage_run; ++sci )
1252 		free( sc_str[sci] );
1253 	free( sc_str );
1254 }
1255 
1256 
1257 
libfla_test_build_function_string(char * func_base_str,signed int impl,char * impl_var_str,unsigned int var,unsigned int n_pc,char * pc_str,char * func_str)1258 void libfla_test_build_function_string( char*        func_base_str,
1259                                         signed int   impl,
1260                                         char*        impl_var_str,
1261                                         unsigned int var,
1262                                         unsigned int n_pc,
1263                                         char*        pc_str,
1264                                         char*        func_str )
1265 {
1266 
1267 	sprintf( func_str, "%s", func_base_str );
1268 
1269 	if ( impl == FLA_TEST_HIER_FRONT_END || impl == FLA_TEST_FLAT_FRONT_END )
1270 	{
1271 		//sprintf( &func_str[strlen(func_str)], "()" );
1272 		if ( n_pc > 1 )
1273 			sprintf( &func_str[strlen(func_str)], ":%s", pc_str );
1274 	}
1275 	else if ( impl == FLA_TEST_FLAT_UNB_EXT || impl == FLA_TEST_FLAT_BLK_EXT )
1276 	{
1277 		sprintf( &func_str[strlen(func_str)], "_%s", impl_var_str );
1278 
1279 		if ( n_pc > 1 )
1280 			sprintf( &func_str[strlen(func_str)], ":%s", pc_str );
1281 	}
1282 	else
1283 	{
1284 		if ( n_pc > 1 )
1285 			sprintf( &func_str[strlen(func_str)], "_%s", pc_str );
1286 
1287 		sprintf( &func_str[strlen(func_str)], "_%s%u", impl_var_str, var );
1288 	}
1289 }
1290 
1291 
1292 
fill_string_with_n_spaces(char * str,unsigned int n_spaces)1293 void fill_string_with_n_spaces( char* str, unsigned int n_spaces )
1294 {
1295 	unsigned int i;
1296 
1297 	for ( i = 0; i < n_spaces; ++i )
1298 		sprintf( &str[i], " " );
1299 }
1300 
1301 
1302 
libfla_test_obj_create(FLA_Datatype dt,FLA_Trans trans,char storage,dim_t m,dim_t n,FLA_Obj * A)1303 void libfla_test_obj_create( FLA_Datatype dt, FLA_Trans trans, char storage, dim_t m, dim_t n, FLA_Obj* A )
1304 {
1305 	dim_t m_trans = m;
1306 	dim_t n_trans = n;
1307 	dim_t rs_g;
1308 	dim_t cs_g;
1309 
1310 	if ( trans == FLA_TRANSPOSE || trans == FLA_CONJ_TRANSPOSE )
1311 	{
1312 		m_trans = n;
1313 		n_trans = m;
1314 	}
1315 
1316 	// In case of general strides, use strides with a column-major tilt.
1317 	rs_g = 2 * 1;
1318 	cs_g = 2 * m_trans;
1319 
1320 	if      ( storage == 'c' ) FLA_Obj_create( dt, m_trans, n_trans, 0,       0, A );
1321 	else if ( storage == 'r' ) FLA_Obj_create( dt, m_trans, n_trans, n_trans, 1, A );
1322 	else if ( storage == 'g' ) FLA_Obj_create( dt, m_trans, n_trans, rs_g, cs_g, A );
1323 	else                       FLA_Abort();
1324 }
1325 
1326 
1327 
libfla_test_sleep(void)1328 void libfla_test_sleep( void )
1329 {
1330 	int i;
1331 
1332 	libfla_test_output_info( "Resuming in " );
1333 	for ( i = SECONDS_TO_SLEEP; i > 0; --i )
1334 	{
1335 		libfla_test_output_info( "%d ", i );
1336 		sleep(1);
1337 	}
1338 	libfla_test_output_info( "\n" );
1339 }
1340 
1341 
libfla_test_abort(void)1342 void libfla_test_abort( void )
1343 {
1344 	abort();
1345 }
1346 
1347