"src/spm.c" did not exist on "4c071dc74ec07d60824aa7550c83e47ab67ceb3f"
Newer
Older

Mathieu Faverge
committed
/**
*

Mathieu Faverge
committed
*

Mathieu Faverge
committed
* PaStiX is a software package provided by Inria Bordeaux - Sud-Ouest,
* LaBRI, University of Bordeaux 1 and IPB.
*
* @version 5.1.0
* @author Xavier Lacoste
* @author Pierre Ramet
* @author Mathieu Faverge
* @date 2013-06-24
*
**/
#include "common.h"

Mathieu Faverge
committed
#include "z_spm.h"
#include "c_spm.h"
#include "d_spm.h"
#include "s_spm.h"
#include "p_spm.h"
static int (*conversionTable[3][3][6])(pastix_spm_t*) = {

Mathieu Faverge
committed
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/* From CSC */
{{ NULL, NULL, NULL, NULL, NULL, NULL },
{ p_spmConvertCSC2CSR,
NULL,
s_spmConvertCSC2CSR,
d_spmConvertCSC2CSR,
c_spmConvertCSC2CSR,
z_spmConvertCSC2CSR },
{ p_spmConvertCSC2IJV,
NULL,
s_spmConvertCSC2IJV,
d_spmConvertCSC2IJV,
c_spmConvertCSC2IJV,
z_spmConvertCSC2IJV }},
/* From CSR */
{{ p_spmConvertCSR2CSC,
NULL,
s_spmConvertCSR2CSC,
d_spmConvertCSR2CSC,
c_spmConvertCSR2CSC,
z_spmConvertCSR2CSC },
{ NULL, NULL, NULL, NULL, NULL, NULL },
{ p_spmConvertCSR2IJV,
NULL,
s_spmConvertCSR2IJV,
d_spmConvertCSR2IJV,
c_spmConvertCSR2IJV,
z_spmConvertCSR2IJV }},
/* From IJV */
{{ p_spmConvertIJV2CSC,
NULL,
s_spmConvertIJV2CSC,
d_spmConvertIJV2CSC,
c_spmConvertIJV2CSC,
z_spmConvertIJV2CSC },
{ p_spmConvertIJV2CSR,
NULL,
s_spmConvertIJV2CSR,
d_spmConvertIJV2CSR,
c_spmConvertIJV2CSR,
z_spmConvertIJV2CSR },
{ NULL, NULL, NULL, NULL, NULL, NULL }}
};
/**
*******************************************************************************
*
* @ingroup pastix_spm
*
*
*******************************************************************************
*
* @param[in,out] spm
* The sparse matrix to init.
*
*******************************************************************************/
void
spmInit( pastix_spm_t *spm )
{
spm->mtxtype = PastixGeneral;
spm->fmttype = PastixCSC;
spm->gN = 0;
spm->n = 0;
spm->gnnz = 0;
spm->nnz = 0;
spm->gNexp = 0;
spm->nexp = 0;
spm->gnnzexp = 0;
spm->nnzexp = 0;
spm->dof = 1;
spm->dofs = NULL;
spm->layout = PastixColMajor;
spm->colptr = NULL;
spm->rowptr = NULL;
spm->loc2glob = NULL;
spm->values = NULL;
}

Mathieu Faverge
committed
/**
*******************************************************************************
*
* @ingroup pastix_spm
*

Mathieu Faverge
committed
*
*******************************************************************************
*
* @param[in,out] spm

Mathieu Faverge
committed
*
*******************************************************************************/
void
spmExit( pastix_spm_t *spm )
{
if(spm->colptr != NULL)
memFree_null(spm->colptr);
if(spm->rowptr != NULL)
memFree_null(spm->rowptr);
if(spm->loc2glob != NULL)
memFree_null(spm->loc2glob);
if(spm->values != NULL)
memFree_null(spm->values);
}
/**
*******************************************************************************

Mathieu Faverge
committed
*
* @ingroup pastix_spm
*
* @brief Rebase the spm
*
* Rebase the arrays of the spm to the given value. If the value is equal to the
* original base, then nothing is performed.
*
*******************************************************************************
*
* @param[in,out] spm
* The sparse matrix to rebase.
*
* @param[in] baseval
* The base value to use in the graph (0 or 1).

Mathieu Faverge
committed
*
*******************************************************************************/
void
spmBase( pastix_spm_t *spm,
int baseval )

Mathieu Faverge
committed
{
pastix_int_t baseadj;
pastix_int_t i, n, nnz;
/* Parameter checks */
if ( spm == NULL ) {

Mathieu Faverge
committed
pastix_error_print("spmBase: spm pointer is NULL");

Mathieu Faverge
committed
}
if ( (spm->colptr == NULL) ||
(spm->rowptr == NULL) )
{

Mathieu Faverge
committed
pastix_error_print("spmBase: spm pointer is not correctly initialized");
return;
}
if ( (baseval != 0) &&
(baseval != 1) )
{

Mathieu Faverge
committed
pastix_error_print("spmBase: baseval is incorrect, must be 0 or 1");
return;
}
baseadj = baseval - spmFindBase( spm );
if (baseadj == 0)
return;
n = spm->n;
switch(spm->fmttype)
{
case PastixCSC:
assert( nnz == (spm->colptr[n] - spm->colptr[0]) );
for (i = 0; i <= n; i++) {
spm->colptr[i] += baseadj;
}
for (i = 0; i < nnz; i++) {
spm->rowptr[i] += baseadj;
}
break;
case PastixCSR:
assert( nnz == (spm->rowptr[n] - spm->rowptr[0]) );
for (i = 0; i <= n; i++) {
spm->rowptr[i] += baseadj;
}
for (i = 0; i < nnz; i++) {
spm->colptr[i] += baseadj;
}
break;
case PastixIJV:
for (i = 0; i < nnz; i++) {
spm->rowptr[i] += baseadj;
spm->colptr[i] += baseadj;
}
}
if (spm->loc2glob != NULL) {
for (i = 0; i < n; i++) {
spm->loc2glob[i] += baseadj;
}

Mathieu Faverge
committed
}

Mathieu Faverge
committed
}
/**
*******************************************************************************
*
* @ingroup pastix_spm
*
* @brief Search the base used in the spm structure.

Mathieu Faverge
committed
*
*******************************************************************************
*
* @param[in] spm
* The sparse matrix structure.
*
********************************************************************************
*
* @return The baseval used in the given sparse matrix structure.
*
*******************************************************************************/
pastix_int_t

Mathieu Faverge
committed
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
{
pastix_int_t i, *tmp, baseval;
/*
* Check the baseval, we consider that arrays are sorted by columns or rows
*/
baseval = pastix_imin( *(spm->colptr), *(spm->rowptr) );
/*
* if not:
*/
if ( ( baseval != 0 ) &&
( baseval != 1 ) )
{
baseval = spm->n;
tmp = spm->colptr;
for(i=0; i<spm->nnz; i++, tmp++){
baseval = pastix_imin( *tmp, baseval );
}
}
return baseval;
}
/**
*******************************************************************************
*
* @ingroup pastix_spm
*
* @brief Convert the storage format of the spm to ofmttype.
*
* Convert the storage format of the given sparse matrix from any of the
* following format: PastixCSC, PastixCSR, or PastixIJV to one of these.
*
*******************************************************************************
*
* @param[in] ofmttype
* The output format of the sparse matrix. It might be PastixCSC,
* PastixCSR, or PastixIJV.
*
* @param[in,out] spm
* The sparse matrix structure to convert.
*
********************************************************************************
*
* @return
* \retval PASTIX_SUCCESS if the conversion happened successfuly
* \retval PASTIX_ERR_BADPARAMETER if one the parameter is incorrect.
*
*******************************************************************************/
int
spmConvert( int ofmttype, pastix_spm_t *spm )
{
if ( spm->dof != 1 ) {
spm = spmExpand( spm );
}
if ( conversionTable[spm->fmttype][ofmttype][spm->flttype] ) {
return conversionTable[spm->fmttype][ofmttype][spm->flttype]( spm );
}
else {
return PASTIX_SUCCESS;
}
}
/**
*******************************************************************************
*
* @ingroup pastix_spm
*
* @brief Compute the norm of the spm.
*
* Return the ntype norm of the sparse matrix spm.

Mathieu Faverge
committed
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
*
* spmNorm = ( max(abs(spm(i,j))), NORM = PastixMaxNorm
* (
* ( norm1(spm), NORM = PastixOneNorm
* (
* ( normI(spm), NORM = PastixInfNorm
* (
* ( normF(spm), NORM = PastixFrobeniusNorm
*
* where norm1 denotes the one norm of a matrix (maximum column sum),
* normI denotes the infinity norm of a matrix (maximum row sum) and
* normF denotes the Frobenius norm of a matrix (square root of sum
* of squares). Note that max(abs(spm(i,j))) is not a consistent matrix
* norm.
*
*******************************************************************************
*
* @param[in] ntype
* = PastixMaxNorm: Max norm
* = PastixOneNorm: One norm
* = PastixInfNorm: Infinity norm
* = PastixFrobeniusNorm: Frobenius norm
*
* @param[in] spm
* The sparse matrix structure.
*
********************************************************************************
*
* @return
* \retval the norm described above. Note that for simplicity, even if
* the norm of single real or single complex matrix is computed with
* single precision, the returned norm is stored in double precision
* number.
* \retval -1., if the floating point of the sparse matrix is
* undefined.
*
*******************************************************************************/
double
spmNorm( int ntype,

Mathieu Faverge
committed
{

Mathieu Faverge
committed
if ( spm->dof != 1 ) {
fprintf(stderr, "WARNING: spm expanded due to non implemented norm for non-expanded spm\n");

Mathieu Faverge
committed
case PastixFloat:
norm = (double)s_spmNorm( ntype, spmtmp );
break;

Mathieu Faverge
committed
case PastixDouble:
norm = d_spmNorm( ntype, spmtmp );
break;

Mathieu Faverge
committed
case PastixComplex32:
norm = (double)c_spmNorm( ntype, spmtmp );
break;

Mathieu Faverge
committed
case PastixComplex64:
norm = z_spmNorm( ntype, spmtmp );
break;

Mathieu Faverge
committed

Mathieu Faverge
committed
default:

Mathieu Faverge
committed
}

Mathieu Faverge
committed
}
/**
*******************************************************************************
*
* @ingroup pastix_spm
*
* @brief Sort the subarray of edges of each vertex in a CSC or CSR spm
*
* This routine sorts the subarray of edges of each vertex in a

Mathieu Faverge
committed
* centralized spm stored in CSC or CSR format. Nothing is performed if IJV
* format is used.
*
* WARNING: This function should NOT be called if dof is greater than 1.
*
*******************************************************************************
*
* @param[in,out] spm
* On entry, the pointer to the sparse matrix structure.
* On exit, the same sparse matrix with subarrays of edges sorted by
* ascending order.
*
********************************************************************************
*
* @return
* \retval PASTIX_SUCCESS if the sort was called
* \retval PASTIX_ERR_BADPARAMETER, if the given spm was incorrect.
*
*******************************************************************************/
int

Mathieu Faverge
committed
{
if ( spm->dof != 1 ) {
fprintf(stderr, "WARNING: spm expanded due to non implemented sort for non-expanded spm\n");
spm = spmExpand( spm );
}

Mathieu Faverge
committed
case PastixPattern:

Mathieu Faverge
committed
break;
case PastixFloat:

Mathieu Faverge
committed
break;
case PastixDouble:

Mathieu Faverge
committed
break;
case PastixComplex32:

Mathieu Faverge
committed
break;
case PastixComplex64:

Mathieu Faverge
committed
break;
default:
return PASTIX_ERR_BADPARAMETER;
}
return PASTIX_SUCCESS;
}
/**
*******************************************************************************
*
* @ingroup pastix_spm
*
* @brief Merge mulitple entries in a spm by summing them.
*
* This routine merge the multiple entries in a sparse

Mathieu Faverge
committed
* matrix by suming their values together. The sparse matrix needs to be sorted
* first (see spmSort()).
*
* WARNING: Not implemented for CSR and IJV format.
*
*******************************************************************************
*
* @param[in,out] spm
* On entry, the pointer to the sparse matrix structure.
* On exit, the reduced sparse matrix of multiple entries were present
* in it. The multiple values for a same vertex are sum up together.
*
********************************************************************************
*
* @return
* \retval If >=0, the number of vertices that were merged
* \retval PASTIX_ERR_BADPARAMETER, if the given spm was incorrect.
*
*******************************************************************************/
pastix_int_t

Mathieu Faverge
committed
{
if ( spm->dof != 1 ) {
fprintf(stderr, "WARNING: spm expanded due to non implemented merge for non-expanded spm\n");
spm = spmExpand( spm );
}

Mathieu Faverge
committed
case PastixPattern:

Mathieu Faverge
committed
case PastixFloat:

Mathieu Faverge
committed
case PastixDouble:

Mathieu Faverge
committed
case PastixComplex32:

Mathieu Faverge
committed
case PastixComplex64:

Mathieu Faverge
committed
default:
return PASTIX_ERR_BADPARAMETER;
}
}
/**
*******************************************************************************
*
* @ingroup pastix_spm
*
* @brief Symmetrize the pattern of the spm
*
* Symmetrize the pattern of the input spm by edges when A(i,j) exists, but
* A(j,i) does not. When values are associated to the edge, zeroes are added to
* the values array.

Mathieu Faverge
committed
*
* WARNING: Not implemented for CSR and IJV format.
*
*******************************************************************************
*
* @param[in,out] spm
* On entry, the pointer to the sparse matrix structure.
* On exit, the reduced sparse matrix of multiple entries were present
* in it. The multiple values for a same vertex are sum up together.
*
********************************************************************************
*
* @return
* \retval If >=0, the number of vertices that were merged
* \retval PASTIX_ERR_BADPARAMETER, if the given spm was incorrect.
*
*******************************************************************************/
pastix_int_t

Mathieu Faverge
committed
{
if ( spm->dof != 1 ) {
fprintf(stderr, "WARNING: spm expanded due to non implemented symmetrize for non-expanded spm\n");
spm = spmExpand( spm );
}

Mathieu Faverge
committed
case PastixPattern:

Mathieu Faverge
committed
case PastixFloat:

Mathieu Faverge
committed
case PastixDouble:

Mathieu Faverge
committed
case PastixComplex32:

Mathieu Faverge
committed
case PastixComplex64:

Mathieu Faverge
committed
default:
return PASTIX_ERR_BADPARAMETER;
}
}
/**
*******************************************************************************
*
* @ingroup pastix_spm
*
* @brief Check the correctness of a spm.
*
* This routine initializes the sparse matrix to fit the PaStiX requirements. If
* needed, the format is changed to CSC, the duplicated vertices are merged
* together by summing their values; the graph is made symmetric for matrices
* with unsymmetric pattern, new values are set to 0.; Only the lower part is
* kept for the symmetric matrices.

Mathieu Faverge
committed
*
* On exit, if no changes have been made, the initial sparse matrix is returned,
* otherwise a copy of the sparse matrix structured fixed to meet the PaStiX
* requirements is returned.
*
*******************************************************************************
*
* @param[in,out] spm
* The pointer to the sparse matrix structure to check, and correct.
* On exit, the subarrays related to each column might have been sorted
* by ascending order.
*
*******************************************************************************
*
* @return
* \retval If no modifications were made to the initial matrix
* structure, the one given as parameter is returned
* \retval Otherwise, the news sparse matrix structure is returned. It
* must be destroyed with spmExit() and a free of the returned
* pointer.
*
*******************************************************************************/
pastix_spm_t *
spmCheckAndCorrect( pastix_spm_t *spm )

Mathieu Faverge
committed
{

Mathieu Faverge
committed
pastix_int_t count;
/* Let's work on a copy */

Mathieu Faverge
committed
/* PaStiX works on CSC matrices */

Mathieu Faverge
committed
if ( newspm->dof != 1 ) {
fprintf(stderr, "WARNING: newspm expanded due to missing check functions implementations\n");
newspm = spmExpand( newspm );
}

Mathieu Faverge
committed
/* Sort the rowptr for each column */

Mathieu Faverge
committed
/* Merge the duplicated entries by summing the values */

Mathieu Faverge
committed
if ( count > 0 ) {
fprintf(stderr, "spmCheckAndCorrect: %ld entries have been merged\n", (int64_t)count );
}
/**
* If the matrix is symmetric or hermitian, we keep only the upper or lower
* part, otherwise, we symmetrize the graph to get A+A^t, new values are set
* to 0.
*/
if ( newspm->mtxtype == PastixGeneral ) {
count = spmSymmetrize( newspm );

Mathieu Faverge
committed
if ( count > 0 ) {
fprintf(stderr, "spmCheckAndCorrect: %ld entries have been added for symmetry\n", (int64_t)count );
}
}
else {

Mathieu Faverge
committed
}
/**
* Check if we return the new one, or the original one because no changes
* have been made
*/
if (( spm->fmttype != newspm->fmttype ) ||

Mathieu Faverge
committed
{

Mathieu Faverge
committed
}
else {
spmExit( newspm );
free(newspm);
return (pastix_spm_t*)spm;

Mathieu Faverge
committed
}
}
/**
*******************************************************************************
*
* @ingroup pastix_spm
*
* @brief Create a copy of the spm

Mathieu Faverge
committed
*
* Duplicate the spm data structure given as parameter. All new arrays are
* allocated and copied from the original matrix. Both matrices need to be
* freed.

Mathieu Faverge
committed
*
*******************************************************************************
*
* @param[in] spm
* The sparse matrix to copy.
*
*******************************************************************************
*
* @return
* The copy of the sparse matrix.
*
*******************************************************************************/
pastix_spm_t *
spmCopy( const pastix_spm_t *spm )

Mathieu Faverge
committed
{
pastix_spm_t *newspm = (pastix_spm_t*)malloc(sizeof(pastix_spm_t));

Mathieu Faverge
committed
memcpy( newspm, spm, sizeof(pastix_spm_t));

Mathieu Faverge
committed
if(spm->colptr != NULL) {
newspm->colptr = (pastix_int_t*)malloc((spm->n+1) * sizeof(pastix_int_t));
memcpy( newspm->colptr, spm->colptr, (spm->n+1) * sizeof(pastix_int_t));
}
if(spm->rowptr != NULL) {
newspm->rowptr = (pastix_int_t*)malloc(spm->nnz * sizeof(pastix_int_t));
memcpy( newspm->rowptr, spm->rowptr, spm->nnz * sizeof(pastix_int_t));
}
if(spm->loc2glob != NULL) {
newspm->loc2glob = (pastix_int_t*)malloc(spm->n * sizeof(pastix_int_t));
memcpy( newspm->loc2glob, spm->loc2glob, spm->n * sizeof(pastix_int_t));
}
if(spm->values != NULL) {
size_t valsize = spm->nnzexp * pastix_size_of( spm->flttype );

Mathieu Faverge
committed
newspm->values = malloc(valsize);
memcpy( newspm->values, spm->values, valsize);
}
return newspm;
}
/**
*******************************************************************************
*
* @ingroup pastix_spm
*
* @brief Expand a multi-dof spm matrix into an spm with constant dof to 1.
*
* Duplicate the spm data structure given as parameter. All new arrays are
* allocated and copied from the original matrix. Both matrices need to be
* freed.
*
*******************************************************************************
*
* @param[in] spm
* The sparse matrix to copy.
*
*******************************************************************************
*
* @return
* The copy of the sparse matrix.
*
*******************************************************************************/
pastix_spm_t *
spmExpand(const pastix_spm_t* spm)
case PastixPattern:
return p_spmExpand(spm);
break;

Mathieu Faverge
committed
/**
*******************************************************************************
*
* @ingroup pastix_spm
*
* @brief Compute a matrix-vector product
*
* Compute the matrix vector product:
*
* y = alpha * op(A) * x + beta * y, where op(A) is one of
*
* op( A ) = A or op( A ) = A' or op( A ) = conjg( A' )
*
* alpha and beta are scalars, and x and y are vectors.

Mathieu Faverge
committed
*
*******************************************************************************
*
* @param[in] trans
* Specifies whether the matrix spm is transposed, not transposed or
* conjugate transposed:
* = PastixNoTrans: A is not transposed;
* = PastixTrans: A is transposed;
* = PastixConjTrans: A is conjugate transposed.

Mathieu Faverge
committed
*
* @param[in] alpha
* alpha specifies the scalar alpha.
*
* @param[in] spm
* The PastixGeneral spm.
*
* @param[in] x
* The vector x.
*
* @param[in] beta
* beta specifies the scalar beta.
*
* @param[in,out] y
* The vector y.
*
*******************************************************************************
*
* @return
* \retval PASTIX_SUCCESS if the y vector has been computed succesfully,
* \retval PASTIX_ERR_BADPARAMETER otherwise.

Mathieu Faverge
committed
*
*******************************************************************************/
int
spmMatVec(const pastix_trans_t trans,
const void *alpha,
const pastix_spm_t *spm,
const void *x,
const void *beta,
void *y )

Mathieu Faverge
committed
{
if ( spm->fmttype != PastixCSC ) {
return PASTIX_ERR_BADPARAMETER;
}
switch (spm->flttype) {
case PastixFloat:
return s_spmCSCMatVec( trans, alpha, spm, x, beta, y );
case PastixComplex32:
return c_spmCSCMatVec( trans, alpha, spm, x, beta, y );
case PastixComplex64:
return z_spmCSCMatVec( trans, alpha, spm, x, beta, y );
case PastixDouble:

Mathieu Faverge
committed
default:
return d_spmCSCMatVec( trans, alpha, spm, x, beta, y );

Mathieu Faverge
committed
}
}
/**
*******************************************************************************
*

Mathieu Faverge
committed
*
* @brief Generate right hand sides.
*
* Generate nrhs right hand side vectors associated to a given matrix to test a
* problem with a solver. The vectors can be initialized randomly, or to get a
* specific solution.

Mathieu Faverge
committed
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
*
*******************************************************************************
*
* @param[in] type
* Defines how to compute the vector b.
* - PastixRhsOne: b is computed such that x = 1 [ + I ]
* - PastixRhsI: b is computed such that x = i [ + i * I ]
* - PastixRhsRndX: b is computed by matrix-vector product, such that
* is a random vector in the range [-0.5, 0.5]
* - PastixRhsRndB: b is computed randomly and x is not computed.
*
* @param[in] nrhs
* Defines the number of right hand side that must be generated.
*
* @param[in] spm
* The sparse matrix uses to generate the right hand side, and the
* solution of the full problem.
*
* @param[out] x
* On exit, if x != NULL, then the x vector(s) generated to compute b
* is returned. Must be of size at least ldx * spm->n.
*
* @param[in] ldx
* Defines the leading dimension of x when multiple right hand sides
* are available. ldx >= spm->n.
*
* @param[in,out] b
* b must be an allocated matrix of size at least ldb * nrhs.
* On exit, b is initialized as defined by the type parameter.
*
* @param[in] ldb
* Defines the leading dimension of b when multiple right hand sides
* are available. ldb >= spm->n.
*
*******************************************************************************
*
* @return
* \retval PASTIX_SUCCESS if the b vector has been computed succesfully,
* \retval PASTIX_ERR_BADPARAMETER otherwise.
*
*******************************************************************************/
int
spmGenRHS( int type, int nrhs,

Mathieu Faverge
committed
void *x, int ldx,
void *b, int ldb )
{
static int (*ptrfunc[4])(int, int,

Mathieu Faverge
committed
void *, int, void *, int) =
{
s_spmGenRHS, d_spmGenRHS, c_spmGenRHS, z_spmGenRHS
};
int id = spm->flttype - PastixFloat;
if ( (id < 0) || (id > 3) ) {
return PASTIX_ERR_BADPARAMETER;
}
else {
return ptrfunc[id](type, nrhs, spm, x, ldx, b, ldb );
}
}
/**
*******************************************************************************
*

Mathieu Faverge
committed
*
* @brief Check backward and forward errors
*
* Check the backward error, and the forward error if x0 is provided.

Mathieu Faverge
committed
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
*
*******************************************************************************
*
* @param[in] nrhs
* Defines the number of right hand side that must be generated.
*
* @param[in] spm
* The sparse matrix uses to generate the right hand side, and the
* solution of the full problem.
*
* @param[in,out] x0
* If x0 != NULL, the forward error is computed.
* On exit, x0 stores (x0-x)
*
* @param[in] ldx0
* Defines the leading dimension of x0 when multiple right hand sides
* are available. ldx0 >= spm->n.
*
* @param[in,out] b
* b is a matrix of size at least ldb * nrhs.
* On exit, b stores Ax-b.
*
* @param[in] ldb
* Defines the leading dimension of b when multiple right hand sides
* are available. ldb >= spm->n.
*
* @param[in] x
* Contains the solution computed by the solver.
*
* @param[in] ldx
* Defines the leading dimension of x when multiple right hand sides
* are available. ldx >= spm->n.
*
*******************************************************************************
*
* @return
* \retval PASTIX_SUCCESS if the b vector has been computed succesfully,
* \retval PASTIX_ERR_BADPARAMETER otherwise.
*
*******************************************************************************/
int
spmCheckAxb( int nrhs,

Mathieu Faverge
committed
void *x0, int ldx0,
void *b, int ldb,
const void *x, int ldx )
{
static int (*ptrfunc[4])(int, const pastix_spm_t *,

Mathieu Faverge
committed
void *, int, void *, int, const void *, int) =
{
s_spmCheckAxb, d_spmCheckAxb, c_spmCheckAxb, z_spmCheckAxb
};
int id = spm->flttype - PastixFloat;
if ( (id < 0) || (id > 3) ) {
return PASTIX_ERR_BADPARAMETER;
}
else {
return ptrfunc[id](nrhs, spm, x0, ldx0, b, ldb, x, ldx );
}
}