Little fix after the last commit (mostly a git fail)
[eigenmath-fx.git] / index.cpp
blob9e2e784f079e7da4642544b4d765d6d64a935ee3
1 #include "stdafx.h"
2 #include "defs.h"
4 // n is the total number of things on the stack. The first thing on the stack
5 // is the object to be indexed, followed by the indices themselves.
7 void
8 index_function(int n)
10 int i, k, m, ndim, nelem, t;
11 U **s;
13 save();
14 s = stack + tos - n;
15 p1 = s[0];
17 // index of scalar ok
19 if (!istensor(p1)) {
20 tos -= n;
21 push(p1);
22 restore();
23 return;
26 ndim = p1->u.tensor->ndim;
28 m = n - 1;
30 if (m > ndim)
31 stop("too many indices for tensor");
33 k = 0;
35 for (i = 0; i < m; i++) {
36 push(s[i + 1]);
37 t = pop_integer();
38 if (t < 1 || t > p1->u.tensor->dim[i])
39 stop("index out of range");
40 k = k * p1->u.tensor->dim[i] + t - 1;
43 if (ndim == m) {
44 tos -= n;
45 push(p1->u.tensor->elem[k]);
46 restore();
47 return;
50 for (i = m; i < ndim; i++)
51 k = k * p1->u.tensor->dim[i] + 0;
53 nelem = 1;
55 for (i = m; i < ndim; i++)
56 nelem *= p1->u.tensor->dim[i];
58 p2 = alloc_tensor(nelem);
60 p2->u.tensor->ndim = ndim - m;
62 for (i = m; i < ndim; i++)
63 p2->u.tensor->dim[i - m] = p1->u.tensor->dim[i];
65 for (i = 0; i < nelem; i++)
66 p2->u.tensor->elem[i] = p1->u.tensor->elem[k + i];
68 tos -= n;
69 push(p2);
70 restore();
73 //-----------------------------------------------------------------------------
75 // Input: n Number of args on stack
77 // tos-n Right-hand value
79 // tos-n+1 Left-hand value
81 // tos-n+2 First index
83 // .
84 // .
85 // .
87 // tos-1 Last index
89 // Output: Result on stack
91 //-----------------------------------------------------------------------------
93 #define LVALUE p1
94 #define RVALUE p2
95 #define TMP p3
97 void
98 set_component(int n)
100 int i, k, m, ndim, t;
101 U **s;
103 save();
105 if (n < 3)
106 stop("error in indexed assign");
108 s = stack + tos - n;
110 RVALUE = s[0];
112 LVALUE = s[1];
114 if (!istensor(LVALUE))
115 stop("error in indexed assign");
117 ndim = LVALUE->u.tensor->ndim;
119 m = n - 2;
121 if (m > ndim)
122 stop("error in indexed assign");
124 k = 0;
126 for (i = 0; i < m; i++) {
127 push(s[i + 2]);
128 t = pop_integer();
129 if (t < 1 || t > LVALUE->u.tensor->dim[i])
130 stop("error in indexed assign");
131 k = k * p1->u.tensor->dim[i] + t - 1;
134 for (i = m; i < ndim; i++)
135 k = k * p1->u.tensor->dim[i] + 0;
137 // copy
139 TMP = alloc_tensor(LVALUE->u.tensor->nelem);
141 TMP->u.tensor->ndim = LVALUE->u.tensor->ndim;
143 for (i = 0; i < p1->u.tensor->ndim; i++)
144 TMP->u.tensor->dim[i] = LVALUE->u.tensor->dim[i];
146 for (i = 0; i < p1->u.tensor->nelem; i++)
147 TMP->u.tensor->elem[i] = LVALUE->u.tensor->elem[i];
149 LVALUE = TMP;
151 if (ndim == m) {
152 if (istensor(RVALUE))
153 stop("error in indexed assign");
154 LVALUE->u.tensor->elem[k] = RVALUE;
155 tos -= n;
156 push(LVALUE);
157 restore();
158 return;
161 // see if the rvalue matches
163 if (!istensor(RVALUE))
164 stop("error in indexed assign");
166 if (ndim - m != RVALUE->u.tensor->ndim)
167 stop("error in indexed assign");
169 for (i = 0; i < RVALUE->u.tensor->ndim; i++)
170 if (LVALUE->u.tensor->dim[m + i] != RVALUE->u.tensor->dim[i])
171 stop("error in indexed assign");
173 // copy rvalue
175 for (i = 0; i < RVALUE->u.tensor->nelem; i++)
176 LVALUE->u.tensor->elem[k + i] = RVALUE->u.tensor->elem[i];
178 tos -= n;
180 push(LVALUE);
182 restore();
185 #if SELFTEST
187 static char *s[] = {
189 "A=((A11,A12),(A21,A22))",
192 "A[1,1]",
193 "A11",
195 "A[1,2]",
196 "A12",
198 "A[2,1]",
199 "A21",
201 "A[2,2]",
202 "A22",
204 "A[1]",
205 "(A11,A12)",
207 "A[2]",
208 "(A21,A22)",
210 "A[1]=(B11,B12)",
213 "A",
214 "((B11,B12),(A21,A22))",
216 "A[2]=(B21,B22)",
219 "A",
220 "((B11,B12),(B21,B22))",
222 "A=((0,0),(0,0))",
225 "A[1,1]",
226 "0",
228 // index of scalar ok
230 "1[2]",
231 "1",
234 void
235 test_index(void)
237 test(__FILE__, s, sizeof s / sizeof (char *));
240 #endif