algebrite
Version:
Computer Algebra System in Coffeescript
125 lines (97 loc) • 1.88 kB
text/coffeescript
### contract =====================================================================
Tags
----
scripting, JS, internal, treenode, general concept
Parameters
----------
a,i,j
General description
-------------------
Contract across tensor indices i.e. returns "a" summed over indices i and j.
If i and j are omitted then 1 and 2 are used.
contract(m) is equivalent to the trace of matrix m.
###
Eval_contract = ->
push(cadr(p1))
Eval()
if (cddr(p1) == symbol(NIL))
push_integer(1)
push_integer(2)
else
push(caddr(p1))
Eval()
push(cadddr(p1))
Eval()
contract()
contract = ->
save()
yycontract()
restore()
yycontract = ->
h = 0
i = 0
j = 0
k = 0
l = 0
m = 0
n = 0
ndim = 0
nelem = 0
ai = []
an = []
p3 = pop()
p2 = pop()
p1 = pop()
if (!istensor(p1))
if (!iszero(p1))
stop("contract: tensor expected, 1st arg is not a tensor")
push(zero)
return
push(p2)
l = pop_integer()
push(p3)
m = pop_integer()
ndim = p1.tensor.ndim
if (l < 1 || l > ndim || m < 1 || m > ndim || l == m \
|| p1.tensor.dim[l - 1] != p1.tensor.dim[m - 1])
stop("contract: index out of range")
l--
m--
n = p1.tensor.dim[l]
# nelem is the number of elements in "b"
nelem = 1
for i in [0...ndim]
if (i != l && i != m)
nelem *= p1.tensor.dim[i]
p2 = alloc_tensor(nelem)
p2.tensor.ndim = ndim - 2
j = 0
for i in [0...ndim]
if (i != l && i != m)
p2.tensor.dim[j++] = p1.tensor.dim[i]
a = p1.tensor.elem
b = p2.tensor.elem
for i in [0...ndim]
ai[i] = 0
an[i] = p1.tensor.dim[i]
for i in [0...nelem]
push(zero)
for j in [0...n]
ai[l] = j
ai[m] = j
h = 0
for k in [0...ndim]
h = (h * an[k]) + ai[k]
push(a[h])
add()
b[i] = pop()
for j in [(ndim - 1)..0]
if (j == l || j == m)
continue
if (++ai[j] < an[j])
break
ai[j] = 0
if (nelem == 1)
push(b[0])
else
push(p2)