Blame spmatrix/spoper.c

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() */