transpose.cpp 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. // Transpose tensor indices
  2. #include "stdafx.h"
  3. #include "defs.h"
  4. void
  5. eval_transpose(void)
  6. {
  7. push(cadr(p1));
  8. eval();
  9. if (cddr(p1) == symbol(NIL)) {
  10. push_integer(1);
  11. push_integer(2);
  12. } else {
  13. push(caddr(p1));
  14. eval();
  15. push(cadddr(p1));
  16. eval();
  17. }
  18. transpose();
  19. }
  20. void
  21. transpose(void)
  22. {
  23. int i, j, k, l, m, ndim, nelem, t;
  24. int ai[MAXDIM], an[MAXDIM];
  25. U **a, **b;
  26. save();
  27. p3 = pop();
  28. p2 = pop();
  29. p1 = pop();
  30. if (!istensor(p1)) {
  31. if (!iszero(p1))
  32. stop("transpose: tensor expected, 1st arg is not a tensor");
  33. push(zero);
  34. restore();
  35. return;
  36. }
  37. ndim = p1->u.tensor->ndim;
  38. nelem = p1->u.tensor->nelem;
  39. // vector?
  40. if (ndim == 1) {
  41. push(p1);
  42. restore();
  43. return;
  44. }
  45. push(p2);
  46. l = pop_integer();
  47. push(p3);
  48. m = pop_integer();
  49. if (l < 1 || l > ndim || m < 1 || m > ndim)
  50. stop("transpose: index out of range");
  51. l--;
  52. m--;
  53. p2 = alloc_tensor(nelem);
  54. p2->u.tensor->ndim = ndim;
  55. for (i = 0; i < ndim; i++)
  56. p2->u.tensor->dim[i] = p1->u.tensor->dim[i];
  57. p2->u.tensor->dim[l] = p1->u.tensor->dim[m];
  58. p2->u.tensor->dim[m] = p1->u.tensor->dim[l];
  59. a = p1->u.tensor->elem;
  60. b = p2->u.tensor->elem;
  61. // init tensor index
  62. for (i = 0; i < ndim; i++) {
  63. ai[i] = 0;
  64. an[i] = p1->u.tensor->dim[i];
  65. }
  66. // copy components from a to b
  67. for (i = 0; i < nelem; i++) {
  68. // swap indices l and m
  69. t = ai[l]; ai[l] = ai[m]; ai[m] = t;
  70. t = an[l]; an[l] = an[m]; an[m] = t;
  71. // convert tensor index to linear index k
  72. k = 0;
  73. for (j = 0; j < ndim; j++)
  74. k = (k * an[j]) + ai[j];
  75. // swap indices back
  76. t = ai[l]; ai[l] = ai[m]; ai[m] = t;
  77. t = an[l]; an[l] = an[m]; an[m] = t;
  78. // copy one element
  79. b[k] = a[i];
  80. // increment tensor index
  81. // Suppose the tensor dimensions are 2 and 3.
  82. // Then the tensor index ai increments as follows:
  83. // 00 -> 01
  84. // 01 -> 02
  85. // 02 -> 10
  86. // 10 -> 11
  87. // 11 -> 12
  88. // 12 -> 00
  89. for (j = ndim - 1; j >= 0; j--) {
  90. if (++ai[j] < an[j])
  91. break;
  92. ai[j] = 0;
  93. }
  94. }
  95. push(p2);
  96. restore();
  97. }
  98. #if SELFTEST
  99. static char *s[] = {
  100. "transpose(0)",
  101. "0",
  102. "transpose(0.0)",
  103. "0",
  104. "transpose(((a,b),(c,d)))",
  105. "((a,c),(b,d))",
  106. "transpose(((a,b),(c,d)),1,2)",
  107. "((a,c),(b,d))",
  108. "transpose(((a,b,c),(d,e,f)),1,2)",
  109. "((a,d),(b,e),(c,f))",
  110. "transpose(((a,d),(b,e),(c,f)),1,2)",
  111. "((a,b,c),(d,e,f))",
  112. "transpose((a,b,c))",
  113. "(a,b,c)",
  114. };
  115. void
  116. test_transpose(void)
  117. {
  118. test(__FILE__, s, sizeof s / sizeof (char *));
  119. }
  120. #endif