|
Packit |
67cb25 |
/* spio.c
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* Copyright (C) 2016 Patrick Alken
|
|
Packit |
67cb25 |
* Copyright (C) 2016 Alexis Tantet
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* This program is free software; you can redistribute it and/or modify
|
|
Packit |
67cb25 |
* it under the terms of the GNU General Public License as published by
|
|
Packit |
67cb25 |
* the Free Software Foundation; either version 3 of the License, or (at
|
|
Packit |
67cb25 |
* your option) any later version.
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* This program is distributed in the hope that it will be useful, but
|
|
Packit |
67cb25 |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
67cb25 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
67cb25 |
* General Public License for more details.
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* You should have received a copy of the GNU General Public License
|
|
Packit |
67cb25 |
* along with this program; if not, write to the Free Software
|
|
Packit |
67cb25 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#include <config.h>
|
|
Packit |
67cb25 |
#include <stdlib.h>
|
|
Packit |
67cb25 |
#include <math.h>
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#include <gsl/gsl_math.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_errno.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_spmatrix.h>
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/*
|
|
Packit |
67cb25 |
gsl_spmatrix_fprintf()
|
|
Packit |
67cb25 |
Print sparse matrix to file in MatrixMarket format:
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
M N NNZ
|
|
Packit |
67cb25 |
I1 J1 A(I1,J1)
|
|
Packit |
67cb25 |
...
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
Note that indices start at 1 and not 0
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_spmatrix_fprintf(FILE *stream, const gsl_spmatrix *m,
|
|
Packit |
67cb25 |
const char *format)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int status;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* print header */
|
|
Packit |
67cb25 |
status = fprintf(stream, "%%%%MatrixMarket matrix coordinate real general\n");
|
|
Packit |
67cb25 |
if (status < 0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("fprintf failed for header", GSL_EFAILED);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* print rows,columns,nnz */
|
|
Packit |
67cb25 |
status = fprintf(stream, "%u\t%u\t%u\n",
|
|
Packit |
67cb25 |
(unsigned int) m->size1,
|
|
Packit |
67cb25 |
(unsigned int) m->size2,
|
|
Packit |
67cb25 |
(unsigned int) m->nz);
|
|
Packit |
67cb25 |
if (status < 0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("fprintf failed for dimension header", GSL_EFAILED);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (GSL_SPMATRIX_ISTRIPLET(m))
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
size_t n;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (n = 0; n < m->nz; ++n)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
status = fprintf(stream, "%u\t%u\t", (unsigned int) m->i[n] + 1, (unsigned int) m->p[n] + 1);
|
|
Packit |
67cb25 |
if (status < 0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("fprintf failed", GSL_EFAILED);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
status = fprintf(stream, format, m->data[n]);
|
|
Packit |
67cb25 |
if (status < 0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("fprintf failed", GSL_EFAILED);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
status = putc('\n', stream);
|
|
Packit |
67cb25 |
if (status == EOF)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("putc failed", GSL_EFAILED);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (GSL_SPMATRIX_ISCCS(m))
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
size_t j, p;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (j = 0; j < m->size2; ++j)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
for (p = m->p[j]; p < m->p[j + 1]; ++p)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
status = fprintf(stream, "%u\t%u\t", (unsigned int) m->i[p] + 1, (unsigned int) j + 1);
|
|
Packit |
67cb25 |
if (status < 0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("fprintf failed", GSL_EFAILED);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
status = fprintf(stream, format, m->data[p]);
|
|
Packit |
67cb25 |
if (status < 0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("fprintf failed", GSL_EFAILED);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
status = putc('\n', stream);
|
|
Packit |
67cb25 |
if (status == EOF)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("putc failed", GSL_EFAILED);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (GSL_SPMATRIX_ISCRS(m))
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
size_t i, p;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (i = 0; i < m->size1; ++i)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
for (p = m->p[i]; p < m->p[i + 1]; ++p)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
status = fprintf(stream, "%u\t%u\t", (unsigned int) i + 1, (unsigned int) m->i[p] + 1);
|
|
Packit |
67cb25 |
if (status < 0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("fprintf failed", GSL_EFAILED);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
status = fprintf(stream, format, m->data[p]);
|
|
Packit |
67cb25 |
if (status < 0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("fprintf failed", GSL_EFAILED);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
status = putc('\n', stream);
|
|
Packit |
67cb25 |
if (status == EOF)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("putc failed", GSL_EFAILED);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("unknown sparse matrix type", GSL_EINVAL);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_spmatrix *
|
|
Packit |
67cb25 |
gsl_spmatrix_fscanf(FILE *stream)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_spmatrix *m;
|
|
Packit |
67cb25 |
unsigned int size1, size2, nz;
|
|
Packit |
67cb25 |
char buf[1024];
|
|
Packit |
67cb25 |
int found_header = 0;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* read file until we find rows,cols,nz header */
|
|
Packit |
67cb25 |
while (fgets(buf, 1024, stream) != NULL)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int c;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* skip comments */
|
|
Packit |
67cb25 |
if (*buf == '%')
|
|
Packit |
67cb25 |
continue;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
c = sscanf(buf, "%u %u %u",
|
|
Packit |
67cb25 |
&size1, &size2, &nz;;
|
|
Packit |
67cb25 |
if (c == 3)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
found_header = 1;
|
|
Packit |
67cb25 |
break;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (!found_header)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR_NULL ("fscanf failed reading header", GSL_EFAILED);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
m = gsl_spmatrix_alloc_nzmax((size_t) size1, (size_t) size2, (size_t) nz, GSL_SPMATRIX_TRIPLET);
|
|
Packit |
67cb25 |
if (!m)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR_NULL ("error allocating m", GSL_ENOMEM);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
unsigned int i, j;
|
|
Packit |
67cb25 |
double val;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
while (fgets(buf, 1024, stream) != NULL)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int c = sscanf(buf, "%u %u %lg", &i, &j, &val;;
|
|
Packit |
67cb25 |
if (c < 3 || (i == 0) || (j == 0))
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR_NULL ("error in input file format", GSL_EFAILED);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if ((i > size1) || (j > size2))
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR_NULL ("element exceeds matrix dimensions", GSL_EBADLEN);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* subtract 1 from (i,j) since indexing starts at 1 */
|
|
Packit |
67cb25 |
gsl_spmatrix_set(m, i - 1, j - 1, val);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return m;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_spmatrix_fwrite(FILE *stream, const gsl_spmatrix *m)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
size_t items;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* write header: size1, size2, nz */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
items = fwrite(&(m->size1), sizeof(size_t), 1, stream);
|
|
Packit |
67cb25 |
if (items != 1)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("fwrite failed on size1", GSL_EFAILED);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
items = fwrite(&(m->size2), sizeof(size_t), 1, stream);
|
|
Packit |
67cb25 |
if (items != 1)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("fwrite failed on size2", GSL_EFAILED);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
items = fwrite(&(m->nz), sizeof(size_t), 1, stream);
|
|
Packit |
67cb25 |
if (items != 1)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("fwrite failed on nz", GSL_EFAILED);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* write m->i and m->data which are size nz in all storage formats */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
items = fwrite(m->i, sizeof(size_t), m->nz, stream);
|
|
Packit |
67cb25 |
if (items != m->nz)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("fwrite failed on row indices", GSL_EFAILED);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
items = fwrite(m->data, sizeof(double), m->nz, stream);
|
|
Packit |
67cb25 |
if (items != m->nz)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("fwrite failed on data", GSL_EFAILED);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (GSL_SPMATRIX_ISTRIPLET(m))
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
items = fwrite(m->p, sizeof(size_t), m->nz, stream);
|
|
Packit |
67cb25 |
if (items != m->nz)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("fwrite failed on column indices", GSL_EFAILED);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (GSL_SPMATRIX_ISCCS(m))
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
items = fwrite(m->p, sizeof(size_t), m->size2 + 1, stream);
|
|
Packit |
67cb25 |
if (items != m->size2 + 1)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("fwrite failed on column indices", GSL_EFAILED);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (GSL_SPMATRIX_ISCRS(m))
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
items = fwrite(m->p, sizeof(size_t), m->size1 + 1, stream);
|
|
Packit |
67cb25 |
if (items != m->size1 + 1)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("fwrite failed on column indices", GSL_EFAILED);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_spmatrix_fread(FILE *stream, gsl_spmatrix *m)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
size_t size1, size2, nz;
|
|
Packit |
67cb25 |
size_t items;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* read header: size1, size2, nz */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
items = fread(&size1, sizeof(size_t), 1, stream);
|
|
Packit |
67cb25 |
if (items != 1)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("fread failed on size1", GSL_EFAILED);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
items = fread(&size2, sizeof(size_t), 1, stream);
|
|
Packit |
67cb25 |
if (items != 1)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("fread failed on size2", GSL_EFAILED);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
items = fread(&nz, sizeof(size_t), 1, stream);
|
|
Packit |
67cb25 |
if (items != 1)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("fread failed on nz", GSL_EFAILED);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (m->size1 != size1)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("matrix has wrong size1", GSL_EBADLEN);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (m->size2 != size2)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("matrix has wrong size2", GSL_EBADLEN);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (nz > m->nzmax)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("matrix nzmax is too small", GSL_EBADLEN);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* read m->i and m->data arrays, which are size nz for all formats */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
items = fread(m->i, sizeof(size_t), nz, stream);
|
|
Packit |
67cb25 |
if (items != nz)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("fread failed on row indices", GSL_EFAILED);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
items = fread(m->data, sizeof(double), nz, stream);
|
|
Packit |
67cb25 |
if (items != nz)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("fread failed on data", GSL_EFAILED);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
m->nz = nz;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (GSL_SPMATRIX_ISTRIPLET(m))
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
items = fread(m->p, sizeof(size_t), nz, stream);
|
|
Packit |
67cb25 |
if (items != nz)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("fread failed on column indices", GSL_EFAILED);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* build binary search tree for m */
|
|
Packit |
67cb25 |
gsl_spmatrix_tree_rebuild(m);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (GSL_SPMATRIX_ISCCS(m))
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
items = fread(m->p, sizeof(size_t), size2 + 1, stream);
|
|
Packit |
67cb25 |
if (items != size2 + 1)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("fread failed on row pointers", GSL_EFAILED);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (GSL_SPMATRIX_ISCRS(m))
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
items = fread(m->p, sizeof(size_t), size1 + 1, stream);
|
|
Packit |
67cb25 |
if (items != size1 + 1)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("fread failed on column pointers", GSL_EFAILED);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|