Blame permutation/permute_source.c

Packit 67cb25
/* permutation/permute_source.c
Packit 67cb25
 * 
Packit 67cb25
 * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough
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
/* In-place Permutations 
Packit 67cb25
Packit 67cb25
   permute:    OUT[i]       = IN[perm[i]]     i = 0 .. N-1
Packit 67cb25
   invpermute: OUT[perm[i]] = IN[i]           i = 0 .. N-1
Packit 67cb25
Packit 67cb25
   PERM is an index map, i.e. a vector which contains a permutation of
Packit 67cb25
   the integers 0 .. N-1.
Packit 67cb25
Packit 67cb25
   From Knuth "Sorting and Searching", Volume 3 (3rd ed), Section 5.2
Packit 67cb25
   Exercise 10 (answers), p 617
Packit 67cb25
Packit 67cb25
   FIXME: these have not been fully tested.
Packit 67cb25
*/
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
TYPE (gsl_permute) (const size_t * p, ATOMIC * data, const size_t stride, const size_t n)
Packit 67cb25
{
Packit 67cb25
  size_t i, k, pk;
Packit 67cb25
Packit 67cb25
  for (i = 0; i < n; i++)
Packit 67cb25
    {
Packit 67cb25
      k = p[i];
Packit 67cb25
      
Packit 67cb25
      while (k > i) 
Packit 67cb25
        k = p[k];
Packit 67cb25
      
Packit 67cb25
      if (k < i)
Packit 67cb25
        continue ;
Packit 67cb25
      
Packit 67cb25
      /* Now have k == i, i.e the least in its cycle */
Packit 67cb25
      
Packit 67cb25
      pk = p[k];
Packit 67cb25
      
Packit 67cb25
      if (pk == i)
Packit 67cb25
        continue ;
Packit 67cb25
      
Packit 67cb25
      /* shuffle the elements of the cycle */
Packit 67cb25
      
Packit 67cb25
      {
Packit 67cb25
        unsigned int a;
Packit 67cb25
Packit 67cb25
        ATOMIC t[MULTIPLICITY];
Packit 67cb25
        
Packit 67cb25
        for (a = 0; a < MULTIPLICITY; a++)
Packit 67cb25
          t[a] = data[i*stride*MULTIPLICITY + a];
Packit 67cb25
      
Packit 67cb25
        while (pk != i)
Packit 67cb25
          {
Packit 67cb25
            for (a = 0; a < MULTIPLICITY; a++)
Packit 67cb25
              {
Packit 67cb25
                ATOMIC r1 = data[pk*stride*MULTIPLICITY + a];
Packit 67cb25
                data[k*stride*MULTIPLICITY + a] = r1;
Packit 67cb25
              }
Packit 67cb25
            k = pk;
Packit 67cb25
            pk = p[k];
Packit 67cb25
          };
Packit 67cb25
        
Packit 67cb25
        for (a = 0; a < MULTIPLICITY; a++)
Packit 67cb25
          data[k*stride*MULTIPLICITY + a] = t[a];
Packit 67cb25
      }
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  return GSL_SUCCESS;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
FUNCTION (gsl_permute,inverse) (const size_t * p, ATOMIC * data, const size_t stride, const size_t n)
Packit 67cb25
{
Packit 67cb25
  size_t i, k, pk;
Packit 67cb25
Packit 67cb25
  for (i = 0; i < n; i++)
Packit 67cb25
    {
Packit 67cb25
      k = p[i];
Packit 67cb25
          
Packit 67cb25
      while (k > i) 
Packit 67cb25
        k = p[k];
Packit 67cb25
Packit 67cb25
      if (k < i)
Packit 67cb25
        continue ;
Packit 67cb25
      
Packit 67cb25
      /* Now have k == i, i.e the least in its cycle */
Packit 67cb25
Packit 67cb25
      pk = p[k];
Packit 67cb25
Packit 67cb25
      if (pk == i)
Packit 67cb25
        continue ;
Packit 67cb25
      
Packit 67cb25
      /* shuffle the elements of the cycle in the inverse direction */
Packit 67cb25
      
Packit 67cb25
      {
Packit 67cb25
        unsigned int a;
Packit 67cb25
Packit 67cb25
        ATOMIC t[MULTIPLICITY];
Packit 67cb25
Packit 67cb25
        for (a = 0; a < MULTIPLICITY; a++)
Packit 67cb25
          t[a] = data[k*stride*MULTIPLICITY+a];
Packit 67cb25
Packit 67cb25
        while (pk != i)
Packit 67cb25
          {
Packit 67cb25
            for (a = 0; a < MULTIPLICITY; a++)
Packit 67cb25
              {
Packit 67cb25
                ATOMIC r1 = data[pk*stride*MULTIPLICITY + a];
Packit 67cb25
                data[pk*stride*MULTIPLICITY + a] = t[a];
Packit 67cb25
                t[a] = r1;
Packit 67cb25
              }
Packit 67cb25
Packit 67cb25
            k = pk;
Packit 67cb25
            pk = p[k];
Packit 67cb25
          };
Packit 67cb25
Packit 67cb25
        for (a = 0; a < MULTIPLICITY; a++)
Packit 67cb25
          data[pk*stride*MULTIPLICITY+a] = t[a];
Packit 67cb25
      }
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  return GSL_SUCCESS;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
TYPE (gsl_permute_vector) (const gsl_permutation * p, TYPE (gsl_vector) * v)
Packit 67cb25
{
Packit 67cb25
  if (v->size != p->size)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR ("vector and permutation must be the same length", GSL_EBADLEN);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  TYPE (gsl_permute) (p->data, v->data, v->stride, v->size) ;
Packit 67cb25
Packit 67cb25
  return GSL_SUCCESS;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
FUNCTION (gsl_permute_vector,inverse) (const gsl_permutation * p, TYPE (gsl_vector) * v)
Packit 67cb25
{
Packit 67cb25
  if (v->size != p->size)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR ("vector and permutation must be the same length", GSL_EBADLEN);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  FUNCTION (gsl_permute,inverse) (p->data, v->data, v->stride, v->size) ;
Packit 67cb25
Packit 67cb25
  return GSL_SUCCESS;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
TYPE (gsl_permute_matrix) (const gsl_permutation * p, TYPE (gsl_matrix) * A)
Packit 67cb25
{
Packit 67cb25
  if (A->size2 != p->size)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR ("matrix columns and permutation must be the same length", GSL_EBADLEN);
Packit 67cb25
    }
Packit 67cb25
  else
Packit 67cb25
    {
Packit 67cb25
      size_t i;
Packit 67cb25
Packit 67cb25
      for (i = 0; i < A->size1; ++i)
Packit 67cb25
        {
Packit 67cb25
          QUALIFIED_VIEW (gsl_vector, view) r = FUNCTION (gsl_matrix, row) (A, i);
Packit 67cb25
Packit 67cb25
          TYPE (gsl_permute_vector) (p, &r.vector);
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      return GSL_SUCCESS;
Packit 67cb25
    }
Packit 67cb25
}