123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- // Transpose tensor indices
- #include "stdafx.h"
- #include "defs.h"
- void
- eval_transpose(void)
- {
- push(cadr(p1));
- eval();
- if (cddr(p1) == symbol(NIL)) {
- push_integer(1);
- push_integer(2);
- } else {
- push(caddr(p1));
- eval();
- push(cadddr(p1));
- eval();
- }
- transpose();
- }
- void
- transpose(void)
- {
- int i, j, k, l, m, ndim, nelem, t;
- int ai[MAXDIM], an[MAXDIM];
- U **a, **b;
- save();
- p3 = pop();
- p2 = pop();
- p1 = pop();
- if (!istensor(p1)) {
- if (!iszero(p1))
- stop("transpose: tensor expected, 1st arg is not a tensor");
- push(zero);
- restore();
- return;
- }
- ndim = p1->u.tensor->ndim;
- nelem = p1->u.tensor->nelem;
- // vector?
- if (ndim == 1) {
- push(p1);
- restore();
- return;
- }
- push(p2);
- l = pop_integer();
- push(p3);
- m = pop_integer();
- if (l < 1 || l > ndim || m < 1 || m > ndim)
- stop("transpose: index out of range");
- l--;
- m--;
- p2 = alloc_tensor(nelem);
- p2->u.tensor->ndim = ndim;
- for (i = 0; i < ndim; i++)
- p2->u.tensor->dim[i] = p1->u.tensor->dim[i];
- p2->u.tensor->dim[l] = p1->u.tensor->dim[m];
- p2->u.tensor->dim[m] = p1->u.tensor->dim[l];
- a = p1->u.tensor->elem;
- b = p2->u.tensor->elem;
- // init tensor index
- for (i = 0; i < ndim; i++) {
- ai[i] = 0;
- an[i] = p1->u.tensor->dim[i];
- }
- // copy components from a to b
- for (i = 0; i < nelem; i++) {
- // swap indices l and m
- t = ai[l]; ai[l] = ai[m]; ai[m] = t;
- t = an[l]; an[l] = an[m]; an[m] = t;
- // convert tensor index to linear index k
- k = 0;
- for (j = 0; j < ndim; j++)
- k = (k * an[j]) + ai[j];
- // swap indices back
- t = ai[l]; ai[l] = ai[m]; ai[m] = t;
- t = an[l]; an[l] = an[m]; an[m] = t;
- // copy one element
- b[k] = a[i];
- // increment tensor index
- // Suppose the tensor dimensions are 2 and 3.
- // Then the tensor index ai increments as follows:
- // 00 -> 01
- // 01 -> 02
- // 02 -> 10
- // 10 -> 11
- // 11 -> 12
- // 12 -> 00
- for (j = ndim - 1; j >= 0; j--) {
- if (++ai[j] < an[j])
- break;
- ai[j] = 0;
- }
- }
- push(p2);
- restore();
- }
- #if SELFTEST
- static char *s[] = {
- "transpose(0)",
- "0",
- "transpose(0.0)",
- "0",
- "transpose(((a,b),(c,d)))",
- "((a,c),(b,d))",
- "transpose(((a,b),(c,d)),1,2)",
- "((a,c),(b,d))",
- "transpose(((a,b,c),(d,e,f)),1,2)",
- "((a,d),(b,e),(c,f))",
- "transpose(((a,d),(b,e),(c,f)),1,2)",
- "((a,b,c),(d,e,f))",
- "transpose((a,b,c))",
- "(a,b,c)",
- };
- void
- test_transpose(void)
- {
- test(__FILE__, s, sizeof s / sizeof (char *));
- }
- #endif
|