Matrix transposition: Difference between revisions

Content added Content deleted
m (added another c version)
Line 236: Line 236:
5.00 25.00 125.00 625.00
5.00 25.00 125.00 625.00
</pre>
</pre>
Playing more to c's strengths, the following implementation
transposes a matrix of any type and dimensions
in place with only O(1) space. See the [http://www.en.wikipedia.org/wiki/In-place_matrix_transposition Wikipedia article]
for more information.
<lang C>
void
*transpose_matrix(matrix,rows,cols,item_size)
void *matrix;
int rows;
int cols;
size_t item_size;
{
#define ALIGNMENT 16 /* power of 2 >= minimum array boundary alignment; maybe unnecessary but machine dependent */


char *cursor;
char carry[ALIGNMENT];
size_t block_size,remaining_size;
int nadir,lag,orbit,ents;


if ((rows == 1) ? 1 : (cols == 1))
return matrix;
ents = rows * cols;
cursor = (char *) matrix;
remaining_size = item_size;
block_size = ((ALIGNMENT < remaining_size) ? ALIGNMENT : remaining_size);
while (block_size)
{
nadir = 1; /* first and last entries are always fixed points so aren't visited */
while (nadir + 1 < ents)
{
memcpy(carry,&(cursor[(lag = nadir) * item_size]),block_size);
while ((orbit = (lag / rows) + cols * (lag % rows)) > nadir) /* follow a complete cycle */
{
memcpy(&(cursor[lag * item_size]),&(cursor[orbit * item_size]),block_size);
lag = orbit;
}
memcpy(&(cursor[lag * item_size]),carry,block_size);
orbit = nadir++;
while ((orbit < nadir) ? (nadir + 1 < ents) : 0) /* find the next unvisited index by an exhaustive search */
{
orbit = nadir;
while ((orbit = (orbit / rows) + cols * (orbit % rows)) > nadir);
nadir = ((orbit < nadir) ? nadir + 1 : nadir);
}
}
cursor = cursor + block_size;
remaining_size = remaining_size - block_size;
block_size = ((ALIGNMENT < remaining_size) ? ALIGNMENT : remaining_size);
}
return matrix;
}
</lang>
No extra storage allocation is required by the caller. Here are
usage examples for an array of doubles and an array of complex numbers.
<lang c>
a = (double *) transpose_matrix((void *) a, n, m, sizeof(double));
b = (complex *) transpose_matrix((void *) b, n, m, sizeof(complex));
</lang>
After execution, the memory maps of a and b will be those of m by n arrays instead
of n by m.
=={{header|Common Lisp}}==
=={{header|Common Lisp}}==
<lang lisp>(defun transpose (m)
<lang lisp>(defun transpose (m)