|
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 |
}
|