|
Packit |
67cb25 |
/* spoper.c
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* Copyright (C) 2012 Patrick Alken
|
|
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_matrix.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_errno.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_spmatrix.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_spblas.h>
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_spmatrix_scale(gsl_spmatrix *m, const double x)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
size_t i;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (i = 0; i < m->nz; ++i)
|
|
Packit |
67cb25 |
m->data[i] *= x;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
} /* gsl_spmatrix_scale() */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_spmatrix_minmax(const gsl_spmatrix *m, double *min_out, double *max_out)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
double min, max;
|
|
Packit |
67cb25 |
size_t n;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (m->nz == 0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("matrix is empty", GSL_EINVAL);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
min = m->data[0];
|
|
Packit |
67cb25 |
max = m->data[0];
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (n = 1; n < m->nz; ++n)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
double x = m->data[n];
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (x < min)
|
|
Packit |
67cb25 |
min = x;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (x > max)
|
|
Packit |
67cb25 |
max = x;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
*min_out = min;
|
|
Packit |
67cb25 |
*max_out = max;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
} /* gsl_spmatrix_minmax() */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/*
|
|
Packit |
67cb25 |
gsl_spmatrix_add()
|
|
Packit |
67cb25 |
Add two sparse matrices
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
Inputs: c - (output) a + b
|
|
Packit |
67cb25 |
a - (input) sparse matrix
|
|
Packit |
67cb25 |
b - (input) sparse matrix
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
Return: success or error
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_spmatrix_add(gsl_spmatrix *c, const gsl_spmatrix *a,
|
|
Packit |
67cb25 |
const gsl_spmatrix *b)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
const size_t M = a->size1;
|
|
Packit |
67cb25 |
const size_t N = a->size2;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (b->size1 != M || b->size2 != N || c->size1 != M || c->size2 != N)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("matrices must have same dimensions", GSL_EBADLEN);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (a->sptype != b->sptype || a->sptype != c->sptype)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("matrices must have same sparse storage format",
|
|
Packit |
67cb25 |
GSL_EINVAL);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (GSL_SPMATRIX_ISTRIPLET(a))
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("triplet format not yet supported", GSL_EINVAL);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int status = GSL_SUCCESS;
|
|
Packit |
67cb25 |
size_t *w = a->work_sze;
|
|
Packit |
67cb25 |
double *x = c->work_dbl;
|
|
Packit |
67cb25 |
size_t *Cp, *Ci;
|
|
Packit |
67cb25 |
double *Cd;
|
|
Packit |
67cb25 |
size_t j, p;
|
|
Packit |
67cb25 |
size_t nz = 0; /* number of non-zeros in c */
|
|
Packit |
67cb25 |
size_t inner_size, outer_size;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (GSL_SPMATRIX_ISCCS(a))
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
inner_size = M;
|
|
Packit |
67cb25 |
outer_size = N;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (GSL_SPMATRIX_ISCRS(a))
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
inner_size = N;
|
|
Packit |
67cb25 |
outer_size = M;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("unknown sparse matrix type", GSL_EINVAL);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (c->nzmax < a->nz + b->nz)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
status = gsl_spmatrix_realloc(a->nz + b->nz, c);
|
|
Packit |
67cb25 |
if (status)
|
|
Packit |
67cb25 |
return status;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* initialize w = 0 */
|
|
Packit |
67cb25 |
for (j = 0; j < inner_size; ++j)
|
|
Packit |
67cb25 |
w[j] = 0;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
Ci = c->i;
|
|
Packit |
67cb25 |
Cp = c->p;
|
|
Packit |
67cb25 |
Cd = c->data;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (j = 0; j < outer_size; ++j)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
Cp[j] = nz;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* CCS: x += A(:,j); CRS: x += A(j,:) */
|
|
Packit |
67cb25 |
nz = gsl_spblas_scatter(a, j, 1.0, w, x, j + 1, c, nz);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* CCS: x += B(:,j); CRS: x += B(j,:) */
|
|
Packit |
67cb25 |
nz = gsl_spblas_scatter(b, j, 1.0, w, x, j + 1, c, nz);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (p = Cp[j]; p < nz; ++p)
|
|
Packit |
67cb25 |
Cd[p] = x[Ci[p]];
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* finalize last column of c */
|
|
Packit |
67cb25 |
Cp[j] = nz;
|
|
Packit |
67cb25 |
c->nz = nz;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return status;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
} /* gsl_spmatrix_add() */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/*
|
|
Packit |
67cb25 |
gsl_spmatrix_d2sp()
|
|
Packit |
67cb25 |
Convert a dense gsl_matrix to sparse (triplet) format
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
Inputs: S - (output) sparse matrix in triplet format
|
|
Packit |
67cb25 |
A - (input) dense matrix to convert
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_spmatrix_d2sp(gsl_spmatrix *S, const gsl_matrix *A)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int s = GSL_SUCCESS;
|
|
Packit |
67cb25 |
size_t i, j;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_spmatrix_set_zero(S);
|
|
Packit |
67cb25 |
S->size1 = A->size1;
|
|
Packit |
67cb25 |
S->size2 = A->size2;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (i = 0; i < A->size1; ++i)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
for (j = 0; j < A->size2; ++j)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
double x = gsl_matrix_get(A, i, j);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (x != 0.0)
|
|
Packit |
67cb25 |
gsl_spmatrix_set(S, i, j, x);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return s;
|
|
Packit |
67cb25 |
} /* gsl_spmatrix_d2sp() */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/*
|
|
Packit |
67cb25 |
gsl_spmatrix_sp2d()
|
|
Packit |
67cb25 |
Convert a sparse matrix to dense format
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_spmatrix_sp2d(gsl_matrix *A, const gsl_spmatrix *S)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
if (A->size1 != S->size1 || A->size2 != S->size2)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("matrix sizes do not match", GSL_EBADLEN);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_matrix_set_zero(A);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (GSL_SPMATRIX_ISTRIPLET(S))
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
size_t n;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for (n = 0; n < S->nz; ++n)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
size_t i = S->i[n];
|
|
Packit |
67cb25 |
size_t j = S->p[n];
|
|
Packit |
67cb25 |
double x = S->data[n];
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_matrix_set(A, i, j, x);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
GSL_ERROR("non-triplet formats not yet supported", GSL_EINVAL);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
} /* gsl_spmatrix_sp2d() */
|