index.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. #include "stdafx.h"
  2. #include "defs.h"
  3. // n is the total number of things on the stack. The first thing on the stack
  4. // is the object to be indexed, followed by the indices themselves.
  5. void
  6. index_function(int n)
  7. {
  8. int i, k, m, ndim, nelem, t;
  9. U **s;
  10. save();
  11. s = stack + tos - n;
  12. p1 = s[0];
  13. // index of scalar ok
  14. if (!istensor(p1)) {
  15. tos -= n;
  16. push(p1);
  17. restore();
  18. return;
  19. }
  20. ndim = p1->u.tensor->ndim;
  21. m = n - 1;
  22. if (m > ndim)
  23. stop("too many indices for tensor");
  24. k = 0;
  25. for (i = 0; i < m; i++) {
  26. push(s[i + 1]);
  27. t = pop_integer();
  28. if (t < 1 || t > p1->u.tensor->dim[i])
  29. stop("index out of range");
  30. k = k * p1->u.tensor->dim[i] + t - 1;
  31. }
  32. if (ndim == m) {
  33. tos -= n;
  34. push(p1->u.tensor->elem[k]);
  35. restore();
  36. return;
  37. }
  38. for (i = m; i < ndim; i++)
  39. k = k * p1->u.tensor->dim[i] + 0;
  40. nelem = 1;
  41. for (i = m; i < ndim; i++)
  42. nelem *= p1->u.tensor->dim[i];
  43. p2 = alloc_tensor(nelem);
  44. p2->u.tensor->ndim = ndim - m;
  45. for (i = m; i < ndim; i++)
  46. p2->u.tensor->dim[i - m] = p1->u.tensor->dim[i];
  47. for (i = 0; i < nelem; i++)
  48. p2->u.tensor->elem[i] = p1->u.tensor->elem[k + i];
  49. tos -= n;
  50. push(p2);
  51. restore();
  52. }
  53. //-----------------------------------------------------------------------------
  54. //
  55. // Input: n Number of args on stack
  56. //
  57. // tos-n Right-hand value
  58. //
  59. // tos-n+1 Left-hand value
  60. //
  61. // tos-n+2 First index
  62. //
  63. // .
  64. // .
  65. // .
  66. //
  67. // tos-1 Last index
  68. //
  69. // Output: Result on stack
  70. //
  71. //-----------------------------------------------------------------------------
  72. #define LVALUE p1
  73. #define RVALUE p2
  74. #define TMP p3
  75. void
  76. set_component(int n)
  77. {
  78. int i, k, m, ndim, t;
  79. U **s;
  80. save();
  81. if (n < 3)
  82. stop("error in indexed assign");
  83. s = stack + tos - n;
  84. RVALUE = s[0];
  85. LVALUE = s[1];
  86. if (!istensor(LVALUE))
  87. stop("error in indexed assign");
  88. ndim = LVALUE->u.tensor->ndim;
  89. m = n - 2;
  90. if (m > ndim)
  91. stop("error in indexed assign");
  92. k = 0;
  93. for (i = 0; i < m; i++) {
  94. push(s[i + 2]);
  95. t = pop_integer();
  96. if (t < 1 || t > LVALUE->u.tensor->dim[i])
  97. stop("error in indexed assign");
  98. k = k * p1->u.tensor->dim[i] + t - 1;
  99. }
  100. for (i = m; i < ndim; i++)
  101. k = k * p1->u.tensor->dim[i] + 0;
  102. // copy
  103. TMP = alloc_tensor(LVALUE->u.tensor->nelem);
  104. TMP->u.tensor->ndim = LVALUE->u.tensor->ndim;
  105. for (i = 0; i < p1->u.tensor->ndim; i++)
  106. TMP->u.tensor->dim[i] = LVALUE->u.tensor->dim[i];
  107. for (i = 0; i < p1->u.tensor->nelem; i++)
  108. TMP->u.tensor->elem[i] = LVALUE->u.tensor->elem[i];
  109. LVALUE = TMP;
  110. if (ndim == m) {
  111. if (istensor(RVALUE))
  112. stop("error in indexed assign");
  113. LVALUE->u.tensor->elem[k] = RVALUE;
  114. tos -= n;
  115. push(LVALUE);
  116. restore();
  117. return;
  118. }
  119. // see if the rvalue matches
  120. if (!istensor(RVALUE))
  121. stop("error in indexed assign");
  122. if (ndim - m != RVALUE->u.tensor->ndim)
  123. stop("error in indexed assign");
  124. for (i = 0; i < RVALUE->u.tensor->ndim; i++)
  125. if (LVALUE->u.tensor->dim[m + i] != RVALUE->u.tensor->dim[i])
  126. stop("error in indexed assign");
  127. // copy rvalue
  128. for (i = 0; i < RVALUE->u.tensor->nelem; i++)
  129. LVALUE->u.tensor->elem[k + i] = RVALUE->u.tensor->elem[i];
  130. tos -= n;
  131. push(LVALUE);
  132. restore();
  133. }
  134. #if SELFTEST
  135. static char *s[] = {
  136. "A=((A11,A12),(A21,A22))",
  137. "",
  138. "A[1,1]",
  139. "A11",
  140. "A[1,2]",
  141. "A12",
  142. "A[2,1]",
  143. "A21",
  144. "A[2,2]",
  145. "A22",
  146. "A[1]",
  147. "(A11,A12)",
  148. "A[2]",
  149. "(A21,A22)",
  150. "A[1]=(B11,B12)",
  151. "",
  152. "A",
  153. "((B11,B12),(A21,A22))",
  154. "A[2]=(B21,B22)",
  155. "",
  156. "A",
  157. "((B11,B12),(B21,B22))",
  158. "A=((0,0),(0,0))",
  159. "",
  160. "A[1,1]",
  161. "0",
  162. // index of scalar ok
  163. "1[2]",
  164. "1",
  165. };
  166. void
  167. test_index(void)
  168. {
  169. test(__FILE__, s, sizeof s / sizeof (char *));
  170. }
  171. #endif