1 /*
2 
3 Copyright (C) 2008-2021 Michele Martone
4 
5 This file is part of librsb.
6 
7 librsb is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11 
12 librsb is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
15 License for more details.
16 
17 You should have received a copy of the GNU Lesser General Public
18 License along with librsb; see the file COPYING.
19 If not, see <http://www.gnu.org/licenses/>.
20 
21 */
22 /* @cond INNERDOC  */
23 /*!
24  @file
25  @author Michele Martone
26  @brief
27  This is the main program used to benchmark and test our library.
28  This should be the swiss army knife program for our library.
29  */
30 /*
31   This not an example program: to be built, it needs all of the internal library headers.
32  */
33 
34 #include <stdlib.h>
35 #include "rsb.h"
36 #include "rsb_test_matops.h"
37 #include "rsb_failure_tests.h"
38 #include "rsb_internals.h"
39 #if RSB_WITH_SPARSE_BLAS_INTERFACE
40 #include "rsb_libspblas_handle.h"
41 #endif /* RSB_WITH_SPARSE_BLAS_INTERFACE  */
42 #include "rsb_libspblas_tests.h"
43 //#include "rsb-config.h"
44 #if RSB_WANT_ACTION
45 #include <signal.h>
46 #if defined(RSB_WANT_ACTION_SIGNAL)
47 #else /* defined(RSB_WANT_ACTION_SIGNAL) */
48 #include <bits/sigaction.h>
49 #endif /* defined(RSB_WANT_ACTION_SIGNAL) */
50 #endif /* RSB_WANT_ACTION */
51 
52 #define RSB_WANT_PERMISSIVE_RSBENCH 1
53 #define RSB_SHALL_UPDATE_COMPLETEBENCHS 1
54 #define RSB_WANT_REDUCED_RSB_M4_MATRIX_META_OPS 1
55 
56 
57 #if RSB_WITH_LIKWID
58 #define RSB_RSBENCH_EXEC(FEXP) {rsb_err_t errval;RSB_LIKWID_MARKER_INIT;errval=RSB_ERR_TO_PROGRAM_ERROR(FEXP);RSB_LIKWID_MARKER_EXIT;return errval;}
59 #else /* RSB_WITH_LIKWID */
60 #define RSB_RSBENCH_EXEC(FEXP) {return RSB_ERR_TO_PROGRAM_ERROR(FEXP);}
61 #endif /* RSB_WITH_LIKWID */
62 
63 #if RSB_WANT_ACTION
64 	int rsb__quit_rsbench;
65 #if defined(RSB_WANT_ACTION_SIGNAL)
66 #else /* defined(RSB_WANT_ACTION_SIGNAL) */
67 	struct sigaction rsb_osa;
68 #endif /* defined(RSB_WANT_ACTION_SIGNAL) */
69 
rsb__chk_srt(void)70 static rsb_err_t rsb__chk_srt(void)
71 {
72 	rsb_err_t errval = RSB_ERR_INTERNAL_ERROR;
73 
74 	RSBENCH_STDOUT("SORT CHECK: BEGIN\n");
75 
76 {
77 	const rsb_flags_t flags = RSB_FLAG_NOFLAGS;
78 	const rsb_type_t typecode = RSB_NUMERICAL_TYPE_DEFAULT;
79 	const rsb_nnz_idx_t nnz = 2;
80 	const rsb_coo_idx_t nr = 1000000;
81 	const rsb_coo_idx_t nc = 1000000;
82 	rsb_coo_idx_t IA[] = { 463325, 417887};
83 	rsb_coo_idx_t JA[] = { 463231, 417880};
84 	RSB_DEFAULT_TYPE VA[] = {1,1};
85 
86 	errval = rsb_coo_sort(VA, IA, JA, nnz, nr, nc, typecode, flags);
87 
88 	if(RSB_SOME_ERROR(errval))
89 		RSB_PERR_GOTO(err,RSB_ERRM_ES);
90 
91 	if( IA[0] != 417887)
92 		RSB_PERR_GOTO(merr,RSB_ERRM_ES);
93 	if( JA[0] != 417880)
94 		RSB_PERR_GOTO(merr,RSB_ERRM_ES);
95 }
96 
97 #define RSB_EXPECT_2P_SORT_BUG 0
98 {
99 	// trigger double pass
100 	const struct rsb_mtx_partitioning_info_t * pinfop = NULL;
101 	const rsb_flags_t flags = RSB_FLAG_NOFLAGS;
102 	const enum rsb_op_flags_t op_flags = RSB_OP_FLAG_DEFAULT;
103 	const int bs = RSB_DEFAULT_BLOCKING;
104 	const size_t wb = 0;
105 	const int br = bs, bc = bs;
106 	void * WA = NULL;
107 	const rsb_type_t typecode = RSB_NUMERICAL_TYPE_DEFAULT;
108 	const rsb_nnz_idx_t nnz = 2;
109 	const rsb_coo_idx_t nr = 1000000;
110 	const rsb_coo_idx_t nc = 1000000;
111 	rsb_coo_idx_t IA[] = { 463325, 417887};
112 	rsb_coo_idx_t JA[] = { 463231, 417880};
113 	rsb_coo_idx_t rIA[] = { 463325, 417887};
114 	rsb_coo_idx_t rJA[] = { 463231, 417880};
115 	RSB_DEFAULT_TYPE VA[] = {1,1};
116 	RSB_DEFAULT_TYPE rVA[] = {1,1};
117 
118 	errval = rsb__do_index_based_bcsr_sort( IA, JA, VA, rIA, rJA, rVA, nr, nc, br, bc, nnz, typecode, flags, op_flags, WA, wb);
119 
120 	if(RSB_SOME_ERROR(errval))
121 		RSB_PERR_GOTO(err,RSB_ERRM_ES);
122 
123 #if RSB_EXPECT_2P_SORT_BUG
124 	if( rIA[0] == 417887)
125 		RSB_PERR_GOTO(merr,RSB_ERRM_ES);
126 	if( rJA[0] == 417880)
127 		RSB_PERR_GOTO(merr,RSB_ERRM_ES);
128 #else
129 	if( rIA[0] != 417887)
130 		RSB_PERR_GOTO(merr,RSB_ERRM_ES);
131 	if( rJA[0] != 417880)
132 		RSB_PERR_GOTO(merr,RSB_ERRM_ES);
133 #endif
134 }
135 
136 #define RSB_EXPECT_IP2P_SORT_BUG 0
137 {
138 	// trigger double pass
139 	const struct rsb_mtx_partitioning_info_t * pinfop = NULL;
140 	const rsb_flags_t flags = RSB_FLAG_EXPERIMENTAL_IN_PLACE_PERMUTATION_SORT;
141 	const enum rsb_op_flags_t op_flags = RSB_OP_FLAG_DEFAULT;
142 	const int bs = RSB_DEFAULT_BLOCKING;
143 	const size_t wb = 0;
144 	const int br = bs, bc = bs;
145 	void * WA = NULL;
146 	const rsb_type_t typecode = RSB_NUMERICAL_TYPE_DEFAULT;
147 	const rsb_nnz_idx_t nnz = 7;
148 	const rsb_coo_idx_t nr = 2*RSB_MAX_VALUE_FOR_TYPE(rsb_half_idx_t);
149 	const rsb_coo_idx_t nc = 2*RSB_MAX_VALUE_FOR_TYPE(rsb_half_idx_t);
150 	rsb_coo_idx_t IA[] = {0,1,2,3,4,5,1};
151 	rsb_coo_idx_t JA[] = {0,1,2,3,4,5,0};
152 	RSB_DEFAULT_TYPE VA[] = {1,1,1,1,1,1,2};
153 	RSB_DEFAULT_TYPE rVA[nnz];
154 	rsb_coo_idx_t rIA[nnz];
155 	rsb_coo_idx_t rJA[nnz];
156 
157 	errval = rsb__do_index_based_bcsr_sort( IA, JA, VA, rIA, rJA, rVA, nr, nc, br, bc, nnz, typecode, flags, op_flags, WA, wb);
158 #if RSB_EXPECT_IP2P_SORT_BUG
159 	if( rIA[1] != 1 )
160 		RSB_PERR_GOTO(merr,RSB_ERRM_ES);
161 	if( rJA[1] != 1 )
162 		RSB_PERR_GOTO(merr,RSB_ERRM_ES);
163 	if( rVA[1] != 1 )
164 		RSB_PERR_GOTO(merr,RSB_ERRM_ES);
165 #else
166 	if( rIA[1] != 1 )
167 		RSB_PERR_GOTO(merr,RSB_ERRM_ES);
168 	if( rJA[1] != 0 )
169 		RSB_PERR_GOTO(merr,RSB_ERRM_ES);
170 	if( rVA[1] != 2 )
171 		RSB_PERR_GOTO(merr,RSB_ERRM_ES);
172 #endif
173 }
174 
175 {
176 	// do not trigger double pass
177 	const struct rsb_mtx_partitioning_info_t * pinfop = NULL;
178 	const rsb_flags_t flags = RSB_FLAG_EXPERIMENTAL_IN_PLACE_PERMUTATION_SORT;
179 	const enum rsb_op_flags_t op_flags = RSB_OP_FLAG_DEFAULT;
180 	const int bs = RSB_DEFAULT_BLOCKING;
181 	const size_t wb = 0;
182 	const int br = bs, bc = bs;
183 	void * WA = NULL;
184 	const rsb_type_t typecode = RSB_NUMERICAL_TYPE_DEFAULT;
185 	const rsb_nnz_idx_t nnz = 7;
186 	const rsb_coo_idx_t nr = 6;
187 	const rsb_coo_idx_t nc = 6;
188 	rsb_coo_idx_t IA[] = {0,1,2,3,4,5,1};
189 	rsb_coo_idx_t JA[] = {0,1,2,3,4,5,0};
190 	RSB_DEFAULT_TYPE VA[] = {1,1,1,1,1,1,2};
191 	RSB_DEFAULT_TYPE rVA[nnz];
192 	rsb_coo_idx_t rIA[nnz];
193 	rsb_coo_idx_t rJA[nnz];
194 
195 	errval = rsb__do_index_based_bcsr_sort( IA, JA, VA, rIA, rJA, rVA, nr, nc, br, bc, nnz, typecode, flags, op_flags, WA, wb);
196 
197 	if(RSB_SOME_ERROR(errval))
198 		RSB_PERR_GOTO(err,RSB_ERRM_ES);
199 
200 	if( rIA[1] != 1 )
201 		RSB_PERR_GOTO(merr,RSB_ERRM_ES);
202 	if( rJA[1] != 0 )
203 		RSB_PERR_GOTO(merr,RSB_ERRM_ES);
204 	if( rVA[1] != 2 )
205 		RSB_PERR_GOTO(merr,RSB_ERRM_ES);
206 }
207 
208 	RSBENCH_STDOUT("SORT CHECK: END\n");
209 	//errval = RSB_ERR_NO_ERROR;
210 goto err;
211 merr:
212 	errval = RSB_ERR_INTERNAL_ERROR;
213 err:
214 	if(RSB_SOME_ERROR(errval))
215 		RSBENCH_STDOUT("SORT CHECK: FAIL\n");
216 	return errval;
217 }
218 
rsb__chk_trtr(void)219 static rsb_err_t rsb__chk_trtr(void)
220 {
221 	rsb_err_t errval = RSB_ERR_INTERNAL_ERROR;
222 	struct rsb_mtx_t *mtxAp = NULL;	/* matrix structure pointer */
223 
224 	RSBENCH_STDOUT("REGRESSION TEST: BEGIN\n");
225 
226 #define RSB_EXPECT_TRTR_BUG_COO 0
227 
228 #ifdef RSB_NUMERICAL_TYPE_DOUBLE
229 {
230 	const int bs = RSB_DEFAULT_BLOCKING;
231 	const int brA = bs, bcA = bs;
232 	const rsb_type_t typecode = RSB_NUMERICAL_TYPE_DOUBLE;
233 	const rsb_nnz_idx_t nnzA = 3;
234 	const rsb_coo_idx_t incX = 1, incY = 1;
235 	const rsb_coo_idx_t nrA = 3;
236 	const rsb_coo_idx_t ncA = 1;
237 	const rsb_coo_idx_t IA[] = {0,1,2};
238 	const rsb_coo_idx_t JA[] = {0,0,0};
239 	const double VA[] = {1,1,1};
240 	const double X[] = {1,1,1};
241 	double Y[] = {1,1,1};
242 	const double alpha = 1.0;
243 	const double beta = 0.0;
244 	const rsb_trans_t transA = RSB_TRANSPOSITION_C;
245 
246 	mtxAp = rsb_mtx_alloc_from_coo_const(
247 		VA,IA,JA,nnzA,typecode,nrA,ncA,brA,bcA,
248 		RSB_FLAG_DEFAULT_COO_MATRIX_FLAGS|RSB_FLAG_USE_HALFWORD_INDICES
249 		, &errval);
250 
251 	if((!mtxAp) || RSB_SOME_ERROR(errval))
252 		RSB_PERR_GOTO(err,RSB_ERRM_ES);
253 
254 	if( Y[0] != 1 || Y[1] != 1 )
255 		RSB_PERR_GOTO(err,RSB_ERRM_ES);
256 	errval = rsb_spmv(transA, &alpha, mtxAp, X, incX, &beta, Y, incY);
257 	if(RSB_SOME_ERROR(errval))
258 		RSB_PERR_GOTO(err,RSB_ERRM_ES);
259 #if RSB_EXPECT_TRTR_BUG_COO
260 	if( Y[0] != 3 || Y[2] != 0 )
261 		RSB_PERR_GOTO(merr,RSB_ERRM_ES);
262 	// bug: Y[0:2] have been zeroed, instead of Y[0:1]
263 #else
264 	if( Y[0] != 3 || Y[2] != 1 )
265 		RSB_PERR_GOTO(merr,RSB_ERRM_ES);
266 	// ok : only Y[0:1] should have been zeroed
267 #endif
268 
269 	RSB_MTX_FREE(mtxAp);
270 }
271 #endif /* RSB_NUMERICAL_TYPE_DOUBLE */
272 
273 #ifdef RSB_NUMERICAL_TYPE_DOUBLE
274 {
275 	const int bs = RSB_DEFAULT_BLOCKING;
276 	const int brA = bs, bcA = bs;
277 	const rsb_type_t typecode = RSB_NUMERICAL_TYPE_DOUBLE;
278 	const rsb_nnz_idx_t nnzA = 3;
279 	const rsb_coo_idx_t incX = 1, incY = 1;
280 	const rsb_coo_idx_t nrA = 1;
281 	const rsb_coo_idx_t ncA = 3;
282 	const rsb_coo_idx_t IA[] = {0,0,0};
283 	const rsb_coo_idx_t JA[] = {0,1,2};
284 	const double VA[] = {1,1,1};
285 	const double X[] = {1,1,1};
286 	double Y[] = {1,1,1};
287 	const double alpha = 1.0;
288 	const double beta = 0.0;
289 	const rsb_trans_t transA = RSB_TRANSPOSITION_C;
290 
291 	mtxAp = rsb_mtx_alloc_from_coo_const(
292 		VA,IA,JA,nnzA,typecode,nrA,ncA,brA,bcA,
293 		RSB_FLAG_DEFAULT_COO_MATRIX_FLAGS|RSB_FLAG_USE_HALFWORD_INDICES
294 		, &errval);
295 
296 	if((!mtxAp) || RSB_SOME_ERROR(errval))
297 		RSB_PERR_GOTO(err,RSB_ERRM_ES);
298 
299 	if( Y[0] != 1 || Y[1] != 1 )
300 		RSB_PERR_GOTO(err,RSB_ERRM_ES);
301 	errval = rsb_spmv(transA, &alpha, mtxAp, X, incX, &beta, Y, incY);
302 	if(RSB_SOME_ERROR(errval))
303 		RSB_PERR_GOTO(err,RSB_ERRM_ES);
304 #if RSB_EXPECT_TRTR_BUG_COO
305 	if( Y[0] != 1 || Y[1] != 2 ) // bug: Y[1] should have been zeroed before add
306 		RSB_PERR_GOTO(merr,RSB_ERRM_ES);
307 #else
308 	if( Y[0] != 1 || Y[1] != 1 ) // ok : Y[1] should have been zeroed before add
309 		RSB_PERR_GOTO(merr,RSB_ERRM_ES);
310 #endif
311 
312 	RSB_MTX_FREE(mtxAp);
313 }
314 #endif /* RSB_NUMERICAL_TYPE_DOUBLE */
315 
316 #ifdef RSB_NUMERICAL_TYPE_DOUBLE
317 {
318 	const int bs = RSB_DEFAULT_BLOCKING;
319 	const int brA = bs, bcA = bs;
320 	const rsb_type_t typecode = RSB_NUMERICAL_TYPE_DOUBLE;
321 	const rsb_nnz_idx_t nnzA = 4;
322 	const rsb_coo_idx_t incX = 1, incY = 1;
323 	const rsb_coo_idx_t nrA = 3;
324 	const rsb_coo_idx_t ncA = 2;
325 	const rsb_coo_idx_t IA[] = {0,1,2,2};
326 	const rsb_coo_idx_t JA[] = {0,0,0,1};
327 	const double VA[] = {1,1,1,1};
328 	const double X[] = {1,1,1};
329 	double Y[] = {1,1,1};
330 	const double alpha = 1.0;
331 	const double beta = 0.0;
332 	const rsb_trans_t transA = RSB_TRANSPOSITION_C;
333 
334 	mtxAp = rsb_mtx_alloc_from_coo_const(
335 		VA,IA,JA,nnzA,typecode,nrA,ncA,brA,bcA,
336 		RSB_FLAG_DEFAULT_CSR_MATRIX_FLAGS|RSB_FLAG_USE_HALFWORD_INDICES
337 		, &errval);
338 
339 	if((!mtxAp) || RSB_SOME_ERROR(errval))
340 		RSB_PERR_GOTO(err,RSB_ERRM_ES);
341 
342 	if( Y[0] != 1 || Y[1] != 1 )
343 		RSB_PERR_GOTO(err,RSB_ERRM_ES);
344 	errval = rsb_spmv(transA, &alpha, mtxAp, X, incX, &beta, Y, incY);
345 	if(RSB_SOME_ERROR(errval))
346 		RSB_PERR_GOTO(err,RSB_ERRM_ES);
347 #if RSB_EXPECT_TRTR_BUG_COO
348 	if( Y[0] != 3 || Y[2] != 0 )
349 		RSB_PERR_GOTO(merr,RSB_ERRM_ES);
350 	// bug: Y[0:2] have been zeroed, instead of Y[0:1]
351 #else
352 	if( Y[0] != 3 || Y[2] != 1 )
353 		RSB_PERR_GOTO(merr,RSB_ERRM_ES);
354 	// ok : only Y[0:1] should have been zeroed
355 #endif
356 
357 	RSB_MTX_FREE(mtxAp);
358 }
359 #endif /* RSB_NUMERICAL_TYPE_DOUBLE */
360 
361 #ifdef RSB_NUMERICAL_TYPE_DOUBLE_COMPLEX
362 {
363 	const int bs = RSB_DEFAULT_BLOCKING;
364 	const int brA = bs, bcA = bs;
365 	const rsb_type_t typecode = RSB_NUMERICAL_TYPE_DOUBLE_COMPLEX;
366 	const rsb_nnz_idx_t nnzA = 5;
367 	const rsb_coo_idx_t nrA = 3;
368 	const rsb_coo_idx_t ncA = 3;
369 	const rsb_coo_idx_t IA[] = {0,2,1,0,2};
370 	const rsb_coo_idx_t CP[] = {0,2,3,5};
371 	const double VA[] = {1,1, 1,0, 1,0, 1,0, 1,0};
372 
373 	mtxAp = rsb_mtx_alloc_from_csc_const(
374 		VA,IA,CP,nnzA,typecode,nrA,ncA,brA,bcA,
375 		RSB_FLAG_LOWER_HERMITIAN|RSB_FLAG_TRIANGULAR
376 		, &errval);
377 
378 	if((!mtxAp) || RSB_SOME_ERROR(errval))
379 		RSB_PERR_GOTO(err,RSB_ERRM_ES);
380 
381 	if ( mtxAp->nnz != 4 )
382 		RSB_PERR_GOTO(merr,RSB_ERRM_ES);
383 
384 	RSB_MTX_FREE(mtxAp);
385 }
386 #endif /* RSB_NUMERICAL_TYPE_DOUBLE_COMPLEX */
387 
388 #ifdef RSB_NUMERICAL_TYPE_DOUBLE
389 #define RSB_EXPECT_RECT_IMPDIA_NRHS_BUG 0
390 {
391 	const int bs = RSB_DEFAULT_BLOCKING;
392 	const int brA = bs, bcA = bs;
393 	const rsb_type_t typecode = RSB_NUMERICAL_TYPE_DOUBLE;
394 	const rsb_nnz_idx_t nnzA = 2;
395 	const rsb_coo_idx_t nrA = 2;
396 	const rsb_coo_idx_t ncA = 1;
397 	const rsb_coo_idx_t IA[] = {0,1};
398 	const rsb_coo_idx_t JA[] = {0,0};
399 	const rsb_coo_idx_t nrhs = 2;
400 	const double VA[] = {1,1};
401 	const double X[] = {1,1};
402 	double Y[] = {0,0,0,0};
403 	const double alpha = 1.0;
404 	const double beta = 1.0;
405 	const rsb_trans_t transA = RSB_TRANSPOSITION_N;
406 
407 	mtxAp = rsb_mtx_alloc_from_coo_const(
408 		VA,IA,JA,nnzA,typecode,nrA,ncA,brA,bcA,
409 		RSB_FLAG_UNIT_DIAG_IMPLICIT
410 		, &errval);
411 
412 	if((!mtxAp) || RSB_SOME_ERROR(errval))
413 		RSB_PERR_GOTO(err,RSB_ERRM_ES);
414 
415 	errval = rsb_spmm(transA, &alpha, mtxAp, nrhs, RSB_FLAG_WANT_COLUMN_MAJOR_ORDER, X, 1, &beta, Y, 2);
416 	if(RSB_SOME_ERROR(errval))
417 		RSB_PERR_GOTO(err,RSB_ERRM_ES);
418 #if RSB_EXPECT_RECT_IMPDIA_NRHS_BUG
419 	if( Y[1] != 2 || Y[3] != 1 )
420 		RSB_PERR_GOTO(merr,RSB_ERRM_ES);
421 	// bug: Y[1] has been added an extra 1
422 #else
423 	if( Y[1] != 1 || Y[3] != 1 )
424 		RSB_PERR_GOTO(merr,RSB_ERRM_ES);
425 	// ok : Y[1] has been added no extra 1
426 #endif
427 
428 	RSB_MTX_FREE(mtxAp);
429 }
430 #undef RSB_EXPECT_RECT_IMPDIA_NRHS_BUG
431 #endif /* RSB_NUMERICAL_TYPE_DOUBLE */
432 
433 #ifdef RSB_NUMERICAL_TYPE_DOUBLE
434 #define RSB_EXPECT_TUNE_BROKEN_FOR_ROWS_MAJOR 0
435 {
436 	const int bs = RSB_DEFAULT_BLOCKING;
437 	const int brA = bs, bcA = bs;
438 	const rsb_type_t typecode = RSB_NUMERICAL_TYPE_DOUBLE;
439 	const rsb_nnz_idx_t nnzA = 2;
440 	const rsb_coo_idx_t incX = 1, incY = 1;
441 	const rsb_coo_idx_t nrA = 3; // overzealous rsb_tune_spmm bug triggers on e.g. ldB<nrA (like when RSB_FLAG_WANT_ROW_MAJOR_ORDER)
442 	const rsb_coo_idx_t ncA = 1;
443 	const rsb_coo_idx_t IA[] = {0,1};
444 	const rsb_coo_idx_t JA[] = {0,0};
445 	const rsb_coo_idx_t nrhs = 2;
446 	const rsb_coo_idx_t ldB = nrhs;
447 	const rsb_coo_idx_t ldC = nrhs;
448 	const double VA[] = {1,1};
449 	const double B[] = {1,1};
450 	double C[] = {0,0,0,0};
451 	const double alpha = 1.0;
452 	const double beta = 1.0;
453 	const rsb_trans_t transA = RSB_TRANSPOSITION_N;
454 
455 	mtxAp = rsb_mtx_alloc_from_coo_const(
456 		VA,IA,JA,nnzA,typecode,nrA,ncA,brA,bcA,
457 		RSB_FLAG_UNIT_DIAG_IMPLICIT
458 		, &errval);
459 
460 	if((!mtxAp) || RSB_SOME_ERROR(errval))
461 		RSB_PERR_GOTO(err,RSB_ERRM_ES);
462 
463 	errval = rsb_tune_spmm(NULL, NULL, NULL, 0.0, 0.0, transA, &alpha, mtxAp, nrhs, RSB_FLAG_WANT_ROW_MAJOR_ORDER, B, ldB, &beta, C, ldC);
464 
465 #if RSB_EXPECT_TUNE_BROKEN_FOR_ROWS_MAJOR
466 	if(!RSB_SOME_ERROR(errval))
467 	{
468 		errval = RSB_ERR_INTERNAL_ERROR;
469 		RSB_PERR_GOTO(err,RSB_ERRM_ES);
470 	}
471 #else
472 	if( RSB_SOME_ERROR(errval))
473 		RSB_PERR_GOTO(err,RSB_ERRM_ES);
474 #endif
475 
476 	RSB_MTX_FREE(mtxAp);
477 }
478 #undef RSB_EXPECT_TUNE_BROKEN_FOR_ROWS_MAJOR
479 #endif /* RSB_NUMERICAL_TYPE_DOUBLE */
480 
481 #ifdef RSB_NUMERICAL_TYPE_DOUBLE
482 {
483 	const int bs = RSB_DEFAULT_BLOCKING;
484 	const int brA = bs, bcA = bs;
485 	const rsb_type_t typecode = RSB_NUMERICAL_TYPE_DOUBLE;
486 	const rsb_nnz_idx_t nnzA = 1;
487 	const rsb_coo_idx_t nrA = 1;
488 	const rsb_coo_idx_t ncA = 1;
489 	const rsb_coo_idx_t IA[] = {0};
490 	const rsb_coo_idx_t JA[] = {0};
491 	const rsb_coo_idx_t nrhs = 2;
492 	const rsb_coo_idx_t ldB = nrhs;
493 	const rsb_coo_idx_t ldC = nrhs + 1;
494 	const double VA[] = {1};
495 	const double B[] = {1,2,3,4};
496 	double C[] = {0,0,0,0};
497 	const double alpha = 1.0;
498 	const double beta = 1.0;
499 	const rsb_trans_t transA = RSB_TRANSPOSITION_N;
500 
501 	mtxAp = rsb_mtx_alloc_from_coo_const(
502 		VA,IA,JA,nnzA,typecode,nrA,ncA,brA,bcA,
503 		RSB_FLAG_UNIT_DIAG_IMPLICIT,
504 		&errval);
505 
506 	if((!mtxAp) || RSB_SOME_ERROR(errval))
507 		RSB_PERR_GOTO(err,RSB_ERRM_ES);
508 
509 	errval = rsb_spmm(transA, &alpha, mtxAp, nrhs, RSB_FLAG_WANT_ROW_MAJOR_ORDER, B, ldB, &beta, C, ldC);
510 
511 	if( C[0] != 1 || C[1] != 2 || C[2] != 0 || C[3] != 0 )
512 		RSB_PERR_GOTO(merr,RSB_ERRM_ES);
513 
514 	RSB_MTX_FREE(mtxAp);
515 }
516 #endif /* RSB_NUMERICAL_TYPE_DOUBLE */
517 
518 	RSBENCH_STDOUT("REGRESSION TEST: END\n");
519 	errval = RSB_ERR_NO_ERROR;
520 goto err;
521 merr:
522 	errval = RSB_ERR_INTERNAL_ERROR;
523 err:
524 	if(RSB_SOME_ERROR(errval))
525 		RSBENCH_STDOUT("REGRESSION TEST: FAIL\n");
526 	RSB_MTX_FREE(mtxAp);
527 	return errval;
528 }
529 
530 RSB_INTERNALS_COMMON_HEAD_DECLS /* for RSB_INFO */
531 
rsb__chk_sppsp(void)532 static rsb_err_t rsb__chk_sppsp(void)
533 {
534 	rsb_err_t errval = RSB_ERR_INTERNAL_ERROR;
535 	struct rsb_mtx_t *mtxAp = NULL;	/* matrix structure pointer */
536 	struct rsb_mtx_t *mtxCp = NULL;	/* matrix structure pointer */
537 
538 	RSB_INFO("MATRIX SUMS TEST: BEGIN\n");
539 {
540 	const int bs = RSB_DEFAULT_BLOCKING;
541 	const int brA = bs, bcA = bs;
542 	const rsb_type_t typecode = RSB_NUMERICAL_TYPE_DEFAULT;
543 	const rsb_nnz_idx_t nnzA = 6;
544 	const rsb_coo_idx_t nrA = 4;
545 	const rsb_coo_idx_t ncA = 4;
546 	const rsb_coo_idx_t IT[] = {1,1,1,2,2,4};
547 	const rsb_coo_idx_t JL[] = {1,3,4,1,2,4};
548 	const RSB_DEFAULT_TYPE VT[] = {11,13,14,-21,22,44};
549 
550 	const void *alphap = NULL;
551 	const void *betap = NULL;
552 	struct rsb_mtx_t *mtxBp = NULL;
553 	const rsb_trans_t transA = RSB_TRANSPOSITION_T;
554 	const rsb_trans_t transB = RSB_TRANSPOSITION_T;
555 
556 	mtxAp = rsb_mtx_alloc_from_coo_const(
557 		VT,IT,JL,nnzA,typecode,nrA,ncA,brA,bcA,
558 		RSB_FLAG_DEFAULT_RSB_MATRIX_FLAGS
559 		| RSB_FLAG_DUPLICATES_SUM
560 		| RSB_FLAG_FORTRAN_INDICES_INTERFACE
561 		, &errval);
562 
563 	if((!mtxAp) || RSB_SOME_ERROR(errval))
564 		RSB_PERR_GOTO(err,RSB_ERRM_ES);
565 
566 	mtxBp = mtxAp;
567 	mtxCp = rsb_sppsp(typecode, transA, alphap, mtxAp, transB, betap, mtxBp, &errval);
568 
569 	if((!mtxCp) || RSB_SOME_ERROR(errval))
570 		RSB_PERR_GOTO(err,RSB_ERRM_ES);
571 
572 	if(mtxAp->nnz != mtxCp->nnz)
573 		RSB_PERR_GOTO(err,RSB_ERRM_ES);
574 }
575 	RSB_INFO("MATRIX SUMS TEST: END\n");
576 	goto ret;
577 err:
578 	RSB_INFO("MATRIX SUMS TEST: FAIL\n");
579 	errval = RSB_ERR_INTERNAL_ERROR;
580 ret:
581 	RSB_MTX_FREE(mtxAp);
582 	RSB_MTX_FREE(mtxCp);
583 	return errval;
584 }
585 
rsb__sigh(int signal)586 void rsb__sigh(int signal)
587 {
588 	/* TODO: extend this mechanism optionally to the library itself. */
589 
590 	if( rsb__quit_rsbench == 0 )
591 	{
592 		RSBENCH_STDOUT("\n");
593 		RSBENCH_STDOUT("====================================================\n");
594 		RSBENCH_STDOUT("Caught signal %d: will terminate as soon as possible.\n",signal);
595 		RSBENCH_STDOUT("  ( next time won't catch the signal anymore ).\n");
596 		RSBENCH_STDOUT("====================================================\n");
597 		RSBENCH_STDOUT("\n");
598 		rsb__quit_rsbench++;
599 	}
600 	else
601 	if( rsb__quit_rsbench == 1 )
602 	{
603 #if defined(RSB_WANT_ACTION_SIGNAL)
604 #else /* defined(RSB_WANT_ACTION_SIGNAL) */
605 		sigaction(SIGINT,&rsb_osa,NULL);
606 #endif /* defined(RSB_WANT_ACTION_SIGNAL) */
607 	}
608 }
609 
rsb__sigr(void)610 void rsb__sigr(void)
611 {
612 	rsb__quit_rsbench = 0;
613 	{
614 #if RSB_WANT_ACTION_SIGNAL
615 		/* signal() is part of C99 */
616 		signal(SIGINT,&rsb__sigh); /* not to be called from a threaded environment ... */
617 #else /* RSB_WANT_ACTION_SIGNAL */
618 		/* sigaction() is part of POSIX, not part of C99 */
619 		struct sigaction act;
620 		RSB_BZERO_P(&act);
621 		RSB_BZERO_P(&rsb_osa);
622 		act.sa_handler  = rsb__sigh;
623 		sigemptyset(&act.sa_mask);
624     		sigaction(SIGINT, &act,&rsb_osa);
625 /*
626 		sigaction(SIGUSR1, &act, &rsb_osa);
627 		sigaction(SIGUSR2, &act, &rsb_osa);
628 
629 		sigaction(SIGQUIT,&act,&rsb_osa);
630 		sigaction(SIGTERM,&act,&rsb_osa);
631 
632 		sigaction(SIGABRT,&act,&rsb_osa);
633 		sigaction(SIGTSTP,&act,&rsb_osa);
634 
635 		sigaction(SIGBUS, &act,&rsb_osa);
636 		sigaction(SIGILL, &act,&rsb_osa);
637 	    	sigaction(SIGSEGV,&act,&rsb_osa);
638 */
639 #endif /* RSB_WANT_ACTION_SIGNAL */
640 	}
641 }
642 #endif /* RSB_WANT_ACTION */
643 
rsb__print_configuration_string_rsbench(const char * pn,rsb_char_t * cs,rsb_bool_t wci)644 rsb_err_t rsb__print_configuration_string_rsbench(const char *pn, rsb_char_t * cs, rsb_bool_t wci)
645 {
646 	/* TODO: output buffer length check */
647 	rsb_err_t errval = RSB_ERR_NO_ERROR;
648 #if RSB_WANT_MKL
649 #ifdef mkl_get_version
650 	MKLVersion mv;
651 #endif /* mkl_get_version */
652 #endif /* RSB_WANT_MKL */
653 	if(!cs)
654 	{
655 		errval = RSB_ERR_BADARGS;
656 		goto err;
657 	}
658 	errval = rsb__print_configuration_string(pn, cs, wci);
659 	if(wci == RSB_BOOL_FALSE)
660 		goto err;
661 #if RSB_WANT_MKL
662 #ifdef mkl_get_version
663 	mkl_get_version(&mv);
664 	sprintf(cs+strlen(cs),"MKL:%d.%d-%d, %s, %s, %s, %s\n",mv.MajorVersion,mv.MinorVersion,mv.UpdateVersion,mv.ProductStatus,mv.Build,mv.Processor,mv.Platform);
665 #else /* mkl_get_version */
666 	sprintf(cs+strlen(cs),"MKL:version unknown.\n");
667 #endif /* mkl_get_version */
668 #else /* RSB_WANT_MKL */
669 	sprintf(cs+strlen(cs),"MKL:not linked.\n");
670 #endif /* RSB_WANT_MKL */
671 #if RSB_WANT_XDR_SUPPORT
672 	sprintf(cs+strlen(cs),"XDR support: on.\n");
673 #else /* RSB_WANT_XDR_SUPPORT */
674 	sprintf(cs+strlen(cs),"XDR support: off.\n");
675 #endif /* RSB_WANT_XDR_SUPPORT */
676 #if RSB_WANT_ZLIB_SUPPORT
677 	sprintf(cs+strlen(cs),"ZLIB support: on.\n");
678 #else /* RSB_WANT_ZLIB_SUPPORT */
679 	sprintf(cs+strlen(cs),"ZLIB support: off.\n");
680 #endif /* RSB_WANT_ZLIB_SUPPORT */
681 err:
682 	return errval;
683 }
684 
rsb__main_help(const int argc,char * const argv[],int default_program_operation,const char * program_codes,rsb_option * options)685 static int rsb__main_help(const int argc, char * const argv[], int default_program_operation, const char * program_codes, rsb_option *options)
686 {
687 			const char * pbn = rsb__basename(argv[0]);
688 
689 			//RSB_STDOUT(
690 			printf(
691 				/*"[OBSOLETE DOCUMENTATION] \n"*/
692 				"Usage: %s [OPTIONS] \n"
693 				"  or:  %s [ -o OPCODE] [ -O {subprogram-code}] [ {subprogram-specific-arguments} ] \n"
694 				"%s "RSB_INFOMSG_SAK"."
695 				"\n"
696 				"\n"
697 				//"\tOne may choose {option} among:\n"
698 				//"\t-I for getting system information and some micro benchmarking\n"
699 				"\t\n"
700 				 "Choose {subprogram-code} among:\n\n"
701 				"\tr for the reference benchmark (will produce a machine specific file)\n\n"
702 				"\tc for the complete benchmark\n\n"
703 				"\te for the matrix experimentation code\n\n"
704 				"\td for a single matrix dumpout\n\n"
705 				"\tb for the (current, going to be obsoleted) benchmark\n\n"
706 				"\tt for some matrix construction tests\n\n"
707 				"\to obsolete, will soon be removed\n"
708 				"\n"
709 				 "{subprogram-specific-arguments} will be available from the subprograms.\n\n"
710 				"\te.g.: %s      -O b -h   will show the current benchmark subprogram's options\n\n"
711 				"\te.g.: %s -o a -O b -h   will show the spmv     benchmark subprogram's options\n\n"
712 				"\te.g.: %s -o n -O b -h   will show the negation benchmark subprogram's options\n\n"
713 //				"\te.g.: %s -o A -O b    will run all of the benchmark programs.\n"
714 				"\nThe default {subprogram-code} is '%c'\n"
715 				"\n\tWith OPCODE among '%s'\n"/* TODO: fix this description, as it is too laconic. */
716 				"\n"
717 				,pbn
718 				,pbn
719 				,pbn
720 				,pbn
721 				,pbn
722 				,pbn
723 				,default_program_operation
724 				,program_codes
725 				);
726 			if(options)
727 				rsb_test_help_and_exit(pbn,options,0);
728 	return 0;
729 }
730 
731 int rsb_genmm_main(int argc,char *argv[]);
732 int rsb_mtx_ls_main(int argc,char *argv[]);
733 
main(const int argc,char * argv[])734 int main(const int argc, char * argv[])
735 {
736 	rsb_option options[] = {
737 	    {"help",			no_argument, NULL, 'h' },
738 	    {"matrix-operation",	required_argument, NULL, 'o' },
739 	    {"subprogram-operation",	required_argument, NULL, 'O' },
740 	    {"information",		no_argument, NULL, 'I' },
741 	    {"configuration",		no_argument, NULL, 'C' },
742 	    {"hardware-counters",	no_argument, NULL, 'H' },
743 	    {"experiments",		no_argument, NULL, 'e' },
744 	    {"version",			no_argument, NULL, 'v' },
745 	    {"blas-testing",		no_argument, NULL, 'B' },
746 	    {"quick-blas-testing",		required_argument, NULL, 'Q' },
747 	    {"error-testing",		required_argument, NULL, 'E' },
748 	    {"fp-bench",		no_argument, NULL, 'F' },
749 	    {"transpose-test",		no_argument, NULL, 't' },
750 	    {"limits-testing",		no_argument, NULL, 0x6c696d74 },
751 	    {"guess-blocking",		no_argument, NULL, 'G' },	/* will pass guess parameters here some day (FIXME: obsolete) */
752 	    {"generate-matrix",		no_argument, NULL, 'g' }, /* should be synced to rsb_genmm_main */
753 	    {"plot-matrix",		no_argument, NULL,  0x50505050},/* should be synced to rsb__dump_postscript */
754 	    {"matrix-ls",		no_argument, NULL,  0x006D6C73},/* should be synced to rsb_mtx_ls_main */
755 	    {"read-performance-record",		required_argument, NULL,  0x7270720a},/*  */
756 	    {"help-read-performance-record",		no_argument, NULL,  0x72707268},/*  */
757 	    {0,0,0,0}
758 	};
759 
760 	/*
761 	 * NOTE: this implies that unless an argument reset mechanism is implemented here,
762 	 * the o and O options will be forwarded to the host program!
763 	 * */
764 	//const char default_operation='v';
765 	const char default_operation='a';
766 	char operation=default_operation;
767 	//const char default_program_operation='r';
768 	const char default_program_operation='b';
769 	char program_operation=default_program_operation;
770 	rsb_err_t errval = RSB_ERR_NO_ERROR;
771 #if RSB_WANT_REDUCED_RSB_M4_MATRIX_META_OPS
772 	const char * program_codes = "a"
773 #else /* RSB_WANT_REDUCED_RSB_M4_MATRIX_META_OPS */
774 	const char * program_codes = "avms"
775 #endif /* RSB_WANT_REDUCED_RSB_M4_MATRIX_META_OPS */
776 #if !RSB_SHALL_UPDATE_COMPLETEBENCHS
777 		"c"
778 #endif /* RSB_SHALL_UPDATE_COMPLETEBENCHS */
779 #ifdef RSB_OPTYPE_INDEX_SPSV_UXUA
780 		"t"
781 #endif
782 		"inS";
783 	int program_not_chosen=1;
784 	struct rsb_tester_options_t to;
785 	rsb_char_t cs[RSB_MAX_VERSION_STRING_LENGTH];
786 	int c;
787 
788 	rsb_blas_tester_options_init(&to);
789 
790 	for (;program_not_chosen;)
791 	{
792 		int opt_index = 0;
793 		c = rsb_getopt_long(argc,argv,"CP:"
794 				"gBGvMHIho:O:"
795 /* #if RSB_WANT_EXPERIMENTS_CODE
796 				"e"
797 #endif */ /* RSB_WANT_EXPERIMENTS_CODE */
798 				"FQ:E:",options,&opt_index);
799 		if (c == -1)break;
800 		switch (c)
801 		{
802 			case 'F':
803 				/*
804 				 * Floating point mini-benchmark
805 				 * */
806 				return (rsb_lib_init(RSB_NULL_INIT_OPTIONS) == RSB_ERR_NO_ERROR && rsb__fp_benchmark() == RSB_ERR_NO_ERROR) ?RSB_PROGRAM_ERROR:RSB_PROGRAM_SUCCESS;
807 			break;
808 			case 'G':
809 				/*
810 				 * Sparse GEMM preliminary code.
811 				 * TODO: remove this temporary case, as it may break other functionality with the G flag.
812 				 * */
813 				return RSB_ERR_TO_PROGRAM_ERROR(rsb__do_spgemm_test_code(argc-1,argv+1));
814 			case 'g':
815 				return RSB_ERR_TO_PROGRAM_ERROR(rsb_genmm_main(argc,argv));
816 			break;
817 			case 0x006D6C73:
818 				return RSB_ERR_TO_PROGRAM_ERROR(rsb_mtx_ls_main(argc,argv));
819 			break;
820 			case 0x7270720a:
821 			case 0x72707268:
822 			goto qos;
823 			break;
824 			case 0x50505050:
825 				return RSB_ERR_TO_PROGRAM_ERROR(rsb__dump_postscript(argc,argv));
826 			break;
827 			case 0x6c696d74:
828 			{
829 				if((errval = rsb_lib_init(RSB_NULL_INIT_OPTIONS)) != RSB_ERR_NO_ERROR)
830 					goto berr;
831 				RSB_DO_ERROR_CUMULATE(errval,rsb_blas_limit_cases_tester());
832 				if((!RSB_WANT_PERMISSIVE_RSBENCH) && RSB_SOME_ERROR(errval))goto ferr;
833 				return RSB_ERR_TO_PROGRAM_ERROR(errval);
834 			}
835 			break;
836 			case 'E':
837 			{
838 				if((errval = rsb_lib_init(RSB_NULL_INIT_OPTIONS)) != RSB_ERR_NO_ERROR)
839 					goto berr;
840 				RSB_DO_ERROR_CUMULATE(errval,rsb_blas_failure_tester(optarg));
841 				if((!RSB_WANT_PERMISSIVE_RSBENCH) && RSB_SOME_ERROR(errval))goto ferr;
842 				return RSB_ERR_TO_PROGRAM_ERROR(errval);
843 			}
844 			case 'Q':
845 				to.mtt = rsb__util_atof(optarg);
846 				if(strstr(optarg,"R")!=NULL)to.rrm=RSB_BOOL_TRUE;
847 				if(strstr(optarg,"U")!=NULL)to.tur=RSB_BOOL_TRUE;
848 				if(strstr(optarg,"Q")!=NULL)to.wqt=RSB_BOOL_TRUE;
849 				if(strstr(optarg,"q")!=NULL)to.wqc=RSB_BOOL_TRUE;
850 				if(strstr(optarg,"C")!=NULL)to.wcs=RSB_BOOL_TRUE;
851 			case 'B':
852 			RSB_SIGHR
853 			/* Sparse BLAS test.  */
854 //#if RSB_WITH_SPARSE_BLAS_INTERFACE
855 #if 1
856 			{
857 				if((errval = rsb_lib_init(RSB_NULL_INIT_OPTIONS)) != RSB_ERR_NO_ERROR)
858 					goto berr;
859 #if RSB_ALLOW_INTERNAL_GETENVS
860 				if(getenv("RSB_RSBENCH_BBMB") && rsb__util_atoi(getenv("RSB_RSBENCH_BBMB")) )
861 					goto bbmb;
862 #endif /* RSB_ALLOW_INTERNAL_GETENVS */
863 				RSB_DO_ERROR_CUMULATE(errval,rsb_blas_runtime_limits_tester());
864 				if((!RSB_WANT_PERMISSIVE_RSBENCH) && RSB_SOME_ERROR(errval))goto ferr;
865 #if 0
866 				/*  TODO: this is here temporarily */
867 				RSB_DO_ERROR_CUMULATE(errval,rsb__do_lock_test());
868 #endif
869 				RSB_DO_ERROR_CUMULATE(errval,rsb__chk_srt());
870 				if((!RSB_WANT_PERMISSIVE_RSBENCH) && RSB_SOME_ERROR(errval))goto ferr;
871 				RSB_DO_ERROR_CUMULATE(errval,rsb__chk_trtr());
872 				if((!RSB_WANT_PERMISSIVE_RSBENCH) && RSB_SOME_ERROR(errval))goto ferr;
873 				RSB_DO_ERROR_CUMULATE(errval,rsb__chk_sppsp());
874 				if((!RSB_WANT_PERMISSIVE_RSBENCH) && RSB_SOME_ERROR(errval))goto ferr;
875 				RSB_DO_ERROR_CUMULATE(errval,rsb_blas_mini_tester());
876 				if((!RSB_WANT_PERMISSIVE_RSBENCH) && RSB_SOME_ERROR(errval))goto ferr;
877 				//RSB_LIKWID_MARKER_INIT;
878 				//RSB_LIKWID_MARKER_R_START("RSB-QUICKTEST");
879 #if RSB_ALLOW_INTERNAL_GETENVS
880 bbmb:
881 #endif /* RSB_ALLOW_INTERNAL_GETENVS */
882 				RSB_DO_ERROR_CUMULATE(errval,rsb_blas_bigger_matrices_tester(&to));/* TODO: options should be passed here */
883 				//RSB_LIKWID_MARKER_R_STOP("RSB-QUICKTEST");
884 				//RSB_LIKWID_MARKER_EXIT;
885 				if((!RSB_WANT_PERMISSIVE_RSBENCH) && RSB_SOME_ERROR(errval))
886 					goto ferr;
887 				goto ferr;
888 			}
889 #else
890 				RSB_STDERR("no Sparse BLAS interface built.\n");
891 				//return -1;
892 				return 0;
893 #endif
894 			break;
895 			case 'C':
896 				if((errval = rsb_lib_init(RSB_NULL_INIT_OPTIONS)) != RSB_ERR_NO_ERROR)
897 					RSB_STDERR(RSB_ERRM_SILTC);
898 				errval = rsb__print_configuration_string_rsbench(argv[0],cs,RSB_BOOL_TRUE);
899 				printf("%s",cs);
900 				goto verr;
901 			break;
902 			case 'v':
903 				if((errval = rsb_lib_init(RSB_NULL_INIT_OPTIONS)) != RSB_ERR_NO_ERROR)
904 					RSB_STDERR(RSB_ERRM_SILTC);
905 				errval = rsb__print_configuration_string_rsbench(argv[0],cs,RSB_BOOL_FALSE);
906 				printf("%s",cs);
907 				goto verr;
908 			break;
909 			case 'M':
910 				if((errval = rsb_lib_init(RSB_NULL_INIT_OPTIONS)) != RSB_ERR_NO_ERROR)
911 					RSB_PERR_GOTO(err,RSB_ERRM_ES);
912 				return RSB_ERR_TO_PROGRAM_ERROR(rsb__memory_benchmark());
913 			break;
914 			case 'H':
915 				return RSB_ERR_TO_PROGRAM_ERROR(rsb_hc_main());		/* preliminary */
916 			break;
917 			case 'I':
918 				rsb_lib_init(RSB_NULL_INIT_OPTIONS);
919 			return
920 				RSB_ERR_TO_PROGRAM_ERROR(rsb_perror(NULL,rsb__sys_info()));
921 			break;
922 			/*
923 #if RSB_WANT_EXPERIMENTS_CODE
924 			case 'e':
925 				return rsb_exp_bcsr_guess_experiments(argc,argv);
926 			break;
927 #endif */ /* RSB_WANT_EXPERIMENTS_CODE */
928 			case 'P':
929 		{
930 			errval = rsb_lib_init(RSB_NULL_INIT_OPTIONS);
931 			if(RSB_SOME_ERROR(errval))
932 				goto err;
933 			{
934 				struct rsb_mtx_t * mtxAp = rsb_file_mtx_load(optarg,RSB_FLAG_DEFAULT_MATRIX_FLAGS,RSB_NUMERICAL_TYPE_DEFAULT,NULL);
935 				errval = rsb_file_mtx_save(mtxAp,NULL);
936 				RSB_MTX_FREE(mtxAp);
937 			}
938 			RSB_MASK_OUT_SOME_ERRORS(errval)
939 			goto verr;
940 		}
941 			break;
942 			case 'o':
943 				operation=*optarg;
944 			break;
945 			case 'O':
946 				program_operation=*optarg;
947 				program_not_chosen=0;
948 			break;
949 			case 'h':
950 				/* getsubopt may come in help here */
951 				return rsb__main_help(argc, argv,default_program_operation,program_codes,options);
952 			break;
953 			/*
954 			case 't':
955 				return rsb__main_transpose(argc,argv);
956 			break;
957 			*/
958 			default:
959 			{
960 			}
961 		}
962 	}
963 
964 qos:	/* quit option selection */
965 
966 	if(c == 0x72707268)
967 	{
968 		errval = rsb__pr_dumpfiles(NULL,0);
969 		return RSB_ERR_TO_PROGRAM_ERROR(errval);
970 	}
971 	if(c == 0x7270720a)
972 	{
973 /*
974 		if(argc == 3)
975 			return rsb__pr_dumpfile(optarg);
976 		if(argc == 3)
977 			return rsb__pr_dumpfiles(&optarg,1);
978  */
979 
980 		if(argc >= 3)
981 		{
982 			const int RSB__PR_DUMP_MAXARGS = 1024; /* TODO: temporary */
983 			const rsb_char_t*fna[RSB__PR_DUMP_MAXARGS];
984 			int i;
985 			for(i=2;i<RSB_MIN(RSB__PR_DUMP_MAXARGS,argc);++i)
986 				fna[i-2] = argv[i];
987 			errval = rsb__pr_dumpfiles(fna,i-2);
988 			return RSB_ERR_TO_PROGRAM_ERROR(errval);
989 		}
990 	}
991 
992 	if(program_not_chosen)
993 		return rsb__main_help(argc, argv,default_program_operation,program_codes,options);
994 
995 	switch (program_operation)	/* O */
996 	{
997 		case 'r':
998 	{
999 			/*
1000 			 * A benchmark to compute (machine,compiled) reference performance values.
1001 			 * */
1002 			errval = rsb_lib_init(RSB_NULL_INIT_OPTIONS);
1003 			if(errval == RSB_ERR_NO_ERROR)
1004 				goto verr;
1005 			errval = rsb__do_referencebenchmark(); /* FIXME: probably obsolete */
1006 			RSB_MASK_OUT_SOME_ERRORS(errval)
1007 			goto verr;
1008 	}
1009 		break;
1010 		case 'R':
1011 			/**/
1012 			/*
1013 			 * Dump current (hardcoded) performance info without computing anything.
1014 			 * */
1015 			errval = rsb__dump_current_global_reference_performance_info(); /* FIXME: probably obsolete */
1016 			RSB_MASK_OUT_SOME_ERRORS(errval)
1017 			goto verr;
1018 		break;
1019 #if !RSB_SHALL_UPDATE_COMPLETEBENCHS
1020 		case 'c':
1021 			/* A complete benchmark.  TODO: this is broken / old; needs a revamp, or oblivion  */
1022 			errval = rsb_do_completebenchmark(argc,argv); /* FIXME: probably obsolete */
1023 			RSB_MASK_OUT_SOME_ERRORS(errval)
1024 			goto verr;
1025 		break;
1026 #endif /* RSB_SHALL_UPDATE_COMPLETEBENCHS */
1027 		case 'd':
1028 			/*
1029 			 * A single matrix dump (almost useless).
1030 			 * */
1031 			return rsb__test_dump_main(argc,argv); /* FIXME: probably obsolete */
1032 		break;
1033 		case 'e':
1034 			/*
1035 			 * The matrix experimentation code.
1036 			 * */
1037 			RSB_STDERR("this option was obsoleted by -oS -Ob\n");
1038 			/*return rsb_test_main_block_partitioned_matrix_stats(argc,argv); */ /* FIXME: probably obsolete */
1039 			return -1;
1040 		break;
1041 		case 'b':
1042 		{
1043 			/*
1044 			 * The current reference benchmark.
1045 			 * */
1046 			RSB_SIGHR
1047 			switch(operation)	/* o */
1048 			{
1049 #ifdef RSB_HAVE_OPTYPE_SPMV_UAUA
1050 				case 'a':
1051 				return RSB_ERR_TO_PROGRAM_ERROR(rsb__main_block_partitioned_spmv_uaua(argc,argv));
1052 				break;
1053 #endif /* RSB_HAVE_OPTYPE_SPMV_UAUA */
1054 #if !RSB_WANT_REDUCED_RSB_M4_MATRIX_META_OPS
1055 #ifdef RSB_HAVE_OPTYPE_SPMV_UAUZ
1056 				case 'v':
1057 				return RSB_ERR_TO_PROGRAM_ERROR(rsb__main_block_partitioned_spmv_uauz(argc,argv));
1058 				break;
1059 #endif /* RSB_HAVE_OPTYPE_SPMV_UAUZ */
1060 #ifdef RSB_HAVE_OPTYPE_SPMM_AZ
1061 				case 'm':
1062 				return RSB_ERR_TO_PROGRAM_ERROR(rsb__main_block_partitioned_spmm_az(argc,argv));
1063 				break;
1064 #endif /* RSB_HAVE_OPTYPE_SPMM_AZ */
1065 #ifdef RSB_HAVE_OPTYPE_SCALE
1066 				case 's':
1067 				return RSB_ERR_TO_PROGRAM_ERROR(rsb__main_block_partitioned_scale(argc,argv));
1068 				break;
1069 #endif /* RSB_HAVE_OPTYPE_SCALE */
1070 #ifdef RSB_HAVE_OPTYPE_SPMV_UXUX
1071 				case 'c':
1072 				return RSB_ERR_TO_PROGRAM_ERROR(rsb__main_block_partitioned_spmv_uxux(argc,argv));
1073 				break;
1074 #endif /* RSB_HAVE_OPTYPE_SPMV_UXUX */
1075 #ifdef RSB_HAVE_OPTYPE_INFTY_NORM
1076 				case 'i':
1077 				return RSB_ERR_TO_PROGRAM_ERROR(rsb__main_block_partitioned_infty_norm(argc,argv));
1078 				break;
1079 #endif /* RSB_HAVE_OPTYPE_INFTY_NORM */
1080 #ifdef RSB_HAVE_OPTYPE_NEGATION
1081 				case 'n':
1082 				return RSB_ERR_TO_PROGRAM_ERROR(rsb__main_block_partitioned_negation(argc,argv));
1083 				break;
1084 #endif /* RSB_HAVE_OPTYPE_NEGATION */
1085 #endif /* RSB_WANT_REDUCED_RSB_M4_MATRIX_META_OPS */
1086 #ifdef RSB_OPTYPE_INDEX_SPSV_UXUA
1087 				case 't':
1088 				return RSB_ERR_TO_PROGRAM_ERROR(rsb__main_block_partitioned_spsv_uxua(argc,argv));
1089 				break;
1090 #endif /* RSB_OPTYPE_INDEX_SPSV_UXUA */
1091 #if 1	/* this is a special case */
1092 				case 'S':
1093 				//return rsb__main_block_partitioned_sort_only(argc,argv);//old
1094 				return RSB_ERR_TO_PROGRAM_ERROR(rsb__main_block_partitioned_mat_stats(argc,argv));//new
1095 				break;
1096 #endif
1097 				default:
1098 				RSB_STDERR(
1099 					"You did not choose a correct operation code.\n"
1100 					"Choose one among %s.\n",program_codes
1101 					);
1102 				errval = RSB_ERR_UNSUPPORTED_OPERATION;
1103 				RSB_DO_ERR_RETURN(errval)
1104 			}
1105 		}
1106 		break;
1107 #if 0
1108 		case 't': /* to reintegrate, add 't' to program_codes */
1109 			/*
1110 			 * A whole matrix repartitioning test.
1111 			 * */
1112 			return RSB_ERR_TO_PROGRAM_ERROR(rsb_test_main_block_partitioned_construction_test(argc,argv));
1113 		break;
1114 #endif
1115 		default:
1116 			RSB_STDERR("You did not choose an action. See help:\n");
1117 			return rsb__main_help(argc, argv,default_program_operation,program_codes,NULL);
1118 		return RSB_PROGRAM_SUCCESS;
1119     	}
1120 	goto err;
1121 ferr:
1122 	/* rsb__getrusage(); */
1123 	RSB_DO_ERROR_CUMULATE(errval,rsb_lib_exit(RSB_NULL_EXIT_OPTIONS));
1124 berr:
1125 	if(RSB_SOME_ERROR(errval))
1126 		rsb_perror(NULL,errval);
1127 verr:
1128 	return RSB_ERR_TO_PROGRAM_ERROR(errval);
1129 err:
1130 	if(RSB_SOME_ERROR(errval))
1131 		rsb_perror(NULL,errval);
1132 	return RSB_PROGRAM_ERROR;
1133 }
1134 
1135 /* @endcond */
1136