123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- // Outer product of tensors
- #include "stdafx.h"
- #include "defs.h"
- void
- eval_outer(void)
- {
- p1 = cdr(p1);
- push(car(p1));
- eval();
- p1 = cdr(p1);
- while (iscons(p1)) {
- push(car(p1));
- eval();
- outer();
- p1 = cdr(p1);
- }
- }
- void
- outer(void)
- {
- save();
- p2 = pop();
- p1 = pop();
- if (istensor(p1) && istensor(p2))
- yyouter();
- else {
- push(p1);
- push(p2);
- if (istensor(p1))
- tensor_times_scalar();
- else if (istensor(p2))
- scalar_times_tensor();
- else
- multiply();
- }
- restore();
- }
- void
- yyouter(void)
- {
- int i, j, k, ndim, nelem;
- ndim = p1->u.tensor->ndim + p2->u.tensor->ndim;
- if (ndim > MAXDIM)
- stop("outer: rank of result exceeds maximum");
- nelem = p1->u.tensor->nelem * p2->u.tensor->nelem;
- p3 = alloc_tensor(nelem);
- p3->u.tensor->ndim = ndim;
- for (i = 0; i < p1->u.tensor->ndim; i++)
- p3->u.tensor->dim[i] = p1->u.tensor->dim[i];
- j = i;
- for (i = 0; i < p2->u.tensor->ndim; i++)
- p3->u.tensor->dim[j + i] = p2->u.tensor->dim[i];
- k = 0;
- for (i = 0; i < p1->u.tensor->nelem; i++)
- for (j = 0; j < p2->u.tensor->nelem; j++) {
- push(p1->u.tensor->elem[i]);
- push(p2->u.tensor->elem[j]);
- multiply();
- p3->u.tensor->elem[k++] = pop();
- }
- push(p3);
- }
- #if SELFTEST
- static char *s[] = {
- "outer(a,b)",
- "a*b",
- "outer(a,(b1,b2))",
- "(a*b1,a*b2)",
- "outer((a1,a2),b)",
- "(a1*b,a2*b)",
- "H33=hilbert(3)",
- "",
- "H44=hilbert(4)",
- "",
- "H55=hilbert(5)",
- "",
- "H3344=outer(H33,H44)",
- "",
- "H4455=outer(H44,H55)",
- "",
- "H33444455=outer(H33,H44,H44,H55)",
- "",
- "simplify(inner(H3344,H4455)-contract(H33444455,4,5))",
- "0",
- };
- void
- test_outer(void)
- {
- test(__FILE__, s, sizeof s / sizeof (char *));
- }
- #endif
|