]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - dense-linear-algebra-libraries/linalg.git/blob - blis/testsuite/src/test_libblis.c
00249a59a44d7accfd7f117aa48a2db862eb84c4
[dense-linear-algebra-libraries/linalg.git] / blis / testsuite / src / test_libblis.c
1 /*
3    BLIS    
4    An object-based framework for developing high-performance BLAS-like
5    libraries.
7    Copyright (C) 2014, The University of Texas at Austin
9    Redistribution and use in source and binary forms, with or without
10    modification, are permitted provided that the following conditions are
11    met:
12     - Redistributions of source code must retain the above copyright
13       notice, this list of conditions and the following disclaimer.
14     - Redistributions in binary form must reproduce the above copyright
15       notice, this list of conditions and the following disclaimer in the
16       documentation and/or other materials provided with the distribution.
17     - Neither the name of The University of Texas at Austin nor the names
18       of its contributors may be used to endorse or promote products
19       derived from this software without specific prior written permission.
21    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25    HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
35 #include "blis.h"
36 #include "test_libblis.h"
39 // Global variables.
40 char libblis_test_binary_name[ MAX_BINARY_NAME_LENGTH + 1 ];
42 char libblis_test_parameters_filename[ MAX_FILENAME_LENGTH + 1 ];
43 char libblis_test_operations_filename[ MAX_FILENAME_LENGTH + 1 ];
45 char libblis_test_pass_string[ MAX_PASS_STRING_LENGTH + 1 ];
46 char libblis_test_warn_string[ MAX_PASS_STRING_LENGTH + 1 ];
47 char libblis_test_fail_string[ MAX_PASS_STRING_LENGTH + 1 ];
49 char libblis_test_store_chars[ NUM_OPERAND_TYPES ][ MAX_STORE_VALS_PER_TYPE + 1 ];
51 char libblis_test_param_chars[ NUM_PARAM_TYPES ][ MAX_PARAM_VALS_PER_TYPE + 1 ];
55 int main( int argc, char** argv )
56 {
57         test_params_t params;
58         test_ops_t    ops;
60         // Initialize libblis.
61         bli_init();
63         // Initialize some strings.
64         libblis_test_init_strings();
66         // Parse the command line parameters.
67         libblis_test_parse_command_line( argc, argv );
69         // Read the global parameters file.
70         libblis_test_read_params_file( libblis_test_parameters_filename, &params );
72         // Read the operations parameter file.
73         libblis_test_read_ops_file( libblis_test_operations_filename, &ops );
74         
75         // Test the utility operations.
76         libblis_test_utility_ops( &params, &ops );
78         // Test the level-1v operations.
79         libblis_test_level1v_ops( &params, &ops );
81         // Test the level-1m operations.
82         libblis_test_level1m_ops( &params, &ops );
84         // Test the level-1f operations.
85         libblis_test_level1f_ops( &params, &ops );
87         // Test the level-2 operations.
88         libblis_test_level2_ops( &params, &ops );
90         // Test the level-3 micro-kernels.
91         libblis_test_level3_ukrs( &params, &ops );
93         // Test the level-3 operations.
94         libblis_test_level3_ops( &params, &ops );
96         // Finalize libblis.
97         bli_finalize();
99         // Return peacefully.
100         return 0;
105 void libblis_test_utility_ops( test_params_t* params, test_ops_t* ops )
107         libblis_test_randv( params, &(ops->randv) );
108         libblis_test_randm( params, &(ops->randm) );
113 void libblis_test_level1v_ops( test_params_t* params, test_ops_t* ops )
115         libblis_test_addv( params, &(ops->addv) );
116         libblis_test_axpyv( params, &(ops->axpyv) );
117         libblis_test_copyv( params, &(ops->copyv) );
118         libblis_test_dotv( params, &(ops->dotv) );
119         libblis_test_dotxv( params, &(ops->dotxv) );
120         libblis_test_normfv( params, &(ops->normfv) );
121         libblis_test_scalv( params, &(ops->scalv) );
122         libblis_test_scal2v( params, &(ops->scal2v) );
123         libblis_test_setv( params, &(ops->setv) );
124         libblis_test_subv( params, &(ops->subv) );
129 void libblis_test_level1m_ops( test_params_t* params, test_ops_t* ops )
131         libblis_test_addm( params, &(ops->addm) );
132         libblis_test_axpym( params, &(ops->axpym) );
133         libblis_test_copym( params, &(ops->copym) );
134         libblis_test_normfm( params, &(ops->normfm) );
135         libblis_test_scalm( params, &(ops->scalm) );
136         libblis_test_scal2m( params, &(ops->scal2m) );
137         libblis_test_setm( params, &(ops->setm) );
138         libblis_test_subm( params, &(ops->subm) );
143 void libblis_test_level1f_ops( test_params_t* params, test_ops_t* ops )
145         libblis_test_axpy2v( params, &(ops->axpy2v) );
146         libblis_test_dotaxpyv( params, &(ops->dotaxpyv) );
147         libblis_test_axpyf( params, &(ops->axpyf) );
148         libblis_test_dotxf( params, &(ops->dotxf) );
149         libblis_test_dotxaxpyf( params, &(ops->dotxaxpyf) );
154 void libblis_test_level2_ops( test_params_t* params, test_ops_t* ops )
156         libblis_test_gemv( params, &(ops->gemv) );
157         libblis_test_ger( params, &(ops->ger) );
158         libblis_test_hemv( params, &(ops->hemv) );
159         libblis_test_her( params, &(ops->her) );
160         libblis_test_her2( params, &(ops->her2) );
161         libblis_test_symv( params, &(ops->symv) );
162         libblis_test_syr( params, &(ops->syr) );
163         libblis_test_syr2( params, &(ops->syr2) );
164         libblis_test_trmv( params, &(ops->trmv) );
165         libblis_test_trsv( params, &(ops->trsv) );
170 void libblis_test_level3_ukrs( test_params_t* params, test_ops_t* ops )
172         libblis_test_gemm_ukr( params, &(ops->gemm_ukr) );
173         libblis_test_trsm_ukr( params, &(ops->trsm_ukr) );
174         libblis_test_gemmtrsm_ukr( params, &(ops->gemmtrsm_ukr) );
179 void libblis_test_level3_ops( test_params_t* params, test_ops_t* ops )
181         libblis_test_gemm( params, &(ops->gemm) );
182         libblis_test_hemm( params, &(ops->hemm) );
183         libblis_test_herk( params, &(ops->herk) );
184         libblis_test_her2k( params, &(ops->her2k) );
185         libblis_test_symm( params, &(ops->symm) );
186         libblis_test_syrk( params, &(ops->syrk) );
187         libblis_test_syr2k( params, &(ops->syr2k) );
188         libblis_test_trmm( params, &(ops->trmm) );
189         libblis_test_trmm3( params, &(ops->trmm3) );
190         libblis_test_trsm( params, &(ops->trsm) );
195 void libblis_test_read_ops_file( char* input_filename, test_ops_t* ops )
197         FILE* input_stream;
199         // Attempt to open input file corresponding to input_filename as
200         // read-only/binary.
201         input_stream = fopen( input_filename, "rb" );
202         libblis_test_fopen_check_stream( input_filename, input_stream );
204         // Begin reading operations input file.
206         //                                            dimensions          n_param   operation
208         // Section overrides
209         libblis_test_read_section_override( ops, input_stream, &(ops->util_over) );
210         libblis_test_read_section_override( ops, input_stream, &(ops->l1v_over) );
211         libblis_test_read_section_override( ops, input_stream, &(ops->l1m_over) );
212         libblis_test_read_section_override( ops, input_stream, &(ops->l1f_over) );
213         libblis_test_read_section_override( ops, input_stream, &(ops->l2_over) );
214         libblis_test_read_section_override( ops, input_stream, &(ops->l3ukr_over) );
215         libblis_test_read_section_override( ops, input_stream, &(ops->l3_over) );
217         // Utility operations
218         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_M,   0, &(ops->randv) );
219         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_MN,  0, &(ops->randm) );
221         // Level-1v
222         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_M,   1, &(ops->addv) );
223         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_M,   1, &(ops->axpyv) );
224         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_M,   1, &(ops->copyv) );
225         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_M,   2, &(ops->dotv) );
226         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_M,   2, &(ops->dotxv) );
227         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_M,   0, &(ops->normfv) );
228         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_M,   1, &(ops->scalv) );
229         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_M,   1, &(ops->scal2v) );
230         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_M,   0, &(ops->setv) );
231         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_M,   1, &(ops->subv) );
233         // Level-1m
234         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_MN,  1, &(ops->addm) );
235         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_MN,  1, &(ops->axpym) );
236         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_MN,  1, &(ops->copym) );
237         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_MN,  0, &(ops->normfm) );
238         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_MN,  1, &(ops->scalm) );
239         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_MN,  1, &(ops->scal2m) );
240         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_MN,  0, &(ops->setm) );
241         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_MN,  1, &(ops->subm) );
243         // Level-1f
244         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_M,   2, &(ops->axpy2v) );
245         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_M,   3, &(ops->dotaxpyv) );
246         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_MF,  2, &(ops->axpyf) );
247         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_MF,  2, &(ops->dotxf) );
248         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_MF,  4, &(ops->dotxaxpyf) );
250         // Level-2
251         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_MN,  2, &(ops->gemv) );
252         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_MN,  2, &(ops->ger) );
253         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_M,   3, &(ops->hemv) );
254         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_M,   2, &(ops->her) );
255         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_M,   3, &(ops->her2) );
256         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_M,   3, &(ops->symv) );
257         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_M,   2, &(ops->syr) );
258         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_M,   3, &(ops->syr2) );
259         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_M,   3, &(ops->trmv) );
260         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_M,   3, &(ops->trsv) );
262         // Level-3 micro-kernels
263         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_K,   0, &(ops->gemm_ukr) );
264         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_NO_DIMS,  1, &(ops->trsm_ukr) );
265         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_K,   1, &(ops->gemmtrsm_ukr) );
267         // Level-3
268         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_MNK, 2, &(ops->gemm) );
269         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_MN,  4, &(ops->hemm) );
270         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_MK,  2, &(ops->herk) );
271         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_MK,  3, &(ops->her2k) );
272         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_MN,  4, &(ops->symm) );
273         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_MK,  2, &(ops->syrk) );
274         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_MK,  3, &(ops->syr2k) );
275         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_MN,  4, &(ops->trmm) );
276         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_MN,  5, &(ops->trmm3) );
277         libblis_test_read_op_info( ops, input_stream, BLIS_TEST_DIMS_MN,  4, &(ops->trsm) );
279         // Output the section overrides.
280         libblis_test_output_section_overrides( stdout, ops );
282         // Close the file.
283         fclose( input_stream );
289 void libblis_test_read_params_file( char* input_filename, test_params_t* params )
291         FILE* input_stream;
292         char  buffer[ INPUT_BUFFER_SIZE ];
293         char  temp[ INPUT_BUFFER_SIZE ];
294         int   i;
296         // Attempt to open input file corresponding to input_filename as
297         // read-only/binary.
298         input_stream = fopen( input_filename, "rb" );
299         libblis_test_fopen_check_stream( input_filename, input_stream );
301         // Read the number of repeats.
302         libblis_test_read_next_line( buffer, input_stream );
303         sscanf( buffer, "%u ", &(params->n_repeats) );
305         // Read the matrix storage schemes to test. We should have at most three:
306         // 'r' for row-major, 'c' for column-major, and 'g' for general strides.
307         libblis_test_read_next_line( buffer, input_stream );
308         sscanf( buffer, "%s ", temp );
310         params->n_mstorage = strlen( temp );
311         if ( params->n_mstorage > MAX_NUM_MSTORAGE )
312         {
313                 libblis_test_printf_error( "Detected too many matrix storage schemes (%u) in input file.\n",
314                                            params->n_mstorage );
315         }
316         strcpy( params->storage[ BLIS_TEST_MATRIX_OPERAND ], temp );
318         // Read the vector storage schemes to test. We should have at most four:
319         // 'r' for row vectors with unit stride, 'c' for column vectors with unit
320         // stride, 'i' for row vectors with non-unit stride, and 'j' for column
321         // vectors with non-unit stride.
322         libblis_test_read_next_line( buffer, input_stream );
323         sscanf( buffer, "%s ", temp );
325         params->n_vstorage = strlen( temp );
326         if ( params->n_vstorage > MAX_NUM_VSTORAGE )
327         {
328                 libblis_test_printf_error( "Detected too many vector storage schemes (%u) in input file.\n",
329                                            params->n_vstorage );
330         }
331         strcpy( params->storage[ BLIS_TEST_VECTOR_OPERAND ], temp );
333         // Read whether to mix all storage combinations.
334         libblis_test_read_next_line( buffer, input_stream );
335         sscanf( buffer, "%u ", &(params->mix_all_storage) );
337         // Read the general stride "spacing".
338         libblis_test_read_next_line( buffer, input_stream );
339         sscanf( buffer, "%u ", &(params->gs_spacing) );
341         // Overwrite the existing storage character arrays with the sets provided.
342         strcpy( libblis_test_store_chars[BLIS_TEST_MATRIX_OPERAND],
343                          params->storage[BLIS_TEST_MATRIX_OPERAND] );
344         strcpy( libblis_test_store_chars[BLIS_TEST_VECTOR_OPERAND],
345                          params->storage[BLIS_TEST_VECTOR_OPERAND] );
347         // Read the datatypes to test. We should have at most four: 's', 'd', 'c',
348         // and 'z'.
349         libblis_test_read_next_line( buffer, input_stream );
350         sscanf( buffer, "%s ", temp );
352         params->n_datatypes = strlen( temp );
353         if ( params->n_datatypes > MAX_NUM_DATATYPES )
354         {
355                 libblis_test_printf_error( "Detected too many datatype requests (%u) in input file.\n",
356                                            params->n_datatypes );
357         }
359         for( i = 0; i < params->n_datatypes; ++i )
360         {
361                 if      ( temp[i] == 's' ) params->datatype[i] = BLIS_FLOAT;
362                 else if ( temp[i] == 'd' ) params->datatype[i] = BLIS_DOUBLE;
363                 else if ( temp[i] == 'c' ) params->datatype[i] = BLIS_SCOMPLEX;
364                 else if ( temp[i] == 'z' ) params->datatype[i] = BLIS_DCOMPLEX;
366                 params->datatype_char[i] = temp[i];
367         }
369         // Read the initial problem size to test.
370         libblis_test_read_next_line( buffer, input_stream );
371         sscanf( buffer, "%u ", &(params->p_first) );
373         // Read the maximum problem size to test.
374         libblis_test_read_next_line( buffer, input_stream );
375         sscanf( buffer, "%u ", &(params->p_max) );
377         // Read the problem size increment to test.
378         libblis_test_read_next_line( buffer, input_stream );
379         sscanf( buffer, "%u ", &(params->p_inc) );
381         // Read whether to enable 3mh.
382         libblis_test_read_next_line( buffer, input_stream );
383         sscanf( buffer, "%u ", &(params->enable_3mh) );
385         // Read whether to enable 3m.
386         libblis_test_read_next_line( buffer, input_stream );
387         sscanf( buffer, "%u ", &(params->enable_3m) );
389         // Read whether to enable 4mh.
390         libblis_test_read_next_line( buffer, input_stream );
391         sscanf( buffer, "%u ", &(params->enable_4mh) );
393         // Read whether to enable 4m.
394         libblis_test_read_next_line( buffer, input_stream );
395         sscanf( buffer, "%u ", &(params->enable_4m) );
397         // Read the requested error-checking level.
398         libblis_test_read_next_line( buffer, input_stream );
399         sscanf( buffer, "%u ", &(params->error_checking_level) );
401         // Read the requested course of action if a test fails.
402         libblis_test_read_next_line( buffer, input_stream );
403         sscanf( buffer, "%c ", &(params->reaction_to_failure) );
405         if ( params->reaction_to_failure != ON_FAILURE_IGNORE_CHAR &&
406              params->reaction_to_failure != ON_FAILURE_SLEEP_CHAR  &&
407              params->reaction_to_failure != ON_FAILURE_ABORT_CHAR  )
408         {
409                 libblis_test_printf_error( "Invalid reaction-to-failure character code (%c) in input file.\n",
410                                            params->reaction_to_failure );
411         }
413         // Read whether to output in matlab format.
414         libblis_test_read_next_line( buffer, input_stream );
415         sscanf( buffer, "%u ", &(params->output_matlab_format) );
417         // Read whether to output to files in addition to stdout.
418         libblis_test_read_next_line( buffer, input_stream );
419         sscanf( buffer, "%u ", &(params->output_files) );
421         // Close the file.
422         fclose( input_stream );
424         // Enable/disable the alternative complex implementations.
425         if ( params->enable_3mh ) bli_3mh_enable();
426         else                      bli_3mh_disable();
427         if ( params->enable_3m  ) bli_3m_enable();
428         else                      bli_3m_disable();
429         if ( params->enable_4mh ) bli_4mh_enable();
430         else                      bli_4mh_disable();
431         if ( params->enable_4m  ) bli_4m_enable();
432         else                      bli_4m_disable();
434         // Output the parameter struct.
435         libblis_test_output_params_struct( stdout, params );
439 void libblis_test_read_section_override( test_ops_t*  ops,
440                                          FILE*        input_stream,
441                                          int*         override )
443         char  buffer[ INPUT_BUFFER_SIZE ];
445         // Read the line for the section override switch.
446         libblis_test_read_next_line( buffer, input_stream );
447         sscanf( buffer, "%d ", override );
451 void libblis_test_read_op_info( test_ops_t*  ops,
452                                 FILE*        input_stream,
453                                 dimset_t     dimset,
454                                 unsigned int n_params,
455                                 test_op_t*   op )
457         char  buffer[ INPUT_BUFFER_SIZE ];
458         char  temp[ INPUT_BUFFER_SIZE ];
459         int   i, p;
461         // Read the line for the overall operation switch.
462         libblis_test_read_next_line( buffer, input_stream );
463         sscanf( buffer, "%d ", &(op->op_switch) );
465         // Read the line for the sequential front-end/micro-kernel interface.
466         libblis_test_read_next_line( buffer, input_stream );
467         sscanf( buffer, "%d ", &(op->front_seq) );
469         op->n_dims = libblis_test_get_n_dims_from_dimset( dimset );
470         op->dimset = dimset;
472         if ( op->n_dims > MAX_NUM_DIMENSIONS )
473         {
474                 libblis_test_printf_error( "Detected too many dimensions (%u) in input file to store.\n",
475                                            op->n_dims );
476         }
478         //printf( "n_dims = %u\n", op->n_dims );
480         // If there is at least one dimension for the current operation, read the
481         // dimension specifications, which encode the actual dimensions or the
482         // dimension ratios for each dimension.
483         if ( op->n_dims > 0 )
484         {
485                 libblis_test_read_next_line( buffer, input_stream );
487                 for ( i = 0, p = 0; i < op->n_dims; ++i )
488                 {
489                         //printf( "buffer[p]:       %s\n", &buffer[p] );
491                         // Advance until we hit non-whitespace (ie: the next number).
492                         for ( ; isspace( buffer[p] ); ++p ) ; 
494                         //printf( "buffer[p] after: %s\n", &buffer[p] );
496                         sscanf( &buffer[p], "%d", &(op->dim_spec[i]) );
498                         //printf( "dim[%d] = %d\n", i, op->dim_spec[i] );
500                         // Advance until we hit whitespace (ie: the space before the next number).
501                         for ( ; !isspace( buffer[p] ); ++p ) ; 
502                 }
503         }
505         // If there is at least one parameter for the current operation, read the
506         // parameter chars, which encode which parameter combinations to test.
507         if ( n_params > 0 )
508         {
509                 libblis_test_read_next_line( buffer, input_stream );
510                 sscanf( buffer, "%s ", temp );
512                 op->n_params = strlen( temp );
513                 if ( op->n_params > MAX_NUM_PARAMETERS )
514                 {
515                         libblis_test_printf_error( "Detected too many parameters (%u) in input file.\n",
516                                                    op->n_params );
517                 }
518                 if ( op->n_params != n_params )
519                 {
520                         libblis_test_printf_error( "Number of parameters specified by caller does not match length of parameter string in input file. strlen( temp ) = %u; n_params = %u\n", op->n_params, n_params );
521                 }
523                 strcpy( op->params, temp );
524         }
525         else
526         {
527                 op->n_params = 0;
528                 strcpy( op->params, "" );
529         }
531         // Initialize the "test done" switch.
532         op->test_done = FALSE;
534         // Initialize the parent pointer.
535         op->ops = ops;
537         // Disable operation if requested.
538         if ( op->op_switch == DISABLE_ALL )
539         {
540                 op->front_seq = DISABLE;
541         }
545 void libblis_test_output_section_overrides( FILE* os, test_ops_t* ops )
547         libblis_test_fprintf_c( os, "\n" );
548         libblis_test_fprintf_c( os, "--- Section overrides ---\n" );
549         libblis_test_fprintf_c( os, "\n" );
550         libblis_test_fprintf_c( os, "Utility operations           %d\n", ops->util_over );
551         libblis_test_fprintf_c( os, "Level-1v operations          %d\n", ops->l1v_over );
552         libblis_test_fprintf_c( os, "Level-1m operations          %d\n", ops->l1m_over );
553         libblis_test_fprintf_c( os, "Level-1f operations          %d\n", ops->l1f_over );
554         libblis_test_fprintf_c( os, "Level-2 operations           %d\n", ops->l2_over );
555         libblis_test_fprintf_c( os, "Level-3 micro-kernels        %d\n", ops->l3ukr_over );
556         libblis_test_fprintf_c( os, "Level-3 operations           %d\n", ops->l3_over );
557         libblis_test_fprintf_c( os, "\n" );
558         libblis_test_fprintf( os, "\n" );
563 void libblis_test_output_params_struct( FILE* os, test_params_t* params )
565         int    i;
566         //char   int_type_size_str[8];
567         gint_t int_type_size;
569         // If bli_info_get_int_type_size() returns 32 or 64, the size is forced.
570         // Otherwise, the size is chosen automatically. We query the result of
571         // that automatic choice via sizeof(gint_t).
572 /*      
573         if ( bli_info_get_int_type_size() == 32 ||
574              bli_info_get_int_type_size() == 64 )
575                 sprintf( int_type_size_str, "%d", ( int )bli_info_get_int_type_size() );
576         else
577                 sprintf( int_type_size_str, "%d", ( int )sizeof(gint_t) * 8 );
578 */
579         if ( bli_info_get_int_type_size() == 32 ||
580              bli_info_get_int_type_size() == 64 )
581                 int_type_size = bli_info_get_int_type_size();
582         else
583                 int_type_size = sizeof(gint_t) * 8;
585         // Output some system parameters.
587         libblis_test_fprintf_c( os, "\n" );
588         libblis_test_fprintf_c( os, "--- BLIS library info -------------------------------------\n" );
589         libblis_test_fprintf_c( os, "\n" );
590         libblis_test_fprintf_c( os, "version string               %s\n", bli_info_get_version_str() );
591         libblis_test_fprintf_c( os, "\n" );
592         libblis_test_fprintf_c( os, "--- BLIS config header ---\n" );
593         libblis_test_fprintf_c( os, "\n" );
594         libblis_test_fprintf_c( os, "integer type size (bits)     %d\n", ( int )int_type_size );
595         libblis_test_fprintf_c( os, "# of floating-point types    %d\n", ( int )bli_info_get_num_fp_types() );
596         libblis_test_fprintf_c( os, "maximum type size            %d\n", ( int )bli_info_get_max_type_size() );
597         libblis_test_fprintf_c( os, "\n" );
598         libblis_test_fprintf_c( os, "maximum number of threads    %d\n", ( int )bli_info_get_max_num_threads() );
599         libblis_test_fprintf_c( os, "\n" );
600         libblis_test_fprintf_c( os, "SIMD alignment (bytes)       %d\n", ( int )bli_info_get_simd_align_size() );
601         libblis_test_fprintf_c( os, "\n" );
602         libblis_test_fprintf_c( os, "stack memory allocation        \n" );
603         libblis_test_fprintf_c( os, "  address alignment (bytes)  %d\n", ( int )bli_info_get_stack_buf_align_size() );
604         libblis_test_fprintf_c( os, "\n" );
605         libblis_test_fprintf_c( os, "dynamic memory allocation      \n" );
606         libblis_test_fprintf_c( os, "  address alignment          %d\n", ( int )bli_info_get_heap_addr_align_size() );
607         libblis_test_fprintf_c( os, "  stride alignment           %d\n", ( int )bli_info_get_heap_stride_align_size() );
608         libblis_test_fprintf_c( os, "\n" );
609         libblis_test_fprintf_c( os, "contiguous memory allocation   \n" );
610         libblis_test_fprintf_c( os, "  # of mc x kc blocks        %d\n", ( int )bli_info_get_num_mc_x_kc_blocks() );
611         libblis_test_fprintf_c( os, "  # of kc x nc blocks        %d\n", ( int )bli_info_get_num_kc_x_nc_blocks() );
612         libblis_test_fprintf_c( os, "  # of mc x nc blocks        %d\n", ( int )bli_info_get_num_mc_x_nc_blocks() );
613         libblis_test_fprintf_c( os, "  block address alignment    %d\n", ( int )bli_info_get_contig_addr_align_size() );
614         libblis_test_fprintf_c( os, "  max preload byte offset    %d\n", ( int )bli_info_get_max_preload_byte_offset() );
615         libblis_test_fprintf_c( os, "  actual pool sizes (bytes)    \n" );
616         libblis_test_fprintf_c( os, "    for mc x kc blocks of A  %d\n", ( int )bli_info_get_mk_pool_size() );
617         libblis_test_fprintf_c( os, "    for kc x nc panels of B  %d\n", ( int )bli_info_get_kn_pool_size() );
618         libblis_test_fprintf_c( os, "    for mc x nc panels of C  %d\n", ( int )bli_info_get_mn_pool_size() );
619         libblis_test_fprintf_c( os, "\n" );
620         libblis_test_fprintf_c( os, "BLAS compatibility layer       \n" );
621         libblis_test_fprintf_c( os, "  enabled?                   %d\n", ( int )bli_info_get_enable_blas2blis() );
622         libblis_test_fprintf_c( os, "  integer type size (bits)   %d\n", ( int )bli_info_get_blas2blis_int_type_size() );
623         libblis_test_fprintf_c( os, "\n" );
624         libblis_test_fprintf_c( os, "--- BLIS kernel header ---\n" );
625         libblis_test_fprintf_c( os, "\n" );
626         libblis_test_fprintf_c( os, "floating-point types           s       d       c       z \n" );
627         libblis_test_fprintf_c( os, "  sizes (bytes)          %7u %7u %7u %7u\n", sizeof(float),
628                                                                                   sizeof(double),
629                                                                                   sizeof(scomplex),
630                                                                                   sizeof(dcomplex) );
631         libblis_test_fprintf_c( os, "\n" );
632         libblis_test_fprintf_c( os, "level-3 def cache blkszes      s       d       c       z \n" );
633         libblis_test_fprintf_c( os, "  m dimension            %7d %7d %7d %7d\n",
634                                 ( int )bli_info_get_default_mc_s(),
635                                 ( int )bli_info_get_default_mc_d(),
636                                 ( int )bli_info_get_default_mc_c(),
637                                 ( int )bli_info_get_default_mc_z() );
638         libblis_test_fprintf_c( os, "  k dimension            %7d %7d %7d %7d\n",
639                                 ( int )bli_info_get_default_kc_s(),
640                                 ( int )bli_info_get_default_kc_d(),
641                                 ( int )bli_info_get_default_kc_c(),
642                                 ( int )bli_info_get_default_kc_z() );
643         libblis_test_fprintf_c( os, "  n dimension            %7d %7d %7d %7d\n",
644                                 ( int )bli_info_get_default_nc_s(),
645                                 ( int )bli_info_get_default_nc_d(),
646                                 ( int )bli_info_get_default_nc_c(),
647                                 ( int )bli_info_get_default_nc_z() );
648         libblis_test_fprintf_c( os, "\n" );
649         libblis_test_fprintf_c( os, "level-3 max cache blkszes      s       d       c       z \n" );
650         libblis_test_fprintf_c( os, "  m dimension            %7d %7d %7d %7d\n",
651                                 ( int )bli_info_get_maximum_mc_s(),
652                                 ( int )bli_info_get_maximum_mc_d(),
653                                 ( int )bli_info_get_maximum_mc_c(),
654                                 ( int )bli_info_get_maximum_mc_z() );
655         libblis_test_fprintf_c( os, "  k dimension            %7d %7d %7d %7d\n",
656                                 ( int )bli_info_get_maximum_kc_s(),
657                                 ( int )bli_info_get_maximum_kc_d(),
658                                 ( int )bli_info_get_maximum_kc_c(),
659                                 ( int )bli_info_get_maximum_kc_z() );
660         libblis_test_fprintf_c( os, "  n dimension            %7d %7d %7d %7d\n",
661                                 ( int )bli_info_get_maximum_nc_s(),
662                                 ( int )bli_info_get_maximum_nc_d(),
663                                 ( int )bli_info_get_maximum_nc_c(),
664                                 ( int )bli_info_get_maximum_nc_z() );
665         libblis_test_fprintf_c( os, "\n" );
666         libblis_test_fprintf_c( os, "level-3 register blocksizes    s       d       c       z \n" );
667         libblis_test_fprintf_c( os, "  m dimension            %7d %7d %7d %7d\n",
668                                 ( int )bli_info_get_default_mr_s(),
669                                 ( int )bli_info_get_default_mr_d(),
670                                 ( int )bli_info_get_default_mr_c(),
671                                 ( int )bli_info_get_default_mr_z() );
672         libblis_test_fprintf_c( os, "  n dimension            %7d %7d %7d %7d\n",
673                                 ( int )bli_info_get_default_nr_s(),
674                                 ( int )bli_info_get_default_nr_d(),
675                                 ( int )bli_info_get_default_nr_c(),
676                                 ( int )bli_info_get_default_nr_z() );
677         libblis_test_fprintf_c( os, "\n" );
678         libblis_test_fprintf_c( os, "level-3 pack register blksz    s       d       c       z \n" );
679         libblis_test_fprintf_c( os, "  m dimension            %7d %7d %7d %7d\n",
680                                 ( int )bli_info_get_packdim_mr_s(),
681                                 ( int )bli_info_get_packdim_mr_d(),
682                                 ( int )bli_info_get_packdim_mr_c(),
683                                 ( int )bli_info_get_packdim_mr_z() );
684         libblis_test_fprintf_c( os, "  n dimension            %7d %7d %7d %7d\n",
685                                 ( int )bli_info_get_packdim_nr_s(),
686                                 ( int )bli_info_get_packdim_nr_d(),
687                                 ( int )bli_info_get_packdim_nr_c(),
688                                 ( int )bli_info_get_packdim_nr_z() );
689         libblis_test_fprintf_c( os, "\n" );
690         libblis_test_fprintf_c( os, "micro-panel alignment (bytes)  s       d       c       z \n" );
691         libblis_test_fprintf_c( os, "  A (left matrix)        %7d %7d %7d %7d\n",
692                                 ( int )bli_info_get_upanel_a_align_size_s(),
693                                 ( int )bli_info_get_upanel_a_align_size_d(),
694                                 ( int )bli_info_get_upanel_a_align_size_c(),
695                                 ( int )bli_info_get_upanel_a_align_size_z() );
696         libblis_test_fprintf_c( os, "  B (right matrix)       %7d %7d %7d %7d\n",
697                                 ( int )bli_info_get_upanel_b_align_size_s(),
698                                 ( int )bli_info_get_upanel_b_align_size_d(),
699                                 ( int )bli_info_get_upanel_b_align_size_c(),
700                                 ( int )bli_info_get_upanel_b_align_size_z() );
701         libblis_test_fprintf_c( os, "\n" );
702         libblis_test_fprintf_c( os, "level-2 cache blocksizes       s       d       c       z \n" );
703         libblis_test_fprintf_c( os, "  m dimension            %7d %7d %7d %7d\n",
704                                 ( int )bli_info_get_default_l2_mc_s(),
705                                 ( int )bli_info_get_default_l2_mc_d(),
706                                 ( int )bli_info_get_default_l2_mc_c(),
707                                 ( int )bli_info_get_default_l2_mc_z() );
708         libblis_test_fprintf_c( os, "  n dimension            %7d %7d %7d %7d\n",
709                                 ( int )bli_info_get_default_l2_nc_s(),
710                                 ( int )bli_info_get_default_l2_nc_d(),
711                                 ( int )bli_info_get_default_l2_nc_c(),
712                                 ( int )bli_info_get_default_l2_nc_z() );
713         libblis_test_fprintf_c( os, "\n" );
714         libblis_test_fprintf_c( os, "level-1f fusing factors        s       d       c       z \n" );
715         libblis_test_fprintf_c( os, "  default                %7d %7d %7d %7d\n",
716                                 ( int )bli_info_get_default_l1f_fuse_fac_s(),
717                                 ( int )bli_info_get_default_l1f_fuse_fac_d(),
718                                 ( int )bli_info_get_default_l1f_fuse_fac_c(),
719                                 ( int )bli_info_get_default_l1f_fuse_fac_z() );
720         libblis_test_fprintf_c( os, "  axpyf                  %7d %7d %7d %7d\n",
721                                 ( int )bli_info_get_axpyf_fuse_fac_s(),
722                                 ( int )bli_info_get_axpyf_fuse_fac_d(),
723                                 ( int )bli_info_get_axpyf_fuse_fac_c(),
724                                 ( int )bli_info_get_axpyf_fuse_fac_z() );
725         libblis_test_fprintf_c( os, "  dotxf                  %7d %7d %7d %7d\n",
726                                 ( int )bli_info_get_dotxf_fuse_fac_s(),
727                                 ( int )bli_info_get_dotxf_fuse_fac_d(),
728                                 ( int )bli_info_get_dotxf_fuse_fac_c(),
729                                 ( int )bli_info_get_dotxf_fuse_fac_z() );
730         libblis_test_fprintf_c( os, "  dotxaxpyf              %7d %7d %7d %7d\n",
731                                 ( int )bli_info_get_dotxaxpyf_fuse_fac_s(),
732                                 ( int )bli_info_get_dotxaxpyf_fuse_fac_d(),
733                                 ( int )bli_info_get_dotxaxpyf_fuse_fac_c(),
734                                 ( int )bli_info_get_dotxaxpyf_fuse_fac_z() );
735         libblis_test_fprintf_c( os, "\n" );
736         libblis_test_fprintf_c( os, "micro-kernel types             s       d       c       z\n" );
737         libblis_test_fprintf_c( os, "  gemm                   %7s %7s %7s %7s\n",
738                                 bli_info_get_gemm_ukr_type_string( BLIS_FLOAT ),
739                                 bli_info_get_gemm_ukr_type_string( BLIS_DOUBLE ),
740                                 bli_info_get_gemm_ukr_type_string( BLIS_SCOMPLEX ),
741                                 bli_info_get_gemm_ukr_type_string( BLIS_DCOMPLEX ) );
742         libblis_test_fprintf_c( os, "  gemmtrsm_l             %7s %7s %7s %7s\n",
743                                 bli_info_get_gemmtrsm_l_ukr_type_string( BLIS_FLOAT ),
744                                 bli_info_get_gemmtrsm_l_ukr_type_string( BLIS_DOUBLE ),
745                                 bli_info_get_gemmtrsm_l_ukr_type_string( BLIS_SCOMPLEX ),
746                                 bli_info_get_gemmtrsm_l_ukr_type_string( BLIS_DCOMPLEX ) );
747         libblis_test_fprintf_c( os, "  gemmtrsm_u             %7s %7s %7s %7s\n",
748                                 bli_info_get_gemmtrsm_u_ukr_type_string( BLIS_FLOAT ),
749                                 bli_info_get_gemmtrsm_u_ukr_type_string( BLIS_DOUBLE ),
750                                 bli_info_get_gemmtrsm_u_ukr_type_string( BLIS_SCOMPLEX ),
751                                 bli_info_get_gemmtrsm_u_ukr_type_string( BLIS_DCOMPLEX ) );
752         libblis_test_fprintf_c( os, "  trsm_l                 %7s %7s %7s %7s\n",
753                                 bli_info_get_trsm_l_ukr_type_string( BLIS_FLOAT ),
754                                 bli_info_get_trsm_l_ukr_type_string( BLIS_DOUBLE ),
755                                 bli_info_get_trsm_l_ukr_type_string( BLIS_SCOMPLEX ),
756                                 bli_info_get_trsm_l_ukr_type_string( BLIS_DCOMPLEX ) );
757         libblis_test_fprintf_c( os, "  trsm_u                 %7s %7s %7s %7s\n",
758                                 bli_info_get_trsm_u_ukr_type_string( BLIS_FLOAT ),
759                                 bli_info_get_trsm_u_ukr_type_string( BLIS_DOUBLE ),
760                                 bli_info_get_trsm_u_ukr_type_string( BLIS_SCOMPLEX ),
761                                 bli_info_get_trsm_u_ukr_type_string( BLIS_DCOMPLEX ) );
762         libblis_test_fprintf_c( os, "\n" );
763         libblis_test_fprintf_c( os, "--- BLIS implementation details ---\n" );
764         libblis_test_fprintf_c( os, "\n" );
765         libblis_test_fprintf_c( os, "level-3 implementations        s       d       c       z\n" );
766         libblis_test_fprintf_c( os, "  gemm                   %7s %7s %7s %7s\n",
767                                 bli_info_get_gemm_impl_string( BLIS_FLOAT ),
768                                 bli_info_get_gemm_impl_string( BLIS_DOUBLE ),
769                                 bli_info_get_gemm_impl_string( BLIS_SCOMPLEX ),
770                                 bli_info_get_gemm_impl_string( BLIS_DCOMPLEX ) );
771         libblis_test_fprintf_c( os, "  hemm                   %7s %7s %7s %7s\n",
772                                 bli_info_get_hemm_impl_string( BLIS_FLOAT ),
773                                 bli_info_get_hemm_impl_string( BLIS_DOUBLE ),
774                                 bli_info_get_hemm_impl_string( BLIS_SCOMPLEX ),
775                                 bli_info_get_hemm_impl_string( BLIS_DCOMPLEX ) );
776         libblis_test_fprintf_c( os, "  herk                   %7s %7s %7s %7s\n",
777                                 bli_info_get_herk_impl_string( BLIS_FLOAT ),
778                                 bli_info_get_herk_impl_string( BLIS_DOUBLE ),
779                                 bli_info_get_herk_impl_string( BLIS_SCOMPLEX ),
780                                 bli_info_get_herk_impl_string( BLIS_DCOMPLEX ) );
781         libblis_test_fprintf_c( os, "  her2k                  %7s %7s %7s %7s\n",
782                                 bli_info_get_her2k_impl_string( BLIS_FLOAT ),
783                                 bli_info_get_her2k_impl_string( BLIS_DOUBLE ),
784                                 bli_info_get_her2k_impl_string( BLIS_SCOMPLEX ),
785                                 bli_info_get_her2k_impl_string( BLIS_DCOMPLEX ) );
786         libblis_test_fprintf_c( os, "  symm                   %7s %7s %7s %7s\n",
787                                 bli_info_get_symm_impl_string( BLIS_FLOAT ),
788                                 bli_info_get_symm_impl_string( BLIS_DOUBLE ),
789                                 bli_info_get_symm_impl_string( BLIS_SCOMPLEX ),
790                                 bli_info_get_symm_impl_string( BLIS_DCOMPLEX ) );
791         libblis_test_fprintf_c( os, "  syrk                   %7s %7s %7s %7s\n",
792                                 bli_info_get_syrk_impl_string( BLIS_FLOAT ),
793                                 bli_info_get_syrk_impl_string( BLIS_DOUBLE ),
794                                 bli_info_get_syrk_impl_string( BLIS_SCOMPLEX ),
795                                 bli_info_get_syrk_impl_string( BLIS_DCOMPLEX ) );
796         libblis_test_fprintf_c( os, "  syr2k                  %7s %7s %7s %7s\n",
797                                 bli_info_get_syr2k_impl_string( BLIS_FLOAT ),
798                                 bli_info_get_syr2k_impl_string( BLIS_DOUBLE ),
799                                 bli_info_get_syr2k_impl_string( BLIS_SCOMPLEX ),
800                                 bli_info_get_syr2k_impl_string( BLIS_DCOMPLEX ) );
801         libblis_test_fprintf_c( os, "  trmm                   %7s %7s %7s %7s\n",
802                                 bli_info_get_trmm_impl_string( BLIS_FLOAT ),
803                                 bli_info_get_trmm_impl_string( BLIS_DOUBLE ),
804                                 bli_info_get_trmm_impl_string( BLIS_SCOMPLEX ),
805                                 bli_info_get_trmm_impl_string( BLIS_DCOMPLEX ) );
806         libblis_test_fprintf_c( os, "  trmm3                  %7s %7s %7s %7s\n",
807                                 bli_info_get_trmm3_impl_string( BLIS_FLOAT ),
808                                 bli_info_get_trmm3_impl_string( BLIS_DOUBLE ),
809                                 bli_info_get_trmm3_impl_string( BLIS_SCOMPLEX ),
810                                 bli_info_get_trmm3_impl_string( BLIS_DCOMPLEX ) );
811         libblis_test_fprintf_c( os, "  trsm                   %7s %7s %7s %7s\n",
812                                 bli_info_get_trsm_impl_string( BLIS_FLOAT ),
813                                 bli_info_get_trsm_impl_string( BLIS_DOUBLE ),
814                                 bli_info_get_trsm_impl_string( BLIS_SCOMPLEX ),
815                                 bli_info_get_trsm_impl_string( BLIS_DCOMPLEX ) );
816         libblis_test_fprintf_c( os, "\n" );
817         libblis_test_fprintf( os, "\n" );
819         // Output the contents of the param struct.
820         libblis_test_fprintf_c( os, "\n" );
821         libblis_test_fprintf_c( os, "--- BLIS test suite parameters ----------------------------\n" );
822         libblis_test_fprintf_c( os, "\n" );
823         libblis_test_fprintf_c( os, "num repeats per experiment   %u\n", params->n_repeats );
824         libblis_test_fprintf_c( os, "num matrix storage schemes   %u\n", params->n_mstorage );
825         libblis_test_fprintf_c( os, "storage[ matrix ]            %s\n", params->storage[ BLIS_TEST_MATRIX_OPERAND ] );
826         libblis_test_fprintf_c( os, "num vector storage schemes   %u\n", params->n_vstorage );
827         libblis_test_fprintf_c( os, "storage[ vector ]            %s\n", params->storage[ BLIS_TEST_VECTOR_OPERAND ] );
828         libblis_test_fprintf_c( os, "mix all storage schemes?     %u\n", params->mix_all_storage );
829         libblis_test_fprintf_c( os, "general stride spacing       %u\n", params->gs_spacing );
830         libblis_test_fprintf_c( os, "num datatypes                %u\n", params->n_datatypes );
831         libblis_test_fprintf_c( os, "datatype[0]                  %d (%c)\n", params->datatype[0],
832                                                                         params->datatype_char[0] );
833         for( i = 1; i < params->n_datatypes; ++i )
834         libblis_test_fprintf_c( os, "        [%d]                  %d (%c)\n", i, params->datatype[i],
835                                                                             params->datatype_char[i] );
836         libblis_test_fprintf_c( os, "problem size: first to test  %u\n", params->p_first );
837         libblis_test_fprintf_c( os, "problem size: max to test    %u\n", params->p_max );
838         libblis_test_fprintf_c( os, "problem size increment       %u\n", params->p_inc );
839         libblis_test_fprintf_c( os, "enable 3mh?                  %u\n", params->enable_3mh );
840         libblis_test_fprintf_c( os, "enable 3m?                   %u\n", params->enable_3m );
841         libblis_test_fprintf_c( os, "enable 4mh?                  %u\n", params->enable_4mh );
842         libblis_test_fprintf_c( os, "enable 4m?                   %u\n", params->enable_4m );
843         libblis_test_fprintf_c( os, "error-checking level         %u\n", params->error_checking_level );
844         libblis_test_fprintf_c( os, "reaction to failure          %c\n", params->reaction_to_failure );
845         libblis_test_fprintf_c( os, "output in matlab format?     %u\n", params->output_matlab_format );
846         libblis_test_fprintf_c( os, "output to stdout AND files?  %u\n", params->output_files );
847         libblis_test_fprintf_c( os, "\n" );
848         libblis_test_fprintf( os, "\n" );
853 void libblis_test_output_op_struct( FILE* os, test_op_t* op, char* op_str )
855         dimset_t dimset = op->dimset;
857         libblis_test_fprintf_c( os, "test %s seq front-end?    %d\n", op_str, op->front_seq );
859         if (      dimset == BLIS_TEST_DIMS_MNK )
860         {
861                 libblis_test_fprintf_c( os, "%s m n k                  %d %d %d\n", op_str,
862                                                 op->dim_spec[0], op->dim_spec[1], op->dim_spec[2] );
863         }
864         else if ( dimset == BLIS_TEST_DIMS_MN )
865         {
866                 libblis_test_fprintf_c( os, "%s m n                    %d %d\n", op_str,
867                                                 op->dim_spec[0], op->dim_spec[1] );
868         }
869         else if ( dimset == BLIS_TEST_DIMS_MK )
870         {
871                 libblis_test_fprintf_c( os, "%s m k                    %d %d\n", op_str,
872                                                 op->dim_spec[0], op->dim_spec[1] );
873         }
874         else if ( dimset == BLIS_TEST_DIMS_M ||
875                   dimset == BLIS_TEST_DIMS_MF )
876         {
877                 libblis_test_fprintf_c( os, "%s m                      %d\n", op_str,
878                                                 op->dim_spec[0] );
879         }
880         else if ( dimset == BLIS_TEST_DIMS_K )
881         {
882                 libblis_test_fprintf_c( os, "%s k                      %d\n", op_str,
883                                                 op->dim_spec[0] );
884         }
885         else if ( dimset == BLIS_TEST_NO_DIMS )
886         {
887                 // Do nothing.
888         }
889         else
890         {
891                 libblis_test_printf_error( "Invalid dimension combination.\n" );
892         }
894         if ( op->n_params > 0 )
895                 libblis_test_fprintf_c( os, "%s operand params         %s\n", op_str, op->params );
896         else
897                 libblis_test_fprintf_c( os, "%s operand params         %s\n", op_str, "(none)" );
899         libblis_test_fprintf_c( os, "\n" );
900         libblis_test_fprintf( os, "\n" );
905 char* libblis_test_get_string_for_result( double    resid,
906                                           num_t     dt,
907                                           thresh_t* thresh )
909         char* r_val;
911         if      ( resid > thresh[dt].failwarn ) r_val = libblis_test_fail_string;
912         else if ( resid > thresh[dt].warnpass ) r_val = libblis_test_warn_string;
913         else                                    r_val = libblis_test_pass_string;
915         return r_val;
920 param_t libblis_test_get_param_type_for_char( char p_type )
922         param_t r_val;
924         if      ( p_type == 's' ) r_val = BLIS_TEST_PARAM_SIDE;
925         else if ( p_type == 'u' ) r_val = BLIS_TEST_PARAM_UPLO;
926         else if ( p_type == 'e' ) r_val = BLIS_TEST_PARAM_UPLODE;
927         else if ( p_type == 'h' ) r_val = BLIS_TEST_PARAM_TRANS;
928         else if ( p_type == 'c' ) r_val = BLIS_TEST_PARAM_CONJ;
929         else if ( p_type == 'd' ) r_val = BLIS_TEST_PARAM_DIAG;
930         else
931         {
932                 r_val = 0;
933                 libblis_test_printf_error( "Invalid parameter character.\n" );
934         }
936         return r_val;
941 operand_t libblis_test_get_operand_type_for_char( char o_type )
943         operand_t r_val;
945         if      ( o_type == 'm' ) r_val = BLIS_TEST_MATRIX_OPERAND;
946         else if ( o_type == 'v' ) r_val = BLIS_TEST_VECTOR_OPERAND;
947         else
948         {
949                 r_val = 0;
950                 libblis_test_printf_error( "Invalid operand character.\n" );
951         }
953         return r_val;
958 unsigned int libblis_test_get_n_dims_from_dimset( dimset_t dimset )
960         unsigned int n_dims;
962         if      ( dimset == BLIS_TEST_DIMS_MNK ) n_dims = 3;
963         else if ( dimset == BLIS_TEST_DIMS_MN  ) n_dims = 2;
964         else if ( dimset == BLIS_TEST_DIMS_MK  ) n_dims = 2;
965         else if ( dimset == BLIS_TEST_DIMS_M   ) n_dims = 1;
966         else if ( dimset == BLIS_TEST_DIMS_MF  ) n_dims = 1;
967         else if ( dimset == BLIS_TEST_DIMS_K   ) n_dims = 1;
968         else if ( dimset == BLIS_TEST_NO_DIMS  ) n_dims = 0;
969         else
970         {
971                 n_dims = 0;
972                 libblis_test_printf_error( "Invalid dimension combination.\n" );
973         }
975         return n_dims;
980 unsigned int libblis_test_get_n_dims_from_string( char* dims_str )
982         unsigned int n_dims;
983         char*        cp;
985         cp = dims_str;
987         for ( n_dims = 0; *cp != '\0'; ++n_dims )
988         {
989                 //printf( "n_dims = %u\n", n_dims );
990                 while ( isspace( *cp ) )
991                 {
992                         //printf( "current char: _%c_", *cp );
993                          ++cp;
994                 }
996                 while ( isdigit( *cp ) )
997                 {
998                         //printf( "current char: _%c_", *cp );
999                         ++cp;
1000                 }
1001         }
1002         //printf( "n_dims finally = %u\n", n_dims );
1004         return n_dims;
1009 dim_t libblis_test_get_dim_from_prob_size( int          dim_spec,
1010                                            unsigned int p_size )
1012         dim_t dim;
1014         if ( dim_spec < 0 ) dim = p_size / bli_abs(dim_spec);
1015         else                dim = dim_spec;
1017         return dim;
1022 void libblis_test_fill_param_strings( char*         p_spec_str,
1023                                       char**        chars_for_param,
1024                                       unsigned int  n_params,
1025                                       unsigned int  n_param_combos,
1026                                       char**        pc_str )
1028         unsigned int  pci, pi, i;
1029         unsigned int* counter;
1030         unsigned int* n_vals_for_param;
1032         // Allocate an array that will store the number of parameter values
1033         // for each parameter.
1034         n_vals_for_param = ( unsigned int* ) malloc( n_params * sizeof( unsigned int ) );
1036         // Fill n_vals_for_param[i] with the number of parameter values (chars)
1037         // in chars_for_param[i] (this is simply the string length).
1038         for ( i = 0; i < n_params; ++i )
1039         {
1040                 if ( p_spec_str[i] == '?' ) n_vals_for_param[i] = strlen( chars_for_param[i] );
1041                 else                        n_vals_for_param[i] = 1;
1042         }
1044         // Allocate an array with one digit per parameter. We will use
1045         // this array to keep track of our progress as we canonically move
1046         // though all possible parameter combinations.
1047         counter = ( unsigned int* ) malloc( n_params * sizeof( unsigned int ) );
1049         // Initialize all values in c to zero.
1050         for ( i = 0; i < n_params; ++i ) counter[i] = 0;
1052         for ( pci = 0; pci < n_param_combos; ++pci )
1053         {
1054                 // Iterate backwards through each parameter string we create, since we
1055                 // want to form (for example, if the parameters are transa and conjx:
1056                 // (1) nn, (2) nc, (3) cn, (4) cc, (5) tn, (6) tc, (7) hn, (8) hc.
1057                 for ( i = 0, pi = n_params - 1; i < n_params; --pi, ++i )
1058                 {
1059                         // If the current parameter character, p_spec_str[pi] is fixed (ie: if
1060                         // it is not '?'), then just copy it into the parameter combination
1061                         // string. Otherwise, map the current integer value in c to the
1062                         // corresponding character in char_for_param[pi].
1063                         if ( p_spec_str[pi] != '?' )
1064                                 pc_str[pci][pi] = p_spec_str[pi];
1065                         else
1066                                 pc_str[pci][pi] = chars_for_param[ pi ][ counter[pi] ];
1067                 }
1069                 // Terminate the current parameter combination string.
1070                 pc_str[pci][n_params] = '\0';
1072                 // Only try to increment/carryover if this is NOT the last param
1073                 // combo.
1074                 if ( pci < n_param_combos - 1 )
1075                 {
1076                         // Increment the least-most significant counter.
1077                         counter[ n_params - 1 ]++;
1079                         // Perform "carryover" if needed.
1080                         carryover( &counter[ n_params - 1 ],
1081                                    &n_vals_for_param[ n_params - 1 ],
1082                                    n_params );
1083                 }
1084         }
1086         // Free the temporary arrays.
1087         free( counter );
1089         // Free the array holding the number of parameter values for each
1090         // parameter.
1091         free( n_vals_for_param );
1096 void carryover( unsigned int* c,
1097                 unsigned int* n_vals_for_param,
1098                 unsigned int  n_params )
1100         if ( n_params == 1 ) return;
1101         else
1102         {
1103                 if ( *c == *n_vals_for_param )
1104                 {
1105                         *c = 0;
1106                         *(c-1) += 1;
1107                         carryover( c-1, n_vals_for_param-1, n_params-1 );
1108                 }
1109         }
1114 void libblis_test_op_driver( test_params_t* params,
1115                              test_op_t*     op,
1116                              iface_t        iface,
1117                              char*          op_str,
1118                              char*          p_types,
1119                              char*          o_types,
1120                              thresh_t*      thresh,
1121                              void (*f_exp)  (test_params_t*, // params struct
1122                                              test_op_t*,     // op struct
1123                                              iface_t,        // iface
1124                                              num_t,          // datatype (current datatype)
1125                                              char*,          // pc_str (current param string)
1126                                              char*,          // sc_str (current storage string)
1127                                              unsigned int,   // p_cur (current problem size)
1128                                              double*,        // perf
1129                                              double* ) )     // residual
1131         unsigned int  n_mstorage          = params->n_mstorage;
1132         unsigned int  n_vstorage          = params->n_vstorage;
1133         unsigned int  n_datatypes         = params->n_datatypes;
1134         unsigned int  p_first             = params->p_first;
1135         unsigned int  p_max               = params->p_max;
1136         unsigned int  p_inc               = params->p_inc;
1137         unsigned int  mix_all_storage     = params->mix_all_storage;
1138         unsigned int  reaction_to_failure = params->reaction_to_failure;
1140         num_t         datatype;
1141         char          dt_char;
1143         char*         p_spec_str;
1144         unsigned int  n_params;
1145         char**        chars_for_param;
1146         unsigned int  n_param_combos;
1147         char**        pc_str;
1149         char          s_spec_str[ MAX_NUM_OPERANDS + 1 ];
1150         unsigned int  n_operands;
1151         char**        chars_for_storage;
1152         unsigned int  n_store_combos;
1153         char**        sc_str;
1155         unsigned int  p_cur, pi;
1156         unsigned int  dt, pci, sci, i, j, o;
1158         double        perf, resid;
1159         char*         pass_str;
1160         char          blank_str[32];
1161         char          funcname_str[64];
1162         char          dims_str[64];
1163         char          label_str[128];
1164         unsigned int  n_spaces;
1165         unsigned int  n_dims_print;
1167         FILE*         output_stream = NULL;
1170         // If output to files was requested, attempt to open a file stream.
1171         if ( params->output_files )
1172                 libblis_test_fopen_ofile( op_str, iface, &output_stream );
1174         // Set the error-checking level according to what was specified in the
1175         // input file.
1176         if ( params->error_checking_level == 0 )
1177                 bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING );
1178         else
1179                 bli_error_checking_level_set( BLIS_FULL_ERROR_CHECKING );
1181         // Obtain the parameter specification (filter) string.
1182         p_spec_str = op->params;
1184         // Figure out how many parameters we have.
1185         n_params = strlen( p_types );
1187         if ( strlen( p_types ) != strlen( p_spec_str) )
1188         {
1189                 libblis_test_printf_error( "Parameter specification string from input file does not match length of p_types string.\n" );
1190         }
1192         // Allocate an array that stores pointers to the sets of possible parameter
1193         // chars for each parameter.
1194         chars_for_param = ( char** ) malloc( n_params * sizeof( char* ) );
1196         // Set the values in chars_for_param to the appropriate string addresses.
1197         for ( i = 0; i < n_params; ++i )
1198         {
1199                 param_t param_type = libblis_test_get_param_type_for_char( p_types[i] );
1200                 chars_for_param[i] = libblis_test_param_chars[ param_type ];
1201 #ifdef CBLAS
1203                 if (strcmp(op_str,"hemm")==0 || strcmp(op_str,"herk")==0 || strcmp(op_str,"her2k")==0 )
1204                 {
1205                         if(param_type == BLIS_TEST_PARAM_TRANS)
1206                         {
1207                                 //printf("chars %s",chars_for_param[i]);
1208                                 chars_for_param[i] = "nh";
1209                         }
1210                 }
1211                 if( strcmp(op_str,"hemv")==0 || strcmp(op_str,"her") ==0 || strcmp(op_str,"her2") ==0 ||
1212                         strcmp(op_str,"symv")==0 || strcmp(op_str,"syr") ==0 || strcmp(op_str,"syr2") ==0 ||
1213                         strcmp(op_str,"gemv")==0 || strcmp(op_str,"ger")==0 )
1214                 {
1215                         if(param_type == BLIS_TEST_PARAM_CONJ)
1216                         {
1217                                 //printf("chars %s",chars_for_param[i]);
1218                                 chars_for_param[i] = "n";
1219                         }
1220                 }
1221 #endif
1222         }
1224         // Compute the total number of parameter combinations to test (which is
1225         // simply the product of the string lengths of chars_for_param[i].
1226         for ( i = 0, n_param_combos = 1; i < n_params; ++i )
1227         {
1228                 if ( p_spec_str[i] == '?' )
1229                         n_param_combos *= strlen( chars_for_param[i] );
1230         }
1232         // Allocate an array of parameter combination strings, one for each
1233         // parameter combination that needs to be tested.
1234         pc_str = ( char** ) malloc( n_param_combos * sizeof( char* ) );
1235         for ( i = 0; i < n_param_combos; ++i )
1236                 pc_str[i] = ( char* ) malloc( ( n_params + 1 ) * sizeof( char ) );
1238         // Fill the parameter combination strings in pc_str with the parameter
1239         // combinations called for by the parameter string p_spec_str.
1240         libblis_test_fill_param_strings( p_spec_str,
1241                                          chars_for_param,
1242                                          n_params,
1243                                          n_param_combos,
1244                                          pc_str );
1248         // Figure out how many operands we have.
1249         n_operands = strlen( o_types );
1251         // If we are testing a micro-kernel, unconditionally disable the
1252         // "mix all storage" option.
1253         if ( iface == BLIS_TEST_SEQ_UKERNEL )
1254                 mix_all_storage = DISABLE;
1256         // Determine the total number of storage schemes.
1257         if ( mix_all_storage )
1258         {
1259                 // Fill storage specification string with wildcard chars.
1260                 for ( i = 0; i < n_operands; ++i )
1261                         s_spec_str[i] = '?';
1262                 s_spec_str[i] = '\0';
1264                 // Allocate an array that stores pointers to the sets of possible
1265                 // storage chars for each operand.
1266                 chars_for_storage = ( char** ) malloc( n_operands * sizeof( char* ) );
1268                 // Set the values in chars_for_storage to the address of the string
1269                 // that holds the storage chars.
1270                 for ( i = 0; i < n_operands; ++i )
1271                 {
1272                         operand_t operand_type = libblis_test_get_operand_type_for_char( o_types[i] );
1273                         chars_for_storage[i] = libblis_test_store_chars[ operand_type ];
1274                 }
1276                 // Compute the total number of storage combinations to test (which is
1277                 // simply the product of the string lengths of chars_for_storage[i].
1278                 for ( i = 0, n_store_combos = 1; i < n_operands; ++i )
1279                 {
1280                         if ( s_spec_str[i] == '?' )
1281                                 n_store_combos *= strlen( chars_for_storage[i] );
1282                 }
1284                 // Allocate an array of storage combination strings, one for each
1285                 // storage combination that needs to be tested.
1286                 sc_str = ( char** ) malloc( n_store_combos * sizeof( char* ) );
1287                 for ( sci = 0; sci < n_store_combos; ++sci )
1288                         sc_str[sci] = ( char* ) malloc( ( n_operands + 1 ) * sizeof( char ) );
1291                 // Fill the storage combination strings in sc_str with the storage
1292                 // combinations called for by the storage string p_spec_str.
1293                 libblis_test_fill_param_strings( s_spec_str,
1294                                              chars_for_storage,
1295                                              n_operands,
1296                                              n_store_combos,
1297                                              sc_str );
1298         }
1299         else // if ( !mix_all_storage )
1300         {
1301                 // Only run combinations where all operands of either type (matrices
1302                 // or vectors) are stored in one storage scheme or another (no mixing
1303                 // of schemes within the same operand type).
1304                 unsigned int n_mat_operands = 0;
1305                 unsigned int n_vec_operands = 0;
1307                 for ( o = 0; o < n_operands; ++o )
1308                 {
1309                         operand_t operand_type
1310                                   = libblis_test_get_operand_type_for_char( o_types[o] );
1311                         if      ( operand_type == BLIS_TEST_MATRIX_OPERAND ) ++n_mat_operands;
1312                         else if ( operand_type == BLIS_TEST_VECTOR_OPERAND ) ++n_vec_operands;
1313                 }
1315                 // We compute the total number of storage combinations based on whether
1316                 // the current operation has only matrix operands, only vector operands,
1317                 // or both.
1318                 if      ( n_vec_operands == 0 )
1319                 {
1320                         n_store_combos = n_mstorage;
1321                         n_vstorage = 1;
1322                 }
1323                 else if ( n_mat_operands == 0 )
1324                 {
1325                         n_store_combos = n_vstorage;
1326                         n_mstorage = 1;
1327                 }
1328                 else
1329                 {
1330                         n_store_combos = n_mstorage * n_vstorage;
1331                 }
1333                 sc_str = ( char** ) malloc( n_store_combos * sizeof( char* ) );
1335                 for ( j = 0; j < n_mstorage; ++j )
1336                 {
1337                         for ( i = 0; i < n_vstorage; ++i )
1338                         {
1339                                 sci = j*n_vstorage + i;
1341                                 sc_str[ sci ]
1342                                 = ( char* ) malloc( ( n_operands + 1 ) * sizeof( char ) );
1344                                 for ( o = 0; o < n_operands; ++o )
1345                                 { 
1346                                         unsigned int ij;
1347                                         operand_t    operand_type
1348                                         = libblis_test_get_operand_type_for_char( o_types[o] );
1350                                         if ( operand_type == BLIS_TEST_MATRIX_OPERAND ) ij = j;
1351                                         else                                            ij = i;
1353                                         sc_str[sci][o] = params->storage[ operand_type ][ij];
1354                                 }
1355                                 sc_str[sci][n_operands] = '\0';
1356                         }
1357                 }
1358         }
1362         // Output a heading and the contents of the op struct.
1363         libblis_test_fprintf_c( stdout, "--- %s ---\n", op_str );
1364         libblis_test_fprintf_c( stdout, "\n" );
1365         libblis_test_output_op_struct( stdout, op, op_str );
1367         // Also output to a matlab file if requested (and successfully opened).
1368         if ( output_stream )
1369         {
1370                 // For file output, we also include the contents of the global
1371                 // parameter struct. We do this per operation so that the parameters
1372                 // are included in each file, whereas we only output it once to
1373                 // stdout (at the end of libblis_test_read_parameter_file()).
1374                 libblis_test_output_params_struct( output_stream, params );
1376                 libblis_test_fprintf_c( output_stream, "--- %s ---\n", op_str );
1377                 libblis_test_fprintf_c( output_stream, "\n" );
1378                 libblis_test_output_op_struct( output_stream, op, op_str );
1379         }
1381         // Loop over the requested storage schemes.
1382         for ( sci = 0; sci < n_store_combos; ++sci )
1383         {
1384                 // Loop over the requested datatypes.
1385                 for ( dt = 0; dt < n_datatypes; ++dt )
1386                 {
1387                         datatype = params->datatype[dt];
1388                         dt_char  = params->datatype_char[dt];
1390 #ifdef CBLAS
1391                         if (strcmp(op_str,"hemm")==0 || strcmp(op_str,"herk")==0 || strcmp(op_str,"her2k")==0 ||
1392                                 strcmp(op_str,"hemv")==0 || strcmp(op_str,"her")==0  || strcmp(op_str,"her2")==0)
1393                         {
1394                                 if (dt_char == 's' || dt_char == 'd')
1395                                 {
1396                                         continue;
1397                                 }
1398                         }
1399                         if (strcmp(op_str,"symv")==0 || strcmp(op_str,"syr")==0 || strcmp(op_str,"syr2")==0 )
1400                         {
1401                                 if (dt_char == 'c' || dt_char == 'z')
1402                                 {
1403                                         continue;
1404                                 }
1405                         }
1406                         if (strcmp(op_str,"dotxv")==0 )
1407                         {
1408                                 if (dt_char == 'd' || dt_char == 'c' || dt_char == 'z')
1409                                 {
1410                                         continue;
1411                                 }
1412                         }
1413 #endif
1415                         // Build a commented column label string.
1416                         libblis_test_build_col_labels_string( op, label_str );
1418                         // Output the column label string.
1419                         libblis_test_fprintf( stdout, "%s\n", label_str );
1421                         // Also output to a matlab file if requested (and successfully
1422                         // opened).
1423                         if ( output_stream )
1424                                 libblis_test_fprintf( output_stream, "%s\n", label_str );
1426                         // Loop over the requested parameter combinations.
1427                         for ( pci = 0; pci < n_param_combos; ++pci )    
1428                         {
1429                                 // Loop over the requested problem sizes.
1430                                 for ( p_cur = p_first, pi = 1; p_cur <= p_max; p_cur += p_inc, ++pi )
1431                                 {
1432                                         /*To enable Multithreading over tests to verify the OpenMP application running OpenCL jobs
1433                                         dim_t test_way = bli_read_nway_from_env( "BLIS_LB_NT" );
1434 #pragma omp parallel num_threads(test_way)*/
1435                                         {
1436                                                 f_exp( params,
1437                                                                 op,
1438                                                                 iface,
1439                                                                 datatype,
1440                                                                 pc_str[pci],
1441                                                                 sc_str[sci],
1442                                                                 p_cur,
1443                                                                 &perf, &resid );
1445                                                 // Remove the sign of the residual, if there is one.
1446                                                 resid = bli_fabs( resid );
1447                                                 if ( resid == -0.0 ) resid = 0.0;
1449                                                 // Query the string corresponding to the residual's
1450                                                 // position relative to the thresholds.
1451                                                 pass_str = libblis_test_get_string_for_result( resid,
1452                                                                 datatype,
1453                                                                 thresh );
1455                                                 // Build a string unique to the operation, datatype,
1456                                                 // parameter combination, and storage combination being
1457                                                 // tested.
1458                                                 libblis_test_build_function_string( BLIS_FILEDATA_PREFIX_STR,
1459                                                                 op_str,
1460                                                                 dt_char,
1461                                                                 n_param_combos,
1462                                                                 pc_str[pci],
1463                                                                 sc_str[sci],
1464                                                                 funcname_str );
1466                                                 // Compute the number of spaces we have left to fill given
1467                                                 // length of our operation's name.
1468                                                 n_spaces = MAX_FUNC_STRING_LENGTH - strlen( funcname_str );
1469                                                 fill_string_with_n_spaces( blank_str, n_spaces );
1471                                                 // Print all dimensions to a single string.
1472                                                 libblis_test_build_dims_string( op, p_cur, dims_str );
1474                                                 // Count the number of dimensions that were printed to the string.
1475                                                 n_dims_print = libblis_test_get_n_dims_from_string( dims_str );
1477                                                 // Output the results of the test. Use matlab format if requested.
1478                                                 if ( params->output_matlab_format )
1479                                                 {
1480                                                         libblis_test_fprintf( stdout,
1481                                                                         "%s%s( %3u, 1:%u ) = [%s  %7.3lf  %8.2le ]; %c %s\n",
1482                                                                         funcname_str, blank_str, pi, n_dims_print + 2,
1483                                                                         dims_str, perf, resid,
1484                                                                         OUTPUT_COMMENT_CHAR,
1485                                                                         pass_str );
1487                                                         // Also output to a file if requested (and successfully opened).
1488                                                         if ( output_stream )
1489                                                                 libblis_test_fprintf( output_stream,
1490                                                                                 "%s%s( %3u, 1:%u ) = [%s  %7.3lf  %8.2le ]; %c %s\n",
1491                                                                                 funcname_str, blank_str, pi, n_dims_print + 2,
1492                                                                                 dims_str, perf, resid,
1493                                                                                 OUTPUT_COMMENT_CHAR,
1494                                                                                 pass_str );
1495                                                 }
1496                                                 else
1497                                                 {
1498                                                         libblis_test_fprintf( stdout,
1499                                                                         "%s%s                %s  %7.3lf   %8.2le   %s\n",
1500                                                                         funcname_str, blank_str,
1501                                                                         dims_str, perf, resid,
1502                                                                         pass_str );
1504                                                         // Also output to a file if requested (and successfully opened).
1505                                                         if ( output_stream )
1506                                                                 libblis_test_fprintf( output_stream,
1507                                                                                 "%s%s                %s  %7.3lf   %8.2le   %s\n",
1508                                                                                 funcname_str, blank_str,
1509                                                                                 dims_str, perf, resid,
1510                                                                                 pass_str );
1511                                                 }
1513                                                 // If we need to check whether to do something on failure,
1514                                                 // do so now.
1515                                                 if ( reaction_to_failure == ON_FAILURE_SLEEP_CHAR )
1516                                                 {
1517                                                         if ( strstr( pass_str, BLIS_TEST_FAIL_STRING ) == pass_str )
1518                                                                 libblis_test_sleep();
1519                                                 }
1520                                                 else if ( reaction_to_failure == ON_FAILURE_ABORT_CHAR )
1521                                                 {
1522                                                         if ( strstr( pass_str, BLIS_TEST_FAIL_STRING ) == pass_str )
1523                                                                 libblis_test_abort();
1524                                                 }
1525                                         }
1526                                 }
1527                         }
1528         
1529                         libblis_test_fprintf( stdout, "\n" );
1531                         if ( output_stream )
1532                                 libblis_test_fprintf( output_stream, "\n" );
1533                 }
1534         }
1537         // Free the array that stored pointers to the sets of possible parameter
1538         // chars for each parameter.
1539         free( chars_for_param );
1541         // Free the parameter combination strings and then the master pointer.
1542         for ( pci = 0; pci < n_param_combos; ++pci )
1543                 free( pc_str[pci] );
1544         free( pc_str );
1546         // Free the storage combination strings and then the master pointer.
1547         for ( sci = 0; sci < n_store_combos; ++sci )
1548                 free( sc_str[sci] );
1549         free( sc_str );
1552         // If the file was opened (successfully), close the output stream.
1553         if ( output_stream )
1554                 libblis_test_fclose_ofile( output_stream );
1557         // Mark this operation as done.
1558         op->test_done = TRUE;
1563 void libblis_test_build_function_string( char*        prefix_str,
1564                                          char*        op_str,
1565                                          char         dt_char,
1566                                          unsigned int n_param_combos,
1567                                          char*        pc_str,
1568                                          char*        sc_str,
1569                                          char*        funcname_str )
1571         sprintf( funcname_str, "%s_%c%s", prefix_str, dt_char, op_str );
1573         // We check the string length of pc_str in case the user is running an
1574         // operation that has parameters (and thus generally more than one
1575         // parameter combination), but has fixed all parameters in the input
1576         // file, which would result in n_param_combos to equal one. This way,
1577         // the function string contains the parameter string associated with
1578         // the parameters that were fixed.
1579         if ( n_param_combos > 1 || strlen(pc_str) > 0 )
1580                 sprintf( &funcname_str[strlen(funcname_str)], "_%s_%s", pc_str, sc_str );
1581         else
1582                 sprintf( &funcname_str[strlen(funcname_str)], "_%s", sc_str );
1584         if ( strlen( funcname_str ) > MAX_FUNC_STRING_LENGTH )
1585                 libblis_test_printf_error( "Function name string length (%d) exceeds maximum (%d).\n",
1586                                            strlen( funcname_str ), MAX_FUNC_STRING_LENGTH );
1587                 
1591 void libblis_test_build_dims_string( test_op_t* op,
1592                                      dim_t      p_cur,
1593                                      char*      dims_str )
1595         unsigned int i;
1597         // For level-1f experiments with fusing factors, we grab the fusing
1598         // factor from the op struct. We do something similar for micro-kernel
1599         // calls.
1600         if      ( op->dimset == BLIS_TEST_DIMS_MF )
1601         {
1602                 //sprintf( &dims_str[strlen(dims_str)], " %5u %5u",
1603                 sprintf( dims_str, " %5u %5u",
1604                          ( unsigned int )
1605                          libblis_test_get_dim_from_prob_size( op->dim_spec[0],
1606                                                               p_cur ),
1607                          ( unsigned int ) op->dim_aux[0] );
1608         }
1609         else if ( op->dimset == BLIS_TEST_DIMS_K )
1610         {
1611                 //sprintf( &dims_str[strlen(dims_str)], " %5u %5u %5u",
1612                 sprintf( dims_str, " %5u %5u %5u",
1613                          ( unsigned int ) op->dim_aux[0],
1614                          ( unsigned int ) op->dim_aux[1],
1615                      ( unsigned int )
1616                          libblis_test_get_dim_from_prob_size( op->dim_spec[0],
1617                                                               p_cur ) );
1618         }
1619         else if ( op->dimset == BLIS_TEST_NO_DIMS )
1620         {
1621                 //sprintf( &dims_str[strlen(dims_str)], " %5u %5u",
1622                 sprintf( dims_str, " %5u %5u",
1623                          ( unsigned int ) op->dim_aux[0],
1624                          ( unsigned int ) op->dim_aux[1] );
1625         }
1626         else // For all other operations, we just use the dim_spec[] values
1627              // and the current problem size.
1628         {
1629                 // Initialize the string as empty.
1630                 sprintf( dims_str, "%s", "" );
1632                 // Print all dimensions to a single string.
1633                 for ( i = 0; i < op->n_dims; ++i )
1634                 {
1635                         sprintf( &dims_str[strlen(dims_str)], " %5u",
1636                                  ( unsigned int )
1637                                  libblis_test_get_dim_from_prob_size( op->dim_spec[i],
1638                                                                       p_cur ) );
1639                 }
1640         }
1644 // % dtoper_params_storage                       m     n     k   gflops  resid       result
1645 void libblis_test_build_col_labels_string( test_op_t* op, char* l_str )
1647         unsigned int n_spaces;
1648         char         blank_str[64];
1650         strcpy( l_str, "" );
1652         if ( op->n_params > 0 )
1653         {
1654                 sprintf( &l_str[strlen(l_str)], "%c %s_%s", OUTPUT_COMMENT_CHAR,
1655                                                             BLIS_FILEDATA_PREFIX_STR,
1656                                                             "<dt><oper>_<params>_<storage>" );
1657         }
1658         else // ( n_params == 0 )
1659         {
1660                 sprintf( &l_str[strlen(l_str)], "%c %s_%s", OUTPUT_COMMENT_CHAR,
1661                                                             BLIS_FILEDATA_PREFIX_STR,
1662                                                             "<dt><oper>_<storage>         " );
1663         }
1665         n_spaces = 6;
1666         fill_string_with_n_spaces( blank_str, n_spaces );
1668         sprintf( &l_str[strlen(l_str)], "%s", blank_str );
1670         if ( op->dimset == BLIS_TEST_DIMS_MNK ||
1671              op->dimset == BLIS_TEST_DIMS_MN  ||
1672              op->dimset == BLIS_TEST_DIMS_MK  ||
1673              op->dimset == BLIS_TEST_DIMS_M   ||
1674              op->dimset == BLIS_TEST_DIMS_K   ||
1675              op->dimset == BLIS_TEST_DIMS_MF  ||
1676              op->dimset == BLIS_TEST_NO_DIMS  )
1677                 sprintf( &l_str[strlen(l_str)], " %5s", "m" );
1679         if ( op->dimset == BLIS_TEST_DIMS_MNK ||
1680              op->dimset == BLIS_TEST_DIMS_MN  ||
1681              op->dimset == BLIS_TEST_DIMS_K   ||
1682              op->dimset == BLIS_TEST_DIMS_MF  ||
1683              op->dimset == BLIS_TEST_NO_DIMS  )
1684                 sprintf( &l_str[strlen(l_str)], " %5s", "n" );
1686         if ( op->dimset == BLIS_TEST_DIMS_MNK ||
1687              op->dimset == BLIS_TEST_DIMS_MK  ||
1688              op->dimset == BLIS_TEST_DIMS_K   )
1689                 sprintf( &l_str[strlen(l_str)], " %5s", "k" );
1691         sprintf( &l_str[strlen(l_str)], "%s", "   gflops   resid      result" );
1696 void libblis_test_build_filename_string( char*        prefix_str,
1697                                          char*        op_str,
1698                                          char*        funcname_str )
1700         sprintf( funcname_str, "%s_%s.m", prefix_str, op_str );
1705 void fill_string_with_n_spaces( char* str, unsigned int n_spaces )
1707         unsigned int i;
1709         // Initialze to empty string in case n_spaces == 0.
1710         sprintf( str, "%s", "" );
1712         for ( i = 0; i < n_spaces; ++i )
1713                 sprintf( &str[i], " " );
1718 void libblis_test_mobj_create( test_params_t* params, num_t dt, trans_t trans, char storage, dim_t m, dim_t n, obj_t* a )
1720         dim_t gs      = params->gs_spacing;
1721         dim_t m_trans = m;
1722         dim_t n_trans = n;
1723         dim_t rs_g;
1724         dim_t cs_g;
1725         
1726         // Apply the trans parameter to the dimensions (if needed).
1727         bli_set_dims_with_trans( trans, m, n, m_trans, n_trans );
1729         // In case of general strides, use the general stride spacing specified by the
1730         // user to create strides with a column-major tilt.
1731         rs_g = gs * 1;
1732         cs_g = gs * m_trans;
1734         if      ( storage == 'c' ) bli_obj_create( dt, m_trans, n_trans, 0,       0, a );
1735         else if ( storage == 'r' ) bli_obj_create( dt, m_trans, n_trans, n_trans, 1, a );
1736         else if ( storage == 'g' ) bli_obj_create( dt, m_trans, n_trans, rs_g, cs_g, a );
1737         else
1738         {
1739                 libblis_test_printf_error( "Invalid storage character: %c\n", storage );
1740         }
1745 void libblis_test_pobj_create( blksz_t* m, blksz_t* n, invdiag_t inv_diag, pack_t pack_schema, packbuf_t pack_buf, obj_t* a, obj_t* p )
1747         // Start with making p and alias to a.
1748         bli_obj_alias_to( *a, *p );
1750         // Then initialize p appropriately for packing.
1751         bli_packm_init_pack( inv_diag,
1752                              pack_schema,
1753                              BLIS_PACK_FWD_IF_UPPER,
1754                              BLIS_PACK_FWD_IF_LOWER,
1755                              pack_buf,
1756                              m, n,
1757                              a,
1758                              p );
1763 void libblis_test_vobj_create( test_params_t* params, num_t dt, char storage, dim_t m, obj_t* x )
1765         dim_t gs = params->gs_spacing;
1767         // Column vector (unit stride)
1768         if      ( storage == 'c' ) bli_obj_create( dt, m, 1,  1,  m,    x );
1769         // Row vector (unit stride)
1770         else if ( storage == 'r' ) bli_obj_create( dt, 1, m,  m,  1,    x );
1771         // Column vector (non-unit stride)
1772         else if ( storage == 'j' ) bli_obj_create( dt, m, 1,  gs, gs*m, x );
1773         // Row vector (non-unit stride)
1774         else if ( storage == 'i' ) bli_obj_create( dt, 1, m,  gs*m, gs, x );
1775         else
1776         {
1777                 libblis_test_printf_error( "Invalid storage character: %c\n", storage );
1778         }
1783 void libblis_test_init_strings( void )
1785         strcpy( libblis_test_pass_string, BLIS_TEST_PASS_STRING );
1786         strcpy( libblis_test_warn_string, BLIS_TEST_WARN_STRING );
1787         strcpy( libblis_test_fail_string, BLIS_TEST_FAIL_STRING );
1789         strcpy( libblis_test_param_chars[BLIS_TEST_PARAM_SIDE],   BLIS_TEST_PARAM_SIDE_CHARS );
1790         strcpy( libblis_test_param_chars[BLIS_TEST_PARAM_UPLO],   BLIS_TEST_PARAM_UPLO_CHARS );
1791         strcpy( libblis_test_param_chars[BLIS_TEST_PARAM_UPLODE], BLIS_TEST_PARAM_UPLODE_CHARS );
1792         strcpy( libblis_test_param_chars[BLIS_TEST_PARAM_TRANS],  BLIS_TEST_PARAM_TRANS_CHARS );
1793         strcpy( libblis_test_param_chars[BLIS_TEST_PARAM_CONJ],   BLIS_TEST_PARAM_CONJ_CHARS );
1794         strcpy( libblis_test_param_chars[BLIS_TEST_PARAM_DIAG],   BLIS_TEST_PARAM_DIAG_CHARS );
1796         strcpy( libblis_test_store_chars[BLIS_TEST_MATRIX_OPERAND], BLIS_TEST_MSTORE_CHARS );
1797         strcpy( libblis_test_store_chars[BLIS_TEST_VECTOR_OPERAND], BLIS_TEST_VSTORE_CHARS );
1802 void libblis_test_sleep( void )
1804         int i;
1806         libblis_test_printf_infoc( "Resuming in " );
1807         for ( i = SECONDS_TO_SLEEP; i > 0; --i )
1808         {
1809                 libblis_test_printf_info( "%d ", i );
1810 #ifndef BLIS_ENABLE_C66X_BUILD
1811                 sleep(1);
1812 #endif
1813         }
1814         libblis_test_printf_info( "\n" );
1819 void libblis_test_abort( void )
1821         abort();
1826 void libblis_test_fopen_ofile( char* op_str, iface_t iface, FILE** output_stream )
1828         char filename_str[ MAX_FILENAME_LENGTH ];
1830         if ( iface == BLIS_TEST_MT_FRONT_END )
1831                 bli_check_error_code( BLIS_NOT_YET_IMPLEMENTED );
1833         // Construct a filename string for the current operation.
1834         libblis_test_build_filename_string( BLIS_FILE_PREFIX_STR,
1835                                             op_str,
1836                                             filename_str );
1838         // Open the output file (overwriting a previous instance, if it exists)
1839         // for writing (in binary mode).
1840         *output_stream = fopen( filename_str, "wb" );
1842         // Check the output stream and report an error if something went wrong.
1843         libblis_test_fopen_check_stream( filename_str, *output_stream );
1848 void libblis_test_fclose_ofile( FILE* output_stream )
1850         fclose( output_stream );
1855 void libblis_test_fopen_check_stream( char* filename_str,
1856                                       FILE* stream )
1858         // Check for success.
1859         if ( stream == NULL )
1860         {
1861                 libblis_test_printf_error( "Failed to open file %s. Check existence (if file is being read), permissions (if file is being overwritten), and/or storage limit.\n",
1862                                            filename_str );
1863         }
1868 void libblis_test_read_next_line( char* buffer, FILE* input_stream )
1870         char temp[ INPUT_BUFFER_SIZE ];
1872         // We want to read at least one line, so we use a do-while loop.
1873         do
1874         {
1875                 // Read the next line into a temporary buffer and check success.
1876                 if ( fgets( temp, INPUT_BUFFER_SIZE-1, input_stream ) == NULL )
1877                 {
1878                         if ( feof( input_stream ) )
1879                                 libblis_test_printf_error( "Error reading input file: encountered unexpected EOF." );
1880                         else
1881                                 libblis_test_printf_error( "Error (non-EOF) reading input file." );
1882                 }
1883         }
1884     // We continue to read lines into buffer until the line is neither
1885         // commented nor blank.
1886         while ( temp[0] == INPUT_COMMENT_CHAR || temp[0] == '\n' ||
1887                 temp[0] == ' '                || temp[0] == '\t' );
1889         // Save the string in temp, up to first white space character, into buffer.
1890         //sscanf( temp, "%s ", buffer );
1891         strcpy( buffer, temp );
1893         //printf( "libblis_test_read_next_line() read: %s\n", buffer );
1898 void libblis_test_fprintf( FILE* output_stream, char* message, ... )
1900     va_list args;
1902     // Initialize variable argument environment.
1903     va_start( args, message );
1905     // Parse the received message and print its components.
1906     libblis_test_parse_message( output_stream, message, args );
1908     // Shutdown variable argument environment and clean up stack.
1909     va_end( args );
1911         // Flush the output stream.
1912     fflush( output_stream );
1917 void libblis_test_fprintf_c( FILE* output_stream, char* message, ... )
1919     va_list args;
1921         fprintf( output_stream, "%c ", OUTPUT_COMMENT_CHAR );
1923     // Initialize variable argument environment.
1924     va_start( args, message );
1926     // Parse the received message and print its components.
1927     libblis_test_parse_message( output_stream, message, args );
1929     // Shutdown variable argument environment and clean up stack.
1930     va_end( args );
1932         // Flush the output stream.
1933     fflush( output_stream );
1938 void libblis_test_printf_info( char* message, ... )
1940         FILE*   output_stream = stdout;
1941     va_list args;
1943     // Initialize variable argument environment.
1944     va_start( args, message );
1946     // Parse the received message and print its components.
1947     libblis_test_parse_message( output_stream, message, args );
1949     // Shutdown variable argument environment and clean up stack.
1950     va_end( args );
1952         // Flush the output stream.
1953     fflush( output_stream );
1958 void libblis_test_printf_infoc( char* message, ... )
1960         FILE*   output_stream = stdout;
1961     va_list args;
1963         fprintf( output_stream, "%c ", OUTPUT_COMMENT_CHAR );
1965     // Initialize variable argument environment.
1966     va_start( args, message );
1968     // Parse the received message and print its components.
1969     libblis_test_parse_message( output_stream, message, args );
1971     // Shutdown variable argument environment and clean up stack.
1972     va_end( args );
1974         // Flush the output stream.
1975     fflush( output_stream );
1980 void libblis_test_printf_error( char* message, ... )
1982         FILE*   output_stream = stderr;
1983     va_list args;
1985     fprintf( output_stream, "%s: *** error ***: ", libblis_test_binary_name );
1987     // Initialize variable argument environment.
1988     va_start( args, message );
1990     // Parse the received message and print its components.
1991     libblis_test_parse_message( output_stream, message, args );
1993     // Shutdown variable argument environment and clean up stack.
1994     va_end( args );
1996         // Flush the output stream.
1997     fflush( output_stream );
1999         // Exit.
2000         exit(1);
2005 void libblis_test_parse_message( FILE* output_stream, char* message, va_list args )
2007         int           c, cf;
2008         char          format_spec[8];
2009         unsigned int  the_uint;
2010         int           the_int;
2011         double        the_double;
2012         char*         the_string;
2013         char          the_char;
2015         // Begin looping over message to insert variables wherever there are 
2016         // format specifiers.
2017         for ( c = 0; message[c] != '\0'; )
2018         {
2019                 if ( message[c] != '%' )
2020                 {
2021                         fprintf( output_stream, "%c", message[c] );
2022                         c += 1;
2023                 }
2024                 else if ( message[c] == '%' && message[c+1] == '%' ) // handle escaped '%' chars.
2025                 {
2026                         fprintf( output_stream, "%c", message[c] );
2027                         c += 2;
2028                 }
2029                 else
2030                 {
2031                         // Save the format string if there is one.
2032                         format_spec[0] = '%';
2033                         for ( c += 1, cf = 1; strchr( "udefsc", message[c] ) == NULL; ++c, ++cf )
2034                         {
2035                                 format_spec[cf] = message[c];
2036                         }
2038                         // Add the final type specifier, and null-terminate the string.
2039                         format_spec[cf] = message[c];
2040                         format_spec[cf+1] = '\0';
2042                         // Switch based on type, since we can't predict what will
2043                         // va_args() will return.
2044                         switch ( message[c] )
2045                         {
2046                                 case 'u':
2047                                 the_uint = va_arg( args, unsigned int );
2048                                 fprintf( output_stream, format_spec, the_uint );
2049                                 break;
2051                                 case 'd':
2052                                 the_int = va_arg( args, int );
2053                                 fprintf( output_stream, format_spec, the_int );
2054                                 break;
2056                                 case 'e':
2057                                 the_double = va_arg( args, double );
2058                                 fprintf( output_stream, format_spec, the_double );
2059                                 break;
2061                                 case 'f':
2062                                 the_double = va_arg( args, double );
2063                                 fprintf( output_stream, format_spec, the_double );
2064                                 break;
2066                                 case 's':
2067                                 the_string = va_arg( args, char* );
2068                                 //fprintf( output_stream, "%s", the_string );
2069                                 fprintf( output_stream, format_spec, the_string );
2070                                 break;
2072                                 case 'c':
2073                                 the_char = va_arg( args, int );
2074                                 fprintf( output_stream, "%c", the_char );
2075                                 break;
2076                         }
2078                         // Move to next character past type specifier.
2079                         c += 1;
2080                 }
2081         }
2086 void libblis_test_parse_command_line( int argc, char** argv )
2088         bool_t gave_option_g = FALSE;
2089         bool_t gave_option_o = FALSE;
2090         int    opt;
2091         char   opt_ch;
2093         // Copy the binary name to a global string so we can use it later.
2094         strncpy( libblis_test_binary_name, argv[0], MAX_BINARY_NAME_LENGTH );
2096         // Process all option arguments until we get a -1, which means we're done.
2097 #ifndef BLIS_ENABLE_C66X_BUILD
2098         while( (opt = bli_getopt( argc, argv, "g:o:" )) != -1 )
2099         {
2100                 // Explicitly typecast opt, which is an int, to a char. (Failing to
2101                 // typecast resulted in at least one user-reported problem whereby
2102                 // opt was being filled with garbage.)
2103                 opt_ch = ( char )opt;
2105                 switch( opt_ch )
2106                 {
2107                         case 'g':
2108                         libblis_test_printf_infoc( "detected -g option; using \"%s\" for parameters filename.\n", bli_optarg );
2109                         strncpy( libblis_test_parameters_filename,
2110                                  bli_optarg, MAX_FILENAME_LENGTH );
2111                         gave_option_g = TRUE;
2112                         break;
2114                         case 'o':
2115                         libblis_test_printf_infoc( "detected -o option; using \"%s\" for operations filename.\n", bli_optarg );
2116                         strncpy( libblis_test_operations_filename,
2117                                  bli_optarg, MAX_FILENAME_LENGTH );
2118                         gave_option_o = TRUE;
2119                         break;
2121                         case '?':
2122                         libblis_test_printf_error( "unexpected option '%c' given or missing option argument\n", bli_optopt );
2123                         break;
2125                         default:
2126                         libblis_test_printf_error( "unexpected option chararcter returned from getopt: %c\n", opt_ch );
2127                 }
2128         }
2129 #endif
2131         if ( gave_option_g == FALSE )
2132         {
2133                 libblis_test_printf_infoc( "no -g option given; defaulting to \"%s\" for parameters filename.\n", PARAMETERS_FILENAME );
2135                 // Copy default parameters filename into its global string.
2136                 strncpy( libblis_test_parameters_filename,
2137                          PARAMETERS_FILENAME, MAX_FILENAME_LENGTH );
2138         }
2140         if ( gave_option_o == FALSE )
2141         {
2142                 libblis_test_printf_infoc( "no -o option given; defaulting to \"%s\" for operations filename.\n", OPERATIONS_FILENAME );
2144                 // Copy default operations filename into its global string.
2145                 strncpy( libblis_test_operations_filename,
2146                          OPERATIONS_FILENAME, MAX_FILENAME_LENGTH );
2147         }
2149         // If there are still arguments remaining after getopt() processing is
2150         // complete, print an error.
2151         if ( bli_optind < argc )
2152         {
2153                 libblis_test_printf_error( "Encountered unexpected non-option argument: %s\n", argv[ bli_optind ] );
2154         }
2159 void libblis_test_check_empty_problem( obj_t* c, double* perf, double* resid )
2161         if ( bli_obj_has_zero_dim( *c ) )
2162         {
2163                 *perf  = 0.0;
2164                 *resid = 0.0;
2165         }