Blame permutation/permutation.c

Packit 67cb25
/* permutation/permutation.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
#include <config.h>
Packit 67cb25
#include <gsl/gsl_errno.h>
Packit 67cb25
#include <gsl/gsl_permutation.h>
Packit 67cb25
Packit 67cb25
size_t
Packit 67cb25
gsl_permutation_size (const gsl_permutation * p)
Packit 67cb25
{
Packit 67cb25
  return p->size ;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
size_t *
Packit 67cb25
gsl_permutation_data (const gsl_permutation * p)
Packit 67cb25
{
Packit 67cb25
  return p->data ;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_permutation_swap (gsl_permutation * p, const size_t i, const size_t j)
Packit 67cb25
{
Packit 67cb25
  const size_t size = p->size ;
Packit 67cb25
  
Packit 67cb25
  if (i >= size)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR("first index is out of range", GSL_EINVAL);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  if (j >= size)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR("second index is out of range", GSL_EINVAL);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  if (i != j)
Packit 67cb25
    {
Packit 67cb25
      size_t tmp = p->data[i];
Packit 67cb25
      p->data[i] = p->data[j];
Packit 67cb25
      p->data[j] = tmp;
Packit 67cb25
    }
Packit 67cb25
  
Packit 67cb25
  return GSL_SUCCESS;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_permutation_valid (const gsl_permutation * p)
Packit 67cb25
{
Packit 67cb25
  const size_t size = p->size ;
Packit 67cb25
Packit 67cb25
  size_t i, j ;
Packit 67cb25
Packit 67cb25
  for (i = 0; i < size; i++) 
Packit 67cb25
    {
Packit 67cb25
      if (p->data[i] >= size)
Packit 67cb25
        {
Packit 67cb25
          GSL_ERROR("permutation index outside range", GSL_FAILURE) ;
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      for (j = 0; j < i; j++)
Packit 67cb25
        {
Packit 67cb25
          if (p->data[i] == p->data[j])
Packit 67cb25
            {
Packit 67cb25
              GSL_ERROR("duplicate permutation index", GSL_FAILURE) ;
Packit 67cb25
            }
Packit 67cb25
        }
Packit 67cb25
    }
Packit 67cb25
  
Packit 67cb25
  return GSL_SUCCESS;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
void
Packit 67cb25
gsl_permutation_reverse (gsl_permutation * p)
Packit 67cb25
{
Packit 67cb25
  const size_t size = p->size ;
Packit 67cb25
Packit 67cb25
  size_t i ;
Packit 67cb25
  
Packit 67cb25
  for (i = 0; i < (size / 2); i++) 
Packit 67cb25
    {
Packit 67cb25
      size_t j = size - i - 1;
Packit 67cb25
Packit 67cb25
      size_t tmp = p->data[i] ;
Packit 67cb25
      p->data[i] = p->data[j] ;
Packit 67cb25
      p->data[j] = tmp ;
Packit 67cb25
    }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
int 
Packit 67cb25
gsl_permutation_inverse (gsl_permutation * inv, const gsl_permutation * p)
Packit 67cb25
{
Packit 67cb25
  const size_t size = p->size ;
Packit 67cb25
Packit 67cb25
  size_t i ;
Packit 67cb25
Packit 67cb25
  if (inv->size != size)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR("permutation lengths are not equal", GSL_EBADLEN);
Packit 67cb25
    }
Packit 67cb25
  
Packit 67cb25
  for (i = 0; i < size; i++) 
Packit 67cb25
    {
Packit 67cb25
      inv->data[p->data[i]] = i ;
Packit 67cb25
    }
Packit 67cb25
  
Packit 67cb25
  return GSL_SUCCESS ;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_permutation_next (gsl_permutation * p)
Packit 67cb25
{
Packit 67cb25
  /* Replaces p with the next permutation (in the standard lexicographical
Packit 67cb25
   * ordering).  Returns GSL_FAILURE if there is no next permutation.
Packit 67cb25
   */
Packit 67cb25
  const size_t size = p->size;
Packit 67cb25
  size_t i, j, k;
Packit 67cb25
Packit 67cb25
  if (size < 2)
Packit 67cb25
    {
Packit 67cb25
      return GSL_FAILURE;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  i = size - 2;
Packit 67cb25
Packit 67cb25
  while ((p->data[i] > p->data[i+1]) && (i != 0))
Packit 67cb25
    {
Packit 67cb25
      i--;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  if ((i == 0) && (p->data[0] > p->data[1]))
Packit 67cb25
    {
Packit 67cb25
     return GSL_FAILURE;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  k = i + 1;
Packit 67cb25
Packit 67cb25
  for (j = i + 2; j < size; j++ )
Packit 67cb25
    {
Packit 67cb25
      if ((p->data[j] > p->data[i]) && (p->data[j] < p->data[k]))
Packit 67cb25
        {
Packit 67cb25
          k = j;
Packit 67cb25
        }
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  /* swap i and k */
Packit 67cb25
Packit 67cb25
  {
Packit 67cb25
    size_t tmp = p->data[i];
Packit 67cb25
    p->data[i] = p->data[k];
Packit 67cb25
    p->data[k] = tmp;
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  for (j = i + 1; j <= ((size + i) / 2); j++)
Packit 67cb25
    {
Packit 67cb25
      size_t tmp = p->data[j];
Packit 67cb25
      p->data[j] = p->data[size + i - j];
Packit 67cb25
      p->data[size + i - j] = tmp;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  return GSL_SUCCESS;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_permutation_prev (gsl_permutation * p)
Packit 67cb25
{
Packit 67cb25
  const size_t size = p->size;
Packit 67cb25
  size_t i, j, k;
Packit 67cb25
Packit 67cb25
  if (size < 2)
Packit 67cb25
    {
Packit 67cb25
      return GSL_FAILURE;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  i = size - 2;
Packit 67cb25
Packit 67cb25
  while ((p->data[i] < p->data[i+1]) && (i != 0))
Packit 67cb25
    {
Packit 67cb25
      i--;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  if ((i == 0) && (p->data[0] < p->data[1]))
Packit 67cb25
    {
Packit 67cb25
      return GSL_FAILURE;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  k = i + 1;
Packit 67cb25
Packit 67cb25
  for (j = i + 2; j < size; j++ )
Packit 67cb25
    {
Packit 67cb25
      if ((p->data[j] < p->data[i]) && (p->data[j] > p->data[k]))
Packit 67cb25
        {
Packit 67cb25
          k = j;
Packit 67cb25
        }
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  /* swap i and k */
Packit 67cb25
Packit 67cb25
  {
Packit 67cb25
    size_t tmp = p->data[i];
Packit 67cb25
    p->data[i] = p->data[k];
Packit 67cb25
    p->data[k] = tmp;
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  for (j = i + 1; j <= ((size + i) / 2); j++)
Packit 67cb25
    {
Packit 67cb25
      size_t tmp = p->data[j];
Packit 67cb25
      p->data[j] = p->data[size + i - j];
Packit 67cb25
      p->data[size + i - j] = tmp;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  return GSL_SUCCESS;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_permutation_mul (gsl_permutation * p, const gsl_permutation * pa, const gsl_permutation * pb)
Packit 67cb25
{
Packit 67cb25
  size_t i;
Packit 67cb25
  const size_t size = p->size;
Packit 67cb25
Packit 67cb25
  if (pa->size != size)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR("size of result does not match size of pa", GSL_EINVAL);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  if (pb->size != size)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR("size of result does not match size of pb", GSL_EINVAL);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  for (i = 0; i < size; i++)
Packit 67cb25
    {
Packit 67cb25
      p->data[i] = pb->data[pa->data[i]];
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  return GSL_SUCCESS;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_permutation_memcpy (gsl_permutation * dest,
Packit 67cb25
                        const gsl_permutation * src)
Packit 67cb25
{
Packit 67cb25
  const size_t src_size = src->size;
Packit 67cb25
  const size_t dest_size = dest->size;
Packit 67cb25
Packit 67cb25
  if (src_size != dest_size)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR ("permutation lengths are not equal", GSL_EBADLEN);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  {
Packit 67cb25
    size_t j;
Packit 67cb25
Packit 67cb25
    for (j = 0; j < src_size; j++)
Packit 67cb25
      {
Packit 67cb25
        dest->data[j] = src->data[j];
Packit 67cb25
      }
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  return GSL_SUCCESS;
Packit 67cb25
}