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 source file contains matrix info getter functions.
28  * */
29 
30 #include "rsb_internals.h"
31 
32 RSB_INTERNALS_COMMON_HEAD_DECLS
33 
rsb__is_coo_matrix(const struct rsb_mtx_t * mtxAp)34 rsb_bool_t rsb__is_coo_matrix(const struct rsb_mtx_t *mtxAp)
35 {
36 	/*!
37 	 * \ingroup gr_internals
38 	 * */
39 	rsb_bool_t is;
40 	RSB_DEBUG_ASSERT(mtxAp);
41 	if(!mtxAp)
42 		return RSB_BOOL_FALSE;
43 
44 	is = (
45 #ifdef RSB_MATRIX_STORAGE_BCOR
46 	 (mtxAp->matrix_storage == RSB_MATRIX_STORAGE_BCOR)||
47 #endif /* RSB_MATRIX_STORAGE_BCOR */
48 #ifdef RSB_MATRIX_STORAGE_BCOC
49 	 (mtxAp->matrix_storage == RSB_MATRIX_STORAGE_BCOC)||
50 #endif /* RSB_MATRIX_STORAGE_BCOC */
51 	  0
52 	)?RSB_BOOL_TRUE:RSB_BOOL_FALSE;
53 	return is;
54 }
55 
rsb__is_square(const struct rsb_mtx_t * mtxAp)56 rsb_bool_t rsb__is_square(const struct rsb_mtx_t *mtxAp)
57 {
58 	/*!
59 	 * \ingroup gr_internals
60 	 * */
61 	RSB_DEBUG_ASSERT(mtxAp);
62 	if(!mtxAp)
63 		return RSB_BOOL_FALSE;
64 
65 	return (mtxAp->nr == mtxAp->nc)?RSB_BOOL_TRUE:RSB_BOOL_FALSE;
66 }
67 
rsb__is_hermitian(const struct rsb_mtx_t * mtxAp)68 rsb_bool_t rsb__is_hermitian(const struct rsb_mtx_t *mtxAp)
69 {
70 	/*!
71 	 * \ingroup gr_internals
72 	 * */
73 	if(!mtxAp)
74 		return RSB_BOOL_FALSE;
75 
76 	return (rsb__get_hermitian_flag(mtxAp))?RSB_BOOL_TRUE:RSB_BOOL_FALSE;
77 }
78 
rsb__is_triangle(rsb_flags_t flags)79 rsb_bool_t rsb__is_triangle(rsb_flags_t flags)
80 {
81 	return (rsb__is_lower_triangle(flags) | rsb__is_upper_triangle(flags));
82 }
83 
rsb__is_lower_triangle(rsb_flags_t flags)84 rsb_bool_t rsb__is_lower_triangle(rsb_flags_t flags)
85 {
86 	/*!
87 	 * \ingroup gr_internals
88 	 * */
89 	return (RSB_DO_FLAG_HAS(flags,RSB_FLAG_LOWER|RSB_FLAG_TRIANGULAR));
90 }
91 
rsb__is_upper_triangle(rsb_flags_t flags)92 rsb_bool_t rsb__is_upper_triangle(rsb_flags_t flags)
93 {
94 	/*!
95 	 * \ingroup gr_internals
96 	 * */
97 	return (RSB_DO_FLAG_HAS(flags,RSB_FLAG_UPPER|RSB_FLAG_TRIANGULAR));
98 }
99 
rsb__is_symmetric(const struct rsb_mtx_t * mtxAp)100 rsb_bool_t rsb__is_symmetric(const struct rsb_mtx_t *mtxAp)
101 {
102 	/*!
103 	 * \ingroup gr_internals
104 	 * */
105 	if(!mtxAp)
106 		return RSB_BOOL_FALSE;
107 
108 	return (rsb__get_symmetry_flag(mtxAp))?RSB_BOOL_TRUE:RSB_BOOL_FALSE;
109 }
110 
rsb__is_not_unsymmetric(const struct rsb_mtx_t * mtxAp)111 rsb_bool_t rsb__is_not_unsymmetric(const struct rsb_mtx_t *mtxAp)
112 {
113 	/*!
114 	 * \ingroup gr_internals
115 	 * */
116 	if(!mtxAp)
117 		return RSB_BOOL_FALSE;
118 
119 	if(rsb__get_hermitian_flag(mtxAp) || rsb__get_symmetry_flag(mtxAp))
120 		return RSB_BOOL_TRUE;
121 	else
122 		return RSB_BOOL_FALSE;
123 }
124 
rsb__is_csr_matrix(const struct rsb_mtx_t * mtxAp)125 rsb_bool_t rsb__is_csr_matrix(const struct rsb_mtx_t *mtxAp)
126 {
127 	/*!
128 	 * \ingroup gr_internals
129 	 * */
130 	const rsb_bool_t is_csr = RSB_DO_FLAG_HAS(mtxAp->flags,RSB_FLAG_WANT_BCSS_STORAGE);
131 
132 	return is_csr;
133 }
134 
rsb__is_bcss_matrix(const struct rsb_mtx_t * mtxAp)135 rsb_bool_t rsb__is_bcss_matrix(const struct rsb_mtx_t *mtxAp)
136 {
137 	/*!
138 	 * \ingroup gr_internals
139 	 * \return nonzero if the given matrix is row or column block major
140 	 *
141 	 * */
142 	rsb_bool_t ret = 0;
143 
144 	if(!mtxAp)
145 		return ret;
146 	ret =
147 #ifdef RSB_MATRIX_STORAGE_BCSR
148 		mtxAp->matrix_storage & RSB_MATRIX_STORAGE_BCSR ||
149 #endif /* RSB_MATRIX_STORAGE_BCSR */
150 #ifdef RSB_MATRIX_STORAGE_BCSC
151 		mtxAp->matrix_storage & RSB_MATRIX_STORAGE_BCSC ||
152 #endif /* RSB_MATRIX_STORAGE_BCSC */
153 		 0;
154 
155 #if RSB_EXPERIMENTAL_USE_PURE_BCSS
156 	if(ret)
157 	{
158 		RSB_ASSERT(mtxAp->br>0);
159 		RSB_ASSERT(mtxAp->bc>0);
160 	}
161 #endif /* RSB_EXPERIMENTAL_USE_PURE_BCSS */
162 	return ret;
163 }
164 
rsb__is_css_matrix(const struct rsb_mtx_t * mtxAp)165 rsb_bool_t rsb__is_css_matrix(const struct rsb_mtx_t *mtxAp)
166 {
167 	/*!
168 	 * \ingroup gr_internals
169 	 * \return nonzero if the given matrix is not CSR or CSC.
170 	 *
171 	 * */
172 	//rsb_bool_t ret = RSB_BOOL_FALSE;
173 	rsb_blk_idx_t br, bc;
174 	rsb_err_t errval = RSB_ERR_NO_ERROR;
175 
176 	if(!mtxAp)
177 		return RSB_BOOL_FALSE;
178 
179 	if((errval = rsb__get_blocking_size(mtxAp, &br, &bc))!=RSB_ERR_NO_ERROR)
180 		return RSB_BOOL_FALSE;
181 
182 	return ( br==1 && bc==1 ) ? RSB_BOOL_TRUE : RSB_BOOL_FALSE;
183 }
184 
rsb__is_bcsr_matrix(const struct rsb_mtx_t * mtxAp)185 rsb_bool_t rsb__is_bcsr_matrix(const struct rsb_mtx_t *mtxAp)
186 {
187 	/*!
188 	 * \ingroup gr_internals
189 	 * \return nonzero if the given matrix is row block major.
190 	 *
191 	 * */
192 	rsb_bool_t ret = RSB_BOOL_FALSE;
193 
194 	if(!mtxAp)
195 		return ret;
196 
197 #ifdef RSB_MATRIX_STORAGE_BCSR
198 	if( ( mtxAp->matrix_storage & RSB_MATRIX_STORAGE_BCSR ) != 0 ) ret = RSB_BOOL_TRUE;
199 #endif /* RSB_MATRIX_STORAGE_BCSR */
200 
201 #if RSB_EXPERIMENTAL_USE_PURE_BCSS
202 	if(ret)
203 	{
204 		RSB_ASSERT(mtxAp->br>0);
205 		RSB_ASSERT(mtxAp->bc>0);
206 	}
207 #endif /* RSB_EXPERIMENTAL_USE_PURE_BCSS */
208 	return ret;
209 }
210 
rsb__is_bcsc_matrix(const struct rsb_mtx_t * mtxAp)211 rsb_bool_t rsb__is_bcsc_matrix(const struct rsb_mtx_t *mtxAp)
212 {
213 	/*!
214 	 * \ingroup gr_internals
215 	 * \return nonzero if the given matrix is column block major.
216 	 *
217 	 * */
218 	rsb_bool_t ret = 0;
219 
220 	if(!mtxAp)
221 		return ret;
222 
223 	ret =
224 #ifdef RSB_MATRIX_STORAGE_BCSC
225 		mtxAp->matrix_storage & RSB_MATRIX_STORAGE_BCSC ||
226 #endif /* RSB_MATRIX_STORAGE_BCSC */
227 	0;
228 
229 #if RSB_EXPERIMENTAL_USE_PURE_BCSS
230 	if(ret)
231 	{
232 		RSB_ASSERT(mtxAp->br>0);
233 		RSB_ASSERT(mtxAp->bc>0);
234 	}
235 #endif /* RSB_EXPERIMENTAL_USE_PURE_BCSS */
236 	return ret;
237 }
238 
rsb__have_fixed_blocks_matrix_flags(rsb_flags_t flags)239 rsb_bool_t rsb__have_fixed_blocks_matrix_flags(rsb_flags_t flags)
240 {
241 	/*!
242 	 * \ingroup gr_internals
243 	 * \return nonzero if the given flags are for a fixed block partitioning.
244 	 * */
245 	return RSB_DO_FLAG_HAS_INTERSECTION(flags,( RSB_FLAG_WANT_FIXED_BLOCKING_VBR | RSB_FLAG_WANT_BCSS_STORAGE | RSB_FLAG_WANT_COO_STORAGE ));
246 }
247 
rsb__have_linked_storage(const rsb_flags_t flags)248 rsb_bool_t rsb__have_linked_storage(const rsb_flags_t flags)
249 {
250 	/*!
251 	 * \ingroup gr_internals
252 	 * \return nonzero if the given flags are for a linked lists storage.
253 	 */
254 #ifdef RSB_FLAG_WANT_LINKED_STORAGE
255 	return RSB_DO_FLAG_HAS(flags,RSB_FLAG_WANT_LINKED_STORAGE);
256 #else /* RSB_FLAG_WANT_LINKED_STORAGE */
257 	return RSB_BOOL_FALSE;
258 #endif /* RSB_FLAG_WANT_LINKED_STORAGE */
259 }
260 
rsb__is_terminal_recursive_matrix(const struct rsb_mtx_t * mtxAp)261 rsb_bool_t rsb__is_terminal_recursive_matrix(const struct rsb_mtx_t *mtxAp)
262 {
263 	/*!
264 	 * \ingroup gr_internals
265 	 * \return nonzero if the given matrix is terminal
266 	 * FIXME : is this function really needed ?
267 	 * FIXME : should return one for terminal of non recursive ?
268 	 * TODO rsb__is_terminal_recursive_matrix -> rsb_is_terminal_matrix or rsb_is_leaf_matrix
269 	 */
270 	rsb_submatrix_idx_t i,j;
271 	struct rsb_mtx_t * submatrix = NULL;
272 	int smc = 0;
273 
274 	if(!mtxAp)
275 		goto rz;
276 
277 	RSB_SUBMATRIX_FOREACH(mtxAp,submatrix,i,j)
278 	if(submatrix)
279 		++smc;
280 
281 	return (smc==0);
282 rz:
283 	return 0; /* TODO: eliminate this case */
284 }
285 
rsb__is_recursive_matrix(rsb_flags_t flags)286 rsb_bool_t rsb__is_recursive_matrix(rsb_flags_t flags)
287 {
288 	/*!
289 	 * \ingroup gr_internals
290 	 * \return nonzero if the given flags are for a recursive storage.
291 	 */
292 	return
293 	(RSB_DO_FLAG_HAS(flags,RSB_FLAG_QUAD_PARTITIONING));
294 }
295 
rsb__is_fixed_block_matrix(const struct rsb_mtx_t * mtxAp)296 rsb_bool_t rsb__is_fixed_block_matrix(const struct rsb_mtx_t *mtxAp)
297 {
298 	/*!
299 	 * \ingroup gr_internals
300 	 * \return nonzero if the given matrix was partitioned with a fixed blocking,
301 	 *         thus enabling optimized operations on it.
302 	 * */
303 	if(!mtxAp)
304 		return 0;
305 
306 	if( rsb__have_fixed_blocks_matrix_flags(mtxAp->flags) )
307 		return 1;
308 
309 	/* FIXME : is this ok ? */
310 	if(
311 #ifdef RSB_MATRIX_STORAGE_VBR
312 		mtxAp->matrix_storage & RSB_MATRIX_STORAGE_VBR ||
313 #endif /* RSB_MATRIX_STORAGE_VBR */
314 #ifdef RSB_MATRIX_STORAGE_VBC
315 		mtxAp->matrix_storage & RSB_MATRIX_STORAGE_VBC ||
316 #endif/* RSB_MATRIX_STORAGE_VBC */
317 		0 )
318 		return RSB_DO_FLAG_HAS(mtxAp->flags,RSB_FLAG_WANT_FIXED_BLOCKING_VBR);
319 
320 	else
321 	return
322 #ifdef RSB_MATRIX_STORAGE_BCSR
323 		mtxAp->matrix_storage & RSB_MATRIX_STORAGE_BCSR ||
324 #endif /* RSB_MATRIX_STORAGE_BCSR */
325 #ifdef RSB_MATRIX_STORAGE_BCSC
326 		mtxAp->matrix_storage & RSB_MATRIX_STORAGE_BCSC ||
327 #endif /* RSB_MATRIX_STORAGE_BCSC */
328 		0;
329 }
330 
rsb__util_are_flags_suitable_for_optimized_1x1_constructor(rsb_flags_t flags)331 rsb_bool_t rsb__util_are_flags_suitable_for_optimized_1x1_constructor(rsb_flags_t flags)
332 {
333 	/*!
334 	 	\ingroup gr_internals
335 		FIXME : temporary
336 	*/
337 	return	(RSB_DO_FLAG_HAS(  flags,RSB_FLAG_WANT_BCSS_STORAGE)  &&
338 		 (!RSB_DO_FLAG_HAS(flags,RSB_FLAG_AUTO_BLOCKING))    &&
339 		 (!RSB_DO_FLAG_HAS(flags,RSB_FLAG_QUAD_PARTITIONING )) );
340 }
341 
rsb__is_root_matrix(const struct rsb_mtx_t * mtxAp)342 rsb_bool_t rsb__is_root_matrix(const struct rsb_mtx_t *mtxAp)
343 {
344 	/*!
345 	 	\ingroup gr_internals
346 	*/
347 	return (!RSB_DO_FLAG_HAS(mtxAp->flags,RSB_FLAG_NON_ROOT_MATRIX))?RSB_BOOL_TRUE:RSB_BOOL_FALSE;
348 }
349 
rsb__mtx_chk(const struct rsb_mtx_t * mtxAp)350 rsb_bool_t rsb__mtx_chk(const struct rsb_mtx_t *mtxAp)
351 {
352 	/*!
353 	 	\ingroup gr_internals
354 
355 		This is mainly used as a debugging tool when re-developing core functionality.
356 		FIXME: will die in the presence of the RSB_FLAG_FORTRAN_INDICES_INTERFACE flag
357 		TODO: move to rsb__mtx_check.c
358 		TODO: invoke rsb__check_bounds.
359 	*/
360 	if(!mtxAp)
361 	{
362 	       	RSB_ERROR(RSB_ERRM_ES);
363 		RSB_PERR_GOTO(err,RSB_ERRM_E_MTXAP);
364 	}
365 
366 	if( RSB_INVALID_COO_INDEX(mtxAp->Mdim)  || RSB_INVALID_COO_INDEX(mtxAp->nr) || RSB_INVALID_NNZ_INDEX(mtxAp->nnz) )
367 	{
368 	       	RSB_ERROR("out of allowed bounds dimensions !");
369 		RSB_ERROR("bad matrix:"),RSB_ERROR_MATRIX_SUMMARY(mtxAp),RSB_ERROR(RSB_ERRM_NL);
370 		RSB_PERR_GOTO(err,RSB_ERRM_ES)
371 	}
372 
373 	if ( rsb__get_hermitian_flag(mtxAp) && rsb__get_symmetry_flag(mtxAp) )
374 	{
375 		RSB_PERR_GOTO(err,"bad flags: matrix at once hermitian and symmetric!\n");
376 	}
377 
378 #if RSB_MERCY_FOR_LEGACY_INTERFACE
379 	if(
380 			rsb_get_matrix_n_rows(mtxAp)!=mtxAp->nr ||
381 			rsb_get_matrix_n_columns(mtxAp)!=mtxAp->nc ||
382 			rsb_get_matrix_n_rows(NULL)!=RSB_DEFAULT_UNDEFINED_COO_VALUE  ||
383 			rsb_get_matrix_n_columns(NULL)!=RSB_DEFAULT_UNDEFINED_COO_VALUE
384 			)
385 #else /* RSB_MERCY_FOR_LEGACY_INTERFACE */
386 	if(0)
387 #endif /* RSB_MERCY_FOR_LEGACY_INTERFACE */
388 	{
389 		RSB_PERR_GOTO(err,RSB_ERRM_ES)
390 	}
391 
392 	/* if(rsb__is_recursive_matrix(mtxAp->flags) && ! RSB_DO_FLAG_HAS_INTERSECTION(mtxAp->flags,RSB_FLAG_NON_ROOT_MATRIX ) ) */
393 	if( rsb__is_recursive_matrix(mtxAp->flags) )
394 	{
395 		rsb_submatrix_idx_t i,j;
396 		struct rsb_mtx_t * submatrix;
397 
398 		/* RSB_ASSERT( mtxAp->VA == NULL && mtxAp->bpntr == NULL && mtxAp->bindx == NULL ); */
399 
400 		if( rsb__is_root_matrix(mtxAp) ) /* 20140921 */
401 		{
402 			rsb_submatrix_idx_t smi;
403 
404 			RSB_SUBMATRIX_FOREACH_LEAF(mtxAp,submatrix,smi)
405 			{
406 				if(!submatrix)
407 				{
408 			       		RSB_PERR_GOTO(err,"leaf node %d (of %d) is NULL !?\n",smi,mtxAp->all_leaf_matrices_n);
409 				}
410 
411 				if( rsb__is_root_matrix(submatrix) )
412 				{
413 			       		RSB_PERR_GOTO(err,"leaf node %d (of %d) has root flag in flags 0x%x=%d !?\n",smi,mtxAp->all_leaf_matrices_n,submatrix->flags,submatrix->flags);
414 				}
415 
416 				if( submatrix->nnz > 0 && submatrix->VA == NULL )
417 				{
418 			       		RSB_PERR_GOTO(err,"leaf node %d (of %d) has %d nonzeroes and VA=NULL !?\n",smi,mtxAp->all_leaf_matrices_n,submatrix->nnz);
419 				}
420 
421 				if( rsb__is_recursive_matrix(submatrix->flags) )
422 				{
423 			       		RSB_PERR_GOTO(err,"leaf node %d (of %d) has quad-partitioning flag in flags 0x%x=%d !?\n",smi,mtxAp->all_leaf_matrices_n,submatrix->flags,submatrix->flags);
424 				}
425 
426 				if( submatrix->all_leaf_matrices != NULL )
427 				{
428 			       		RSB_PERR_GOTO(err,"leaf node %d (of %d) has a non-NULL submatrices pointer !?\n",smi,mtxAp->all_leaf_matrices_n);
429 				}
430 
431 				if( submatrix->all_leaf_matrices_n > 0 )
432 				{
433 			       		RSB_PERR_GOTO(err,"leaf node %d (of %d) has a submatrices count of %d !?\n",smi,mtxAp->all_leaf_matrices_n,submatrix->all_leaf_matrices_n);
434 				}
435 			}
436 		}
437 
438 		RSB_SUBMATRIX_FOREACH(mtxAp,submatrix,i,j)
439 		if(submatrix)
440 		{
441 			if(
442 				(mtxAp->roff>submatrix->roff) || (mtxAp->coff>submatrix->coff) ||
443 				(mtxAp->nr<submatrix->nr) || (mtxAp->nc<submatrix->nc) ||
444 					0)
445 			{
446 			       	RSB_PERR_GOTO(err,RSB_ERRM_ES)
447 			}
448 
449 			if(!rsb__mtx_chk(submatrix))
450 			{
451 			       	RSB_PERR_GOTO(err,"submatrix at %d %d seems corrupted\n",submatrix->roff,submatrix->coff);
452 			}
453 		}
454 	}
455 	else
456 	{
457 		rsb_nnz_idx_t n;
458 
459 		if(!RSB_IS_MATRIX_STORAGE_ALLOWED_FOR_LEAF(mtxAp->matrix_storage))
460 		{
461 		       	RSB_PERR_GOTO(err,RSB_ERRM_ES)
462 	       	}
463 
464 		if(
465 					RSB_INVALID_COO_INDEX(mtxAp->roff) ||
466 					RSB_INVALID_COO_INDEX(mtxAp->coff) ||
467 					RSB_INVALID_COO_INDEX(mtxAp->nr) ||
468 					RSB_INVALID_COO_INDEX(mtxAp->nc) ||
469 					(mtxAp->roff>mtxAp->broff) ||
470 					(mtxAp->coff>mtxAp->bcoff) ||
471 					(mtxAp->nr<mtxAp->bm) ||
472 					(mtxAp->nc<mtxAp->bk) ||
473 					0
474 					)
475 		{
476 			RSB_PERR_GOTO(err,"submatrix bounds ([%d .. %d ... %d .. %d, %d .. %d ... %d .. %d]) are wrong!\n",
477 					mtxAp->roff,
478 					mtxAp->broff,
479 					mtxAp->bm,
480 					mtxAp->nr,
481 					mtxAp->coff,
482 					mtxAp->bcoff,
483 					mtxAp->bk,
484 					mtxAp->nc
485 					);
486 		}
487 
488 		if(RSB_DO_FLAG_HAS(mtxAp->flags,(RSB_FLAG_USE_HALFWORD_INDICES)))
489 		{
490 			if(rsb__is_coo_matrix(mtxAp))
491 			if( (!RSB_INDICES_FIT_IN_HALFWORD(mtxAp->nr,mtxAp->nc)) || 0)
492 			{
493 				RSB_PERR_GOTO(err,"coo submatrix bounds are wrong, given the halfword indices!\n");
494 			}
495 
496 			if(rsb__is_csr_matrix(mtxAp))
497 			if( (!RSB_INDEX_FIT_IN_HALFWORD(mtxAp->nc)) || 0)
498 			{
499 				RSB_PERR_GOTO(err,"csr submatrix bounds are wrong, given the halfword indices!\n");
500 			}
501 		}
502 
503 		if(rsb__is_coo_matrix(mtxAp))
504 		{
505 			const rsb_coo_idx_t mai = 0; /* minimal allowed index */ /* FIXME: if one-based, this shall be 1 ! */
506 
507 			if(RSB_DO_FLAG_HAS(mtxAp->flags,RSB_FLAG_USE_HALFWORD_INDICES))
508 			{
509 				RSB_DECLARE_CONST_HALFCOO_ARRAYS_FROM_MATRIX(IA,JA,mtxAp)
510 
511 				for(n=0;RSB_LIKELY(n<mtxAp->nnz);++n)
512 				{
513 					if( IA[n] < mai || JA[n] < mai )
514 					{
515 						RSB_PERR_GOTO(err,"negative halfword COO indices @%d: %d<%d || %d,%d!\n", n,IA[n],mai,JA[n],mai);
516 					}
517 
518 					if( IA[n]>=mtxAp->Mdim || JA[n]>=mtxAp->mdim )
519 					{
520 						RSB_PERR_GOTO(err,"bad halfword COO indices @%d: %d>=%d || %d>=%d!\n", n,IA[n],mtxAp->Mdim,JA[n],mtxAp->mdim);
521 					}
522 				}
523 
524 				if( rsb__util_is_halfword_coo_array_sorted_up_partial_order(IA,mtxAp->nnz) != RSB_BOOL_TRUE )
525 				{
526 					RSB_PERR_GOTO(err,"halfword COO input is not sorted! \n");
527 				}
528 				goto ok;
529 			}
530 			else
531 			{
532 				RSB_DECLARE_CONST_FULLCOO_ARRAYS_FROM_MATRIX(IA,JA,mtxAp)
533 
534 				for(n=0;RSB_LIKELY(n<mtxAp->nnz);++n)
535 				{
536 					if( IA[n] < mai || JA[n] < mai )
537 					{
538 						RSB_PERR_GOTO(err,"negative fullword COO indices @%d: %d<%d || %d,%d!\n", n,IA[n],mai,JA[n],mai);
539 					}
540 
541 					if( IA[n]>=mtxAp->Mdim || JA[n]>=mtxAp->mdim )
542 					{
543 						RSB_PERR_GOTO(err,"bad fullword COO indices @%d: %d>=%d || %d>=%d!\n",
544 							n,IA[n],mtxAp->Mdim,JA[n],mtxAp->mdim);
545 					}
546 				}
547 
548 				if( rsb__util_is_nnz_array_sorted_up_partial_order(IA,mtxAp->nnz) != RSB_BOOL_TRUE )
549 				{
550 					RSB_PERR_GOTO(err,"fullword COO input is not sorted! \n");
551 				}
552 
553 				goto ok;
554 			}
555 		}
556 
557 		if(RSB_DO_FLAG_HAS(mtxAp->flags,(RSB_FLAG_WANT_COO_STORAGE))
558 		    && !RSB_DO_FLAG_HAS(mtxAp->flags,(RSB_FLAG_USE_HALFWORD_INDICES)))
559 			;
560 		//	goto ok;//{RSB_PERR_GOTO(err,"full word COO is not allowed on a leaf matrix!\n");}
561 		//
562 		if(RSB_DO_FLAG_HAS(mtxAp->flags,RSB_FLAG_WANT_COO_STORAGE))
563 		{
564 			if(RSB_DO_FLAG_HAS(mtxAp->flags,(RSB_FLAG_USE_HALFWORD_INDICES_COO)))
565 			{
566 			}
567 			else
568 			{
569 				// FIXME: I am not sure whether this code is ever executed.
570 				RSB_DECLARE_CONST_FULLCOO_ARRAYS_FROM_MATRIX(IA,JA,mtxAp)
571 				for(n=0;RSB_LIKELY(n<mtxAp->nnz);++n)
572 				{
573 					if( IA[n]>=mtxAp->Mdim || JA[n]>=mtxAp->mdim )
574 					{
575 						RSB_PERR_GOTO(err,"bad fullword COO indices @%d: %d>=%d || %d>=%d!\n",
576 							n,IA[n],mtxAp->Mdim,JA[n],mtxAp->mdim);
577 					}
578 				}
579 			}
580 			goto ok;
581 		}
582 		else
583 				;/* ok */
584 #if 0
585 //		if(RSB_DO_FLAG_HAS(mtxAp->flags,(RSB_FLAG_USE_HALFWORD_INDICES_CSR))
586 //		    && RSB_DO_FLAG_HAS(mtxAp->flags,(RSB_FLAG_USE_HALFWORD_INDICES_COO)))
587 //				{RSB_PERR_GOTO(err,"both halfword COO and halfword CSR is not allowed on a leaf matrix!\n");}
588 //		else
589 //				;/* ok */
590 #endif
591 
592 		if(!rsb__is_csr_matrix(mtxAp))
593 		{
594 			RSB_PERR_GOTO(err,"not a csr matrix ?\n");
595 		}
596 		if(mtxAp->element_count != mtxAp->nnz)
597 		{
598 			RSB_PERR_GOTO(err,RSB_ERRM_EM);
599 		}
600 		if(mtxAp->element_count != mtxAp->block_count)
601 		{
602 			RSB_PERR_GOTO(err,RSB_ERRM_EM);
603 		}
604 		if(!mtxAp->bpntr)
605 		{
606 			RSB_PERR_GOTO(err,"!bpntr!\n");
607 		}
608 		if(!mtxAp->bindx)
609 		{
610 			RSB_PERR_GOTO(err,"!bindx!\n");
611 		}
612 		if(mtxAp->bpntr[0]!=0)
613 		{
614 			RSB_PERR_GOTO(err,"bpntr[0]!=0!\n");
615 		}
616 		if(RSB_DO_FLAG_HAS(mtxAp->flags,RSB_FLAG_WANT_COO_STORAGE))
617 		{
618 			if(!RSB_DO_FLAG_HAS(mtxAp->flags,(RSB_FLAG_USE_HALFWORD_INDICES)))
619 			{
620 				if(RSB_SOME_ERROR( rsb__util_is_sorted_coo_as_row_major(mtxAp->VA,mtxAp->bpntr,mtxAp->bindx,mtxAp->nnz,mtxAp->typecode,NULL,mtxAp->flags)) )
621 				{
622 					RSB_PERR_GOTO(err,"COO matrix seems unsorted!\n");
623 				}
624 			}
625 			else
626 			{
627 				/* FIXME: missing */
628 			}
629 		}
630 		else
631 		{
632 			if(mtxAp->bpntr[mtxAp->Mdim]!=mtxAp->nnz)
633 			{
634 				RSB_PERR_GOTO(err,"%d=bpntr[Mdim]!=nnz=%d\n",(int)mtxAp->bpntr[mtxAp->Mdim],(int)mtxAp->nnz);
635 			}
636 			if(!rsb__util_is_nnz_array_sorted_up_partial_order(mtxAp->bpntr,mtxAp->Mdim+1))
637 			{
638 				RSB_PERR_GOTO(err,"bpntr seems unsorted!\n");
639 			}
640 		}
641 
642 		if(RSB_DO_FLAG_HAS(mtxAp->flags,RSB_FLAG_USE_CSR_RESERVED))
643 			for(n=0;RSB_LIKELY(n<mtxAp->Mdim);++n)
644 			if( RSB_UNLIKELY( mtxAp->bpntr[n+1] - mtxAp->bpntr[n] > mtxAp->mdim ) )
645 			{
646 				RSB_ERROR("invalid CSR pointer:  mtxAp->bpntr[%d+1] - mtxAp->bpntr[%d] > mtxAp->mdim: %d - %d > %d !\n",n,n,mtxAp->bpntr[n+1],mtxAp->bpntr[n],mtxAp->mdim);
647 				RSB_PERR_GOTO(err,"!\n");
648 			}
649 
650 
651 		if(RSB_DO_FLAG_HAS(mtxAp->flags,(RSB_FLAG_USE_HALFWORD_INDICES_COO)))
652 		{
653 			/* FIXME: write me */
654 		}
655 		else
656 		if(RSB_DO_FLAG_HAS(mtxAp->flags,(RSB_FLAG_USE_HALFWORD_INDICES_CSR)))
657 		{
658 			for(n=0;RSB_LIKELY(n<mtxAp->Mdim);++n)
659 			if(!rsb__util_is_halfword_coo_array_sorted_up(
660 						((rsb_half_idx_t*)mtxAp->bindx)+mtxAp->bpntr[n],mtxAp->bpntr[n+1]-mtxAp->bpntr[n]))
661 			{
662 				RSB_PERR_GOTO(err,"(halfword) bindx seems unsorted!\n");
663 			}
664 
665 
666 
667 	//		for(n=0;RSB_LIKELY(n<mtxAp->Mdim);++n)
668 	//		{
669 	//			rsb_nnz_idx_t i;
670 	//			for(i=mtxAp->bpntr[n];i<mtxAp->bpntr[n+1];++i)
671 	//				RSB_STDOUT("at %d %d\n",1+n,1+((rsb_half_idx_t*)(mtxAp->bindx))[i]);
672 	//		}
673 		}
674 		else
675 		{
676 			if(RSB_SOME_ERROR(rsb__csr_chk(mtxAp->bpntr,mtxAp->bindx,mtxAp->Mdim,mtxAp->mdim,mtxAp->nnz,0)))
677 			{
678 				RSB_PERR_GOTO(err,"CSR submatrix seems corrupt!\n");
679 			}
680 		}
681 	}
682 ok:
683 	return RSB_BOOL_TRUE;
684 err:
685 #if 1
686 	RSB_ERROR("bad submatrix: "),RSB_ERROR_MATRIX_SUMMARY(mtxAp),RSB_ERROR(RSB_ERRM_NL);
687 #endif
688 	return RSB_BOOL_FALSE;
689 }
690 
rsb__do_is_matrix_binary_loaded(const struct rsb_mtx_t * mtxAp)691 rsb_bool_t rsb__do_is_matrix_binary_loaded(const struct rsb_mtx_t * mtxAp)
692 {
693 	rsb_bool_t is_bio; // binary I/O matrix
694 	if(!mtxAp)
695 		return RSB_BOOL_FALSE;
696 #if 0
697 	struct rsb_mtx_t *fsm = rsb__do_get_first_submatrix(mtxAp);
698 	is_bio=!((long)mtxAp<((long)fsm->bpntr) || (long)(mtxAp)>=((long)fsm->bpntr+mtxAp->nnz));
699 #else
700 	is_bio = RSB_DO_FLAG_HAS(mtxAp->flags,RSB_FLAG_FIX_FOR_BINARY_LOADED_MATRIX);
701 #endif
702 	return is_bio;
703 }
704 
705 
706 /* @endcond */
707