Eigenmath/index.cpp

241 lines
3.6 KiB
C++

#include "stdafx.h"
#include "defs.h"
// n is the total number of things on the stack. The first thing on the stack
// is the object to be indexed, followed by the indices themselves.
void
index_function(int n)
{
int i, k, m, ndim, nelem, t;
U **s;
save();
s = stack + tos - n;
p1 = s[0];
// index of scalar ok
if (!istensor(p1)) {
tos -= n;
push(p1);
restore();
return;
}
ndim = p1->u.tensor->ndim;
m = n - 1;
if (m > ndim)
stop("too many indices for tensor");
k = 0;
for (i = 0; i < m; i++) {
push(s[i + 1]);
t = pop_integer();
if (t < 1 || t > p1->u.tensor->dim[i])
stop("index out of range");
k = k * p1->u.tensor->dim[i] + t - 1;
}
if (ndim == m) {
tos -= n;
push(p1->u.tensor->elem[k]);
restore();
return;
}
for (i = m; i < ndim; i++)
k = k * p1->u.tensor->dim[i] + 0;
nelem = 1;
for (i = m; i < ndim; i++)
nelem *= p1->u.tensor->dim[i];
p2 = alloc_tensor(nelem);
p2->u.tensor->ndim = ndim - m;
for (i = m; i < ndim; i++)
p2->u.tensor->dim[i - m] = p1->u.tensor->dim[i];
for (i = 0; i < nelem; i++)
p2->u.tensor->elem[i] = p1->u.tensor->elem[k + i];
tos -= n;
push(p2);
restore();
}
//-----------------------------------------------------------------------------
//
// Input: n Number of args on stack
//
// tos-n Right-hand value
//
// tos-n+1 Left-hand value
//
// tos-n+2 First index
//
// .
// .
// .
//
// tos-1 Last index
//
// Output: Result on stack
//
//-----------------------------------------------------------------------------
#define LVALUE p1
#define RVALUE p2
#define TMP p3
void
set_component(int n)
{
int i, k, m, ndim, t;
U **s;
save();
if (n < 3)
stop("error in indexed assign");
s = stack + tos - n;
RVALUE = s[0];
LVALUE = s[1];
if (!istensor(LVALUE))
stop("error in indexed assign");
ndim = LVALUE->u.tensor->ndim;
m = n - 2;
if (m > ndim)
stop("error in indexed assign");
k = 0;
for (i = 0; i < m; i++) {
push(s[i + 2]);
t = pop_integer();
if (t < 1 || t > LVALUE->u.tensor->dim[i])
stop("error in indexed assign");
k = k * p1->u.tensor->dim[i] + t - 1;
}
for (i = m; i < ndim; i++)
k = k * p1->u.tensor->dim[i] + 0;
// copy
TMP = alloc_tensor(LVALUE->u.tensor->nelem);
TMP->u.tensor->ndim = LVALUE->u.tensor->ndim;
for (i = 0; i < p1->u.tensor->ndim; i++)
TMP->u.tensor->dim[i] = LVALUE->u.tensor->dim[i];
for (i = 0; i < p1->u.tensor->nelem; i++)
TMP->u.tensor->elem[i] = LVALUE->u.tensor->elem[i];
LVALUE = TMP;
if (ndim == m) {
if (istensor(RVALUE))
stop("error in indexed assign");
LVALUE->u.tensor->elem[k] = RVALUE;
tos -= n;
push(LVALUE);
restore();
return;
}
// see if the rvalue matches
if (!istensor(RVALUE))
stop("error in indexed assign");
if (ndim - m != RVALUE->u.tensor->ndim)
stop("error in indexed assign");
for (i = 0; i < RVALUE->u.tensor->ndim; i++)
if (LVALUE->u.tensor->dim[m + i] != RVALUE->u.tensor->dim[i])
stop("error in indexed assign");
// copy rvalue
for (i = 0; i < RVALUE->u.tensor->nelem; i++)
LVALUE->u.tensor->elem[k + i] = RVALUE->u.tensor->elem[i];
tos -= n;
push(LVALUE);
restore();
}
#if SELFTEST
static char *s[] = {
"A=((A11,A12),(A21,A22))",
"",
"A[1,1]",
"A11",
"A[1,2]",
"A12",
"A[2,1]",
"A21",
"A[2,2]",
"A22",
"A[1]",
"(A11,A12)",
"A[2]",
"(A21,A22)",
"A[1]=(B11,B12)",
"",
"A",
"((B11,B12),(A21,A22))",
"A[2]=(B21,B22)",
"",
"A",
"((B11,B12),(B21,B22))",
"A=((0,0),(0,0))",
"",
"A[1,1]",
"0",
// index of scalar ok
"1[2]",
"1",
};
void
test_index(void)
{
test(__FILE__, s, sizeof s / sizeof (char *));
}
#endif