Blame spmatrix/spswap.c

Packit 67cb25
/* spswap.c
Packit 67cb25
 * 
Packit 67cb25
 * Copyright (C) 2014 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_matrix.h>
Packit 67cb25
#include <gsl/gsl_errno.h>
Packit 67cb25
#include <gsl/gsl_spmatrix.h>
Packit 67cb25
Packit 67cb25
#include "avl.c"
Packit 67cb25
Packit 67cb25
/*
Packit 67cb25
gsl_spmatrix_transpose()
Packit 67cb25
  Replace the sparse matrix src by its transpose,
Packit 67cb25
keeping the matrix in the same storage format
Packit 67cb25
Packit 67cb25
Inputs: A - (input/output) sparse matrix to transpose.
Packit 67cb25
*/
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_spmatrix_transpose(gsl_spmatrix * m)
Packit 67cb25
{
Packit 67cb25
  if (GSL_SPMATRIX_ISTRIPLET(m))
Packit 67cb25
    {
Packit 67cb25
      size_t n;
Packit 67cb25
Packit 67cb25
      /* swap row/column indices */
Packit 67cb25
      for (n = 0; n < m->nz; ++n)
Packit 67cb25
        {
Packit 67cb25
          size_t tmp = m->p[n];
Packit 67cb25
          m->p[n] = m->i[n];
Packit 67cb25
          m->i[n] = tmp;
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      /* need to rebuild AVL tree, or element searches won't
Packit 67cb25
       * work correctly with transposed indices */
Packit 67cb25
      gsl_spmatrix_tree_rebuild(m);
Packit 67cb25
    }
Packit 67cb25
  else
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR("unknown sparse matrix type", GSL_EINVAL);
Packit 67cb25
    }
Packit 67cb25
  
Packit 67cb25
  /* swap dimensions */
Packit 67cb25
  if (m->size1 != m->size2)
Packit 67cb25
    {
Packit 67cb25
      size_t tmp = m->size1;
Packit 67cb25
      m->size1 = m->size2;
Packit 67cb25
      m->size2 = tmp;
Packit 67cb25
    }
Packit 67cb25
  
Packit 67cb25
  return GSL_SUCCESS;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
/*
Packit 67cb25
gsl_spmatrix_transpose2()
Packit 67cb25
  Replace the sparse matrix src by its transpose either by
Packit 67cb25
  swapping its row and column indices if it is in triplet storage,
Packit 67cb25
  or by switching its major if it is in compressed storage.
Packit 67cb25
Packit 67cb25
Inputs: A - (input/output) sparse matrix to transpose.
Packit 67cb25
*/
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_spmatrix_transpose2(gsl_spmatrix * m)
Packit 67cb25
{
Packit 67cb25
  if (GSL_SPMATRIX_ISTRIPLET(m))
Packit 67cb25
    {
Packit 67cb25
      return gsl_spmatrix_transpose(m);
Packit 67cb25
    }
Packit 67cb25
  else if (GSL_SPMATRIX_ISCCS(m))
Packit 67cb25
    {
Packit 67cb25
      m->sptype = GSL_SPMATRIX_CRS;
Packit 67cb25
    }
Packit 67cb25
  else if (GSL_SPMATRIX_ISCRS(m))
Packit 67cb25
    {
Packit 67cb25
      m->sptype = GSL_SPMATRIX_CCS;
Packit 67cb25
    }
Packit 67cb25
  else
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR("unknown sparse matrix type", GSL_EINVAL);
Packit 67cb25
    }
Packit 67cb25
  
Packit 67cb25
  /* swap dimensions */
Packit 67cb25
  if (m->size1 != m->size2)
Packit 67cb25
    {
Packit 67cb25
      size_t tmp = m->size1;
Packit 67cb25
      m->size1 = m->size2;
Packit 67cb25
      m->size2 = tmp;
Packit 67cb25
    }
Packit 67cb25
  
Packit 67cb25
  return GSL_SUCCESS;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_spmatrix_transpose_memcpy(gsl_spmatrix *dest, const gsl_spmatrix *src)
Packit 67cb25
{
Packit 67cb25
  const size_t M = src->size1;
Packit 67cb25
  const size_t N = src->size2;
Packit 67cb25
Packit 67cb25
  if (M != dest->size2 || N != dest->size1)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR("dimensions of dest must be transpose of src matrix",
Packit 67cb25
                GSL_EBADLEN);
Packit 67cb25
    }
Packit 67cb25
  else if (dest->sptype != src->sptype)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR("cannot copy matrices of different storage formats",
Packit 67cb25
                GSL_EINVAL);
Packit 67cb25
    }
Packit 67cb25
  else
Packit 67cb25
    {
Packit 67cb25
      int s = GSL_SUCCESS;
Packit 67cb25
      const size_t nz = src->nz;
Packit 67cb25
Packit 67cb25
      if (dest->nzmax < src->nz)
Packit 67cb25
        {
Packit 67cb25
          s = gsl_spmatrix_realloc(src->nz, dest);
Packit 67cb25
          if (s)
Packit 67cb25
            return s;
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      if (GSL_SPMATRIX_ISTRIPLET(src))
Packit 67cb25
        {
Packit 67cb25
          size_t n;
Packit 67cb25
          void *ptr;
Packit 67cb25
Packit 67cb25
          for (n = 0; n < nz; ++n)
Packit 67cb25
            {
Packit 67cb25
              dest->i[n] = src->p[n];
Packit 67cb25
              dest->p[n] = src->i[n];
Packit 67cb25
              dest->data[n] = src->data[n];
Packit 67cb25
Packit 67cb25
              /* copy binary tree data */
Packit 67cb25
              ptr = avl_insert(dest->tree_data->tree, &dest->data[n]);
Packit 67cb25
              if (ptr != NULL)
Packit 67cb25
                {
Packit 67cb25
                  GSL_ERROR("detected duplicate entry", GSL_EINVAL);
Packit 67cb25
                }
Packit 67cb25
            }
Packit 67cb25
        }
Packit 67cb25
      else if (GSL_SPMATRIX_ISCCS(src))
Packit 67cb25
        {
Packit 67cb25
          size_t *Ai = src->i;
Packit 67cb25
          size_t *Ap = src->p;
Packit 67cb25
          double *Ad = src->data;
Packit 67cb25
          size_t *ATi = dest->i;
Packit 67cb25
          size_t *ATp = dest->p;
Packit 67cb25
          double *ATd = dest->data;
Packit 67cb25
          size_t *w = dest->work_sze;
Packit 67cb25
          size_t p, j;
Packit 67cb25
Packit 67cb25
          /* initialize to 0 */
Packit 67cb25
          for (p = 0; p < M + 1; ++p)
Packit 67cb25
            ATp[p] = 0;
Packit 67cb25
Packit 67cb25
          /* compute row counts of A (= column counts for A^T) */
Packit 67cb25
          for (p = 0; p < nz; ++p)
Packit 67cb25
            ATp[Ai[p]]++;
Packit 67cb25
Packit 67cb25
          /* compute row pointers for A (= column pointers for A^T) */
Packit 67cb25
          gsl_spmatrix_cumsum(M, ATp);
Packit 67cb25
Packit 67cb25
          /* make copy of row pointers */
Packit 67cb25
          for (j = 0; j < M; ++j)
Packit 67cb25
            w[j] = ATp[j];
Packit 67cb25
Packit 67cb25
          for (j = 0; j < N; ++j)
Packit 67cb25
            {
Packit 67cb25
              for (p = Ap[j]; p < Ap[j + 1]; ++p)
Packit 67cb25
                {
Packit 67cb25
                  size_t k = w[Ai[p]]++;
Packit 67cb25
                  ATi[k] = j;
Packit 67cb25
                  ATd[k] = Ad[p];
Packit 67cb25
                }
Packit 67cb25
            }
Packit 67cb25
        }
Packit 67cb25
      else if (GSL_SPMATRIX_ISCRS(src))
Packit 67cb25
        {
Packit 67cb25
          size_t *Aj = src->i;
Packit 67cb25
          size_t *Ap = src->p;
Packit 67cb25
          double *Ad = src->data;
Packit 67cb25
          size_t *ATj = dest->i;
Packit 67cb25
          size_t *ATp = dest->p;
Packit 67cb25
          double *ATd = dest->data;
Packit 67cb25
          size_t *w = dest->work_sze;
Packit 67cb25
          size_t p, i;
Packit 67cb25
Packit 67cb25
          /* initialize to 0 */
Packit 67cb25
          for (p = 0; p < N + 1; ++p)
Packit 67cb25
            ATp[p] = 0;
Packit 67cb25
Packit 67cb25
          /* compute column counts of A (= row counts for A^T) */
Packit 67cb25
          for (p = 0; p < nz; ++p)
Packit 67cb25
            ATp[Aj[p]]++;
Packit 67cb25
Packit 67cb25
          /* compute column pointers for A (= row pointers for A^T) */
Packit 67cb25
          gsl_spmatrix_cumsum(N, ATp);
Packit 67cb25
Packit 67cb25
          /* make copy of column pointers */
Packit 67cb25
          for (i = 0; i < N; ++i)
Packit 67cb25
            w[i] = ATp[i];
Packit 67cb25
Packit 67cb25
          for (i = 0; i < M; ++i)
Packit 67cb25
            {
Packit 67cb25
              for (p = Ap[i]; p < Ap[i + 1]; ++p)
Packit 67cb25
                {
Packit 67cb25
                  size_t k = w[Aj[p]]++;
Packit 67cb25
                  ATj[k] = i;
Packit 67cb25
                  ATd[k] = Ad[p];
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
      dest->nz = nz;
Packit 67cb25
Packit 67cb25
      return s;
Packit 67cb25
    }
Packit 67cb25
} /* gsl_spmatrix_transpose_memcpy() */