(* ---------------------------------------------------------------------------- * $Id: LINALGI.mi,v 1.6 1995/11/05 09:23:13 kredel Exp $ * ---------------------------------------------------------------------------- * This file is part of MAS. * ---------------------------------------------------------------------------- * Copyright (c) 1989 - 1992 Universitaet Passau * ---------------------------------------------------------------------------- * $Log: LINALGI.mi,v $ * Revision 1.6 1995/11/05 09:23:13 kredel * Fixed comments and code of: IVSVSUM, ISMPROD, IMDETL, IMDET, IMGELUD, IMLT. * * Revision 1.5 1994/03/11 15:43:31 pesch * Corrections by Lippold. * * Revision 1.4 1992/10/15 16:29:15 kredel * Changed rcsid variable * * Revision 1.3 1992/08/24 10:05:42 kredel * Corrected error in IMDET: wrong check for square matrix. * * Revision 1.2 1992/02/12 17:33:09 pesch * Moved CONST definition to the right place * * Revision 1.1 1992/01/22 15:12:48 kredel * Initial revision * * ---------------------------------------------------------------------------- *) IMPLEMENTATION MODULE LINALGI; (* MAS Linear Algebra Integer Implementation Module. *) (*------------------------------------------------------------------------- Implementation Module: Linear Algebra Integer Programmierpraktikum SS 1990 JUERGEN MUELLER, Heinz Kredel Contents: Standartoperations for matrix and vector manipulations, Gaussian elimination, LU-Decomposition, Solve, Inversion, Nullspace, Determinant. Stand : 27.09.90, Juergen Mueller from then date of the file, Heinz Kredel Remarks: A vector is represented as a list of elements. The elements may be integers or rational numbers. A matix is represented as a list of vectors. In most circumstances these vectors are interpreted row vectors, but they can also be interpreted as column vectors. --------------------------------------------------------------------------*) FROM MASELEM IMPORT GAMMAINT, MASMIN, MASEVEN; FROM MASBIOS IMPORT SWRITE, BLINES; FROM MASSTOR IMPORT LIST, SIL, BETA, ADV, FIRST, RED, INV, LIST1, COMP, LENGTH; FROM MASERR IMPORT ERROR, severe; FROM SACLIST IMPORT OWRITE, LIST2, FIRST2, CCONC, CINV, CONC; FROM SACI IMPORT IWRITE, IABSF, ISUM, IPROD, INEG, ICOMP, ISIGNF, ILCM, IQ, IQR, IMIN, IDIF, IMAX; FROM SACRN IMPORT RNDEN, RNNUM, RNRED, RNINT, RNPROD, RNQ, RNSUM, RNDIF; FROM LINALGRN IMPORT MTRANS, MFILL, MDELCOL, RNMUT, RNUM, RNMUNS, RNMFIM, RNVFIV; CONST rcsidi = "$Id: LINALGI.mi,v 1.6 1995/11/05 09:23:13 kredel Exp $"; CONST copyrighti = "Copyright (c) 1989 - 1992 Universitaet Passau"; TYPE F2 = PROCEDURE(LIST,LIST): LIST; (*The TDI compiler accepts only global functions in expressions. *) PROCEDURE ium(i,j: LIST): LIST; (*unit matrix*) BEGIN IF i = j THEN RETURN(1) ELSE RETURN(0) END; (*9*) END ium; (*---------------- arbitrary matices --------------------*) PROCEDURE MAT(f: F2; m, n: LIST): LIST; (*Matrix. An (m x n) matrix with elements given by f(i,j) is returned. *) VAR i, j, V, M, v: LIST; BEGIN (*1*) M:=SIL; IF (m <= 0) OR (n <= 0) THEN RETURN(M) END; (*2*) i:=0; WHILE i < m DO i:=i+1; j:=0; V:=SIL; WHILE j < n DO j:=j+1; v:=f(i,j); V:=COMP(v,V) END; V:=INV(V); M:=COMP(V,M); END; (*4*) M:=INV(M); RETURN(M); (*9*) END MAT; (*---------------- integer matices --------------------*) PROCEDURE IUM(m, n: LIST): LIST; (*Integer unit matrix. m, n integer. An (m x n) integer unit matrix is returned. *) BEGIN (*1*) RETURN(MAT(ium,m,n)); (*9*) END IUM; PROCEDURE IVWRITE(A : LIST); (*Integer vector write. A is an integer vector. A is written to the output stream. *) VAR a : LIST; BEGIN (*1*) SWRITE("("); (*2*) WHILE A#SIL DO ADV(A, a, A); IWRITE(a); IF A#SIL THEN SWRITE(", ") END; END; (*3*) SWRITE(")"); (*9*) END IVWRITE; PROCEDURE IMWRITE(A : LIST); (*Integer matrix write. A is an integer matrix. A is written to the output stream. *) VAR a : LIST; BEGIN (*1*) BLINES(0); SWRITE("("); (*2*) WHILE A#SIL DO ADV(A, a, A); IVWRITE(a); IF A#SIL THEN SWRITE(", "); BLINES(0) END; END; (*3*) SWRITE(")"); BLINES(0); (*9*) END IMWRITE; PROCEDURE IKM(A, B : LIST): LIST; (*Integer vector component product. IKM returns the difference of the product of the integer vector A with FIRST(B) and the product of the integer vector B with FIRST(A). C = A * FIRST(B) - B * FIRST(A). C is an integer vector. *) VAR a, b, c, d, C, D : LIST; BEGIN (*1*) C := SIL; D := SIL; a := FIRST(A); b := FIRST(B); (*2*) IF a # LIST(0) THEN IF b # LIST(0) THEN WHILE A # SIL DO ADV(A, c, A); c := IPROD(c,b); C := COMP(c,C); ADV(B, d, B); d := IPROD(d,a); D := COMP(d,D); END; A := INV(C); B := INV(D); B := IVVDIF(B,A); END; END; (*3*) RETURN(B); (*9*) END IKM; PROCEDURE IVVDIF(A, B : LIST): LIST; (*Integer vector difference. A and B are integer vectors. The integer vector C = A - B is returned. *) VAR a, b, c, C, test : LIST; BEGIN (*1*) C := SIL; (*2*) WHILE A # SIL DO ADV(A, a, A); ADV(B, b, B); c := IDIF(a,b); C := COMP(c,C); END; (*3*) C := INV(C); RETURN(C); (*9*) END IVVDIF; PROCEDURE IVVSUM(A, B : LIST): LIST; (*Integer vector vector sum. A and B are integer vectors. An integer vector C = A + B is returned. *) VAR a, b, c, C, test : LIST; BEGIN (*1*) C := SIL; (*2*) WHILE A # SIL DO ADV(A, a, A); ADV(B, b, B); c := ISUM(a,b); C := COMP(c,C); END; (*3*) C := INV(C); RETURN(C); (*9*) END IVVSUM; PROCEDURE IVSVSUM(A, B : LIST): LIST; (*Integer vector scalar and vector sum. A and B are integer vectors. An integer vector C = A + FIRST(B) is returned. *) VAR a, b, c, C : LIST; BEGIN (*1*) C := SIL; b:=FIRST(B); (*2*) WHILE A # SIL DO ADV(A, a, A); c := ISUM(a,b); C := COMP(c,C); END; (*3*) C := INV(C); RETURN(C); (*9*) END IVSVSUM; PROCEDURE IVSSUM(A : LIST): LIST; (*Integer vector scalar sum. A is an integer vector. An integer C = a1 + a2 + ... + an is returned. *) VAR a, c : LIST; BEGIN (*1*) c := 0; (*2*) WHILE A # SIL DO ADV(A, a, A); c := ISUM(a,c); END; (*3*) RETURN(c); (*9*) END IVSSUM; PROCEDURE IVSVPROD(A, B : LIST): LIST; (*Integer vector scalar and vector product. A and B are integer vectors. An integer vector C = (a1*FIRST(B), ..., an*FIRST(B) ) is returned. *) VAR a, b, c, C : LIST; BEGIN (*1*) C := SIL; b:=FIRST(B); (*2*) WHILE A # SIL DO ADV(A, a, A); c := IPROD(a,b); C := COMP(c,C); END; (*3*) C := INV(C); RETURN(C); (*9*) END IVSVPROD; PROCEDURE IVVPROD(A, B : LIST): LIST; (*Integer vector vectors product. A and B are integer vectors. An integer vector C = (a1*b1, ..., an*bn) is returned. *) VAR a, b, c, C : LIST; BEGIN (*1*) C := SIL; (*2*) WHILE A # SIL DO ADV(A, a, A); ADV(B, b, B); c := IPROD(a,b); C := COMP(c,C); END; (*3*) C := INV(C); RETURN(C); (*9*) END IVVPROD; PROCEDURE IVSPROD(A, B : LIST): LIST; (*Integer vector scalar product. A and B are integer vectors. An integer C = a1*b1 + ... + an*bn is returned. *) VAR a, b, c, C : LIST; BEGIN (*1*) C := 0; (*2*) WHILE A # SIL DO ADV(A, a, A); ADV(B, b, B); c := IPROD(a,b); C := ISUM(c,C); END; (*3*) RETURN(C); (*9*) END IVSPROD; PROCEDURE IVMAX(M : LIST): LIST; (*Integer vector maximum norm. M is an integer vector. An integer a = maximum absolute value M(i) is returned. *) VAR g, zeile, element, max : LIST; BEGIN (*1*) max := 0; (*2*) WHILE M # SIL DO ADV(M, element, M); element := IABSF(element); max:=IMAX(max,element); END; (*3*) RETURN(max); (*9*) END IVMAX; PROCEDURE IMPROD(A, B : LIST): LIST; (*Integer matrix product. A and B are integer matrices. An integer matrix C = A * B is returned, if the number of coloums of A is equal to the number of rows of B, otherwise the empty matrix is returned. *) VAR H1, H2, C, C1, a, c, BP, BT, b : LIST; BEGIN (*1*) C := SIL; IF A = SIL THEN RETURN(C) END; IF B = SIL THEN RETURN(C) END; H1 := LENGTH(FIRST(A)); H2 := LENGTH(B); IF H1 # H2 THEN RETURN(C) END; (*2*) BT:=MTRANS(B); (*transpose B. *) WHILE A # SIL DO ADV(A, a, A); C1:=SIL; BP:=BT; WHILE BP # SIL DO ADV(BP,b,BP); c:=IVSPROD(a,b); C1:=COMP(c,C1); END; C1 := INV(C1); C := COMP(C1,C); END; (*4*) C := INV(C); RETURN(C); (*9*) END IMPROD; PROCEDURE ISMPROD(A, B : LIST): LIST; (*Integer scalar and matrix product. A is an integer matrix. B is an integer. An integer matrix C = A * B is returned. *) VAR a, b, c, C : LIST; BEGIN (*1*) IF A=SIL THEN RETURN(A) END; C := SIL; b:=LIST1(B); (*2*) WHILE A # SIL DO ADV(A, a, A); c := IVSVPROD(a,b); (* geaendert *) C := COMP(c,C); END; (*3*) C := INV(C); RETURN(C); (*9*) END ISMPROD; PROCEDURE IMDIF(A, B : LIST): LIST; (*Integer matrix difference. A and B are integer matrices. An integer matrix C = A - B is returned. *) VAR a, b, c, C : LIST; BEGIN (*1*) IF A=SIL THEN B := ISMPROD(B,-1); (*geaendert*) RETURN(B); END; IF B=SIL THEN RETURN(A); END; C := SIL; (*2*) WHILE A # SIL DO ADV(A, a, A); ADV(B, b, B); c := IVVDIF(a,b); C := COMP(c,C); END; (*3*) C := INV(C); RETURN(C); (*9*) END IMDIF; PROCEDURE IMSUM(A, B : LIST): LIST; (*Integer matrix sum. A and B are integer matrices. An integer matrix C = A + B is returned. *) VAR a, b, c, C : LIST; BEGIN (*1*) IF A=SIL THEN RETURN(B) END; IF B=SIL THEN RETURN(A) END; C := SIL; (*2*) WHILE A # SIL DO ADV(A, a, A); ADV(B, b, B); c := IVVSUM(a,b); C := COMP(c,C); END; (*3*) C := INV(C); RETURN(C); (*9*) END IMSUM; PROCEDURE IMMAX(M : LIST): LIST; (*Integer matrix maximum norm. M is an integer matrix. An integer a = maximum absolute value M(i,j) is returned. *) VAR g, zeile, element, max : LIST; BEGIN (*1*) max := 0; (*2*) WHILE M # SIL DO ADV(M, zeile, M); element := IVMAX(zeile); max:=IMAX(max,element); END; (*3*) RETURN(max); (*9*) END IMMAX; PROCEDURE IVFRNV(A: LIST): LIST; (*Integer vector from rational number vector. A is a rational number vector. A is muliplied by a common multiple of its denominators, then the denominators are removed. An integer vector C = lcm(denom(A)) * A is returned. *) VAR AP, BP: LIST; BEGIN (*1*) IVFRNV1(A,SIL, AP,BP); RETURN(AP); (*9*) END IVFRNV; PROCEDURE IVFRNV1(A, B : LIST; VAR C, D: LIST); (*Integer vector from rational number vector. A and B are rational number vectors. A and B are muliplied by a common multiple of their denominators, then the denominators are removed. C and D are integer vectors, such that C = lcm(denom(A),denom(B))*A and D = lcm(denom(A),denom(B))*B. *) VAR ap, bp, d, a, c, b: LIST; BEGIN (*1*) C := SIL; D:=SIL; (*2*) (*determine lcm. *) ap:=A; bp:=B; d:=1; WHILE ap # SIL DO ADV(ap, a, ap); c := RNDEN(a); d:=ILCM(d,c); END; WHILE bp # SIL DO ADV(bp, a, bp); c := RNDEN(a); d:=ILCM(d,c); END; (*3*) (*clear denominators. *) ap:=A; bp:=B; WHILE ap # SIL DO ADV(ap, a, ap); c := RNDEN(a); b:=IQ(d,c); c:=RNNUM(a); c:=IPROD(c,b); C:=COMP(c,C); END; WHILE bp # SIL DO ADV(bp, a, bp); c := RNDEN(a); b:=IQ(d,c); c:=RNNUM(a); c:=IPROD(c,b); D:=COMP(c,D); END; (*4*) C := INV(C); D:=INV(D); (*9*) END IVFRNV1; PROCEDURE IMFRNM(A : LIST): LIST; (*Integer matrix from rational number matrix. A is a rational number row matix. The rows of A are muliplied by a common multiple of its denominators, then the denominators are removed. An integer matix C is returned, such that for all rows C(i) = lcm(denom(A(i))) * A(i). *) VAR AP, BP: LIST; BEGIN (*1*) IMFRNM1(A,SIL, AP,BP); RETURN(AP); (*9*) END IMFRNM; PROCEDURE IMFRNM1(A, B : LIST; VAR C, D: LIST); (*Integer matrix from rational number matrix. A is a rational number row matix. B is a rational number column matix. The rows of A and the rows of B are muliplied by a common multiple of their denominators, then the denominators are removed. C and D are integer matices, such that C(i) = lcm(denom(A(i)),B(i)) * A(i) and D(i) = lcm(denom(A(i)),B(i)) * B(i). *) VAR a, b, c, d: LIST; BEGIN (*1*) C:= SIL; D:=SIL; B:=MTRANS(B); (*2*) WHILE A # SIL DO ADV(A, a, A); IF B # SIL THEN ADV(B, b, B) ELSE b:=SIL END; IVFRNV1(a,b,c,d); C:=COMP(c,C); IF d # SIL THEN D:=COMP(d,D) END; END; (*3*) C:=INV(C); D:=INV(D); D:=MTRANS(D); (*9*) END IMFRNM1; (* ------------ *) PROCEDURE IVLC(a, A, b, B : LIST): LIST; (*Integer vector linear combination. A and B are integer vectors. a and b are integers. An integer vector C = a*A + b*B is returned. *) VAR c, cp, C, ap, bp : LIST; BEGIN (*1*) (*initialization*) C := SIL; IF a = 0 THEN a:=b; A:=B; b:=0; END; (*2*) (*a or b zero*) IF b = 0 THEN WHILE A # SIL DO ADV(A, ap, A); c := IPROD(a,ap); C := COMP(c,C); END; C:=INV(C); RETURN(C); END; (*3*) (*general case*) WHILE A # SIL DO ADV(A, ap, A); ADV(B, bp, B); c := IPROD(a,ap); cp := IPROD(b,bp); c := ISUM(c,cp); C := COMP(c,C); END; (*4*) (*finish*) C := INV(C); RETURN(C); (*9*) END IVLC; PROCEDURE IVSQ(a, A: LIST): LIST; (*Integer vector scalar quotient. A is an integer vector. a is an integer. An integer vector C = A/a is returned. a must divide each element of A exactly. *) VAR c, C, ap, r: LIST; BEGIN (*1*) C := SIL; (*2*) WHILE A # SIL DO ADV(A, ap, A); IQR(ap,a,c,r); IF r # 0 THEN ERROR(severe,"IVSQ: non zero remainder.") END; C := COMP(c,C); END; (*3*) C := INV(C); RETURN(C); (*9*) END IVSQ; (* PROCEDURE IMGELUD0(M : LIST; VAR L, U: LIST); (* Integer matrix Gaussian elimination. LU-decomposition. *) VAR C, M1, MP, L1, a, b, c, MP1, V, n, Z : LIST; BEGIN (*1*) M1 := M; MP := SIL; L := SIL; U := SIL; IF M1 = SIL THEN RETURN END; IF FIRST(M1) = SIL THEN RETURN END; n := 0; (*2*) WHILE M1 # SIL DO L1 := SIL; MP1 := M1; M1 := SIL; a := 0; (*search pivot row. *) WHILE (MP1 # SIL) AND (a = 0) DO ADV(MP1, C, MP1); ADV(C, a, C); IF a = 0 THEN M1 := COMP(C,M1); L1 := COMP(a,L1); END; END; IF a = 0 THEN C:=COMP(a,C); M1:=RED(M1); ELSE L1 := COMP(a,L1); WHILE MP1 # SIL DO ADV(MP1, V, MP1); ADV(V, b, V); IF b # 0 THEN V := IVLC(a,V,INEG(b),C) END; M1 := COMP(V,M1); L1 := COMP(b,L1); END; C := COMP(a,C); END; MP := COMP(C,MP); L1 := INV(L1); L := COMP(L1,L); M1 := INV(M1); IF M1 # SIL THEN (*if not square matrix *) IF FIRST(M1) = SIL THEN M1 := SIL END; END; END; (*3*) U := INV(MP); L := INV(L); RETURN; (*9*) END IMGELUD0; *) PROCEDURE IMGELUD(M : LIST; VAR L, U: LIST); (*Integer matrix Gaussian elimination LU-decomposition. M is an integer matrix represented rowwise. L is a lower triangular integer matrix represented columnwise. U is an upper triangular integer matrix represented rowwise. M = L * U for appropriate modifications of L and U. The pivot operations and exact division factors are also recorded in L. *) VAR F, C, CP, M1, MP, L1, a, b, c, MP1, MP2, V, n, Z : LIST; BEGIN (*1*) M1 := M; MP := SIL; L := SIL; U := SIL; IF M1 = SIL THEN RETURN END; IF FIRST(M1) = SIL THEN RETURN END; n := 0; F:=1; (*2*) WHILE M1 # SIL DO L1 := SIL; MP1 := M1; M1 := SIL; a := 0; (*search pivot row. *) WHILE (MP1 # SIL) AND (a = 0) DO ADV(MP1, C, MP1); ADV(C, a, CP); IF a = 0 THEN M1 := COMP(CP,M1); L1 := COMP(a,L1); END; END; IF a = 0 THEN (*M1:=RED(M1);*) F:=1 ELSE L1 := COMP(a,L1); L1 := COMP(F,L1); (*transform rest matrix. *) MP2:=INV(M1); M1:=SIL; WHILE MP2 # SIL DO ADV(MP2, V, MP2); V:=IVLC(a,V,0,CP); IF F # 1 THEN V:=IVSQ(F,V) END; (*Bareiss factor *) M1 := COMP(V,M1); END; WHILE MP1 # SIL DO ADV(MP1, V, MP1); ADV(V, b, V); V:=IVLC(a,V,INEG(b),CP); IF F # 1 THEN V:=IVSQ(F,V) END; (*Bareiss factor *) M1 := COMP(V,M1); L1 := COMP(b,L1); END; F:=a; MP := COMP(C,MP); END; M1 := INV(M1); L1 := INV(L1); L := COMP(L1,L); IF M1 # SIL THEN (*if not square matrix *) IF FIRST(M1) = SIL THEN M1 := SIL END; END; END; (*3*) U := INV(MP); L := INV(L); RETURN; (*9*) END IMGELUD; PROCEDURE IMLT(L, b : LIST): LIST; (*Integer lower triangular matrix transformation. L is a lower triangular integer matrix represented columnwise as generated by IMGELUD. b is an integer vector. An integer vector u = L * b is returned, such that if M * x = b and M = L * U, then U * x = u. *) VAR F, u, L1, b1, b2, c, l, d, a, e: LIST; BEGIN (*1*) u := SIL; (*2*) WHILE L # SIL DO ADV(L, L1, L); b1 := b; b := SIL; b2:=SIL; l := 0; WHILE (L1 # SIL) AND (l = 0) DO ADV(L1, l, L1); ADV(b1, c, b1); IF l = 0 THEN b2 := COMP(c,b2) END; END; IF l = 0 THEN (*u := COMP(c,u);*) b:=b2; ELSE (* l # 0 *) u := COMP(c,u); e:=l; ADV(L1,F,L1); b2:=INV(b2); WHILE b2 # SIL DO ADV(b2, d, b2); a := IPROD(e,d); IF F # 1 THEN a:=IQ(a,F) END; b := COMP(a,b); END; WHILE L1 # SIL DO ADV(L1, l, L1); ADV(b1, d, b1); d := IPROD(e,d); a := IPROD(l,c); a := IDIF(d,a); IF F # 1 THEN a:=IQ(a,F) END; b := COMP(a,b); END; END; b := INV(b); END; (*3*) WHILE b <> SIL DO ADV(b,c,b); (*unsolvable ? *) IF c # 0 THEN RETURN(SIL) END; END; (*4*) u := INV(u); RETURN(u); (*9*) END IMLT; PROCEDURE IMUT(U, b : LIST): LIST; (*Integer upper triangular matrix transformation. U is an upper triangular integer matrix represented rowwise as generated by IMGELUD. b is an integer vector b = L * b' as generated by IMLT. A rational number (!) vector x, such that U * x = b is returned. If no such x exists, then an empty vector is returned. If more than one such x exists, then for free x(i), x(i) = 0 is taken. *) VAR UP, x, bp : LIST; BEGIN (*1*) UP:=RNMFIM(U); bp:=RNVFIV(b); x:=RNMUT(UP,bp); (*3*) RETURN(x); (*9*) END IMUT; PROCEDURE IMGE(M : LIST): LIST; (*Integer matrix Gaussian elimination. M is a (n x m) integer matrix. A (n x m) integer matrix resulting from Gaussian elimination is returned. IMGELUD is called. *) VAR i, j, u, MP, l: LIST; BEGIN (*1*) i:=LENGTH(M); IF M # SIL THEN j:=LENGTH(FIRST(M)) ELSE j:=0 END; (*2*) IMGELUD(M, l, u); (*3*) MP:=MFILL(u,i,j); RETURN(MP); (*9*) END IMGE; PROCEDURE IMSDS(L, U, b : LIST): LIST; (*Integer matrix solve decomposed system. L is a lower triangular integer matrix represented columnwise, U is an upper triangular integer matrix represented rowwise. L and U as generated by IMGELUD. If M = L * U, then a rational number (!) vector x, such that M * x = b is returned. If no such x exists, then an empty vector is returned. If more than one such x exists, then for free x(i), x(i) = 0 is taken. *) VAR u, x : LIST; BEGIN (*1*) u := IMLT(L,b); IF u # SIL THEN x := IMUT(U,u); ELSE x := SIL; (*unsolvable*) END; (*3*) RETURN(x); (*9*) END IMSDS; PROCEDURE RNMINVI(A : LIST): LIST; (*Rational number matrix inversion, integer algorithm. A is a rational number matrix represented rowwise. If it exists, the inverse matrix of A is returned, otherwise an empty matrix is returned. The integer Gaussian elimination IMGELUD is used. *) VAR B, C, n, E, e, x, AP, EP, u, UP, L, U: LIST; BEGIN (*1*) n := LENGTH(A); B := SIL; IF n <= 0 THEN RETURN(B) END; IF n # LENGTH(FIRST(A)) THEN RETURN(B) END; E := RNUM(n,n); IMFRNM1(A,E,AP,EP); (*2*) (*LU-decomposition. *) IMGELUD(AP, L, U); (*3*) (*solve A Ainv = E. *) UP:=RNMFIM(U); WHILE EP # SIL DO ADV(EP, e, EP); u := IMLT(L,e); IF u = SIL THEN RETURN(SIL) END; (*singular *) u:=RNVFIV(u); x:=RNMUT(UP,u); IF x = SIL THEN RETURN(SIL) END; (*singular *) B := COMP(x,B); END; (*4*) B := INV(B); RETURN(B); (*9*) END RNMINVI; PROCEDURE IMUNS(U : LIST): LIST; (*Integer matrix upper triangular matrix solution null space. U is an upper triangular integer matrix represented rowwise as generated by IMGELUD. A matrix X of linear independent rational number vectors x is returned, such that for each x in X, U * x = 0 holds. If only x = 0 satisfies the condition U * x = 0, then the matrix X is empty. *) VAR UP, N: LIST; BEGIN (*1*) UP:=RNMFIM(U); N:=RNMUNS(UP); RETURN(N); (*9*) END IMUNS; PROCEDURE IMDETL(M : LIST): LIST; (*Integer matrix determinant, using Laplace expansion. M is an integer matrix. The determinant of M is returned. *) VAR i, d, dp, s, N, MP, V, VP, v : LIST; BEGIN (*1*) d := 0; IF M = SIL THEN RETURN(d); END; ADV(M, V, MP); IF MP = SIL THEN IF V = SIL THEN RETURN(d); END; ADV(V,d,V); IF V # SIL THEN d:=0 END; RETURN(d); END; s := 1; i := 0; (*2*) WHILE V # SIL DO ADV(V, v, V); i := i+1; IF v # 0 THEN N := MDELCOL(MP,i); dp := IMDETL(N); dp := IPROD(v,dp); IF s < 0 THEN dp := INEG(dp); END; d := ISUM(d,dp); END; s := -s; END; RETURN(d); (*9*) END IMDETL; PROCEDURE IMDET(M : LIST): LIST; (*Integer matrix determinant, using Gaussian elimination. M is an integer matrix. The determinant of M is returned. *) VAR F, d, s, i, C, CP, M1, MP, a, b, c, MP1, MP2, V, e: LIST; BEGIN (*1*) M1 := M; d := 0; s := 1; IF M1 = SIL THEN RETURN(d) END; V:=FIRST(M1); IF V = SIL THEN RETURN(d) END; IF LENGTH(M1) # LENGTH(V) THEN RETURN(d) END; (* not square *) e:=1; d:=e; F:=1; (*2*) WHILE M1 # SIL DO MP1 := M1; M1 := SIL; a := 0; i:=0; (*search pivot row and count sign changes. *) WHILE (MP1 # SIL) AND (a = 0) DO ADV(MP1, C, MP1); i:=i+1; ADV(C, a, CP); IF a = 0 THEN M1 := COMP(CP,M1) END; END; IF a = 0 THEN d:=0; RETURN(d); END; IF MASEVEN(i) THEN s:=-s END; (*rest matrix. *) d:=a; (* d:=IPROD(d,a); *) MP2:=INV(M1); M1:=SIL; WHILE MP2 # SIL DO ADV(MP2, V, MP2); V:=IVLC(a,V,0,CP); IF F # 1 THEN V:=IVSQ(F,V) END; (*Bareiss factor *) M1 := COMP(V,M1); END; WHILE MP1 # SIL DO ADV(MP1, V, MP1); ADV(V, b, V); V := IVLC(a,V,INEG(b),CP); IF F # 1 THEN V:=IVSQ(F,V) END; (*Bareiss factor *) M1 := COMP(V,M1); END; M1 := INV(M1); F:=a; IF M1 # SIL THEN (*not square matrix ? *) IF FIRST(M1) = SIL THEN d := 0; RETURN(d) END; END; END; (*3*) IF s < 0 THEN d:=INEG(d) END; RETURN(d); (*9*) END IMDET; END LINALGI. (* -EOF- *)