mirror of
https://github.com/NVIDIA/cuda-samples.git
synced 2026-10-25 22:28:17 +08:00
Apply consistent code formatting across the repo. Add clang-format and pre-commit hooks.
This commit is contained in:
@@ -9,64 +9,56 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <cuda_runtime.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "cusolverSp.h"
|
||||
|
||||
#include "cusolverSp_LOWLEVEL_PREVIEW.h"
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
|
||||
#include "helper_cuda.h"
|
||||
#include "helper_cusolver.h"
|
||||
|
||||
template <typename T_ELEM>
|
||||
int loadMMSparseMatrix(
|
||||
char *filename,
|
||||
char elem_type,
|
||||
bool csrFormat,
|
||||
int *m,
|
||||
int *n,
|
||||
int *nnz,
|
||||
T_ELEM **aVal,
|
||||
int **aRowInd,
|
||||
int **aColInd,
|
||||
int extendSymMatrix);
|
||||
int loadMMSparseMatrix(char *filename,
|
||||
char elem_type,
|
||||
bool csrFormat,
|
||||
int *m,
|
||||
int *n,
|
||||
int *nnz,
|
||||
T_ELEM **aVal,
|
||||
int **aRowInd,
|
||||
int **aColInd,
|
||||
int extendSymMatrix);
|
||||
|
||||
void UsageSP(void)
|
||||
{
|
||||
printf( "<options>\n");
|
||||
printf( "-h : display this help\n");
|
||||
printf( "-file=<filename> : filename containing a matrix in MM format\n");
|
||||
printf( "-device=<device_id> : <device_id> if want to run on specific GPU\n");
|
||||
printf("<options>\n");
|
||||
printf("-h : display this help\n");
|
||||
printf("-file=<filename> : filename containing a matrix in MM format\n");
|
||||
printf("-device=<device_id> : <device_id> if want to run on specific GPU\n");
|
||||
|
||||
exit( 0 );
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void parseCommandLineArguments(int argc, char *argv[], struct testOpts &opts)
|
||||
{
|
||||
memset(&opts, 0, sizeof(opts));
|
||||
|
||||
if (checkCmdLineFlag(argc, (const char **)argv, "-h"))
|
||||
{
|
||||
if (checkCmdLineFlag(argc, (const char **)argv, "-h")) {
|
||||
UsageSP();
|
||||
}
|
||||
|
||||
if (checkCmdLineFlag(argc, (const char **)argv, "file"))
|
||||
{
|
||||
if (checkCmdLineFlag(argc, (const char **)argv, "file")) {
|
||||
char *fileName = 0;
|
||||
getCmdLineArgumentString(argc, (const char **)argv, "file", &fileName);
|
||||
|
||||
if (fileName)
|
||||
{
|
||||
if (fileName) {
|
||||
opts.sparse_mat_filename = fileName;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
printf("\nIncorrect filename passed to -file \n ");
|
||||
UsageSP();
|
||||
}
|
||||
@@ -74,16 +66,16 @@ void parseCommandLineArguments(int argc, char *argv[], struct testOpts &opts)
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct testOpts opts;
|
||||
struct testOpts opts;
|
||||
cusolverSpHandle_t cusolverSpH = NULL; // reordering, permutation and 1st LU factorization
|
||||
cusparseHandle_t cusparseH = NULL; // residual evaluation
|
||||
cudaStream_t stream = NULL;
|
||||
cusparseMatDescr_t descrA = NULL; // A is a base-0 general matrix
|
||||
cusparseHandle_t cusparseH = NULL; // residual evaluation
|
||||
cudaStream_t stream = NULL;
|
||||
cusparseMatDescr_t descrA = NULL; // A is a base-0 general matrix
|
||||
|
||||
csrcholInfoHost_t h_info = NULL; // opaque info structure for LU with parital pivoting
|
||||
csrcholInfo_t d_info = NULL; // opaque info structure for LU with parital pivoting
|
||||
csrcholInfo_t d_info = NULL; // opaque info structure for LU with parital pivoting
|
||||
|
||||
int rowsA = 0; // number of rows of A
|
||||
int colsA = 0; // number of columns of A
|
||||
@@ -91,76 +83,78 @@ int main (int argc, char *argv[])
|
||||
int baseA = 0; // base index in CSR format
|
||||
|
||||
// CSR(A) from I/O
|
||||
int *h_csrRowPtrA = NULL; // <int> n+1
|
||||
int *h_csrColIndA = NULL; // <int> nnzA
|
||||
double *h_csrValA = NULL; // <double> nnzA
|
||||
int *h_csrRowPtrA = NULL; // <int> n+1
|
||||
int *h_csrColIndA = NULL; // <int> nnzA
|
||||
double *h_csrValA = NULL; // <double> nnzA
|
||||
|
||||
double *h_x = NULL; // <double> n, x = A \ b
|
||||
double *h_b = NULL; // <double> n, b = ones(m,1)
|
||||
double *h_r = NULL; // <double> n, r = b - A*x
|
||||
|
||||
size_t size_internal = 0;
|
||||
size_t size_chol = 0; // size of working space for csrlu
|
||||
void *buffer_cpu = NULL; // working space for Cholesky
|
||||
void *buffer_gpu = NULL; // working space for Cholesky
|
||||
size_t size_internal = 0;
|
||||
size_t size_chol = 0; // size of working space for csrlu
|
||||
void *buffer_cpu = NULL; // working space for Cholesky
|
||||
void *buffer_gpu = NULL; // working space for Cholesky
|
||||
|
||||
int *d_csrRowPtrA = NULL; // <int> n+1
|
||||
int *d_csrColIndA = NULL; // <int> nnzA
|
||||
double *d_csrValA = NULL; // <double> nnzA
|
||||
double *d_x = NULL; // <double> n, x = A \ b
|
||||
double *d_b = NULL; // <double> n, a copy of h_b
|
||||
double *d_r = NULL; // <double> n, r = b - A*x
|
||||
int *d_csrRowPtrA = NULL; // <int> n+1
|
||||
int *d_csrColIndA = NULL; // <int> nnzA
|
||||
double *d_csrValA = NULL; // <double> nnzA
|
||||
double *d_x = NULL; // <double> n, x = A \ b
|
||||
double *d_b = NULL; // <double> n, a copy of h_b
|
||||
double *d_r = NULL; // <double> n, r = b - A*x
|
||||
|
||||
// the constants used in residual evaluation, r = b - A*x
|
||||
const double minus_one = -1.0;
|
||||
const double one = 1.0;
|
||||
const double one = 1.0;
|
||||
// the constant used in cusolverSp
|
||||
// singularity is -1 if A is invertible under tol
|
||||
// tol determines the condition of singularity
|
||||
int singularity = 0;
|
||||
const double tol = 1.e-14;
|
||||
int singularity = 0;
|
||||
const double tol = 1.e-14;
|
||||
|
||||
double x_inf = 0.0; // |x|
|
||||
double r_inf = 0.0; // |r|
|
||||
double A_inf = 0.0; // |A|
|
||||
int errors = 0;
|
||||
double x_inf = 0.0; // |x|
|
||||
double r_inf = 0.0; // |r|
|
||||
double A_inf = 0.0; // |A|
|
||||
int errors = 0;
|
||||
|
||||
parseCommandLineArguments(argc, argv, opts);
|
||||
|
||||
findCudaDevice(argc, (const char **)argv);
|
||||
|
||||
if (opts.sparse_mat_filename == NULL)
|
||||
{
|
||||
opts.sparse_mat_filename = sdkFindFilePath("lap2D_5pt_n100.mtx", argv[0]);
|
||||
if (opts.sparse_mat_filename == NULL) {
|
||||
opts.sparse_mat_filename = sdkFindFilePath("lap2D_5pt_n100.mtx", argv[0]);
|
||||
if (opts.sparse_mat_filename != NULL)
|
||||
printf("Using default input file [%s]\n", opts.sparse_mat_filename);
|
||||
else
|
||||
printf("Could not find lap2D_5pt_n100.mtx\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
printf("Using input file [%s]\n", opts.sparse_mat_filename);
|
||||
}
|
||||
|
||||
printf("step 1: read matrix market format\n");
|
||||
|
||||
if (opts.sparse_mat_filename)
|
||||
{
|
||||
if (loadMMSparseMatrix<double>(opts.sparse_mat_filename, 'd', true , &rowsA, &colsA,
|
||||
&nnzA, &h_csrValA, &h_csrRowPtrA, &h_csrColIndA, true))
|
||||
{
|
||||
if (opts.sparse_mat_filename) {
|
||||
if (loadMMSparseMatrix<double>(opts.sparse_mat_filename,
|
||||
'd',
|
||||
true,
|
||||
&rowsA,
|
||||
&colsA,
|
||||
&nnzA,
|
||||
&h_csrValA,
|
||||
&h_csrRowPtrA,
|
||||
&h_csrColIndA,
|
||||
true)) {
|
||||
return 1;
|
||||
}
|
||||
baseA = h_csrRowPtrA[0]; // baseA = {0,1}
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
fprintf(stderr, "Error: input matrix is not provided\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( rowsA != colsA )
|
||||
{
|
||||
if (rowsA != colsA) {
|
||||
fprintf(stderr, "Error: only support square matrix\n");
|
||||
return 1;
|
||||
}
|
||||
@@ -180,32 +174,29 @@ int main (int argc, char *argv[])
|
||||
checkCudaErrors(cusparseCreateMatDescr(&descrA));
|
||||
|
||||
checkCudaErrors(cusparseSetMatType(descrA, CUSPARSE_MATRIX_TYPE_GENERAL));
|
||||
if (baseA)
|
||||
{
|
||||
if (baseA) {
|
||||
checkCudaErrors(cusparseSetMatIndexBase(descrA, CUSPARSE_INDEX_BASE_ONE));
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
checkCudaErrors(cusparseSetMatIndexBase(descrA, CUSPARSE_INDEX_BASE_ZERO));
|
||||
}
|
||||
|
||||
h_x = (double*)malloc(sizeof(double)*colsA);
|
||||
h_b = (double*)malloc(sizeof(double)*rowsA);
|
||||
h_r = (double*)malloc(sizeof(double)*rowsA);
|
||||
h_x = (double *)malloc(sizeof(double) * colsA);
|
||||
h_b = (double *)malloc(sizeof(double) * rowsA);
|
||||
h_r = (double *)malloc(sizeof(double) * rowsA);
|
||||
|
||||
assert(NULL != h_x);
|
||||
assert(NULL != h_b);
|
||||
assert(NULL != h_r);
|
||||
|
||||
checkCudaErrors(cudaMalloc((void **)&d_csrRowPtrA, sizeof(int)*(rowsA+1)));
|
||||
checkCudaErrors(cudaMalloc((void **)&d_csrColIndA, sizeof(int)*nnzA));
|
||||
checkCudaErrors(cudaMalloc((void **)&d_csrValA , sizeof(double)*nnzA));
|
||||
checkCudaErrors(cudaMalloc((void **)&d_x, sizeof(double)*colsA));
|
||||
checkCudaErrors(cudaMalloc((void **)&d_b, sizeof(double)*rowsA));
|
||||
checkCudaErrors(cudaMalloc((void **)&d_r, sizeof(double)*rowsA));
|
||||
checkCudaErrors(cudaMalloc((void **)&d_csrRowPtrA, sizeof(int) * (rowsA + 1)));
|
||||
checkCudaErrors(cudaMalloc((void **)&d_csrColIndA, sizeof(int) * nnzA));
|
||||
checkCudaErrors(cudaMalloc((void **)&d_csrValA, sizeof(double) * nnzA));
|
||||
checkCudaErrors(cudaMalloc((void **)&d_x, sizeof(double) * colsA));
|
||||
checkCudaErrors(cudaMalloc((void **)&d_b, sizeof(double) * rowsA));
|
||||
checkCudaErrors(cudaMalloc((void **)&d_r, sizeof(double) * rowsA));
|
||||
|
||||
for(int row = 0 ; row < rowsA ; row++)
|
||||
{
|
||||
for (int row = 0; row < rowsA; row++) {
|
||||
h_b[row] = 1.0;
|
||||
}
|
||||
|
||||
@@ -213,69 +204,70 @@ int main (int argc, char *argv[])
|
||||
checkCudaErrors(cusolverSpCreateCsrcholInfoHost(&h_info));
|
||||
|
||||
printf("step 3: analyze chol(A) to know structure of L\n");
|
||||
checkCudaErrors(cusolverSpXcsrcholAnalysisHost(
|
||||
cusolverSpH, rowsA, nnzA,
|
||||
descrA, h_csrRowPtrA, h_csrColIndA,
|
||||
h_info));
|
||||
checkCudaErrors(
|
||||
cusolverSpXcsrcholAnalysisHost(cusolverSpH, rowsA, nnzA, descrA, h_csrRowPtrA, h_csrColIndA, h_info));
|
||||
|
||||
printf("step 4: workspace for chol(A)\n");
|
||||
checkCudaErrors(cusolverSpDcsrcholBufferInfoHost(
|
||||
cusolverSpH, rowsA, nnzA,
|
||||
descrA, h_csrValA, h_csrRowPtrA, h_csrColIndA,
|
||||
h_info,
|
||||
&size_internal,
|
||||
&size_chol));
|
||||
cusolverSpH, rowsA, nnzA, descrA, h_csrValA, h_csrRowPtrA, h_csrColIndA, h_info, &size_internal, &size_chol));
|
||||
|
||||
if (buffer_cpu)
|
||||
{
|
||||
free(buffer_cpu);
|
||||
if (buffer_cpu) {
|
||||
free(buffer_cpu);
|
||||
}
|
||||
buffer_cpu = (void*)malloc(sizeof(char)*size_chol);
|
||||
buffer_cpu = (void *)malloc(sizeof(char) * size_chol);
|
||||
assert(NULL != buffer_cpu);
|
||||
|
||||
printf("step 5: compute A = L*L^T \n");
|
||||
checkCudaErrors(cusolverSpDcsrcholFactorHost(
|
||||
cusolverSpH, rowsA, nnzA,
|
||||
descrA, h_csrValA, h_csrRowPtrA, h_csrColIndA,
|
||||
h_info,
|
||||
buffer_cpu));
|
||||
cusolverSpH, rowsA, nnzA, descrA, h_csrValA, h_csrRowPtrA, h_csrColIndA, h_info, buffer_cpu));
|
||||
|
||||
printf("step 6: check if the matrix is singular \n");
|
||||
checkCudaErrors(cusolverSpDcsrcholZeroPivotHost(
|
||||
cusolverSpH, h_info, tol, &singularity));
|
||||
checkCudaErrors(cusolverSpDcsrcholZeroPivotHost(cusolverSpH, h_info, tol, &singularity));
|
||||
|
||||
if ( 0 <= singularity)
|
||||
{
|
||||
if (0 <= singularity) {
|
||||
fprintf(stderr, "Error: A is not invertible, singularity=%d\n", singularity);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("step 7: solve A*x = b \n");
|
||||
checkCudaErrors(cusolverSpDcsrcholSolveHost(
|
||||
cusolverSpH, rowsA, h_b, h_x, h_info, buffer_cpu));
|
||||
checkCudaErrors(cusolverSpDcsrcholSolveHost(cusolverSpH, rowsA, h_b, h_x, h_info, buffer_cpu));
|
||||
|
||||
printf("step 8: evaluate residual r = b - A*x (result on CPU)\n");
|
||||
// use GPU gemv to compute r = b - A*x
|
||||
checkCudaErrors(cudaMemcpy(d_csrRowPtrA, h_csrRowPtrA, sizeof(int)*(rowsA+1), cudaMemcpyHostToDevice));
|
||||
checkCudaErrors(cudaMemcpy(d_csrColIndA, h_csrColIndA, sizeof(int)*nnzA , cudaMemcpyHostToDevice));
|
||||
checkCudaErrors(cudaMemcpy(d_csrValA , h_csrValA , sizeof(double)*nnzA , cudaMemcpyHostToDevice));
|
||||
checkCudaErrors(cudaMemcpy(d_csrRowPtrA, h_csrRowPtrA, sizeof(int) * (rowsA + 1), cudaMemcpyHostToDevice));
|
||||
checkCudaErrors(cudaMemcpy(d_csrColIndA, h_csrColIndA, sizeof(int) * nnzA, cudaMemcpyHostToDevice));
|
||||
checkCudaErrors(cudaMemcpy(d_csrValA, h_csrValA, sizeof(double) * nnzA, cudaMemcpyHostToDevice));
|
||||
|
||||
checkCudaErrors(cudaMemcpy(d_r, h_b, sizeof(double)*rowsA, cudaMemcpyHostToDevice));
|
||||
checkCudaErrors(cudaMemcpy(d_x, h_x, sizeof(double)*colsA, cudaMemcpyHostToDevice));
|
||||
checkCudaErrors(cudaMemcpy(d_r, h_b, sizeof(double) * rowsA, cudaMemcpyHostToDevice));
|
||||
checkCudaErrors(cudaMemcpy(d_x, h_x, sizeof(double) * colsA, cudaMemcpyHostToDevice));
|
||||
|
||||
/* Wrap raw data into cuSPARSE generic API objects */
|
||||
cusparseSpMatDescr_t matA = NULL;
|
||||
if (baseA)
|
||||
{
|
||||
checkCudaErrors(cusparseCreateCsr(
|
||||
&matA, rowsA, colsA, nnzA, d_csrRowPtrA, d_csrColIndA, d_csrValA, CUSPARSE_INDEX_32I,
|
||||
CUSPARSE_INDEX_32I, CUSPARSE_INDEX_BASE_ONE, CUDA_R_64F));
|
||||
if (baseA) {
|
||||
checkCudaErrors(cusparseCreateCsr(&matA,
|
||||
rowsA,
|
||||
colsA,
|
||||
nnzA,
|
||||
d_csrRowPtrA,
|
||||
d_csrColIndA,
|
||||
d_csrValA,
|
||||
CUSPARSE_INDEX_32I,
|
||||
CUSPARSE_INDEX_32I,
|
||||
CUSPARSE_INDEX_BASE_ONE,
|
||||
CUDA_R_64F));
|
||||
}
|
||||
else
|
||||
{
|
||||
checkCudaErrors(cusparseCreateCsr(
|
||||
&matA, rowsA, colsA, nnzA, d_csrRowPtrA, d_csrColIndA, d_csrValA, CUSPARSE_INDEX_32I,
|
||||
CUSPARSE_INDEX_32I, CUSPARSE_INDEX_BASE_ZERO, CUDA_R_64F));
|
||||
else {
|
||||
checkCudaErrors(cusparseCreateCsr(&matA,
|
||||
rowsA,
|
||||
colsA,
|
||||
nnzA,
|
||||
d_csrRowPtrA,
|
||||
d_csrColIndA,
|
||||
d_csrValA,
|
||||
CUSPARSE_INDEX_32I,
|
||||
CUSPARSE_INDEX_32I,
|
||||
CUSPARSE_INDEX_BASE_ZERO,
|
||||
CUDA_R_64F));
|
||||
}
|
||||
|
||||
cusparseDnVecDescr_t vecx = NULL;
|
||||
@@ -285,17 +277,31 @@ int main (int argc, char *argv[])
|
||||
|
||||
/* Allocate workspace for cuSPARSE */
|
||||
size_t bufferSize = 0;
|
||||
checkCudaErrors(cusparseSpMV_bufferSize(
|
||||
cusparseH, CUSPARSE_OPERATION_NON_TRANSPOSE, &minus_one, matA, vecx,
|
||||
&one, vecAx, CUDA_R_64F, CUSPARSE_SPMV_ALG_DEFAULT, &bufferSize));
|
||||
checkCudaErrors(cusparseSpMV_bufferSize(cusparseH,
|
||||
CUSPARSE_OPERATION_NON_TRANSPOSE,
|
||||
&minus_one,
|
||||
matA,
|
||||
vecx,
|
||||
&one,
|
||||
vecAx,
|
||||
CUDA_R_64F,
|
||||
CUSPARSE_SPMV_ALG_DEFAULT,
|
||||
&bufferSize));
|
||||
void *buffer = NULL;
|
||||
checkCudaErrors(cudaMalloc(&buffer, bufferSize));
|
||||
|
||||
checkCudaErrors(cusparseSpMV(
|
||||
cusparseH, CUSPARSE_OPERATION_NON_TRANSPOSE, &minus_one, matA, vecx,
|
||||
&one, vecAx, CUDA_R_64F, CUSPARSE_SPMV_ALG_DEFAULT, buffer));
|
||||
checkCudaErrors(cusparseSpMV(cusparseH,
|
||||
CUSPARSE_OPERATION_NON_TRANSPOSE,
|
||||
&minus_one,
|
||||
matA,
|
||||
vecx,
|
||||
&one,
|
||||
vecAx,
|
||||
CUDA_R_64F,
|
||||
CUSPARSE_SPMV_ALG_DEFAULT,
|
||||
buffer));
|
||||
|
||||
checkCudaErrors(cudaMemcpy(h_r, d_r, sizeof(double)*rowsA, cudaMemcpyDeviceToHost));
|
||||
checkCudaErrors(cudaMemcpy(h_r, d_r, sizeof(double) * rowsA, cudaMemcpyDeviceToHost));
|
||||
|
||||
x_inf = vec_norminf(colsA, h_x);
|
||||
r_inf = vec_norminf(rowsA, h_r);
|
||||
@@ -304,97 +310,137 @@ int main (int argc, char *argv[])
|
||||
printf("(CPU) |b - A*x| = %E \n", r_inf);
|
||||
printf("(CPU) |A| = %E \n", A_inf);
|
||||
printf("(CPU) |x| = %E \n", x_inf);
|
||||
printf("(CPU) |b - A*x|/(|A|*|x|) = %E \n", r_inf/(A_inf * x_inf));
|
||||
printf("(CPU) |b - A*x|/(|A|*|x|) = %E \n", r_inf / (A_inf * x_inf));
|
||||
|
||||
printf("step 9: create opaque info structure\n");
|
||||
checkCudaErrors(cusolverSpCreateCsrcholInfo(&d_info));
|
||||
|
||||
checkCudaErrors(cudaMemcpy(d_csrRowPtrA, h_csrRowPtrA, sizeof(int)*(rowsA+1), cudaMemcpyHostToDevice));
|
||||
checkCudaErrors(cudaMemcpy(d_csrColIndA, h_csrColIndA, sizeof(int)*nnzA , cudaMemcpyHostToDevice));
|
||||
checkCudaErrors(cudaMemcpy(d_csrValA , h_csrValA , sizeof(double)*nnzA , cudaMemcpyHostToDevice));
|
||||
checkCudaErrors(cudaMemcpy(d_b, h_b, sizeof(double)*rowsA, cudaMemcpyHostToDevice));
|
||||
checkCudaErrors(cudaMemcpy(d_csrRowPtrA, h_csrRowPtrA, sizeof(int) * (rowsA + 1), cudaMemcpyHostToDevice));
|
||||
checkCudaErrors(cudaMemcpy(d_csrColIndA, h_csrColIndA, sizeof(int) * nnzA, cudaMemcpyHostToDevice));
|
||||
checkCudaErrors(cudaMemcpy(d_csrValA, h_csrValA, sizeof(double) * nnzA, cudaMemcpyHostToDevice));
|
||||
checkCudaErrors(cudaMemcpy(d_b, h_b, sizeof(double) * rowsA, cudaMemcpyHostToDevice));
|
||||
|
||||
printf("step 10: analyze chol(A) to know structure of L\n");
|
||||
checkCudaErrors(cusolverSpXcsrcholAnalysis(
|
||||
cusolverSpH, rowsA, nnzA,
|
||||
descrA, d_csrRowPtrA, d_csrColIndA,
|
||||
d_info));
|
||||
checkCudaErrors(cusolverSpXcsrcholAnalysis(cusolverSpH, rowsA, nnzA, descrA, d_csrRowPtrA, d_csrColIndA, d_info));
|
||||
|
||||
printf("step 11: workspace for chol(A)\n");
|
||||
checkCudaErrors(cusolverSpDcsrcholBufferInfo(
|
||||
cusolverSpH, rowsA, nnzA,
|
||||
descrA, d_csrValA, d_csrRowPtrA, d_csrColIndA,
|
||||
d_info,
|
||||
&size_internal,
|
||||
&size_chol));
|
||||
cusolverSpH, rowsA, nnzA, descrA, d_csrValA, d_csrRowPtrA, d_csrColIndA, d_info, &size_internal, &size_chol));
|
||||
|
||||
if (buffer_gpu) {
|
||||
checkCudaErrors(cudaFree(buffer_gpu));
|
||||
}
|
||||
checkCudaErrors(cudaMalloc(&buffer_gpu, sizeof(char)*size_chol));
|
||||
checkCudaErrors(cudaMalloc(&buffer_gpu, sizeof(char) * size_chol));
|
||||
|
||||
printf("step 12: compute A = L*L^T \n");
|
||||
checkCudaErrors(cusolverSpDcsrcholFactor(
|
||||
cusolverSpH, rowsA, nnzA,
|
||||
descrA, d_csrValA, d_csrRowPtrA, d_csrColIndA,
|
||||
d_info,
|
||||
buffer_gpu));
|
||||
cusolverSpH, rowsA, nnzA, descrA, d_csrValA, d_csrRowPtrA, d_csrColIndA, d_info, buffer_gpu));
|
||||
|
||||
printf("step 13: check if the matrix is singular \n");
|
||||
checkCudaErrors(cusolverSpDcsrcholZeroPivot(
|
||||
cusolverSpH, d_info, tol, &singularity));
|
||||
checkCudaErrors(cusolverSpDcsrcholZeroPivot(cusolverSpH, d_info, tol, &singularity));
|
||||
|
||||
if ( 0 <= singularity){
|
||||
if (0 <= singularity) {
|
||||
fprintf(stderr, "Error: A is not invertible, singularity=%d\n", singularity);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("step 14: solve A*x = b \n");
|
||||
checkCudaErrors(cusolverSpDcsrcholSolve(
|
||||
cusolverSpH, rowsA, d_b, d_x, d_info, buffer_gpu));
|
||||
checkCudaErrors(cusolverSpDcsrcholSolve(cusolverSpH, rowsA, d_b, d_x, d_info, buffer_gpu));
|
||||
|
||||
checkCudaErrors(cudaMemcpy(d_r, h_b, sizeof(double)*rowsA, cudaMemcpyHostToDevice));
|
||||
checkCudaErrors(cudaMemcpy(d_r, h_b, sizeof(double) * rowsA, cudaMemcpyHostToDevice));
|
||||
|
||||
checkCudaErrors(cusparseSpMV(
|
||||
cusparseH, CUSPARSE_OPERATION_NON_TRANSPOSE, &minus_one, matA, vecx,
|
||||
&one, vecAx, CUDA_R_64F, CUSPARSE_SPMV_ALG_DEFAULT, buffer));
|
||||
checkCudaErrors(cusparseSpMV(cusparseH,
|
||||
CUSPARSE_OPERATION_NON_TRANSPOSE,
|
||||
&minus_one,
|
||||
matA,
|
||||
vecx,
|
||||
&one,
|
||||
vecAx,
|
||||
CUDA_R_64F,
|
||||
CUSPARSE_SPMV_ALG_DEFAULT,
|
||||
buffer));
|
||||
|
||||
checkCudaErrors(cudaMemcpy(h_r, d_r, sizeof(double)*rowsA, cudaMemcpyDeviceToHost));
|
||||
checkCudaErrors(cudaMemcpy(h_r, d_r, sizeof(double) * rowsA, cudaMemcpyDeviceToHost));
|
||||
|
||||
r_inf = vec_norminf(rowsA, h_r);
|
||||
|
||||
printf("(GPU) |b - A*x| = %E \n", r_inf);
|
||||
printf("(GPU) |b - A*x|/(|A|*|x|) = %E \n", r_inf/(A_inf * x_inf));
|
||||
printf("(GPU) |b - A*x|/(|A|*|x|) = %E \n", r_inf / (A_inf * x_inf));
|
||||
|
||||
|
||||
if (cusolverSpH) { checkCudaErrors(cusolverSpDestroy(cusolverSpH)); }
|
||||
if (cusparseH ) { checkCudaErrors(cusparseDestroy(cusparseH)); }
|
||||
if (stream ) { checkCudaErrors(cudaStreamDestroy(stream)); }
|
||||
if (descrA ) { checkCudaErrors(cusparseDestroyMatDescr(descrA)); }
|
||||
if (h_info ) { checkCudaErrors(cusolverSpDestroyCsrcholInfoHost(h_info)); }
|
||||
if (d_info ) { checkCudaErrors(cusolverSpDestroyCsrcholInfo(d_info)); }
|
||||
if (matA ) { checkCudaErrors(cusparseDestroySpMat(matA)); }
|
||||
if (vecx ) { checkCudaErrors(cusparseDestroyDnVec(vecx)); }
|
||||
if (vecAx ) { checkCudaErrors(cusparseDestroyDnVec(vecAx)); }
|
||||
if (cusolverSpH) {
|
||||
checkCudaErrors(cusolverSpDestroy(cusolverSpH));
|
||||
}
|
||||
if (cusparseH) {
|
||||
checkCudaErrors(cusparseDestroy(cusparseH));
|
||||
}
|
||||
if (stream) {
|
||||
checkCudaErrors(cudaStreamDestroy(stream));
|
||||
}
|
||||
if (descrA) {
|
||||
checkCudaErrors(cusparseDestroyMatDescr(descrA));
|
||||
}
|
||||
if (h_info) {
|
||||
checkCudaErrors(cusolverSpDestroyCsrcholInfoHost(h_info));
|
||||
}
|
||||
if (d_info) {
|
||||
checkCudaErrors(cusolverSpDestroyCsrcholInfo(d_info));
|
||||
}
|
||||
if (matA) {
|
||||
checkCudaErrors(cusparseDestroySpMat(matA));
|
||||
}
|
||||
if (vecx) {
|
||||
checkCudaErrors(cusparseDestroyDnVec(vecx));
|
||||
}
|
||||
if (vecAx) {
|
||||
checkCudaErrors(cusparseDestroyDnVec(vecAx));
|
||||
}
|
||||
|
||||
if (h_csrValA ) { free(h_csrValA); }
|
||||
if (h_csrRowPtrA) { free(h_csrRowPtrA); }
|
||||
if (h_csrColIndA) { free(h_csrColIndA); }
|
||||
if (h_csrValA) {
|
||||
free(h_csrValA);
|
||||
}
|
||||
if (h_csrRowPtrA) {
|
||||
free(h_csrRowPtrA);
|
||||
}
|
||||
if (h_csrColIndA) {
|
||||
free(h_csrColIndA);
|
||||
}
|
||||
|
||||
if (h_x ) { free(h_x); }
|
||||
if (h_b ) { free(h_b); }
|
||||
if (h_r ) { free(h_r); }
|
||||
if (h_x) {
|
||||
free(h_x);
|
||||
}
|
||||
if (h_b) {
|
||||
free(h_b);
|
||||
}
|
||||
if (h_r) {
|
||||
free(h_r);
|
||||
}
|
||||
|
||||
if (buffer_cpu) { free(buffer_cpu); }
|
||||
if (buffer_gpu) { checkCudaErrors(cudaFree(buffer_gpu)); }
|
||||
if (buffer_cpu) {
|
||||
free(buffer_cpu);
|
||||
}
|
||||
if (buffer_gpu) {
|
||||
checkCudaErrors(cudaFree(buffer_gpu));
|
||||
}
|
||||
|
||||
if (d_csrValA ) { checkCudaErrors(cudaFree(d_csrValA)); }
|
||||
if (d_csrRowPtrA) { checkCudaErrors(cudaFree(d_csrRowPtrA)); }
|
||||
if (d_csrColIndA) { checkCudaErrors(cudaFree(d_csrColIndA)); }
|
||||
if (d_x) { checkCudaErrors(cudaFree(d_x)); }
|
||||
if (d_b) { checkCudaErrors(cudaFree(d_b)); }
|
||||
if (d_r) { checkCudaErrors(cudaFree(d_r)); }
|
||||
if (d_csrValA) {
|
||||
checkCudaErrors(cudaFree(d_csrValA));
|
||||
}
|
||||
if (d_csrRowPtrA) {
|
||||
checkCudaErrors(cudaFree(d_csrRowPtrA));
|
||||
}
|
||||
if (d_csrColIndA) {
|
||||
checkCudaErrors(cudaFree(d_csrColIndA));
|
||||
}
|
||||
if (d_x) {
|
||||
checkCudaErrors(cudaFree(d_x));
|
||||
}
|
||||
if (d_b) {
|
||||
checkCudaErrors(cudaFree(d_b));
|
||||
}
|
||||
if (d_r) {
|
||||
checkCudaErrors(cudaFree(d_r));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,128 +1,126 @@
|
||||
/*
|
||||
* Matrix Market I/O library for ANSI C
|
||||
*
|
||||
* See http://math.nist.gov/MatrixMarket for details.
|
||||
*
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Matrix Market I/O library for ANSI C
|
||||
*
|
||||
* See http://math.nist.gov/MatrixMarket for details.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/* avoid Windows warnings (for example: strcpy, fscanf, etc.) */
|
||||
#if defined(_WIN32)
|
||||
#if defined(_WIN32)
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "mmio.h"
|
||||
|
||||
int mm_read_unsymmetric_sparse(const char *fname, int *M_, int *N_, int *nz_,
|
||||
double **val_, int **I_, int **J_)
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int mm_read_unsymmetric_sparse(const char *fname, int *M_, int *N_, int *nz_, double **val_, int **I_, int **J_)
|
||||
{
|
||||
FILE *f;
|
||||
FILE *f;
|
||||
MM_typecode matcode;
|
||||
int M, N, nz;
|
||||
int i;
|
||||
double *val;
|
||||
int *I, *J;
|
||||
|
||||
int M, N, nz;
|
||||
int i;
|
||||
double *val;
|
||||
int *I, *J;
|
||||
|
||||
if ((f = fopen(fname, "r")) == NULL)
|
||||
return -1;
|
||||
|
||||
|
||||
if (mm_read_banner(f, &matcode) != 0)
|
||||
{
|
||||
return -1;
|
||||
|
||||
|
||||
if (mm_read_banner(f, &matcode) != 0) {
|
||||
printf("mm_read_unsymetric: Could not process Matrix Market banner ");
|
||||
printf(" in file [%s]\n", fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ( !(mm_is_real(matcode) && mm_is_matrix(matcode) &&
|
||||
mm_is_sparse(matcode)))
|
||||
{
|
||||
|
||||
|
||||
if (!(mm_is_real(matcode) && mm_is_matrix(matcode) && mm_is_sparse(matcode))) {
|
||||
fprintf(stderr, "Sorry, this application does not support ");
|
||||
fprintf(stderr, "Market Market type: [%s]\n",
|
||||
mm_typecode_to_str(matcode));
|
||||
fprintf(stderr, "Market Market type: [%s]\n", mm_typecode_to_str(matcode));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* find out size of sparse matrix: M, N, nz .... */
|
||||
|
||||
if (mm_read_mtx_crd_size(f, &M, &N, &nz) !=0)
|
||||
{
|
||||
|
||||
if (mm_read_mtx_crd_size(f, &M, &N, &nz) != 0) {
|
||||
fprintf(stderr, "read_unsymmetric_sparse(): could not parse matrix size.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*M_ = M;
|
||||
*N_ = N;
|
||||
|
||||
*M_ = M;
|
||||
*N_ = N;
|
||||
*nz_ = nz;
|
||||
|
||||
|
||||
/* reserve memory for matrices */
|
||||
|
||||
I = (int *) malloc(nz * sizeof(int));
|
||||
J = (int *) malloc(nz * sizeof(int));
|
||||
val = (double *) malloc(nz * sizeof(double));
|
||||
|
||||
|
||||
I = (int *)malloc(nz * sizeof(int));
|
||||
J = (int *)malloc(nz * sizeof(int));
|
||||
val = (double *)malloc(nz * sizeof(double));
|
||||
|
||||
*val_ = val;
|
||||
*I_ = I;
|
||||
*J_ = J;
|
||||
|
||||
*I_ = I;
|
||||
*J_ = J;
|
||||
|
||||
/* NOTE: when reading in doubles, ANSI C requires the use of the "l" */
|
||||
/* specifier as in "%lg", "%lf", "%le", otherwise errors will occur */
|
||||
/* (ANSI C X3.159-1989, Sec. 4.9.6.2, p. 136 lines 13-15) */
|
||||
|
||||
for (i=0; i<nz; i++)
|
||||
{
|
||||
|
||||
for (i = 0; i < nz; i++) {
|
||||
if (fscanf(f, "%d %d %lg\n", &I[i], &J[i], &val[i]) != 3) {
|
||||
return -1;
|
||||
}
|
||||
I[i]--; /* adjust from 1-based to 0-based */
|
||||
I[i]--; /* adjust from 1-based to 0-based */
|
||||
J[i]--;
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mm_is_valid(MM_typecode matcode)
|
||||
{
|
||||
if (!mm_is_matrix(matcode)) return 0;
|
||||
if (mm_is_dense(matcode) && mm_is_pattern(matcode)) return 0;
|
||||
if (mm_is_real(matcode) && mm_is_hermitian(matcode)) return 0;
|
||||
if (mm_is_pattern(matcode) && (mm_is_hermitian(matcode) ||
|
||||
mm_is_skew(matcode))) return 0;
|
||||
if (!mm_is_matrix(matcode))
|
||||
return 0;
|
||||
if (mm_is_dense(matcode) && mm_is_pattern(matcode))
|
||||
return 0;
|
||||
if (mm_is_real(matcode) && mm_is_hermitian(matcode))
|
||||
return 0;
|
||||
if (mm_is_pattern(matcode) && (mm_is_hermitian(matcode) || mm_is_skew(matcode)))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mm_read_banner(FILE *f, MM_typecode *matcode)
|
||||
{
|
||||
char line[MM_MAX_LINE_LENGTH];
|
||||
char banner[MM_MAX_TOKEN_LENGTH];
|
||||
char mtx[MM_MAX_TOKEN_LENGTH];
|
||||
char crd[MM_MAX_TOKEN_LENGTH];
|
||||
char data_type[MM_MAX_TOKEN_LENGTH];
|
||||
char storage_scheme[MM_MAX_TOKEN_LENGTH];
|
||||
char line[MM_MAX_LINE_LENGTH];
|
||||
char banner[MM_MAX_TOKEN_LENGTH];
|
||||
char mtx[MM_MAX_TOKEN_LENGTH];
|
||||
char crd[MM_MAX_TOKEN_LENGTH];
|
||||
char data_type[MM_MAX_TOKEN_LENGTH];
|
||||
char storage_scheme[MM_MAX_TOKEN_LENGTH];
|
||||
char *p;
|
||||
|
||||
|
||||
mm_clear_typecode(matcode);
|
||||
mm_clear_typecode(matcode);
|
||||
|
||||
if (fgets(line, MM_MAX_LINE_LENGTH, f) == NULL)
|
||||
if (fgets(line, MM_MAX_LINE_LENGTH, f) == NULL)
|
||||
return MM_PREMATURE_EOF;
|
||||
|
||||
if (sscanf(line, "%s %s %s %s %s", banner, mtx, crd, data_type,
|
||||
storage_scheme) != 5)
|
||||
if (sscanf(line, "%s %s %s %s %s", banner, mtx, crd, data_type, storage_scheme) != 5)
|
||||
return MM_PREMATURE_EOF;
|
||||
|
||||
for (p=mtx; *p!='\0'; *p=tolower(*p),p++); /* convert to lower case */
|
||||
for (p=crd; *p!='\0'; *p=tolower(*p),p++);
|
||||
for (p=data_type; *p!='\0'; *p=tolower(*p),p++);
|
||||
for (p=storage_scheme; *p!='\0'; *p=tolower(*p),p++);
|
||||
for (p = mtx; *p != '\0'; *p = tolower(*p), p++)
|
||||
; /* convert to lower case */
|
||||
for (p = crd; *p != '\0'; *p = tolower(*p), p++)
|
||||
;
|
||||
for (p = data_type; *p != '\0'; *p = tolower(*p), p++)
|
||||
;
|
||||
for (p = storage_scheme; *p != '\0'; *p = tolower(*p), p++)
|
||||
;
|
||||
|
||||
/* check for banner */
|
||||
if (strncmp(banner, MatrixMarketBanner, strlen(MatrixMarketBanner)) != 0)
|
||||
@@ -130,7 +128,7 @@ int mm_read_banner(FILE *f, MM_typecode *matcode)
|
||||
|
||||
/* first field should be "mtx" */
|
||||
if (strcmp(mtx, MM_MTX_STR) != 0)
|
||||
return MM_UNSUPPORTED_TYPE;
|
||||
return MM_UNSUPPORTED_TYPE;
|
||||
mm_set_matrix(matcode);
|
||||
|
||||
|
||||
@@ -140,46 +138,39 @@ int mm_read_banner(FILE *f, MM_typecode *matcode)
|
||||
|
||||
if (strcmp(crd, MM_SPARSE_STR) == 0)
|
||||
mm_set_sparse(matcode);
|
||||
else
|
||||
if (strcmp(crd, MM_DENSE_STR) == 0)
|
||||
mm_set_dense(matcode);
|
||||
else if (strcmp(crd, MM_DENSE_STR) == 0)
|
||||
mm_set_dense(matcode);
|
||||
else
|
||||
return MM_UNSUPPORTED_TYPE;
|
||||
|
||||
|
||||
|
||||
/* third field */
|
||||
|
||||
if (strcmp(data_type, MM_REAL_STR) == 0)
|
||||
mm_set_real(matcode);
|
||||
else
|
||||
if (strcmp(data_type, MM_COMPLEX_STR) == 0)
|
||||
else if (strcmp(data_type, MM_COMPLEX_STR) == 0)
|
||||
mm_set_complex(matcode);
|
||||
else
|
||||
if (strcmp(data_type, MM_PATTERN_STR) == 0)
|
||||
else if (strcmp(data_type, MM_PATTERN_STR) == 0)
|
||||
mm_set_pattern(matcode);
|
||||
else
|
||||
if (strcmp(data_type, MM_INT_STR) == 0)
|
||||
else if (strcmp(data_type, MM_INT_STR) == 0)
|
||||
mm_set_integer(matcode);
|
||||
else
|
||||
return MM_UNSUPPORTED_TYPE;
|
||||
|
||||
|
||||
|
||||
/* fourth field */
|
||||
|
||||
if (strcmp(storage_scheme, MM_GENERAL_STR) == 0)
|
||||
mm_set_general(matcode);
|
||||
else
|
||||
if (strcmp(storage_scheme, MM_SYMM_STR) == 0)
|
||||
else if (strcmp(storage_scheme, MM_SYMM_STR) == 0)
|
||||
mm_set_symmetric(matcode);
|
||||
else
|
||||
if (strcmp(storage_scheme, MM_HERM_STR) == 0)
|
||||
else if (strcmp(storage_scheme, MM_HERM_STR) == 0)
|
||||
mm_set_hermitian(matcode);
|
||||
else
|
||||
if (strcmp(storage_scheme, MM_SKEW_STR) == 0)
|
||||
else if (strcmp(storage_scheme, MM_SKEW_STR) == 0)
|
||||
mm_set_skew(matcode);
|
||||
else
|
||||
return MM_UNSUPPORTED_TYPE;
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -188,36 +179,34 @@ int mm_write_mtx_crd_size(FILE *f, int M, int N, int nz)
|
||||
{
|
||||
if (fprintf(f, "%d %d %d\n", M, N, nz) != 3)
|
||||
return MM_COULD_NOT_WRITE_FILE;
|
||||
else
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mm_read_mtx_crd_size(FILE *f, int *M, int *N, int *nz )
|
||||
int mm_read_mtx_crd_size(FILE *f, int *M, int *N, int *nz)
|
||||
{
|
||||
char line[MM_MAX_LINE_LENGTH];
|
||||
int num_items_read;
|
||||
int num_items_read;
|
||||
|
||||
/* set return null parameter values, in case we exit with errors */
|
||||
*M = *N = *nz = 0;
|
||||
|
||||
/* now continue scanning until you reach the end-of-comments */
|
||||
do
|
||||
{
|
||||
if (fgets(line,MM_MAX_LINE_LENGTH,f) == NULL)
|
||||
do {
|
||||
if (fgets(line, MM_MAX_LINE_LENGTH, f) == NULL)
|
||||
return MM_PREMATURE_EOF;
|
||||
}while (line[0] == '%');
|
||||
} while (line[0] == '%');
|
||||
|
||||
/* line[] is either blank or has M,N, nz */
|
||||
if (sscanf(line, "%d %d %d", M, N, nz) == 3)
|
||||
return 0;
|
||||
|
||||
else
|
||||
do
|
||||
{
|
||||
num_items_read = fscanf(f, "%d %d %d", M, N, nz);
|
||||
if (num_items_read == EOF) return MM_PREMATURE_EOF;
|
||||
}
|
||||
while (num_items_read != 3);
|
||||
do {
|
||||
num_items_read = fscanf(f, "%d %d %d", M, N, nz);
|
||||
if (num_items_read == EOF)
|
||||
return MM_PREMATURE_EOF;
|
||||
} while (num_items_read != 3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -226,28 +215,26 @@ int mm_read_mtx_crd_size(FILE *f, int *M, int *N, int *nz )
|
||||
int mm_read_mtx_array_size(FILE *f, int *M, int *N)
|
||||
{
|
||||
char line[MM_MAX_LINE_LENGTH];
|
||||
int num_items_read;
|
||||
int num_items_read;
|
||||
/* set return null parameter values, in case we exit with errors */
|
||||
*M = *N = 0;
|
||||
|
||||
/* now continue scanning until you reach the end-of-comments */
|
||||
do
|
||||
{
|
||||
if (fgets(line,MM_MAX_LINE_LENGTH,f) == NULL)
|
||||
do {
|
||||
if (fgets(line, MM_MAX_LINE_LENGTH, f) == NULL)
|
||||
return MM_PREMATURE_EOF;
|
||||
}while (line[0] == '%');
|
||||
} while (line[0] == '%');
|
||||
|
||||
/* line[] is either blank or has M,N, nz */
|
||||
if (sscanf(line, "%d %d", M, N) == 2)
|
||||
return 0;
|
||||
|
||||
else /* we have a blank line */
|
||||
do
|
||||
{
|
||||
num_items_read = fscanf(f, "%d %d", M, N);
|
||||
if (num_items_read == EOF) return MM_PREMATURE_EOF;
|
||||
}
|
||||
while (num_items_read != 2);
|
||||
do {
|
||||
num_items_read = fscanf(f, "%d %d", M, N);
|
||||
if (num_items_read == EOF)
|
||||
return MM_PREMATURE_EOF;
|
||||
} while (num_items_read != 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -256,43 +243,36 @@ int mm_write_mtx_array_size(FILE *f, int M, int N)
|
||||
{
|
||||
if (fprintf(f, "%d %d\n", M, N) != 2)
|
||||
return MM_COULD_NOT_WRITE_FILE;
|
||||
else
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/******************************************************************/
|
||||
/* use when I[], J[], and val[]J, and val[] are already allocated */
|
||||
/******************************************************************/
|
||||
|
||||
int mm_read_mtx_crd_data(FILE *f, int M, int N, int nz, int I[], int J[],
|
||||
double val[], MM_typecode matcode)
|
||||
int mm_read_mtx_crd_data(FILE *f, int M, int N, int nz, int I[], int J[], double val[], MM_typecode matcode)
|
||||
{
|
||||
int i;
|
||||
if (mm_is_complex(matcode))
|
||||
{
|
||||
for (i=0; i<nz; i++)
|
||||
if (fscanf(f, "%d %d %lg %lg", &I[i], &J[i], &val[2*i], &val[2*i+1])
|
||||
!= 4) return MM_PREMATURE_EOF;
|
||||
if (mm_is_complex(matcode)) {
|
||||
for (i = 0; i < nz; i++)
|
||||
if (fscanf(f, "%d %d %lg %lg", &I[i], &J[i], &val[2 * i], &val[2 * i + 1]) != 4)
|
||||
return MM_PREMATURE_EOF;
|
||||
}
|
||||
else if (mm_is_real(matcode) || mm_is_integer(matcode))
|
||||
{
|
||||
for (i=0; i<nz; i++)
|
||||
{
|
||||
if (fscanf(f, "%d %d %lg\n", &I[i], &J[i], &val[i])
|
||||
!= 3) return MM_PREMATURE_EOF;
|
||||
|
||||
else if (mm_is_real(matcode) || mm_is_integer(matcode)) {
|
||||
for (i = 0; i < nz; i++) {
|
||||
if (fscanf(f, "%d %d %lg\n", &I[i], &J[i], &val[i]) != 3)
|
||||
return MM_PREMATURE_EOF;
|
||||
}
|
||||
}
|
||||
|
||||
else if (mm_is_pattern(matcode))
|
||||
{
|
||||
for (i=0; i<nz; i++)
|
||||
if (fscanf(f, "%d %d", &I[i], &J[i])
|
||||
!= 2) return MM_PREMATURE_EOF;
|
||||
else if (mm_is_pattern(matcode)) {
|
||||
for (i = 0; i < nz; i++)
|
||||
if (fscanf(f, "%d %d", &I[i], &J[i]) != 2)
|
||||
return MM_PREMATURE_EOF;
|
||||
}
|
||||
else
|
||||
return MM_UNSUPPORTED_TYPE;
|
||||
@@ -300,24 +280,20 @@ int mm_read_mtx_crd_data(FILE *f, int M, int N, int nz, int I[], int J[],
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mm_read_mtx_crd_entry(FILE *f, int *I, int *J,
|
||||
double *real, double *imag, MM_typecode matcode)
|
||||
int mm_read_mtx_crd_entry(FILE *f, int *I, int *J, double *real, double *imag, MM_typecode matcode)
|
||||
{
|
||||
if (mm_is_complex(matcode))
|
||||
{
|
||||
if (fscanf(f, "%d %d %lg %lg", I, J, real, imag)
|
||||
!= 4) return MM_PREMATURE_EOF;
|
||||
if (mm_is_complex(matcode)) {
|
||||
if (fscanf(f, "%d %d %lg %lg", I, J, real, imag) != 4)
|
||||
return MM_PREMATURE_EOF;
|
||||
}
|
||||
else if (mm_is_real(matcode) || mm_is_integer(matcode))
|
||||
{
|
||||
if (fscanf(f, "%d %d %lg\n", I, J, real)
|
||||
!= 3) return MM_PREMATURE_EOF;
|
||||
|
||||
else if (mm_is_real(matcode) || mm_is_integer(matcode)) {
|
||||
if (fscanf(f, "%d %d %lg\n", I, J, real) != 3)
|
||||
return MM_PREMATURE_EOF;
|
||||
}
|
||||
|
||||
else if (mm_is_pattern(matcode))
|
||||
{
|
||||
if (fscanf(f, "%d %d", I, J) != 2) return MM_PREMATURE_EOF;
|
||||
else if (mm_is_pattern(matcode)) {
|
||||
if (fscanf(f, "%d %d", I, J) != 2)
|
||||
return MM_PREMATURE_EOF;
|
||||
}
|
||||
else
|
||||
return MM_UNSUPPORTED_TYPE;
|
||||
@@ -334,82 +310,76 @@ int mm_read_mtx_crd_entry(FILE *f, int *I, int *J,
|
||||
(nz pairs of real/imaginary values)
|
||||
************************************************************************/
|
||||
|
||||
int mm_read_mtx_crd(char *fname, int *M, int *N, int *nz, int **I, int **J,
|
||||
double **val, MM_typecode *matcode)
|
||||
int mm_read_mtx_crd(char *fname, int *M, int *N, int *nz, int **I, int **J, double **val, MM_typecode *matcode)
|
||||
{
|
||||
int ret_code;
|
||||
int ret_code;
|
||||
FILE *f;
|
||||
|
||||
if (strcmp(fname, "stdin") == 0) f=stdin;
|
||||
else
|
||||
if ((f = fopen(fname, "r")) == NULL)
|
||||
if (strcmp(fname, "stdin") == 0)
|
||||
f = stdin;
|
||||
else if ((f = fopen(fname, "r")) == NULL)
|
||||
return MM_COULD_NOT_READ_FILE;
|
||||
|
||||
|
||||
if ((ret_code = mm_read_banner(f, matcode)) != 0)
|
||||
return ret_code;
|
||||
|
||||
if (!(mm_is_valid(*matcode) && mm_is_sparse(*matcode) &&
|
||||
mm_is_matrix(*matcode)))
|
||||
if (!(mm_is_valid(*matcode) && mm_is_sparse(*matcode) && mm_is_matrix(*matcode)))
|
||||
return MM_UNSUPPORTED_TYPE;
|
||||
|
||||
if ((ret_code = mm_read_mtx_crd_size(f, M, N, nz)) != 0)
|
||||
return ret_code;
|
||||
|
||||
|
||||
*I = (int *) malloc(*nz * sizeof(int));
|
||||
*J = (int *) malloc(*nz * sizeof(int));
|
||||
*I = (int *)malloc(*nz * sizeof(int));
|
||||
*J = (int *)malloc(*nz * sizeof(int));
|
||||
*val = NULL;
|
||||
|
||||
if (mm_is_complex(*matcode))
|
||||
{
|
||||
*val = (double *) malloc(*nz * 2 * sizeof(double));
|
||||
ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val,
|
||||
*matcode);
|
||||
if (ret_code != 0) return ret_code;
|
||||
if (mm_is_complex(*matcode)) {
|
||||
*val = (double *)malloc(*nz * 2 * sizeof(double));
|
||||
ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val, *matcode);
|
||||
if (ret_code != 0)
|
||||
return ret_code;
|
||||
}
|
||||
else if (mm_is_real(*matcode) || mm_is_integer(*matcode))
|
||||
{
|
||||
*val = (double *) malloc(*nz * sizeof(double));
|
||||
ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val,
|
||||
*matcode);
|
||||
if (ret_code != 0) return ret_code;
|
||||
else if (mm_is_real(*matcode) || mm_is_integer(*matcode)) {
|
||||
*val = (double *)malloc(*nz * sizeof(double));
|
||||
ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val, *matcode);
|
||||
if (ret_code != 0)
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
else if (mm_is_pattern(*matcode))
|
||||
{
|
||||
ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val,
|
||||
*matcode);
|
||||
if (ret_code != 0) return ret_code;
|
||||
else if (mm_is_pattern(*matcode)) {
|
||||
ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val, *matcode);
|
||||
if (ret_code != 0)
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
if (f != stdin) fclose(f);
|
||||
if (f != stdin)
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mm_write_banner(FILE *f, MM_typecode matcode)
|
||||
{
|
||||
char *str = mm_typecode_to_str(matcode);
|
||||
int ret_code;
|
||||
int ret_code;
|
||||
|
||||
ret_code = fprintf(f, "%s %s\n", MatrixMarketBanner, str);
|
||||
free(str);
|
||||
if (ret_code !=2 )
|
||||
if (ret_code != 2)
|
||||
return MM_COULD_NOT_WRITE_FILE;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mm_write_mtx_crd(char fname[], int M, int N, int nz, int I[], int J[],
|
||||
double val[], MM_typecode matcode)
|
||||
int mm_write_mtx_crd(char fname[], int M, int N, int nz, int I[], int J[], double val[], MM_typecode matcode)
|
||||
{
|
||||
FILE *f;
|
||||
int i;
|
||||
int i;
|
||||
|
||||
if (strcmp(fname, "stdout") == 0)
|
||||
f = stdout;
|
||||
else
|
||||
if ((f = fopen(fname, "w")) == NULL)
|
||||
else if ((f = fopen(fname, "w")) == NULL)
|
||||
return MM_COULD_NOT_WRITE_FILE;
|
||||
|
||||
/* print banner followed by typecode */
|
||||
@@ -421,50 +391,47 @@ int mm_write_mtx_crd(char fname[], int M, int N, int nz, int I[], int J[],
|
||||
|
||||
/* print values */
|
||||
if (mm_is_pattern(matcode))
|
||||
for (i=0; i<nz; i++)
|
||||
for (i = 0; i < nz; i++)
|
||||
fprintf(f, "%d %d\n", I[i], J[i]);
|
||||
else
|
||||
if (mm_is_integer(matcode))
|
||||
for (i=0; i<nz; i++)
|
||||
else if (mm_is_integer(matcode))
|
||||
for (i = 0; i < nz; i++)
|
||||
fprintf(f, "%d %d %d\n", I[i], J[i], (int)val[i]);
|
||||
else
|
||||
if (mm_is_real(matcode))
|
||||
for (i=0; i<nz; i++)
|
||||
else if (mm_is_real(matcode))
|
||||
for (i = 0; i < nz; i++)
|
||||
fprintf(f, "%d %d %20.16g\n", I[i], J[i], val[i]);
|
||||
else
|
||||
if (mm_is_complex(matcode))
|
||||
for (i=0; i<nz; i++)
|
||||
fprintf(f, "%d %d %20.16g %20.16g\n", I[i], J[i], val[2*i],
|
||||
val[2*i+1]);
|
||||
else
|
||||
{
|
||||
if (f != stdout) fclose(f);
|
||||
else if (mm_is_complex(matcode))
|
||||
for (i = 0; i < nz; i++)
|
||||
fprintf(f, "%d %d %20.16g %20.16g\n", I[i], J[i], val[2 * i], val[2 * i + 1]);
|
||||
else {
|
||||
if (f != stdout)
|
||||
fclose(f);
|
||||
return MM_UNSUPPORTED_TYPE;
|
||||
}
|
||||
|
||||
if (f !=stdout) fclose(f);
|
||||
if (f != stdout)
|
||||
fclose(f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new copy of a string s. mm_strdup() is a common routine, but
|
||||
* not part of ANSI C, so it is included here. Used by mm_typecode_to_str().
|
||||
*
|
||||
*/
|
||||
* Create a new copy of a string s. mm_strdup() is a common routine, but
|
||||
* not part of ANSI C, so it is included here. Used by mm_typecode_to_str().
|
||||
*
|
||||
*/
|
||||
static char *mm_strdup(const char *s)
|
||||
{
|
||||
size_t len = strlen(s);
|
||||
char *s2 = (char *) malloc((len+1)*sizeof(char));
|
||||
char *s2 = (char *)malloc((len + 1) * sizeof(char));
|
||||
return strcpy(s2, s);
|
||||
}
|
||||
|
||||
char *mm_typecode_to_str(MM_typecode matcode)
|
||||
char *mm_typecode_to_str(MM_typecode matcode)
|
||||
{
|
||||
char buffer[MM_MAX_LINE_LENGTH];
|
||||
char buffer[MM_MAX_LINE_LENGTH];
|
||||
char *types[4];
|
||||
//char *mm_strdup(const char *);
|
||||
//int error =0;
|
||||
// char *mm_strdup(const char *);
|
||||
// int error =0;
|
||||
|
||||
/* check for MTX type */
|
||||
if (mm_is_matrix(matcode))
|
||||
@@ -475,8 +442,7 @@ char *mm_typecode_to_str(MM_typecode matcode)
|
||||
/* check for CRD or ARR matrix */
|
||||
if (mm_is_sparse(matcode))
|
||||
types[1] = MM_SPARSE_STR;
|
||||
else
|
||||
if (mm_is_dense(matcode))
|
||||
else if (mm_is_dense(matcode))
|
||||
types[1] = MM_DENSE_STR;
|
||||
else
|
||||
return NULL;
|
||||
@@ -484,14 +450,11 @@ char *mm_typecode_to_str(MM_typecode matcode)
|
||||
/* check for element data type */
|
||||
if (mm_is_real(matcode))
|
||||
types[2] = MM_REAL_STR;
|
||||
else
|
||||
if (mm_is_complex(matcode))
|
||||
else if (mm_is_complex(matcode))
|
||||
types[2] = MM_COMPLEX_STR;
|
||||
else
|
||||
if (mm_is_pattern(matcode))
|
||||
else if (mm_is_pattern(matcode))
|
||||
types[2] = MM_PATTERN_STR;
|
||||
else
|
||||
if (mm_is_integer(matcode))
|
||||
else if (mm_is_integer(matcode))
|
||||
types[2] = MM_INT_STR;
|
||||
else
|
||||
return NULL;
|
||||
@@ -500,18 +463,15 @@ char *mm_typecode_to_str(MM_typecode matcode)
|
||||
/* check for symmetry type */
|
||||
if (mm_is_general(matcode))
|
||||
types[3] = MM_GENERAL_STR;
|
||||
else
|
||||
if (mm_is_symmetric(matcode))
|
||||
else if (mm_is_symmetric(matcode))
|
||||
types[3] = MM_SYMM_STR;
|
||||
else
|
||||
if (mm_is_hermitian(matcode))
|
||||
else if (mm_is_hermitian(matcode))
|
||||
types[3] = MM_HERM_STR;
|
||||
else
|
||||
if (mm_is_skew(matcode))
|
||||
else if (mm_is_skew(matcode))
|
||||
types[3] = MM_SKEW_STR;
|
||||
else
|
||||
return NULL;
|
||||
|
||||
sprintf(buffer,"%s %s %s %s", types[0], types[1], types[2], types[3]);
|
||||
sprintf(buffer, "%s %s %s %s", types[0], types[1], types[2], types[3]);
|
||||
return mm_strdup(buffer);
|
||||
}
|
||||
|
||||
@@ -1,141 +1,138 @@
|
||||
/*
|
||||
* Matrix Market I/O library for ANSI C
|
||||
*
|
||||
* See http://math.nist.gov/MatrixMarket for details.
|
||||
*
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Matrix Market I/O library for ANSI C
|
||||
*
|
||||
* See http://math.nist.gov/MatrixMarket for details.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM_IO_H
|
||||
#define MM_IO_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
extern "C"
|
||||
{
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#define MM_MAX_LINE_LENGTH 1025
|
||||
#define MatrixMarketBanner "%%MatrixMarket"
|
||||
#define MM_MAX_LINE_LENGTH 1025
|
||||
#define MatrixMarketBanner "%%MatrixMarket"
|
||||
#define MM_MAX_TOKEN_LENGTH 64
|
||||
|
||||
typedef char MM_typecode[4];
|
||||
typedef char MM_typecode[4];
|
||||
|
||||
char *mm_typecode_to_str(MM_typecode matcode);
|
||||
char *mm_typecode_to_str(MM_typecode matcode);
|
||||
|
||||
int mm_read_banner(FILE *f, MM_typecode *matcode);
|
||||
int mm_read_mtx_crd_size(FILE *f, int *M, int *N, int *nz);
|
||||
int mm_read_mtx_array_size(FILE *f, int *M, int *N);
|
||||
int mm_read_banner(FILE *f, MM_typecode *matcode);
|
||||
int mm_read_mtx_crd_size(FILE *f, int *M, int *N, int *nz);
|
||||
int mm_read_mtx_array_size(FILE *f, int *M, int *N);
|
||||
|
||||
int mm_write_banner(FILE *f, MM_typecode matcode);
|
||||
int mm_write_mtx_crd_size(FILE *f, int M, int N, int nz);
|
||||
int mm_write_mtx_array_size(FILE *f, int M, int N);
|
||||
int mm_write_banner(FILE *f, MM_typecode matcode);
|
||||
int mm_write_mtx_crd_size(FILE *f, int M, int N, int nz);
|
||||
int mm_write_mtx_array_size(FILE *f, int M, int N);
|
||||
|
||||
|
||||
/********************* MM_typecode query fucntions ***************************/
|
||||
/********************* MM_typecode query fucntions ***************************/
|
||||
|
||||
#define mm_is_matrix(typecode) ((typecode)[0]=='M')
|
||||
#define mm_is_matrix(typecode) ((typecode)[0] == 'M')
|
||||
|
||||
#define mm_is_sparse(typecode) ((typecode)[1]=='C')
|
||||
#define mm_is_coordinate(typecode)((typecode)[1]=='C')
|
||||
#define mm_is_dense(typecode) ((typecode)[1]=='A')
|
||||
#define mm_is_array(typecode) ((typecode)[1]=='A')
|
||||
#define mm_is_sparse(typecode) ((typecode)[1] == 'C')
|
||||
#define mm_is_coordinate(typecode) ((typecode)[1] == 'C')
|
||||
#define mm_is_dense(typecode) ((typecode)[1] == 'A')
|
||||
#define mm_is_array(typecode) ((typecode)[1] == 'A')
|
||||
|
||||
#define mm_is_complex(typecode) ((typecode)[2]=='C')
|
||||
#define mm_is_real(typecode) ((typecode)[2]=='R')
|
||||
#define mm_is_pattern(typecode) ((typecode)[2]=='P')
|
||||
#define mm_is_integer(typecode) ((typecode)[2]=='I')
|
||||
#define mm_is_complex(typecode) ((typecode)[2] == 'C')
|
||||
#define mm_is_real(typecode) ((typecode)[2] == 'R')
|
||||
#define mm_is_pattern(typecode) ((typecode)[2] == 'P')
|
||||
#define mm_is_integer(typecode) ((typecode)[2] == 'I')
|
||||
|
||||
#define mm_is_symmetric(typecode)((typecode)[3]=='S')
|
||||
#define mm_is_general(typecode) ((typecode)[3]=='G')
|
||||
#define mm_is_skew(typecode) ((typecode)[3]=='K')
|
||||
#define mm_is_hermitian(typecode)((typecode)[3]=='H')
|
||||
#define mm_is_symmetric(typecode) ((typecode)[3] == 'S')
|
||||
#define mm_is_general(typecode) ((typecode)[3] == 'G')
|
||||
#define mm_is_skew(typecode) ((typecode)[3] == 'K')
|
||||
#define mm_is_hermitian(typecode) ((typecode)[3] == 'H')
|
||||
|
||||
int mm_is_valid(MM_typecode matcode); /* too complex for a macro */
|
||||
int mm_is_valid(MM_typecode matcode); /* too complex for a macro */
|
||||
|
||||
|
||||
/********************* MM_typecode modify fucntions ***************************/
|
||||
/********************* MM_typecode modify fucntions ***************************/
|
||||
|
||||
#define mm_set_matrix(typecode) ((*typecode)[0]='M')
|
||||
#define mm_set_coordinate(typecode) ((*typecode)[1]='C')
|
||||
#define mm_set_array(typecode) ((*typecode)[1]='A')
|
||||
#define mm_set_dense(typecode) mm_set_array(typecode)
|
||||
#define mm_set_sparse(typecode) mm_set_coordinate(typecode)
|
||||
#define mm_set_matrix(typecode) ((*typecode)[0] = 'M')
|
||||
#define mm_set_coordinate(typecode) ((*typecode)[1] = 'C')
|
||||
#define mm_set_array(typecode) ((*typecode)[1] = 'A')
|
||||
#define mm_set_dense(typecode) mm_set_array(typecode)
|
||||
#define mm_set_sparse(typecode) mm_set_coordinate(typecode)
|
||||
|
||||
#define mm_set_complex(typecode)((*typecode)[2]='C')
|
||||
#define mm_set_real(typecode) ((*typecode)[2]='R')
|
||||
#define mm_set_pattern(typecode)((*typecode)[2]='P')
|
||||
#define mm_set_integer(typecode)((*typecode)[2]='I')
|
||||
#define mm_set_complex(typecode) ((*typecode)[2] = 'C')
|
||||
#define mm_set_real(typecode) ((*typecode)[2] = 'R')
|
||||
#define mm_set_pattern(typecode) ((*typecode)[2] = 'P')
|
||||
#define mm_set_integer(typecode) ((*typecode)[2] = 'I')
|
||||
|
||||
|
||||
#define mm_set_symmetric(typecode)((*typecode)[3]='S')
|
||||
#define mm_set_general(typecode)((*typecode)[3]='G')
|
||||
#define mm_set_skew(typecode) ((*typecode)[3]='K')
|
||||
#define mm_set_hermitian(typecode)((*typecode)[3]='H')
|
||||
#define mm_set_symmetric(typecode) ((*typecode)[3] = 'S')
|
||||
#define mm_set_general(typecode) ((*typecode)[3] = 'G')
|
||||
#define mm_set_skew(typecode) ((*typecode)[3] = 'K')
|
||||
#define mm_set_hermitian(typecode) ((*typecode)[3] = 'H')
|
||||
|
||||
#define mm_clear_typecode(typecode) ((*typecode)[0]=(*typecode)[1]= \
|
||||
(*typecode)[2]=' ',(*typecode)[3]='G')
|
||||
#define mm_clear_typecode(typecode) ((*typecode)[0] = (*typecode)[1] = (*typecode)[2] = ' ', (*typecode)[3] = 'G')
|
||||
|
||||
#define mm_initialize_typecode(typecode) mm_clear_typecode(typecode)
|
||||
|
||||
|
||||
/********************* Matrix Market error codes ***************************/
|
||||
/********************* Matrix Market error codes ***************************/
|
||||
|
||||
|
||||
#define MM_COULD_NOT_READ_FILE 11
|
||||
#define MM_PREMATURE_EOF 12
|
||||
#define MM_NOT_MTX 13
|
||||
#define MM_NO_HEADER 14
|
||||
#define MM_UNSUPPORTED_TYPE 15
|
||||
#define MM_LINE_TOO_LONG 16
|
||||
#define MM_COULD_NOT_WRITE_FILE 17
|
||||
#define MM_COULD_NOT_READ_FILE 11
|
||||
#define MM_PREMATURE_EOF 12
|
||||
#define MM_NOT_MTX 13
|
||||
#define MM_NO_HEADER 14
|
||||
#define MM_UNSUPPORTED_TYPE 15
|
||||
#define MM_LINE_TOO_LONG 16
|
||||
#define MM_COULD_NOT_WRITE_FILE 17
|
||||
|
||||
|
||||
/******************** Matrix Market internal definitions ********************
|
||||
/******************** Matrix Market internal definitions ********************
|
||||
|
||||
MM_matrix_typecode: 4-character sequence
|
||||
MM_matrix_typecode: 4-character sequence
|
||||
|
||||
ojbect sparse/ data storage
|
||||
dense type scheme
|
||||
ojbect sparse/ data storage
|
||||
dense type scheme
|
||||
|
||||
string position: [0] [1] [2] [3]
|
||||
string position: [0] [1] [2] [3]
|
||||
|
||||
Matrix typecode: M(atrix) C(oord) R(eal) G(eneral)
|
||||
A(array) C(omplex) H(ermitian)
|
||||
P(attern) S(ymmetric)
|
||||
I(nteger) K(kew)
|
||||
Matrix typecode: M(atrix) C(oord) R(eal) G(eneral)
|
||||
A(array) C(omplex) H(ermitian)
|
||||
P(attern) S(ymmetric)
|
||||
I(nteger) K(kew)
|
||||
|
||||
***********************************************************************/
|
||||
***********************************************************************/
|
||||
|
||||
#define MM_MTX_STR "matrix"
|
||||
#define MM_ARRAY_STR "array"
|
||||
#define MM_DENSE_STR "array"
|
||||
#define MM_COORDINATE_STR "coordinate"
|
||||
#define MM_SPARSE_STR "coordinate"
|
||||
#define MM_COMPLEX_STR "complex"
|
||||
#define MM_REAL_STR "real"
|
||||
#define MM_INT_STR "integer"
|
||||
#define MM_GENERAL_STR "general"
|
||||
#define MM_SYMM_STR "symmetric"
|
||||
#define MM_HERM_STR "hermitian"
|
||||
#define MM_SKEW_STR "skew-symmetric"
|
||||
#define MM_PATTERN_STR "pattern"
|
||||
#define MM_MTX_STR "matrix"
|
||||
#define MM_ARRAY_STR "array"
|
||||
#define MM_DENSE_STR "array"
|
||||
#define MM_COORDINATE_STR "coordinate"
|
||||
#define MM_SPARSE_STR "coordinate"
|
||||
#define MM_COMPLEX_STR "complex"
|
||||
#define MM_REAL_STR "real"
|
||||
#define MM_INT_STR "integer"
|
||||
#define MM_GENERAL_STR "general"
|
||||
#define MM_SYMM_STR "symmetric"
|
||||
#define MM_HERM_STR "hermitian"
|
||||
#define MM_SKEW_STR "skew-symmetric"
|
||||
#define MM_PATTERN_STR "pattern"
|
||||
|
||||
|
||||
/* high level routines */
|
||||
int mm_read_mtx_crd(char *fname, int *M, int *N, int *nz, int **I, int **J,
|
||||
double **val, MM_typecode *matcode);
|
||||
/* high level routines */
|
||||
int mm_read_mtx_crd(char *fname, int *M, int *N, int *nz, int **I, int **J, double **val, MM_typecode *matcode);
|
||||
|
||||
int mm_write_mtx_crd(char fname[], int M, int N, int nz, int I[], int J[],
|
||||
double val[], MM_typecode matcode);
|
||||
int mm_read_mtx_crd_data(FILE *f, int M, int N, int nz, int I[], int J[],
|
||||
double val[], MM_typecode matcode);
|
||||
int mm_read_mtx_crd_entry(FILE *f, int *I, int *J, double *real, double *img,
|
||||
MM_typecode matcode);
|
||||
int mm_write_mtx_crd(char fname[], int M, int N, int nz, int I[], int J[], double val[], MM_typecode matcode);
|
||||
int mm_read_mtx_crd_data(FILE *f, int M, int N, int nz, int I[], int J[], double val[], MM_typecode matcode);
|
||||
int mm_read_mtx_crd_entry(FILE *f, int *I, int *J, double *real, double *img, MM_typecode matcode);
|
||||
|
||||
int mm_read_unsymmetric_sparse(const char *fname, int *M_, int *N_, int *nz_,
|
||||
double **val_, int **I_, int **J_);
|
||||
int mm_read_unsymmetric_sparse(const char *fname, int *M_, int *N_, int *nz_, double **val_, int **I_, int **J_);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,427 +1,375 @@
|
||||
|
||||
#include <cusolverDn.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "mmio.h"
|
||||
|
||||
#include <cusolverDn.h>
|
||||
|
||||
/* avoid Windows warnings (for example: strcpy, fscanf, etc.) */
|
||||
#if defined(_WIN32)
|
||||
#if defined(_WIN32)
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
/* various __inline__ __device__ function to initialize a T_ELEM */
|
||||
template <typename T_ELEM> __inline__ T_ELEM cuGet (int );
|
||||
template <> __inline__ float cuGet<float >(int x)
|
||||
{
|
||||
return float(x);
|
||||
}
|
||||
template <typename T_ELEM> __inline__ T_ELEM cuGet(int);
|
||||
template <> __inline__ float cuGet<float>(int x) { return float(x); }
|
||||
|
||||
template <> __inline__ double cuGet<double>(int x)
|
||||
{
|
||||
return double(x);
|
||||
}
|
||||
template <> __inline__ double cuGet<double>(int x) { return double(x); }
|
||||
|
||||
template <> __inline__ cuComplex cuGet<cuComplex>(int x)
|
||||
{
|
||||
return (make_cuComplex( float(x), 0.0f ));
|
||||
}
|
||||
template <> __inline__ cuComplex cuGet<cuComplex>(int x) { return (make_cuComplex(float(x), 0.0f)); }
|
||||
|
||||
template <> __inline__ cuDoubleComplex cuGet<cuDoubleComplex>(int x)
|
||||
template <> __inline__ cuDoubleComplex cuGet<cuDoubleComplex>(int x) { return (make_cuDoubleComplex(double(x), 0.0)); }
|
||||
|
||||
|
||||
template <typename T_ELEM> __inline__ T_ELEM cuGet(int, int);
|
||||
template <> __inline__ float cuGet<float>(int x, int y) { return float(x); }
|
||||
|
||||
template <> __inline__ double cuGet<double>(int x, int y) { return double(x); }
|
||||
|
||||
template <> __inline__ cuComplex cuGet<cuComplex>(int x, int y) { return make_cuComplex(float(x), float(y)); }
|
||||
|
||||
template <> __inline__ cuDoubleComplex cuGet<cuDoubleComplex>(int x, int y)
|
||||
{
|
||||
return (make_cuDoubleComplex( double(x), 0.0 ));
|
||||
return (make_cuDoubleComplex(double(x), double(y)));
|
||||
}
|
||||
|
||||
|
||||
template <typename T_ELEM> __inline__ T_ELEM cuGet (int , int );
|
||||
template <> __inline__ float cuGet<float >(int x, int y)
|
||||
{
|
||||
return float(x);
|
||||
}
|
||||
template <typename T_ELEM> __inline__ T_ELEM cuGet(float);
|
||||
template <> __inline__ float cuGet<float>(float x) { return float(x); }
|
||||
|
||||
template <> __inline__ double cuGet<double>(int x, int y)
|
||||
{
|
||||
return double(x);
|
||||
}
|
||||
template <> __inline__ double cuGet<double>(float x) { return double(x); }
|
||||
|
||||
template <> __inline__ cuComplex cuGet<cuComplex>(int x, int y)
|
||||
{
|
||||
return make_cuComplex( float(x), float(y) );
|
||||
}
|
||||
template <> __inline__ cuComplex cuGet<cuComplex>(float x) { return (make_cuComplex(float(x), 0.0f)); }
|
||||
|
||||
template <> __inline__ cuDoubleComplex cuGet<cuDoubleComplex>(int x, int y)
|
||||
template <> __inline__ cuDoubleComplex cuGet<cuDoubleComplex>(float x)
|
||||
{
|
||||
return (make_cuDoubleComplex( double(x), double(y) ));
|
||||
return (make_cuDoubleComplex(double(x), 0.0));
|
||||
}
|
||||
|
||||
|
||||
template <typename T_ELEM> __inline__ T_ELEM cuGet (float );
|
||||
template <> __inline__ float cuGet<float >(float x)
|
||||
{
|
||||
return float(x);
|
||||
}
|
||||
template <typename T_ELEM> __inline__ T_ELEM cuGet(float, float);
|
||||
template <> __inline__ float cuGet<float>(float x, float y) { return float(x); }
|
||||
|
||||
template <> __inline__ double cuGet<double>(float x)
|
||||
{
|
||||
return double(x);
|
||||
}
|
||||
template <> __inline__ double cuGet<double>(float x, float y) { return double(x); }
|
||||
|
||||
template <> __inline__ cuComplex cuGet<cuComplex>(float x)
|
||||
{
|
||||
return (make_cuComplex( float(x), 0.0f ));
|
||||
}
|
||||
template <> __inline__ cuComplex cuGet<cuComplex>(float x, float y) { return (make_cuComplex(float(x), float(y))); }
|
||||
|
||||
template <> __inline__ cuDoubleComplex cuGet<cuDoubleComplex>(float x)
|
||||
template <> __inline__ cuDoubleComplex cuGet<cuDoubleComplex>(float x, float y)
|
||||
{
|
||||
return (make_cuDoubleComplex( double(x), 0.0 ));
|
||||
return (make_cuDoubleComplex(double(x), double(y)));
|
||||
}
|
||||
|
||||
|
||||
template <typename T_ELEM> __inline__ T_ELEM cuGet (float, float );
|
||||
template <> __inline__ float cuGet<float >(float x, float y)
|
||||
{
|
||||
return float(x);
|
||||
}
|
||||
template <typename T_ELEM> __inline__ T_ELEM cuGet(double);
|
||||
template <> __inline__ float cuGet<float>(double x) { return float(x); }
|
||||
|
||||
template <> __inline__ double cuGet<double>(float x, float y)
|
||||
{
|
||||
return double(x);
|
||||
}
|
||||
template <> __inline__ double cuGet<double>(double x) { return double(x); }
|
||||
|
||||
template <> __inline__ cuComplex cuGet<cuComplex>(float x, float y)
|
||||
{
|
||||
return (make_cuComplex( float(x), float(y) ));
|
||||
}
|
||||
template <> __inline__ cuComplex cuGet<cuComplex>(double x) { return (make_cuComplex(float(x), 0.0f)); }
|
||||
|
||||
template <> __inline__ cuDoubleComplex cuGet<cuDoubleComplex>(float x, float y)
|
||||
template <> __inline__ cuDoubleComplex cuGet<cuDoubleComplex>(double x)
|
||||
{
|
||||
return (make_cuDoubleComplex( double(x), double(y) ));
|
||||
return (make_cuDoubleComplex(double(x), 0.0));
|
||||
}
|
||||
|
||||
|
||||
template <typename T_ELEM> __inline__ T_ELEM cuGet (double );
|
||||
template <> __inline__ float cuGet<float >(double x)
|
||||
{
|
||||
return float(x);
|
||||
}
|
||||
template <typename T_ELEM> __inline__ T_ELEM cuGet(double, double);
|
||||
template <> __inline__ float cuGet<float>(double x, double y) { return float(x); }
|
||||
|
||||
template <> __inline__ double cuGet<double>(double x)
|
||||
{
|
||||
return double(x);
|
||||
}
|
||||
template <> __inline__ double cuGet<double>(double x, double y) { return double(x); }
|
||||
|
||||
template <> __inline__ cuComplex cuGet<cuComplex>(double x)
|
||||
{
|
||||
return (make_cuComplex( float(x), 0.0f ));
|
||||
}
|
||||
template <> __inline__ cuComplex cuGet<cuComplex>(double x, double y) { return (make_cuComplex(float(x), float(y))); }
|
||||
|
||||
template <> __inline__ cuDoubleComplex cuGet<cuDoubleComplex>(double x)
|
||||
template <> __inline__ cuDoubleComplex cuGet<cuDoubleComplex>(double x, double y)
|
||||
{
|
||||
return (make_cuDoubleComplex( double(x), 0.0 ));
|
||||
return (make_cuDoubleComplex(double(x), double(y)));
|
||||
}
|
||||
|
||||
|
||||
template <typename T_ELEM> __inline__ T_ELEM cuGet (double, double );
|
||||
template <> __inline__ float cuGet<float >(double x, double y)
|
||||
{
|
||||
return float(x);
|
||||
}
|
||||
|
||||
template <> __inline__ double cuGet<double>(double x, double y)
|
||||
{
|
||||
return double(x);
|
||||
}
|
||||
|
||||
template <> __inline__ cuComplex cuGet<cuComplex>(double x, double y)
|
||||
{
|
||||
return (make_cuComplex( float(x), float(y) ));
|
||||
}
|
||||
|
||||
template <> __inline__ cuDoubleComplex cuGet<cuDoubleComplex>(double x, double y)
|
||||
{
|
||||
return (make_cuDoubleComplex( double(x), double(y) ));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void compress_index(
|
||||
const int *Ind,
|
||||
int nnz,
|
||||
int m,
|
||||
int *Ptr,
|
||||
int base)
|
||||
static void compress_index(const int *Ind, int nnz, int m, int *Ptr, int base)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* initialize everything to zero */
|
||||
for(i=0; i<m+1; i++){
|
||||
Ptr[i]=0;
|
||||
}
|
||||
for (i = 0; i < m + 1; i++) {
|
||||
Ptr[i] = 0;
|
||||
}
|
||||
/* count elements in every row */
|
||||
Ptr[0]=base;
|
||||
for(i=0; i<nnz; i++){
|
||||
Ptr[Ind[i]+(1-base)]++;
|
||||
}
|
||||
Ptr[0] = base;
|
||||
for (i = 0; i < nnz; i++) {
|
||||
Ptr[Ind[i] + (1 - base)]++;
|
||||
}
|
||||
/* add all the values */
|
||||
for(i=0; i<m; i++){
|
||||
Ptr[i+1]+=Ptr[i];
|
||||
}
|
||||
for (i = 0; i < m; i++) {
|
||||
Ptr[i + 1] += Ptr[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct cooFormat {
|
||||
int i ;
|
||||
int j ;
|
||||
int p ; // permutation
|
||||
struct cooFormat
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int p; // permutation
|
||||
};
|
||||
|
||||
|
||||
int cmp_cooFormat_csr( struct cooFormat *s, struct cooFormat *t)
|
||||
int cmp_cooFormat_csr(struct cooFormat *s, struct cooFormat *t)
|
||||
{
|
||||
if ( s->i < t->i ){
|
||||
return -1 ;
|
||||
if (s->i < t->i) {
|
||||
return -1;
|
||||
}
|
||||
else if ( s->i > t->i ){
|
||||
return 1 ;
|
||||
else if (s->i > t->i) {
|
||||
return 1;
|
||||
}
|
||||
else{
|
||||
return s->j - t->j ;
|
||||
else {
|
||||
return s->j - t->j;
|
||||
}
|
||||
}
|
||||
|
||||
int cmp_cooFormat_csc( struct cooFormat *s, struct cooFormat *t)
|
||||
int cmp_cooFormat_csc(struct cooFormat *s, struct cooFormat *t)
|
||||
{
|
||||
if ( s->j < t->j ){
|
||||
return -1 ;
|
||||
if (s->j < t->j) {
|
||||
return -1;
|
||||
}
|
||||
else if ( s->j > t->j ){
|
||||
return 1 ;
|
||||
else if (s->j > t->j) {
|
||||
return 1;
|
||||
}
|
||||
else{
|
||||
return s->i - t->i ;
|
||||
else {
|
||||
return s->i - t->i;
|
||||
}
|
||||
}
|
||||
|
||||
typedef int (*FUNPTR) (const void*, const void*) ;
|
||||
typedef int (*FUNPTR2) ( struct cooFormat *s, struct cooFormat *t) ;
|
||||
typedef int (*FUNPTR)(const void *, const void *);
|
||||
typedef int (*FUNPTR2)(struct cooFormat *s, struct cooFormat *t);
|
||||
|
||||
static FUNPTR2 fptr_array[2] = {
|
||||
static FUNPTR2 fptr_array[2] = {
|
||||
cmp_cooFormat_csr,
|
||||
cmp_cooFormat_csc,
|
||||
};
|
||||
|
||||
|
||||
static int verify_pattern(
|
||||
int m,
|
||||
int nnz,
|
||||
int *csrRowPtr,
|
||||
int *csrColInd)
|
||||
static int verify_pattern(int m, int nnz, int *csrRowPtr, int *csrColInd)
|
||||
{
|
||||
int i, col, start, end, base_index;
|
||||
int error_found = 0;
|
||||
|
||||
if (nnz != (csrRowPtr[m] - csrRowPtr[0])){
|
||||
fprintf(stderr, "Error (nnz check failed): (csrRowPtr[%d]=%d - csrRowPtr[%d]=%d) != (nnz=%d)\n", 0, csrRowPtr[0], m, csrRowPtr[m], nnz);
|
||||
if (nnz != (csrRowPtr[m] - csrRowPtr[0])) {
|
||||
fprintf(stderr,
|
||||
"Error (nnz check failed): (csrRowPtr[%d]=%d - csrRowPtr[%d]=%d) != (nnz=%d)\n",
|
||||
0,
|
||||
csrRowPtr[0],
|
||||
m,
|
||||
csrRowPtr[m],
|
||||
nnz);
|
||||
error_found = 1;
|
||||
}
|
||||
|
||||
base_index = csrRowPtr[0];
|
||||
if ((0 != base_index) && (1 != base_index)){
|
||||
if ((0 != base_index) && (1 != base_index)) {
|
||||
fprintf(stderr, "Error (base index check failed): base index = %d\n", base_index);
|
||||
error_found = 1;
|
||||
}
|
||||
|
||||
for (i=0; (!error_found) && (i<m); i++){
|
||||
start = csrRowPtr[i ] - base_index;
|
||||
end = csrRowPtr[i+1] - base_index;
|
||||
if (start > end){
|
||||
fprintf(stderr, "Error (corrupted row): csrRowPtr[%d] (=%d) > csrRowPtr[%d] (=%d)\n", i, start+base_index, i+1, end+base_index);
|
||||
for (i = 0; (!error_found) && (i < m); i++) {
|
||||
start = csrRowPtr[i] - base_index;
|
||||
end = csrRowPtr[i + 1] - base_index;
|
||||
if (start > end) {
|
||||
fprintf(stderr,
|
||||
"Error (corrupted row): csrRowPtr[%d] (=%d) > csrRowPtr[%d] (=%d)\n",
|
||||
i,
|
||||
start + base_index,
|
||||
i + 1,
|
||||
end + base_index);
|
||||
error_found = 1;
|
||||
}
|
||||
for (col=start; col<end; col++){
|
||||
if (csrColInd[col] < base_index){
|
||||
for (col = start; col < end; col++) {
|
||||
if (csrColInd[col] < base_index) {
|
||||
fprintf(stderr, "Error (column vs. base index check failed): csrColInd[%d] < %d\n", col, base_index);
|
||||
error_found = 1;
|
||||
}
|
||||
if ((col < (end-1)) && (csrColInd[col] >= csrColInd[col+1])){
|
||||
fprintf(stderr, "Error (sorting of the column indecis check failed): (csrColInd[%d]=%d) >= (csrColInd[%d]=%d)\n", col, csrColInd[col], col+1, csrColInd[col+1]);
|
||||
if ((col < (end - 1)) && (csrColInd[col] >= csrColInd[col + 1])) {
|
||||
fprintf(
|
||||
stderr,
|
||||
"Error (sorting of the column indecis check failed): (csrColInd[%d]=%d) >= (csrColInd[%d]=%d)\n",
|
||||
col,
|
||||
csrColInd[col],
|
||||
col + 1,
|
||||
csrColInd[col + 1]);
|
||||
error_found = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return error_found ;
|
||||
return error_found;
|
||||
}
|
||||
|
||||
|
||||
template <typename T_ELEM>
|
||||
int loadMMSparseMatrix(
|
||||
char *filename,
|
||||
char elem_type,
|
||||
bool csrFormat,
|
||||
int *m,
|
||||
int *n,
|
||||
int *nnz,
|
||||
T_ELEM **aVal,
|
||||
int **aRowInd,
|
||||
int **aColInd,
|
||||
int extendSymMatrix)
|
||||
int loadMMSparseMatrix(char *filename,
|
||||
char elem_type,
|
||||
bool csrFormat,
|
||||
int *m,
|
||||
int *n,
|
||||
int *nnz,
|
||||
T_ELEM **aVal,
|
||||
int **aRowInd,
|
||||
int **aColInd,
|
||||
int extendSymMatrix)
|
||||
{
|
||||
MM_typecode matcode;
|
||||
double *tempVal;
|
||||
int *tempRowInd,*tempColInd;
|
||||
double *tval;
|
||||
int *trow,*tcol;
|
||||
int *csrRowPtr, *cscColPtr;
|
||||
int i,j,error,base,count;
|
||||
MM_typecode matcode;
|
||||
double *tempVal;
|
||||
int *tempRowInd, *tempColInd;
|
||||
double *tval;
|
||||
int *trow, *tcol;
|
||||
int *csrRowPtr, *cscColPtr;
|
||||
int i, j, error, base, count;
|
||||
struct cooFormat *work;
|
||||
|
||||
/* read the matrix */
|
||||
/* read the matrix */
|
||||
error = mm_read_mtx_crd(filename, m, n, nnz, &trow, &tcol, &tval, &matcode);
|
||||
if (error) {
|
||||
fprintf(stderr, "!!!! can not open file: '%s'\n", filename);
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* start error checking */
|
||||
if (mm_is_complex(matcode) && ((elem_type != 'z') && (elem_type != 'c'))) {
|
||||
fprintf(stderr, "!!!! complex matrix requires type 'z' or 'c'\n");
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (mm_is_dense(matcode) || mm_is_array(matcode) || mm_is_pattern(matcode) /*|| mm_is_integer(matcode)*/){
|
||||
if (mm_is_dense(matcode) || mm_is_array(matcode) || mm_is_pattern(matcode) /*|| mm_is_integer(matcode)*/) {
|
||||
fprintf(stderr, "!!!! dense, array, pattern and integer matrices are not supported\n");
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* if necessary symmetrize the pattern (transform from triangular to full) */
|
||||
if ((extendSymMatrix) && (mm_is_symmetric(matcode) || mm_is_hermitian(matcode) || mm_is_skew(matcode))){
|
||||
//count number of non-diagonal elements
|
||||
count=0;
|
||||
for(i=0; i<(*nnz); i++){
|
||||
if (trow[i] != tcol[i]){
|
||||
if ((extendSymMatrix) && (mm_is_symmetric(matcode) || mm_is_hermitian(matcode) || mm_is_skew(matcode))) {
|
||||
// count number of non-diagonal elements
|
||||
count = 0;
|
||||
for (i = 0; i < (*nnz); i++) {
|
||||
if (trow[i] != tcol[i]) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
//allocate space for the symmetrized matrix
|
||||
tempRowInd = (int *)malloc((*nnz + count) * sizeof(int));
|
||||
tempColInd = (int *)malloc((*nnz + count) * sizeof(int));
|
||||
if (mm_is_real(matcode) || mm_is_integer(matcode)){
|
||||
// allocate space for the symmetrized matrix
|
||||
tempRowInd = (int *)malloc((*nnz + count) * sizeof(int));
|
||||
tempColInd = (int *)malloc((*nnz + count) * sizeof(int));
|
||||
if (mm_is_real(matcode) || mm_is_integer(matcode)) {
|
||||
tempVal = (double *)malloc((*nnz + count) * sizeof(double));
|
||||
}
|
||||
else{
|
||||
else {
|
||||
tempVal = (double *)malloc(2 * (*nnz + count) * sizeof(double));
|
||||
}
|
||||
//copy the elements regular and transposed locations
|
||||
for(j=0, i=0; i<(*nnz); i++){
|
||||
tempRowInd[j]=trow[i];
|
||||
tempColInd[j]=tcol[i];
|
||||
if (mm_is_real(matcode) || mm_is_integer(matcode)){
|
||||
tempVal[j]=tval[i];
|
||||
// copy the elements regular and transposed locations
|
||||
for (j = 0, i = 0; i < (*nnz); i++) {
|
||||
tempRowInd[j] = trow[i];
|
||||
tempColInd[j] = tcol[i];
|
||||
if (mm_is_real(matcode) || mm_is_integer(matcode)) {
|
||||
tempVal[j] = tval[i];
|
||||
}
|
||||
else{
|
||||
tempVal[2*j] =tval[2*i];
|
||||
tempVal[2*j+1]=tval[2*i+1];
|
||||
else {
|
||||
tempVal[2 * j] = tval[2 * i];
|
||||
tempVal[2 * j + 1] = tval[2 * i + 1];
|
||||
}
|
||||
j++;
|
||||
if (trow[i] != tcol[i]){
|
||||
tempRowInd[j]=tcol[i];
|
||||
tempColInd[j]=trow[i];
|
||||
if (mm_is_real(matcode) || mm_is_integer(matcode)){
|
||||
if (mm_is_skew(matcode)){
|
||||
tempVal[j]=-tval[i];
|
||||
if (trow[i] != tcol[i]) {
|
||||
tempRowInd[j] = tcol[i];
|
||||
tempColInd[j] = trow[i];
|
||||
if (mm_is_real(matcode) || mm_is_integer(matcode)) {
|
||||
if (mm_is_skew(matcode)) {
|
||||
tempVal[j] = -tval[i];
|
||||
}
|
||||
else{
|
||||
tempVal[j]= tval[i];
|
||||
else {
|
||||
tempVal[j] = tval[i];
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(mm_is_hermitian(matcode)){
|
||||
tempVal[2*j] = tval[2*i];
|
||||
tempVal[2*j+1]=-tval[2*i+1];
|
||||
else {
|
||||
if (mm_is_hermitian(matcode)) {
|
||||
tempVal[2 * j] = tval[2 * i];
|
||||
tempVal[2 * j + 1] = -tval[2 * i + 1];
|
||||
}
|
||||
else{
|
||||
tempVal[2*j] = tval[2*i];
|
||||
tempVal[2*j+1]= tval[2*i+1];
|
||||
else {
|
||||
tempVal[2 * j] = tval[2 * i];
|
||||
tempVal[2 * j + 1] = tval[2 * i + 1];
|
||||
}
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
(*nnz)+=count;
|
||||
//free temporary storage
|
||||
(*nnz) += count;
|
||||
// free temporary storage
|
||||
free(trow);
|
||||
free(tcol);
|
||||
free(tval);
|
||||
free(tval);
|
||||
}
|
||||
else{
|
||||
tempRowInd=trow;
|
||||
tempColInd=tcol;
|
||||
tempVal =tval;
|
||||
else {
|
||||
tempRowInd = trow;
|
||||
tempColInd = tcol;
|
||||
tempVal = tval;
|
||||
}
|
||||
// life time of (trow, tcol, tval) is over.
|
||||
// please use COO format (tempRowInd, tempColInd, tempVal)
|
||||
|
||||
// use qsort to sort COO format
|
||||
work = (struct cooFormat *)malloc(sizeof(struct cooFormat)*(*nnz));
|
||||
if (NULL == work){
|
||||
// use qsort to sort COO format
|
||||
work = (struct cooFormat *)malloc(sizeof(struct cooFormat) * (*nnz));
|
||||
if (NULL == work) {
|
||||
fprintf(stderr, "!!!! allocation error, malloc failed\n");
|
||||
return 1;
|
||||
}
|
||||
for(i=0; i<(*nnz); i++){
|
||||
for (i = 0; i < (*nnz); i++) {
|
||||
work[i].i = tempRowInd[i];
|
||||
work[i].j = tempColInd[i];
|
||||
work[i].p = i; // permutation is identity
|
||||
}
|
||||
|
||||
if (csrFormat){
|
||||
/* create row-major ordering of indices (sorted by row and within each row by column) */
|
||||
qsort(work, *nnz, sizeof(struct cooFormat), (FUNPTR)fptr_array[0] );
|
||||
}else{
|
||||
/* create column-major ordering of indices (sorted by column and within each column by row) */
|
||||
qsort(work, *nnz, sizeof(struct cooFormat), (FUNPTR)fptr_array[1] );
|
||||
|
||||
if (csrFormat) {
|
||||
/* create row-major ordering of indices (sorted by row and within each row by column) */
|
||||
qsort(work, *nnz, sizeof(struct cooFormat), (FUNPTR)fptr_array[0]);
|
||||
}
|
||||
else {
|
||||
/* create column-major ordering of indices (sorted by column and within each column by row) */
|
||||
qsort(work, *nnz, sizeof(struct cooFormat), (FUNPTR)fptr_array[1]);
|
||||
}
|
||||
|
||||
// (tempRowInd, tempColInd) is sorted either by row-major or by col-major
|
||||
for(i=0; i<(*nnz); i++){
|
||||
for (i = 0; i < (*nnz); i++) {
|
||||
tempRowInd[i] = work[i].i;
|
||||
tempColInd[i] = work[i].j;
|
||||
}
|
||||
|
||||
// setup base
|
||||
// setup base
|
||||
// check if there is any row/col 0, if so base-0
|
||||
// check if there is any row/col equal to matrix dimension m/n, if so base-1
|
||||
int base0 = 0;
|
||||
int base1 = 0;
|
||||
for(i=0; i<(*nnz); i++){
|
||||
for (i = 0; i < (*nnz); i++) {
|
||||
const int row = tempRowInd[i];
|
||||
const int col = tempColInd[i];
|
||||
if ( (0 == row) || (0 == col) ){
|
||||
if ((0 == row) || (0 == col)) {
|
||||
base0 = 1;
|
||||
}
|
||||
if ( (*m == row) || (*n == col) ){
|
||||
if ((*m == row) || (*n == col)) {
|
||||
base1 = 1;
|
||||
}
|
||||
}
|
||||
if ( base0 && base1 ){
|
||||
if (base0 && base1) {
|
||||
printf("Error: input matrix is base-0 and base-1 \n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
base = 0;
|
||||
if (base1){
|
||||
if (base1) {
|
||||
base = 1;
|
||||
}
|
||||
|
||||
/* compress the appropriate indices */
|
||||
if (csrFormat){
|
||||
if (csrFormat) {
|
||||
/* CSR format (assuming row-major format) */
|
||||
csrRowPtr = (int *)malloc(((*m)+1) * sizeof(csrRowPtr[0]));
|
||||
if (!csrRowPtr) return 1;
|
||||
csrRowPtr = (int *)malloc(((*m) + 1) * sizeof(csrRowPtr[0]));
|
||||
if (!csrRowPtr)
|
||||
return 1;
|
||||
compress_index(tempRowInd, *nnz, *m, csrRowPtr, base);
|
||||
|
||||
*aRowInd = csrRowPtr;
|
||||
@@ -429,101 +377,97 @@ int loadMMSparseMatrix(
|
||||
}
|
||||
else {
|
||||
/* CSC format (assuming column-major format) */
|
||||
cscColPtr = (int *)malloc(((*n)+1) * sizeof(cscColPtr[0]));
|
||||
if (!cscColPtr) return 1;
|
||||
cscColPtr = (int *)malloc(((*n) + 1) * sizeof(cscColPtr[0]));
|
||||
if (!cscColPtr)
|
||||
return 1;
|
||||
compress_index(tempColInd, *nnz, *n, cscColPtr, base);
|
||||
|
||||
*aColInd = cscColPtr;
|
||||
*aRowInd = (int *)malloc((*nnz) * sizeof(int));
|
||||
}
|
||||
}
|
||||
|
||||
/* transfrom the matrix values of type double into one of the cusparse library types */
|
||||
/* transfrom the matrix values of type double into one of the cusparse library types */
|
||||
*aVal = (T_ELEM *)malloc((*nnz) * sizeof(T_ELEM));
|
||||
|
||||
for (i=0; i<(*nnz); i++) {
|
||||
if (csrFormat){
|
||||
|
||||
for (i = 0; i < (*nnz); i++) {
|
||||
if (csrFormat) {
|
||||
(*aColInd)[i] = tempColInd[i];
|
||||
}
|
||||
else{
|
||||
else {
|
||||
(*aRowInd)[i] = tempRowInd[i];
|
||||
}
|
||||
if (mm_is_real(matcode) || mm_is_integer(matcode)){
|
||||
(*aVal)[i] = cuGet<T_ELEM>( tempVal[ work[i].p ] );
|
||||
if (mm_is_real(matcode) || mm_is_integer(matcode)) {
|
||||
(*aVal)[i] = cuGet<T_ELEM>(tempVal[work[i].p]);
|
||||
}
|
||||
else{
|
||||
(*aVal)[i] = cuGet<T_ELEM>(tempVal[2*work[i].p], tempVal[2*work[i].p+1]);
|
||||
else {
|
||||
(*aVal)[i] = cuGet<T_ELEM>(tempVal[2 * work[i].p], tempVal[2 * work[i].p + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
/* check for corruption */
|
||||
int error_found;
|
||||
if (csrFormat){
|
||||
if (csrFormat) {
|
||||
error_found = verify_pattern(*m, *nnz, *aRowInd, *aColInd);
|
||||
}else{
|
||||
}
|
||||
else {
|
||||
error_found = verify_pattern(*n, *nnz, *aColInd, *aRowInd);
|
||||
}
|
||||
if (error_found){
|
||||
if (error_found) {
|
||||
fprintf(stderr, "!!!! verify_pattern failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* cleanup and exit */
|
||||
free(work);
|
||||
free(tempVal);
|
||||
free(tempVal);
|
||||
free(tempColInd);
|
||||
free(tempRowInd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* specific instantiation */
|
||||
template int loadMMSparseMatrix<float>(
|
||||
char *filename,
|
||||
char elem_type,
|
||||
bool csrFormat,
|
||||
int *m,
|
||||
int *n,
|
||||
int *nnz,
|
||||
float **aVal,
|
||||
int **aRowInd,
|
||||
int **aColInd,
|
||||
int extendSymMatrix);
|
||||
template int loadMMSparseMatrix<float>(char *filename,
|
||||
char elem_type,
|
||||
bool csrFormat,
|
||||
int *m,
|
||||
int *n,
|
||||
int *nnz,
|
||||
float **aVal,
|
||||
int **aRowInd,
|
||||
int **aColInd,
|
||||
int extendSymMatrix);
|
||||
|
||||
template int loadMMSparseMatrix<double>(
|
||||
char *filename,
|
||||
char elem_type,
|
||||
bool csrFormat,
|
||||
int *m,
|
||||
int *n,
|
||||
int *nnz,
|
||||
double **aVal,
|
||||
int **aRowInd,
|
||||
int **aColInd,
|
||||
int extendSymMatrix);
|
||||
|
||||
template int loadMMSparseMatrix<cuComplex>(
|
||||
char *filename,
|
||||
char elem_type,
|
||||
bool csrFormat,
|
||||
int *m,
|
||||
int *n,
|
||||
int *nnz,
|
||||
cuComplex **aVal,
|
||||
int **aRowInd,
|
||||
int **aColInd,
|
||||
int extendSymMatrix);
|
||||
|
||||
template int loadMMSparseMatrix<cuDoubleComplex>(
|
||||
char *filename,
|
||||
char elem_type,
|
||||
bool csrFormat,
|
||||
int *m,
|
||||
int *n,
|
||||
int *nnz,
|
||||
cuDoubleComplex **aVal,
|
||||
int **aRowInd,
|
||||
int **aColInd,
|
||||
int extendSymMatrix);
|
||||
template int loadMMSparseMatrix<double>(char *filename,
|
||||
char elem_type,
|
||||
bool csrFormat,
|
||||
int *m,
|
||||
int *n,
|
||||
int *nnz,
|
||||
double **aVal,
|
||||
int **aRowInd,
|
||||
int **aColInd,
|
||||
int extendSymMatrix);
|
||||
|
||||
template int loadMMSparseMatrix<cuComplex>(char *filename,
|
||||
char elem_type,
|
||||
bool csrFormat,
|
||||
int *m,
|
||||
int *n,
|
||||
int *nnz,
|
||||
cuComplex **aVal,
|
||||
int **aRowInd,
|
||||
int **aColInd,
|
||||
int extendSymMatrix);
|
||||
|
||||
template int loadMMSparseMatrix<cuDoubleComplex>(char *filename,
|
||||
char elem_type,
|
||||
bool csrFormat,
|
||||
int *m,
|
||||
int *n,
|
||||
int *nnz,
|
||||
cuDoubleComplex **aVal,
|
||||
int **aRowInd,
|
||||
int **aColInd,
|
||||
int extendSymMatrix);
|
||||
|
||||
Reference in New Issue
Block a user