rsb.h(3)

✨ NAME ✨

okay so welcome to rsb.h(3) bestie πŸ’– this is the page that tells you what librsb is all about β€” specifically the rsb.h library interface (and lowkey the optional rsb.hpp and rsb.F90 ones too πŸ‘€).

So yeah β€” librsb β€” rsb.h β€” The librsb library interface (rsb.h, optional ones rsb.hpp and rsb.F90). That's the vibe. 🫢


🌸 DESCRIPTION 🌸

k so here's the tea β˜• β€” the reference documentation of the rsb library shows up in two whole formats: HTML and Unix man pages. pick your fighter, both are valid πŸ’…

The following sections/man pages are available, and yes you're gonna wanna collect them all like they're shiny Pokémon ✨:

  • The librsb library interface (rsb.h, optional ones rsb.hpp and rsb.F90)
  • The Sparse BLAS interface to librsb (blas_sparse.h, rsb_blas_sparse.F90)
  • Example programs and code

that's the whole menu fr fr πŸ“ consider this your little index of everything librsb, and there is so much more coming, so stick around πŸ‘‘

  • #define RSB_SIZEOF(TYPE) β€” the one macro in the building, and it does exactly the thing the name says: hands you the size of a TYPE. That's it, that's the whole macros section, she's tiny but she's got range. πŸŽ€

🌸 Enumerations 🌸

okay so this is the enum corner of the house, and there's a LOT going on here, so let's go one at a time. no skipping, bestie, every single value matters. πŸ’…

the library-option enum

enum rsb_opt_t {
    RSB_IO_WANT_VERBOSE_INIT =0x000001,
    RSB_IO_WANT_VERBOSE_EXIT =0x000002,
    RSB_IO_WANT_OUTPUT_STREAM =0x000003,
    RSB_IO_WANT_SORT_METHOD =0x000004,
    RSB_IO_WANT_CACHE_BLOCKING_METHOD =0x000005,
    RSB_IO_WANT_SUBDIVISION_MULTIPLIER =0x000006,
    RSB_IO_WANT_VERBOSE_ERRORS =0x000007,
    RSB_IO_WANT_BOUNDED_BOX_COMPUTATION =0x000008,
    RSB_IO_WANT_EXECUTING_THREADS =0x000009,
    RSB_IO_WANT_EXTRA_VERBOSE_INTERFACE =0x000010,
    RSB_IO_WANT_MEMORY_HIERARCHY_INFO_STRING =0x000011,
    RSB_IO_WANT_IS_INITIALIZED_MARKER =0x000012,
    RSB_IO_WANT_MEM_ALLOC_CNT =0x000013,
    RSB_IO_WANT_MEM_ALLOC_TOT =0x000014,
    RSB_IO_WANT_LEAF_LEVEL_MULTIVEC =0x000015,
    RSB_IO_WANT_MAX_MEMORY_ALLOCATIONS =0x000016,
    RSB_IO_WANT_MAX_MEMORY_ALLOCATED =0x000017,
    RSB_IO_WANT_LIBRSB_ETIME =0x000018,
    RSB_IO_WANT_VERBOSE_TUNING =0x000019
}

These are the library option values that the _lib_init_funcs crew works with. nineteen of them, all hex, all iconic. ✨

the extraction filter enum

enum rsb_extff_t {
    RSB_EXTF_NORM_ONE =0x00001001,
    RSB_EXTF_NORM_TWO =0x00001002,
    RSB_EXTF_NORM_INF =0x00001003,
    RSB_EXTF_SUMS_ROW =0x00001004,
    RSB_EXTF_SUMS_COL =0x00001005,
    RSB_EXTF_ASUMS_ROW =0x00001006,
    RSB_EXTF_ASUMS_COL =0x00001007,
    RSB_EXTF_DIAG =0x00000004
}

Extraction filter flags, and you use these cuties with rsb_mtx_get_nrm() / rsb_mtx_get_vec(). (and yes, RSB_EXTF_DIAG really is 0x00000004, not 0x00001008 β€” she's built different, don't question her πŸ’€)

the matrix-info-flag enum

enum rsb_mif_t {
    RSB_MIF_INDEX_STORAGE_IN_BYTES__TO__SIZE_T =0x00000001,
    RSB_MIF_INDEX_STORAGE_IN_BYTES_PER_NNZ__TO__RSB_REAL_T =0x00000002,
    RSB_MIF_MATRIX_ROWS__TO__RSB_COO_INDEX_T =0x00000004,
    RSB_MIF_MATRIX_COLS__TO__RSB_COO_INDEX_T =0x00000008,
    RSB_MIF_MATRIX_NNZ__TO__RSB_NNZ_INDEX_T =0x00000010,
    RSB_MIF_TOTAL_SIZE__TO__SIZE_T =0x00000020,
    RSB_MIF_MATRIX_FLAGS__TO__RSB_FLAGS_T =0x00000040,
    RSB_MIF_MATRIX_TYPECODE__TO__RSB_TYPE_T =0x00000080,
    RSB_MIF_MATRIX_INFO__TO__CHAR_P =0x00000100,
    RSB_MIF_LEAVES_COUNT__TO__RSB_BLK_INDEX_T =0x00000200
}

Flags for getting matrix information via rsb_mtx_get_info() / rsb_mtx_get_info_str(). the double-underscore names are genuinely that long, and honestly? they ate. 🫢

the elemental-operation enum

enum rsb_elopf_t {
    RSB_ELOPF_MUL =0x00000001,
    RSB_ELOPF_DIV =0x00000002,
    RSB_ELOPF_POW =0x00000004,
    RSB_ELOPF_NEG =0x00000008,
    RSB_ELOPF_SCALE_ROWS =0x00000010,
    RSB_ELOPF_SCALE_COLS =0x00000020,
    RSB_ELOPF_SCALE_ROWS_REAL =0x00000040,
    RSB_ELOPF_SCALE_COLS_REAL =0x00000080
}

Flags for specifying a particular elemental/row-wise operation</flag> with rsb_mtx_upd_vals(). that's the whooooole roster, no cuts. πŸ’–


πŸ’œ Functions πŸ’œ

and now. the moment. THE function list. this is long, we're gonna take it in little groups so nobody gets overwhelmed, but literally every single prototype is here, in order, nothing skipped. periodt. πŸ”₯

the lib-config crew

rsb_err_t rsb_lib_init (struct rsb_initopts *iop)
rsb_err_t rsb_lib_set_opt (enum rsb_opt_t iof, const void *iop)
rsb_err_t rsb_lib_get_opt (enum rsb_opt_t iof, void *iop)
rsb_err_t rsb_lib_set_opt_str (const rsb_char_t *opnp, const rsb_char_t *opvp)
rsb_err_t rsb_lib_reinit (struct rsb_initopts *iop)
rsb_err_t rsb_lib_exit (struct rsb_initopts *iop)

the COO-matrix construction besties

struct rsb_mtx_t * rsb_mtx_alloc_from_coo_const (const void *VA, const rsb_coo_idx_t *IA, const 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)
struct rsb_mtx_t * rsb_mtx_alloc_from_coo_inplace (void *VA, rsb_coo_idx_t *IA, 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)
struct rsb_mtx_t * rsb_mtx_free (struct rsb_mtx_t *mtxAp)

the copy & multiply girlies

rsb_err_t rsb_mtx_clone (struct rsb_mtx_t **mtxBpp, rsb_type_t typecode, rsb_trans_t transA, const void *alphap, const struct rsb_mtx_t *mtxAp, rsb_flags_t flags)
rsb_err_t rsb_spmv (rsb_trans_t transA, const void *alphap, const struct rsb_mtx_t *mtxAp, const void *Xp, rsb_coo_idx_t incX, const void *betap, void *Yp, rsb_coo_idx_t incY)
rsb_err_t rsb_spsv (rsb_trans_t transT, const void *alphap, const struct rsb_mtx_t *mtxTp, const void *Xp, rsb_coo_idx_t incX, void *Yp, rsb_coo_idx_t incY)
rsb_err_t rsb_spsm (rsb_trans_t transT, const void *alphap, const struct rsb_mtx_t *mtxTp, rsb_coo_idx_t nrhs, rsb_flags_t order, const void *betap, const void *Bp, rsb_nnz_idx_t ldB, void *Cp, rsb_nnz_idx_t ldC)

the COO tidy-up duo

rsb_err_t rsb_coo_sort (void *VA, rsb_coo_idx_t *IA, rsb_coo_idx_t *JA, rsb_nnz_idx_t nnzA, rsb_coo_idx_t nrA, rsb_coo_idx_t ncA, rsb_type_t typecode, rsb_flags_t flagsA)
rsb_err_t rsb_coo_cleanup (rsb_coo_idx_t *nnzp, void *VA, rsb_coo_idx_t *IA, rsb_coo_idx_t *JA, rsb_nnz_idx_t nnzA, rsb_coo_idx_t nrA, rsb_coo_idx_t ncA, rsb_type_t typecode, rsb_flags_t flagsA)

the error-handling + file-peeking squad

rsb_err_t rsb_file_mtx_get_dims (const char *filename, rsb_coo_idx_t *nrp, rsb_coo_idx_t *ncp, rsb_coo_idx_t *nzp, rsb_flags_t *flagsp)
rsb_err_t rsb_perror (void *stream, rsb_err_t errval)
rsb_err_t rsb_strerror_r (rsb_err_t errval, rsb_char_t *buf, size_t buflen)

the value-poking trio

rsb_err_t rsb_mtx_upd_vals (struct rsb_mtx_t *mtxAp, enum rsb_elopf_t elop_flags, const void *omegap)
rsb_err_t rsb_mtx_set_vals (struct rsb_mtx_t *mtxAp, const void *VA, const rsb_coo_idx_t *IA, const rsb_coo_idx_t *JA, rsb_nnz_idx_t nnz, rsb_flags_t flags)
rsb_err_t rsb_mtx_get_vals (const struct rsb_mtx_t *mtxAp, void *VA, const rsb_coo_idx_t *IA, const rsb_coo_idx_t *JA, rsb_nnz_idx_t nnz, rsb_flags_t flags)
psst β€” there are TWO rsb_err_t rsb_file_vec_* functions coming up, and yes the save one takes rsb_coo_idx_t yvl while the load one takes rsb_coo_idx_t *yvlp. pointer vs no pointer, they are NOT the same girl, do not mix them up 😭

the file I/O lineup

rsb_err_t rsb_file_mtx_save (const struct rsb_mtx_t *mtxAp, const rsb_char_t *filename)
rsb_err_t rsb_file_vec_save (const rsb_char_t *filename, rsb_type_t typecode, const void *Yp, rsb_coo_idx_t yvl)
rsb_err_t rsb_file_vec_load (const rsb_char_t *filename, rsb_type_t typecode, void *Yp, rsb_coo_idx_t *yvlp)
struct rsb_mtx_t * rsb_file_mtx_load (const rsb_char_t *filename, rsb_flags_t flagsA, rsb_type_t typecode, rsb_err_t *errvalp)

the sparse-times-sparse duo (they return a whole matrix, main character energy)

struct rsb_mtx_t * rsb_sppsp (rsb_type_t typecode, rsb_trans_t transA, const void *alphap, const struct rsb_mtx_t *mtxAp, rsb_trans_t transB, const void *betap, const struct rsb_mtx_t *mtxBp, rsb_err_t *errvalp)
struct rsb_mtx_t * rsb_spmsp (rsb_type_t typecode, rsb_trans_t transA, const void *alphap, const struct rsb_mtx_t *mtxAp, rsb_trans_t transB, const void *betap, const struct rsb_mtx_t *mtxBp, rsb_err_t *errvalp)

the dense-merge + PSBLAS translation icons

rsb_err_t rsb_mtx_add_to_dense (const void *alphap, const struct rsb_mtx_t *mtxAp, rsb_nnz_idx_t ldB, rsb_nnz_idx_t nrB, rsb_nnz_idx_t ncB, rsb_bool_t rowmajorB, void *Bp)
rsb_trans_t rsb_psblas_trans_to_rsb_trans (const char psbtrans)

the CSR / CSC builders

struct rsb_mtx_t * rsb_mtx_alloc_from_csr_const (const void *VA, const rsb_coo_idx_t *RP, const 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)
struct rsb_mtx_t * rsb_mtx_alloc_from_csc_const (const void *VA, const rsb_coo_idx_t *IA, const rsb_coo_idx_t *CP, 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)
struct rsb_mtx_t * rsb_mtx_alloc_from_csr_inplace (void *VA, rsb_nnz_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)
tiny detail that matters: in rsb_mtx_alloc_from_csr_inplace the row pointer is rsb_nnz_idx_t *RP, but in rsb_mtx_alloc_from_csr_const it's const rsb_coo_idx_t *RP. different types, bestie. the compiler WILL notice. πŸ’€

the format-switchers

rsb_err_t rsb_mtx_switch_to_csr (struct rsb_mtx_t *mtxAp, void **VAp, rsb_coo_idx_t **IAp, rsb_coo_idx_t **JAp, rsb_flags_t flags)
rsb_err_t rsb_mtx_switch_to_coo (struct rsb_mtx_t *mtxAp, void **VAp, rsb_coo_idx_t **IAp, rsb_coo_idx_t **JAp, rsb_flags_t flags)

the "gimme the data" gang

rsb_err_t rsb_mtx_get_coo (const struct rsb_mtx_t *mtxAp, void *VA, rsb_coo_idx_t *IA, rsb_coo_idx_t *JA, rsb_flags_t flags)
rsb_err_t rsb_mtx_get_csr (rsb_type_t typecode, const struct rsb_mtx_t *mtxAp, void *VA, rsb_nnz_idx_t *RP, rsb_coo_idx_t *JA, rsb_flags_t flags)
rsb_err_t rsb_mtx_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)
rsb_err_t rsb_mtx_get_coo_block (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_coo_idx_t fcA, rsb_coo_idx_t lcA, const rsb_coo_idx_t *IREN, const rsb_coo_idx_t *JREN, rsb_nnz_idx_t *rnzp, rsb_flags_t flags)

the bigger-products section

rsb_err_t rsb_spmm (rsb_trans_t transA, const void *alphap, const struct rsb_mtx_t *mtxAp, rsb_coo_idx_t nrhs, rsb_flags_t order, const void *Bp, rsb_nnz_idx_t ldB, const void *betap, void *Cp, rsb_nnz_idx_t ldC)
rsb_err_t rsb_spmsp_to_dense (rsb_type_t typecode, rsb_trans_t transA, const void *alphap, const struct rsb_mtx_t *mtxAp, rsb_trans_t transB, const void *betap, const struct rsb_mtx_t *mtxBp, rsb_nnz_idx_t ldC, rsb_nnz_idx_t nrC, rsb_nnz_idx_t ncC, rsb_bool_t rowmajorC, void *Cp)

the render squad 🎨

rsb_err_t rsb_mtx_rndr (const char *filename, const struct rsb_mtx_t *mtxAp, rsb_coo_idx_t pmWidth, rsb_coo_idx_t pmHeight, rsb_marf_t rflags)
rsb_err_t rsb_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)

precision + info + norms + vecs

rsb_err_t rsb_mtx_get_prec (void *opdp, const struct rsb_mtx_t *mtxAp, rsb_precf_t prec_flags, const void *ipdp)
rsb_err_t rsb_mtx_get_info (const struct rsb_mtx_t *mtxAp, enum rsb_mif_t miflags, void *minfop)
rsb_err_t rsb_mtx_get_info_str (const struct rsb_mtx_t *mtxAp, const rsb_char_t *mis, void *minfop, size_t buflen)
rsb_err_t rsb_mtx_get_nrm (const struct rsb_mtx_t *mtxAp, void *Np, enum rsb_extff_t flags)
rsb_err_t rsb_mtx_get_vec (const struct rsb_mtx_t *mtxAp, void *Dp, enum rsb_extff_t flags)

the clock ⏰

rsb_time_t rsb_time (void)

the begin/end construction combo (yes she takes **mtxApp, yes that's on purpose)

struct rsb_mtx_t * rsb_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 flagsA, rsb_err_t *errvalp)
rsb_err_t rsb_mtx_alloc_from_coo_end (struct rsb_mtx_t **mtxApp)

the autotuning icons ✨

rsb_err_t rsb_tune_spmm (struct rsb_mtx_t **mtxOpp, rsb_real_t *sfp, rsb_int_t *tnp, rsb_int_t maxr, rsb_time_t maxt, rsb_trans_t transA, const void *alphap, const struct rsb_mtx_t *mtxAp, rsb_coo_idx_t nrhs, rsb_flags_t order, const void *Bp, rsb_nnz_idx_t ldB, const void *betap, void *Cp, rsb_nnz_idx_t ldC)
rsb_err_t rsb_tune_spsm (struct rsb_mtx_t **mtxOpp, rsb_real_t *sfp, rsb_int_t *tnp, rsb_int_t maxr, rsb_time_t maxt, rsb_trans_t transA, const void *alphap, const struct rsb_mtx_t *mtxAp, rsb_coo_idx_t nrhs, rsb_flags_t order, const void *Bp, rsb_nnz_idx_t ldB, const void *betap, void *Cp, rsb_nnz_idx_t ldC)

and that's the entire synopsis, every macro, every enum, every last prototype, all fifty-something of them, zero left behind. πŸ¦‹ don't worry bestie, the actual explanations of what they all DO are coming, we're just getting the roll call out of the way first. πŸ’œ

πŸ’– DETAILED DESCRIPTION πŸ’–

Okay bestie, so the rsb library ships its reference docs in two flavors: HTML and good old Unix man pages. Both, always. Slay.

Here's the full menu of what's available:

  • The librsb library interface β€” that's rsb.h, plus the optional ones rsb.hpp and rsb.F90 πŸŽ€
  • The Sparse BLAS interface to librsb β€” that's blas_sparse.h and rsb_blas_sparse.F90
  • Example programs and code ✨

Generally speaking, the people using this library are obsessed with high performance sparse matrix computations running on cache based shared memory parallel computers. That's the whole vibe.

So for that, rsb gives you:

  • a native C interface (the one documented right here, hi πŸ’…)
  • a Fortran one, in rsb.F90, which is equivalent to the C declaration headers from rsb.h
  • plus the Sparse BLAS one, in both C and Fortran (documented too)

And for the C++ API you should go look at the optional <rsb.hpp> πŸ¦‹

Configuration, build, and installation instructions? Those live in the README file distributed in the sources archive. Go read it, it's important.


🌸 Typical C program structure 🌸

  1. initialize rsb with rsb_lib_init()
  2. (in any order) allocate matrices β€” e.g.: with rsb_mtx_alloc_from_coo_inplace() or others; do any computation with them (e.g.: rsb_spmv(), rsb_spsv()); convert matrices (e.g.: with rsb_mtx_switch_to_coo()); free matrices (rsb_mtx_free())
  3. finalize rsb with rsb_lib_exit()

πŸ’œ Important usage notes πŸ’œ

General C program structure

Before calling any rsb function, a program is required to initialize rsb's internal status. That's what rsb_lib_init() is for. After that, any rsb function can be safely used πŸ”₯

When rsb functions are not intended to be called anymore, a program may call rsb_lib_exit() to free any resource. And then, rsb_lib_init() should be called for further usage of rsb. Round and round, periodt.

Manipulating matrices and vectors

Here's the thing: to use rsb, the user is not required to explicitly use any of rsb's data structures β€” their manipulation is to be performed by rsb functions. So honestly, knowledge of rsb's matrix type (rsb_mtx_t) is not necessary at all: this structure is intended to be used as an opaque container. iykyk πŸ™ˆ

On the contrary, arrays for numerical vectors (or more generally, dense matrices) are expected to be managed by the user: rsb does not furnish any specific vector type. Computational functions treat dense vectors/matrices as simple arrays of a specified type β€” see the Example programs and code πŸ’–

Computational functions

This library can be configured at build time to support a custom subset of numerical types. And to keep the programming interface compact, it has been decided to not replicate the computational functions to each numerical type. Instead, the type is expected to be specified by the user via a type flag ✨

So for instance, matrix assembly functions (e.g.: rsb_mtx_alloc_from_coo_const()) accept a type information and keep it stored in the matrix structure. Therefore, computational functions (e.g.: rsb_spmv()) can fetch this information from their rsb_mtx_t operand, and treat accordingly the other parameters (e.g.: alphap, Xp, ...). Very main character energy.

⚠️ Mixed type operations are currently not supported. Not a vibe, but that's the rule.

Memory management

Matrix structures (rsb_mtx_t) allocated by rsb shall be freed only via rsb_mtx_free(). Only. Do not improvise. 😭

Benchmarking

If you want to benchmark this library, there are different possibilities:

#!/bin/bash

set -e
set -x

# the benchmark command assumes A.mtx is a file in Matrix Market format
rsbench -oa -Ob --bench --nmb -f pd.mtx

# it has many (librsb development-oriented) options
rsbench -oa -Ob --help

# this is mostly a development tool so don't rely on much more than the above.

Tuning and Customization

There are different ./configure options you may look at for tuning or customizing the library. Go peek, bestie πŸ‘‘


πŸŽ€ MACRO DEFINITION DOCUMENTATION πŸŽ€

#define RSB_SIZEOF( TYPE)

Value:

RSB_NUMERICAL_TYPE_SIZE(TYPE)

Use the RSB_SIZEOF macro to get the size (in bytes 🫢) of a type supported by the library β€” e.g.: when allocating numerical vectors. Iconic, honestly.

πŸŽ€ Enumeration Type Documentation πŸŽ€


🌈 enum rsb_elopf_t

okay bestie, these are the flags that tell rsb_mtx_upd_vals() which specific elemental / row-wise operation you want it to do. pick your fighter πŸ’…

Enumerators

  • RSB_ELOPF_MUL β€” elemental multiplication of the matrix by a scalar you specify (usable with rsb_mtx_upd_vals(), binary operation). βœ–οΈ
  • RSB_ELOPF_DIV β€” elemental division by a scalar you specify (usable with rsb_mtx_upd_vals(), binary operation). βž—
  • RSB_ELOPF_POW β€” elemental power to a scalar you specify (usable with rsb_mtx_upd_vals(), binary operation). πŸ’₯
  • RSB_ELOPF_NEG β€” elemental negation (usable with rsb_mtx_upd_vals(), unary operation). πŸ™ƒ only takes one thing, queen behaviour
  • RSB_ELOPF_SCALE_ROWS β€” row wise scaling by a scaling vector you specify (usable with rsb_mtx_upd_vals(), binary operation). πŸͺ„
  • RSB_ELOPF_SCALE_COLS β€” column wise scaling by a scaling vector you specify (usable with rsb_mtx_upd_vals(), binary operation). πŸͺ„
  • RSB_ELOPF_SCALE_ROWS_REAL β€” row wise scaling by a scaling vector you specify. If the matrix is of a complex type, the argument is expected to be of the corresponding real type (assumed that that type has been enabled). (usable with rsb_mtx_upd_vals(), binary operation). yes it's the complicated sibling
  • RSB_ELOPF_SCALE_COLS_REAL β€” column wise scaling by a scaling vector you specify. If the matrix is of a complex type, the argument is expected to be of the corresponding real type (assumed that that type has been enabled). (usable with rsb_mtx_upd_vals(), binary operation). same energy, column edition

🌈 enum rsb_extff_t

Extraction filter flags, fr fr β€” these are the ones you pair with rsb_mtx_get_nrm() / rsb_mtx_get_vec().

Enumerators

  • RSB_EXTF_NORM_ONE β€” rsb_mtx_get_nrm() flag value for computing the one-norm. 1️⃣
  • RSB_EXTF_NORM_TWO β€” rsb_mtx_get_nrm() flag value for computing the two-norm (Frobenius norm). 2️⃣
  • RSB_EXTF_NORM_INF β€” rsb_mtx_get_nrm() flag value for computing the infinity-norm. ♾️
  • RSB_EXTF_SUMS_ROW β€” rsb_mtx_get_vec() flag value for computing the sum along each row. βž•
  • RSB_EXTF_SUMS_COL β€” rsb_mtx_get_vec() flag value for computing the sum along each column. βž•
  • RSB_EXTF_ASUMS_ROW β€” rsb_mtx_get_vec() flag value for computing the absolute values sum, along each row. absolutely 🫢
  • RSB_EXTF_ASUMS_COL β€” rsb_mtx_get_vec() flag value for computing the absolute values sum, along each column. absolutely 🫢
  • RSB_EXTF_DIAG β€” rsb_mtx_get_vec() flag value for extracting the diagonal submatrix. πŸ“ main character diagonal energy

🌈 enum rsb_mif_t

Flags for getting matrix information via rsb_mtx_get_info() / rsb_mtx_get_info_str(). each one tells you what you're asking for and what type the answer comes back as, so pay attention to the type in the parens okay 🫢

Enumerators

  • RSB_MIF_INDEX_STORAGE_IN_BYTES__TO__SIZE_T β€” index storage occupation, in bytes. (size_t)
  • RSB_MIF_INDEX_STORAGE_IN_BYTES_PER_NNZ__TO__RSB_REAL_T β€” index storage occupation per nnz, in bytes. (rsb_real_t)
  • RSB_MIF_MATRIX_ROWS__TO__RSB_COO_INDEX_T β€” rows count (rsb_coo_idx_t)
  • RSB_MIF_MATRIX_COLS__TO__RSB_COO_INDEX_T β€” columns count (rsb_coo_idx_t)
  • RSB_MIF_MATRIX_NNZ__TO__RSB_NNZ_INDEX_T β€” nonzeroes count (rsb_nnz_idx_t)
  • RSB_MIF_TOTAL_SIZE__TO__SIZE_T β€” total size, in bytes (size_t)
  • RSB_MIF_MATRIX_FLAGS__TO__RSB_FLAGS_T β€” matrix flags (rsb_flags_t)
  • RSB_MIF_MATRIX_TYPECODE__TO__RSB_TYPE_T β€” matrix type code (rsb_type_t)
  • RSB_MIF_MATRIX_INFO__TO__CHAR_P β€” matrix info string, only for rsb_mtx_get_info_str() (rsb_char_t*)
  • RSB_MIF_LEAVES_COUNT__TO__RSB_BLK_INDEX_T β€” leaf submatrices count (rsb_blk_idx_t) πŸƒ

🌈 enum rsb_opt_t

library option values, for \see_lib_init_funcs. this is the big one, bestie β€” grab a snack πŸ“

Enumerators

  • RSB_IO_WANT_VERBOSE_INIT β€” RSB_IO_WANT_VERBOSE_INIT prompts for a verbose initialization of the library: messages will be written to the file descriptor (FILE*) pointed by the value pointer when calling rsb_lib_init or rsb_lib_reinit. ✨
  • RSB_IO_WANT_VERBOSE_EXIT β€” RSB_IO_WANT_VERBOSE_EXIT prompts for a verbose finalization of the library: messages will be written to the file descriptor (FILE*) pointed by the value pointer when calling rsb_lib_exit.
  • RSB_IO_WANT_OUTPUT_STREAM β€” specifies the default output stream. Output (debug info) info will be written to the file descriptor (FILE*) pointed by the value pointer.
  • RSB_IO_WANT_SORT_METHOD β€” specifies the default sorting method. Specified as a pointed integer (rsb_int_t) number, in {[0],1}. (internal)
  • RSB_IO_WANT_CACHE_BLOCKING_METHOD β€” specifies the default cache blocking method. Specified as a pointed integer (rsb_int_t) number, in {-1,[0],1}. (internal)
  • RSB_IO_WANT_SUBDIVISION_MULTIPLIER β€” specifies a multiplier for finer (if >1.0) or coarser (if <1.0) subdivisions. Specified as a pointed (rsb_real_t) number, in {..,[1.0],..}. (internal)
  • RSB_IO_WANT_VERBOSE_ERRORS β€” prompts for a verbose error reporting: messages will be written to the file descriptor (FILE*) pointed by the value pointer. Only meaningful if an interface error verbosity greater than 0 was set at configure time. 😭
  • RSB_IO_WANT_BOUNDED_BOX_COMPUTATION β€” prompts for bounded box computation, for a smoother submatrices locking; pointed rsb_int_t in {0,[1]}. (internal).
  • RSB_IO_WANT_EXECUTING_THREADS β€” specifies the number of desired executing threads; pointed rsb_int_t in {[0],1,..}. 🧡
  • RSB_IO_WANT_EXTRA_VERBOSE_INTERFACE β€” specifies the level of interface verbosity; if setting, pointed rsb_int_t values should be in {[0],1,..}. Support may be enabled or disabled at build time via the --enable-internals-error-verbosity configure option. If disabled, only getting is supported and yields -1, but setting is not supported and the RSB_ERR_NO_STREAM_OUTPUT_CONFIGURED_OUT error will be returned.
  • RSB_IO_WANT_MEMORY_HIERARCHY_INFO_STRING β€” specifies a custom memory hierarchy info string; pointed const rsb_char_t*; (may point to a NULL string pointer).
  • RSB_IO_WANT_IS_INITIALIZED_MARKER β€” used for getting whether the library has been initialized (RSB_BOOL_TRUE) or not (RSB_BOOL_FALSE) ; pointed const rsb_bool_t*; (this is NOT for general users). πŸ™ˆ
  • RSB_IO_WANT_MEM_ALLOC_CNT β€” used for getting the count of memory allocations performed by librsb employing librsb's memory allocation wrapper (if disabled, will return zero); pointed const size_t*; (this is for debugging purposes). πŸ›
  • RSB_IO_WANT_MEM_ALLOC_TOT β€” used for getting the total amount of memory allocated by librsb employing librsb's memory allocation wrapper (if disabled, will return zero); pointed const size_t*; (this is for debugging purposes). πŸ›
  • RSB_IO_WANT_LEAF_LEVEL_MULTIVEC β€” specifies whether the default multi-vector ops shall act at a leaf level (default value of 0 is yes). Specified as a pointed integer (rsb_int_t) number, in {-1,[0]}. (internal)
  • RSB_IO_WANT_MAX_MEMORY_ALLOCATIONS β€” specifies an upper limit to the count of allocated memory areas (default value of 0 means no limit). Specified as a pointed size_t. \rsb_configure_memwrap
  • RSB_IO_WANT_MAX_MEMORY_ALLOCATED β€” specifies an upper limit to the amount of allocated memory (default value of 0 means no limit). Specified as a pointed size_t. \rsb_configure_memwrap
  • RSB_IO_WANT_LIBRSB_ETIME β€” represents time spent in librsb. Specified as a pointed rsb_time_t. Only works if statistics collection (--enable-librsb-stats) was specified at configure time. ⏱️
  • RSB_IO_WANT_VERBOSE_TUNING β€” auto tuning verbosity level for rsb_tune_spmm / rsb_tune_spsm. If 0, no verbosity; if 1, verbose; if 2, verbose with trace files being dumped. πŸ”₯

⭐ Function Documentation ⭐


πŸ¦‹ rsb_err_t rsb_coo_cleanup (rsb_coo_idx_t * nnzp, void * VA, rsb_coo_idx_t * IA, rsb_coo_idx_t * JA, rsb_nnz_idx_t nnzA, rsb_coo_idx_t nrA, rsb_coo_idx_t ncA, rsb_type_t typecode, rsb_flags_t flagsA)

okay so this one compacts the COO input arrays you hand it, representing a sparse matrix $A$. basically it tidies up your duplicates for you 🧹✨

it will either sum together duplicates or use the last one β€” which one depends on whether RSB_FLAG_DUPLICATES_KEEP_LAST or RSB_FLAG_DUPLICATES_SUM is present in flagsA.

bestie listen 😭 it is important that the input is sorted and that flagsA shall contain RSB_FLAG_SORTED_INPUT, otherwise the algorithm's complexity will be quadratic. no cap. don't do that to yourself.

Parameters

  • nnzp β€” pointer to the number of nonzeroes after the cleanup.
  • VA,IA,JA β€” output numerical values (VA) array; output row (IA) and column (JA) indices arrays.
  • nnzA β€” the number of nonzeroes in the input arrays representing matrix $A$.
  • nrA,ncA β€” the number of rows and columns of the sparse matrix $A$.
  • typecode β€” a valid type code for the given (numerical array) input pointer (see matrix_type_symbols_section).
  • flagsA β€” a valid combination of matrix storage flags. If unsure, use RSB_FLAG_NOFLAGS.

Returns

RSB_ERR_NO_ERROR on correct operation, an error code otherwise. You can use rsb_strerror_r() or rsb_perror() to get more information about the error. 🫢

See also

rsb_time, rsb_coo_sort

rsb_coo_sort

⚠️ Warning β€” this is an experimental librsb-1.3 function. experimental!! act accordingly πŸ’…

Note

By invoking with swapped IA and JA (and swapping nrA and ncA as well) one can obtain column major order. πŸ”„

Examples:

rsb_err_t errval = RSB_ERR_NO_ERROR;
rsb_nnz_idx_t nnzA = 4;
const rsb_coo_idx_t  nrA = 4;
const rsb_coo_idx_t  ncA = 4;
rsb_coo_idx_t    IA[] = { 1, 1, 1, 2 };
rsb_coo_idx_t    JA[] = { 1, 1, 3, 2 };
RSB_DEFAULT_TYPE VA[] = { 1, 10, 13, 22 };
const rsb_type_t typecode = RSB_NUMERICAL_TYPE_DEFAULT;
rsb_flags_t flagsA = RSB_FLAG_DUPLICATES_SUM | RSB_FLAG_SORTED_INPUT;
// IA={1,1,1,2} JA={1,1,3,2} VA={1,10,13,22} nnzA=4 nrA=4 nca=4

if((errval = rsb_lib_init(RSB_NULL_INIT_OPTIONS))
                != RSB_ERR_NO_ERROR) goto err;

errval = rsb_coo_cleanup(&nnzA, VA, IA, JA,
         nnzA, nrA, ncA, typecode, flagsA );
if(errval != RSB_ERR_NO_ERROR )
{
        printf("Error calling rsb_coo_cleanup!\n");
        goto err;
}
// IA={1,1,2} JA={1,3,2} VA={11,13,22} nnzA=3 nrA=4 nca=4

…and here's the rest of that little sum-up example, bestie, typed out exactly so you can copy-paste it and feel like a genius ✨

               rsb_err_t errval = RSB_ERR_NO_ERROR;
               rsb_nnz_idx_t nnzA = 3;
               const rsb_coo_idx_t  nrA = 2;
               const rsb_coo_idx_t  ncA = 2;
               rsb_coo_idx_t    IA[] = { 1, 1, 1 };
               rsb_coo_idx_t    JA[] = { 2, 1, 1 };
               RSB_DEFAULT_TYPE VA[] = { 1, 2, 3 };
               const rsb_type_t typecode = RSB_NUMERICAL_TYPE_DEFAULT;
               const rsb_flags_t flagsA = RSB_FLAG_DUPLICATES_SUM
                               | RSB_FLAG_SORTED_INPUT
                               | RSB_FLAG_FORTRAN_INDICES_INTERFACE;

               // IA={1,1,1} JA={2,1,1} VA={1,2,3} nnzA=3 nrA=2 nca=2
               errval =rsb_coo_sort(VA, IA, JA, nnzA, nrA, ncA,  typecode, flagsA);
               if(errval != RSB_ERR_NO_ERROR )
               {
                       printf("Error calling rsb_coo_cleanup!\n");
                       goto err;
               }
               // IA={1,1,1} JA={1,1,2} VA={2,3,1} nnzA=3 nrA=2 nca=2

               errval = rsb_coo_cleanup(&nnzA, VA, IA, JA, nnzA,
                        nrA, ncA, typecode, flagsA );
               if(errval != RSB_ERR_NO_ERROR )
               {
                       printf("Error calling rsb_coo_cleanup!\n");
                       goto err;
               }
               // IA={1,1} JA={1,2} VA={5,1} nnzA=2 nrA=2 nca=2

πŸ¦‹ rsb_coo_sort

rsb_err_t rsb_coo_sort (void * VA, rsb_coo_idx_t * IA, rsb_coo_idx_t * JA,
    rsb_nnz_idx_t nnzA, rsb_coo_idx_t nrA, rsb_coo_idx_t ncA, rsb_type_t
    typecode, rsb_flags_t flagsA)

okay so this one sorts the COO input arrays you hand it, row-major style, and those arrays are representing a sparse matrix $A$. it's giving "put my triplets in order pls" πŸ’…

Parameters πŸŽ€

  • VA, IA, JA β€” the output numerical values array (VA), plus the output row (IA) and column (JA) index arrays.
  • nnzA β€” how many nonzeroes live in the input arrays representing matrix $A$.
  • nrA, ncA β€” the number of rows and columns of the sparse matrix $A$. heads up: if either nrA or ncA is zero, then no sort happens at all, periodt.
  • typecode β€” a valid type code for the given (numerical array) input pointer (peep matrix_type_symbols_section).
  • flagsA β€” a valid combo of matrix storage flags. unsure? bestie just use RSB_FLAG_NOFLAGS.

Returns 🌸

RSB_ERR_NO_ERROR when everything's slay, an error code when it's not. you can hit up rsb_strerror_r() or rsb_perror() if you wanna know more about whatever went wrong.

See also πŸ”

rsb_time, rsb_coo_sort

Note πŸ’­

lowkey a fun trick: if you call this with IA and JA swapped (and swap nrA and ncA too, don't forget 😭), you get column major order. iconic behavior honestly.


🌈 rsb_file_mtx_get_dims

rsb_err_t rsb_file_mtx_get_dims (const char * filename, rsb_coo_idx_t * nrp,
    rsb_coo_idx_t * ncp, rsb_coo_idx_t * nzp, rsb_flags_t * flagsp)

this cutie reads the structural info β€” dimensions and structural flags β€” for a matrix file, and drops them into your user-specified variables (which, btw, are optionally NULL, so no pressure 🫢).

Parameters πŸŽ€

  • filename β€” the specified matrix file name (cannot be NULL).
  • nrp, ncp β€” output pointers to the rows and columns count variables (can be NULL).
  • nzp β€” output pointer to the nonzeroes count variable (can be NULL).
  • flagsp β€” output pointer to the detected structural flags variable. it'll be some combo of RSB_FLAG_LOWER, RSB_FLAG_UPPER, RSB_FLAG_SYMMETRIC, RSB_FLAG_HERMITIAN.

Returns 🌸

RSB_ERR_NO_ERROR on correct operation, an error code otherwise. and yeah, rsb_strerror_r() or rsb_perror() got your back with more details if you need 'em. one thing tho: if the dims you read are illegal (see rsb_coo_idx_t, rsb_nnz_idx_t), you'll get back RSB_ERR_LIMITS.

Example β€” getting dimensions of a sparse matrix stored in a Matrix Market file:

               if(RSB_ERR_NO_ERROR!=(errval =
                       rsb_file_mtx_get_dims("pd.mtx",&nrA,&ncA,&nnzA,NULL)))
               {
                       if(errval != RSB_ERR_UNSUPPORTED_FEATURE)
                               goto err; /* may have not configured what needed */
               }

Note πŸ’­

the only sparse matrix file format currently supported is Matrix Market. e.g.:

%%MatrixMarket matrix coordinate real symmetric
%
% A Hilbert Matrix of order 3, so with 3 rows, 3 columns, and 6 nonzeroes.
%
3 3 6
1 1 1.0
2 1 0.5
2 2 0.33
3 1 0.33
3 2 0.25
3 3 0.2

so in that example header up there on the first line, you can specify either real or complex or pattern for the numerical type. and for the structure you can specify either general, symmetric, or hermitian. in the case of pattern matrices, only coordinate indices get loaded (and saving pattern matrices is not yet supported, fyi πŸ₯²); in the case of real matrices, one coefficient value gets saved/loaded too; and in the case of complex matrices, both the real and imaginary parts get saved/loaded on top of the indices. the way that pattern matrices just skip the values… πŸ’€

also: upper/lower flags will not be reported. hermitian-ness will be. that's the vibe check.

See also πŸ”

rsb_mtx_get_coo, rsb_mtx_get_csr, rsb_mtx_get_rows_sparse, rsb_mtx_get_coo_block, rsb_mtx_get_prec, rsb_mtx_get_nrm, rsb_mtx_get_vec, rsb_file_mtx_get_dims, rsb_mtx_get_vals


🌸 rsb_file_mtx_load

struct rsb_mtx_t * rsb_file_mtx_load (const rsb_char_t * filename,
    rsb_flags_t flagsA, rsb_type_t typecode, rsb_err_t * errvalp)

loads a sparse matrix from the matrix file you point at, assembles it in the format you asked for with flags, and uses the numerical type representation you specified. and ooh, if you want the input errors or warnings to be extra chatty, you can turn up verbosity with the ./configure --enable-internals-error-verbosity option. yes bestie, she's loud πŸ“£

Parameters πŸŽ€

  • filename β€” the specified matrix file name (cannot be NULL).
  • flagsA β€” a valid combination of matrix storage flags.
  • typecode β€” a valid type code for the given (numerical array) input pointer (see matrix_type_symbols_section).
  • errvalp β€” an optional (can be NULL) pointer to rsb_err_t where the error status gets written.

Returns 🌸

on success, a valid pointer (struct rsb_mtx_t*) to the freshly allocated matrix structure; on error, NULL. no in-between, she's dramatic like that πŸ’…

Note πŸ’­

the only sparse matrix file format currently supported is Matrix Market. e.g.:

%%MatrixMarket matrix coordinate real symmetric
%
% A Hilbert Matrix of order 3, so with 3 rows, 3 columns, and 6 nonzeroes.
%
3 3 6
1 1 1.0
2 1 0.5
2 2 0.33
3 1 0.33
3 2 0.25
3 3 0.2

in that header on the first line you can say real, complex, or pattern for the numerical type, and general, symmetric, or hermitian for the structure. pattern matrices? only coordinate indices get loaded (saving them is not yet supported, sadly πŸ₯²). real matrices? one coefficient value gets saved/loaded too. complex matrices? both the real and imaginary parts come along for the ride, in addition to the indices.

Example β€” loading a matrix from a Matrix Market file:

               mtxAp = rsb_file_mtx_load("pd.mtx",
                       RSB_FLAG_NOFLAGS,typecode,NULL);
               if(!mtxAp)
               {
                       return EXIT_FAILURE;
               }

See also πŸ”

rsb_mtx_get_info, rsb_mtx_get_info_str, rsb_file_mtx_save, rsb_file_vec_load, rsb_file_mtx_load


🎨 rsb_file_mtx_rndr

rsb_err_t rsb_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)

renders the matrix sitting inside a matrix file as a pixel map. art?? in my sparse matrix library?? it's more likely than you think ✨

Parameters πŸŽ€

  • pmp β€” pixel map array pointer.
  • filename β€” the specified matrix file name (cannot be NULL).
  • pmlWidth β€” stride between lines (in pixels; no less than pmWidth).
  • pmWidth β€” pixel map width (in pixels or points).
  • pmHeight β€” pixel map height (in pixels or points).
  • rflags β€” the color mode. only RSB_MARF_RGB is supported for now (1 byte per channel, 3 channels β€” red, green, blue), and this requires the array pmp to be at least (3*pmlWidth*pmHeight) bytes large. size it right or it's a bad time 😭

Returns 🌸

RSB_ERR_NO_ERROR on correct operation, an error code otherwise. rsb_strerror_r() or rsb_perror() for the deets, as always.

Note πŸ’­

at the time being, pmlWidth is required to be equal to pmWidth. no negotiating, bestie 🫢

Example β€” rendering a matrix from a Matrix Market file to a pixelmap in memory:

               /* matrices can be rendered from file to a pixelmap as well */
               {
                       unsigned char pixmap[3*2*2];

                       if(RSB_ERR_NO_ERROR!=(errval =
                       rsb_file_mtx_rndr(pixmap,"pd.mtx",2,2,2,RSB_MARF_RGB)))
                               goto err;
               }

See also πŸ”

rsb_mtx_rndr, rsb_file_mtx_rndr


πŸ’– rsb_file_mtx_save

rsb_err_t rsb_file_mtx_save (const struct rsb_mtx_t * mtxAp, const
    rsb_char_t * filename)

saves the matrix you give her into the matrix file you name. cute, simple, efficient πŸ’…

Parameters πŸŽ€

  • mtxAp β€” valid rsb_mtx_t pointer to matrix $A$ representation.
  • filename β€” the specified output file name. and plot twist: if it's NULL or '' (the empty string), it'll write to standard output instead. periodt.

Returns 🌸

RSB_ERR_NO_ERROR on correct operation, an error code otherwise. rsb_strerror_r() or rsb_perror() will spill the tea if something's off.

Warning ⚠️

some structural info contained in the matrix structural flags may be lost in the output data. so like… don't assume it round-trips perfectly, bestie, write that down 😭

Note πŸ’­

the only sparse matrix file format currently supported is Matrix Market. e.g.:

%%MatrixMarket matrix coordinate real symmetric
%
% A Hilbert Matrix of order 3, so with 3 rows, 3 columns, and 6 nonzeroes.
%
3 3 6
1 1 1.0
2 1 0.5
2 2 0.33
3 1 0.33
3 2 0.25
3 3 0.2

as established: first line header, real/complex/pattern for the numerical type, general/symmetric/hermitian for the structure. pattern matrices only load coordinate indices (and saving pattern matrices is not yet supported β€” annoying, I know). real matrices also save/load one coefficient value. complex matrices save/load both real and imaginary parts alongside the indices.

Example β€” printing a matrix to standard output:

               if(RSB_ERR_NO_ERROR!=(errval = rsb_file_mtx_save(mtxAp,NULL)))
               {
                       if(errval != RSB_ERR_UNSUPPORTED_FEATURE)
                               goto err;
               }

See also πŸ”

rsb_mtx_get_info, rsb_mtx_get_info_str, rsb_file_mtx_save, rsb_file_vec_load, rsb_file_mtx_load


🧚 rsb_file_vec_load

rsb_err_t rsb_file_vec_load (const rsb_char_t * filename, rsb_type_t
    typecode, void * Yp, rsb_coo_idx_t * yvlp)

loads a dense vector from the file you specify, using the numerical type representation you asked for. and here's the gag β€” this function is designed to be called in two steps: first call it with Yp=NULL so it writes the vector length into *yvlp; then call it again with yvlp=NULL to actually get Yp written. two-step girlie, very choreographed, she ate πŸ“

Parameters

  • filename β€” the vector file name you're pointing at (cannot be NULL, bestie, that's a hard no).
  • typecode β€” a valid type code for the incoming (numerical array) pointer. Peep matrix_type_symbols_section for the menu of options.
  • Yp β€” the input array vector. This is where the goods land.
  • yvlp β€” an optional pointer (can be NULL). If you hand one over, the vector length gets written right there and no vector gets read at all β€” it's giving "just tell me the size, don't unpack".

Returns

RSB_ERR_NO_ERROR when everything's vibing, or an error code otherwise. Want the tea on what went wrong? Hit up rsb_strerror_r() or rsb_perror(). πŸ’…

Example loading vector matrix from file

        /* also vectors can be loaded */
        if(RSB_ERR_NO_ERROR!=(errval =
            rsb_file_vec_load("vf.mtx",typecode,NULL,&vl )))
            goto err;
        /* we expect vf.mtx to be 6 rows long */
        if( vl != 6 )
        {
            goto err;
        }

        if(RSB_ERR_NO_ERROR!=(errval =
            rsb_file_vec_load("vf.mtx",typecode,XV, NULL )))
            goto err;

Note

Lowkey the only dense vector file format supported rn is Matrix Market. Like:

%%MatrixMarket matrix array complex general
% Test MatrixMarket file with a complex vector.
% Note: a blank line like the following is OK.

6           1
11.000000000000000E+000 12.000000000000000E+000
21.000000000000000E+000 22.000000000000000E+000
31.000000000000000E+000 32.000000000000000E+000
41.000000000000000E+000 42.000000000000000E+000
51.000000000000000E+000 52.000000000000000E+000
61.000000000000000E+000 62.000000000000000E+000

See that header on the first line, up in the example? You can specify either real or complex or pattern for the numerical type. Slay, pick your fighter. ✨

See also

rsb_mtx_get_info, rsb_mtx_get_info_str, rsb_file_mtx_save, rsb_file_vec_load, rsb_file_mtx_load


rsb_file_vec_save πŸ’Ύ

rsb_err_t rsb_file_vec_save (const rsb_char_t * filename, rsb_type_t
    typecode, const void * Yp, rsb_coo_idx_t yvl)

Saves a dense vector to the file you picked, using the numerical type representation you specified. This one assumes Yp!=NULL and yvl>0 β€” no empty vibes allowed. 🫢

Parameters

  • filename β€” the vector file name (cannot be NULL).
  • typecode β€” a valid type code for the given (numerical array) input pointer, see matrix_type_symbols_section.
  • Yp β€” the output array vector.
  • yvl β€” output vector length.

Returns

RSB_ERR_NO_ERROR if it ate, an error code otherwise. More info? rsb_strerror_r() or rsb_perror(), as always.

Note

Again, the only dense vector file format currently supported is Matrix Market. E.g.:

%%MatrixMarket matrix array complex general
% Test MatrixMarket file with a complex vector.
% Note: a blank line like the following is OK.

6           1
11.000000000000000E+000 12.000000000000000E+000
21.000000000000000E+000 22.000000000000000E+000
31.000000000000000E+000 32.000000000000000E+000
41.000000000000000E+000 42.000000000000000E+000
51.000000000000000E+000 52.000000000000000E+000
61.000000000000000E+000 62.000000000000000E+000

And the same deal as before: in that first-line header you can specify either real or complex or pattern for the numerical type. πŸ‘‘

Example printing to standard output:

        errval = rsb_file_vec_save(NULL, typecode, X, nrA);
        if(errval != RSB_ERR_NO_ERROR )
        {
            printf("Error printing vector!\n");
            goto err;
        }

See also

rsb_mtx_get_info, rsb_mtx_get_info_str, rsb_file_mtx_save, rsb_file_vec_load, rsb_file_mtx_load


rsb_lib_exit πŸŒ™

rsb_err_t rsb_lib_exit (struct rsb_initopts * iop)

Finalize librsb. That's it, that's the whole job. Closing time, bestie. πŸŽ€

rsb_lib_exit should be called after having freed all matrices. If not all of the data structures were properly deallocated beforehand, this function may still attempt to finalize the library and return the RSB_ERR_MEMORY_LEAK error code β€” and whether it can even do that depends on the --enable-allocator-wrapper configure time option. Any allocated memory will be lost (librsb does not keep track of allocated matrices). 😭

Internal library state gets cleared. After this call, it is legal to initialize the library again by calling rsb_lib_init().

On an error, the library state may be inconsistent, so it is advisable to either terminate program execution (rather than forcing a new initialization with rsb_lib_init()). No cap, just end the program.

Parameter iop is reserved for future use; for now it is safe to pass RSB_NULL_EXIT_OPTIONS.

It should be safe to call rsb_lib_exit() more than once. Reuse queen. πŸ’…

Parameters

  • iop β€” a pointer to a rsb_initopts structure with library options. It may be NULL (or better, RSB_NULL_INIT_OPTIONS/RSB_NULL_EXIT_OPTIONS) for specifying default options.

Returns

RSB_ERR_NO_ERROR on correct operation, an error code otherwise. You can use rsb_strerror_r() or rsb_perror() to get more information about the error.

An example snippet declaring an error variable accumulator at program's beginning:

        rsb_err_t errval = RSB_ERR_NO_ERROR;

and finalizing the library at program's end:

        if((errval = rsb_lib_exit(RSB_NULL_EXIT_OPTIONS))
                != RSB_ERR_NO_ERROR)
        {
            printf("Error finalizing the library!\n");
            goto err;
        }

See also

rsb_lib_init, rsb_lib_set_opt_str, rsb_lib_reinit, rsb_lib_exit, rsb_lib_get_opt, rsb_lib_set_opt, or (deprecated) macros RSB_REINIT_SINGLE_VALUE_GET, RSB_REINIT_SINGLE_VALUE_SET, RSB_REINIT_SINGLE_VALUE, RSB_REINIT_SINGLE_VALUE_C_IOP..


rsb_lib_get_opt πŸ”

rsb_err_t rsb_lib_get_opt (enum rsb_opt_t iof, void * iop)

Gets the value of a library option. It's the "what's the setting rn" girlie. ✨

A value specified by the request flag iof will be fetched from the library internal state, and *iop will be updated accordingly.

Parameters

  • iof β€” library options flags. See rsb_opt_t for a list of valid options.
  • iop β€” library options value output pointer (the pointed location will be updated).

See also

RSB_REINIT_SINGLE_VALUE_GET, RSB_REINIT_SINGLE_VALUE_SET, RSB_REINIT_SINGLE_VALUE, RSB_REINIT_SINGLE_VALUE_C_IOP

rsb_lib_init, rsb_lib_set_opt_str, rsb_lib_reinit, rsb_lib_exit, rsb_lib_get_opt, rsb_lib_set_opt, or (deprecated) macros RSB_REINIT_SINGLE_VALUE_GET, RSB_REINIT_SINGLE_VALUE_SET, RSB_REINIT_SINGLE_VALUE, RSB_REINIT_SINGLE_VALUE_C_IOP..


rsb_lib_init πŸš€

rsb_err_t rsb_lib_init (struct rsb_initopts * iop)

This is the library initialization function. The main character moment of setup. 🌈

It must be called only once before using any other library function. It is allowed to call it again after rsb_lib_exit().

To fine-tune the library behaviour, one may specify a number of options via the iop parameter.

Options may also be specified after rsb_lib_init() by calling rsb_lib_reinit().

One may call RSB_REINIT_SINGLE_VALUE_GET with flag RSB_IO_WANT_IS_INITIALIZED_MARKER to verify whether the library has been initialized or not. Vibe check, essentially. πŸ’–

If the RSB_NUM_THREADS environment variable is set, rsb_lib_init() uses it and sets the number of active threads, thus overriding what's detected by the OpenMP runtime (e.g. OMP_NUM_THREADS). Yeah, it wins that argument.

Parameters

  • iop β€” a pointer to a rsb_initopts structure with library options. It may be NULL (or better, RSB_NULL_INIT_OPTIONS/RSB_NULL_EXIT_OPTIONS) for specifying default options.

Returns

RSB_ERR_NO_ERROR on correct operation, an error code otherwise. You can use rsb_strerror_r() or rsb_perror() to get more information about the error.

An example snippet declaring an error variable accumulator at program's beginning:

        rsb_err_t errval = RSB_ERR_NO_ERROR;

and initializing the library soon thereafter:

        if((errval = rsb_lib_init(RSB_NULL_INIT_OPTIONS)) !=
                RSB_ERR_NO_ERROR)
        {
            printf("Error initializing the library!\n");
            goto err;
        }

See also

rsb_lib_init, rsb_lib_set_opt_str, rsb_lib_reinit, rsb_lib_exit, rsb_lib_get_opt, rsb_lib_set_opt, or (deprecated) macros RSB_REINIT_SINGLE_VALUE_GET, RSB_REINIT_SINGLE_VALUE_SET, RSB_REINIT_SINGLE_VALUE, RSB_REINIT_SINGLE_VALUE_C_IOP..


rsb_lib_reinit πŸ”„

rsb_err_t rsb_lib_reinit (struct rsb_initopts * iop)

Changes the library operation options which were set at initialization time, either by a user or as defaults. Glow-up for your settings. πŸ’…

Not all options may be supported, depending on build time library settings.

If an unsupported option was specified, an appropriate error (e.g.: RSB_ERR_UNSUPPORTED_OPERATION) will be returned. Rude, but honest.

On the first error, option processing is interrupted and the remaining options (if any) are not processed. And program execution may continue safely even if an error code is returned (that is, library status should be consistent). So like, you're fine, just don't expect the rest of the list to have happened. 🫢

Parameters

  • iop β€” a pointer to a rsb_initopts structure with library options. It may be NULL (or better, RSB_NULL_INIT_OPTIONS/RSB_NULL_EXIT_OPTIONS) for specifying default options.

Returns

RSB_ERR_NO_ERROR on correct operation, an error code otherwise. You can use rsb_strerror_r() or rsb_perror() to get more information about the error.

        rsb_err_t errval = RSB_ERR_NO_ERROR;
        struct rsb_initopts io;

        rsb_int_t ione={1};
        enum rsb_opt_t keys[]={RSB_IO_WANT_EXTRA_VERBOSE_INTERFACE};
        void*values[]={&ione};
        io.action=RSB_IO_SPECIFIER_SET;
        io.keys=keys;
        io.values=values;
        io.n_pairs=1;

        if((errval = rsb_lib_init(RSB_NULL_INIT_OPTIONS))
                != RSB_ERR_NO_ERROR) goto err;

        // won't print anything
        if((errval = rsb_lib_reinit(&io))
                != RSB_ERR_NO_ERROR) goto err;

        // may print verbose message (depends on configure)
        if((errval = rsb_lib_reinit(NULL))
                != RSB_ERR_NO_ERROR) goto err;

        // may print verbose message (depends on configure)
        if((errval = rsb_lib_set_opt_str(
            "RSB_IO_WANT_EXTRA_VERBOSE_INTERFACE","0"))
                != RSB_ERR_NO_ERROR) goto err;

        // won't print anything anymore
        if((errval = rsb_lib_exit(&io))
                != RSB_ERR_NO_ERROR) goto err;

πŸ” See also

  • rsb_lib_init, rsb_lib_set_opt_str, rsb_lib_reinit, rsb_lib_exit, rsb_lib_get_opt, rsb_lib_set_opt, or (deprecated) macros RSB_REINIT_SINGLE_VALUE_GET, RSB_REINIT_SINGLE_VALUE_SET, RSB_REINIT_SINGLE_VALUE, RSB_REINIT_SINGLE_VALUE_C_IOP..

rsb_err_t rsb_lib_set_opt (enum rsb_opt_t iof, const void * iop)

Sets value of a library option.

okay so basically: whatever request flag you drop into iof, the library grabs the value sitting at *iop and uses it to update that option in the library's internal state. That's the whole vibe. πŸ’…

Parameters

  • iof β€” library options flags. Peep rsb_opt_t for the full list of valid options.
  • iop β€” library options value output pointer (pointed location will be updated).

Example snip:

                rsb_int_t evi=1;

                /* Setting a single optional library parameter. */
                errval = rsb_lib_set_opt(
                        RSB_IO_WANT_EXTRA_VERBOSE_INTERFACE, &evi);
                if(errval != RSB_ERR_NO_ERROR)
                {
                       /*! [Copy error message to string] */
                        char errbuf[256];
                        rsb_strerror_r(errval,&errbuf[0],sizeof(errbuf));
                        printf("Failed setting the"
                        " RSB_IO_WANT_EXTRA_VERBOSE_INTERFACE"
                        " library option (reason string:\n%s).\n",errbuf);
                       /*! [Copy error message to string] */
                        if(errval&RSB_ERRS_UNSUPPORTED_FEATURES)
                        {
                          printf("This error may be safely ignored.\n");
                        }
                        else
                        {
                          printf("Some unexpected error occurred!\n");
                          goto err;
                        }
                }
                else
                {
                        printf("Setting back the "
                                "RSB_IO_WANT_EXTRA_VERBOSE_INTERFACE"
                                " library option.\n");
                        evi = 0;
                        errval = rsb_lib_set_opt(RSB_IO_WANT_EXTRA_VERBOSE_INTERFACE,
                                        &evi);
                        errval = RSB_ERR_NO_ERROR;
                }

πŸ” See also

  • RSB_REINIT_SINGLE_VALUE_GET, RSB_REINIT_SINGLE_VALUE_SET, RSB_REINIT_SINGLE_VALUE, RSB_REINIT_SINGLE_VALUE_C_IOP
  • rsb_lib_init, rsb_lib_set_opt_str, rsb_lib_reinit, rsb_lib_exit, rsb_lib_get_opt, rsb_lib_set_opt, or (deprecated) macros RSB_REINIT_SINGLE_VALUE_GET, RSB_REINIT_SINGLE_VALUE_SET, RSB_REINIT_SINGLE_VALUE, RSB_REINIT_SINGLE_VALUE_C_IOP..

rsb_err_t rsb_lib_set_opt_str (const rsb_char_t * opnp, const rsb_char_t * opvp)

Specifies individual library options in order to fine-tune the library behaviour.

fr fr both the option name and the value have to be strings, and they gotta match their preprocessor identifiers exactly (go look at rsb_opt_t ). The opnp string gets translated internally into the corresponding request flag values, and whatever you passed in opvp gets parsed out of it. it's giving stringly-typed but make it fashion πŸŽ€

Parameters

  • opnp β€” A pointer to a library option input name string (may not be NULL).
  • opvp β€” A pointer to a library option input value string (may not be NULL).

Returns

RSB_ERR_NO_ERROR on correct operation, an error code otherwise. You can use rsb_strerror_r() or rsb_perror() to get more information about the error. 🫢

    rsb_err_t errval = RSB_ERR_NO_ERROR;
    struct rsb_initopts io;

    rsb_int_t ione={1};
    enum rsb_opt_t keys[]={RSB_IO_WANT_EXTRA_VERBOSE_INTERFACE};
    void*values[]={&ione};
    io.action=RSB_IO_SPECIFIER_SET;
    io.keys=keys;
    io.values=values;
    io.n_pairs=1;

    if((errval = rsb_lib_init(RSB_NULL_INIT_OPTIONS))
                    != RSB_ERR_NO_ERROR) goto err;

    // won't print anything
    if((errval = rsb_lib_reinit(&io))
                    != RSB_ERR_NO_ERROR) goto err;

    // may print verbose message (depends on configure)
    if((errval = rsb_lib_reinit(NULL))
                    != RSB_ERR_NO_ERROR) goto err;

    // may print verbose message (depends on configure)
    if((errval = rsb_lib_set_opt_str(
            "RSB_IO_WANT_EXTRA_VERBOSE_INTERFACE","0"))
                    != RSB_ERR_NO_ERROR) goto err;

    // won't print anything anymore
    if((errval = rsb_lib_exit(&io))
                    != RSB_ERR_NO_ERROR) goto err;

πŸ” See also

  • rsb_lib_init, rsb_lib_set_opt_str, rsb_lib_reinit, rsb_lib_exit, rsb_lib_get_opt, rsb_lib_set_opt, or (deprecated) macros RSB_REINIT_SINGLE_VALUE_GET, RSB_REINIT_SINGLE_VALUE_SET, RSB_REINIT_SINGLE_VALUE, RSB_REINIT_SINGLE_VALUE_C_IOP..

rsb_err_t rsb_mtx_add_to_dense (const void * alphap, const struct rsb_mtx_t * mtxAp, rsb_nnz_idx_t ldB, rsb_nnz_idx_t nrB, rsb_nnz_idx_t ncB, rsb_bool_t rowmajorB, void * Bp)

Dense matrix B is updated by adding scaled sparse matrix ${A}$ to it: $B <- B + alpha {A} $

no cap, it's just ✨accumulation✨

Parameters

  • alphap β€” Optional pointer (if NULL, will default to 1) to a numerical value (of the same type as matrix).
  • mtxAp β€” Valid rsb_mtx_t pointer to matrix $A$ representation.
  • ldB β€” Leading dimension of Bp array.
  • nrB,ncB β€” The number of rows and columns for the dense matrix $B$.
  • rowmajorB β€” RSB_BOOL_TRUE if the dense matrix $B$ is considered stored as row major, or RSB_BOOL_FALSE if as column major.
  • Bp β€” Array representing the dense matrix $B$.

Returns

RSB_ERR_NO_ERROR on correct operation, an error code otherwise. You can use rsb_strerror_r() or rsb_perror() to get more information about the error. 😭

Example snip:

        const rsb_nnz_idx_t ldB = 4, nrB = 3, ncB = 3;
        const rsb_bool_t rowmajorB = RSB_BOOL_TRUE;
        RSB_DEFAULT_TYPE Bp[ /*ldB*nrB*/ ] = {
                -1, -1, -1, -1,
                -1, -1, -1, -1,
                -1, -1, -1, -1
        };
        RSB_DEFAULT_TYPE *alphap = NULL;

        errval = rsb_mtx_add_to_dense(alphap, mtxAp, ldB,
                 nrB, ncB, rowmajorB, Bp);
        if(errval != RSB_ERR_NO_ERROR )
        {
                printf("Error calling rsb_mtx_add_to_dense!\n");
                goto err;
        }

Note

Please note that it suffices to 'transpose' Bp's description parameters to get $A$ transposed summed in. πŸ”„

Symmetry is currently not expanded.

Threaded, for large enough matrices. 🧡

πŸ” See also

  • rsb_spmsp_to_dense, rsb_sppsp, rsb_spmsp, rsb_mtx_add_to_dense

struct rsb_mtx_t * rsb_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 flagsA, rsb_err_t * errvalp)

Creates an empty matrix structure in assembly state. The user then populates it using rsb_mtx_set_vals() repeatedly; then assembles it with rsb_mtx_alloc_from_coo_end().

bestie this is the two-step build, okay? you start her up empty, feed her values, then seal the deal. 🌸

Parameters

  • nnzA β€” A rough estimate of the number of nonzeroes matrix $A$ will host (used for optimizing arrays allocation). If you do not know yet, you can specify zero.
  • typecode β€” A valid type code for the given (numerical array) input pointer (see matrix_type_symbols_section).
  • nrA,ncA β€” The number of rows and columns of the sparse matrix $A$.
  • flagsA β€” A valid combination of index conversion and matrix storage flags and other meaningful flags.
  • The encouraged base choice here is RSB_FLAG_DEFAULT_RSB_MATRIX_FLAGS. If Fortran (1 based) indices are being used for the IA, JA arrays, then the RSB_FLAG_FORTRAN_INDICES_INTERFACE flag should be added. If symmetric storage is desired, then RSB_FLAG_SYMMETRIC (or RSB_FLAG_HERMITIAN, for Hermitian matrices) is necessary, in combination with either RSB_FLAG_LOWER or RSB_FLAG_UPPER. If you intend to use this matrix for triangular solution (e.g.: rsb_spsv()/rsb_spsm()), it needs to be triangular and specified with either RSB_FLAG_LOWER_TRIANGULAR or RSB_FLAG_UPPER_TRIANGULAR, and not have RSB_FLAG_LOWER_SYMMETRIC or RSB_FLAG_LOWER_HERMITIAN. Nonzeroes non complying with the specified flags will be ignored. If a matrix is both RSB_FLAG_LOWER_TRIANGULAR and RSB_FLAG_UPPER_TRIANGULAR at the same time, then it's diagonal, for which shorthand: RSB_FLAG_DIAGONAL can be used. If RSB_FLAG_UNIT_DIAG_IMPLICIT is present, diagonal entries will be not represented but assumed to be unitary. If RSB_FLAG_DUPLICATES_SUM is present, duplicate entries will be summed together. If RSB_FLAG_DISCARD_ZEROS is present, zeroes will be discarded.
  • errvalp β€” An optional (can be NULL) pointer to rsb_err_t where the error status will be written to.

Returns

Pointer to a rsb_mtx_t matrix structure in assembly state, or NULL (on error).

Warning

This function has not been thoroughly tested. πŸ™ˆ

πŸ” See also

  • rsb_mtx_alloc_from_coo_const, rsb_mtx_alloc_from_coo_inplace, rsb_mtx_free, rsb_mtx_clone, rsb_mtx_alloc_from_csr_const, rsb_mtx_alloc_from_csc_const, rsb_mtx_alloc_from_csr_inplace, rsb_mtx_switch_to_csr, rsb_mtx_alloc_from_coo_begin, rsb_mtx_alloc_from_coo_end

struct rsb_mtx_t * rsb_mtx_alloc_from_coo_const (const void * VA, const rsb_coo_idx_t * IA, const 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)

Given as input COO arrays VA,IA,JA, allocates and assembles an RSB matrix using separate arrays. πŸ¦‹

✨ Parameters ✨

  • VA,IA,JA β€” bestie these are ur input arrays: VA holds the numerical values, IA holds the row indices and JA holds the column indices. trio of icons fr 🫢
  • nnzA β€” the number of nonzeroes in the input arrays representing matrix $A$. no cap, count them all.
  • typecode β€” a valid type code for the given (numerical array) input pointer (peep the matrix_type_symbols_section if u need the lore). πŸ’œ
  • nrA,ncA β€” the number of rows and columns of the sparse matrix $A$. and here's the lil plot twist: if either nrA or ncA is zero, it gets detected on the basis of the IA and JA arrays and flagsA. slay, it figures it out itself.
  • brA,bcA β€” the blocking parameters. brA should be set to 1 or RSB_DEFAULT_ROW_BLOCKING (currently unused, reserved for future use); bcA should be set to 1 or RSB_DEFAULT_ROW_BLOCKING (currently unused, reserved for future use). so basically rn they're just chillin, reserved for later πŸ‘‘
  • flagsA β€” a valid combination of index conversion and matrix storage flags and other meaningful flags. okay bestie this one has LAYERS so let's go:

The encouraged base choice here is RSB_FLAG_DEFAULT_RSB_MATRIX_FLAGS. If Fortran (1 based) indices are being used for the IA, JA arrays, then the RSB_FLAG_FORTRAN_INDICES_INTERFACE flag should be added. If symmetric storage is desired, then RSB_FLAG_SYMMETRIC (or RSB_FLAG_HERMITIAN, for Hermitian matrices) is necessary, in combination with either RSB_FLAG_LOWER or RSB_FLAG_UPPER. If you intend to use this matrix for triangular solution (e.g.: rsb_spsv()/rsb_spsm()), it needs to be triangular and specified with either RSB_FLAG_LOWER_TRIANGULAR or RSB_FLAG_UPPER_TRIANGULAR, and not have RSB_FLAG_LOWER_SYMMETRIC or RSB_FLAG_LOWER_HERMITIAN. Nonzeroes non complying with the specified flags will be ignored. If a matrix is both RSB_FLAG_LOWER_TRIANGULAR and RSB_FLAG_UPPER_TRIANGULAR at the same time, then it's diagonal, for which shorthand: RSB_FLAG_DIAGONAL can be used. If RSB_FLAG_UNIT_DIAG_IMPLICIT is present, diagonal entries will be not represented but assumed to be unitary. If RSB_FLAG_DUPLICATES_SUM is present, duplicate entries will be summed together. If RSB_FLAG_DISCARD_ZEROS is present, zeroes will be discarded. πŸ’…

  • errvalp β€” an optional (can be NULL) pointer to rsb_err_t where the error status will be written to. it's giving "tell me what went wrong" energy πŸŽ€

✨ Returns ✨

On success, a valid pointer (struct rsb_mtx_t*) to the newly allocated matrix structure; on error, NULL. literally that simple, icon behavior 🌟

✨ Example snip ✨

    mtxAp = rsb_mtx_alloc_from_coo_const(
            VA,IA,JA,nnzA,typecode,nrA,ncA,
            brA,bcA,RSB_FLAG_NOFLAGS,NULL);
    if(!mtxAp)
    {
        return EXIT_FAILURE;
    }

And another one, this time with the duplicate sum flags, bc we love a summed dupe era:

    mtxAp = rsb_mtx_alloc_from_coo_const(
        VA,IA,JA,nnzA,typecode,nrA,ncA,brA,bcA,
        RSB_FLAG_NOFLAGS    /* default format will be chosen */
        |RSB_FLAG_DUPLICATES_SUM/* duplicates will be summed */
            ,&errval);
    if((!mtxAp) || (errval != RSB_ERR_NO_ERROR))
    {
        printf("Error while allocating the matrix!\n");
        goto err;
    }

And yet another, and this one's allocating a triangular matrix (main character behavior tbh):

    mtxAp = rsb_mtx_alloc_from_coo_const(
        VA,IA,JA,nnzA,typecode,nrA,ncA,brA,bcA,
        RSB_FLAG_DEFAULT_RSB_MATRIX_FLAGS /* force rsb */
        | RSB_FLAG_DUPLICATES_SUM/* sum dups */
        | RSB_FLAG_UNIT_DIAG_IMPLICIT/* ask diagonal implicit */
        | RSB_FLAG_TRIANGULAR /* need triangle for spsv */
        , &errval);
    if((!mtxAp) || (errval != RSB_ERR_NO_ERROR))
    {
        printf("Error while allocating the matrix!\n");
        goto err;
    }
    printf("Correctly allocated a matrix with %ld nonzeroes.\n",
        (long int)nnzA);

✨ See also ✨

rsb_mtx_alloc_from_coo_const, rsb_mtx_alloc_from_coo_inplace, rsb_mtx_free, rsb_mtx_clone, rsb_mtx_alloc_from_csr_const, rsb_mtx_alloc_from_csc_const, rsb_mtx_alloc_from_csr_inplace, rsb_mtx_switch_to_csr, rsb_mtx_alloc_from_coo_begin, rsb_mtx_alloc_from_coo_end


rsb_err_t rsb_mtx_alloc_from_coo_end (struct rsb_mtx_t ** mtxApp)

Okay so this one assembles the RSB arrays for a matrix that's in build state β€” like, a matrix that was created with rsb_mtx_alloc_from_coo_begin() and then populated with rsb_mtx_set_vals(). Once the assembly is done, any operation on the matrix is allowed. it's the glow-up moment βœ¨πŸ¦‹

Parameters

  • mtxApp β€” a rsb_mtx_t pointer to an unassembled matrix address. hand it the address bestie πŸ’–

Returns

RSB_ERR_NO_ERROR on correct operation, an error code otherwise. You can use rsb_strerror_r() or rsb_perror() to get more information about the error. slay, the diagnostics are there for u.

Warning

This function has not been thoroughly tested. 😭 so like, tread carefully bestie, no cap.

Note

Note that the memory location of the matrix will be changed by this call, and the (old) *mtxApp address value will be not valid anymore. so don't go holding onto that old pointer, it's giving expired πŸ’€

See also

rsb_mtx_alloc_from_coo_const, rsb_mtx_alloc_from_coo_inplace, rsb_mtx_free, rsb_mtx_clone, rsb_mtx_alloc_from_csr_const, rsb_mtx_alloc_from_csc_const, rsb_mtx_alloc_from_csr_inplace, rsb_mtx_switch_to_csr, rsb_mtx_alloc_from_coo_begin, rsb_mtx_alloc_from_coo_end


struct rsb_mtx_t * rsb_mtx_alloc_from_coo_inplace (void * VA, rsb_coo_idx_t * IA, 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)

Given the COO arrays VA,IA,JA as input, this allocates and assembles an RSB matrix while reusing the input arrays. recycling era, we love to see it 🌈

It assumes all three VA,IA,JA arrays are at least max(nnzA,nrA+1,ncA+1) sized. The user is expected NOT to use these arrays until the matrix has been destroyed with rsb_mtx_free(). Then, it is possible to use these arrays again. so like, hands off until the matrix is gone, periodt πŸ™ˆ

Parameters

  • VA,IA,JA β€” input/output numerical values array (VA); row (IA) and column (JA) indices arrays. yeah they're in/out now, things change πŸ’…
  • nnzA β€” the number of nonzeroes in the input arrays representing matrix $A$.
  • typecode β€” a valid type code for the given (numerical array) input pointer (see matrix_type_symbols_section).
  • nrA,ncA β€” the number of rows and columns of the sparse matrix $A$.
  • brA,bcA β€” blocking parameters: brA should be set to 1 or RSB_DEFAULT_ROW_BLOCKING (currently unused, reserved for future use); bcA should be set to 1 or RSB_DEFAULT_ROW_BLOCKING (currently unused, reserved for future use).
  • flagsA β€” a valid combination of index conversion and matrix storage flags and other meaningful flags.

The encouraged base choice here is RSB_FLAG_DEFAULT_RSB_MATRIX_FLAGS. If Fortran (1 based) indices are being used for the IA, JA arrays, then the RSB_FLAG_FORTRAN_INDICES_INTERFACE flag should be added. If symmetric storage is desired, then RSB_FLAG_SYMMETRIC (or RSB_FLAG_HERMITIAN, for Hermitian matrices) is necessary, in combination with either RSB_FLAG_LOWER or RSB_FLAG_UPPER. If you intend to use this matrix for triangular solution (e.g.: rsb_spsv()/rsb_spsm()), it needs to be triangular and specified with either RSB_FLAG_LOWER_TRIANGULAR or RSB_FLAG_UPPER_TRIANGULAR, and not have RSB_FLAG_LOWER_SYMMETRIC or RSB_FLAG_LOWER_HERMITIAN. Nonzeroes non complying with the specified flags will be ignored. If a matrix is both RSB_FLAG_LOWER_TRIANGULAR and RSB_FLAG_UPPER_TRIANGULAR at the same time, then it's diagonal, for which shorthand: RSB_FLAG_DIAGONAL can be used. If RSB_FLAG_UNIT_DIAG_IMPLICIT is present, diagonal entries will be not represented but assumed to be unitary. If RSB_FLAG_DUPLICATES_SUM is present, duplicate entries will be summed together. If RSB_FLAG_DISCARD_ZEROS is present, zeroes will be discarded. πŸŽ€

  • errvalp β€” an optional (can be NULL) pointer to rsb_err_t where the error status will be written to.

Returns

On success, a valid pointer (struct rsb_mtx_t*) to the newly allocated matrix structure; on error, NULL. πŸ’œ

See also

rsb_mtx_alloc_from_coo_const, rsb_mtx_alloc_from_coo_inplace, rsb_mtx_free, rsb_mtx_clone, rsb_mtx_alloc_from_csr_const, rsb_mtx_alloc_from_csc_const, rsb_mtx_alloc_from_csr_inplace, rsb_mtx_switch_to_csr, rsb_mtx_alloc_from_coo_begin, rsb_mtx_alloc_from_coo_end


struct rsb_mtx_t * rsb_mtx_alloc_from_csc_const (const void * VA, const rsb_coo_idx_t * IA, const rsb_coo_idx_t * CP, 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)

Given input read only CSC format arrays, this allocates and assembles an RSB matrix (stored in separate arrays). const and read-only, so hands off the originals bestie, we're building u something new πŸ¦‹βœ¨

okay so here's what every single one of these params actually does, bestie, read carefully:

  • VA,IA,CP β€” the input numerical values array (VA), the input row indices array (IA), and the compressed column indices array (CP). the whole squad 🫢
  • nnzA β€” the number of nonzeroes in the input arrays representing matrix $A$. count 'em.
  • typecode β€” a valid type code for the given (numerical array) input pointer (peep matrix_type_symbols_section).
  • nrA,ncA β€” the number of rows and columns of the sparse matrix $A$.
  • brA,bcA β€” blocking parameters: brA should be set to 1 or RSB_DEFAULT_ROW_BLOCKING (currently unused, reserved for future use); bcA should be set to 1 or RSB_DEFAULT_ROW_BLOCKING (currently unused, reserved for future use). yeah both of them are literally just vibing in the reserved-for-future-use era rn πŸ’€
  • flagsA β€” a valid combination of index conversion and matrix storage flags and other meaningful flags.

the encouraged base choice here is RSB_FLAG_DEFAULT_RSB_MATRIX_FLAGS. if Fortran (1 based) indices are being used for the IA, JA arrays, then the RSB_FLAG_FORTRAN_INDICES_INTERFACE flag should be added. if symmetric storage is desired, then RSB_FLAG_SYMMETRIC (or RSB_FLAG_HERMITIAN, for Hermitian matrices β€” hermitian girlies rise 🌈) is necessary, in combination with either RSB_FLAG_LOWER or RSB_FLAG_UPPER. if you intend to use this matrix for triangular solution (e.g.: rsb_spsv()/rsb_spsm()), it needs to be triangular and specified with either RSB_FLAG_LOWER_TRIANGULAR or RSB_FLAG_UPPER_TRIANGULAR, and not have RSB_FLAG_LOWER_SYMMETRIC or RSB_FLAG_LOWER_HERMITIAN. nonzeroes non complying with the specified flags will be ignored. if a matrix is both RSB_FLAG_LOWER_TRIANGULAR and RSB_FLAG_UPPER_TRIANGULAR at the same time, then it's diagonal, for which shorthand: RSB_FLAG_DIAGONAL can be used. if RSB_FLAG_UNIT_DIAG_IMPLICIT is present, diagonal entries will be not represented but assumed to be unitary. if RSB_FLAG_DUPLICATES_SUM is present, duplicate entries will be summed together. if RSB_FLAG_DISCARD_ZEROS is present, zeroes will be discarded. periodt. ✨

  • errvalp β€” an optional (can be NULL) pointer to rsb_err_t where the error status will be written to. she's optional, she's fine with NULL, she contains multitudes.

πŸ’« Returns πŸ’«

on success, a valid pointer (struct rsb_mtx_t*) to the newly allocated matrix structure; on error, NULL. that's it. that's the whole range of emotion. 😭

πŸ¦‹ See also πŸ¦‹

rsb_mtx_alloc_from_coo_const, rsb_mtx_alloc_from_coo_inplace, rsb_mtx_free, rsb_mtx_clone, rsb_mtx_alloc_from_csr_const, rsb_mtx_alloc_from_csc_const, rsb_mtx_alloc_from_csr_inplace, rsb_mtx_switch_to_csr, rsb_mtx_alloc_from_coo_begin, rsb_mtx_alloc_from_coo_end β€” the whole clique, go say hi πŸ’œ

πŸŽ€ Example: πŸŽ€

    rsb_err_t errval = RSB_ERR_NO_ERROR;
    struct rsb_mtx_t *mtxAp = NULL;
    const rsb_blk_idx_t brA = RSB_DEFAULT_BLOCKING,
                bcA = RSB_DEFAULT_BLOCKING;
    const rsb_nnz_idx_t nnzA = 4;
    const rsb_coo_idx_t  nrA = 3;
    const rsb_coo_idx_t  ncA = 3;
    const rsb_coo_idx_t    IA[] = { 0, 2, 1, 2 };
    const rsb_coo_idx_t    CP[] = { 0, 2, 3, 4 };
    const RSB_DEFAULT_TYPE VA[] = { 11, 31, 22, 33 };
    const rsb_type_t typecode = RSB_NUMERICAL_TYPE_DEFAULT;

    if(rsb_lib_init(RSB_NULL_INIT_OPTIONS)!=RSB_ERR_NO_ERROR)
    {
        return EXIT_FAILURE;
    }

    mtxAp = rsb_mtx_alloc_from_csc_const(
            VA,IA,CP,nnzA,typecode,nrA,ncA,
            brA,bcA,RSB_FLAG_NOFLAGS,NULL);
    if(!mtxAp)
    {
        return EXIT_FAILURE;
    }

    rsb_file_mtx_save(mtxAp, NULL);

🌟 struct rsb_mtx_t * rsb_mtx_alloc_from_csr_const (const void * VA, const rsb_coo_idx_t * RP, const 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) 🌟

given input read only CSR format arrays, allocates and assembles an RSB matrix (stored in separate arrays). const-correct king behavior, honestly πŸ‘‘

🌸 Parameters 🌸

  • VA,RP,JA β€” input numerical values (VA) array; compressed rows (RP) and column (JA) input indices arrays.
  • nnzA β€” the number of nonzeroes in the input arrays representing matrix $A$.
  • typecode β€” a valid type code for the given (numerical array) input pointer (peep matrix_type_symbols_section).
  • nrA,ncA β€” the number of rows and columns of the sparse matrix $A$.
  • brA,bcA β€” blocking parameters: brA should be set to 1 or RSB_DEFAULT_ROW_BLOCKING (currently unused, reserved for future use); bcA should be set to 1 or RSB_DEFAULT_ROW_BLOCKING (currently unused, reserved for future use).
  • flagsA β€” a valid combination of index conversion and matrix storage flags and other meaningful flags.

the encouraged base choice here is RSB_FLAG_DEFAULT_RSB_MATRIX_FLAGS. if Fortran (1 based) indices are being used for the IA, JA arrays, then the RSB_FLAG_FORTRAN_INDICES_INTERFACE flag should be added. if symmetric storage is desired, then RSB_FLAG_SYMMETRIC (or RSB_FLAG_HERMITIAN, for Hermitian matrices) is necessary, in combination with either RSB_FLAG_LOWER or RSB_FLAG_UPPER. if you intend to use this matrix for triangular solution (e.g.: rsb_spsv()/rsb_spsm()), it needs to be triangular and specified with either RSB_FLAG_LOWER_TRIANGULAR or RSB_FLAG_UPPER_TRIANGULAR, and not have RSB_FLAG_LOWER_SYMMETRIC or RSB_FLAG_LOWER_HERMITIAN. nonzeroes non complying with the specified flags will be ignored. if a matrix is both RSB_FLAG_LOWER_TRIANGULAR and RSB_FLAG_UPPER_TRIANGULAR at the same time, then it's diagonal, for which shorthand: RSB_FLAG_DIAGONAL can be used. if RSB_FLAG_UNIT_DIAG_IMPLICIT is present, diagonal entries will be not represented but assumed to be unitary. if RSB_FLAG_DUPLICATES_SUM is present, duplicate entries will be summed together. if RSB_FLAG_DISCARD_ZEROS is present, zeroes will be discarded.

  • errvalp β€” an optional (can be NULL) pointer to rsb_err_t where the error status will be written to.

πŸ’« Returns πŸ’«

on success, a valid pointer (struct rsb_mtx_t*) to the newly allocated matrix structure; on error, NULL.

πŸ¦‹ See also πŸ¦‹

rsb_mtx_alloc_from_coo_const, rsb_mtx_alloc_from_coo_inplace, rsb_mtx_free, rsb_mtx_clone, rsb_mtx_alloc_from_csr_const, rsb_mtx_alloc_from_csc_const, rsb_mtx_alloc_from_csr_inplace, rsb_mtx_switch_to_csr, rsb_mtx_alloc_from_coo_begin, rsb_mtx_alloc_from_coo_end


πŸ”₯ struct rsb_mtx_t * rsb_mtx_alloc_from_csr_inplace (void * VA, rsb_nnz_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) πŸ”₯

given as input CSR arrays VA,RP,JA , allocates and assembles an RSB matrix reusing input arrays. in-place girlies, this one's for you πŸ’…

⚠️ assumes all three VA,IA,JA arrays are at least max(nnzA,nrA+1,ncA+1) sized. the user is expected NOT to use these arrays until the matrix has been destroyed with rsb_mtx_free(). then, it is possible to use these arrays again. so like… hands off until she says so, okay?? no cap. πŸ™ˆ

🌸 Parameters 🌸

  • VA,RP,JA β€” input numerical values (VA) array; compressed rows (RP) and column (JA) input indices arrays. will not be freed by rsb_mtx_free().
  • nnzA β€” the number of nonzeroes in the input arrays representing matrix $A$.
  • typecode β€” a valid type code for the given (numerical array) input pointer (peep matrix_type_symbols_section).
  • nrA,ncA β€” the number of rows and columns of the sparse matrix $A$.
  • brA,bcA β€” blocking parameters: brA should be set to 1 or RSB_DEFAULT_ROW_BLOCKING (currently unused, reserved for future use); bcA should be set to 1 or RSB_DEFAULT_ROW_BLOCKING (currently unused, reserved for future use).
  • flagsA β€” a valid combination of index conversion and matrix storage flags and other meaningful flags.

the encouraged base choice here is RSB_FLAG_DEFAULT_RSB_MATRIX_FLAGS. if Fortran (1 based) indices are being used for the IA, JA arrays, then the RSB_FLAG_FORTRAN_INDICES_INTERFACE flag should be added. if symmetric storage is desired, then RSB_FLAG_SYMMETRIC (or RSB_FLAG_HERMITIAN, for Hermitian matrices) is necessary, in combination with either RSB_FLAG_LOWER or RSB_FLAG_UPPER. if you intend to use this matrix for triangular solution (e.g.: rsb_spsv()/rsb_spsm()), it needs to be triangular and specified with either RSB_FLAG_LOWER_TRIANGULAR or RSB_FLAG_UPPER_TRIANGULAR, and not have RSB_FLAG_LOWER_SYMMETRIC or RSB_FLAG_LOWER_HERMITIAN. nonzeroes non complying with the specified flags will be ignored. if a matrix is both RSB_FLAG_LOWER_TRIANGULAR and RSB_FLAG_UPPER_TRIANGULAR at the same time, then it's diagonal, for which shorthand: RSB_FLAG_DIAGONAL can be used. if RSB_FLAG_UNIT_DIAG_IMPLICIT is present, diagonal entries will be not represented but assumed to be unitary. if RSB_FLAG_DUPLICATES_SUM is present, duplicate entries will be summed together. if RSB_FLAG_DISCARD_ZEROS is present, zeroes will be discarded.

  • errvalp β€” an optional (can be NULL) pointer to rsb_err_t where the error status will be written to.

πŸ’« Returns πŸ’«

on success, a valid pointer (struct rsb_mtx_t*) to the newly allocated matrix structure; on error, NULL.

πŸ¦‹ See also πŸ¦‹

rsb_mtx_alloc_from_coo_const, rsb_mtx_alloc_from_coo_inplace, rsb_mtx_free, rsb_mtx_clone, rsb_mtx_alloc_from_csr_const, rsb_mtx_alloc_from_csc_const, rsb_mtx_alloc_from_csr_inplace, rsb_mtx_switch_to_csr, rsb_mtx_alloc_from_coo_begin, rsb_mtx_alloc_from_coo_end


πŸ‘‘ rsb_err_t rsb_mtx_clone (struct rsb_mtx_t ** mtxBpp, rsb_type_t typecode, rsb_trans_t transA, const void * alphap, const struct rsb_mtx_t * mtxAp, rsb_flags_t flags) πŸ‘‘

this function clones a given matrix, allocating a fresh data structure or overwriting an existing one. copy-paste but make it ✨elegant✨

target type (specified by typecode) can be different from that in the matrix. if alphap=NULL, the cloned matrix will not be scaled. no alphap, no scaling, simple as that πŸ“

this new structure will be completely separated and independent from the original one. fully her own main character, no enmeshment, we love to see it 🌈

Examples:

// will clone the matrix exactly
errval = rsb_mtx_clone(&mtxBp,RSB_NUMERICAL_TYPE_SAME_TYPE,RSB_TRANSPOSITION_N,NULL,mtxAp,RSB_FLAG_IDENTICAL_FLAGS);
// will clone the transpose of the matrix
errval = rsb_mtx_clone(&mtxBp,RSB_NUMERICAL_TYPE_SAME_TYPE,RSB_TRANSPOSITION_T,NULL,mtxAp,RSB_FLAG_IDENTICAL_FLAGS);
// will clone the lower triangle of the matrix
errval = rsb_mtx_clone(&mtxBp,RSB_NUMERICAL_TYPE_SAME_TYPE,RSB_TRANSPOSITION_N,NULL,mtxAp,RSB_FLAG_TRIANGULAR|RSB_FLAG_LOWER);

like, three whole moods of clone in one little snippet πŸ’… one's a straight copy, one's the transpose, one's just the lower triangle. pick your fighter, bestie.

Parameters πŸŽ€

  • mtxBpp β€” a valid rsb_mtx_t pointer to an address for matrix $B$ (the clone destination, bestie). If *mtxBpp==NULL, a shiny fresh clone gets assigned right there; if it's not NULL, the existing matrix structure gets freed first and then re-allocated to host the new one. And yes, the case *mtxBpp==mtxAp is supported β€” cloning onto yourself is allowed, iconique.
  • typecode β€” a valid type code for the output matrix you want (peep matrix_type_symbols_section).
  • transA β€” the transposition parameter for $A$ (see matrix_transposition_flags_section).
  • alphap β€” optional pointer for scaling the output (if it's NULL, it just defaults to 1). Of the type code of mtxAp. πŸ“
  • mtxAp β€” valid rsb_mtx_t pointer to the $A$ matrix representation.
  • flags β€” either RSB_FLAG_IDENTICAL_FLAGS or some combo of other flags, e.g.: RSB_FLAG_C_INDICES_INTERFACE, RSB_FLAG_SYMMETRIC, RSB_FLAG_HERMITIAN, RSB_FLAG_TRIANGULAR, RSB_FLAG_UPPER, RSB_FLAG_LOWER, RSB_FLAG_UNIT_DIAG_IMPLICIT, RSB_FLAG_DISCARD_ZEROS.
Careful bestie!! 🚨 The flag RSB_FLAG_EXTERNALLY_ALLOCATED_ARRAYS is forbidden here, no cap. And RSB_FLAG_FORTRAN_INDICES_INTERFACE just gets ignored, like it's not even in the room.

Returns ✨

RSB_ERR_NO_ERROR when everything goes right, an error code otherwise. Want the tea on what went wrong? Hit up rsb_strerror_r() or rsb_perror(). 🫢

Example snip πŸ’–

if( RSB_ERR_NO_ERROR != (errval =
        rsb_mtx_clone(&mtxAp,RSB_NUMERICAL_TYPE_SAME_TYPE,
        RSB_TRANSPOSITION_T,NULL,mtxAp,RSB_FLAG_IDENTICAL_FLAGS)))
{
        goto err;
}

See also 🌸

rsb_mtx_alloc_from_coo_const, rsb_mtx_alloc_from_coo_inplace, rsb_mtx_free, rsb_mtx_clone, rsb_mtx_alloc_from_csr_const, rsb_mtx_alloc_from_csc_const, rsb_mtx_alloc_from_csr_inplace, rsb_mtx_switch_to_csr, rsb_mtx_alloc_from_coo_begin, rsb_mtx_alloc_from_coo_end


struct rsb_mtx_t * rsb_mtx_free (struct rsb_mtx_t * mtxAp) 🧚

Frees a sparse matrix structure that was previously allocated. like, it's the cleanup era and we're letting it go bestie πŸ¦‹

Heads up though: if the matrix rocks the RSB_FLAG_EXTERNALLY_ALLOCATED_ARRAYS flag, then the three main data arrays VA, IA, JA will NOT be freed by rsb_mtx_free β€” because they were never yours to begin with, they came from outside (peep rsb_mtx_alloc_from_coo_inplace,rsb_mtx_alloc_from_csr_inplace). πŸ’€

Parameters πŸŽ€

  • mtxAp β€” valid rsb_mtx_t pointer to the $A$ matrix representation.

Returns ✨

Always NULL. periodt. (convenient for chaining, lowkey thoughtful)

Example freeing a sparse matrix 🌈

rsb_mtx_free(mtxAp);

See also 🌸

rsb_mtx_alloc_from_coo_const, rsb_mtx_alloc_from_coo_inplace, rsb_mtx_free, rsb_mtx_clone, rsb_mtx_alloc_from_csr_const, rsb_mtx_alloc_from_csc_const, rsb_mtx_alloc_from_csr_inplace, rsb_mtx_switch_to_csr, rsb_mtx_alloc_from_coo_begin, rsb_mtx_alloc_from_coo_end


rsb_err_t rsb_mtx_get_coo (const struct rsb_mtx_t * mtxAp, void * VA, rsb_coo_idx_t * IA, rsb_coo_idx_t * JA, rsb_flags_t flags) πŸ“

Hands you back the matrix converted into a coordinate storage format. COO girlie era, we love to see it 😌

Elements get stored in no particular order β€” it's giving chaos but make it valid. And if there are structural or fill-in zero elements hanging around? They get skipped, bye. ✌️

It writes exactly as many entries as there are nonzeroes. So to figure out how many arrays to allocate, you do this whole thing:

rsb_mtx_get_info(mtxAp,RSB_MIF_MATRIX_NNZ__TO__RSB_NNZ_INDEX_T,&nnz)

...to find out how many, so your arrays are sized correctly. πŸŽ€

Parameters πŸŽ€

  • mtxAp β€” valid rsb_mtx_t pointer to the $A$ matrix representation.
  • VA,IA,JA β€” the output numerical values (VA) array, plus output row (IA) and column (JA) indices arrays.
  • flags β€” either RSB_FLAG_FORTRAN_INDICES_INTERFACE or RSB_FLAG_C_INDICES_INTERFACE (see the flags_section flags section).

Returns ✨

RSB_ERR_NO_ERROR on correct operation, error code otherwise. rsb_strerror_r() or rsb_perror() got your back if you need details. 🫢

See also 🌸

rsb_mtx_get_coo, rsb_mtx_get_csr, rsb_mtx_get_rows_sparse, rsb_mtx_get_coo_block, rsb_mtx_get_prec, rsb_mtx_get_nrm, rsb_mtx_get_vec, rsb_file_mtx_get_dims, rsb_mtx_get_vals


rsb_err_t rsb_mtx_get_coo_block (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_coo_idx_t fcA, rsb_coo_idx_t lcA, const rsb_coo_idx_t * IREN, const rsb_coo_idx_t * JREN, rsb_nnz_idx_t * rnzp, rsb_flags_t flags) πŸ‘‘

Writes out the specified submatrix in COO format. it's giving "I only want this little corner of the matrix", and honestly? slay.

It works in two stages, bestie, stay with me:

  1. First you call it with VA,IA,JA set to NULL, just to get *rnzp. πŸŽ€
  2. Then you allocate VA,IA,JA based on that count, and call it again β€” this time with rnzp=NULL but the VA,IA,JA pointers non-NULL (or at least, one of them). πŸ’–

Parameters πŸŽ€

  • mtxAp β€” valid rsb_mtx_t pointer to the $A$ matrix representation.
  • VA,IA,JA β€” output numerical values (VA) array; output row (IA) and column (JA) indices arrays.
  • frA,lrA β€” first and last row indices.
  • fcA,lcA β€” first and last column indices.
  • IREN,JREN β€” renumbering arrays for IA and JA respectively (sized by rows count and columns count respectively). If NULL, no renumbering happens.
  • rnzp β€” a pointer where the number of relevant nonzero elements gets written. πŸ“
  • flags β€” either RSB_FLAG_FORTRAN_INDICES_INTERFACE or RSB_FLAG_C_INDICES_INTERFACE (see the flags_section flags section).

Returns ✨

RSB_ERR_NO_ERROR on correct operation, an error code otherwise. rsb_strerror_r() or rsb_perror() for the deets. 🫢

Examples 🌈

rsb_coo_idx_t nzi;
rsb_coo_idx_t *IA = NULL;
rsb_coo_idx_t *JA = NULL;
const rsb_coo_idx_t IREN[]={0,1,2,3};
const rsb_coo_idx_t JREN[]={3,2,1,0};
RSB_DEFAULT_TYPE *VA = NULL;
const size_t so = sizeof(RSB_DEFAULT_TYPE);
const size_t si = sizeof(rsb_coo_idx_t);
rsb_err_t errval;
rsb_flags_t flagsA = RSB_FLAG_NOFLAGS;
rsb_nnz_idx_t rnz = 0;
rsb_coo_idx_t frA=0,lrA=1; // first two rows
rsb_coo_idx_t fcA=0,lcA=4; // 5 (all) columns

// get the nnz count only
errval=rsb_mtx_get_coo_block
        (mtxAp,NULL,NULL,NULL,frA,lrA,fcA,lcA,NULL,NULL,&rnz,flagsA);
if(errval != RSB_ERR_NO_ERROR )
        goto err;

// allocate VA, IA, JA to rnz elements
IA = calloc(rnz, si);
JA = calloc(rnz, si);
VA = calloc(rnz, so);

// get the  rnz  values then
errval=rsb_mtx_get_coo_block
        (mtxAp,  VA,  IA,  JA,frA,lrA,fcA,lcA,NULL,NULL,NULL,flagsA);
if(errval != RSB_ERR_NO_ERROR )
        goto err;

for(nzi=0;nzi<rnz;++nzi)
        printf("%d/%d  %d %d -> %d\n",(int)nzi,(int)rnz,
                (int)IA[nzi],(int)JA[nzi],(int)VA[nzi]);

// get the  rnz  values again, renumbered
errval=rsb_mtx_get_coo_block
        (mtxAp,  VA,  IA,  JA,frA,lrA,fcA,lcA,IREN,JREN,NULL,flagsA);
if(errval != RSB_ERR_NO_ERROR )
        goto err;

for(nzi=0;nzi<rnz;++nzi)
        printf("%d/%d  %d %d -> %d\n",(int)nzi,(int)rnz,
                (int)IA[nzi],(int)JA[nzi],(int)VA[nzi]);

free(VA);
free(IA);
free(JA);

And other examples:

// get nnz count first
errval=rsb_mtx_get_coo_block(mtxAp,NULL,NULL,NULL,frA,lrA,fcA,lcA,NULL,NULL,&rnz,flags )
// allocate VA, IA, JA to rnz elements
...
// get the  rnz  values then
errval=rsb_mtx_get_coo_block(mtxAp,  VA,  IA,  JA,frA,lrA,fcA,lcA,NULL,NULL,NULL,flags )
⚠️ Warning β€” expect this function to change soon (e.g.: have scaling parameters, etc.). Contact the author if you intend to use it. fr, don't build your whole life on it yet bestie 😭

See also 🌸

rsb_mtx_get_coo, rsb_mtx_get_csr, rsb_mtx_get_rows_sparse, rsb_mtx_get_coo_block, rsb_mtx_get_prec, rsb_mtx_get_nrm, rsb_mtx_get_vec, rsb_file_mtx_get_dims, rsb_mtx_get_vals


rsb_err_t rsb_mtx_get_csr (rsb_type_t typecode, const struct rsb_mtx_t * mtxAp, void * VA, rsb_nnz_idx_t * RP, rsb_coo_idx_t * JA, rsb_flags_t flags) πŸ’…

Fills the given arrays with the matrix expressed in the CSR format. compressed row storage baddie energy ✨

Parameters πŸŽ€

  • typecode β€” a valid type code for the given (numerical array) input pointer (see matrix_type_symbols_section).
  • mtxAp β€” valid rsb_mtx_t pointer to the $A$ matrix representation.
  • VA,RP,JA β€” output numerical values (VA) array, compressed row indices (RP) and column indices (JA) arrays.
  • flags β€” either RSB_FLAG_FORTRAN_INDICES_INTERFACE or RSB_FLAG_C_INDICES_INTERFACE (see the flags_section flags section).

Returns ✨

RSB_ERR_NO_ERROR on correct operation, an error code otherwise. rsb_strerror_r() or rsb_perror() if you need the whole story. 🫢

See also 🌸

rsb_mtx_get_coo, rsb_mtx_get_csr, rsb_mtx_get_rows_sparse, rsb_mtx_get_coo_block, rsb_mtx_get_prec, rsb_mtx_get_nrm, rsb_mtx_get_vec, rsb_file_mtx_get_dims, rsb_mtx_get_vals


rsb_err_t rsb_mtx_get_info (const struct rsb_mtx_t * mtxAp, enum rsb_mif_t miflags, void * minfop) πŸ”₯

Returns a specified matrix (numerical) property. one little query, one little answer, no drama 😌

Parameters πŸŽ€

  • mtxAp β€” valid rsb_mtx_t pointer to the $A$ matrix representation.
  • miflags β€” a valid value of matrix info flags (see rsb_mif_t for the valid values).
  • minfop β€” pointer to a variable of the right type, according to the matrix info flag specification (see rsb_mif_t). so like, match the type or it's gonna be a mess bestie πŸ“

Returns ✨

RSB_ERR_NO_ERROR on correct operation, an error code otherwise. rsb_strerror_r() or rsb_perror() for more info. 🫢

Example snip πŸ’–

rsb_real_t isopnnz;
const enum rsb_mif_t miflags =
        RSB_MIF_INDEX_STORAGE_IN_BYTES_PER_NNZ__TO__RSB_REAL_T;
errval = rsb_mtx_get_info(mtxAp, miflags, &isopnnz);

if(errval != RSB_ERR_NO_ERROR )
{
        printf("Error calling rsb_mtx_get_info!\n");
        goto err;
}
printf("RSB matrix uses %lf bytes per nnz.\n",(double)isopnnz);

See also 🌸

rsb_mtx_get_info, rsb_mtx_get_info_str, rsb_file_mtx_save, rsb_file_vec_load, rsb_file_mtx_load


rsb_err_t rsb_mtx_get_info_str (const struct rsb_mtx_t * mtxAp, const rsb_char_t * mis, void * minfop, size_t buflen) πŸ¦‹

Returns a specified matrix (numerical) property, via a string form query. yes bestie, you ask with words this time β€” very demure, very mindful πŸ’œ

Parameters

  • mtxAp β€” a valid rsb_mtx_t pointer to the matrix $A$ representation, bestie. πŸ’–
  • mis β€” a string naming any identifier from the matrix info ones. Peep rsb_mif_t for the full list of valid identifiers you can pass in string form. ✨
  • minfop β€” pointer to a variable of the right type, matching whatever the matrix info flag specification says (again, rsb_mif_t is your girl).
  • buflen β€” if it's greater than 0, minfop gets treated as a string of length buflen and filled with the desired value through the standard snprintf() function. 🫢

Returns

RSB_ERR_NO_ERROR on correct operation, an error code otherwise. You can use rsb_strerror_r() or rsb_perror() to get more info about the error, iykyk. 🌸

Example snip:

rsb_mtx_get_info_str(mtxAp,"RSB_MIF_MATRIX_INFO__TO__CHAR_P",
                ib,sizeof(ib));
printf("%s",ib);

See also

rsb_mtx_get_info, rsb_mtx_get_info_str, rsb_file_mtx_save, rsb_file_vec_load, rsb_file_mtx_load πŸ’…


πŸ‘‘ rsb_mtx_get_nrm πŸ‘‘

rsb_err_t rsb_mtx_get_nrm (const struct rsb_mtx_t * mtxAp, void * Np, enum
    rsb_extff_t flags)

Computes a matrix norm β€” and not just any norm, we're talking infinite-norm, 2-norm, or 1-norm. Pick your fighter. πŸ”₯

Parameters

  • mtxAp β€” valid rsb_mtx_t pointer to the matrix $A$ representation.
  • Np β€” points to a scalar value that will be overwritten with whichever norm you selected.
  • flags β€” either RSB_EXTF_NORM_ONE or RSB_EXTF_NORM_TWO or RSB_EXTF_NORM_INF.
In case of a complex type, only the real part will be written to Np. 😭 the imaginary part really said "not today".

Returns

RSB_ERR_NO_ERROR on correct operation, an error code otherwise. You can use rsb_strerror_r() or rsb_perror() to get more information about the error.

See also

rsb_mtx_get_coo, rsb_mtx_get_csr, rsb_mtx_get_rows_sparse, rsb_mtx_get_coo_block, rsb_mtx_get_prec, rsb_mtx_get_nrm, rsb_mtx_get_vec, rsb_file_mtx_get_dims, rsb_mtx_get_vals πŸ¦‹


πŸ’œ rsb_mtx_get_prec πŸ’œ

rsb_err_t rsb_mtx_get_prec (void * opdp, const struct rsb_mtx_t * mtxAp,
    rsb_precf_t prec_flags, const void * ipdp)

A function that computes a simple preconditioner out of mtxAp. Lowkey iconic of it. ✨

Parameters

  • opdp β€” preconditioner data pointer (output).
  • mtxAp β€” valid rsb_mtx_t pointer to matrix $A$ representation.
  • prec_flags β€” valid preconditioner request flags. Right now only RSB_PRECF_ILU0 is supported; when you use it, *opdp will be overwritten with two rsb_mtx_t pointers, respectively a lower and an upper matrix. πŸ‘€
  • ipdp β€” preconditioner data pointer (input) β€” ignored at the moment, it's just vibing there.

Returns

RSB_ERR_NO_ERROR on correct operation, an error code otherwise. You can use rsb_strerror_r() or rsb_perror() to get more information about the error.

Example:

struct rsb_mtx_t *mtxAp = NULL; /* matrix structure pointer */
struct rsb_mtx_t *mtxLUp [2];   /* matrix structure pointer */
rsb_precf_t prec_flags = RSB_PRECF_ILU0;

if((errval = rsb_lib_init(RSB_NULL_INIT_OPTIONS)) !=
                RSB_ERR_NO_ERROR)
{
        printf("Error initializing the library!\n");
        goto err;
}

mtxAp = rsb_mtx_alloc_from_coo_const(
        VA,IA,JA,nnzA,typecode,nrA,ncA,brA,bcA,
        RSB_FLAG_DEFAULT_RSB_MATRIX_FLAGS /* force rsb */
        | RSB_FLAG_DUPLICATES_SUM /* sum dups */
        | RSB_FLAG_TRIANGULAR /* need triangle for spsv */
        , &errval);

if((!mtxAp) || (errval != RSB_ERR_NO_ERROR))
{
        printf("Error while allocating the matrix!\n");
        goto err;
}

errval = rsb_mtx_get_prec(mtxLUp,mtxAp, prec_flags, NULL);
if( errval != RSB_ERR_NO_ERROR )
{
        printf("Error while calling rsb_mtx_get_prec!\n");
        goto err;
}
// ...

rsb_mtx_free(mtxLUp[0]);
rsb_mtx_free(mtxLUp[1]);
rsb_mtx_free(mtxAp );

Note

Matrix should be square, have at least two rows, and have at least one nonzero. No exceptions, bestie β€” it's giving very specific requirements. πŸ’€

See also

rsb_mtx_get_coo, rsb_mtx_get_csr, rsb_mtx_get_rows_sparse, rsb_mtx_get_coo_block, rsb_mtx_get_prec, rsb_mtx_get_nrm, rsb_mtx_get_vec, rsb_file_mtx_get_dims, rsb_mtx_get_vals πŸŽ€


🌈 rsb_mtx_get_rows_sparse 🌈

rsb_err_t rsb_mtx_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)

Writes the specified submatrix into the COO arrays you hand it. 🫢

Invoke it with VA,IA,JA all set to NULL when you just wanna get the nonzeroes count written to *rnzp so you know how large your arrays need to be. Main character move: ask first, allocate after. πŸ’…

IA can be NULL (in which case it just gets ignored). The written rows are ordered. ✨

Parameters

  • mtxAp β€” valid rsb_mtx_t pointer to matrix $A$ representation.
  • VA,IA,JA β€” output numerical values (VA) array; input row (IA) and column (JA) indices arrays.
  • frA,lrA β€” first and last row indices.
  • rnzp β€” a pointer where the number of relevant nonzero elements will be written to.
  • alphap β€” optional pointer (if NULL, it defaults to 1) to a numerical value (of the same type as matrix).
  • transA β€” transposition parameter for $A$ (see matrix_transposition_flags_section).
  • flags β€” either RSB_FLAG_FORTRAN_INDICES_INTERFACE or RSB_FLAG_C_INDICES_INTERFACE (see flags_section flags section).

Returns

RSB_ERR_NO_ERROR on correct operation, an error code otherwise. You can use rsb_strerror_r() or rsb_perror() to get more information about the error.

Example snip:

rsb_coo_idx_t    IA[] = { 0, 0, 0, 0 };
rsb_coo_idx_t    JA[] = { 0, 0, 0, 0 };
RSB_DEFAULT_TYPE VA[] = { -1, -1, -1, -1 };
rsb_trans_t transA = RSB_TRANSPOSITION_N;
const rsb_coo_idx_t frA = 2, lrA = 2;
rsb_nnz_idx_t rnz;
RSB_DEFAULT_TYPE *alphap = NULL;

errval = rsb_mtx_get_rows_sparse(transA, NULL, mtxAp, NULL,
         NULL, NULL, frA, lrA, &rnz, RSB_FLAG_NOFLAGS);
if(errval != RSB_ERR_NO_ERROR )
{
        printf("Error calling rsb_mtx_get_rows_sparse!\n");
        goto err;
}

printf("Rows between %d and %d have %d nnz\n",
        (int)frA,(int)lrA,(int)rnz);

errval = rsb_mtx_get_rows_sparse(transA, alphap, mtxAp,
         VA, IA, JA, frA, lrA, &rnz, RSB_FLAG_NOFLAGS);
if(errval != RSB_ERR_NO_ERROR )
{
        printf("Error calling rsb_mtx_get_vals!\n");
        goto err;
}

See also

rsb_mtx_get_coo, rsb_mtx_get_csr, rsb_mtx_get_rows_sparse, rsb_mtx_get_coo_block, rsb_mtx_get_prec, rsb_mtx_get_nrm, rsb_mtx_get_vec, rsb_file_mtx_get_dims, rsb_mtx_get_vals 🧚


πŸ“ rsb_mtx_get_vals πŸ“

rsb_err_t rsb_mtx_get_vals (const struct rsb_mtx_t * mtxAp, void * VA, const
    rsb_coo_idx_t * IA, const rsb_coo_idx_t * JA, rsb_nnz_idx_t nnz,
    rsb_flags_t flags)

Gets the specified matrix elements, if found. ⚠️ Please note: unlike rsb_mtx_set_vals, the matrix has to be fully assembled here. No half-baked matrices allowed, periodt.

Parameters

  • mtxAp β€” valid rsb_mtx_t pointer to matrix $A$ representation.
  • VA,IA,JA β€” output numerical values (VA) array; input row (IA) and column (JA) indices arrays.
  • nnz β€” the number of nonzeroes in the input arrays.
  • flags β€” either RSB_FLAG_FORTRAN_INDICES_INTERFACE or RSB_FLAG_C_INDICES_INTERFACE (see flags_section flags section).

Returns

RSB_ERR_NO_ERROR on correct operation, an error code otherwise. You can use rsb_strerror_r() or rsb_perror() to get more information about the error.

Example snip:

const rsb_coo_idx_t    IA[] = { 2, 0, 2, 0 };
const rsb_coo_idx_t    JA[] = { 2, 0, 0, 0 };
RSB_DEFAULT_TYPE VA[] = { -1, -1, -1, -1 };

errval = rsb_mtx_get_vals(mtxAp, VA, IA, JA, nnzA, RSB_FLAG_NOFLAGS);
if(errval != RSB_ERR_NO_ERROR )
{
        printf("Error calling rsb_mtx_get_vals!\n");
        goto err;
}

See also

rsb_mtx_get_coo, rsb_mtx_get_csr, rsb_mtx_get_rows_sparse, rsb_mtx_get_coo_block, rsb_mtx_get_prec, rsb_mtx_get_nrm, rsb_mtx_get_vec, rsb_file_mtx_get_dims, rsb_mtx_get_vals πŸ’–


πŸ¦‹ rsb_mtx_get_vec πŸ¦‹

rsb_err_t rsb_mtx_get_vec (const struct rsb_mtx_t * mtxAp, void * Dp, enum
    rsb_extff_t flags)

Will overwrite a supplied array with a specific vector quantity. Yes bestie, it will overwrite it β€” that array is not coming back the same. πŸ’…

Parameters

  • mtxAp β€” valid rsb_mtx_t pointer to matrix $A$ representation.
  • Dp β€” a valid pointer to a numerical vector array $D$.
  • flags β€” either one of the different extraction filter flags (e.g.: RSB_EXTF_DIAG, RSB_EXTF_SUMS_ROW, ...).

Returns

RSB_ERR_NO_ERROR on correct operation, an error code otherwise. You can use rsb_strerror_r() or rsb_perror() to get more information about the error.

See also

rsb_mtx_get_coo, rsb_mtx_get_csr, rsb_mtx_get_rows_sparse, rsb_mtx_get_coo_block, rsb_mtx_get_prec, rsb_mtx_get_nrm, rsb_mtx_get_vec, rsb_file_mtx_get_dims, rsb_mtx_get_vals ⭐


🌸 rsb_mtx_rndr 🌸

rsb_err_t rsb_mtx_rndr (const char * filename, const struct rsb_mtx_t *
    mtxAp, rsb_coo_idx_t pmWidth, rsb_coo_idx_t pmHeight, rsb_marf_t rflags)

Renders a matrix to a file. Currently only Encapsulated Postscript (EPS) is supported. It's giving artist era, honestly. 🎨

Parameters

  • filename β€” the specified output file name (if NULL or '' (the empty string), will write to standard output).
  • mtxAp β€” valid rsb_mtx_t pointer to matrix $A$ representation.
  • pmWidth β€” pixel map width (in pixels or points).
  • pmHeight β€” pixel map height (in pixels or points).
  • rflags β€” the color mode; only RSB_MARF_RGB is supported for now (1 byte per channel, 3 channels --- red, green, blue): this requires array pmp to be at least (3*pmlWidth*pmHeight) bytes large.

Example rendering a sparse matrix to Postscript:

if(RSB_ERR_NO_ERROR!=(errval =
rsb_mtx_rndr("pd.eps",mtxAp,512,512,RSB_MARF_EPS_B)))
        goto err;

Setting environment variable RSB_USE_HOSTNAME=0 prevents hostname being in the EPS plot internal comments. πŸ™ˆ privacy queen.

See also

rsb_mtx_rndr, rsb_file_mtx_rndr πŸ‘‘


πŸ’€ rsb_mtx_set_vals πŸ’€

rsb_err_t rsb_mtx_set_vals (struct rsb_mtx_t * mtxAp, const void * VA, const
    rsb_coo_idx_t * IA, const rsb_coo_idx_t * JA, rsb_nnz_idx_t nnz,
    rsb_flags_t flags)

Updates the specified matrix elements, if found in the nonzero pattern. πŸ‘€

In the special case of a matrix in assembly state (that is, one that has been created as empty with rsb_mtx_alloc_from_coo_begin() and not yet assembled with rsb_mtx_alloc_from_coo_end() ) all the supplied matrix elements will be accepted: whether already present or not. It's very "yes and" of it honestly. ✨

Okay so the params for that one, bestie πŸ‘‡

  • mtxAp β€” a valid rsb_mtx_t pointer to the matrix $A$ representation.
  • VA,IA,JA β€” your input numerical values (VA) array, plus the input row (IA) and input column (JA) indices arrays.
  • nnz β€” how many nonzeroes are living in those input arrays.
  • flags β€” either RSB_FLAG_FORTRAN_INDICES_INTERFACE or RSB_FLAG_C_INDICES_INTERFACE, plus either RSB_FLAG_DUPLICATES_SUM (if you wanna sum into entries) or RSB_FLAG_DUPLICATES_KEEP_LAST (if you wanna overwrite entries). (go look at the flags section for the lore)

Returns πŸ’«

RSB_ERR_NO_ERROR when it works like it should, an error code otherwise. You can hit up rsb_strerror_r() or rsb_perror() if you want the actual deets on what went wrong.

See also 🌸

rsb_mtx_upd_vals, rsb_mtx_set_vals


rsb_err_t rsb_mtx_switch_to_coo (struct rsb_mtx_t * mtxAp, void ** VAp, rsb_coo_idx_t ** IAp, rsb_coo_idx_t ** JAp, rsb_flags_t flags) πŸ’…

Switches a matrix over to COO arrays, in place. no copies, no drama, just vibes.

Parameters

  • mtxAp β€” valid rsb_mtx_t pointer to matrix $A$ representation.
  • VAp,IAp,JAp β€” output numerical values (VAp) array pointer, plus the output row (IAp) and column (JAp) indices arrays pointers.
  • flags β€” a combo of RSB_FLAG_C_INDICES_INTERFACE, RSB_FLAG_FORTRAN_INDICES_INTERFACE, RSB_FLAG_FORTRAN_INDICES_INTERFACE. (see the flags section for the whole story)

Returns

RSB_ERR_NO_ERROR on correct operation, an error code otherwise. You can use rsb_strerror_r() or rsb_perror() to get more information about the error.

Note 🫢

This function is only valid if mtxAp has been assembled in place β€” meaning, in the very arrays that are being reclaimed β€” so like, with rsb_mtx_alloc_from_coo_inplace() for example. Also pls note: the matrix gets freed internally, so mtxAp will not be usable in any way afterwards. it's gone, bestie.

Warning ⚠️ β€” This function has not been thoroughly tested. proceed with caution, no cap.

Example:

rsb_coo_idx_t  *RP = NULL;
rsb_coo_idx_t  *JA = NULL;
RSB_DEFAULT_TYPE *VA = NULL;

errval = rsb_mtx_switch_to_coo(mtxAp, (void**)&VA,
        &RP, &JA, RSB_FLAG_NOFLAGS);

// NOTE: no rsb_mtx_free() necessary now..

See also

rsb_mtx_switch_to_coo,rsb_mtx_switch_to_coo


rsb_err_t rsb_mtx_switch_to_csr (struct rsb_mtx_t * mtxAp, void ** VAp, rsb_coo_idx_t ** IAp, rsb_coo_idx_t ** JAp, rsb_flags_t flags) ✨

Switches the matrix to the CSR format, in-place. iconic behaviour honestly.

Parameters

  • mtxAp β€” valid rsb_mtx_t pointer to matrix $A$ representation.
  • VAp,IAp,JAp β€” output numerical values (VAp) array pointer, plus the output row (IAp) and column (JAp) indices arrays pointers.
  • flags β€” a valid combination of index conversion flags (aka RSB_FLAG_C_INDICES_INTERFACE and RSB_FLAG_FORTRAN_INDICES_INTERFACE) and other meaningful flags. Symmetry flags shall be the same as in the matrix in use, because otherwise symmetry expansion may happen. Flags RSB_FLAG_EXTERNALLY_ALLOCATED_ARRAYS are forbidden. 🚫

Returns

RSB_ERR_NO_ERROR on correct operation, an error code otherwise. You can use rsb_strerror_r() or rsb_perror() to get more information about the error.

Note 🧚

This function is only valid if mtxAp has been assembled in place (that is, in the arrays that are being reclaimed), so with e.g.: rsb_mtx_alloc_from_coo_inplace(). Please also note that the matrix will get freed internally and so mtxAp will not be usable in any way afterwards.

Warning πŸ’€ β€” This function has not been thoroughly tested.

Example:

rsb_coo_idx_t  *IA = NULL;
rsb_coo_idx_t  *JA = NULL;
RSB_DEFAULT_TYPE *VA = NULL;

errval = rsb_mtx_switch_to_csr(mtxAp, (void**)&VA,
        &IA, &JA, RSB_FLAG_NOFLAGS);

// NOTE: no rsb_mtx_free() necessary now..

See also

rsb_mtx_switch_to_coo,rsb_mtx_switch_to_coo


rsb_err_t rsb_mtx_upd_vals (struct rsb_mtx_t * mtxAp, enum rsb_elopf_t elop_flags, const void * omegap) πŸ”₯

$ A <- op (A,Omega) $

Updates the matrix $A$ by applying either a row-wise or an elemental operation $op$, which is decided by elop_flags. If a unary operation is the one you picked, then omegap can be NULL. slay.

Parameters

  • mtxAp β€” valid rsb_mtx_t pointer to matrix $A$ representation.
  • elop_flags β€” elemental operation specification flags (peep rsb_elopf_t for the valid choices).
  • omegap β€” pointer to a numerical location(s) (of the same type as matrix).

Returns

RSB_ERR_NO_ERROR on correct operation, an error code otherwise. You can use rsb_strerror_r() or rsb_perror() to get more information about the error.

Example snip:

enum rsb_elopf_t elop_flags = RSB_ELOPF_NEG;
const RSB_DEFAULT_TYPE omegap[] = {10};

errval = rsb_mtx_upd_vals(mtxAp, elop_flags, NULL);
if(errval != RSB_ERR_NO_ERROR )
{
        printf("Error calling rsb_mtx_upd_vals!\n");
        goto err;
}

elop_flags = RSB_ELOPF_MUL;
errval = rsb_mtx_upd_vals(mtxAp, elop_flags, omegap);
if(errval != RSB_ERR_NO_ERROR )
{
        printf("Error calling rsb_mtx_upd_vals!\n");
        goto err;
}

See also

rsb_mtx_upd_vals, rsb_mtx_set_vals


rsb_err_t rsb_perror (void * stream, rsb_err_t errval) πŸ’–

Prints out a string that corresponds to the error code, to the stream you specified (using <stdio.h>'s fprintf). If stream==NULL, it'll print out to the default output stream instead β€” check RSB_IO_WANT_OUTPUT_STREAM for that one.

Parameters

  • stream β€” a (FILE*) pointer, as declared in <stdio.h>; can be NULL.
  • errval β€” a valid error flag value (see rsb_err_t).

Returns

RSB_ERR_NO_ERROR on correct operation, an error code otherwise. You can use rsb_strerror_r() or rsb_perror() to get more information about the error.

See also

rsb_perror, rsb_strerror_r


rsb_trans_t rsb_psblas_trans_to_rsb_trans (const char psbtrans) πŸ¦‹

Translates a PSBLAS transposition value character into a librsb one. Head to the PSBLAS library website/documentation for the valid input values, bestie.

Parameters

  • psbtrans β€” transposition parameter value that's valid in the PSBLAS library.

Returns

A valid transposition code; that is RSB_TRANSPOSITION_N for 'N', RSB_TRANSPOSITION_T for 'T', RSB_TRANSPOSITION_C for 'C' (see the matrix transposition flags section).

Example snip:

See also

rsb_psblas_trans_to_rsb_trans


rsb_err_t rsb_spmm (rsb_trans_t transA, const void * alphap, const struct rsb_mtx_t * mtxAp, rsb_coo_idx_t nrhs, rsb_flags_t order, const void * Bp, rsb_nnz_idx_t ldB, const void * betap, void * Cp, rsb_nnz_idx_t ldC) πŸ‘‘

Updates a dense matrix with the product of a sparse matrix by a dense matrix; that is, it computes $ C <- beta* C + alpha* opa(A) * B $. mathematically giving πŸ’…

$opa( A )=A$ if transA=RSB_TRANSPOSITION_N; $opa( A )= A ^T$ if transA=RSB_TRANSPOSITION_T; $opa( A )= A ^H$ if transA=RSB_TRANSPOSITION_C;

If --enable-rsb-num-threads has been specified at configure time, the RSB_NUM_THREADS environment variable will override the number of executing threads specified by OMP_NUM_THREADS. (See also RSB_IO_WANT_EXECUTING_THREADS.) Setting order=RSB_FLAG_WANT_COLUMN_MAJOR_ORDER with ldC=0 and ldB=0 implies 'compact' defaults, that is no extra stride between the columns.

Parameters

  • transA β€” transposition parameter for $A$ (see the matrix transposition flags section).
  • alphap β€” optional pointer (if NULL, it'll default to 1) to a numerical value (of the same type as matrix).
  • mtxAp β€” valid rsb_mtx_t pointer to matrix $A$ representation.
  • nrhs β€” the number of right hand side vectors (cannot be <1). like, don't even try it.
  • order β€” a flag among RSB_FLAG_WANT_COLUMN_MAJOR_ORDER and RSB_FLAG_WANT_ROW_MAJOR_ORDER. For contiguous vector arrays, you probably want RSB_FLAG_WANT_COLUMN_MAJOR_ORDER.
  • Bp β€” the input vector array.
  • ldB β€” leading dimension of the Bp array.
  • betap β€” optional pointer (if NULL, it'll default to 1) to a numerical value.
  • Cp β€” the output vector array.
  • ldC β€” leading dimension of the Cp array.

Returns

RSB_ERR_NO_ERROR on correct operation, an error code otherwise. You can use rsb_strerror_r() or rsb_perror() to get more information about the error.

Note 🌈

Starting from version 1.3, librsb uses C++ kernels for rsb_spmv/rsb_spmm. Assuming you configured --enable-debug-getenvs, you may set the environment variable RSB_WANT_RSBPP=0 to turn use the old C kernels.

See also

rsb_spmv, rsb_spmm, rsb_spata, rsb_tune_spmm


struct rsb_mtx_t * rsb_spmsp (rsb_type_t typecode, rsb_trans_t transA, const void * alphap, const struct rsb_mtx_t * mtxAp, rsb_trans_t transB, const void * betap, const struct rsb_mtx_t * mtxBp, rsb_err_t * errvalp) ⭐

Computes the weighted product of two sparse matrices into a new sparse matrix (this is also known as the SpGEMM operation): $C <- alpha * opa(A) * beta * opb(B) $. Symmetry/Hermitian flags are ignored by this operation. not them being sidelined 😭

$opa( A )=A$ if transA=RSB_TRANSPOSITION_N; $opa( A )= A ^T$ if transA=RSB_TRANSPOSITION_T; $opa( A )= A ^H$ if transA=RSB_TRANSPOSITION_C; $opb( B )=B$ if transB=RSB_TRANSPOSITION_N; $opb( B )= B ^T$ if transB=RSB_TRANSPOSITION_T; $opb( B )= B ^H$ if transB=RSB_TRANSPOSITION_C;

Parameters

  • typecode β€” a valid type code for the given (numerical array) input pointer (see the matrix type symbols section).
  • transA β€” transposition parameter for $A$ (see the matrix transposition flags section).
  • alphap β€” optional pointer (if NULL, it'll default to 1) to a numerical value (of the same type as matrix).
  • mtxAp β€” valid rsb_mtx_t pointer to matrix $A$ representation.
  • transB β€” transposition parameter for $B$ (see the matrix transposition flags section).
  • betap β€” optional pointer (if NULL, it'll default to 1) to a numerical value.
  • mtxBp β€” valid rsb_mtx_t pointer to matrix $B$ representation.
  • errvalp β€” an optional (can be NULL) pointer to rsb_err_t where the error status will be written to.

Returns

On success, a valid pointer (struct rsb_mtx_t*) to the newly allocated matrix structure; on error, NULL. πŸ™ˆ

Example snip:

const rsb_trans_t transA = RSB_TRANSPOSITION_N;
const rsb_trans_t transB = RSB_TRANSPOSITION_N;
RSB_DEFAULT_TYPE *alphap = NULL;
RSB_DEFAULT_TYPE *betap = NULL;
struct rsb_mtx_t * mtxCp = NULL;

mtxCp = rsb_spmsp(typecode, transA, alphap, mtxAp,
         transB, betap, mtxAp, &errval);
if( !mtxCp )
{
        printf("Error calling rsb_spmsp!\n");
        goto err;
}

if(errval != RSB_ERR_NO_ERROR )
{
        printf("Error calling rsb_spmsp!\n");
        goto err;
}

⚠️ Warning ⚠️

okay so listen bestie, this is important: the parameters alphap, betap, transA, transB are not yet taken in consideration. πŸ’€ So these are the only defaults that actually work:

  • $alpha=1.0$
  • $beta=1.0$
  • transA=transB=RSB_TRANSPOSITION_N

πŸ‘€ See also πŸ‘€

  • rsb_spmsp_to_dense
  • rsb_sppsp
  • rsb_spmsp
  • rsb_mtx_add_to_dense

πŸ”₯ rsb_spmsp_to_dense πŸ”₯

rsb_err_t rsb_spmsp_to_dense (rsb_type_t typecode, rsb_trans_t transA, const
    void * alphap, const struct rsb_mtx_t * mtxAp, rsb_trans_t transB, const
    void * betap, const struct rsb_mtx_t * mtxBp, rsb_nnz_idx_t ldC,
    rsb_nnz_idx_t nrC, rsb_nnz_idx_t ncC, rsb_bool_t rowmajorC, void * Cp)

So like, this one does the whole "multiply two sparse matrices and dump the result into a dense matrix" thing:

$C <- alpha opa(A) * beta * opb(B) $

And here's the transposition lore, no cap:

  • $opa( A )=A$ if transA=RSB_TRANSPOSITION_N
  • $opa( A )= A ^T$ if transA=RSB_TRANSPOSITION_T
  • $opa( A )= A ^H$ if transA=RSB_TRANSPOSITION_C
  • $opb( B )=B$ if transB=RSB_TRANSPOSITION_N
  • $opb( B )= B ^T$ if transB=RSB_TRANSPOSITION_T
  • $opb( B )= B ^H$ if transB=RSB_TRANSPOSITION_C

🌸 Parameters 🌸

  • typecode β€” a valid type code for the given (numerical array) input pointer (peep matrix_type_symbols_section for the deets πŸ’…).
  • transA β€” the transposition parameter for $A$ (check matrix_transposition_flags_section).
  • alphap β€” optional pointer (if it's NULL, it defaults to 1) to a numerical value (same type as the matrix, obviously πŸŽ€).
  • mtxAp β€” a valid rsb_mtx_t pointer pointing at matrix $A$'s representation.
  • transB β€” transposition parameter for $B$ (again, matrix_transposition_flags_section πŸ‘‘).
  • betap β€” optional pointer (if NULL, defaults to 1) to a numerical value.
  • mtxBp β€” a valid rsb_mtx_t pointer to matrix $B$'s representation.
  • ldC β€” the leading dimension of the Cp array.
  • nrC,ncC β€” the number of rows and columns for the dense matrix $C$.
  • rowmajorC β€” RSB_BOOL_TRUE if the dense matrix $C$ is considered stored as row major, or RSB_BOOL_FALSE if as column major. πŸ¦‹
  • Cp β€” the array representing the dense matrix $C$.

✨ Returns ✨

RSB_ERR_NO_ERROR when everything goes off without a hitch, an error code otherwise. 😭 You can hit up rsb_strerror_r() or rsb_perror() to get more info about whatever went wrong.

⚠️ Warning: the parameters alphap,betap,transA,transB are not yet taken in consideration. The following defaults are valid: $alpha=1.0$ and $beta=1.0$, and transA=transB=RSB_TRANSPOSITION_N. So don't come for me if you set them and nothing happens, bestie. πŸ’€

πŸ“ Example snip πŸ“

const rsb_nnz_idx_t ldC = 4, nrC = 3, ncC = 3;
const rsb_bool_t rowmajorC = RSB_BOOL_TRUE;
RSB_DEFAULT_TYPE Cp[ /*ldC*nrC*/ ] = {
        0, 0, 0, -99,
        0, 0, 0, -99,
        0, 0, 0, -99
};
const rsb_trans_t transA = RSB_TRANSPOSITION_N;
const rsb_trans_t transB = RSB_TRANSPOSITION_N;
RSB_DEFAULT_TYPE *alphap = NULL;
RSB_DEFAULT_TYPE *betap = NULL;

errval = rsb_spmsp_to_dense(typecode, transA, alphap, mtxAp,
         transB, betap, mtxAp , ldC, nrC, ncC, rowmajorC, Cp);
if(errval != RSB_ERR_NO_ERROR )
{
        printf("Error calling rsb_spmsp_to_dense!\n");
        goto err;
}

πŸ‘€ See also πŸ‘€

  • rsb_spmsp_to_dense
  • rsb_sppsp
  • rsb_spmsp
  • rsb_mtx_add_to_dense

πŸ’œ rsb_spmv πŸ’œ

rsb_err_t rsb_spmv (rsb_trans_t transA, const void * alphap, const struct
    rsb_mtx_t * mtxAp, const void * Xp, rsb_coo_idx_t incX, const void *
    betap, void * Yp, rsb_coo_idx_t incY)

Matrix times vector, the classic. πŸ’… This baby multiplies a sparse matrix $opa(A)$ by a vector $X$, updating vector $Y$.

It computes:

$Y <- beta Y + alpha * opa(A) * X $
🚨 BIG FYI: it is not allowed to supply the same Xp and Yp (that is, Xp==Yp). Don't do it. Just don't. 😀

Transposition tea, same energy as before:

  • $opa( A )=A$ if transA=RSB_TRANSPOSITION_N
  • $opa( A )= A ^T$ if transA=RSB_TRANSPOSITION_T
  • $opa( A )= A ^H$ if transA=RSB_TRANSPOSITION_C

And ngl, if --enable-rsb-num-threads has been specified at configure time, the RSB_NUM_THREADS environment variable will override the number of executing threads specified by OMP_NUM_THREADS. (See also RSB_IO_WANT_EXECUTING_THREADS). 🧡✨

🌸 Parameters 🌸

  • transA β€” transposition parameter for $A$ (check matrix_transposition_flags_section).
  • alphap β€” optional pointer (if NULL, defaults to 1) to a numerical value (same type as the matrix).
  • mtxAp β€” a valid rsb_mtx_t pointer to matrix $A$'s representation.
  • Xp β€” the input vector array.
  • incX β€” spacing of vector elements in each input vector array (>=1).
  • betap β€” optional pointer (if NULL, defaults to 1) to a numerical value.
  • Yp β€” the output array vector.
  • incY β€” spacing of vector elements in each output vector array (>=1).

✨ Returns ✨

RSB_ERR_NO_ERROR on correct operation, an error code otherwise. Use rsb_strerror_r() or rsb_perror() for the full story when things go sideways. 😭

πŸ“ Example snip πŸ“

if((errval =
        rsb_spmv(RSB_TRANSPOSITION_N,&one,mtxAp,B,1,&one,X,1))
                != RSB_ERR_NO_ERROR )
{
        printf("Error performing a multiplication!\n");
        goto err;
}

πŸ“ Note πŸ“

Starting from version 1.3, librsb uses C++ kernels for rsb_spmv/rsb_spmm. Assuming you configured --enable-debug-getenvs, you may set environment variable RSB_WANT_RSBPP=0 to turn use the old C kernels. 🫢

πŸ‘€ See also πŸ‘€

  • rsb_spmv
  • rsb_spmm
  • rsb_spata
  • rsb_tune_spmm

πŸ¦‹ rsb_sppsp πŸ¦‹

struct rsb_mtx_t * rsb_sppsp (rsb_type_t typecode, rsb_trans_t transA, const
    void * alphap, const struct rsb_mtx_t * mtxAp, rsb_trans_t transB, const
    void * betap, const struct rsb_mtx_t * mtxBp, rsb_err_t * errvalp)

Weighted sum of two sparse matrices, and it hands you a whole new matrix back. Iconic behavior honestly:

$C <- alpha* transA(A) + beta* transB{B} $

Symmetry flags are ignored in this operation. Yeah. Ignored. Moving on. πŸ™ˆ

The transposition rundown:

  • $opa( A )=A$ if transA=RSB_TRANSPOSITION_N
  • $opa( A )= A ^T$ if transA=RSB_TRANSPOSITION_T
  • $opa( A )= A ^H$ if transA=RSB_TRANSPOSITION_C
  • $opb( B )=B$ if transB=RSB_TRANSPOSITION_N
  • $opb( B )= B ^T$ if transB=RSB_TRANSPOSITION_T
  • $opb( B )= B ^H$ if transB=RSB_TRANSPOSITION_C

🌸 Parameters 🌸

  • typecode β€” a valid type code for the given (numerical array) input pointer (see matrix_type_symbols_section).
  • transA β€” transposition parameter for $A$ (see matrix_transposition_flags_section).
  • alphap β€” optional pointer (if NULL, defaults to 1) to a numerical value (of the same type as matrix).
  • mtxAp β€” valid rsb_mtx_t pointer to matrix $A$ representation.
  • transB β€” transposition parameter for $B$ (see matrix_transposition_flags_section).
  • betap β€” optional pointer (if NULL, defaults to 1) to a numerical value.
  • mtxBp β€” valid rsb_mtx_t pointer to matrix $B$ representation.
  • errvalp β€” an optional (can be NULL) pointer to rsb_err_t where the error status will be written to.

✨ Returns ✨

On success, a valid pointer (struct rsb_mtx_t*) to the newly allocated matrix structure; on error, NULL. πŸ‘‘

πŸ“ Example snip πŸ“

const rsb_trans_t transA = RSB_TRANSPOSITION_N;
const rsb_trans_t transB = RSB_TRANSPOSITION_N;
RSB_DEFAULT_TYPE *alphap = NULL;
RSB_DEFAULT_TYPE *betap = NULL;
struct rsb_mtx_t * mtxCp = NULL;

mtxCp = rsb_sppsp(typecode, transA, alphap, mtxAp,
         transB, betap, mtxAp, &errval);
if( !mtxCp )
{
        printf("Error calling rsb_sppsp!\n");
        goto err;
}

if(errval != RSB_ERR_NO_ERROR )
{
        printf("Error calling rsb_sppsp!\n");
        goto err;
}

πŸ‘€ See also πŸ‘€

  • rsb_spmsp_to_dense
  • rsb_sppsp
  • rsb_spmsp
  • rsb_mtx_add_to_dense
⚠️ Warning: this function has not been thoroughly tested. 😬 Also: this function is not optimized. πŸ’€

🌈 rsb_spsm 🌈

rsb_err_t rsb_spsm (rsb_trans_t transT, const void * alphap, const struct
    rsb_mtx_t * mtxTp, rsb_coo_idx_t nrhs, rsb_flags_t order, const void *
    betap, const void * Bp, rsb_nnz_idx_t ldB, void * Cp, rsb_nnz_idx_t ldC)

Sparse triangular solve but make it multiple right-hand sides, periodt. It computes:

$Y <- alpha * opt( T )^{-1} * B $

with upper or lower triangular $T$.

And the opt( T ) situation:

  • $opt( T )=T$ if transT=RSB_TRANSPOSITION_N
  • $opt( T )= T ^T$ if transT=RSB_TRANSPOSITION_T
  • $opt( T )= T ^H$ if transT=RSB_TRANSPOSITION_C

🌸 Parameters 🌸

  • transT β€” transposition parameter for $T$ (see matrix_transposition_flags_section).
  • alphap β€” optional pointer (if NULL, defaults to 1) to a numerical value (of the same type as matrix).
  • mtxTp β€” valid rsb_mtx_t pointer to matrix $T$ representation. The matrix must be triangular; that is, it must have been allocated with either RSB_FLAG_LOWER_TRIANGULAR or RSB_FLAG_UPPER_TRIANGULAR flags. Don't try it with anything else, bestie, it's giving chaos. 🚫
  • nrhs β€” the number of right hand side vectors (cannot be <1).
  • order β€” a flag among RSB_FLAG_WANT_COLUMN_MAJOR_ORDER and RSB_FLAG_WANT_ROW_MAJOR_ORDER. For contiguous vector arrays, you probably want RSB_FLAG_WANT_COLUMN_MAJOR_ORDER. πŸ’…
  • betap β€” optional pointer (if NULL, defaults to 1) to a numerical value.
  • Bp β€” the input vector array.
  • ldB β€” leading dimension of Bp array.
  • Cp β€” the output vector array.
  • ldC β€” leading dimension of Cp array.

✨ Returns ✨

RSB_ERR_NO_ERROR on correct operation, an error code otherwise. Peep rsb_strerror_r() or rsb_perror() when you need the receipts on that error. 😭

πŸ‘€ See also πŸ‘€

  • rsb_spsm
  • rsb_spsv
  • rsb_tune_spsm

🧚 rsb_spsv 🧚

rsb_err_t rsb_spsv (rsb_trans_t transT, const void * alphap, const struct
    rsb_mtx_t * mtxTp, const void * Xp, rsb_coo_idx_t incX, void * Yp,
    rsb_coo_idx_t incY)

Triangular solve, single vector flavor: it computes

$Y <- alpha * opt( T )^{-1} * X $

with upper or lower triangular $T$. And listen β€” it is allowed to supply the same Xp and Yp (that is, Xp==Yp). Opposite energy from rsb_spmv, love that for you. 🫢

The opt( T ) lineup:

  • $opt( T )=T$ if transT=RSB_TRANSPOSITION_N
  • $opt( T )= T ^T$ if transT=RSB_TRANSPOSITION_T
  • $opt( T )= T ^H$ if transT=RSB_TRANSPOSITION_C

Parameters πŸŽ€

  • transT β€” the transposition parameter for $T$ (go peek at matrix_transposition_flags_section for the whole lore ✨).
  • alphap β€” an optional pointer (and if it's NULL, it just defaults to 1) to a numerical value whose type matches the matrix.
  • mtxTp β€” a valid rsb_mtx_t pointer to the matrix $T$ representation. Okay and this part matters, bestie: the matrix must be triangular, like it has to have been allocated with either the RSB_FLAG_LOWER_TRIANGULAR or RSB_FLAG_UPPER_TRIANGULAR flags. No flag, no vibe. πŸ’…
  • Xp β€” the input vector array.
  • incX β€” the spacing of vector elements in each input vector array, and it's got to be >=1.
  • Yp β€” the output array vector.
  • incY β€” the spacing of vector elements in each output vector array, also >=1.

Returns 🌈

RSB_ERR_NO_ERROR when everything behaves, an error code otherwise. You can hit up rsb_strerror_r() or rsb_perror() to find out what actually went wrong. And lowkey important: if --enable-zero-division-checks-on-solve was specified at configure time, then attempts to solve a triangular matrix with zeroes on a diagonal will just fail. πŸ’€

Example: backsolving a triangular system 🧚

if((errval = rsb_spsv(RSB_TRANSPOSITION_N,&one,mtxAp,X,1,X,1))
                != RSB_ERR_NO_ERROR )
{
        printf("Error performing triangular solve!\n");
        goto err;
}

See also πŸ‘‘

rsb_spsm, rsb_spsv, rsb_tune_spsm


rsb_err_t rsb_strerror_r (rsb_err_t errval, rsb_char_t * buf, size_t buflen)

Writes a textual description of an error code into the string buffer you give it. It will never write more than buflen characters β€” and yes, that count is comprehensive of the terminating NUL character, so budget for the NUL too 🫢. And if you pass in RSB_ERR_NO_ERROR, it does absolutely nothing, no action performed. Another thing, and this one trips people up: error flags can't be added together the way regular flags can. Like, (RSB_ERR_GENERIC_ERROR|RSB_ERR_BADARGS) just evaluates to RSB_ERR_GENERIC_ERROR. Not a combo, not a merge β€” it just fully collapses. 😭

Parameters

  • errval β€” a valid error flag value (see rsb_err_t).
  • buf β€” a valid string buffer pointer, this is where the writing happens.
  • buflen β€” the string buffer length.

Returns

RSB_ERR_NO_ERROR on correct operation, an error code otherwise. You can use rsb_strerror_r() or rsb_perror() to get more information about the error.

Examples:

                        char errbuf[256];
                        rsb_strerror_r(errval,&errbuf[0],sizeof(errbuf));
                        printf("Failed setting the"
                        " RSB_IO_WANT_EXTRA_VERBOSE_INTERFACE"
                        " library option (reason string:\n%s).\n",errbuf);

or

rsb_err_t errval = RSB_ERR_INTERNAL_ERROR;

// ...

if(errval != RSB_ERR_NO_ERROR)
{
        char errbuf[256];

        rsb_strerror_r(errval,&errbuf[0],sizeof(errbuf));

        // error handling ...

See also

rsb_perror, rsb_strerror_r


rsb_time_t rsb_time (void )

Returns the current time in seconds. This one is here for computing wall clock time intervals β€” think benchmarking, think "how long did that actually take" ✨. But do not, and I mean do not, rely on this function for absolute time computations. That is not its job and it is not that girl for it πŸ’….

Returns

A value for the current time, in seconds.

See also

rsb_time, rsb_coo_sort


rsb_err_t rsb_tune_spmm (struct rsb_mtx_t ** mtxOpp, rsb_real_t * sfp, rsb_int_t * tnp, rsb_int_t maxr, rsb_time_t maxt, rsb_trans_t transA, const void * alphap, const struct rsb_mtx_t * mtxAp, rsb_coo_idx_t nrhs, rsb_flags_t order, const void * Bp, rsb_nnz_idx_t ldB, const void * betap, void * Cp, rsb_nnz_idx_t ldC)

An auto-tuner ✨ β€” it optimizes either the matrix instance, the thread count, or both, all for the rsb_spmm operation.

The way it works is it evaluates a bunch of different instances and working-threads variants. Whichever instance gives you the faster operation time gets retained and handed back to you in *mtxOpp. If nrhs==1 and order==RSB_FLAG_WANT_COLUMN_MAJOR_ORDER, then unitary stride vectors are assumed. And if something goes wrong, the original input matrix shall stay unaffected. You can also specify the leading dimensions of Bp,Cp implicitly with ldB=0 and ldC=0 β€” when you do that, their values get computed internally, and if Bp!=NULL,Cp!=NULL they'll just be assumed to be sufficiently sized. Values of nrhs<1 get treated as 1. Bp and Cp can be NULL: temporary vectors will be allocated, used, and deallocated right inside the tuner. If mtxOpp=NULL and *tnp!=NULL, the best thread count gets probed for the matrix given in mtxAp. But heads up β€” if you ask for threads-only tuning and the matrix has too few leaves (see RSB_MIF_LEAVES_COUNT__TO__RSB_BLK_INDEX_T), tuning will not work. If mtxAp==NULL, then the *mtxOpp instance gets used instead; however, in that case, if a better instance is found, the original will be destroyed just as with rsb_mtx_free(). And the case mtxAp!=NULL&&*mtxOpp!=NULL is illegal and will make error code RSB_ERR_BADARGS come back at you. πŸ’€

Parameters

  • mtxOpp β€” the optimal matrix structure pointer gets assigned to *mtxOpp (it can totally happen that *mtxOpp==mtxAp on output, bestie, don't be shocked). If mtxOpp is NULL then no data structure optimization is attempted at all β€” only the optimal threads search happens, and tnp must be not NULL then.
  • sfp β€” the achieved speedup factor gets written to *sfp, unless sfp==NULL.
  • tnp β€” if tnp==NULL on input, the current thread count is used. Otherwise, if *tnp>0, then *tnp is used as the first suggestion in the optimal thread count searching. If tnp!=NULL, on output *tnp gets set to contain the optimal number of threads. After that, you're expected to set this number of threads yourself, e.g. with: RSB_REINIT_SINGLE_VALUE_SET(RSB_IO_WANT_EXECUTING_THREADS,tnp,errval). Please note this affects the whole library's operation, not just this matrix. 🌈
  • maxr β€” optimizer rounds max count. If it's <1, it's treated as 1; if it's 0, it gets decided automatically. The max is RSB_CONST_MAX_TUNING_ROUNDS.
  • maxt β€” maximum time in seconds per optimization round (and no, it does not take conversion time into account). If maxt<0.0 is provided, then -ceil(maxt) gets interpreted as the number of iterations to check for each operation time sample. If maxt==0.0 is provided, a default choice gets made instead.
  • transA β€” the transposition parameter for $A$ (see matrix_transposition_flags_section).
  • alphap β€” an optional pointer (if NULL, it defaults to 1) to a numerical value of the same type as the matrix.
  • mtxAp β€” a valid rsb_mtx_t pointer to the matrix $A$ representation.
  • nrhs β€” the number of right hand side vectors (cannot be <1).
  • order β€” a flag among RSB_FLAG_WANT_COLUMN_MAJOR_ORDER and RSB_FLAG_WANT_ROW_MAJOR_ORDER. For contiguous vector arrays, you probably want RSB_FLAG_WANT_COLUMN_MAJOR_ORDER.
  • Bp β€” the input vector array. If it's NULL, a temporary, internally allocated copy gets used.
  • ldB β€” leading dimension of the Bp array.
  • betap β€” an optional pointer (if NULL, it defaults to 1) to a numerical value.
  • Cp β€” the output vector array. If it's NULL, a temporary, internally allocated copy gets used.
  • ldC β€” leading dimension of the Cp array.

Returns

RSB_ERR_NO_ERROR on correct operation, an error code otherwise. You can use rsb_strerror_r() or rsb_perror() to get more information about the error.

Examples:

// obtain best thread count for mtxAp:
errval = rsb_tune_spmm(NULL  ,&sf,&tn ,maxr,maxt,transA,&alpha,mtxAp,nrhs,order,Bp,ldB,&beta,Cp,ldC);

// obtain best thread count for mtxAp; Bp and Cp will be allocated by the tuner:
errval = rsb_tune_spmm(NULL  ,&sf,&tn ,maxr,maxt,transA,&alpha,mtxAp,nrhs,order,NULL,0,&beta,NULL,0);

// obtain best clone of mtxAp (for current thread count):
assert(mtxOp == NULL && mtxAp != NULL);
errval = rsb_tune_spmm(&mtxOp,&sf,NULL,maxr,maxt,transA,&alpha,mtxAp,nrhs,order,Bp,ldB,&beta,Cp,ldC);

// obtain best clone of mtxAp and best thread count:
assert(mtxOp == NULL && mtxAp != NULL);
errval = rsb_tune_spmm(&mtxOp,&sf,&tn ,maxr,maxt,transA,&alpha,mtxAp,nrhs,order,Bp,ldB,&beta,Cp,ldC);

// replace mtxAp with best clone (if any):
errval = rsb_tune_spmm(&mtxAp,&sf,NULL,maxr,maxt,transA,&alpha,NULL ,nrhs,order,Bp,ldB,&beta,Cp,ldC);

// replace mtxAp with best clone (if any) and obtain best thread count:
errval = rsb_tune_spmm(&mtxAp,&sf,&tn ,maxr,maxt,transA,&alpha,NULL ,nrhs,order,Bp,ldB,&beta,Cp,ldC);

// illegal call:
assert(mtxOp != NULL && mtxAp != NULL);
errval = rsb_tune_spmm(&mtxOp,&sf,&tn ,maxr,maxt,transA,&alpha,mtxAp,nrhs,order,Bp,ldB,&beta,Cp,ldC);

Warning ⚠️

This function is still experimental, bestie. In case of error, even though the matrix shall be unaffected, the library status may be affected β€” stuff like execution thread count, default matrix subdivision. So yeah, be mindful. 😭

Todo πŸ“

Autotuning functionality is still object of much research. Need support for lightweight, threads-only optimization.

Sample matrix sparse block structure before tuning

Sample matrix sparse block structure after tuning

See also πŸ¦‹

rsb_spmv, rsb_spmm, rsb_spata, rsb_tune_spmm


rsb_err_t rsb_tune_spsm (struct rsb_mtx_t ** mtxOpp, rsb_real_t * sfp, rsb_int_t * tnp, rsb_int_t maxr, rsb_time_t maxt, rsb_trans_t transA, const void * alphap, const struct rsb_mtx_t * mtxAp, rsb_coo_idx_t nrhs, rsb_flags_t order, const void * Bp, rsb_nnz_idx_t ldB, const void * betap, void * Cp, rsb_nnz_idx_t ldC)

An auto-tuner ✨ β€” it optimizes either the matrix instance, the thread count, or both, for the rsb_spsm operation. πŸ’…

okay bestie so the tuner?? it literally just tries out a bunch of different instance + working-thread variants and ✨vibe checks✨ them. Whichever instance gives you the faster operation time gets to stay, and that's the one handed back to you in *mtxOpp. πŸ’…

If nrhs==1 and order==RSB_FLAG_WANT_COLUMN_MAJOR_ORDER, then unitary stride vectors are assumed, periodt.

If something goes wrong (😭), the original input matrix shall be unaffected β€” no cap.

And here's a cute little shortcut: you can specify the leading dimensions of Bp,Cp implicitly with ldB=0 and ldC=0. In that case their values get computed internally, and if Bp!=NULL,Cp!=NULL, they'll just be assumed to be sufficiently sized. ngl, convenient. Values of nrhs<1 will be treated as 1. πŸ’–

Bp, Cp can totally be NULL β€” then temporary vectors get allocated, used, and deallocated inside the tuner. Girl boss of resource management fr.

If mtxOpp==NULL and *tnp!=NULL, the best thread count will be probed for the matrix given in mtxAp. But ⚠️ heads up: if threads-only tuning is requested and the matrix has too few leaves (see RSB_MIF_LEAVES_COUNT__TO__RSB_BLK_INDEX_T), tuning will not work.

If mtxAp==NULL, then the *mtxOpp instance will be used β€” however, in this case, if a better instance is found, the original will be destroyed, exactly as with rsb_mtx_free(). πŸ’€ so like, be aware.

The case mtxAp!=NULL&&*mtxOpp!=NULL is illegal and will cause error code RSB_ERR_BADARGS to be returned. 🚫 no, ma'am.


🌸 Parameters 🌸

  • mtxOpp β€” Optimal matrix structure pointer will be assigned to *mtxOpp (it may occur that *mtxOpp==mtxAp on output). If mtxOpp is NULL then no data structure optimization will be attempted; rather, only optimal threads search will occur (tnp must be not NULL then).
  • sfp β€” Achieved speedup factor will be written to *sfp (unless sfp==NULL).
  • tnp β€” If tnp==NULL on input, the current thread count will be utilized. Otherwise, if *tnp>0, then *tnp will be used as first suggestion in optimal thread count searching. If tnp!=NULL ,on output *tnp will be set to contain the optimal number of threads. Then, the user is expected to set this number of threads using e.g.:
RSB_REINIT_SINGLE_VALUE_SET(RSB_IO_WANT_EXECUTING_THREADS,tnp,errval).

Please note that this will affect the whole library operation, not only this matrix. πŸ‘‘ (main character energy: this setting touches EVERYTHING)

  • maxr β€” Optimizer rounds max count. If <1, will be treated as 1; if 0 will be decided automatically. Max is RSB_CONST_MAX_TUNING_ROUNDS.
  • maxt β€” Maximum time (in seconds) per optimization round (does not take in account conversion time). If maxt<0.0 is provided, -ceil(maxt) will be interpreted as number of iterations to check for each operation time sample. If maxt==0.0 is provided, a default choice will be made instead.
  • transA β€” Transposition parameter for $A$ (see matrix_transposition_flags_section).
  • alphap β€” Optional pointer (if NULL, will default to 1) to a numerical value (of the same type as matrix).
  • mtxAp β€” Valid rsb_mtx_t pointer to matrix $A$ representation.
  • nrhs β€” The number of right hand side vectors (cannot be <1).
  • order β€” A flag among RSB_FLAG_WANT_COLUMN_MAJOR_ORDER and RSB_FLAG_WANT_ROW_MAJOR_ORDER. For contiguous vector arrays, you probably want RSB_FLAG_WANT_COLUMN_MAJOR_ORDER. 🫢
  • Bp β€” The input vector array. If NULL, a temporary, internally allocated copy will be used.
  • ldB β€” Leading dimension of Bp array.
  • betap β€” Optional pointer (if NULL, will default to 1) to a numerical value.
  • Cp β€” The output vector array. If NULL, a temporary, internally allocated copy will be used.
  • ldC β€” Leading dimension of Cp array.

πŸ’– Returns πŸ’–

RSB_ERR_NO_ERROR on correct operation, an error code otherwise. You can use rsb_strerror_r() or rsb_perror() to get more information about the error. πŸ”

If --enable-zero-division-checks-on-solve was specified at configure time, attempts to solve a triangular matrix with zeroes on a diagonal will fail. 🚨 (good, honestly, protect yourself)


🌈 Warning 🌈

This function is still experimental πŸ‘©β€πŸ”¬. In case of error, although the matrix shall be unaffected, the library status may be affected (e.g.: execution thread count, default matrix subdivision). πŸ™ˆ so like... keep an eye on your library state bestie, not just your matrix.

πŸŽ€ Todo πŸŽ€

Autotuning functionality is still object of much research. Need support for lightweight, threads-only optimization. πŸ“


🌷 Sample matrix sparse block structure before tuning πŸ¦‹ Sample matrix sparse block structure after tuning

(iconic glow-up, fr)


🌟 See also 🌟

rsb_spsm, rsb_spsv, rsb_tune_spsm

rsb_tune_spmm


🌸 Author 🌸

librsb was written by Michele Martone; this documentation has been generated by Doxygen. πŸ’œ


✨ SEE ALSO ✨

rsb-examples rsb-spblas.h rsb.h rsb.hpp


and that's a wrap on the whole page bestie!! πŸŽ‰ this was librsb, Version 1.3.0.3, the rsb.h(3) page β€” go forth and tune those matrices, you absolute icon πŸ‘‘πŸ’…βœ¨

πŸ“¦ where this page comes from