1 ;;; -*- Mode: Lisp; Package: Maxima; Syntax: Common-Lisp; Base: 10 -*- ;;;;
2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3 ;;; The data in this file contains enhancments. ;;;;;
5 ;;; Copyright (c) 1984,1987 by William Schelter,University of Texas ;;;;;
6 ;;; All rights reserved ;;;;;
7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8 ;;; (c) Copyright 1980 Massachusetts Institute of Technology ;;;
9 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12 (macsyma-module linnew
)
14 ;; This is a matrix package which uses minors, basically.
15 ;; TMLINSOLVE(LIST-OF-EQUAIONS,LIST-OF-VARIABLES,LIST-OF-VARIABLES-TO-BE-OBTAINED)
16 ;; solves the linear equation. LIST-OF-VARIABLES-TO-BE-OBTAINED can be omitted,
17 ;; in which case all variables are obtained. TMNEWDET(MATRIX,DIMENSION)
18 ;; computes the determinant. DIMENSION can be omitted. The default is
19 ;; DIMENSION=(declared dimension of MATRIX). TMINVERSE(MATRIX) computes the
22 ;; The program uses hash arrays to remember the minors if N > threshold. If
23 ;; $WISE is set to T, the program knocks out unnecessary elements. But also it
24 ;; kills necessary ones in the case of zero elements! The $WISE flag should
25 ;; not be set to T for inverse. The default of $WISE is NIL.
27 ;; There seem to have been a number of bugs in this code. I changed
28 ;; the array referencing to value cell, and some of the stuff about
29 ;; cre form. It now seems tminverse and tmlinsolve, now seem to work. --wfs.
32 (declare-top (special *tmarrays
* *a2
* *b
* *aa
* *row
* *col
* *rowinv
* *colinv
* *indx
*))
34 (declare-top (special n nx ix
))
36 (declare-top (special $linenum $dispflag $linechar $wise $fool
))
38 (defvar *tmarrays
* nil
)
40 ;; If N < threshold declared array is used, otherwise hashed array.
42 (defparameter *threshold
* 10)
44 (defun tminitialflag nil
45 (unless (boundp '$wise
) (setq $wise nil
))
46 (unless (boundp '$fool
) (setq $fool nil
)))
48 ;; TMDET returns the determinant of N*N matrix A2 which is in an globally
58 (setq index
(nreverse index
))
59 (tminor a4 n
1 index
0)))
61 ;; TMLIN SOLVES M SETS OF LINEAR EQUATIONS WITH N UNKNOWN VARIABLES. IT SOLVES
62 ;; ONLY FOR THE FIRST NX UNKNOWNS OUT OF N. THE EQUATIONS ARE EXPRESSED IN
63 ;; MATRIX FORM WHICH IS IN N*(N+M) ARRAY A2. AS USUAL , THE LEFT HAND SIDE N*N
64 ;; OF A2 REPRESENTS THE COEFFICIENT MATRIX, AND NEXT N*M OF A2 IS THE RIGHT
65 ;; HAND SIDE OF THE M SETS OF EQUATIONS. SUPPOSE N=3, M=2, AND THE UNKKNOWNS
66 ;; ARE (X1 Y1 Z1) FOR THE FIRST SET AND (X2 Y2 Z2) FOR THE SECOND. THEN THE
67 ;; RESULT OF TMLIN IS ((DET) (U1 U2) (V1 V2) (W1 W2)) WHERE DET IS THE
68 ;; DETERMINANT OF THE COEFFICIENT MATRIX AND X1=U1/DET, X2=U2/DET, Y1=V1/DET,
71 (defun tmlin (a4 n m nx
)
78 (setq index
(reverse index
))
82 ((> ix nx
) (reverse result
))
83 (push (do ((i 1 (1+ i
)) (res))
84 ((> i
(if (= ix
0) 1 m
))
86 (unless $wise
(tmkillarray ix
))
87 (push (tminor a4 n
1 index i
) res
))
89 (when (and (= ix
0) (equal (car result
) '(0 .
1)))
90 (merror (intl:gettext
"tmlin: coefficient matrix is singular.")))))
94 ;; TMINOR ACTUALLY COMPUTES THE MINOR DETERMINANT OF A SUBMATRIX OF A2, WHICH
95 ;; IS CONSTRUCTED BY EXTRACTING ROWS (K,K+1,K+2,...,N) AND COLUMNS SPECIFIED BY
96 ;; INDEX. N IS THE DIMENSION OF THE ORIGINAL MATRIX A2. WHEN TMINOR IS USED
97 ;; FOR LINEAR EQUATION PROGRAM, JRIGHT SPECIFIES A COLUMN OF THE CONSTANT
98 ;; MATRIX WHICH IS PLUGED INTO AN IX-TH COLUMN OF THE COEFFICIENT MATRIX FOR
99 ;; ABTAINING IX-TH UNKNOWN. IN OTHER WORDS, JRIGHT SPECIFIES JRIGHT-TH
102 (defun tminor (a4 n k index jright
)
103 (prog (subindx l result name aorb
)
104 (setq a4
(get-array-pointer a4
))
108 (aref a4
(car index
) (+ jright n
))
109 (aref a4
(car index
) k
))))
114 ((> j
(1+ (- n k
))) (setq result sum
))
115 (setq l
(extract index j
))
116 (setq subindx
(cadr l
))
118 (setq aorb
(if (= k ix
)
119 (aref a4 l
(+ jright n
))
121 (unless (equal aorb
'(0 .
1))
122 (setq name
(tmaccess subindx
))
124 (funcall (if (oddp j
) #'ratplus
#'ratdifference
)
129 (tminor a4 n
(1+ k
) subindx jright
)
130 (cond ((not (null (tmeval name
)))
134 (tminor a4 n
(1+ k
) subindx jright
))
136 (tmstore name
(tminor a4 n
(1+ k
) subindx jright
)))))
139 (when (tmnomoreuse j l k
)
140 (tmkill subindx k
))))))
143 (defun extract (index j
)
144 (do ((ind index
(cdr ind
))
149 (return (list (car ind
) (nconc subindx
(cdr ind
))))
150 (setq subindx
(nconc subindx
(list (car ind
)))))))
152 (declare-top (special vlist varlist genvar
))
154 (defun tmratconv (bbb n m
)
156 (declare (special ccc
)) ;Tell me this worked in Maclisp. --gsb
157 ;Actually, i suspect it didn't, at least ever since
159 (setf (symbol-value 'ccc
) bbb
)
164 (newvar1 (setf (aref *a2
* k j
)
166 ;; (nth j (nth k *a2*))
167 ;; (MEVAL (LIST (LIST 'CCC 'array) K J)) ;;just the
170 (newvar (cons '(mtimes) vlist
))
175 (setf (aref *a2
* k j
) (cdr (ratrep* (aref *a2
* k j
))))))))
177 (defmfun $tmnewdet
(mat &optional
(dim nil dim?
))
178 (prog (*aa
* r vlist n
)
180 (unless (integerp dim
)
181 (merror (intl:gettext
"tmnewdet: second argument must be an integer; found: ~M") dim
))
184 (setq n
(length (cdr mat
))))
186 (merror (intl:gettext
"tmnewdet: first argument must be a matrix; found: ~M") mat
)))
188 (setq *a2
* (make-array (list (1+ n
) (1+ n
)) :initial-element nil
))
191 (setq r
(cons (list 'mrat
'simp varlist genvar
) (tmdet '*a2
* n
)))
195 (defmfun $tmlinsolve
(&rest arglist
)
196 (prog (equations vars outvars result
*aa
*)
197 (setq equations
(cdar arglist
)
199 outvars
(cond ((null (cddr arglist
)) vars
)
200 (t (cdaddr arglist
))))
201 (setq vars
(tmerge vars outvars
))
202 (setq nx
(length outvars
))
203 (setq n
(length vars
))
204 (unless (= n
(length equations
))
205 (return (print 'too-few-or-much-equations
)))
207 (cons '($matrix simp
)
208 (mapcar #'(lambda (exp)
211 (mapcar #'(lambda (v)
213 (setq exp
($bothcoef exp v
)
215 exp
(meval (caddr exp
)))
218 (list (list '(mminus) exp
))))
219 (mapcar #'(lambda (e)
220 (meval (list '(mplus)
222 (list '(mminus) ($rhs e
)))))
224 (setq result
(cdr ($tmlin
*aa
* n
1 nx
)))
226 (do ((vars (cons nil outvars
) (cdr vars
))
231 (cons '(mlist) (cdr (reverse labels
))))
232 (setq name
(makelabel $linechar
))
234 (setf (symbol-value name
)
235 (cond ((null (car vars
))
242 (list '(mexpt simp
) dlabel -
1))))))
244 (setq result
(cdr result
))
246 (mtell-open "~M" (nconc (ncons '(mlabel))
248 (ncons (eval name
)))))))))
250 (defun tmerge (vars outvars
)
253 (mapcar #'(lambda (v)
254 (if (member v outvars
) nil
(push v l
)))
256 (return (reverse l
)))))
258 (defmfun $tmlin
(*aa
* n m nx
)
260 (setq *a2
* (make-array (list (1+ n
) (+ 1 m n
)) :initial-element nil
))
262 (tmratconv *aa
* n
(+ m n
))
268 (mapcar #'(lambda (result)
269 (cons (list 'mrat
'simp varlist genvar
) result
))
271 (tmlin '*a2
* n m nx
))))
275 (defun tmkill (*indx
* k
)
276 (prog (name subindx j l
)
277 (when (null *indx
*) (return nil
))
278 (setq name
(tmaccess *indx
*))
279 (cond ((not (null (tmeval name
)))
282 (do ((ind *indx
* (cdr ind
))
283 (count 1 (1+ count
)))
285 (setq l
(extract *indx
* count
)
289 (tmkill subindx
(1+ k
))))))))
291 (defun tmnomoreuse (j l k
)
292 (if (and (= j l
) (or (> k nx
) (< k
(1+ ix
))))
296 (defun tmdefarray (n)
298 (cond ((setq *tmarrays
* (get-array-pointer *tmarrays
*))
299 (tmrearray (1- (cond ((cadr (arraydims *tmarrays
*)))
301 (setq *tmarrays
* (make-array (1+ n
) :initial-element nil
))
304 (setq name
(if (= i
1) (make-symbol "M") (gensym)))
305 (cond ((< n
*threshold
*)
306 (setf (symbol-value name
) (make-array (1+ (tmcombi n i
)) :initial-element nil
))
307 (setf (aref *tmarrays
* i
) (get-array-pointer name
)))
309 (setf (aref *tmarrays
* i
) (list name
'simp
'array
)))))
312 ;; TMREARRAY kills the TMARRAYS which holds pointers to minors. If (TMARRAYS I)
313 ;; is an atom, it is declared array. Otherwise it is hashed array.
319 (unless (atom (aref *tmarrays
* i
))
320 (tm$kill
(car (aref *tmarrays
* i
)))))))
322 (defun tmaccess (index)
324 (cond ($fool
(return nil
)))
325 (setq l
(length index
))
327 (cond ((< n
*threshold
*)
328 (list 'aref
(aref *tmarrays
* l
)
334 (do ((j (1+ x
) (1+ j
)))
336 (incf sum
(tmcombi (- n j
) (- l i
)))))))
337 (t (cons 'aref
(cons (aref *tmarrays
* l
) index
)))))) )
341 (/ (tmfactorial n
(- n i
)) (tmfactorial i
0))
342 (/ (tmfactorial n i
) (tmfactorial (- n i
) 0))))
344 (defun tmfactorial (i j
)
347 (* i
(tmfactorial (1- i
) j
))))
349 (defun tmstore (name x
)
350 (cond ((< n
*threshold
*)
351 (eval `(setf ,name
',x
)))
353 (mset name
(list '(mquote simp
) x
))
356 ;; TMKILLARRAY kills all (N-IX+1)*(N-IX+1) minors which are not necessary for
357 ;; the computation of IX-TH variable in the linear equation. Otherwise, they
360 (defun tmkillarray (ix)
361 (do ((i (1+ (- n ix
)) (1+ i
)))
363 (if (< n
*threshold
*)
364 (fillarray (aref *tmarrays
* i
) '(nil))
365 (tm$kill
(car (aref *tmarrays
* i
))))))
369 (return (cond ((< n
*threshold
*)
372 (setq result
(meval e
))
373 (if (equal result e
) nil
(cadr result
)))))))
378 (defmfun $tminverse
(*aa
*)
379 (prog (r vlist n m nx
)
380 (setq n
(length (cdr *aa
*)) m n nx n
)
381 (setq *a2
* (make-array (list (1+ n
) (+ 1 m n
)) :initial-element nil
))
387 (setf (aref *a2
* i
(+ n j
))
388 (if (= i j
) '(1 .
1) '(0 .
1)))))
389 (setq r
(mapcar #'(lambda (res)
391 (mapcar #'(lambda (result)
392 ($ratdisrep
(cons (list 'mrat
'simp varlist genvar
) result
)))
394 (tmlin '*a2
* n m nx
)))
395 (setq r
(list '(mtimes simp
)
396 (list '(mexpt simp
) (cadar r
) -
1)
397 (cons '($matrix simp
) (cdr r
))))
400 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
401 ;;THIS IS A UTILITY PACKAGE FOR SPARSE
402 ;;MATRIX INVERSION. A3 IS A N*N MATRIX.
403 ;;IT RETURNS A LIST OF LISTS, SUCH AS
404 ;;((I1 I2 ...) (J1 J2...) ...) WHERE (I1
405 ;;I2 ..) SHOWS THE ROWS WHICH BELONGS TO
406 ;;THE FIRST BLOCK, AND SO ON. THE ROWS
407 ;;SHOUD BE REORDERED IN THIS ORDER. THE
408 ;;COLUMNS ARE NOT CHANGED. IT RETURNS NIL
409 ;;IF A3 IS "OBVIOUSLY" SINGULAR.
411 ;; (DEFUN TMISOLATE (A3 N)
413 ;; (SETQ A3 (GET A3 'ARRAY))
414 ;; (setq B (*ARRAY nil 'T (1+ N) (1+ N)))
415 ;; (setq ROW (*ARRAY nil 'T (1+ N)))
416 ;; (setq COL (*ARRAY nil 'T (1+ N)))
417 ;; (DO ((I 1 (1+ I)))
420 ;; (STORE (COL I) I))
421 ;; (DO ((I 1 (1+ I)))
423 ;; (DO ((J 1 (1+ J)))
426 ;; (NOT (EQUAL (AREF A3 I J)
428 ;; (COND ((NULL (TMPIVOT-ISOLATE 1))
429 ;; (SETQ NODELIST NIL)
431 ;; (DO ((I 1 (1+ I)))
433 ;; (DO ((J 1 (1+ J)))
435 ;; (STORE (B (ROW J) (COL I))
436 ;; (OR (B (ROW I) (COL J))
437 ;; (B (ROW J) (COL I))))
438 ;; (STORE (B (ROW I) (COL J)) (B (ROW J) (COL I))))
439 ;; (STORE (B (ROW I) (COL I)) T))
440 ;; (DO ((I 1 (1+ I)))
442 ;; (COND ((EQ (B (ROW I) (COL I)) T)
444 ;; (CONS (TMPULL-OVER I N) NODELIST)))))
449 ;; (RETURN (REVERSE NODELIST)))))
451 ;; (DEFUN TMPULL-OVER (P N)
453 ;; (STORE (B (ROW P) (COL P)) NIL)
454 ;; (DO ((J 1 (1+ J)))
455 ;; ((> J N) (SETQ Q NIL))
456 ;; (COND ((EQ (B (ROW P) (COL J)) T)
457 ;; (RETURN (SETQ Q J)))))
458 ;; (COND ((NULL Q) (RETURN (LIST (ROW P))))
459 ;; (T (DO ((J 1 (1+ J)))
461 ;; (STORE (B (ROW Q) (COL J))
462 ;; (OR (B (ROW Q) (COL J))
463 ;; (B (ROW P) (COL J))))
464 ;; (STORE (B (ROW J) (COL Q))
465 ;; (B (ROW Q) (COL J))))
467 ;; (RETURN (CONS (ROW P) (TMPULL-OVER Q N)))))))
470 ;; (DO ((I 1 (1+ I)))
472 ;; (STORE (B (ROW P) (COL I)) NIL)
473 ;; (STORE (B (ROW I) (COL P)) NIL)))
475 ;;TMPIVOT-ISOLATE CARRIES OUT PIVOTTING
476 ;;SO THAT THE ALL DIAGONAL ELEMENTS ARE
477 ;;NONZERO. THIS GARANTIES WE HAVE MAXIMUM
478 ;;NUMBER OF BLOCKS ISOLATED.
480 (defun tmpivot-isolate (k)
482 (t (do ((i k
(1+ i
)))
484 (when (aref *b
* (aref *row
* i
) (aref *col
* k
))
485 (tmexchange '*row
* k i
)
486 (if (tmpivot-isolate (1+ k
))
488 (tmexchange '*row
* k i
)))))))
490 (defun tmexchange (rowcol i j
)
492 (setq rowcol
(get-array-pointer rowcol
))
493 (setq dummy
(aref rowcol i
))
494 (setf (aref rowcol i
) (aref rowcol j
))
495 (setf (aref rowcol j
) dummy
)))
498 ;; PROGRAM TO PREDICT ZERO ELEMENTS IN
499 ;; THE SOLUTION OF INVERSE OR LINEAR
500 ;; EQUATION. A IS THE COEFFICIENT MATRIX.
501 ;; B IS THE RIGHT HAND SIDE MATRIX FOR
502 ;; LINEAR EQUATIONS. A3 IS N*N AND B IS
503 ;; M*M. X IS AN N*M MATRIX WHERE T -NIL
504 ;; PATTERN SHOWING THE ZERO ELEMENTS IN
505 ;; THE RESULT IS RETURNED. T CORRESPONDS TO
506 ;; NON-ZERO ELEMENT. IN THE CASE OF
507 ;; INVERSE, YOU CAN PUT ANYTHING (SAY,NIL)
508 ;; FOR B AND 0 FOR M. NORMALLY IT RETURNS
509 ;; T, BUT IN CASE OF SINGULAR MATRIX, IT
512 ;; (DEFUN TMPREDICT (A3 B X N M)
513 ;; (PROG (FLAGINV FLAG-NONSINGULAR)
514 ;; (SETQ A3 (GET A3 'ARRAY) B (GET B 'ARRAY) X (GET X 'ARRAY))
515 ;; (setq AA (*ARRAY nil 'T (1+ N) (1+ N)))
516 ;; (setq ROW (*ARRAY nil 'T (1+ N)))
517 ;; (SETQ FLAGINV (= M 0))
518 ;; (COND (FLAGINV (SETQ M N)))
519 ;; (DO ((I 1 (1+ I)))
521 ;; (DO ((J 1 (1+ J)))
524 ;; (NOT (EQUAL (AREF A3 I J) '(0 . 1))))))
525 ;; (DO ((I 1 (1+ I)))
527 ;; (DO ((J 1 (1+ J)))
529 ;; (STORE (AREF X I J)
530 ;; (COND (FLAGINV (EQ I J))
531 ;; (T (EQUAL (AREF B I J)
533 ;; (DO ((I 1 (1+ I))) ((> I N)) (STORE (ROW I) I))
534 ;; ;FORWARD ELIMINATION.
535 ;; (DO ((I 1 (1+ I)))
537 ;; (SETQ FLAG-NONSINGULAR
538 ;; (DO ((II I (1+ II)))
540 ;; (COND ((AA (ROW II) I)
541 ;; (TMEXCHANGE 'ROW II I)
543 ;; (COND ((NULL FLAG-NONSINGULAR) (RETURN NIL)))
544 ;; (DO ((II (1+ I) (1+ II)))
546 ;; (COND ((AA (ROW II) I)
547 ;; (DO ((JJ (1+ I) (1+ JJ)))
549 ;; (STORE (AA (ROW II) JJ)
550 ;; (OR (AA (ROW I) JJ)
551 ;; (AA (ROW II) JJ))))
552 ;; (DO ((JJ 1 (1+ JJ)))
554 ;; (STORE (AREF X (ROW II) JJ)
555 ;; (OR (AREF X (ROW I) JJ)
556 ;; (AREF X (ROW II) JJ))))))))
557 ;; (COND ((NULL FLAG-NONSINGULAR) (GO EXIT))) ;GET OUT BACKWARD SUBSTITUTION
558 ;; (DO ((I (1- N) (1- I)))
560 ;; (DO ((L 1 (1+ L)))
562 ;; (STORE (AREF X (ROW I) L)
563 ;; (OR (AREF X (ROW I) L)
564 ;; (DO ((J (1+ I) (1+ J)) (SUM))
568 ;; (AND (AA (ROW I) J)
573 ;; ;RECOVER THE ORDER.
574 ;; (TMPERMUTE 'X N M 0 0 'ROW N 'ROW)
575 ;; EXIT (*TMREARRAY 'ROW) (*TMREARRAY 'AA) (RETURN FLAG-NONSINGULAR)))
577 ;;TMPERMUTE PERMUTES THE ROWS OR COLUMNS
578 ;;OF THE N*M MATRIX AX ACCORDING TO THE
579 ;;SPECIFICATION OF INDEXLIST. THE FLAG
580 ;;MUST BE SET 'ROW IF ROW PERMUTATION IS
581 ;;DESIRED , OR 'COL OTHERWISE. THE RESULT
582 ;;IS IN AX. NM IS THE DIMENSION OF
585 (defun tmpermute (ax n m rbias cbias indexlist nm flag
)
587 ;; (SETQ AX (GET AX 'array)
588 ;; INDEXLIST (GET INDEXLIST 'array))
589 (setq ax
(get-array-pointer ax
))
590 (setq indexlist
(get-array-pointer indexlist
))
591 (setf (symbol-array *indx
*) (make-array (1+ nm
) :initial-element nil
))
594 (setf (aref *indx
* i
) (aref indexlist i
)))
597 (cond ((not (= (aref *indx
* i
) i
))
599 (tmmove ax n m rbias cbias i
0 flag
)
601 loop
(setq k
(aref *indx
* l
))
602 (setf (aref *indx
* l
) l
)
604 (tmmove ax n m rbias cbias
0 l flag
))
605 (t (tmmove ax n m rbias cbias k l flag
)
609 (defun tmmove (ax n m rbias cbias i j flag
)
611 (setq ax
(get-array-pointer ax
))
612 (setq ll
(if (eq flag
'*row
*)
617 (cond ((eq flag
'*row
*)
618 (setf (aref ax
(+ rbias j
) (+ cbias k
))
619 (aref ax
(+ rbias i
) (+ cbias k
))))
620 (t (setf (aref ax
(+ rbias k
) (+ cbias j
))
621 (aref ax
(+ rbias k
) (+ cbias i
))))))))
623 ;;TMSYMETRICP CHECKS THE SYMMETRY OF THE MATRIX.
625 (defun tmsymetricp (a3 n
)
626 (setq a3
(get-array-pointer a3
))
629 (cond ((null (do ((j (1+ i
) (1+ j
)))
631 (unless (equal (aref a3 i j
) (aref a3 j i
))
635 ;;TMLATTICE CHECKS THE "LATTICE"
636 ;;STRUCTURE OF THE MATRIX A. IT RETURNS
637 ;;NIL IF THE MATRIX IS "OBVIOUSLY"
638 ;;SINGULAR. OTHERWISE IT RETURNS A LIST
639 ;;(L1 L2 ... LM) WHERE M IS THE NUMBER OF
640 ;;BLOCKS (STRONGLY CONNECTED SUBGRAPHS),
641 ;;AND L1 L2 ... ARE LIST OF ROW AND
642 ;;COLUMN NUBERS WHICH BELONG TO EACH
643 ;;BLOCKS. THE LIST LOOKS LIKE ((R1 C1)
644 ;;(R2 C2) ...) WHERE R R'S ARE ROWS AND
647 (defun tmlattice (a3 xrow xcol n
)
648 (setq a3
(get-array-pointer a3
))
649 (setq xrow
(get-array-pointer xrow
))
650 (setq xcol
(get-array-pointer xcol
))
651 (setq *b
* (make-array (list (1+ n
) (1+ n
)) :initial-element nil
))
652 (setq *row
* (make-array (1+ n
) :initial-element nil
))
653 (setq *col
* (make-array (1+ n
) :initial-element nil
))
659 (not (equal (aref a3 i j
) '(0 .
1))))))
662 (setf (aref *row
* i
) i
)
663 (setf (aref *col
* i
) i
))
664 (when (null (tmpivot-isolate 1))
665 (return-from tmlattice nil
))
668 (setf (aref *b
* (aref *row
* i
) (aref *col
* i
)) i
)
669 (setf (aref *b
* (aref *row
* i
) (aref *col
* 0)) t
))
671 (tmsort-lattice xrow xcol
))
673 (defun tmlattice1 (k)
680 (if (setq looppath
(tmpathp k k
))
681 (tmunify-loop k
(cdr looppath
))
685 (cond ((equal (aref *b
* (aref *row
* j
) (aref *col
* k
)) t
)
688 (do ((jj k
(1+ jj
)) (path))
690 (when (and (equal (aref *b
* (aref *row
* j
) (aref *col
* jj
)) t
)
691 (setq path
(tmpathp jj k
)))
692 (return (cons j path
)))))))
694 (defun tmunify-loop (k chain
)
695 (prog (l dummyk dummyl
)
697 (cond ((= l k
) (return nil
)))
698 (setq dummyk
(aref *b
* (aref *row
* k
) (aref *col
* k
)))
699 (setq dummyl
(aref *b
* (aref *row
* l
) (aref *col
* l
)))
700 (setf (aref *b
* (aref *row
* k
) (aref *col
* k
)) nil
)
701 (setf (aref *b
* (aref *row
* l
) (aref *col
* l
)) nil
)
704 (setf (aref *b
* (aref *row
* k
) (aref *col
* i
))
705 (or (aref *b
* (aref *row
* k
) (aref *col
* i
)) (aref *b
* (aref *row
* l
) (aref *col
* i
))))
706 (setf (aref *b
* (aref *row
* i
) (aref *col
* k
))
707 (or (aref *b
* (aref *row
* i
) (aref *col
* k
)) (aref *b
* (aref *row
* i
) (aref *col
* l
))))
708 (setf (aref *b
* (aref *row
* l
) (aref *col
* i
)) nil
)
709 (setf (aref *b
* (aref *row
* i
) (aref *col
* l
)) nil
))
710 (setf (aref *b
* (aref *row
* k
) (aref *col
* k
)) dummyl
)
711 (setf (aref *b
* (aref *row
* l
) (aref *col
* l
)) dummyk
)
712 (setf (aref *b
* (aref *row
* k
) (aref *col
* 0)) t
)
713 (setf (aref *b
* (aref *row
* l
) (aref *col
* 0)) nil
)
714 (tmunify-loop k
(cdr chain
))))
716 (defun tmsort-lattice (xrow xcol
)
717 (prog (nodelist result
)
718 (setq nodelist
(tmsort1))
720 (do ((x nodelist
(cdr x
)) (result))
723 (cons (do ((next (aref *b
* (aref *row
* (car x
)) (aref *col
* (car x
)))
724 (aref *b
* (aref *row
* next
) (aref *col
* next
)))
727 (cons (list (aref *row
* next
) (aref *col
* next
)) res
))
728 (push (list (aref *row
* next
) (aref *col
* next
)) res
))
730 (do ((list1 result
(cdr list1
))
733 (do ((list2 (car list1
) (cdr list2
)))
735 (setf (aref xrow i
) (caar list2
))
736 (setf (aref xcol i
) (cadar list2
))
740 ;; (DEFUN TMLESS (I J) (B (ROW I) (COL J)))
746 (cond ((and (aref *b
* (aref *row
* i
) (aref *col
* 0)) (tmmaxp i
))
750 (setf (aref *b
* (aref *row
* i
) (aref *col
* j
)) nil
)))
751 (setf (aref *b
* (aref *row
* i
) (aref *col
* 0)) nil
)
758 (when (and (not (= i j
)) (aref *b
* (aref *row
* j
) (aref *col
* i
)))
761 ;;UNPIVOT IS USED IN PAUL WANG'S PROGRAM
762 ;;TO RECOVER THE PIVOTTING. TO GET THE
763 ;;INVERSE OF A, PAUL'S PROGRAM COMPUTES
764 ;;THE INVERSE OF U*A*V BECAUSE OF
765 ;;BLOCKING. LET THE INVERSE Y. THEN
766 ;;A^^-1=V*Y*U. WHERE U AND V ARE
767 ;;FUNDAMENTAL TRANSFORMATION
768 ;;(PERMUTATION). UNPIVOT DOES THIS,
769 ;;NAMELY, GIVEN A MATRIX A3, INDEX ROW
770 ;;AND COL ,WHICH CORRESPONDS TO THE Y , U
771 ;; AND V, RESPECTIVELY, IT COMPUTES V*Y*U
772 ;;AND RETURNS IT TO THE SAME ARGUMENT A.
774 (defun tmunpivot (a3 *row
* *col
* n m
)
776 (setq *col
* (get-array-pointer *col
*))
777 (setq *row
* (get-array-pointer *row
*))
778 (setq *rowinv
* (make-array (1+ n
) :initial-element nil
))
779 (setq *colinv
* (make-array (1+ n
) :initial-element nil
))
782 (setf (aref *rowinv
* (aref *row
* i
)) i
))
785 (setf (aref *colinv
* (aref *col
* i
)) i
))
786 (tmpermute a3 n m
0 n
'*colinv
* n
'*row
*)
787 (tmpermute a3 n m
0 n
'*rowinv
* n
'*col
*)))
789 (declare-top (unspecial n vlist nx ix
))