123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 |
- #include "stdafx.h"
- #include "defs.h"
- static int
- check_arg(void)
- {
- if (!istensor(p1))
- return 0;
- else if (p1->u.tensor->ndim != 2)
- return 0;
- else if (p1->u.tensor->dim[0] != p1->u.tensor->dim[1])
- return 0;
- else
- return 1;
- }
- void
- inv(void)
- {
- int i, n;
- U **a;
- save();
- p1 = pop();
- if (check_arg() == 0) {
- push_symbol(INV);
- push(p1);
- list(2);
- restore();
- return;
- }
- n = p1->u.tensor->nelem;
- a = p1->u.tensor->elem;
- for (i = 0; i < n; i++)
- if (!isnum(a[i]))
- break;
- if (i == n)
- yyinvg();
- else {
- push(p1);
- adj();
- push(p1);
- det();
- p2 = pop();
- if (iszero(p2))
- stop("inverse of singular matrix");
- push(p2);
- divide();
- }
- restore();
- }
- void
- invg(void)
- {
- save();
- p1 = pop();
- if (check_arg() == 0) {
- push_symbol(INVG);
- push(p1);
- list(2);
- restore();
- return;
- }
- yyinvg();
- restore();
- }
- void
- yyinvg(void)
- {
- int h, i, j, n;
- n = p1->u.tensor->dim[0];
- h = tos;
- for (i = 0; i < n; i++)
- for (j = 0; j < n; j++)
- if (i == j)
- push(one);
- else
- push(zero);
- for (i = 0; i < n * n; i++)
- push(p1->u.tensor->elem[i]);
- decomp(n);
- p1 = alloc_tensor(n * n);
- p1->u.tensor->ndim = 2;
- p1->u.tensor->dim[0] = n;
- p1->u.tensor->dim[1] = n;
- for (i = 0; i < n * n; i++)
- p1->u.tensor->elem[i] = stack[h + i];
- tos -= 2 * n * n;
- push(p1);
- }
- #define A(i, j) stack[a + n * (i) + (j)]
- #define U(i, j) stack[u + n * (i) + (j)]
- void
- decomp(int n)
- {
- int a, d, i, j, u;
- a = tos - n * n;
- u = a - n * n;
- for (d = 0; d < n; d++) {
-
- if (equal(A(d, d), zero)) {
-
- for (i = d + 1; i < n; i++)
- if (!equal(A(i, d), zero))
- break;
- if (i == n)
- stop("inverse of singular matrix");
-
- for (j = 0; j < n; j++) {
- p2 = A(d, j);
- A(d, j) = A(i, j);
- A(i, j) = p2;
- p2 = U(d, j);
- U(d, j) = U(i, j);
- U(i, j) = p2;
- }
- }
-
- p2 = A(d, d);
- for (j = 0; j < n; j++) {
- if (j > d) {
- push(A(d, j));
- push(p2);
- divide();
- A(d, j) = pop();
- }
- push(U(d, j));
- push(p2);
- divide();
- U(d, j) = pop();
- }
-
- for (i = 0; i < n; i++) {
- if (i == d)
- continue;
-
- p2 = A(i, d);
-
- for (j = 0; j < n; j++) {
- if (j > d) {
- push(A(i, j));
- push(A(d, j));
- push(p2);
- multiply();
- subtract();
- A(i, j) = pop();
- }
- push(U(i, j));
- push(U(d, j));
- push(p2);
- multiply();
- subtract();
- U(i, j) = pop();
- }
- }
- }
- }
|