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 *
28 * Implementation of the interface functions.
29 * \internal
30 *
31 * */
32 /* TODO: introduce RSB_MSG_BADARGS_ERROR(ERRVAL,MSG,BAN) */
33 #include "rsb_common.h"
34 #include "rsb_util.h"
35 #include "rsb.h"
36 #include "rsb_unroll.h"
37 #ifdef RSB_HAVE_SYS_UTSNAME_H
38 #include <sys/utsname.h> /* uname */
39 #endif /* RSB_HAVE_SYS_UTSNAME_H */
40 #include "rsb_do.h"
41 extern struct rsb_session_handle_t rsb_global_session_handle;
42
43 RSB_INTERNALS_COMMON_HEAD_DECLS
44
rsb_do_prec_build(struct rsb_mtx_t ** mtxLpp,struct rsb_mtx_t ** mtxUpp,const struct rsb_mtx_t * mtxAp)45 rsb_err_t rsb_do_prec_build(struct rsb_mtx_t ** mtxLpp, struct rsb_mtx_t ** mtxUpp, const struct rsb_mtx_t * mtxAp)
46 {
47 /*
48 * FIXME: UNFINISHED, UNTESTED
49 * */
50 rsb_err_t errval = RSB_ERR_NO_ERROR;
51 struct rsb_mtx_t *L=NULL,*U=NULL;
52 struct rsb_coo_matrix_t csr,lcoo,ucoo;
53 rsb_flags_t flags = RSB_FLAG_DEFAULT_MATRIX_FLAGS;
54
55 csr.VA=NULL; csr.IA=NULL; csr.JA=NULL;
56 if(!mtxLpp)
57 goto err;
58 if(!mtxUpp)
59 goto err;
60 if(!mtxAp)
61 goto err;
62 if(mtxAp->nr != mtxAp->nc)
63 goto err;
64 csr.nr=mtxAp->nr;
65 csr.nc=mtxAp->nc;
66 csr.nnz = RSB_MAX(mtxAp->nnz,RSB_MAX(csr.nr,csr.nc)+1);
67 csr.typecode=mtxAp->typecode;
68 ucoo=csr; lcoo=csr;
69 if(rsb__allocate_coo_matrix_t(&csr)!=&csr)
70 {
71 errval = RSB_ERR_ENOMEM;
72 RSB_PERR_GOTO(err,RSB_ERRM_ES);
73 }
74 csr.nnz=mtxAp->nnz;
75 /* a reasonably efficient routine would: */
76 /* build a fullword CSR clone (using a RSB-to-CSR constructor) */
77 /* perform ILU on the CSR struct */
78 /* build RSB clones for the L and U CSR parts (using a modified CSR-to-RSB constructor, eventually building them together, in one shot) */
79 /* FIXME: TODO */
80 /* a reasonable quick hack routine would: */
81 /* build a fullword CSR clone (using a RSB-to-CSR constructor) */
82 if((errval = rsb__do_get_csr(mtxAp->typecode,mtxAp,csr.VA,csr.IA,csr.JA,RSB_FLAG_DEFAULT_CSR_MATRIX_FLAGS))!=RSB_ERR_NO_ERROR)
83 goto err;
84 /* perform ILU on the CSR struct */
85 if((errval = rsb__prec_csr_ilu0(&csr))!=RSB_ERR_NO_ERROR)
86 goto err;
87 /* perform CSR to COO conversion */
88 rsb__do_count_tri_in_csr(&csr,&lcoo.nnz,&ucoo.nnz);
89
90 ucoo.nnz=RSB_MAX(ucoo.nnz,ucoo.nr+1);
91 if(rsb__allocate_coo_matrix_t(&ucoo)!=&ucoo) { errval = RSB_ERR_ENOMEM; goto err; }
92
93 lcoo.nnz=RSB_MAX(lcoo.nnz,lcoo.nr+1);
94
95 if(rsb__allocate_coo_matrix_t(&lcoo)!=&lcoo) { errval = RSB_ERR_ENOMEM; goto err; }
96 rsb__do_count_tri_in_csr(&csr,&lcoo.nnz,&ucoo.nnz);
97
98 rsb__do_copy_tri_from_csr_to_coo(&csr,&lcoo,&ucoo);
99
100 /* allocating L and U */
101 L = rsb__do_mtx_alloc_from_coo_const(lcoo.VA,lcoo.IA,lcoo.JA,lcoo.nnz,lcoo.typecode,lcoo.nr,lcoo.nc,RSB_DEFAULT_ROW_BLOCKING,RSB_DEFAULT_COL_BLOCKING,flags|RSB_FLAG_LOWER_TRIANGULAR,&errval);
102 if(!L)
103 {
104 rsb__destroy_coo_matrix_t(&lcoo);
105 RSB_BZERO_P(&lcoo);
106 goto err;
107 }
108 U = rsb__do_mtx_alloc_from_coo_const(ucoo.VA,ucoo.IA,ucoo.JA,ucoo.nnz,ucoo.typecode,ucoo.nr,ucoo.nc,RSB_DEFAULT_ROW_BLOCKING,RSB_DEFAULT_COL_BLOCKING,flags|RSB_FLAG_UPPER_TRIANGULAR,&errval);
109 if(!U)
110 {
111 rsb__destroy_coo_matrix_t(&ucoo);
112 RSB_BZERO_P(&ucoo);
113 goto err;
114 }
115 /*RSB_ERROR(RSB_ERRM_WUF);*/
116
117 *mtxLpp=L;
118 *mtxUpp=U;
119 rsb__destroy_coo_matrix_t(&csr);
120 rsb__destroy_coo_matrix_t(&lcoo); rsb__destroy_coo_matrix_t(&ucoo);
121
122 return errval;
123 err:
124 rsb__destroy_coo_matrix_t(&lcoo); rsb__destroy_coo_matrix_t(&ucoo);
125 rsb__destroy_coo_matrix_t(&csr);
126 rsb__do_perror(NULL,errval);
127 RSB_MTX_FREE(L);
128 RSB_MTX_FREE(U);
129 errval = RSB_ERR_BADARGS;
130 return errval;
131 }
132
rsb__do_get_preconditioner(void * opd,const struct rsb_mtx_t * mtxAp,rsb_precf_t prec_flags,const void * ipd)133 rsb_err_t rsb__do_get_preconditioner(void *opd, const struct rsb_mtx_t * mtxAp, rsb_precf_t prec_flags, const void *ipd)/* FIXME: temporary interface */
134 {
135 // FIXME: UNFINISHED, UNTESTED
136 rsb_err_t errval = RSB_ERR_GENERIC_ERROR;
137 struct rsb_mtx_t * LU[2]={NULL,NULL};
138
139 if(!opd || !mtxAp)
140 {
141 RSB_PERR_GOTO(err,RSB_ERRM_ES);
142 }
143 errval = rsb_do_prec_build(&LU[0],&LU[1],mtxAp);
144 rsb__memcpy(opd,LU,sizeof(LU));
145 err:
146 return errval;
147 }
148 #if 0
149 rsb_err_t rsb_do_prec_apply(const struct rsb_prec_t * precp, const void *r)
150 {
151 /*
152 * given the preconditioner P, computes \f$ r \leftarrow {P}^{-1} r.\f$
153 * \f$ r' = {P}^{-1} r \f$
154 * \f$ r' = {L \cdot U}^{-1} r \f$
155 * \f$ r' = {U}^{-1} {L}^{-1} r \f$
156 * \f$ r' = ({U}^{-1} ({L}^{-1} r)) \f$
157 * */
158 //rsb__debug_print_vector(r,precp->L->nr,precp->L->typecode,1);
159 double one=1.0;
160 rsb_err_t errval = RSB_ERR_NO_ERROR;
161 RSB_DO_ERROR_CUMULATE(errval,rsb__do_spsv(RSB_TRANSPOSITION_N,&one,precp->L,r,1,r,1));
162 if(RSB_SOME_ERROR(errval))
163 goto err;
164 RSB_DO_ERROR_CUMULATE(errval,rsb__do_spsv(RSB_TRANSPOSITION_N,&one,precp->U,r,1,r,1));
165 if(RSB_SOME_ERROR(errval))
166 goto err;
167
168 //rsb__debug_print_vector(r,precp->L->nr,precp->L->typecode,1);
169 err:
170 if(RSB_SOME_ERROR(errval))
171 rsb__do_perror(NULL,errval);
172 return errval;
173 }
174 #endif
175
rsb__do_get_rows_sparse(rsb_trans_t transA,const void * alphap,const struct rsb_mtx_t * mtxAp,void * VA,rsb_coo_idx_t * IA,rsb_coo_idx_t * JA,rsb_coo_idx_t frA,rsb_coo_idx_t lrA,rsb_nnz_idx_t * rnzp,rsb_flags_t flags)176 rsb_err_t rsb__do_get_rows_sparse(rsb_trans_t transA, const void * alphap, const struct rsb_mtx_t * mtxAp, void* VA, rsb_coo_idx_t * IA, rsb_coo_idx_t * JA, rsb_coo_idx_t frA, rsb_coo_idx_t lrA, rsb_nnz_idx_t *rnzp, rsb_flags_t flags)
177 {
178 /* TODO: having a return scaled rows would be an efficient feature. */
179 rsb_err_t errval = RSB_ERR_NO_ERROR;
180 rsb_coo_idx_t off = 0;
181
182 #if RSB_ALLOW_ZERO_DIM
183 if(RSB_ANY_MTX_DIM_ZERO(mtxAp))
184 {
185 goto err; /* FIXME: skipping checks on ldB, ldC, op_flags*/
186 }
187 #endif
188
189 if(VA == NULL && JA == NULL && IA == NULL && rnzp != NULL)
190 {
191 *rnzp = rsb__dodo_get_rows_nnz(mtxAp, frA, lrA,flags,&errval);
192 goto err;
193 }
194
195 if(!mtxAp)
196 {
197 errval = RSB_ERR_BADARGS;
198 RSB_PERR_GOTO(err,RSB_ERRM_E_MTXAP);
199 }
200
201 if(!rnzp)
202 {
203 errval = RSB_ERR_BADARGS;
204 RSB_PERR_GOTO(err,"user did not supply a results nonzeroes pointer\n");
205 }
206
207 if(RSB_DO_FLAG_HAS(flags,RSB_FLAG_FORTRAN_INDICES_INTERFACE))
208 {
209 off=1;
210 lrA--;
211 frA--;
212 RSB_DO_FLAG_DEL(flags,RSB_FLAG_FORTRAN_INDICES_INTERFACE);
213 }
214
215 if(frA<0 || lrA>mtxAp->nr)
216 {
217 errval = RSB_ERR_BADARGS;
218 RSB_PERR_GOTO(err,RSB_ERRM_EM);
219 }
220
221 if(!VA)
222 {
223 errval = RSB_ERR_BADARGS;
224 RSB_PERR_GOTO(err,RSB_ERRM_NULL_VA);
225 }
226
227 if(frA>lrA)
228 {
229 errval = RSB_ERR_BADARGS;
230 RSB_PERR_GOTO(err,RSB_ERRM_EM);
231 }
232
233 if(RSB_DOES_TRANSPOSE(transA))
234 RSB_SWAP(rsb_coo_idx_t*,IA,JA);
235
236 *rnzp=0;
237 #if 0
238 errval = rsb__do_get_rows_sparse_rec(mtxAp,VA,frA,lrA,IA,JA,rnzp,off,off);
239 if(flags & RSB_FLAG_SORT_INPUT)
240 errval = rsb__util_sort_row_major_inner(VA,IA,JA,*rnzp,mtxAp->nr+off,mtxAp->nc+off,mtxAp->typecode,flags|RSB_FLAG_EXPERIMENTAL_IN_PLACE_CSR);
241 #if 0
242 if( flags & RSB_FLAG_FORTRAN_INDICES_INTERFACE )
243 rsb__util_nnz_array_to_fortran_indices(IA,*rnzp),
244 rsb__util_nnz_array_to_fortran_indices(JA,*rnzp);
245 #endif
246 #else
247 #if 1
248 {
249 rsb_coo_idx_t i;
250 for(i=frA;i<=lrA;++i)
251 RSB_DO_ERROR_CUMULATE(errval,rsb__do_get_rows_sparse_rec(mtxAp,VA,i,i,IA,JA,rnzp,off,off));
252 }
253 #else
254 {
255 /* this is too slow for many leaf matrices */
256 rsb_submatrix_idx_t si;
257 rsb_coo_idx_t i;
258 for(i=frA;i<=lrA;++i)
259 for(si=0;si<mtxAp->all_leaf_matrices_n;++si)
260 RSB_DO_ERROR_CUMULATE(errval,rsb__do_get_rows_sparse_rec(mtxAp->all_leaf_matrices[si].mtxlp,VA,i,i,IA,JA,rnzp,off,off));
261 }
262 #endif
263 #endif
264 RSB_DEBUG_ASSERT(rsb__dodo_get_rows_nnz(mtxAp,frA,lrA,flags,NULL)==*rnzp);
265 if(RSB_DOES_TRANSPOSE(transA))
266 {
267 RSB_SWAP(rsb_coo_idx_t*,IA,JA);
268 /* swapping back and ready for sorting. if now, would get column major. */
269 if(RSB_SOME_ERROR(errval = rsb__util_sort_row_major_inner(VA,IA,JA,*rnzp,mtxAp->nr,mtxAp->nc,mtxAp->typecode,flags)))
270 {
271 RSB_PERR_GOTO(err,RSB_ERRM_EM);
272 }
273 }
274
275 if(RSB_DOES_CONJUGATE(transA))
276 {
277 RSB_DO_ERROR_CUMULATE(errval,rsb__util_do_conjugate(VA,mtxAp->typecode,*rnzp));
278 }
279
280 if(alphap)
281 {
282 RSB_DO_ERROR_CUMULATE(errval,rsb__cblas_Xscal(mtxAp->typecode,*rnzp,alphap,VA,1));
283 }
284 err:
285 if(RSB_SOME_ERROR(errval))
286 RSB_ERROR(RSB_ERRM_NL);
287 return errval;
288 }
289
rsb__do_scal(struct rsb_mtx_t * mtxAp,const void * d,rsb_trans_t trans)290 rsb_err_t rsb__do_scal(struct rsb_mtx_t * mtxAp, const void * d, rsb_trans_t trans)
291 {
292 /* TODO : what should be the semantics of scaling a symmetric matrix ? */
293 /* FIXME : and error handling ? **/
294 rsb_err_t errval = RSB_ERR_UNSUPPORTED_OPERATION;
295
296 #ifdef RSB_HAVE_OPTYPE_SCALE
297
298 #if RSB_ALLOW_ZERO_DIM
299 if(RSB_ANY_MTX_DIM_ZERO(mtxAp))
300 {
301 errval = RSB_ERR_NO_ERROR;
302 goto err; /* FIXME: skipping checks on ldB, ldC, op_flags*/
303 }
304 #endif
305
306 if(!mtxAp)
307 // return RSB_ERR_NO_ERROR;
308 {
309 errval = RSB_ERR_BADARGS;
310 RSB_PERR_GOTO(err,RSB_ERRM_EM);
311 }
312
313 if( rsb__is_recursive_matrix(mtxAp->flags))
314 {
315 rsb_submatrix_idx_t i,j;
316 struct rsb_mtx_t * submatrix=NULL;
317
318 RSB_SUBMATRIX_FOREACH(mtxAp,submatrix,i,j)
319 if(submatrix)
320 {
321 rsb_coo_idx_t off;
322 if(RSB_DOES_NOT_TRANSPOSE(trans))
323 off=submatrix->roff-mtxAp->roff;
324 else
325 off=submatrix->coff-mtxAp->coff;
326
327 rsb__do_scal(submatrix,((rsb_byte_t*)d)+mtxAp->el_size*off,trans);
328 }
329 //return RSB_ERR_NO_ERROR;
330 {
331 errval = RSB_ERR_NO_ERROR;
332 goto err;
333 }
334 }
335 else
336 errval = rsb__do_scale(mtxAp,trans,d);
337 #else /* RSB_HAVE_OPTYPE_SCALE */
338 #endif /* RSB_HAVE_OPTYPE_SCALE */
339 err:
340 return errval;
341 }
342
rsb__dodo_getdiag(const struct rsb_mtx_t * mtxAp,void * diagonal)343 rsb_err_t rsb__dodo_getdiag( const struct rsb_mtx_t * mtxAp, void * diagonal )
344 {
345 // FIXME : missing documentation and error checks!
346 rsb_err_t errval = RSB_ERR_NO_ERROR;
347
348 if(!mtxAp)
349 {
350 errval = RSB_ERR_BADARGS;
351 RSB_PERR_GOTO(err,RSB_ERRM_E_MTXAP);
352 }
353 if(!RSB_BLOCK_CROSSED_BY_DIAGONAL(0,0,mtxAp->nr,mtxAp->nc))
354 {
355 errval = RSB_ERR_BADARGS;
356 goto err;
357 }
358
359 if(1)
360 //if( mtxAp->flags & RSB_FLAG_USE_HALFWORD_INDICES_COO )
361 {
362 // FIXME: THIS IS SLOW, TEMPORARY
363 rsb_coo_idx_t i;
364 long nt = rsb_get_num_threads();
365 const int gdc = RSB_DIVIDE_IN_CHUNKS(mtxAp->nr,nt);
366 #pragma omp parallel for schedule(static,gdc) reduction(|:errval) RSB_NTC
367 for(i=0;i<mtxAp->nr;++i)
368 RSB_DO_ERROR_CUMULATE(errval,rsb__do_get_coo_element(mtxAp,((rsb_char_t*)diagonal)+mtxAp->el_size*(i),i,i));
369 errval = RSB_ERR_NO_ERROR;
370 }
371 #if 0
372 else
373 {
374 RSB_BZERO(diagonal,mtxAp->el_size*RSB_MTX_DIAG_SIZE(mtxAp));
375 errval = rsb_do_getdiag(mtxAp,diagonal);
376 }
377 #endif
378 err:
379 return errval;
380 }
381
rsb_do_elemental_scale(struct rsb_mtx_t * mtxAp,const void * alphap)382 static rsb_err_t rsb_do_elemental_scale(struct rsb_mtx_t * mtxAp, const void * alphap)
383 {
384 /*!
385 \ingroup rsb_doc_matrix_handling
386
387 Computes \f$ A \leftarrow \alpha A \f$.
388
389 \param \rsb_mtxt_inp_param_msg
390 \param \rsb_alpha_inp_param_msg
391 \return \rsberrcodemsg
392 */
393 rsb_err_t errval = RSB_ERR_NO_ERROR;
394 struct rsb_mtx_t * submatrix=NULL;
395
396 if(!mtxAp)
397 {
398 errval = RSB_ERR_BADARGS;
399 goto err;
400 }
401 #if RSB_WANT_PARALLEL_ELEMENTAL_OPS
402 if(1)
403 errval = rsb__do_elemental_scale_parallel(mtxAp,alphap);
404 #else /* RSB_WANT_PARALLEL_ELEMENTAL_OPS */
405 if(rsb__is_recursive_matrix(mtxAp->flags))
406 {
407 rsb_submatrix_idx_t smi;
408 //#pragma omp parallel for schedule(static,1) reduction(|:errval) shared(mtxAp) RSB_NTC
409 RSB_SUBMATRIX_FOREACH_LEAF(mtxAp,submatrix,smi)
410 RSB_DO_ERROR_CUMULATE(errval,rsb__cblas_Xscal(submatrix->typecode,submatrix->nnz,alphap,submatrix->VA,1));
411 }
412 #endif /* RSB_WANT_PARALLEL_ELEMENTAL_OPS */
413 else
414 RSB_DO_ERROR_CUMULATE(errval,rsb__cblas_Xscal(mtxAp->typecode,mtxAp->nnz,alphap,mtxAp->VA,1));
415 err:
416 return errval;
417 }
418
rsb_do_elemental_scale_inv(struct rsb_mtx_t * mtxAp,const void * alphap)419 static rsb_err_t rsb_do_elemental_scale_inv(struct rsb_mtx_t * mtxAp, const void * alphap)
420 {
421 /*!
422 \ingroup rsb_doc_matrix_handling
423
424 Computes \f$ A \leftarrow \frac{1}{\alpha} A \f$.
425
426 \param \rsb_mtxt_inp_param_msg
427 \param \rsb_alpha_inp_param_msg
428 \return \rsberrcodemsg
429 */
430 rsb_err_t errval = RSB_ERR_NO_ERROR;
431 struct rsb_mtx_t * submatrix=NULL;
432
433 if(!mtxAp)
434 {
435 errval = RSB_ERR_BADARGS;
436 goto err;
437 }
438
439 if(rsb__is_recursive_matrix(mtxAp->flags))
440 {
441 rsb_submatrix_idx_t smi;
442 //#pragma omp parallel for schedule(static,1) reduction(|:errval) shared(mtxAp) RSB_NTC
443 RSB_SUBMATRIX_FOREACH_LEAF(mtxAp,submatrix,smi)
444 RSB_DO_ERROR_CUMULATE(errval,rsb__vector_scale_inv(submatrix->VA,alphap,submatrix->typecode,submatrix->nnz));
445 }
446 else
447 RSB_DO_ERROR_CUMULATE(errval,rsb__vector_scale_inv(mtxAp->VA,alphap,mtxAp->typecode,mtxAp->nnz));
448 err:
449 return errval;
450 }
451
rsb_do_elemental_pow(struct rsb_mtx_t * mtxAp,const void * alphap)452 static rsb_err_t rsb_do_elemental_pow(struct rsb_mtx_t * mtxAp, const void * alphap)
453 {
454 /*!
455 \ingroup rsb_doc_matrix_handling
456
457 Raises each matrix element to the given power.
458
459 \param \rsb_mtxt_inp_param_msg
460 \param \rsb_alpha_inp_param_msg
461 \return \rsberrcodemsg
462 */
463 rsb_err_t errval = RSB_ERR_NO_ERROR;
464 struct rsb_mtx_t * submatrix=NULL;
465
466 if(!mtxAp)
467 {
468 errval = RSB_ERR_BADARGS;
469 goto err;
470 }
471 if(rsb__is_recursive_matrix(mtxAp->flags))
472 {
473 rsb_submatrix_idx_t smi;
474 //#pragma omp parallel for schedule(static,1) reduction(|:errval) shared(mtxAp) RSB_NTC
475 RSB_SUBMATRIX_FOREACH_LEAF(mtxAp,submatrix,smi)
476 RSB_DO_ERROR_CUMULATE(errval,rsb__util_vector_pow(submatrix->VA,submatrix->typecode,alphap,submatrix->nnz));
477 }
478 else
479 RSB_DO_ERROR_CUMULATE(errval,rsb__util_vector_pow(mtxAp->VA,mtxAp->typecode,alphap,mtxAp->nnz));
480 err:
481 return errval;
482 }
483
rsb_dodo_negation(struct rsb_mtx_t * mtxAp)484 static rsb_err_t rsb_dodo_negation(struct rsb_mtx_t * mtxAp)
485 {
486 #ifdef RSB_HAVE_OPTYPE_NEGATION
487 rsb_err_t errval = RSB_ERR_NO_ERROR;
488
489 if(!mtxAp)
490 {errval = RSB_ERR_BADARGS;goto err;}
491
492 if(rsb__is_recursive_matrix(mtxAp->flags))
493 {
494 rsb_submatrix_idx_t i,j;
495 struct rsb_mtx_t * submatrix=NULL;
496
497 RSB_SUBMATRIX_FOREACH(mtxAp,submatrix,i,j)
498 if(submatrix)
499 RSB_DO_ERROR_CUMULATE(errval,rsb_dodo_negation(submatrix));
500 }
501 else
502 errval = rsb_do_negation(mtxAp,0xf1c57415,RSB_DEFAULT_TRANSPOSITION);
503 #else /* RSB_HAVE_OPTYPE_NEGATION */
504 /* FIXME : eliminate negation as mop ! */
505 // return RSB_ERR_UNSUPPORTED_OPERATION;
506 rsb_err_t errval = RSB_ERR_NO_ERROR;
507 if(!mtxAp)
508 {errval = RSB_ERR_BADARGS;goto err;}
509
510 if(rsb__is_recursive_matrix(mtxAp->flags))
511 {
512 rsb_submatrix_idx_t i,j;
513 struct rsb_mtx_t * submatrix=NULL;
514
515 RSB_SUBMATRIX_FOREACH(mtxAp,submatrix,i,j)
516 if(submatrix)
517 RSB_DO_ERROR_CUMULATE(errval,rsb_dodo_negation(submatrix));
518 }
519 else
520 /* FIXME : assuming elements are contiguous ! */
521 errval = rsb__util_do_negate(mtxAp->VA,mtxAp->typecode,mtxAp->element_count);
522 #endif /* RSB_HAVE_OPTYPE_NEGATION */
523 err:
524 return errval;
525 }
526
rsb__do_elemental_unop(struct rsb_mtx_t * mtxAp,enum rsb_elopf_t elop_flags)527 rsb_err_t rsb__do_elemental_unop(struct rsb_mtx_t * mtxAp, enum rsb_elopf_t elop_flags)
528 {
529 // FIXME: untested
530 rsb_err_t errval = RSB_ERR_NO_ERROR;
531
532 if(!mtxAp) {errval = RSB_ERR_BADARGS; goto err;}
533 switch(elop_flags)
534 {
535 case(RSB_ELOPF_NEG):
536 errval = rsb_dodo_negation(mtxAp);
537 break;
538 //#define RSB_ELOPF_SQRT 0x00000010 /*!< Elemental square root (usable with rsb_mtx_elemental_unop). */
539 /*
540 case(RSB_ELOPF_SQRT):
541 errval=....(mtxAp);
542 break;
543 */
544 /* case(RSB_ELOPF_TRANS):
545 errval = rsb_transpose(&mtxAp);
546 break;
547 case(RSB_ELOPF_HTRANS):
548 errval = rsb_htranspose(&mtxAp);
549 break;*/
550 default:
551 {errval = RSB_ERR_BADARGS; goto err;}
552 }
553 err:
554 return errval;
555 }
556
rsb__do_elemental_binop(struct rsb_mtx_t * mtxAp,enum rsb_elopf_t elop_flags,const void * opp)557 rsb_err_t rsb__do_elemental_binop(struct rsb_mtx_t * mtxAp, enum rsb_elopf_t elop_flags, const void * opp)
558 {
559 // FIXME: untested
560 rsb_err_t errval = RSB_ERR_NO_ERROR;
561 rsb_trans_t transA = RSB_TRANSPOSITION_N;
562 void * topp=NULL;
563
564 if(!mtxAp) {errval = RSB_ERR_BADARGS; goto err;}
565 if(!opp) {errval = RSB_ERR_BADARGS; goto err;}
566
567 switch(elop_flags)
568 {
569 case(RSB_ELOPF_SCALE_COLS_REAL):
570 case(RSB_ELOPF_SCALE_COLS):
571 transA = RSB_TRANSPOSITION_T;
572 break;
573 default: RSB_NULL_STATEMENT_FOR_COMPILER_HAPPINESS;
574 }
575
576 switch(elop_flags)
577 {
578 case(RSB_ELOPF_SCALE_COLS_REAL):
579 case(RSB_ELOPF_SCALE_ROWS_REAL):
580 if( RSB_IS_MATRIX_TYPE_COMPLEX(mtxAp->typecode) )
581 {
582 /* FIXME: this is inefficient */
583 rsb_type_t typecode = RSB_NUMERICAL_TYPE_REAL_TYPE(mtxAp->typecode);
584 if( NULL == (topp = rsb__calloc_vector(mtxAp->nr,mtxAp->typecode)) )
585 {
586 errval = RSB_ERR_ENOMEM;
587 goto err;
588 }
589 errval = rsb__cblas_Xcopy(typecode,mtxAp->nr,opp,1,topp,2);
590 }
591 case(RSB_ELOPF_SCALE_COLS):
592 case(RSB_ELOPF_SCALE_ROWS):
593 errval = rsb__do_scal(mtxAp,topp?topp:opp,transA);
594 break;
595 case(RSB_ELOPF_MUL):
596 errval = rsb_do_elemental_scale(mtxAp,opp);
597 break;
598 case(RSB_ELOPF_DIV):
599 errval = rsb_do_elemental_scale_inv(mtxAp,opp);
600 break;
601 case(RSB_ELOPF_POW):
602 errval = rsb_do_elemental_pow(mtxAp,opp);
603 break;
604 default:
605 {
606 errval = RSB_ERR_BADARGS;
607 goto err;
608 }
609 }
610 err:
611 RSB_CONDITIONAL_FREE(topp);
612 return errval;
613 }
614
rsb__dodo_get_rows_nnz(const struct rsb_mtx_t * mtxAp,rsb_blk_idx_t fr,rsb_blk_idx_t lr,rsb_flags_t flags,rsb_err_t * errvalp)615 rsb_nnz_idx_t rsb__dodo_get_rows_nnz(const struct rsb_mtx_t *mtxAp, rsb_blk_idx_t fr, rsb_blk_idx_t lr, rsb_flags_t flags, rsb_err_t * errvalp)
616 {
617 rsb_err_t errval = RSB_ERR_NO_ERROR;
618 rsb_nnz_idx_t rnz = 0;
619
620 RSB_DEBUG_ASSERT(fr <= lr);
621
622 if(RSB_DO_FLAG_HAS(flags,RSB_FLAG_FORTRAN_INDICES_INTERFACE))
623 lr--,fr--;
624 errval = rsb_do_get_rows_nnz(mtxAp,fr,lr,&rnz);
625 RSB_CONDITIONAL_ERRPSET(errvalp,errval);
626 if(RSB_SOME_ERROR(errval))
627 rnz=0;
628 return rnz;
629 }
630
631 #if RSB_WANT_PARALLEL_ELEMENTAL_OPS
632 rsb_err_t rsb__do_elemental_scale_parallel(struct rsb_mtx_t * mtxAp, const void * alphap);
633 {
634 /**
635 \ingroup gr_internals
636 TODO: move to somewhere else
637 */
638 rsb_err_t errval = RSB_ERR_NO_ERROR;
639 const rsb_thread_t wet = rsb_get_num_threads();
640
641 if(RSB_UNLIKELY(mtxAp->nnz<wet*RSB_MIN_THREAD_MEMCPY_NNZ))
642 {
643 RSB_DO_ERROR_CUMULATE(errval,rsb__cblas_Xscal(mtxAp->typecode,mtxAp->nnz,alphap,((rsb_byte_t*)mtxAp->VA),1));
644 }
645 else
646 {
647 rsb_nnz_idx_t wi;
648 size_t cnz=(mtxAp->nnz+wet-1)/wet; /* chunk size */
649 #pragma omp parallel for schedule(static,1) RSB_NTC
650 for(wi=0;wi<wet;++wi)
651 {
652 size_t coff=wi*cnz;
653 size_t cnnz=(wi<wet-1)?cnz:mtxAp->nnz-((wet-1)*cnz);
654 printf("%d nz on %d\n",cnnz,wi);
655 RSB_DO_ERROR_CUMULATE(errval,rsb__cblas_Xscal(mtxAp->typecode,cnnz,alphap,((rsb_byte_t*)mtxAp->VA)+RSB_SIZEOF(mtxAp->typecode)*mtxAp->coff,1));
656 }
657 }
658 }
659 #endif /* RSB_WANT_PARALLEL_ELEMENTAL_OPS */
660
rsb__do_matrix_add_to_dense(const void * alphap,const struct rsb_mtx_t * mtxAp,rsb_nnz_idx_t ldB,rsb_nnz_idx_t nr,rsb_nnz_idx_t nc,rsb_bool_t rowmajor,void * Bp)661 rsb_err_t rsb__do_matrix_add_to_dense(const void *alphap, const struct rsb_mtx_t * mtxAp, rsb_nnz_idx_t ldB, rsb_nnz_idx_t nr, rsb_nnz_idx_t nc, rsb_bool_t rowmajor, void * Bp)
662 {
663 // FIXME: could this be documented in two groups (mops and unfinished) at the same time ?
664 // TODO: what about supporting transA ?
665 rsb_err_t errval = RSB_ERR_NO_ERROR;
666 struct rsb_mtx_t * submatrix = NULL;
667 rsb_aligned_t pone[RSB_CONST_ENOUGH_ALIGNED_FOR_ANY_TYPE];
668
669 if(!mtxAp)
670 {
671 errval = RSB_ERR_BADARGS;
672 goto err;
673 }
674
675 if(!alphap)
676 {
677 rsb__util_set_area_to_converted_integer(&pone[0],mtxAp->typecode,+1);
678 alphap = &pone[0];
679 }
680
681 if(rsb__is_recursive_matrix(mtxAp->flags))
682 {
683 rsb_submatrix_idx_t smi;
684 //#pragma omp parallel for schedule(static,1) reduction(|:errval) shared(mtxAp) RSB_NTC
685 RSB_SUBMATRIX_FOREACH_LEAF(mtxAp,submatrix,smi)
686 RSB_DO_ERROR_CUMULATE(errval,rsb__do_add_submatrix_to_dense(submatrix,alphap,Bp,ldB,nr,nc,rowmajor));
687 }
688 else
689 RSB_DO_ERROR_CUMULATE(errval,rsb__do_add_submatrix_to_dense(mtxAp,alphap,Bp,ldB,nr,nc,rowmajor));
690 err:
691 return errval;
692 }
693
rsb__do_switch_rsb_mtx_to_csr_sorted(struct rsb_mtx_t * mtxAp,void ** VAP,rsb_coo_idx_t ** IAP,rsb_coo_idx_t ** JAP,rsb_flags_t flags)694 rsb_err_t rsb__do_switch_rsb_mtx_to_csr_sorted(struct rsb_mtx_t * mtxAp, void ** VAP, rsb_coo_idx_t ** IAP, rsb_coo_idx_t ** JAP, rsb_flags_t flags)
695 {
696 rsb_err_t errval = RSB_ERR_NO_ERROR;
697 struct rsb_coo_matrix_t coo;
698 const rsb_nnz_idx_t nnz=mtxAp?mtxAp->nnz:0;
699 const rsb_coo_idx_t m=mtxAp?mtxAp->nr:0;
700 //const rsb_coo_idx_t k=mtxAp?mtxAp->nc:0;
701 const rsb_flags_t mflags=mtxAp?mtxAp->flags:RSB_FLAG_NOFLAGS;
702
703 if(!mtxAp)
704 {
705 errval = RSB_ERR_BADARGS;
706 goto err;
707 }
708
709 if(!RSB_DO_FLAG_HAS(mtxAp->flags,RSB_FLAG_EXTERNALLY_ALLOCATED_ARRAYS))
710 {
711 errval = RSB_ERR_BADARGS;
712 goto err;
713 }
714
715 if(!IAP || !JAP || !VAP)
716 {
717 errval = RSB_ERR_BADARGS;
718 RSB_PERR_GOTO(err,RSB_ERRM_E_VIJP);
719 }
720 errval = rsb__do_switch_recursive_in_place_matrix_to_in_place_coo_sorted(mtxAp,&coo);
721 if(RSB_SOME_ERROR(errval))
722 goto err;
723 errval = rsb__util_compress_to_row_pointers_array(NULL,nnz,m,mflags,flags,coo.IA);
724 if(RSB_SOME_ERROR(errval))
725 goto err;
726 if(RSB_DO_FLAG_HAS(flags,RSB_FLAG_FORTRAN_INDICES_INTERFACE))
727 rsb__util_nnz_array_to_fortran_indices(coo.JA,nnz);
728 *JAP=coo.JA;
729 *IAP=coo.IA;
730 *VAP=coo.VA;
731 err:
732 return errval;
733 }
734
rsb__do_get_csr(rsb_type_t typecode,const struct rsb_mtx_t * mtxAp,rsb_byte_t * VA,rsb_nnz_idx_t * RP,rsb_coo_idx_t * JA,rsb_flags_t flags)735 rsb_err_t rsb__do_get_csr(rsb_type_t typecode, const struct rsb_mtx_t *mtxAp, rsb_byte_t * VA, rsb_nnz_idx_t * RP, rsb_coo_idx_t * JA, rsb_flags_t flags)
736 {
737 /* NOTE this writes more than mtxAp->nnz elements! */
738 rsb_err_t errval = RSB_ERR_NO_ERROR;
739
740 if(!mtxAp)
741 {
742 errval = RSB_ERR_BADARGS;
743 RSB_PERR_GOTO(err,RSB_ERRM_ES);
744 }
745
746 #define RSB_WANT_OLD_TO_CSR_SEMANTICS 0
747
748 if((mtxAp->typecode != typecode && typecode != RSB_NUMERICAL_TYPE_SAME_TYPE) || (mtxAp->flags != flags))/* FIXME: condition on cflags is unnecessarily restrictive */
749 {
750 const rsb_flags_t flagsC = flags | (mtxAp->flags & RSB_FLAG_ALL_STRUCTURAL_FLAGS);
751 struct rsb_mtx_t * mtxCp = NULL;
752 errval = rsb__mtx_clone(&mtxCp, typecode, RSB_TRANSPOSITION_N, NULL, mtxAp, flagsC );
753 if(RSB_SOME_ERROR(errval))
754 RSB_PERR_GOTO(err,RSB_ERRM_ES);
755 errval = rsb__dodo_get_csr(mtxCp,&VA,&RP,&JA);
756 RSB_MTX_FREE(mtxCp);
757 }
758 else
759 errval = rsb__dodo_get_csr(mtxAp,&VA,&RP,&JA);
760
761 if(RSB_SOME_ERROR(errval))
762 {
763 RSB_PERR_GOTO(err,RSB_ERRM_ES);
764 }
765 //#if RSB_WANT_OLD_TO_CSR_SEMANTICS
766 /* FIXME: shall move C -> Fortran indices semantics to rsb__dodo_get_csr */
767 if(flags & RSB_FLAG_FORTRAN_INDICES_INTERFACE)
768 rsb__util_nnz_array_to_fortran_indices(RP,mtxAp->nr+1),
769 rsb__util_nnz_array_to_fortran_indices(JA,mtxAp->nnz);
770 //#endif
771 err:
772 return errval;
773 }
774
rsb__do_get_matrix_info(const struct rsb_mtx_t * mtxAp,enum rsb_mif_t miflags,void * info,size_t buflen)775 rsb_err_t rsb__do_get_matrix_info(const struct rsb_mtx_t *mtxAp, enum rsb_mif_t miflags, void* info, size_t buflen)
776 {
777 /*!
778 \ingroup FIXME
779 \warning \rsb_warn_unfinished_msg
780 FIXME: UNFINISHED, UNTESTED
781 */
782 rsb_err_t errval = RSB_ERR_NO_ERROR;
783 rsb_real_t rrv=0;
784 size_t szv=0;
785 rsb_coo_idx_t civ=0;
786 rsb_nnz_idx_t niv=0;
787 rsb_flags_t fiv=0;
788 rsb_type_t tiv=0;
789 rsb_blk_idx_t biv=0;
790 char*cis=(char*)info;
791
792 if(!mtxAp || !info)
793 {
794 errval = RSB_ERR_BADARGS;
795 goto err;
796 }
797 switch(miflags)
798 {
799 case RSB_MIF_INDEX_STORAGE_IN_BYTES__TO__SIZE_T:
800 {
801 szv = rsb__get_index_storage_amount(mtxAp);
802 if(buflen<=0) *(size_t*)info = szv;
803 else snprintf(cis,buflen,"%zd",szv);
804 }
805 break;
806 case RSB_MIF_INDEX_STORAGE_IN_BYTES_PER_NNZ__TO__RSB_REAL_T:
807 {
808 const size_t isa = rsb__get_index_storage_amount(mtxAp);
809 if ( mtxAp->nnz > 0 )
810 rrv = ((rsb_real_t)isa) / ((rsb_real_t)mtxAp->nnz);
811 else
812 rrv = 2 * sizeof(rsb_coo_idx_t);
813 if(buflen<=0)
814 *(rsb_real_t*) info=rrv;
815 else
816 snprintf(cis,buflen,"%lg",rrv);
817 }
818 break;
819 case RSB_MIF_MATRIX_ROWS__TO__RSB_COO_INDEX_T:
820 {
821 civ = (mtxAp->nr);
822 if(buflen<=0) *(rsb_coo_idx_t*)info = civ;
823 else snprintf(cis,buflen,"%d",civ);
824 }
825 break;
826 case RSB_MIF_MATRIX_COLS__TO__RSB_COO_INDEX_T:
827 {
828 civ = (mtxAp->nc);
829 if(buflen<=0) *(rsb_coo_idx_t*)info = civ;
830 else snprintf(cis,buflen,"%d",civ);
831 }
832 break;
833 case RSB_MIF_MATRIX_NNZ__TO__RSB_NNZ_INDEX_T:
834 {
835 niv = (mtxAp->nnz);
836 if(buflen<=0) *(rsb_nnz_idx_t*)info = niv;
837 else snprintf(cis,buflen,"%d",niv);
838 }
839 break;
840 case RSB_MIF_TOTAL_SIZE__TO__SIZE_T:
841 {
842 szv = rsb__get_sizeof(mtxAp);
843 if(buflen<=0) *(size_t*)info = szv;
844 else snprintf(cis,buflen,"%zd",szv);
845 }
846 break;
847 case RSB_MIF_MATRIX_FLAGS__TO__RSB_FLAGS_T:
848 {
849 fiv = (mtxAp->flags);
850 if(buflen<=0) *(rsb_flags_t*)info = fiv;
851 else snprintf(cis,buflen,"%d",fiv);
852 }
853 break;
854 case RSB_MIF_MATRIX_TYPECODE__TO__RSB_TYPE_T:
855 {
856 tiv = (mtxAp->typecode);
857 if(buflen<=0) *(rsb_type_t*)info = tiv;
858 else snprintf(cis,buflen,"%d",tiv);
859 }
860 break;
861 case RSB_MIF_MATRIX_INFO__TO__CHAR_P:
862 {
863 tiv = (mtxAp->typecode);
864 if(buflen<=0) { errval = RSB_ERR_BADARGS; goto err; }
865 else snprintf(cis,buflen,RSB_PRINTF_MTX_SUMMARY_ARGS(mtxAp));
866
867 }
868 break;
869 case RSB_MIF_LEAVES_COUNT__TO__RSB_BLK_INDEX_T:
870 {
871 biv = (mtxAp->all_leaf_matrices_n);
872 if(buflen<=0) *(rsb_blk_idx_t*)info = biv;
873 else snprintf(cis,buflen,"%d",biv);
874 }
875 break;
876 default:
877 errval = RSB_ERR_GENERIC_ERROR;
878 }
879 err:
880 return errval;
881 }
882
rsb__do_check_leak(void)883 rsb_err_t rsb__do_check_leak(void)
884 {
885 /*!
886 \ingroup rsb_doc_library
887
888 Called after \ref rsb_lib_exit(), will report on the standard output stream
889 (see #RSB_IO_WANT_OUTPUT_STREAM) whether some previously allocated
890 memory area was not freed by librsb.
891 \n
892 Will report leak information only if built with the #RSB_DISABLE_ALLOCATOR_WRAPPER symbol undefined.
893 \n
894 Will return #RSB_ERR_NO_ERROR on no leak; an error otherwise.
895 \n
896
897 \warning \rsb_warn_soon_to_be_deprecated_msg
898 \return \rsberrcodemsg
899 */
900 rsb_err_t errval = RSB_ERR_NO_ERROR;
901
902 if(rsb__get_g_rsb_memory_count())
903 {
904 RSB_INFO("WARNING: allocated memory : %zu : POSSIBLE MEMORY LEAK\n",rsb__get_g_rsb_memory_count());
905 RSB_DO_ERROR_CUMULATE(errval,RSB_ERR_INTERNAL_ERROR);
906 }
907
908 if(rsb__get_g_rsb_allocations_count())
909 {
910 RSB_INFO("WARNING: allocations count : %zu : POSSIBLE MEMORY LEAK\n",rsb__get_g_rsb_allocations_count());
911 RSB_DO_ERROR_CUMULATE(errval,RSB_ERR_INTERNAL_ERROR);
912 }
913 return errval;
914 }
915
rsb__do_matrix_norm(const struct rsb_mtx_t * mtxAp,void * np,enum rsb_extff_t flags)916 rsb_err_t rsb__do_matrix_norm(const struct rsb_mtx_t * mtxAp , void * np, enum rsb_extff_t flags)
917 {
918 rsb_err_t errval = RSB_ERR_BADARGS;
919
920 switch(flags)
921 {
922 case RSB_EXTF_NORM_ONE:
923 errval = rsb__do_infinity_norm(mtxAp,np,RSB_BOOL_FALSE,RSB_TRANSPOSITION_T);
924 break;
925 case RSB_EXTF_NORM_TWO:/* FIXME: UNTESTED ! */
926 errval = rsb__cblas_Xnrm2(mtxAp->typecode,mtxAp->nnz,rsb__do_get_first_submatrix(mtxAp)->VA,1,np);
927 break;
928 case RSB_EXTF_NORM_INF:
929 errval = rsb__do_infinity_norm(mtxAp,np,RSB_BOOL_FALSE,RSB_TRANSPOSITION_N);
930 break;
931 default:
932 break;
933 }
934 return errval;
935 }
936
rsb__do_matrix_compute(const struct rsb_mtx_t * mtxAp,void * dp,enum rsb_extff_t flags)937 rsb_err_t rsb__do_matrix_compute(const struct rsb_mtx_t * mtxAp , void * dp, enum rsb_extff_t flags)
938 {
939 rsb_err_t errval = RSB_ERR_BADARGS;
940
941 #if RSB_ALLOW_ZERO_DIM
942 if(RSB_ANY_MTX_DIM_ZERO(mtxAp))
943 {
944 errval = RSB_ERR_NO_ERROR;
945 goto ret; /* FIXME: skipping further error checks */
946 }
947 #endif
948
949 if( mtxAp == NULL || ( mtxAp->nnz > 0 && dp == NULL ) )
950 goto ret;
951
952 switch(flags)
953 {
954 case RSB_EXTF_SUMS_ROW:
955 errval = rsb__do_rows_sums_inner(mtxAp,dp,RSB_BOOL_FALSE,RSB_TRANSPOSITION_N);
956 break;
957 case RSB_EXTF_SUMS_COL:
958 errval = rsb__do_rows_sums_inner(mtxAp,dp,RSB_BOOL_FALSE,RSB_TRANSPOSITION_T);
959 break;
960 case RSB_EXTF_ASUMS_ROW:
961 errval = rsb__do_absolute_rows_sums( mtxAp , dp);
962 break;
963 case RSB_EXTF_ASUMS_COL:
964 errval = rsb__do_absolute_columns_sums(mtxAp,dp);
965 break;
966 case RSB_EXTF_DIAG:
967 errval = rsb__dodo_getdiag(mtxAp,dp);
968 break;
969 default:
970 break;
971 }
972 ret:
973 return errval;
974 }
975
rsb__do_load_vector_file_as_matrix_market(const rsb_char_t * filename,rsb_type_t typecode,void * yp,rsb_coo_idx_t * yvlp)976 rsb_err_t rsb__do_load_vector_file_as_matrix_market(const rsb_char_t * filename, rsb_type_t typecode, void * yp, rsb_coo_idx_t *yvlp)
977 {
978 rsb_err_t errval = RSB_ERR_NO_ERROR;
979
980 if(!filename || ((!yvlp) && (!yp)))
981 {
982 errval = RSB_ERR_BADARGS;
983 RSB_PERR_GOTO(err,RSB_ERRM_EM);
984 }
985 if(yvlp)
986 {
987 /* FIXME: temporarily ignoring second dimension! */
988 rsb_coo_idx_t yvk=0, yvm=0;
989 rsb_bool_t is_vector = RSB_BOOL_FALSE;
990
991 if(RSB_SOME_ERROR(errval = rsb__util_mm_info_matrix_f(filename,&yvm,&yvk,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&is_vector)) )
992 {
993 RSB_PERR_GOTO(err,RSB_ERRM_EM);
994 }
995 *yvlp=yvm;
996 }
997 if(yp)
998 {
999 /* printf("stub: reading in %s...\n",filename); */
1000 rsb_nnz_idx_t vnz=0;
1001
1002 errval = rsb__util_mm_load_vector_f(filename,&yp,&vnz,typecode);
1003 }
1004 err:
1005 return errval;
1006 }
1007
rsb__dodo_load_matrix_file_as_matrix_market(const rsb_char_t * filename,rsb_flags_t flags,rsb_type_t typecode,rsb_err_t * errvalp)1008 struct rsb_mtx_t * rsb__dodo_load_matrix_file_as_matrix_market(const rsb_char_t * filename, rsb_flags_t flags, rsb_type_t typecode, rsb_err_t *errvalp)
1009 {
1010 // FIXME
1011 struct rsb_mtx_t * mtxAp = NULL;
1012 rsb_err_t errval = RSB_ERR_NO_ERROR;
1013
1014 errval = rsb__do_load_matrix_file_as_matrix_market(&mtxAp,filename,flags,typecode);
1015 RSB_CONDITIONAL_ERRPSET(errvalp,errval);
1016 return mtxAp;
1017 }
1018
rsb__do_was_initialized(void)1019 rsb_bool_t rsb__do_was_initialized(void)
1020 {
1021 /*!
1022 \ingroup rsb_doc_library
1023
1024 Call this function to know whether the library had already been initialized or not.
1025 \n
1026 This function is mainly intended to be used in between \ref rsb_lib_exit() and \ref rsb_lib_init() calls,
1027 or generally after one or more calls to \ref rsb_lib_init() were already been done.
1028 \n
1029 It is not meant to be called before the 'first' initialization ever, unless
1030 the user is sure this library was built on a system which supports default
1031 initialization to zero of static variables (which indeed is supported by most standards;
1032 e.g.: ANSI C: http://flash-gordon.me.uk/ansi.c.txt ).
1033
1034 \return #RSB_BOOL_TRUE if it was initialized, #RSB_BOOL_FALSE otherwise.
1035 */
1036 /* TODO: redocument elsewhere! redundant function! */
1037 return (rsb_global_session_handle.rsb_g_initialized == RSB_BOOL_TRUE) ? RSB_BOOL_TRUE : RSB_BOOL_FALSE;
1038 }
1039
rsb__do_switch_rsb_mtx_to_coo_unsorted(struct rsb_mtx_t * mtxAp,void ** VAP,rsb_coo_idx_t ** IAP,rsb_coo_idx_t ** JAP,rsb_flags_t flags)1040 static rsb_err_t rsb__do_switch_rsb_mtx_to_coo_unsorted(struct rsb_mtx_t * mtxAp, void ** VAP, rsb_coo_idx_t ** IAP, rsb_coo_idx_t ** JAP, rsb_flags_t flags)
1041 {
1042 struct rsb_coo_matrix_t coo;
1043 rsb_err_t errval = RSB_ERR_NO_ERROR;
1044
1045 RSB_ASSERT( RSB_DO_FLAG_HAS(mtxAp->flags, RSB_FLAG_EXTERNALLY_ALLOCATED_ARRAYS) );
1046
1047 if(!IAP || !JAP || !VAP)
1048 {
1049 errval = RSB_ERR_BADARGS;
1050 RSB_PERR_GOTO(err,RSB_ERRM_EM);
1051 }
1052
1053 errval = rsb__do_switch_recursive_in_place_matrix_to_in_place_coo_unsorted(mtxAp,&coo);
1054 if(RSB_DO_FLAG_HAS(flags,RSB_FLAG_FORTRAN_INDICES_INTERFACE))
1055 rsb__util_nnz_array_to_fortran_indices(coo.IA,coo.nnz),
1056 rsb__util_nnz_array_to_fortran_indices(coo.JA,coo.nnz);
1057 *JAP = coo.JA;
1058 *IAP = coo.IA;
1059 *VAP = coo.VA;
1060 err:
1061 return errval;
1062 }
1063
rsb__do_switch_rsb_mtx_to_coo_sorted(struct rsb_mtx_t * mtxAp,void ** VAP,rsb_coo_idx_t ** IAP,rsb_coo_idx_t ** JAP,rsb_flags_t flags)1064 static rsb_err_t rsb__do_switch_rsb_mtx_to_coo_sorted(struct rsb_mtx_t * mtxAp, void ** VAP, rsb_coo_idx_t ** IAP, rsb_coo_idx_t ** JAP, rsb_flags_t flags)
1065 {
1066 rsb_err_t errval = RSB_ERR_NO_ERROR;
1067 struct rsb_coo_matrix_t coo;
1068 const rsb_nnz_idx_t nnz = mtxAp ? mtxAp-> nnz:0;
1069
1070 RSB_ASSERT( RSB_DO_FLAG_HAS(mtxAp->flags, RSB_FLAG_EXTERNALLY_ALLOCATED_ARRAYS) );
1071
1072 if(!IAP || !JAP || !VAP)
1073 {
1074 errval = RSB_ERR_BADARGS;
1075 RSB_PERR_GOTO(err, RSB_ERRM_EM);
1076 }
1077
1078 RSB_BZERO_P(&coo);
1079 errval = rsb__do_switch_recursive_in_place_matrix_to_in_place_coo_sorted(mtxAp, &coo);
1080 if(RSB_SOME_ERROR(errval))
1081 {
1082 RSB_PERR_GOTO(err, RSB_ERRM_EM);
1083 }
1084 if(RSB_DO_FLAG_HAS(flags,RSB_FLAG_FORTRAN_INDICES_INTERFACE))
1085 rsb__util_nnz_array_to_fortran_indices(coo.IA, nnz),
1086 rsb__util_nnz_array_to_fortran_indices(coo.JA, nnz);
1087 *JAP = coo.JA;
1088 *IAP = coo.IA;
1089 *VAP = coo.VA;
1090 err:
1091 return errval;
1092 }
1093
rsb__do_switch_rsb_mtx_to_coo(struct rsb_mtx_t * mtxAp,void ** VAP,rsb_coo_idx_t ** IAP,rsb_coo_idx_t ** JAP,rsb_flags_t flags)1094 rsb_err_t rsb__do_switch_rsb_mtx_to_coo(struct rsb_mtx_t * mtxAp, void ** VAP, rsb_coo_idx_t ** IAP, rsb_coo_idx_t ** JAP, rsb_flags_t flags)
1095 {
1096 rsb_err_t errval = RSB_ERR_NO_ERROR;
1097
1098 if(!mtxAp)
1099 {
1100 errval = RSB_ERR_BADARGS;
1101 RSB_PERR_GOTO(err, RSB_ERRM_E_MTXAP"\n");
1102 }
1103
1104 /* Purpose of the following is avoidance of internally allocated memory leakage. */
1105 /* TODO: As an improvement, one may relax this constraint when the allocation wrapper is off. */
1106 if(!RSB_DO_FLAG_HAS(mtxAp->flags, RSB_FLAG_EXTERNALLY_ALLOCATED_ARRAYS))
1107 {
1108 errval = RSB_ERR_BADARGS;
1109 RSB_PERR_GOTO(err, RSB_ERRM_IMNIP);
1110 }
1111
1112 if(RSB_DO_FLAG_HAS(flags, RSB_FLAG_SORTED_INPUT))
1113 errval = rsb__do_switch_rsb_mtx_to_coo_sorted(mtxAp, VAP, IAP, JAP, flags);
1114 else
1115 errval = rsb__do_switch_rsb_mtx_to_coo_unsorted(mtxAp, VAP, IAP, JAP, flags);
1116 err:
1117 return errval;
1118 }
1119
1120 #if RSB_WANT_COO_BEGIN
rsb__do_mtx_alloc_from_coo_begin(rsb_nnz_idx_t nnzA,rsb_type_t typecode,rsb_coo_idx_t nrA,rsb_coo_idx_t ncA,rsb_flags_t flags,rsb_err_t * errvalp)1121 struct rsb_mtx_t * rsb__do_mtx_alloc_from_coo_begin(rsb_nnz_idx_t nnzA, rsb_type_t typecode, rsb_coo_idx_t nrA, rsb_coo_idx_t ncA, rsb_flags_t flags, rsb_err_t * errvalp)
1122 {
1123 rsb_err_t errval = RSB_ERR_NO_ERROR;
1124 struct rsb_mtx_t * mtxAp = NULL;
1125 blas_sparse_matrix bmtxA = RSB_BLAS_INVALID_VAL;
1126
1127 rsb__init_struct(mtxAp = rsb__calloc(sizeof(struct rsb_mtx_t)));
1128 if(!mtxAp)
1129 {
1130 errval = RSB_ERR_BADARGS;
1131 RSB_PERR_GOTO(err,RSB_ERRM_E_MTXAP"\n");
1132 }
1133 mtxAp->RSB_MTX_BMF = RSB_MTX_BMV;
1134 bmtxA = mtxAp->RSB_MTX_BDF = rsb__BLAS_Xuscr_begin(nrA,ncA,typecode);
1135 if( mtxAp->RSB_MTX_BDF == RSB_BLAS_INVALID_VAL )
1136 {
1137 errval = RSB_ERR_GENERIC_ERROR;
1138 RSB_CONDITIONAL_FREE(mtxAp);
1139 RSB_PERR_GOTO(err,RSB_ERRM_IPEWIEM);
1140 }
1141 /* FIXME : the following need an improvement */
1142 if(RSB_DO_FLAG_HAS(flags,RSB_FLAG_FORTRAN_INDICES_INTERFACE)) rsb__BLAS_ussp( bmtxA, blas_one_base);
1143 if(RSB_DO_FLAG_HAS(flags,RSB_FLAG_UNIT_DIAG_IMPLICIT)) rsb__BLAS_ussp( bmtxA, blas_unit_diag );
1144 if(RSB_DO_FLAG_HAS(flags,RSB_FLAG_LOWER_TRIANGULAR)) rsb__BLAS_ussp( bmtxA, blas_lower_triangular);
1145 if(RSB_DO_FLAG_HAS(flags,RSB_FLAG_UPPER_TRIANGULAR)) rsb__BLAS_ussp( bmtxA, blas_upper_triangular);
1146 if(RSB_DO_FLAG_HAS(flags,RSB_FLAG_LOWER_SYMMETRIC)) rsb__BLAS_ussp( bmtxA, blas_lower_symmetric);
1147 if(RSB_DO_FLAG_HAS(flags,RSB_FLAG_UPPER_SYMMETRIC)) rsb__BLAS_ussp( bmtxA, blas_upper_symmetric);
1148 if(RSB_DO_FLAG_HAS(flags,RSB_FLAG_LOWER_HERMITIAN)) rsb__BLAS_ussp( bmtxA, blas_lower_hermitian);
1149 if(RSB_DO_FLAG_HAS(flags,RSB_FLAG_UPPER_HERMITIAN)) rsb__BLAS_ussp( bmtxA, blas_upper_hermitian);
1150 err:
1151 RSB_CONDITIONAL_ERRPSET(errvalp,errval);
1152 return mtxAp;
1153 }
1154
rsb__do_mtx_alloc_from_coo_end(struct rsb_mtx_t ** mtxApp)1155 rsb_err_t rsb__do_mtx_alloc_from_coo_end(struct rsb_mtx_t ** mtxApp)
1156 {
1157 rsb_err_t errval = RSB_ERR_NO_ERROR;
1158 blas_sparse_matrix bmtxA = RSB_BLAS_INVALID_VAL;
1159 struct rsb_mtx_t * mtxBp = NULL;
1160 struct rsb_mtx_t * mtxAp = NULL;
1161
1162 if(!mtxApp || !*mtxApp)
1163 {
1164 errval = RSB_ERR_BADARGS;
1165 RSB_PERR_GOTO(err,RSB_ERRM_E_MTXAPP);
1166 }
1167
1168 mtxAp = *mtxApp ;
1169
1170 if( !RSB_MTX_HBDF( mtxAp ) )
1171 {
1172 /* errval = RSB_ERR_NO_ERROR; */
1173 errval = RSB_ERR_BADARGS;
1174 RSB_PERR_GOTO(err,RSB_ERRM_DNSAMIWAFCB);
1175 }
1176
1177 bmtxA = RSB_MTX_HBDFH(mtxAp);
1178 /* FIXME: missing serious check on mtxAp->flags ! */
1179 if( rsb__BLAS_Xuscr_end_flagged(bmtxA,NULL) == RSB_BLAS_INVALID_VAL )
1180 {
1181 errval = RSB_ERR_BADARGS;
1182 RSB_PERR_GOTO(err,RSB_ERRM_PFTM);
1183 /* FIXME: insufficient cleanup */
1184 }
1185 mtxBp = rsb__BLAS_inner_matrix_retrieve(bmtxA);
1186 *mtxApp = mtxBp;
1187 rsb__free(mtxAp);
1188 rsb__BLAS_handle_free(bmtxA); /* ignoring return value ... */
1189 err:
1190 return errval;
1191 }
1192 #endif /* RSB_WANT_COO_BEGIN */
1193
rsb__do_upd_vals(struct rsb_mtx_t * mtxAp,enum rsb_elopf_t elop_flags,const void * omegap)1194 rsb_err_t rsb__do_upd_vals(struct rsb_mtx_t * mtxAp, enum rsb_elopf_t elop_flags, const void * omegap)
1195 {
1196 rsb_err_t errval = RSB_ERR_NO_ERROR;
1197
1198 switch(elop_flags)
1199 {
1200 case(RSB_ELOPF_MUL):
1201 case(RSB_ELOPF_DIV):
1202 case(RSB_ELOPF_POW):
1203 case(RSB_ELOPF_SCALE_ROWS):
1204 case(RSB_ELOPF_SCALE_COLS):
1205 case(RSB_ELOPF_SCALE_ROWS_REAL):
1206 case(RSB_ELOPF_SCALE_COLS_REAL):
1207 RSB_DO_ERROR_CUMULATE(errval,rsb__do_elemental_binop(mtxAp,elop_flags,omegap));
1208 break;
1209 case(RSB_ELOPF_NEG):
1210 RSB_DO_ERROR_CUMULATE(errval,rsb__do_elemental_unop(mtxAp,elop_flags));
1211 break;
1212 default: {errval = RSB_ERR_BADARGS; goto err;}
1213 }
1214 err:
1215 return errval;
1216 }
1217
rsb__do_mtx_get_info(const struct rsb_mtx_t * mtxAp,enum rsb_mif_t miflags,void * minfop)1218 rsb_err_t rsb__do_mtx_get_info(const struct rsb_mtx_t *mtxAp, enum rsb_mif_t miflags, void* minfop)
1219 {
1220 rsb_err_t errval = RSB_ERR_UNIMPLEMENTED_YET;
1221 errval = rsb__do_get_matrix_info(mtxAp,miflags,minfop,0);
1222 return errval;
1223 }
1224
rsb__do_file_mtx_save(const struct rsb_mtx_t * mtxAp,const rsb_char_t * filename)1225 rsb_err_t rsb__do_file_mtx_save(const struct rsb_mtx_t * mtxAp, const rsb_char_t * filename)
1226 {
1227 rsb_err_t errval = RSB_ERR_NO_ERROR;
1228 errval = rsb__do_print_matrix_stats(mtxAp,RSB_CONST_DUMP_MATRIX_MARKET,filename);
1229 return errval;
1230 }
1231
rsb__do_vec_save(const rsb_char_t * filename,rsb_type_t typecode,const void * Yp,rsb_coo_idx_t yvl)1232 rsb_err_t rsb__do_vec_save(const rsb_char_t * filename, rsb_type_t typecode, const void * Yp, rsb_coo_idx_t yvl)
1233 {
1234 rsb_err_t errval = RSB_ERR_NO_ERROR;
1235 FILE*stream = NULL;
1236 const int incX = 1;
1237
1238 if(filename == NULL)
1239 stream = stdout;
1240 else
1241 stream = fopen(filename,"w");
1242
1243 errval = rsb__debug_print_vector_extra(Yp,yvl,typecode,incX,0x1,stream);
1244
1245 if(filename == NULL)
1246 ;
1247 else
1248 fclose(stream);
1249
1250 return errval;
1251 }
1252
rsb__do_mtx_alloc_from_csr_inplace(void * VA,rsb_coo_idx_t * RP,rsb_coo_idx_t * JA,rsb_nnz_idx_t nnzA,rsb_type_t typecode,rsb_coo_idx_t nrA,rsb_coo_idx_t ncA,rsb_blk_idx_t brA,rsb_blk_idx_t bcA,rsb_flags_t flagsA,rsb_err_t * errvalp)1253 struct rsb_mtx_t * rsb__do_mtx_alloc_from_csr_inplace (void *VA, rsb_coo_idx_t * RP, rsb_coo_idx_t * JA, rsb_nnz_idx_t nnzA, rsb_type_t typecode, rsb_coo_idx_t nrA, rsb_coo_idx_t ncA, rsb_blk_idx_t brA, rsb_blk_idx_t bcA, rsb_flags_t flagsA, rsb_err_t * errvalp )
1254 {
1255 struct rsb_mtx_t * mtxAp = NULL;
1256 rsb_err_t errval = RSB_ERR_NO_ERROR;
1257
1258 #if RSB_ALLOW_EMPTY_MATRICES
1259 if( nnzA > 0 )
1260 #endif /* RSB_ALLOW_EMPTY_MATRICES */
1261 errval = rsb__util_uncompress_row_pointers_array(RP,nrA,flagsA,flagsA,RP);
1262
1263 if(RSB_SOME_ERROR(errval))
1264 RSB_CONDITIONAL_ERRPSET(errvalp,errval);
1265 if( RSB_DO_FLAG_HAS(flagsA,RSB_FLAG_FORTRAN_INDICES_INTERFACE))
1266 rsb__util_coo_array_sub(RP,nnzA,1),
1267 rsb__util_coo_array_sub(JA,nnzA,1),
1268 RSB_DO_FLAG_DEL(flagsA,RSB_FLAG_FORTRAN_INDICES_INTERFACE);
1269 RSB_DO_FLAG_ADD(flagsA,RSB_FLAG_SORTED_INPUT);
1270 if(errval == RSB_ERR_NO_ERROR)
1271 mtxAp = rsb__do_mtx_alloc_from_coo_inplace(VA,RP,JA,nnzA,typecode,nrA,ncA,brA,bcA,flagsA,&errval);
1272 return mtxAp;
1273 }
1274
rsb__do_file_mtx_rndr(void * pmp,const char * filename,rsb_coo_idx_t pmlWidth,rsb_coo_idx_t pmWidth,rsb_coo_idx_t pmHeight,rsb_marf_t rflags)1275 rsb_err_t rsb__do_file_mtx_rndr(void * pmp, const char * filename, rsb_coo_idx_t pmlWidth, rsb_coo_idx_t pmWidth, rsb_coo_idx_t pmHeight, rsb_marf_t rflags)
1276 {
1277 rsb_err_t errval = RSB_ERR_NO_ERROR;
1278
1279 if( pmlWidth != pmHeight )
1280 {
1281 errval = RSB_ERR_BADARGS;
1282 goto err;
1283 }
1284
1285 switch(rflags)
1286 {
1287 case(RSB_MARF_RGB):
1288 RSB_DO_ERROR_CUMULATE(errval,rsb__do_get_pixmap_RGB_from_matrix(filename,pmp,pmWidth,pmHeight));
1289 break;
1290 case(RSB_MARF_EPS):
1291 // rsb_dump_postscript_from_mtx_t(fd,mtxAp,1,1,pmWidth,pmHeight,0);
1292 // RSB_DO_ERROR_CUMULATE(errval,rsb__dump_postscript_from_matrix(filename,1,1,pmWidth,pmHeight,0));
1293 RSB_DO_ERROR_CUMULATE(errval,RSB_ERR_UNIMPLEMENTED_YET);
1294 //RSB_DO_ERROR_CUMULATE(errval,rsb__dump_postscript_recursion_from_matrix(filename,1,1,pmWidth,pmHeight,RSB_FLAG_NOFLAGS,1,1,0,RSB_NUMERICAL_TYPE_DEFAULT));
1295 break;
1296 default: {errval = RSB_ERR_UNIMPLEMENTED_YET; goto err;}
1297 }
1298 err:
1299 return errval;
1300 }
1301
1302
1303 /* @endcond */
1304