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