Provided by: librsb-dev_1.3.0.2+dfsg-6.1build1_amd64 bug

NAME

       librsb - rsb-examples - Example programs and code

DESCRIPTION

        - Examples of usage of librsb in C (<rsb.h> and <blas_sparse.h>), C++ (optional
       <rsb.hpp>), Fortran (<rsb.F90> and <rsb_blas_sparse.F90>).

SYNOPSIS

   Files
       file assemble.cpp
           C++ example based on <rsb.hpp> assembling RsbMatrix by pieces.
       file autotune.cpp
           C++ example based on <rsb.hpp> for performance-benchmarking a matrix from file using
           RsbMatrix.tune_spmm(), for various right-hand side counts.
       file bench.cpp
           C++ example based on <rsb.hpp> for performance-benchmarking a matrix from file using
           RsbMatrix.spmm(), for various right-hand side counts.
       file build.cpp
           C++ example based on <rsb.hpp> using timings for common matrix operations on
           RsbMatrix: RsbMatrix.get_coo(), rsb_coo_sort(), rsb_time().
       file example.cpp
           C++ example based on <rsb.hpp> using RsbMatrix.spmm().
       file misc.cpp
           C++ example based on <rsb.hpp> showing various RsbMatrix operations.
       file mtx2bin.cpp
           C++ example based on <rsb.hpp> converting a Matrix Market file into a custom format
           using RsbMatrix.get_coo().
       file render.cpp
           C++ example based on <rsb.hpp> of invoking the autotuner on an RsbMatrix matrix with
           RsbMatrix.tune_spmm() and rendering it with RsbMatrix.rndr().
       file span.cpp
           C++ example based on <rsb.hpp> illustrating use of RsbMatrix.file_save(), and
           std::span-based versions of RsbMatrix.tune_spmm(), RsbMatrix.spmv().
       file twonnz.cpp
           C++ example based on <rsb.hpp> measuring RsbMatrix.spmm() performance of a matrix with
           only two elements; this is is effectively measuring performance of result vector
           scaling.
       file autotune.c
           C 'RSB autotune' example program based on <rsb.h>. uses rsb_file_mtx_load(),
           rsb_spmm(), rsb_tune_spmm().
       file backsolve.c
           C triangular solve example program. Uses rsb_spsv(),rsb_tune_spsm(). Based on <rsb.h>.
       file cplusplus.cpp
           C++ program using the C <rsb.h> interface. Uses rsb_tune_spmm(), rsb_spmv().
       file hello-spblas.c
           A first C 'hello RSB' example program using a Sparse BLAS interface and <rsb.h>. Uses
           BLAS_duscr_begin(), BLAS_ussp(), BLAS_usgp(), BLAS_duscr_insert_entries(),
           BLAS_duscr_end(), BLAS_dusget_element(),BLAS_dusmv(),BLAS_usds().
       file hello.c
           A first 'hello RSB' example C program based on <rsb.h>. Uses rsb_lib_set_opt(),
           rsb_mtx_get_info_str().
       file io-spblas.c
           Example C program using the Sparse BLAS interface and reading from file using
           rsb_blas_file_mtx_load(), BLAS_usgp(), BLAS_dusmv(), BLAS_usds().
       file power.c
           A toy <rsb.h>-based C program implementing the power method for computing matrix
           eigenvalues. Uses rsb_spmv().
       file snippets.c
           Collection of C snippets of other examples. Used piecewise the documentation. Not
           intended to be read as example.
       file transpose.c
           A toy <rsb.h>-based C program showing instantiation, transposition and other
           operations on a single matrix. Uses rsb_mtx_clone(), rsb_file_mtx_save(),
           rsb_file_mtx_get_dims(), rsb_file_mtx_load().

Detailed Description

       Examples of usage of librsb in C (<rsb.h> and <blas_sparse.h>), C++ (optional <rsb.hpp>),
       Fortran (<rsb.F90> and <rsb_blas_sparse.F90>).

          The following fully working example programs illustrate correct ways of using the library.

       • First example in C, using <rsb.h>: examples_hello_c.

       • First example in C, using <blas_sparse.h>: examples_hello_spblas_c.

       • Autotuning example in C, using <rsb.h>: examples_autotune_c.

       • I/O example in C, using <blas_sparse.h>: examples_io_spblas_c.

       • Example transposing a matrix in C, using <rsb.h> in C: examples_transpose_c.

       • Example showing the power method in C, using <rsb.h> in C: examples_power_c.

       • Example in Fortran, using <rsb_blas_sparse.F90>: examples_fortran_F90.

       • Example in Fortran, using <rsb.F90>: examples_fortran_rsb_fi_F90.

       • Example in C, using <rsb.h>: examples_backsolve_c.

       • Misc example snippets in C, using <rsb.h>: examples_snippets_c.

       • Benchmark invocation from shell script: examples_bench_sh.

       Once installed librsb, the script displayed here (examples/make.sh) should be sufficient
       to build these examples:

       #!/bin/bash
       # Example script to build the librsb example programs.
       # Uses librsb-config in the $PATH for build flags.
       # Environment-provided $LIBRSB_CONFIG override that.
       set -e
       set -x

       srcdir=${srcdir:-`pwd`}
       builddir=${builddir:-`pwd`}
       prefix="/usr"
       exec_prefix="${prefix}"
       bindir="${exec_prefix}/bin"
       if test -z "${LIBRSB_CONFIG}"; then
               export PATH="${bindir}:$PATH"
       fi
       LIBRSB_CONFIG=${LIBRSB_CONFIG:-librsb-config}
       PKG_CONFIG=pkg-config
       WANT_PKGCONFIG="yes"
       WANT_CLEANUP=${WANT_CLEANUP:-false}

       if test x"yes" == x"yes" ; then
       CXX="`${LIBRSB_CONFIG} --cxx`"
       if test x"rsblib" != x"" -a x"${CXX}" != x"" ; then
       for s in ${srcdir}/*.cpp
       do
               p=${builddir}/`basename ${s/.cpp/}`
               rm -f $p
               CXXFLAGS=`${LIBRSB_CONFIG} --cxxflags --I_opts`
               LDFLAGS=`${LIBRSB_CONFIG} --ldflags --extra_libs`
               LINK=`${LIBRSB_CONFIG} --link`
               o="${p}.o"
               ccmd="$CXX $CXXFLAGS -c $s -o $o"
               lcmd="$LINK $o $LDFLAGS -o $p"
               echo "$ccmd && $lcmd"
               ( $ccmd && $lcmd )
               ${WANT_CLEANUP} && rm -f "$p"
               # one may use a single command, but that's error-prone (may miss libraries):
               #cmd="$CXX $CXXFLAGS $s $LDFLAGS -o $p"
               #echo $cmd
               #$cmd
       done
       fi
       fi

       if test x"yes" == x"yes" ; then
       for s in ${srcdir}/*.c
       do
               p=`basename ${s/.c/}`
               if test $p == hello-spblas -a x"yes" != x"yes" ; then continue; fi
               if test $p ==    io-spblas -a x"yes" != x"yes" ; then continue; fi
               rm -f $p
               CFLAGS=`${LIBRSB_CONFIG} --I_opts --cppflags`
               LDFLAGS=`${LIBRSB_CONFIG} --ldflags --extra_libs`
               CC=`${LIBRSB_CONFIG} --cc`
               LINK=`${LIBRSB_CONFIG} --link`
               o="${p}.o"
               ccmd="$CC $CFLAGS -c $s -o $o"
               lcmd="$LINK $o $LDFLAGS -o $p"
               echo "$ccmd && $lcmd"
               ( $ccmd && $lcmd )
               ${WANT_CLEANUP} && rm -f "$p"
               # one may use a single command, but that's error-prone (may miss libraries):
               #cmd="$CC $CFLAGS $s $LDFLAGS -o $p"
               #echo $cmd
               #$cmd
               if test x"${WANT_PKGCONFIG}" != x"no" ; then
                       CFLAGS=`${PKG_CONFIG} --cflags librsb`
                       LIBS=`${PKG_CONFIG} --libs --static librsb`
                       ccmd="$CC $CFLAGS -c $s -o $o"
                       lcmd="$LINK $o $LIBS -o $p"
                       ${WANT_CLEANUP} && rm -f "$p"
                       echo "$ccmd && $lcmd"
                       ( $ccmd && $lcmd )
               fi
       done
       fi

       if test x"yes" == x"yes" ; then
       if test x"yes" = x"yes" ; then
       FP=${srcdir}/fortran_rsb_fi.F90
       if test x"yes" = x"yes" ; then
               FP+=\ ${srcdir}/fortran.F90
       fi
       # activated if you have built the Fortran modules and installed them in the right path.
       for s in $FP
       do
               p=`basename ${s/.F90/}`
               rm -f $p
               FCFLAGS=`${LIBRSB_CONFIG} --I_opts --fcflags`
               LDFLAGS=`${LIBRSB_CONFIG} --ldflags --extra_libs`
               FC=`${LIBRSB_CONFIG} --fc`
               LINK=`${LIBRSB_CONFIG} --link`
               o="${p}.o"
               FCLIBS=`${LIBRSB_CONFIG} --fclibs`
               ccmd="$FC $FCFLAGS -c $s -o $o"
               lcmd="$LINK $o $LDFLAGS $FCLIBS -o $p"
               echo "$ccmd && $lcmd"
               ( $ccmd && $lcmd )
               ${WANT_CLEANUP} && rm -f "$p"
       done
       fi
       fi

       echo " [*] done building examples!"

        examples/hello.c:

       /*

       Copyright (C) 2008-2021 Michele Martone

       This file is part of librsb.

       librsb is free software; you can redistribute it and/or modify it
       under the terms of the GNU Lesser General Public License as published
       by the Free Software Foundation; either version 3 of the License, or
       (at your option) any later version.

       librsb is distributed in the hope that it will be useful, but WITHOUT
       ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
       License for more details.

       You should have received a copy of the GNU Lesser General Public
       License along with librsb; see the file COPYING.
       If not, see <http://www.gnu.org/licenses/>.

       */
       /*!
        \ingroup rsb-examples
        @file
        @author Michele Martone

        @brief A first "hello RSB" example C program based on <rsb.h>.
          Uses #rsb_lib_set_opt(), #rsb_mtx_get_info_str().

        \include hello.c
       */
       #include <rsb.h> /* librsb header to include */
       #include <stdio.h>       /* printf() */

       int main(const int argc, char * const argv[])
       {
               /*!
                 A Hello-RSB program.

                 This program shows how to use the rsb.h interface correctly to:

                 - initialize the library using #rsb_lib_init()
                 - set library options using #rsb_lib_set_opt()
                 - revert such changes
                 - allocate (build) a single sparse matrix in the RSB format
                   using #rsb_mtx_alloc_from_coo_const()
                 - prints information obtained via #rsb_mtx_get_info_str()
                 - multiply the matrix times a vector using #rsb_spmv()
                 - deallocate the matrix using #rsb_mtx_free()
                 - finalize the library using #rsb_lib_exit()

                 In this example, we use #RSB_DEFAULT_TYPE as matrix type.
                 This type depends on what was configured at library build time.
                * */
               const rsb_blk_idx_t bs = RSB_DEFAULT_BLOCKING;
               const rsb_blk_idx_t brA = bs, bcA = bs;
               const RSB_DEFAULT_TYPE one = 1;
               const rsb_type_t typecode = RSB_NUMERICAL_TYPE_DEFAULT;
               const rsb_nnz_idx_t nnzA = 4;           /* matrix nonzeroes count */
               const rsb_coo_idx_t nrA = 3;            /* matrix rows count */
               const rsb_coo_idx_t ncA = 3;            /* matrix columns count */
               /* nonzero row indices coordinates: */
               const rsb_coo_idx_t IA[] = {0,1,2,2};
               /* nonzero column indices coordinates: */
               const rsb_coo_idx_t JA[] = {0,1,2,2};
               const RSB_DEFAULT_TYPE VA[] = {11,22,32,1};/* values of nonzeroes */
               RSB_DEFAULT_TYPE X[] = { 0, 0, 0 };     /* X vector's array */
               const RSB_DEFAULT_TYPE B[] = { -1, -2, -5 }; /* B vector's array */
               char ib[200];
               struct rsb_mtx_t *mtxAp = NULL; /* matrix structure pointer */
               rsb_err_t errval = RSB_ERR_NO_ERROR;

               printf("Hello, RSB!\n");
               printf("Initializing the library...\n");
               if((errval = rsb_lib_init(RSB_NULL_INIT_OPTIONS)) !=
                               RSB_ERR_NO_ERROR)
               {
                       printf("Error initializing the library!\n");
                       goto err;
               }
               printf("Correctly initialized the library.\n");

               printf("Attempting to set the"
                      " RSB_IO_WANT_EXTRA_VERBOSE_INTERFACE library option.\n");
               {
                       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)
                       {
                               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);
                               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;
                       }
               }

               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;
               }
               printf("Correctly allocated a matrix.\n");
               printf("Summary information of the matrix:\n");
               /* print out the matrix summary information  */
               rsb_mtx_get_info_str(mtxAp,"RSB_MIF_MATRIX_INFO__TO__CHAR_P",
                               ib,sizeof(ib));
               printf("%s",ib);
               printf("\n");

               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;
               }
               printf("Correctly performed a SPMV.\n");
               rsb_mtx_free(mtxAp);
               printf("Correctly freed the matrix.\n");
               if((errval = rsb_lib_exit(RSB_NULL_EXIT_OPTIONS))
                               != RSB_ERR_NO_ERROR)
               {
                       printf("Error finalizing the library!\n");
                       goto err;
               }
               printf("Correctly finalized the library.\n");
               printf("Program terminating with no error.\n");
               return EXIT_SUCCESS;
       err:
               rsb_perror(NULL,errval);
               printf("Program terminating with error.\n");
               return EXIT_FAILURE;
       }

        examples/hello-spblas.c:

       /*

       Copyright (C) 2008-2021 Michele Martone

       This file is part of librsb.

       librsb is free software; you can redistribute it and/or modify it
       under the terms of the GNU Lesser General Public License as published
       by the Free Software Foundation; either version 3 of the License, or
       (at your option) any later version.

       librsb is distributed in the hope that it will be useful, but WITHOUT
       ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
       License for more details.

       You should have received a copy of the GNU Lesser General Public
       License along with librsb; see the file COPYING.
       If not, see <http://www.gnu.org/licenses/>.

       */
       /*!
        \ingroup rsb-examples
        @file
        @author Michele Martone

        @brief A first C "hello RSB" example program using
               a Sparse BLAS interface and <rsb.h>.
               Uses #BLAS_duscr_begin(), #BLAS_ussp(), #BLAS_usgp(),
               #BLAS_duscr_insert_entries(), #BLAS_duscr_end(),
               #BLAS_dusget_element(),#BLAS_dusmv(),#BLAS_usds().

        \include hello-spblas.c
       */
       #include <rsb.h> /* for rsb_lib_init */
       #include <blas_sparse.h> /* Sparse BLAS on the top of librsb */
       #include <stdio.h>       /* printf */

       int main(const int argc, char * const argv[])
       {
               /*!
                * A Hello/Sparse BLAS program.
                *
                * This program shows how to use the blas_sparse.h
                * interface correctly to:
                *
                * - initialize the library using #rsb_lib_init()
                * - allocate (build) a single sparse matrix in the RSB
                *   format using #BLAS_duscr_begin()/#BLAS_duscr_insert_entries()
                *   /#BLAS_duscr_end()
                * - extract one matrix element with #BLAS_dusget_element()
                * - multiply the matrix times a vector using #BLAS_dusmv()
                * - deallocate the matrix using #BLAS_usds()
                * - finalize the library using
                *   #rsb_lib_exit(#RSB_NULL_EXIT_OPTIONS)
               */
       #ifndef RSB_NUMERICAL_TYPE_DOUBLE
               printf("'double' type configured out."
               " Please reconfigure the library with it and recompile.\n");
               return EXIT_SUCCESS;
       #else /* RSB_NUMERICAL_TYPE_DOUBLE */
               blas_sparse_matrix A = blas_invalid_handle; /* handle for A */
               const int nnz = 4;      /* number of nonzeroes of matrix A */
               const int  nr = 3;      /* number of A's rows */
               const int  nc = 3;      /* number of A's columns */
               /* A's nonzero elements row indices (coordinates): */
       #ifdef RSB_WANT_LONG_IDX_TYPE
               const int64_t IA[] = { 0, 1, 2, 2 };
       #else /* RSB_WANT_LONG_IDX_TYPE */
               const int   IA[] = { 0, 1, 2, 2 };
       #endif /* RSB_WANT_LONG_IDX_TYPE */
               /* A's nonzero elements column indices (coordinates): */
       #ifdef RSB_WANT_LONG_IDX_TYPE
               const int64_t JA[] = { 0, 1, 0, 2 };
       #else /* RSB_WANT_LONG_IDX_TYPE */
               const int   JA[] = { 0, 1, 0, 2 };
       #endif /* RSB_WANT_LONG_IDX_TYPE */
               /* A's nonzero values (matrix coefficients): */
               double VA[] = { 11.0, 22.0, 13.0, 33.0  };
               /* the X vector's array: */
               double X[] = { 0.0, 0.0, 0.0 };
               /* the B vector's array: */
               const double B[] = { -1.0, -2.0, -2.0 };
               /* the (known) result array: */
               const double AB[] = { 11.0+26.0, 44.0, 66.0+13.0 };
               /* rsb error variable: */
               rsb_err_t errval = RSB_ERR_NO_ERROR;
               int i;

               printf("Hello, RSB!\n");
               /* initialize the library */
               if((errval = rsb_lib_init(RSB_NULL_INIT_OPTIONS))
                               != RSB_ERR_NO_ERROR)
               {
                       goto err;
               }
               printf("Correctly initialized the library.\n");

               /* initialize a matrix descriptor */
               A = BLAS_duscr_begin(nr,nc);
               if( A == blas_invalid_handle )
               {
                       goto err;
               }

               /* specify properties (e.g.: symmetry)*/
               if( BLAS_ussp(A,blas_lower_symmetric) != 0 )
               {
                       goto err;
               }

               /* get properties (e.g.: symmetry) */
               if( BLAS_usgp(A,blas_lower_symmetric) != 1 )
               {
                       printf("Symmetry property non set ?!\n");
                       goto err;
               }

               /* insert the nonzeroes (here, all at once) */
               if( BLAS_duscr_insert_entries(A, nnz, VA, IA, JA)
                               == blas_invalid_handle)
               {
                       goto err;
               }

               /* finalize (allocate) the matrix build  */
               if( BLAS_duscr_end(A) == blas_invalid_handle )
               {
                       goto err;
               }
               printf("Correctly allocated a matrix.\n");

               VA[0] = 0.0;
               if( BLAS_dusget_element(A, IA[0], JA[0], &VA[0]) )
               {
                       goto err;
               }

               /* a check */
               if( VA[0] != 11.0 )
               {
                       goto err;
               }

               /* compute X = X + (-1) * A * B   */
               if(BLAS_dusmv(blas_no_trans,-1,A,B,1,X,1))
               {
                       goto err;
               }

               for( i = 0 ; i < nc; ++i )
                       if( X[i] != AB[i] )
                       {
                               printf("Computed SPMV result seems wrong. Terminating.\n");
                               goto err;
                       }
               printf("Correctly performed a SPMV.\n");

               /* deallocate matrix A */
               if( BLAS_usds(A) )
               {
                       goto err;
               }
               printf("Correctly freed the matrix.\n");

               /* finalize the library */
               if((errval = rsb_lib_exit(RSB_NULL_EXIT_OPTIONS))
                               != RSB_ERR_NO_ERROR)
               {
                       goto err;
               }
               printf("Correctly finalized the library.\n");
               printf("Program terminating with no error.\n");

               return EXIT_SUCCESS;
       err:
               rsb_perror(NULL,errval);
               printf("Program terminating with error.\n");
               return EXIT_FAILURE;
       #endif /* RSB_NUMERICAL_TYPE_DOUBLE */
       }

        examples/autotune.c:

       /*

       Copyright (C) 2008-2021 Michele Martone

       This file is part of librsb.

       librsb is free software; you can redistribute it and/or modify it
       under the terms of the GNU Lesser General Public License as published
       by the Free Software Foundation; either version 3 of the License, or
       (at your option) any later version.

       librsb is distributed in the hope that it will be useful, but WITHOUT
       ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
       License for more details.

       You should have received a copy of the GNU Lesser General Public
       License along with librsb; see the file COPYING.
       If not, see <http://www.gnu.org/licenses/>.

       */
       /*!
        \ingroup rsb-examples
        @file
        @author Michele Martone

        @brief C "RSB autotune" example program based on <rsb.h>.
          uses #rsb_file_mtx_load(), rsb_spmm(), rsb_tune_spmm().

        \include autotune.c
       */
       #include <rsb.h> /* librsb header to include */
       #include <stdio.h>       /* printf() */
       #include <ctype.h>       /* isdigit() */
       #include <stdlib.h>      /* atoi() */
       /* #include "rsb_internals.h" */

       static int tune_from_file(char * const filename, rsb_int_t wvat)
       {
               struct rsb_mtx_t *mtxMp = NULL;
               /* spmv specific variables */
               const void * alphap = NULL; // equivalent to 1
               const void * betap = NULL; // equivalent to 1
               rsb_flags_t order = RSB_FLAG_WANT_COLUMN_MAJOR_ORDER;
               const rsb_coo_idx_t nrhs = 2;  /* number of right hand sides */
               rsb_trans_t transA = RSB_TRANSPOSITION_N; /* transposition */
               rsb_nnz_idx_t ldB = 0;
               rsb_nnz_idx_t ldC = 0;
               /* misc variables */
               rsb_err_t errval = RSB_ERR_NO_ERROR;
               rsb_time_t dt;
               char ib[200];
               const char*is = "RSB_MIF_MATRIX_INFO__TO__CHAR_P";
               /* misc variables */
               /* input autotuning variables */
               rsb_int_t oitmax = 1 /*15*/;    /* auto-tune iterations */
               rsb_time_t tmax = 0.1;   /* time per autotune operation */
               /* output autotuning variables */
               rsb_flags_t flagsA = RSB_FLAG_NOFLAGS;
               /* int ione = 1; */
               rsb_type_t typecodea [] = RSB_MATRIX_TYPE_CODES_ARRAY;
               int typecodei;

               errval = rsb_lib_init(RSB_NULL_INIT_OPTIONS);

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

               errval = rsb_lib_set_opt(RSB_IO_WANT_VERBOSE_TUNING, &wvat );

               /*
               errval = rsb_lib_set_opt(RSB_IO_WANT_EXTRA_VERBOSE_INTERFACE, &ione);
               */

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

               printf("Loading matrix from file \"%s\".\n",filename);

               mtxMp = rsb_file_mtx_load(filename, flagsA, typecodea[0], &errval);

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

               for( typecodei = 0 ; typecodei < RSB_IMPLEMENTED_TYPES; ++typecodei )
               {
                       rsb_type_t typecode = typecodea[typecodei];
                       struct rsb_mtx_t *mtxAp = NULL;
                       struct rsb_mtx_t *mtxOp = NULL;
                       rsb_real_t sf = 0.0;
                       rsb_int_t tn = 0;

                       sf = 0.0;
                       tn = 0;

                       printf("Considering %c clone.\n",typecode);

                       errval = rsb_mtx_clone(&mtxAp, typecode, transA, NULL, mtxMp,
                                       flagsA);

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

                       printf("Base matrix:\n");
                       rsb_mtx_get_info_str(mtxAp,is,ib,sizeof(ib));
                       printf("%s\n\n",ib);

                       dt = -rsb_time();
                       errval = rsb_tune_spmm(NULL, &sf, &tn, oitmax, tmax, transA,
                            alphap, mtxAp, nrhs, order, NULL, ldB, betap, NULL, ldC);

                       dt += rsb_time();
                       if(tn == 0)
                       printf("After %lfs, autotuning routine did not find a better"
                               " threads count configuration.\n",dt);
                       else
                       printf("After %lfs, thread autotuning declared speedup of %lg x,"
                               " when using threads count of %d.\n",dt,sf,tn);
                       printf("\n");

                       dt = -rsb_time();

                       mtxOp = mtxAp;
                       errval = rsb_tune_spmm(&mtxAp, &sf, &tn, oitmax, tmax, transA,
                               alphap, NULL, nrhs, order, NULL, ldB, betap, NULL, ldC);
                       if( (errval) != RSB_ERR_NO_ERROR )
                               goto err;

                       dt += rsb_time();
                       if( mtxOp == mtxAp )
                       {
                               printf("After %lfs, global autotuning found old matrix optimal,"
                               " with declared speedup %lg x when using %d threads\n",dt,sf,tn);
                       }
                       else
                       {
                               printf("After %lfs, global autotuning declared speedup of %lg x,"
                               " when using threads count of %d and a new matrix:\n",dt,sf,tn);
                               rsb_mtx_get_info_str(mtxAp,is,ib,sizeof(ib));
                               printf("%s\n",ib);
                       }
                       printf("\n");

                       /* user is expected to:
                       errval = rsb_lib_set_opt(RSB_IO_WANT_EXECUTING_THREADS,&tn);
                       and use mtxAp in SpMV.
                       */
                       rsb_mtx_free(mtxAp);
                       mtxAp = NULL;
               }
               rsb_mtx_free(mtxMp);
               mtxMp = NULL;

       err:
               rsb_perror(NULL,errval);
               if ( errval != RSB_ERR_NO_ERROR )
                       printf("Program terminating with error.\n");
               return errval;
       }

       int main(const int argc, char * const argv[])
       {
               /*!
                Autotuning example.
                */
               /* matrix variables */
               struct rsb_mtx_t *mtxAp = NULL; /* matrix structure pointer */
               const int bs = RSB_DEFAULT_BLOCKING;
               rsb_coo_idx_t nrA = 500; /* number of rows */
               rsb_coo_idx_t ncA = 500; /* number of cols */
               const rsb_type_t typecode = RSB_NUMERICAL_TYPE_DEFAULT;
               const rsb_coo_idx_t rd = 1;/* every rd rows one is non empty */
               const rsb_coo_idx_t cd = 4;/* every cd cols one is non empty */
               rsb_nnz_idx_t nnzA = (nrA/rd)*(ncA/cd); /* nonzeroes */
               rsb_coo_idx_t*IA = NULL;
               rsb_coo_idx_t*JA = NULL;
               RSB_DEFAULT_TYPE*VA = NULL;
               /* spmv specific variables */
               const RSB_DEFAULT_TYPE alpha = 1;
               const RSB_DEFAULT_TYPE beta = 1;
               RSB_DEFAULT_TYPE*Cp = NULL;
               RSB_DEFAULT_TYPE*Bp = NULL;
               rsb_flags_t order = RSB_FLAG_WANT_COLUMN_MAJOR_ORDER;
               const rsb_coo_idx_t nrhs = 2;  /* number of right hand sides */
               const rsb_trans_t transA = RSB_TRANSPOSITION_N;
               rsb_nnz_idx_t ldB = nrA;
               rsb_nnz_idx_t ldC = ncA;
               /* misc variables */
               rsb_err_t errval = RSB_ERR_NO_ERROR;
               const size_t so = sizeof(RSB_DEFAULT_TYPE);
               const size_t si = sizeof(rsb_coo_idx_t);
               rsb_time_t dt,odt;
               rsb_int_t t;
               const rsb_int_t tt = 100;       /* will repeat spmv tt times */
               char ib[200];
               const char*is = "RSB_MIF_MATRIX_INFO__TO__CHAR_P";
               /* misc counters */
               rsb_coo_idx_t ci;
               rsb_coo_idx_t ri;
               rsb_coo_idx_t ni;
               rsb_int_t nrhsi;
               /* misc variables */
               rsb_time_t etime = 0.0;
               /* input autotuning variables */
               const rsb_int_t oitmax = 15;    /* auto-tune iterations */
               const rsb_time_t tmax = 0.1;     /* time per autotune operation */
               /* input/output autotuning variables */
               rsb_int_t tn = 0;       /* threads number */
               /* output autotuning variables */
               rsb_real_t sf = 0.0;     /* speedup factor obtained from auto tuning */
               const rsb_int_t wvat = 1; /* want verbose autotuning; see
                       documentation of RSB_IO_WANT_VERBOSE_TUNING */

               if(argc > 1 && !isdigit(argv[1][0]) )
               {
                       errval = tune_from_file(argv[1],wvat);
                       goto ret;
               }

               if(argc > 1)
               {
                       nrA = ncA = atoi(argv[1]);
                       if ( nrA < RSB_MIN_MATRIX_DIM || (nrA > (RSB_MAX_MATRIX_DIM) ))
                               goto err;

                       nnzA = (nrA/rd)*(ncA/cd);
                       ldB = nrA;
                       ldC = ncA;
               }

               printf("Creating %d x %d matrix with %d nonzeroes.\n",(int)nrA,
                       (int)ncA, (int)nnzA);

               IA = calloc(nnzA, si);
               JA = calloc(nnzA, si);
               VA = calloc(nnzA, so);
               Bp = calloc(nrhs*ncA ,so);
               Cp = calloc(nrhs*nrA ,so);

               if( ! ( VA && IA && JA && Bp && Cp ) )
                       goto err;

               for(nrhsi=0;nrhsi<nrhs;++nrhsi)
                       for(ci=0;ci<ncA/cd;++ci)
                               Bp[nrhsi*ldC+ci] = 1.0;

               for(nrhsi=0;nrhsi<nrhs;++nrhsi)
                       for(ri=0;ri<nrA/rd;++ri)
                               Cp[nrhsi*ldC+ri] = 1.0;

               ni = 0;

               for(ci=0;ci<ncA/cd;++ci)
                       for(ri=0;ri<nrA/rd;++ri)
                       {
                               VA[ni] = nrA * ri + ci,
                               IA[ni] = ri;
                               JA[ni] = ci;
                               ni++;
                       }

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

               errval = rsb_lib_set_opt(RSB_IO_WANT_VERBOSE_TUNING, &wvat );
               if( (errval) != RSB_ERR_NO_ERROR )
               {
                       printf("Error setting option!\n");
                       goto err;
               }

               mtxAp = rsb_mtx_alloc_from_coo_const(
                       VA,IA,JA,nnzA,typecode,nrA,ncA,bs,bs,
                       RSB_FLAG_NOFLAGS,&errval);

               /* VA, IA, JA are not necessary anymore */
               free(VA);
               free(IA);
               free(JA);
               VA = NULL;
               IA = NULL;
               JA = NULL;

               if((!mtxAp) || (errval != RSB_ERR_NO_ERROR))
                       goto err;

               printf("Allocated matrix of %zd nonzeroes:\n",(size_t)nnzA);
               rsb_mtx_get_info_str(mtxAp,is,ib,sizeof(ib));
               printf("%s\n\n",ib);

               dt = - rsb_time();
               for(t=0;t<tt;++t)
                       /*
                          If nrhs == 1, the following is equivalent to
                          rsb_spmv(transA,alphap,mtxAp,Bp,1,betap,Cp,1);
                       */
                       rsb_spmm(transA,&alpha,mtxAp,nrhs,order,Bp,ldB,&beta,Cp,ldC);
               dt += rsb_time();
               odt = dt;
               printf("Before auto-tuning, %d multiplications took %lfs.\n",tt,dt);

               printf("Threads autotuning (may take more than %lfs)...\n",
                               oitmax*tmax);
               dt = -rsb_time();
               errval = rsb_tune_spmm(NULL, &sf, &tn, oitmax, tmax, transA,
                               &alpha, mtxAp, nrhs, order, Bp, ldB, &beta, Cp, ldC);
               dt += rsb_time();
               if(errval != RSB_ERR_NO_ERROR)
                       goto err;

               if(tn == 0)
               printf("After %lfs, autotuning routine did not find a better"
                               " threads count configuration.\n",dt);
               else
               printf("After %lfs, autotuning routine declared speedup of %lg x,"
                               " when using threads count of %d.\n",dt,sf,tn);

               errval = rsb_lib_set_opt(RSB_IO_WANT_EXECUTING_THREADS,&tn);
               if(errval != RSB_ERR_NO_ERROR)
                       goto err;

               rsb_mtx_get_info_str(mtxAp,is,ib,sizeof(ib));
               printf("%s\n",ib);

               dt = -rsb_time();
               for(t=0;t<tt;++t)
                       /*rsb_spmv(transA,&alpha,mtxAp,Bp,1,&beta,Cp,1);*/
                       rsb_spmm(transA,&alpha,mtxAp,nrhs,order,Bp,ldB,&beta,Cp,ldC);
               dt += rsb_time();
               printf("After threads auto-tuning, %d multiplications took %lfs"
                               "  --  effective speedup of %lg x\n",tt,dt,odt/dt);
               odt = dt;

               tn = 0; /* this will restore default threads count */
               errval = rsb_lib_set_opt(RSB_IO_WANT_EXECUTING_THREADS,&tn);
               if(errval != RSB_ERR_NO_ERROR)
                       goto err;
               errval = rsb_lib_get_opt(RSB_IO_WANT_EXECUTING_THREADS,&tn);
               if(errval != RSB_ERR_NO_ERROR)
                       goto err;

               printf("Matrix autotuning (may take more than %lfs; using %d"
                               " threads )...\n", oitmax*tmax, tn);

               /* A negative tn will request also threads autotuning: */
               /* tn = -tn; */

               dt = -rsb_time();
               errval = rsb_tune_spmm(&mtxAp, &sf, &tn, oitmax, tmax, transA,
                       &alpha,  NULL, nrhs, order, Bp, ldB, &beta, Cp, ldC);
               dt += rsb_time();

               if(errval != RSB_ERR_NO_ERROR)
                       goto err;

               if(tn == 0)
               printf("After %lfs, autotuning routine did not find a better"
                               " threads count configuration.\n",dt);
               else
               printf("After %lfs, autotuning routine declared speedup of %lg x,"
                               " when using threads count of %d.\n",dt,sf,tn);

               rsb_mtx_get_info_str(mtxAp,is,ib,sizeof(ib));
               printf("%s\n",ib);

               dt = -rsb_time();
               for(t=0;t<tt;++t)
                       /*rsb_spmv(transA,&alpha,mtxAp,Bp,1,&beta,Cp,1);*/
                       rsb_spmm(transA,&alpha,mtxAp,nrhs,order,Bp,ldB,&beta,Cp,ldC);
               dt += rsb_time();
               printf("After threads auto-tuning, %d multiplications took %lfs"
                               "  --  further speedup of %lg x\n",tt,dt,odt/dt);

               rsb_mtx_free(mtxAp);
               free(Cp);
               free(Bp);

               errval = rsb_lib_get_opt(RSB_IO_WANT_LIBRSB_ETIME,&etime);
               if(errval == RSB_ERR_UNSUPPORTED_FEATURE)
               {
                       printf("librsb timer-based profiling is not supported in "
                       "this build. If you wish to have it, re-configure librsb "
                       "with its support. So you can safely ignore the error you"
                       " might just have seen printed out on screen.\n");
                       errval = RSB_ERR_NO_ERROR;
               }
               else
               if(etime) /* This will only work if enabled at configure time. */
                       printf("Elapsed program time is %5.2lfs\n",etime);

       ret:
               if((errval = rsb_lib_exit(RSB_NULL_EXIT_OPTIONS))
                               !=RSB_ERR_NO_ERROR)
                       goto err;
               return EXIT_SUCCESS;
       err:
               rsb_perror(NULL,errval);
               printf("Program terminating with error.\n");
               return EXIT_FAILURE;
       }

        examples/io-spblas.c:

       /*

       Copyright (C) 2008-2021 Michele Martone

       This file is part of librsb.

       librsb is free software; you can redistribute it and/or modify it
       under the terms of the GNU Lesser General Public License as published
       by the Free Software Foundation; either version 3 of the License, or
       (at your option) any later version.

       librsb is distributed in the hope that it will be useful, but WITHOUT
       ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
       License for more details.

       You should have received a copy of the GNU Lesser General Public
       License along with librsb; see the file COPYING.
       If not, see <http://www.gnu.org/licenses/>.

       */
       /*!
        \ingroup rsb-examples
        @file
        @author Michele Martone

        @brief Example C program using the Sparse BLAS interface
               and reading from file using \ref rsb_blas_file_mtx_load(),
               \ref BLAS_usgp(), \ref BLAS_dusmv(), \ref BLAS_usds().

        \include io-spblas.c
       */
       #include <rsb.h> /* for rsb_lib_init */
       #include <blas_sparse.h>
       #include <stdio.h>

       int main(const int argc, char * const argv[])
       {
       #ifndef RSB_NUMERICAL_TYPE_DOUBLE
               printf("Skipping a test because of 'double' type opted out.\n");
               return EXIT_SUCCESS;
       #else /* RSB_NUMERICAL_TYPE_DOUBLE */
               blas_sparse_matrix A = blas_invalid_handle;
               const rsb_type_t typecode = RSB_NUMERICAL_TYPE_DOUBLE;
               const rsb_char_t * filename = argc > 1 ? argv[1] : "pd.mtx";

               printf("Hello, RSB!\n");
               if((rsb_perror(NULL,
                       rsb_lib_init(RSB_NULL_INIT_OPTIONS)))!=RSB_ERR_NO_ERROR)
               {
                       printf("Error while initializing the library.\n");
                       goto err;
               }

               printf("Correctly initialized the library.\n");

               A = rsb_blas_file_mtx_load(filename, typecode );
               if( A == blas_invalid_handle )
               {
                       printf("Error while loading matrix %s from file.\n",
                                       filename);
                       goto err;
               }

               printf("Correctly loaded and allocated a matrix"
                               " from file %s.\n",filename);

               if( BLAS_usgp(A,blas_symmetric) == 1 )
                       printf("Matrix is symmetric\n");

               if( BLAS_usgp(A,blas_hermitian) == 1 )
                       printf("Matrix is hermitian\n");

               printf("Now SPMV with NULL vectors will be attempted,"
                               " resulting in an error (so don't worry).\n");

               if(BLAS_dusmv(blas_no_trans,-1,A,NULL,1,NULL,1))
               {
                       printf("Correctly detected an error condition.\n");
                       goto okerr;
               }

               printf("No error detected ?\nIf you see this line printed out,"
                       " please report as a bug, because the above NULL pointers"
                       " should have been detected\n");
               return EXIT_FAILURE;
       okerr:
               printf("Program correctly recovered from intentional"
                               " error condition.\n");
               if(BLAS_usds(A))
               {
                       printf("Error while freeing the matrix!\n");
                       goto err;
               }

               printf("Correctly freed the matrix.\n");
       err:
               if(rsb_perror(NULL,
                       rsb_lib_exit(RSB_NULL_EXIT_OPTIONS))!=RSB_ERR_NO_ERROR)
               {
                       printf("Failed finalizing the library.\n");
                       goto ferr;
               }

               printf("Correctly finalized the library.\n");
               return EXIT_SUCCESS;
       ferr:
               return EXIT_FAILURE;
       #endif /* RSB_NUMERICAL_TYPE_DOUBLE */
       }

        examples/transpose.c:

       /*

       Copyright (C) 2008-2021 Michele Martone

       This file is part of librsb.

       librsb is free software; you can redistribute it and/or modify it
       under the terms of the GNU Lesser General Public License as published
       by the Free Software Foundation; either version 3 of the License, or
       (at your option) any later version.

       librsb is distributed in the hope that it will be useful, but WITHOUT
       ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
       License for more details.

       You should have received a copy of the GNU Lesser General Public
       License along with librsb; see the file COPYING.
       If not, see <http://www.gnu.org/licenses/>.

       */
       /*!
        @file
        @author Michele Martone

        @brief A toy <rsb.h>-based C program showing instantiation,
        transposition and other operations on a single matrix.
        Uses \ref rsb_mtx_clone(), \ref rsb_file_mtx_save(),
         \ref rsb_file_mtx_get_dims(), \ref rsb_file_mtx_load().

        \ingroup rsb-examples

        \include transpose.c
       */
       #include <rsb.h>
       #include <stdio.h>       /* printf */

       int main(const int argc, char * const argv[])
       {
               struct rsb_mtx_t *mtxAp = NULL;
               const rsb_blk_idx_t brA = RSB_DEFAULT_BLOCKING,
                                   bcA = RSB_DEFAULT_BLOCKING;
               rsb_nnz_idx_t nnzA = 4;
               rsb_coo_idx_t  nrA = 3;
               rsb_coo_idx_t  ncA = 3;
               const rsb_coo_idx_t    IA[] = { 0, 1, 2, 0 };
               const rsb_coo_idx_t    JA[] = { 0, 1, 2, 2 };
               const RSB_DEFAULT_TYPE VA[] = { 11, 22, 33, 13 };
               RSB_DEFAULT_TYPE XV[] = { 0,0,0,0,0,0 };
               rsb_coo_idx_t  vl = 0;
               const rsb_type_t typecode = RSB_NUMERICAL_TYPE_DEFAULT;
               rsb_err_t errval = RSB_ERR_NO_ERROR;

               /* library initialization */
               if(rsb_lib_init(RSB_NULL_INIT_OPTIONS)!=RSB_ERR_NO_ERROR)
               {
                       return EXIT_FAILURE;
               }

               /* allocation */
               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;
               }

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

               /* matrix transposition */
               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;
               }

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

               rsb_mtx_free(mtxAp);

               /* doing the same after load from file */
               mtxAp = rsb_file_mtx_load("pd.mtx",
                       RSB_FLAG_NOFLAGS,typecode,NULL);
               if(!mtxAp)
               {
                       return EXIT_FAILURE;
               }

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

               /* one can see dimensions in advance, also */
               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;
               }

               /* A matrix can be rendered to Postscript. */
               {
                       if(RSB_ERR_NO_ERROR!=(errval =
                       rsb_mtx_rndr("pd.eps",mtxAp,512,512,RSB_MARF_EPS_B)))
                               goto err;
               }

               rsb_mtx_free(mtxAp);

               /* 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;

               /* 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;
               }

               if(RSB_ERR_NO_ERROR != rsb_lib_exit(RSB_NULL_EXIT_OPTIONS))
               {
                       goto err;
               }
               return EXIT_SUCCESS;
       err:
               rsb_perror(NULL,errval);
               return EXIT_FAILURE;
       }

        examples/power.c:

       /*

       Copyright (C) 2008-2021 Michele Martone

       This file is part of librsb.

       librsb is free software; you can redistribute it and/or modify it
       under the terms of the GNU Lesser General Public License as published
       by the Free Software Foundation; either version 3 of the License, or
       (at your option) any later version.

       librsb is distributed in the hope that it will be useful, but WITHOUT
       ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
       License for more details.

       You should have received a copy of the GNU Lesser General Public
       License along with librsb; see the file COPYING.
       If not, see <http://www.gnu.org/licenses/>.

       */
       /*!
        @file
        @author Michele Martone

        @brief A toy <rsb.h>-based C program implementing the power
               method for computing matrix eigenvalues. Uses #rsb_spmv().
        \ingroup rsb-examples

        \include power.c
       */

       #include <stdio.h>       // printf
       #include <math.h>        // sqrt
       #include <stdlib.h>      // calloc
       #include <rsb.h>

       int main(const int argc, char * const argv[])
       {
               const int WANT_VERBOSE = 0;
               struct rsb_mtx_t *mtxAp = NULL;
               const int bs = RSB_DEFAULT_BLOCKING;
               const int br = bs, bc = bs; /* bs x bs blocked */
               const rsb_nnz_idx_t nnzA = 4;
               const rsb_coo_idx_t  nrA = 3;
               const rsb_coo_idx_t  ncA = 3;
               rsb_int_t it = 0;
               const rsb_int_t maxit = 100;
               const rsb_coo_idx_t    IA[] = { 0, 1, 2, 0 };
               const rsb_coo_idx_t    JA[] = { 0, 1, 2, 2 };
               const RSB_DEFAULT_POSSIBLY_FIRST_BLAS_TYPE VA[] = { 11, 22, 33, 13 };
               const RSB_DEFAULT_POSSIBLY_FIRST_BLAS_TYPE ZERO = 0;
               int i;
               rsb_err_t errval = 0;

               RSB_DEFAULT_POSSIBLY_FIRST_BLAS_TYPE norm = 0.0, /* nu */
                       oldnorm = 1.0, /* oldnorm */
                       *b1 = NULL, *b2 = NULL,
                       *bnow = NULL, *bnext = NULL;/* b1 and b2 aliases */
               rsb_type_t typecode = RSB_NUMERICAL_TYPE_FIRST_BLAS;
               size_t ds = 0;
               /* tolerance */
               const RSB_DEFAULT_POSSIBLY_FIRST_BLAS_TYPE tol = 1e-14;

               /* library initialization */
               if(rsb_lib_init(RSB_NULL_INIT_OPTIONS)!=RSB_ERR_NO_ERROR)
                       return EXIT_FAILURE;

               /* allocation */
               mtxAp = rsb_mtx_alloc_from_coo_const(VA,IA,JA,nnzA,
                               typecode,nrA,ncA,br,bc,RSB_FLAG_NOFLAGS,NULL);
               if(!mtxAp)
                       return EXIT_FAILURE;

               ds = (nrA)*sizeof(RSB_DEFAULT_POSSIBLY_FIRST_BLAS_TYPE);
               b1 = calloc(1,ds);
               b2 = calloc(1,ds);

               if(! (b1 && b2))
               {
                       errval = RSB_ERR_ENOMEM;
                       goto err;
               }

               for( i = 0; i < nrA; ++i )
                       b1[i] = 1;

               bnow = b1, bnext = b2;/* b,b' */

               while( fabs(norm-oldnorm) > tol && it<maxit )
               {
                       ++ it;
                       oldnorm = norm;
                       /* b'<-Ab */
                       if(( rsb_spmv(RSB_TRANSPOSITION_N,NULL,mtxAp,bnow,
                               1,&ZERO,bnext,1)) != RSB_ERR_NO_ERROR )
                               goto err;
                       /* nu<-||Ab||^2 */
                       norm = 0;
                       for(i=0;i<nrA;++i)
                               norm += bnext[i]*bnext[i];
                       /* nu<-||Ab|| */
                       norm = sqrt(norm);
                       norm = 1.0/norm;
                       /* b'<- Ab / ||Ab|| */
                       for(i=0;i<nrA;++i)
                               bnext[i] *= norm;
                       norm = 1.0/norm;
                       printf("it:%d norm:%lg norm diff:%lg\n",it,norm,norm-oldnorm);

                       {void *tmp=bnow;bnow=bnext;bnext=tmp;/* pointers swap */}
                       if(WANT_VERBOSE)
                       {
                               printf("norm:%lg\n",norm);
                               if(isinf(norm))
                               /* isinf is a C99 feature (need correct
                                * compilation flags) */
                                       goto err;

                               for(i=0;i<2;++i)
                                       printf("x[%d]=%lg\n",i,((double*)bnext)[i]);
                       }
               }
               /* the biggest eigenvalue should be in bnow */

               rsb_mtx_free(mtxAp);
               free(b1);
               free(b2);
               if(rsb_lib_exit(RSB_NULL_EXIT_OPTIONS)!=RSB_ERR_NO_ERROR)
                       goto err;
               if( it == maxit )
               {
                       printf("ERROR: hit iterations limit without convergence!");
                       errval=RSB_ERR_GENERIC_ERROR;
               }
               return EXIT_SUCCESS;
       err:
               rsb_perror(NULL,errval);
               return EXIT_FAILURE;
       }

        examples/fortran.F90:

       !
       ! Copyright (C) 2008-2022 Michele Martone
       !
       ! This file is part of librsb.
       !
       ! librsb is free software; you can redistribute it and/or modify it
       ! under the terms of the GNU Lesser General Public License as published
       ! by the Free Software Foundation; either version 3 of the License, or
       ! (at your option) any later version.
       !
       ! librsb is distributed in the hope that it will be useful, but WITHOUT
       ! ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       ! FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
       ! License for more details.
       !
       ! You should have received a copy of the GNU Lesser General Public
       ! License along with librsb; see the file COPYING.
       ! If not, see <http://www.gnu.org/licenses/>.
       !

       !> @file
       !! @brief Sparse BLAS-based usage:
       !!  uscr_begin(), usgp(), ussp(), usmv(), ...
       !! \include fortran.F90

             SUBROUTINE blas_sparse_mod_example(res)
             USE blas_sparse
             USE rsb ! For the second part of the example and RSB_IDX_KIND
             USE iso_c_binding
             IMPLICIT NONE
             INTEGER :: i, j
             INTEGER(KIND=RSB_BLAS_IDX_KIND) :: istat = 0, res
             TYPE(C_PTR),TARGET :: mtxAp = c_null_ptr ! matrix pointer
             INTEGER(C_INT) :: A
             INTEGER,PARAMETER :: transn = blas_no_trans
             INTEGER(KIND=RSB_IDX_KIND),PARAMETER :: incx = 1
             INTEGER(KIND=RSB_IDX_KIND),PARAMETER :: incy = 1
             REAL(KIND=8),parameter :: alpha = 3
       ! Symmetric (declared via lower triangle) matrix based example, e.g.:
       ! 1 0
       ! 1 1
             ! declaration of VA,IA,JA
             !INTEGER,PARAMETER :: nr = 100
             INTEGER(KIND=RSB_IDX_KIND),PARAMETER :: nr = 20
             INTEGER(KIND=RSB_IDX_KIND),PARAMETER :: nc = nr
             INTEGER(KIND=RSB_IDX_KIND),PARAMETER :: nnz = (nr*(nr+1))/2 ! half the square
             INTEGER(KIND=RSB_IDX_KIND),PARAMETER :: nrhs = 1
             INTEGER(KIND=RSB_IDX_KIND) :: nt = 0
             INTEGER :: ic, ir
             ! For compatibility with (or compassion for) flang-13, we turn these three lines off:
             ! REAL(KIND=8),PARAMETER :: VA(nnz) = (/ ((1, ic=1,ir), ir=1,nr ) /) ! (/1, 1, 1/)
             ! INTEGER(KIND=RSB_IDX_KIND),PARAMETER :: IA(nnz) = (/ (((ir), ic=1,ir), ir=1,nr ) /) ! (/1, 2, 2/)
             ! INTEGER(KIND=RSB_IDX_KIND),PARAMETER :: JA(nnz) = (/ (((ic), ic=1,ir), ir=1,nr ) /) ! (/1, 1, 2/)
             ! and use these other ones instead, initializing VA,IA,JA later:
             REAL(KIND=8) :: va(nnz)
             INTEGER(KIND=RSB_IDX_KIND) :: IA(nnz)
             INTEGER(KIND=RSB_IDX_KIND) :: JA(nnz)
             REAL(KIND=8) :: x(nc,nrhs) = reshape((/((1), ic=1,nc*nrhs)/),[nc,nrhs]) ! reference x ! (/1, 1/)
             REAL(KIND=8),parameter :: cy(nr,nrhs) = reshape((/((alpha+alpha*nr), ir=1,nr*nrhs)/),[nr,nrhs]) ! reference cy after ! (/9, 9/)
             REAL(KIND=8) :: y(nr,nrhs) = reshape((/((alpha), ir=1,nr*nrhs)/),[nr,nrhs]) ! y will be overwritten ! (/3, 3/)
             va(:) = (/ ((1, ic=1,ir), ir=1,nr ) /) ! (/1, 1, 1/)
             ia(:) = (/ (((ir), ic=1,ir), ir=1,nr ) /) ! (/1, 2, 2/)
             ja(:) = (/ (((ic), ic=1,ir), ir=1,nr ) /) ! (/1, 1, 2/)
             ! First example part: pure blas_sparse code.
             res = 0
             CALL duscr_begin(nr,nc,a,res)
             IF (res.NE.0) GOTO 9999
             CALL ussp(a,blas_lower_symmetric,istat)
             IF (istat.NE.0) GOTO 9997
             CALL ussp(a,blas_rsb_spmv_autotuning_on,istat) ! (experimental) turns auto-tuning + thread setting on
             IF (istat.NE.0) print *,"autotuning returned nonzero:", istat &
              &," ...did you enable autotuning ?"
             !
             ! First style example
             CALL uscr_insert_entries(a,nnz,va,ia,ja,istat)
             IF (istat.NE.0) GOTO 9997
             CALL uscr_end(a,istat)
             IF (istat.NE.0) GOTO 9997
             ! CALL ussp(A,blas_rsb_duplicates_sum,istat)
             ! CALL uscr_insert_entries(A,nnz,VA,IA,JA,istat) ! uncomment this to activate add of coefficients to pattern
             CALL usgp(a,blas_rsb_spmv_autotuning_on,nt)  ! (experimental)
             IF (nt.NE.0) print*,"autotuner chose ",nt," threads"
             CALL ussp(a,blas_rsb_spmv_autotuning_off,istat) ! (experimental) turns auto-tuning + thread setting off
             IF (istat.NE.0) GOTO 9997

             DO j = 1, nrhs
               CALL usmv(transn,alpha,a,x(:,j),incx,y(:,j),incy,istat)
             END DO
             IF (istat.NE.0) GOTO 9997
             !
             DO j = 1, nrhs
             DO i = 1, nr
               IF (y(i,j).NE.cy(i,j)) print *, "first check results are not ok"
               IF (y(i,j).NE.cy(i,j)) GOTO 9997
             END DO
             END DO
             !
             y(:,:) = alpha ! reset
             !
             ! Second style example
             CALL ussp(a,blas_rsb_autotune_next_operation,istat) ! (experimental) turns auto-tuning + thread setting on
             IF (istat.NE.0) GOTO 9997
             DO j = 1, nrhs
               CALL usmv(transn,alpha,a,x(:,j),incx,y(:,j),incy,istat)
             END DO
             CALL usmm(blas_colmajor,transn,nrhs, alpha,a,x,nr,y,nc,istat) ! Equivalent to the above (as long as incx=incy=1).
             CALL usmm(blas_colmajor,transn,nrhs,-alpha,a,x,nr,y,nc,istat) ! Subtract the last usmm call contribution.
             IF (istat.NE.0) GOTO 9997
             !
             DO j = 1, nrhs
             DO i = 1, nr
               IF (y(i,j).NE.cy(i,j)) print *,"second check results are not ok"
               IF (y(i,j).NE.cy(i,j)) GOTO 9997
             END DO
             END DO
             !
             print *, "check results are ok"

             ! Second part of the example: access to the rsb.h interface via
             ! the ISO C Binding interface.
             mtxap = rsb_blas_get_mtx(a) ! get pointer to rsb structure (as in the rsb.h API)
             IF(nr.LT.5) istat = rsb_file_mtx_save(mtxap,c_null_char) ! write to stdout (only if matrix small enough)

             GOTO 9998
       9997      res = -1
       9998      CONTINUE
             CALL usds(a,istat)
             IF (istat.NE.0) res = -1
       9999      CONTINUE
             end SUBROUTINE blas_sparse_mod_example

             ! Example loading a matrix from file and measuring SPMM.
             SUBROUTINE blas_sparse_io_example(res)
             USE blas_sparse
             USE rsb ! For rsb_blas_file_mtx_load
             USE iso_c_binding
             IMPLICIT NONE
             INTEGER(KIND=RSB_IDX_KIND) :: res ! note: same as RSB_BLAS_IDX_KIND
             INTEGER :: j
             INTEGER(KIND=RSB_BLAS_IDX_KIND) :: istat = 0
             INTEGER :: A
             INTEGER,PARAMETER :: transn = blas_no_trans
             INTEGER(KIND=RSB_IDX_KIND),PARAMETER :: incx = 1
             INTEGER(KIND=RSB_IDX_KIND),PARAMETER :: incy = 1
             COMPLEX(KIND=8),PARAMETER :: alpha = 3
             INTEGER(KIND=RSB_IDX_KIND) :: nr
             INTEGER(KIND=RSB_IDX_KIND) :: nc
             INTEGER(KIND=RSB_IDX_KIND) :: nz
             INTEGER(KIND=RSB_IDX_KIND) :: st
             INTEGER(KIND=RSB_IDX_KIND),PARAMETER :: nrhs = 4
             COMPLEX(KIND=8), ALLOCATABLE, TARGET, DIMENSION(:,:) :: x
             COMPLEX(KIND=8), ALLOCATABLE, TARGET, DIMENSION(:,:) :: y
             CHARACTER(KIND=C_CHAR,LEN=7),TARGET :: filename = 'pd.mtx'//c_null_char
             INTEGER(C_SIGNED_CHAR) :: typecode = rsb_numerical_type_double_complex
             REAL(KIND=c_double) :: mvt,mmt,omt
             INTEGER(KIND=C_INT),TARGET::IZERO=0

             res = 0

             a = rsb_blas_file_mtx_load(filename, typecode);
             IF (a.EQ.blas_invalid_handle) GOTO 9997

             CALL usgp(a,blas_num_rows,nr)
             CALL usgp(a,blas_num_cols,nc)
             CALL usgp(a,blas_num_nonzeros,nz)

             print*,"Read matrix ",filename(1:6)," ",nr,"x",nc,":",nz
             CALL usgp(a,blas_general,st)
             IF (st .EQ. 1) print*,"Matrix has no symmetry"
             CALL usgp(a,blas_upper_symmetric,st)
             IF (st .EQ. 1) print*,"Matrix is upper symmetric"
             CALL usgp(a,blas_upper_hermitian,st)
             IF (st .EQ. 1) print*,"Matrix is upper hermitian"
             ! ...

             IF (istat.NE.0) GOTO 9997
             WRITE(*,'(a,i0)') "Using NRHS=",nrhs
             ALLOCATE( x(nc,nrhs))
             ALLOCATE( y(nr,nrhs))
             x = 1.0

             y = 0.0
             mvt = -rsb_time()
             DO j = 1, nrhs
               CALL usmv(transn,alpha,a,x(:,j),incx,y(:,j),incy,istat)
             END DO
             IF (istat.NE.0) GOTO 9997
             mvt = mvt + rsb_time()
             WRITE(*,'(a,e12.4,a)') "Repeated USMV took ",mvt," s"

             y = 0.0
             mmt = -rsb_time()
             CALL usmm(blas_colmajor,transn,nrhs, alpha,a,x,nr,y,nc,istat)
             IF (istat.NE.0) GOTO 9997
             mmt = mmt + rsb_time()
             WRITE(*,'(a,e12.4,a)') "A single USMM took ",mmt," s"

             WRITE(*,'(a,g11.4,a)')"USMM-to-USMV speed ratio is is ", mvt/mmt, "x"

             print*,"Call auto-tuning routine.."
             ! Change IZERO value to 1 to get verbose tuning again.
             res = rsb_lib_set_opt(rsb_io_want_verbose_tuning,c_loc(izero))
             IF (res.NE.0) GOTO 9997
             CALL ussp(a,blas_rsb_autotune_next_operation,istat) ! (experimental) turns auto-tuning + thread setting on
             IF (istat.NE.0) GOTO 9997
             CALL usmm(blas_colmajor,transn,nrhs, alpha,a,x,nr,y,nc,istat)
             IF (istat.NE.0) GOTO 9997

             print*,"Repeat measurement."
             y = 0.0
             omt = -rsb_time()
             CALL usmm(blas_colmajor,transn,nrhs, alpha,a,x,nr,y,nc,istat)
             IF (istat.NE.0) GOTO 9997
             omt = omt + rsb_time()
             WRITE(*,'(a,e12.4,a)') "Tuned USMM took ",omt," s"
             WRITE(*,'(a,g11.4,a)')"Tuned-to-untuned speed ratio is is ",mmt/omt,"x"

             GOTO 9998
       9997      res = -1
       9998      CONTINUE
             CALL usds(a,istat)
             IF (istat.NE.0) res = -1
             end SUBROUTINE blas_sparse_io_example

             PROGRAM main
             USE rsb, ONLY: rsb_lib_init, rsb_lib_exit, c_ptr, c_null_ptr,&
              & rsb_io_want_extra_verbose_interface,rsb_io_want_verbose_tuning,&
              & rsb_lib_set_opt,rsb_idx_kind
             ! USE blas_sparse, only: RSB_BLAS_IDX_KIND ! only if using long indices
             USE iso_c_binding
             IMPLICIT NONE
             INTEGER :: passed = 0, failed = 0
             INTEGER(KIND=RSB_IDX_KIND) :: res ! note: same as RSB_BLAS_IDX_KIND
             !TYPE(C_PTR),PARAMETER :: EO = RSB_NULL_EXIT_OPTIONS
             !TYPE(C_PTR),PARAMETER :: IO = RSB_NULL_INIT_OPTIONS
             ! Note: using C_NULL_PTR instead of the previous lines because of http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59411
             TYPE(C_PTR),PARAMETER :: EO = c_null_ptr
             TYPE(C_PTR),PARAMETER :: IO = c_null_ptr
             INTEGER(KIND=C_INT),TARGET::IONE=1
             res = rsb_lib_init(io)
             res = rsb_lib_set_opt(rsb_io_want_verbose_tuning,c_loc(ione))

             CALL blas_sparse_mod_example(res)
             IF (res.LT.0) failed = failed + 1
             IF (res.EQ.0) passed = passed + 1

             CALL blas_sparse_io_example(res)
             IF (res.LT.0) failed = failed + 1
             IF (res.EQ.0) passed = passed + 1

             res = rsb_lib_exit(eo)

             print *, "FAILED:", failed
             print *, "PASSED:", passed
             IF (failed .GT. 0) THEN
              stop 1
             END IF
             END PROGRAM

        examples/fortran_rsb_fi.F90:

       !
       ! Copyright (C) 2008-2022 Michele Martone
       !
       ! This file is part of librsb.
       !
       ! librsb is free software; you can redistribute it and/or modify it
       ! under the terms of the GNU Lesser General Public License as published
       ! by the Free Software Foundation; either version 3 of the License, or
       ! (at your option) any later version.
       !
       ! librsb is distributed in the hope that it will be useful, but WITHOUT
       ! ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       ! FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
       ! License for more details.
       !
       ! You should have received a copy of the GNU Lesser General Public
       ! License along with librsb; see the file COPYING.
       ! If not, see <http://www.gnu.org/licenses/>.
       !

       !> @file.
       !! @brief RSB.F90-based usage:
       !!        rsb_mtx_alloc_from_coo_const(),
       !!        rsb_tune_spmm(),
       !!        rsb_file_mtx_save(),
       !!        rsb_spmv(),
       !!        ...
       !! \include fortran_rsb_fi.F90

             SUBROUTINE rsb_mod_example1(res)
       ! Example using an unsymmetric matrix specified as COO, and autotuning, built at once.
             USE rsb
             USE iso_c_binding
             IMPLICIT NONE
             INTEGER ::res
             INTEGER,TARGET :: istat = 0, i
             INTEGER :: transt = rsb_transposition_n !
             INTEGER(KIND=RSB_IDX_KIND) :: incx = 1, incy = 1
             REAL(KIND=8),target :: alpha = 3, beta = 1
       ! 1 1
       ! 1 1
             ! declaration of VA,IA,JA
             INTEGER(KIND=RSB_IDX_KIND) :: nnz = 4
             INTEGER(KIND=RSB_IDX_KIND) :: nr = 2
             INTEGER(KIND=RSB_IDX_KIND) :: nc = 2
             INTEGER(KIND=RSB_IDX_KIND) :: nrhs = 1
             INTEGER :: order = rsb_flag_want_column_major_order ! rhs layout
             INTEGER :: flags = rsb_flag_noflags
             INTEGER(KIND=RSB_IDX_KIND),TARGET :: IA(4) = (/0, 1, 1,0/)
             INTEGER(KIND=RSB_IDX_KIND),TARGET :: JA(4) = (/0, 0, 1,1/)
             REAL(KIND=8),target :: va(4) = (/1,1,1,1/)
             REAL(KIND=8),target :: x(2) = (/1, 1/)! reference x
             REAL(KIND=8),target :: cy(2) = (/9, 9/)! reference cy after
             REAL(KIND=8),target :: y(2) = (/3, 3/)! y will be overwritten
             TYPE(C_PTR),TARGET :: mtxAp = c_null_ptr ! matrix pointer
             REAL(KIND=8) :: tmax = 2.0 ! tuning max time
             INTEGER :: titmax = 2 ! tuning max iterations
             INTEGER,TARGET :: ont = 0     ! optimal number of threads
             !TYPE(C_PTR),PARAMETER :: EO = RSB_NULL_EXIT_OPTIONS
             !TYPE(C_PTR),PARAMETER :: IO = RSB_NULL_INIT_OPTIONS
             ! Note: using C_NULL_PTR instead of the previous lines because of http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59411
             TYPE(C_PTR),PARAMETER :: EO = c_null_ptr
             TYPE(C_PTR),PARAMETER :: IO = c_null_ptr
             INTEGER,TARGET :: errval

             res = 0

             errval = rsb_lib_init(io)
             IF (errval.NE.rsb_err_no_error) GOTO 9997

             mtxap = rsb_mtx_alloc_from_coo_const(c_loc(va),c_loc(ia),c_loc(ja)&
              &,nnz,&
              & rsb_numerical_type_double,nr,nc,1,1,flags,c_loc(istat))

             IF (istat.NE.rsb_err_no_error) GOTO 9997

             istat = rsb_file_mtx_save(mtxap,c_null_char)

             ! Structure autotuning:
             istat = rsb_tune_spmm(c_loc(mtxap),c_null_ptr,c_null_ptr,titmax,&
              & tmax,&
              & transt,c_loc(alpha),c_null_ptr,nrhs,order,c_loc(x),nr,&
              & c_loc(beta),c_loc(y),nc)

             IF (istat.NE.rsb_err_no_error) GOTO 9997

             ! Thread count autotuning:
             istat = rsb_tune_spmm(c_null_ptr,c_null_ptr,c_loc(ont),titmax,&
              & tmax,&
              & transt,c_loc(alpha),mtxap,nrhs,order,c_loc(x),nr,c_loc(beta),&
              & c_loc(y),nc)
             print *, "Optimal number of threads:", ont

             y(:) = (/3, 3/)! restoring reference y (rsb_tune_spmm has overwritten it)
             IF (istat.NE.rsb_err_no_error) GOTO 9997

             istat = rsb_file_mtx_save(mtxap,c_null_char)
             IF (istat.NE.rsb_err_no_error) GOTO 9997

             istat = rsb_spmv(transt,c_loc(alpha),mtxap,c_loc(x),incx,&
              & c_loc(beta),c_loc(y),incy)
             IF (istat.NE.rsb_err_no_error) GOTO 9997
             DO i = 1, 2
                   IF (y(i).NE.cy(i)) print *, "type=d dims=2x2 sym=g diag=g &
             &blocks=1x1 usmv alpha= 3 beta= 1 incx=1 incy=1 trans=n is not ok"
                   IF (y(i).NE.cy(i)) GOTO 9997
             END DO
             print*,"type=d dims=2x2 sym=g diag=g blocks=1x1 usmv alpha= 3&
              & beta= 1 incx=1 incy=1 trans=n is ok"

             IF ( res .NE.rsb_err_no_error) GOTO 9997
             GOTO 9998
       9997      res = -1
       9998      CONTINUE
             mtxap = rsb_mtx_free(mtxap)
             IF (istat.NE.rsb_err_no_error) res = -1
       ! 9999      CONTINUE
             errval=rsb_lib_exit(eo)                 ! librsb finalization
             IF (errval.NE.rsb_err_no_error)&
              & stop "error calling rsb_lib_exit"
             print *, "rsb module fortran test is ok"

             istat = rsb_perror(c_null_ptr,istat)
             end SUBROUTINE rsb_mod_example1

             SUBROUTINE rsb_mod_example2(res)
       ! Example using an unsymmetric matrix specified as COO, and autotuning, built piecewise.
             USE rsb
             USE iso_c_binding
             IMPLICIT NONE
             INTEGER,TARGET :: errval
             INTEGER :: res
             INTEGER :: transt = rsb_transposition_n  ! no transposition
             INTEGER(KIND=RSB_IDX_KIND) :: incX = 1, incb = 1        ! X, B vectors increment
             REAL(KIND=8),target :: alpha = 3,beta = 1
             INTEGER(KIND=RSB_IDX_KIND) :: nnzA = 4, nra = 3, nca = 3     ! nonzeroes, rows, columns of matrix A
             INTEGER(KIND=RSB_IDX_KIND),TARGET :: IA(4) = (/1, 2, 3, 3/)  ! row    indices
             INTEGER(KIND=RSB_IDX_KIND),TARGET :: JA(4) = (/1, 2, 1, 3/)  ! column indices
             INTEGER(C_SIGNED_CHAR) :: typecode = rsb_numerical_type_double
             INTEGER :: flags =rsb_flag_default_matrix_flags+rsb_flag_symmetric
             REAL(KIND=8),target :: va(4) = (/11.0, 22.0, 13.0, 33.0/) ! coefficients
             REAL(KIND=8),target :: x(3) = (/   0,    0,    0/)
             REAL(KIND=8),target :: b(3) = (/-1.0, -2.0, -2.0/)
             TYPE(C_PTR),TARGET  :: mtxAp = c_null_ptr
             TYPE(C_PTR)  :: mtxApp = c_null_ptr
             REAL(KIND=8),target :: etime = 0.0
             !TYPE(C_PTR),PARAMETER :: EO = RSB_NULL_EXIT_OPTIONS
             !TYPE(C_PTR),PARAMETER :: IO = RSB_NULL_INIT_OPTIONS
             ! Note: using C_NULL_PTR instead of the previous lines because of http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59411
             TYPE(C_PTR),PARAMETER :: EO = c_null_ptr
             TYPE(C_PTR),PARAMETER :: IO = c_null_ptr

             errval = rsb_lib_init(io)                ! librsb initialization
             IF (errval.NE.rsb_err_no_error) &
              & stop "error calling rsb_lib_init"
       #if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 5)
       #define RSB_SKIP_BECAUSE_OLD_COMPILER 1
       #endif
       #ifndef RSB_SKIP_BECAUSE_OLD_COMPILER
             mtxap = rsb_mtx_alloc_from_coo_begin(nnza,typecode,nra,nca,flags,&
              & c_loc(errval)) ! begin matrix creation
             errval = rsb_mtx_set_vals(mtxap,&
              & c_loc(va),c_loc(ia),c_loc(ja),nnza,flags) ! insert some nonzeroes
             mtxapp = c_loc(mtxap) ! Old compilers like e.g.: Gfortran 4.4.7 will NOT compile this.
             IF (errval.NE.rsb_err_no_error) &
              & stop "error calling rsb_mtx_set_vals"
             errval = rsb_mtx_alloc_from_coo_end(mtxapp)                   ! end matrix creation
             IF (errval.NE.rsb_err_no_error) &
              & stop "error calling rsb_mtx_alloc_from_coo_end"
             errval = rsb_spmv(transt,c_loc(alpha),mtxap,c_loc(x),&
              & incx,c_loc(beta),c_loc(b),incb) ! X := X + (3) * A * B
             IF (errval.NE.rsb_err_no_error)&
              & stop "error calling rsb_spmv"
             mtxap = rsb_mtx_free(mtxap)                                 ! destroy matrix

             ! The following is optional and depends on configure options, so it is allowed to fail
             errval = rsb_lib_get_opt(rsb_io_want_librsb_etime,c_loc(etime))
             IF (errval.EQ.rsb_err_no_error)&
              & print*,"Time spent in librsb is:",etime
             ! IF (errval.NE.0)STOP "error calling rsb_lib_get_opt"
             errval = rsb_err_no_error

             IF (errval.NE.rsb_err_no_error) &
              & stop "error calling rsb_mtx_free"
       #else
             print*,"You have an old Fortran compiler not supporting C_LOC."
             print*,"Skipping a part of the test"
       #endif
             errval=rsb_lib_exit(eo)                 ! librsb finalization
             IF (errval.NE.rsb_err_no_error)&
              & stop "error calling rsb_lib_exit"
             print *, "rsb module fortran test is ok"
             res = errval
             end SUBROUTINE rsb_mod_example2

             SUBROUTINE rsb_mod_example3(res)
       ! Example using a symmetric matrix specified as CSR, and autotuning, built at once.
             USE rsb
             USE iso_c_binding
             IMPLICIT NONE
             INTEGER ::res
             INTEGER,TARGET :: istat = 0, i
             INTEGER :: transt = rsb_transposition_n !
             INTEGER(KIND=RSB_IDX_KIND) :: incx = 1, incy = 1
             REAL(KIND=8),target :: alpha = 4, beta = 1
       ! 11 21
       ! 21 22
             ! declaration of VA,IP,JA
             INTEGER(KIND=RSB_IDX_KIND), PARAMETER :: nnz = 3
             INTEGER(KIND=RSB_IDX_KIND), PARAMETER :: nr = 2
             INTEGER(KIND=RSB_IDX_KIND), PARAMETER :: nc = 2
             INTEGER(KIND=RSB_IDX_KIND), PARAMETER :: nrhs = 1
             INTEGER :: order = rsb_flag_want_column_major_order ! rhs layout
             INTEGER :: flags = rsb_flag_noflags + rsb_flag_symmetric + &
              &                 rsb_flag_fortran_indices_interface        !  optional flags
             INTEGER(KIND=RSB_IDX_KIND),TARGET :: IP(3) = (/1, 2, 4/)
             INTEGER(KIND=RSB_IDX_KIND),TARGET :: JA(3) = (/1, 1, 2/)
             REAL(KIND=8),target :: va(3) = (/11,21,22/) ! lower triangle coefficients
             REAL(KIND=8),target :: x(2) = (/1, 2/)! reference x
             REAL(KIND=8),target :: cy(2) = (/215.0, 264.0/)! reference cy after
             REAL(KIND=8),target :: y(2) = (/3, 4/)! y will be overwritten
             TYPE(C_PTR),TARGET :: mtxAp = c_null_ptr ! matrix pointer
             REAL(KIND=8) :: tmax = 2.0 ! tuning max time
             INTEGER :: titmax = 2 ! tuning max iterations
             INTEGER,TARGET :: ont = 0     ! optimal number of threads
             TYPE(C_PTR),PARAMETER :: EO = c_null_ptr
             TYPE(C_PTR),PARAMETER :: IO = c_null_ptr
             INTEGER,TARGET :: errval

             errval = rsb_lib_init(io)                ! librsb initialization
             IF (errval.NE.rsb_err_no_error) &
              & stop "error calling rsb_lib_init"

             res = 0
             mtxap = rsb_mtx_alloc_from_csr_const(c_loc(va),c_loc(ip),c_loc(ja)&
              &,nnz,rsb_numerical_type_double,nr,nc,1,1,flags,c_loc(istat))

             IF (istat.NE.rsb_err_no_error) GOTO 9997

             istat = rsb_file_mtx_save(mtxap,c_null_char)

             ! Structure autotuning:
             istat = rsb_tune_spmm(c_loc(mtxap),c_null_ptr,c_null_ptr,titmax,&
              & tmax,&
              & transt,c_loc(alpha),c_null_ptr,nrhs,order,c_loc(x),nr,&
              & c_loc(beta),c_loc(y),nc)

             IF (istat.NE.rsb_err_no_error) GOTO 9997

             ! Thread count autotuning:
             istat = rsb_tune_spmm(c_null_ptr,c_null_ptr,c_loc(ont),titmax,&
              & tmax,&
              & transt,c_loc(alpha),mtxap,nrhs,order,c_loc(x),nr,c_loc(beta),&
              & c_loc(y),nc)
             print *, "Optimal number of threads:", ont

             y(:) = (/3, 4/)! restoring reference y (rsb_tune_spmm has overwritten it)
             IF (istat.NE.rsb_err_no_error) GOTO 9997

             istat = rsb_file_mtx_save(mtxap,c_null_char)
             IF (istat.NE.rsb_err_no_error) GOTO 9997

             istat = rsb_spmv(transt,c_loc(alpha),mtxap,c_loc(x),incx,&
              & c_loc(beta),c_loc(y),incy)
             print *, y
             IF (istat.NE.rsb_err_no_error) GOTO 9997
             DO i = 1, 2
                   IF (y(i).NE.cy(i)) print *, "type=d dims=2x2 sym=s diag=g &
             &blocks=1x1 usmv alpha= 4 beta= 1 incx=1 incy=1 trans=n is not ok"
                   IF (y(i).NE.cy(i)) GOTO 9997
             END DO
             print*,"type=d dims=2x2 sym=s diag=g blocks=1x1 usmv alpha= 4&
              & beta= 1 incx=1 incy=1 trans=n is ok"
             GOTO 9998

             errval=rsb_lib_exit(eo)                 ! librsb finalization
             IF (errval.NE.rsb_err_no_error)&
              & stop "error calling rsb_lib_exit"
             print *, "rsb module fortran test is ok"
       9997      res = -1
       9998      CONTINUE
             mtxap = rsb_mtx_free(mtxap)
             IF (istat.NE.rsb_err_no_error) res = -1
       ! 9999      CONTINUE
             istat = rsb_perror(c_null_ptr,istat)
             end SUBROUTINE rsb_mod_example3

             PROGRAM main
             USE rsb
             IMPLICIT NONE
             INTEGER :: res = rsb_err_no_error, passed = 0, failed = 0

             CALL rsb_mod_example1(res)
             IF (res.LT.0) failed = failed + 1
             IF (res.EQ.0) passed = passed + 1

             CALL rsb_mod_example2(res)
             IF (res.LT.0) failed = failed + 1
             IF (res.EQ.0) passed = passed + 1

             CALL rsb_mod_example3(res)
             IF (res.LT.0) failed = failed + 1
             IF (res.EQ.0) passed = passed + 1

             print *, "FAILED:", failed
             print *, "PASSED:", passed
             IF (failed.GT.0) THEN
              stop 1
             END IF
             END PROGRAM

        examples/backsolve.c:

       /*

       Copyright (C) 2008-2021 Michele Martone

       This file is part of librsb.

       librsb is free software; you can redistribute it and/or modify it
       under the terms of the GNU Lesser General Public License as published
       by the Free Software Foundation; either version 3 of the License, or
       (at your option) any later version.

       librsb is distributed in the hope that it will be useful, but WITHOUT
       ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
       License for more details.

       You should have received a copy of the GNU Lesser General Public
       License along with librsb; see the file COPYING.
       If not, see <http://www.gnu.org/licenses/>.

       */
       /*!
        \ingroup rsb-examples
        @file
        @author Michele Martone

        @brief C triangular solve example program.
          Uses #rsb_spsv(),#rsb_tune_spsm().
          Based on <rsb.h>.

        \include hello.c
       */
       #include <rsb.h> /* librsb header to include */
       #include <stdio.h>       /* printf() */

       int main(const int argc, char * const argv[])
       {
               /*!
                 A Hello-RSB program.

                 This program shows how to use the rsb.h interface correctly to:

                 - initialize the library using #rsb_lib_init()
                 - allocate (build) a single sparse matrix in the RSB format
                   using #rsb_mtx_alloc_from_coo_const(), with implicit diagonal
                 - print information obtained via #rsb_mtx_get_info_str()
                 - multiply the triangular matrix using #rsb_spmv()
                 - autotune the matrix for rsb_spsv with #rsb_tune_spsm()
                 - solve the triangular system using #rsb_spsv()
                 - deallocate the matrix using #rsb_mtx_free()
                 - finalize the library using #rsb_lib_exit()

                 In this example, we use #RSB_DEFAULT_TYPE as matrix type.
                 This type depends on what was configured at library build time.
                * */
               const int bs = RSB_DEFAULT_BLOCKING;
               const int brA = bs, bcA = bs;
               const RSB_DEFAULT_TYPE one = 1;
               const rsb_type_t typecode = RSB_NUMERICAL_TYPE_DEFAULT;
               const rsb_nnz_idx_t nnzA = 7;           /* matrix nonzeroes count */
               const rsb_coo_idx_t nrA = 6;            /* matrix rows count */
               const rsb_coo_idx_t ncA = 6;            /* matrix columns count */
               /* nonzero row indices coordinates: */
               const rsb_coo_idx_t IA[] = {1,2,3,4,5,6,1};
               /* nonzero column indices coordinates: */
               const rsb_coo_idx_t JA[] = {1,2,3,4,5,6,6};
               const RSB_DEFAULT_TYPE VA[] = {1,1,1,1,1,1,1};/*values of nonzeroes*/
               RSB_DEFAULT_TYPE X[] = { 0,0,0,0,0,0 }; /* X vector's array */
               const RSB_DEFAULT_TYPE B[] = { 1,1,1,1,1,1 }; /* B */
               struct rsb_mtx_t *mtxAp = NULL; /* matrix structure pointer */
               char ib[200];
               int i;
               rsb_err_t errval = RSB_ERR_NO_ERROR;
               const rsb_int_t wvat = 1; /* want verbose autotuning; see
                         documentation of RSB_IO_WANT_VERBOSE_TUNING */

               printf("Hello, RSB!\n");
               printf("Initializing the library...\n");
               if((errval = rsb_lib_init(RSB_NULL_INIT_OPTIONS)) !=
                               RSB_ERR_NO_ERROR)
               {
                       printf("Error initializing the library!\n");
                       goto err;
               }
               printf("Correctly initialized the library.\n");

               errval = rsb_lib_set_opt(RSB_IO_WANT_VERBOSE_TUNING, &wvat );
               if( (errval) != RSB_ERR_NO_ERROR )
               {
                       printf("Error setting option!\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_UNIT_DIAG_IMPLICIT/* ask diagonal implicit */
                       | RSB_FLAG_TRIANGULAR /* need triangle for spsv */
                       | RSB_FLAG_FORTRAN_INDICES_INTERFACE /* treat indices as 1-based */
                       , &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);
               printf("Summary information of the matrix:\n");
               /* print out the matrix summary information  */
               rsb_mtx_get_info_str(mtxAp,"RSB_MIF_MATRIX_INFO__TO__CHAR_P",
                               ib,sizeof(ib));
               printf("%s",ib);
               printf("\nMatrix printout:\n");

               rsb_file_mtx_save(mtxAp, NULL);

               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;
               }
               printf("\nWe have a unitary vector:\n");
               rsb_file_vec_save(NULL, typecode, B, nrA);

               printf("\nMultiplying matrix by unitary vector we get:\n");
               rsb_file_vec_save(NULL, typecode, X, nrA);

               errval = rsb_tune_spsm(&mtxAp, NULL, NULL, 0, 0, RSB_TRANSPOSITION_N,
                       &one, NULL, 1, RSB_FLAG_WANT_COLUMN_MAJOR_ORDER, NULL, nrA,
                        NULL, NULL, nrA);
               if( (errval) != RSB_ERR_NO_ERROR )
               {
                       printf("Error performing autotuning!\n");
                       goto err;
               }

               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;
               }

               printf("\nBacksolving we should get a unitary vector:\n");
               rsb_file_vec_save(NULL, typecode, X, nrA);

               for(i=0;i<nrA;++i)
                       if(X[i]!=one)
                       {
                               printf("Warning! Result vector not unitary!:\n");
                               errval = RSB_ERR_INTERNAL_ERROR;
                               goto err;
                       }

               printf("All done.\n");
               rsb_mtx_free(mtxAp);
               printf("Correctly freed the matrix.\n");
               if((errval = rsb_lib_exit(RSB_NULL_EXIT_OPTIONS))
                               != RSB_ERR_NO_ERROR)
               {
                       printf("Error finalizing the library!\n");
                       goto err;
               }
               printf("Correctly finalized the library.\n");
               printf("Program terminating with no error.\n");
               return EXIT_SUCCESS;
       err:
               rsb_perror(NULL,errval);
               printf("Program terminating with error.\n");
               return EXIT_FAILURE;
       }

         examples/bench.sh:

       #!/bin/bash
       #
       # Copyright (C) 2008-2022 Michele Martone
       #
       # This file is part of librsb.
       #
       # librsb is free software; you can redistribute it and/or modify it
       # under the terms of the GNU Lesser General Public License as published
       # by the Free Software Foundation; either version 3 of the License, or
       # (at your option) any later version.
       #
       # librsb is distributed in the hope that it will be useful, but WITHOUT
       # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
       # License for more details.
       #
       # You should have received a copy of the GNU Lesser General Public
       # License along with librsb; see the file COPYING.
       # If not, see <http://www.gnu.org/licenses/>.

       # Benchmark rsbench and postprocess results.
       # \ingroup rsb-examples
       # @file
       # @author Michele Martone
       # @brief Benchmark invocation from shell script.
       #
       set -e
       set -x
       which rsbench
       BRF=test.rpr
       # invoke rsbench and produce a performance record, using all types and one thread
       rsbench -oa -Ob --bench --lower 100 --as-symmetric         --types ':' -n 1         --notranspose --compare-competitors         --verbose --verbose         --write-performance-record=${BRF}

       # examine tuning renderings (produced by --verbose --verbose)
       ls -ltr ${BRF/.rpr/}-tuning*

       # convert the performance record to text form
       rsbench --read-performance-record ${BRF} > ${BRF/rpr/txt}
       ls -ltr ${BRF/rpr/txt}

       # convert the performance record to LaTeX table document form
       RSB_PR_WLTC=2 RSB_PR_SR=0  rsbench --read-performance-record ${BRF} > ${BRF/rpr/tex}
       which latex || exit 0 # to compile LaTeX document
       which kpsepath || exit 0 # to check LaTeX packages
       find `kpsepath tex | sed 's/!!//g;s/:/\n/g;'` -name sciposter.cls || exit 0 # need sciposter class, usually in texlive-science
       find `kpsepath tex | sed 's/!!//g;s/:/\n/g;'` -name translator.sty || exit 0 # need sciposter class, usually in texlive-latex-recommended

       # convert the LaTeX table into a DVI (may as well use pdflatex for PDF)
       latex -interaction=batchmode -file-line-error ${BRF/rpr/tex}

       # convert the performance record to GNUPLOT plots
       which gnuplot || exit 0
       RSB_PRD_STYLE_PLT_PFN=${BRF/rpr/} RSB_PRD_STYLE_PLT_FMT=1 RSB_PR_SR=2  rsbench --read-performance-record ${BRF} > ${BRF/rpr/gnu}

       # convert the GNUPLOT plots into PDF
       ls -ltr ${BRF/rpr/gnu}
       gnuplot ${BRF/rpr/gnu}

       # convert the performance record to GNUPLOT plots, different way
       RSB_PRD_STYLE_PLT_PFN=${BRF/rpr/} RSB_PRD_STYLE_PLT_FMT=  RSB_PR_SR=2  rsbench --read-performance-record ${BRF} > ${BRF/rpr/gnu}
       gnuplot ${BRF/rpr/gnu}
       ls -ltr ${BRF/.rpr/}*.png
       ls -ltr ${BRF/.rpr/}*.eps
       ls -ltr ${BRF} ${BRF/rpr/tex} ${BRF/rpr/dvi} ${BRF/rpr/txt}

       # clean up
       rm ${BRF/rpr/}{aux,log,out,gnu}
       rm ${BRF/.rpr/}*{.png,.eps}
       rm      ${BRF} ${BRF/rpr/tex} ${BRF/rpr/dvi} ${BRF/rpr/txt}
       exit

       Most of the snippets in the documentation come from examples/snippets.c.

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