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->flttype = PastixComplex64;
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->colmajor = 1;
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;
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;
}
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
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
{
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
*
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
* @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 ( 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
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
*
* 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
{
double tmp;

Mathieu Faverge
committed
case PastixFloat:

Mathieu Faverge
committed
return tmp;
case PastixDouble:

Mathieu Faverge
committed
case PastixComplex32:

Mathieu Faverge
committed
return tmp;
case PastixComplex64:

Mathieu Faverge
committed
default:
return -1.;
}
}
/**
*******************************************************************************
*
* @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
{

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
{

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
{

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
/* 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 ) ||
( spm->nnz != newspm->nnz ) )

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
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
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->nnz * pastix_size_of( spm->flttype );
newspm->values = malloc(valsize);
memcpy( newspm->values, spm->values, valsize);
}
return newspm;
}
/**
*******************************************************************************
*
* @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
*
*******************************************************************************/
/**
* TODO: Maybe we should move down the cast of the parameters to the lowest
* functions, and simplify this one to have identical calls to all subfunction
*/
int
spmMatVec( int trans,
const void *alpha,

Mathieu Faverge
committed
const void *x,
const void *beta,
void *y )
{

Mathieu Faverge
committed
case PastixHermitian:

Mathieu Faverge
committed
case PastixFloat:
return s_spmSyCSCv( *((const float*)alpha), spm, (const float*)x, *((const float*)beta), (float*)y );

Mathieu Faverge
committed
case PastixComplex32:
return c_spmHeCSCv( *((const pastix_complex32_t*)alpha), spm, (const pastix_complex32_t*)x, *((const pastix_complex32_t*)beta), (pastix_complex32_t*)y );

Mathieu Faverge
committed
case PastixComplex64:
return z_spmHeCSCv( *((const pastix_complex64_t*)alpha), spm, (const pastix_complex64_t*)x, *((const pastix_complex64_t*)beta), (pastix_complex64_t*)y );

Mathieu Faverge
committed
case PastixDouble:
default:
return d_spmSyCSCv( *((const double*)alpha), spm, (const double*)x, *((const double*)beta), (double*)y );

Mathieu Faverge
committed
}
case PastixSymmetric:

Mathieu Faverge
committed
case PastixFloat:
return s_spmSyCSCv( *((const float*)alpha), spm, (const float*)x, *((const float*)beta), (float*)y );

Mathieu Faverge
committed
case PastixComplex32:
return c_spmSyCSCv( *((const pastix_complex32_t*)alpha), spm, (const pastix_complex32_t*)x, *((const pastix_complex32_t*)beta), (pastix_complex32_t*)y );

Mathieu Faverge
committed
case PastixComplex64:
return z_spmSyCSCv( *((const pastix_complex64_t*)alpha), spm, (const pastix_complex64_t*)x, *((const pastix_complex64_t*)beta), (pastix_complex64_t*)y );

Mathieu Faverge
committed
case PastixDouble:
default:
return d_spmSyCSCv( *((const double*)alpha), spm, (const double*)x, *((const double*)beta), (double*)y );

Mathieu Faverge
committed
}
case PastixGeneral:
default:

Mathieu Faverge
committed
case PastixFloat:
return s_spmGeCSCv( trans, *((const float*)alpha), spm, (const float*)x, *((const float*)beta), (float*)y );

Mathieu Faverge
committed
case PastixComplex32:
return c_spmGeCSCv( trans, *((const pastix_complex32_t*)alpha), spm, (const pastix_complex32_t*)x, *((const pastix_complex32_t*)beta), (pastix_complex32_t*)y );

Mathieu Faverge
committed
case PastixComplex64:
return z_spmGeCSCv( trans, *((const pastix_complex64_t*)alpha), spm, (const pastix_complex64_t*)x, *((const pastix_complex64_t*)beta), (pastix_complex64_t*)y );

Mathieu Faverge
committed
case PastixDouble:
default:
return d_spmGeCSCv( trans, *((const double*)alpha), spm, (const double*)x, *((const double*)beta), (double*)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
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
*
*******************************************************************************
*
* @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
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
864
*
*******************************************************************************
*
* @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 );
}
}