Revision 24cf94637541a1006d492dd0f39064c96a561d19 authored by Ben Hermans on 22 April 2020, 17:21:07 UTC, committed by Ben Hermans on 22 April 2020, 17:21:07 UTC
1 parent 22a3296
permutation.c
#include "types.h"
#include "constants.h"
#include "global.h"
#include "stdlib.h"
void ladel_permute_vector(ladel_double *x, ladel_int *p, ladel_int size, ladel_double *y)
{
ladel_int index;
for (index = 0; index < size; index++) y[index] = x[p[index]];
}
void ladel_inverse_permute_vector(ladel_double *x, ladel_int *pinv, ladel_int size, ladel_double *y)
{
ladel_int index;
for (index = 0; index < size; index++) y[pinv[index]] = x[index];
}
static int ladel_int_compare(const ladel_int *a, const ladel_int *b)
{
if (*a > *b) return -1;
else return 1;
}
void ladel_permute_sparse_vector(ladel_sparse_matrix *x, ladel_int col, ladel_int *p, ladel_work *work)
{
ladel_int row, index, index_temp, xnz = x->p[col+1] - x->p[col];
ladel_double *temp = work->array_double_all_zeros_ncol1;
/* In a relatively dense case, don't sort but just do a dense permutation.
The dense permutation takes O(nrow) computations.
The sparse permutation takes O(xnz*log(xnz)) computations, because of the sort. */
if (xnz > x->nrow / 5)
{
for (index = x->p[col]; index < x->p[col+1]; index++)
{
row = p[x->i[index]];
temp[row] = x->x[index];
}
index = 0;
for (index_temp = 0; index_temp < x->nrow; index_temp++)
{
if (temp[index_temp] != 0.0)
{
x->i[index] = row;
x->x[index] = temp[index_temp];
temp[index_temp] = 0.0; /*reset to keep the workspace consistent*/
index++;
}
}
}
else
{
for (index = x->p[col]; index < x->p[col+1]; index++)
{
row = p[x->i[index]];
x->i[index] = row;
temp[row] = x->x[index];
}
qsort(x->i, xnz, sizeof(ladel_int), (int (*) (const void *, const void *)) ladel_int_compare);
for (index = x->p[col]; index < x->p[col+1]; index++)
{
row = x->i[index];
x->x[index] = temp[row];
temp[row] = 0.0;
}
}
}
void ladel_permute_symmetric_matrix(ladel_sparse_matrix *M, ladel_int *p, ladel_sparse_matrix *Mpp, ladel_work* work)
{
if (!M || !Mpp) return;
if (!p)
{
ladel_sparse_copy(M, Mpp);
} else
{
ladel_int col, pcol, prow, index, pindex, prev_col_count, ncol = M->ncol;
ladel_int *col_counts = work->array_int_ncol1, *pinv = work->array_int_ncol2;
for (index = 0; index < ncol; index++) col_counts[index] = 0;
for (col = 0; col < ncol; col++) pinv[p[col]] = col;
for (col = 0; col < ncol; col++)
{
pcol = pinv[col];
for (index = M->p[col]; index < M->p[col+1]; index++)
{
prow = pinv[M->i[index]];
col_counts[LADEL_MAX(pcol, prow)]++;
}
}
Mpp->p[0] = 0;
for (col = 1; col < ncol; col++)
{
prev_col_count = col_counts[col-1];
Mpp->p[col] = prev_col_count;
col_counts[col] += prev_col_count;
col_counts[col-1] = Mpp->p[col-1];
}
Mpp->p[ncol] = col_counts[ncol-1];
col_counts[ncol-1] = Mpp->p[ncol-1];
for (col = 0; col < ncol; col++)
{
pcol = pinv[col];
for (index = M->p[col]; index < M->p[col+1]; index++)
{
prow = pinv[M->i[index]];
if (pcol < prow)
{
pindex = col_counts[prow]++;
Mpp->i[pindex] = pcol;
} else
{
pindex = col_counts[pcol]++;
Mpp->i[pindex] = prow;
}
if (M->values) Mpp->x[pindex] = M->x[index];
}
}
}
}

Computing file changes ...