{ This file is part of the Numlib package. Copyright (c) 1986-2000 by Kees van Ginneken, Wil Kortsmit and Loek van Reij of the Computational centre of the Eindhoven University of Technology FPC port Code by Marco van de Voort (marco@freepascal.org) documentation by Michael van Canneyt (Michael@freepascal.org) Unit was originally undocumented, but is probably an variant of DET. Det accepts vectors as arguments, while MDT calculates determinants for matrices. Contrary to the other undocumented units, this unit is exported in the DLL. See the file COPYING.FPC, included in this distribution, for details about the license. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. **********************************************************************} Unit mdt; interface {$I DIRECT.INC} uses typ, dsl, omv; Procedure mdtgen(n, rwidth: ArbInt; Var alu: ArbFloat; Var p: ArbInt; Var ca:ArbFloat; Var term: ArbInt); Procedure mdtgtr(n: ArbInt; Var l, d, u, l1, d1, u1, u2: ArbFloat; Var p: boolean; Var ca: ArbFloat; Var term: ArbInt); Procedure mdtgsy(n, rwidth: ArbInt; Var a: ArbFloat; Var pp:ArbInt; Var qq:boolean; Var ca:ArbFloat; Var term:ArbInt); Procedure mdtgpd(n, rwidth: ArbInt; Var al, ca: ArbFloat; Var term: ArbInt); Procedure mdtgba(n, lb, rb, rwa: ArbInt; Var a: ArbFloat; rwl: ArbInt; Var l:ArbFloat; Var p: ArbInt; Var ca: ArbFloat; Var term:ArbInt); Procedure mdtgpb(n, lb, rwidth: ArbInt; Var al, ca: ArbFloat; Var term: ArbInt); Procedure mdtdtr(n: ArbInt; Var l, d, u, l1, d1, u1: ArbFloat; Var term:ArbInt); implementation Procedure mdtgen(n, rwidth: ArbInt; Var alu: ArbFloat; Var p: ArbInt; Var ca:ArbFloat; Var term: ArbInt); Var indi, indk, nsr, ind, i, j, k, indexpivot : ArbInt; normr, sumrowi, pivot, l, normt, maxim, h, s : ArbFloat; palu, sumrow, t : ^arfloat1; pp : ^arint1; singular : boolean; Begin If (n<1) Or (rwidth<1) Then Begin term := 3; exit End; {wrong input} palu := @alu; pp := @p; nsr := n*sizeof(ArbFloat); getmem(sumrow, nsr); getmem(t, nsr); normr := 0; singular := false ; For i:=1 To n Do Begin ind := (i-1)*rwidth; pp^[i] := i; sumrowi := 0; For j:=1 To n Do sumrowi := sumrowi+abs(palu^[ind+j]); sumrow^[i] := sumrowi; h := 2*random-1; t^[i] := sumrowi*h; h := abs(h); If normr 0 Then Begin h := abs(palu^[ind+k])/sumrowi; If maxim 0} End; {i} If maxim=0 Then singular := true Else Begin If indexpivot <> k Then Begin ind := (indexpivot-1)*rwidth; indk := (k-1)*rwidth; For j:=1 To n Do Begin h := palu^[ind+j]; palu^[ind+j] := palu^[indk+j]; palu^[indk+j] := h End; {j} h := t^[indexpivot]; t^[indexpivot] := t^[k]; t^[k] := h; pp^[k] := indexpivot; sumrow^[indexpivot] := sumrow^[k] End; {indexpivot <> k} pivot := palu^[(k-1)*rwidth+k]; For i:=k+1 To n Do Begin ind := (i-1)*rwidth; l := palu^[ind+k]/pivot; palu^[ind+k] := l; If l <> 0 Then Begin For j:=k+1 To n Do palu^[ind+j] := palu^[ind+j]-l*palu^[(k-1)*rwidth+j]; If Not singular Then t^[i] := t^[i]-l*t^[k] End {l <> 0} End {i} End {maxim <> 0} End; {k} If Not singular Then Begin normt := 0; For i:=n Downto 1 Do Begin indi := (i-1)*rwidth; s := 0; For j:=i+1 To n Do s := s+t^[j]*palu^[indi+j]; t^[i] := (t^[i]-s)/palu^[indi+i]; h := abs(t^[i]); If normt n) Do Begin i := j; j := j+1; lj := pl1^[j]; If lj <> 0 Then Begin di := pd1^[i]; If di=0 Then pp^[i] := true Else pp^[i] := abs(di/sumrow^[i])0} Else Begin If i 1 Then Begin t^[nmin1] := (t^[nmin1]-pu1^[nmin1]*t^[n])/pd1^[nmin1]; h := abs(t^[nmin1]) End; {n > 1} If normt3 Then Begin t^[2] := alt^[rwidth+2]*alt^[indk+1]+alt^[2*rwidth+2]*alt^[indk+2]; For i:=3 To kmin2 Do Begin indi := (i-1)*rwidth; t^[i] := alt^[indi+i-1]*alt^[indk+i-2]+alt^[indi+i] *alt^[indk+i-1]+alt^[indi+rwidth+i]*alt^[indk+i] End; {i} t^[kmin1] := alt^[indk-rwidth+kmin2]*alt^[indk+k-3] +alt^[indk-rwidth+kmin1]*alt^[indk+kmin2] +alt^[indk+kmin1]; h := alt^[indk+k]; For j:=2 To kmin1 Do h := h-t^[j]*alt^[indk+j-1]; t^[k] := h; alt^[indk+k] := h-alt^[indk+kmin1]*alt^[indk+kmin2] End {k>3} Else If k=3 Then Begin t^[2] := alt^[rwidth+2]*alt^[2*rwidth+1]+alt^[2*rwidth+2]; h := alt^[2*rwidth+3]-t^[2]*alt^[2*rwidth+1]; t^[3] := h; alt^[2*rwidth+3] := h-alt^[2*rwidth+2]*alt^[2*rwidth+1] End {k=3} Else If k=2 Then t^[2] := alt^[rwidth+2]; maxim := 0; For i:=kplus1 To n Do Begin indi := (i-1)*rwidth; h := alt^[indi+k]; For j:=2 To k Do h := h-t^[j]*alt^[indi+j-1]; absh := abs(h); If maxim 0 Then Begin If indexpivot>kplus1 Then Begin indp := (indexpivot-1)*rwidth; indk := k*rwidth; p^[kplus1] := indexpivot; For j:=1 To k Do Begin h := alt^[indk+j]; alt^[indk+j] := alt^[indp+j]; alt^[indp+j] := h End; {j} For j:=indexpivot Downto kplus1 Do Begin indj := (j-1)*rwidth; h := alt^[indj+kplus1]; alt^[indj+kplus1] := alt^[indp+j]; alt^[indp+j] := h End; {j} For i:=indexpivot To n Do Begin indi := (i-1)*rwidth; h := alt^[indi+kplus1]; alt^[indi+kplus1] := alt^[indi+indexpivot]; alt^[indi+indexpivot] := h End {i} End; {if} pivot := alt^[k*rwidth+k]; For i:=k+2 To n Do alt^[(i-1)*rwidth+k] := alt^[(i-1)*rwidth+k]/pivot End {maxim <> 0} End; {k} d^[1] := alt^[1]; i := 1; while i2 Do Begin iplus1 := i; i := imin1; imin1 := imin1-1; h := t1^[i]; For j:=iplus1 To n Do h := h-alt^[(j-1)*rwidth+imin1]*t1^[j]; t1^[i] := h; h := abs(h); If normtn-1) Or (rb>n-1) Or (rwl<0) Or (rwa<1) Then Begin term := 3; exit End; {term=3} sr := sizeof(ArbFloat); au := @a; pl := @l; pp := @p; ll := lb+rb+1; ls := ll*sr; getmem(sumrow, n*sr); getmem(t, n*sr); getmem(row, ls); lbj := 0; jj := 1; For i:=lb Downto 1 Do Begin move(au^[i+jj], au^[jj], (ll-i)*sr); fillchar(au^[jj+ll-i], i*sr, 0); jj := jj+rwa End; {i} jj := (n-rb)*rwa+ll; For i:=1 To rb Do Begin fillchar(au^[jj], i*sr, 0); jj := jj+rwa-1 End; {i} normr := 0; term := 1; ii := 1; For i:=1 To n Do Begin pp^[i] := i; sumrowi := omvn1v(au^[ii], ll); ii := ii+rwa; sumrow^[i] := sumrowi; h := 2*random-1; t^[i] := sumrowi*h; h := abs(h); If normr 0 Then Begin h := abs(au^[ii])/sumrowi; ii := ii+rwa; If maxim 0} End; {i} If maxim=0 Then Begin lbj := 1; ubj := ubi-k; For j:=lbj To ubj Do pl^[(k-1)*rwl+j] := 0; For i:=k+1 To ubi Do Begin ii := (i-1)*rwa; For j:=2 To ll Do au^[ii+j-1] := au^[ii+j]; au^[ii+ll] := 0 End; {i} term := 4 End {maxim=0} Else Begin If ipivot <> k Then Begin ii := (ipivot-1)*rwa+1; move(au^[ii], row^, ls); move(au^[jj], au^[ii], ls); move(row^, au^[jj], ls); h := t^[ipivot]; t^[ipivot] := t^[k]; t^[k] := h; pp^[k] := ipivot; sumrow^[ipivot] := sumrow^[k] End; {ipivot <> k} pivot := au^[jj]; jl := 0; ii := jj; For i:=k+1 To ubi Do Begin jl := jl+1; ii := ii+rwa; h := au^[ii]/pivot; pl^[(k-1)*rwl+jl] := h; For j:=0 To ll-2 Do au^[ii+j] := au^[ii+j+1]-h*au^[jj+j+1]; au^[ii+ll-1] := 0; If term=1 Then t^[i] := t^[i]-h*t^[k] End {i} End; {maxim <> 0} jj := jj+rwa End; {k} If term=1 Then Begin normt := 0; ubj := -lb-1; jj := n*rwa+1; For i:=n Downto 1 Do Begin jj := jj-rwa; If ubjn-1) Or (n<1) Or (rwidth<1) Then Begin term := 3; exit End; {wrong input} pal := @al; getmem(t, n*sizeof(ArbFloat)); ll := lb+1; normr := 0; p := ll+1; norma := 0; For i:=1 To n Do Begin If p>1 Then p := p-1; indi := (i-1)*rwidth+p; sumrowi := omvn1v(pal^[indi], ll-p+1); r := i; j := ll; while (r1) Do Begin r := r+1; j := j-1; sumrowi := sumrowi+abs(pal^[(r-1)*rwidth+j]) End; {r,j} If norma1 Then p := p-1; r := i-ll+p; j := p-1; while j1 Then p := p-1; q := i; h := t^[i]; For k:=llmin1 Downto p Do Begin q := q+1; h := h-pal^[(q-1)*rwidth+k]*t^[q] End; {k} t^[i] := h/pal^[(i-1)*rwidth+ll]; h := abs(t^[i]); If normt n) Do Begin i := j; j := j+1; lj := pl1^[j]/di; pl1^[j] := lj; di := pd1^[j]-lj*pu1^[i]; pd1^[j] := di; If di=0 Then term := 2 End {j} End; {mdtdtr} End.