187 lines
3.5 KiB
CoffeeScript
187 lines
3.5 KiB
CoffeeScript
|
|
|
|
# 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.
|
|
|
|
# called by Eval_index
|
|
index_function = (n) ->
|
|
i = 0
|
|
k = 0
|
|
m = 0
|
|
ndim = 0
|
|
nelem = 0
|
|
t = 0
|
|
|
|
save()
|
|
s = tos - n
|
|
p1 = stack[s]
|
|
|
|
|
|
ndim = p1.tensor.ndim
|
|
|
|
m = n - 1
|
|
|
|
if (m > ndim)
|
|
stop("too many indices for tensor")
|
|
|
|
k = 0
|
|
|
|
for i in [0...m]
|
|
push(stack[s + i + 1])
|
|
t = pop_integer()
|
|
if (t < 1 || t > p1.tensor.dim[i])
|
|
stop("index out of range")
|
|
k = k * p1.tensor.dim[i] + t - 1
|
|
|
|
if (ndim == m)
|
|
moveTos tos - n
|
|
push(p1.tensor.elem[k])
|
|
restore()
|
|
return
|
|
|
|
for i in [m...ndim]
|
|
k = k * p1.tensor.dim[i] + 0
|
|
|
|
nelem = 1
|
|
|
|
for i in [m...ndim]
|
|
nelem *= p1.tensor.dim[i]
|
|
|
|
p2 = alloc_tensor(nelem)
|
|
|
|
p2.tensor.ndim = ndim - m
|
|
|
|
for i in [m...ndim]
|
|
p2.tensor.dim[i - m] = p1.tensor.dim[i]
|
|
|
|
for i in [0...nelem]
|
|
p2.tensor.elem[i] = p1.tensor.elem[k + i]
|
|
|
|
check_tensor_dimensions p1
|
|
check_tensor_dimensions p2
|
|
|
|
moveTos 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
|
|
|
|
set_component = (n) ->
|
|
i = 0
|
|
k = 0
|
|
m = 0
|
|
ndim = 0
|
|
t = 0
|
|
|
|
save()
|
|
|
|
if (n < 3)
|
|
stop("error in indexed assign")
|
|
|
|
s = tos - n
|
|
|
|
p2 = stack[s]; # p2 is RVALUE
|
|
|
|
p1 = stack[s+1]; # p1 is LVALUE
|
|
|
|
if (!istensor(p1)) # p1 is LVALUE
|
|
stop("error in indexed assign: assigning to something that is not a tensor")
|
|
|
|
ndim = p1.tensor.ndim; # p1 is LVALUE
|
|
|
|
m = n - 2
|
|
|
|
if (m > ndim)
|
|
stop("error in indexed assign")
|
|
|
|
k = 0
|
|
|
|
for i in [0...m]
|
|
push(stack[ s + i + 2])
|
|
t = pop_integer()
|
|
if (t < 1 || t > p1.tensor.dim[i]) # p1 is LVALUE
|
|
stop("error in indexed assign\n")
|
|
k = k * p1.tensor.dim[i] + t - 1
|
|
|
|
for i in [m...ndim]
|
|
k = k * p1.tensor.dim[i] + 0
|
|
|
|
# copy
|
|
|
|
p3 = alloc_tensor(p1.tensor.nelem); # p1 is LVALUE # p3 is TMP
|
|
|
|
p3.tensor.ndim = p1.tensor.ndim; # p1 is LVALUE # p3 is TMP
|
|
|
|
for i in [0...p1.tensor.ndim]
|
|
p3.tensor.dim[i] = p1.tensor.dim[i]; # p1 is LVALUE # p3 is TMP
|
|
|
|
for i in [0...p1.tensor.nelem]
|
|
p3.tensor.elem[i] = p1.tensor.elem[i]; # p1 is LVALUE # p3 is TMP
|
|
|
|
check_tensor_dimensions p1
|
|
check_tensor_dimensions p3
|
|
|
|
p1 = p3; # p1 is LVALUE # p3 is TMP
|
|
|
|
if (ndim == m)
|
|
if (istensor(p2)) # p2 is RVALUE
|
|
stop("error in indexed assign")
|
|
p1.tensor.elem[k] = p2; # p1 is LVALUE # p2 is RVALUE
|
|
|
|
check_tensor_dimensions p1
|
|
|
|
moveTos tos - n
|
|
push(p1); # p1 is LVALUE
|
|
restore()
|
|
return
|
|
|
|
|
|
# see if the rvalue matches
|
|
|
|
if (!istensor(p2)) # p2 is RVALUE
|
|
stop("error in indexed assign")
|
|
|
|
if (ndim - m != p2.tensor.ndim) # p2 is RVALUE
|
|
stop("error in indexed assign")
|
|
|
|
for i in [0...p2.tensor.ndim] # p2 is RVALUE
|
|
if (p1.tensor.dim[m + i] != p2.tensor.dim[i]) # p1 is LVALUE # p2 is RVALUE
|
|
stop("error in indexed assign")
|
|
|
|
# copy rvalue
|
|
|
|
for i in [0...p2.tensor.nelem] # p2 is RVALUE
|
|
p1.tensor.elem[k + i] = p2.tensor.elem[i]; # p1 is LVALUE # p2 is RVALUE
|
|
|
|
check_tensor_dimensions p1
|
|
check_tensor_dimensions p2
|
|
|
|
moveTos tos - n
|
|
|
|
push(p1); # p1 is LVALUE
|
|
|
|
restore()
|
|
|