1 // Contract across tensor indices
11 if (cddr(p1
) == symbol(NIL
)) {
34 int h
, i
, j
, k
, l
, m
, n
, ndim
, nelem
;
35 int ai
[MAXDIM
], an
[MAXDIM
];
44 stop("contract: tensor expected, 1st arg is not a tensor");
55 ndim
= p1
->u
.tensor
->ndim
;
57 if (l
< 1 || l
> ndim
|| m
< 1 || m
> ndim
|| l
== m
58 || p1
->u
.tensor
->dim
[l
- 1] != p1
->u
.tensor
->dim
[m
- 1])
59 stop("contract: index out of range");
64 n
= p1
->u
.tensor
->dim
[l
];
66 // nelem is the number of elements in "b"
69 for (i
= 0; i
< ndim
; i
++)
71 nelem
*= p1
->u
.tensor
->dim
[i
];
73 p2
= alloc_tensor(nelem
);
75 p2
->u
.tensor
->ndim
= ndim
- 2;
78 for (i
= 0; i
< ndim
; i
++)
80 p2
->u
.tensor
->dim
[j
++] = p1
->u
.tensor
->dim
[i
];
82 a
= p1
->u
.tensor
->elem
;
83 b
= p2
->u
.tensor
->elem
;
85 for (i
= 0; i
< ndim
; i
++) {
87 an
[i
] = p1
->u
.tensor
->dim
[i
];
90 for (i
= 0; i
< nelem
; i
++) {
92 for (j
= 0; j
< n
; j
++) {
96 for (k
= 0; k
< ndim
; k
++)
97 h
= (h
* an
[k
]) + ai
[k
];
102 for (j
= ndim
- 1; j
>= 0; j
--) {
103 if (j
== l
|| j
== m
)