{ 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) See the file COPYING.FPC, included in this distribution, for details about the copyright. 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 eig; {$I DIRECT.INC} interface uses typ; const versie = 'augustus 1993'; procedure eiggs1(var a: ArbFloat; n, rwidth: ArbInt; var lam: ArbFloat; var term: ArbInt); procedure eiggs2(var a: ArbFloat; n, rwidth, k1, k2: ArbInt; var lam: ArbFloat; var term: ArbInt); procedure eiggs3(var a: ArbFloat; n, rwidtha: ArbInt; var lam, x: ArbFloat; rwidthx: ArbInt; var term: ArbInt); procedure eiggs4(var a: ArbFloat; n, rwidtha, k1, k2: ArbInt; var lam, x: ArbFloat; rwidthx: ArbInt; var m2, term: ArbInt); procedure eigts1(var d, cd: ArbFloat; n: ArbInt; var lam: ArbFloat; var term: ArbInt); procedure eigts2(var d, cd: ArbFloat; n, k1, k2: ArbInt; var lam: ArbFloat; var term: ArbInt); procedure eigts3(var d, cd: ArbFloat; n: ArbInt; var lam, x: ArbFloat; rwidth: ArbInt; var term: ArbInt); procedure eigts4(var d, cd: ArbFloat; n, k1, k2: ArbInt; var lam, x: ArbFloat; rwidth: ArbInt; var m2, term: ArbInt); procedure eigbs1(var a: ArbFloat; n, l: ArbInt; var lam: ArbFloat; var term: ArbInt); procedure eigbs2(var a: ArbFloat; n, l, k1, k2: ArbInt; var lam: ArbFloat; var term: ArbInt); procedure eigbs3(var a: ArbFloat; n, l: ArbInt; var lam, x: ArbFloat; rwidthx: ArbInt; var term: ArbInt); procedure eigbs4(var a: ArbFloat; n, l, k1, k2: ArbInt; var lam, x: ArbFloat; rwidthx: ArbInt; var m2, term: ArbInt); procedure eigge1(var a: ArbFloat; n, rwidth: ArbInt; var lam: complex; var term: ArbInt); procedure eigge3(var a: ArbFloat; n, rwidtha: ArbInt; var lam, x: complex; rwidthx: ArbInt; var term: ArbInt); procedure eiggg1(var a: ArbFloat; n, rwidtha: ArbInt; var b: ArbFloat; rwidthb: ArbInt; var lam: ArbFloat; var term: ArbInt); procedure eiggg2(var a: ArbFloat; n, rwidtha, k1, k2: ArbInt; var b: ArbFloat; rwidthb: ArbInt; var lam: ArbFloat; var term: ArbInt); procedure eiggg3(var a: ArbFloat; n, rwidtha: ArbInt; var b: ArbFloat; rwidthb: ArbInt; var lam, x: ArbFloat; rwidthx: ArbInt; var term: ArbInt); procedure eiggg4(var a: ArbFloat; n, rwidtha, k1, k2: ArbInt; var b: ArbFloat; rwidthb: ArbInt; var lam, x: ArbFloat; rwidthx: ArbInt; var m2, term: ArbInt); procedure eigsv1(var a: ArbFloat; m, n, rwidth: ArbInt; var sig: ArbFloat; var term: ArbInt); procedure eigsv3(var a: ArbFloat; m, n, rwidtha: ArbInt; var sig, u: ArbFloat; rwidthu: ArbInt; var v: ArbFloat; rwidthv: ArbInt; var term: ArbInt); implementation uses eigh1, eigh2; procedure eiggs1(var a: ArbFloat; n, rwidth: ArbInt; var lam: ArbFloat; var term: ArbInt); var i, sr, nsr : ArbInt; d, cd, dh, cdh, u, pa : ^arfloat1; begin if n<1 then begin term:=3; exit end; {wrong input} pa:=@a; sr:=sizeof(ArbFloat); nsr:=n*sr; getmem(d, nsr); getmem(cd, nsr); getmem(dh, nsr); getmem(cdh, nsr); getmem(u, n*nsr); for i:=1 to n do move(pa^[(i-1)*rwidth+1], u^[(i-1)*n+1], i*sr); tred1(u^[1], n, n, d^[1], cd^[1], term); move(d^[1], dh^[1], nsr); move(cd^[1], cdh^[1], nsr); tql1(d^[1], cd^[1], n, lam, term); if term=2 then bisect(dh^[1], cdh^[1], n, 1, n, 0, lam, term); freemem(d, nsr); freemem(cd, nsr); freemem(dh, nsr); freemem(cdh, nsr); freemem(u, n*nsr); end; {eiggs1} procedure eiggs2(var a: ArbFloat; n, rwidth, k1, k2: ArbInt; var lam: ArbFloat; var term: ArbInt); var i, sr, nsr : ArbInt; d, cd, u, pa : ^arfloat1; begin if (n<1) or (k1<1) or (k2n) then begin term:=3; exit end; {wrong input} pa:=@a; sr:=sizeof(ArbFloat); nsr:=n*sr; getmem(d, nsr); getmem(cd, nsr); getmem(u, n*nsr); for i:=1 to n do move(pa^[(i-1)*rwidth+1], u^[(i-1)*n+1], i*sr); tred1(u^[1], n, n, d^[1], cd^[1], term); bisect(d^[1], cd^[1], n, k1, k2, 0, lam, term); freemem(d, nsr); freemem(cd, nsr); freemem(u, n*nsr); end; {eiggs2} procedure eiggs3(var a: ArbFloat; n, rwidtha: ArbInt; var lam, x: ArbFloat; rwidthx: ArbInt; var term: ArbInt); var nsr : ArbInt; d, cd : ^arfloat1; begin if n<1 then begin term:=3; exit end; nsr:=n*sizeof(ArbFloat); getmem(d, nsr); getmem(cd, nsr); tred2(a, n, rwidtha, d^[1], cd^[1], x, rwidthx, term); tql2(d^[1], cd^[1], n, lam, x, rwidthx, term); freemem(d, nsr); freemem(cd, nsr) end; {eiggs3} procedure eiggs4(var a: ArbFloat; n, rwidtha, k1, k2: ArbInt; var lam, x: ArbFloat; rwidthx: ArbInt; var m2, term: ArbInt); var i, sr, nsr : ArbInt; pa, d, cd, u : ^arfloat1; begin if (n<1) or (k1<1) or (k2n) then begin term:=3; exit end; {wrong input} pa:=@a; sr:=sizeof(ArbFloat); nsr:=n*sr; getmem(d, nsr); getmem(cd, nsr); getmem(u, n*nsr); for i:=1 to n do move(pa^[(i-1)*rwidtha+1], u^[(i-1)*n+1], i*sr); tred1(u^[1], n, n, d^[1], cd^[1], term); trsturm1(d^[1], cd^[1], n, k1, k2, lam, x, rwidthx, m2, term); trbak1(u^[1], n, n, cd^[1], k1, k2, x, rwidthx); freemem(d, nsr); freemem(cd, nsr); freemem(u, n*nsr) { toegevoegd 3 apr 92 } end; {eiggs4} procedure eigts1(var d, cd: ArbFloat; n: ArbInt; var lam: ArbFloat; var term: ArbInt); var sr, nsr : ArbInt; pd, pcd, dh, cdh : ^arfloat1; begin if n<1 then begin term:=3; exit end; {wrong input} sr:=sizeof(ArbFloat); nsr:=n*sr; pd:=@d; pcd:=@cd; getmem(dh, nsr); getmem(cdh, nsr); move(pd^[1], dh^[1], nsr); move(pcd^[1], cdh^[2], (n-1)*sr); tql1(dh^[1], cdh^[1], n, lam, term); if term=2 then begin move(pd^[1], dh^[1], nsr); move(pcd^[1], cdh^[2], (n-1)*sr); bisect(dh^[1], cdh^[1], n, 1, n, 0, lam, term) end; freemem(dh, nsr); freemem(cdh, nsr); end; {eigts1} procedure eigts2(var d, cd: ArbFloat; n, k1, k2: ArbInt; var lam: ArbFloat; var term: ArbInt); var sr, nsr : ArbInt; pcd, cdh : ^arfloat1; begin if (n<1) or (k1<1) or (k2n) then begin term:=3; exit end; {wrong input} pcd:=@cd; term:=1; sr:=sizeof(ArbFloat); nsr:=n*sr; getmem(cdh, nsr); move(pcd^[1], cdh^[2], (n-1)*sr); bisect(d, cdh^[1], n, k1, k2, 0, lam, term); freemem(cdh, nsr) end; {eigts2} procedure eigts3(var d, cd: ArbFloat; n: ArbInt; var lam, x: ArbFloat; rwidth: ArbInt; var term: ArbInt); var i, sr, nsr : ArbInt; px, pcd, cdh : ^arfloat1; begin if n<1 then begin term:=3; exit end; px:=@x; pcd:=@cd; sr:=sizeof(ArbFloat); nsr:=n*sr; getmem(cdh, nsr); move(pcd^[1], cdh^[2], (n-1)*sr); for i:=1 to n do fillchar(px^[(i-1)*rwidth+1], nsr, 0); for i:=1 to n do px^[(i-1)*rwidth+i]:=1; tql2(d, cdh^[1], n, lam, px^[1], rwidth, term); freemem(cdh, nsr); end; {eigts3} procedure eigts4(var d, cd: ArbFloat; n, k1, k2: ArbInt; var lam, x: ArbFloat; rwidth: ArbInt; var m2, term: ArbInt); var sr : ArbInt; pcd, cdh : ^arfloat1; begin if (n<1) or (k1<1) or (k2n) then begin term:=3; exit end; {wrong input} term:=1; pcd:=@cd; sr:=sizeof(ArbFloat); getmem(cdh, n*sr); move(pcd^[1], cdh^[2], (n-1)*sr); trsturm1(d, cdh^[1], n, k1, k2, lam, x, rwidth, m2, term); freemem(cdh, n*sr) end; {eigts4} procedure eigbs1(var a: ArbFloat; n, l: ArbInt; var lam: ArbFloat; var term: ArbInt); var u, d, cd : ^arfloat1; uwidth, sr, nsr : ArbInt; begin if (n<1) or (l<0) or (l>n-1) then begin term:=3; exit end; {wrong input} sr:=sizeof(ArbFloat); nsr:=n*sr; uwidth:=l+1; getmem(u, uwidth*nsr); getmem(d, nsr); getmem(cd, nsr); transf(a, n, l, u^[1], uwidth); bandrd1(u^[1], n, l, uwidth, d^[1], cd^[1]); eigts1(d^[1], cd^[2], n, lam, term); freemem(u, uwidth*nsr); freemem(d, nsr); freemem(cd, nsr); end; {eigbs1} procedure eigbs2(var a: ArbFloat; n, l, k1, k2: ArbInt; var lam: ArbFloat; var term: ArbInt); var u, d, cd : ^arfloat1; sr, nsr, uwidth : ArbInt; begin if (n<1) or (k1<1) or (k2n) or (l<0) or (l>n-1) then begin term:=3; exit end; {wrong input} sr:=sizeof(ArbFloat); nsr:=n*sr; uwidth:=l+1; getmem(u, uwidth*nsr); getmem(d, nsr); getmem(cd, nsr); transf(a, n, l, u^[1], uwidth); bandrd1(u^[1], n, l, uwidth, d^[1], cd^[1]); eigts2(d^[1], cd^[2], n, k1, k2, lam, term); freemem(u, uwidth*nsr); freemem(d, nsr); freemem(cd, nsr) end; {eigbs2} procedure eigbs3(var a: ArbFloat; n, l: ArbInt; var lam, x: ArbFloat; rwidthx: ArbInt; var term: ArbInt); var u, d, cd : ^arfloat1; sr, nsr, uwidth : ArbInt; begin if (n<1) or (l<0) or (l>n-1) then begin term:=3; exit end; {wrong input} sr:=sizeof(ArbFloat); nsr:=n*sr; uwidth:=l+1; getmem(u, uwidth*nsr); getmem(d, nsr); getmem(cd, nsr); transf(a, n, l, u^[1], uwidth); bandrd2(u^[1], n, l, uwidth, d^[1], cd^[1], x, rwidthx); tql2(d^[1], cd^[1], n, lam, x, rwidthx, term); freemem(u, uwidth*nsr); freemem(d, nsr); freemem(cd, nsr) end; {eigbs3} procedure eigbs4(var a: ArbFloat; n, l, k1, k2: ArbInt; var lam, x: ArbFloat; rwidthx: ArbInt; var m2, term: ArbInt); var i, j, k, m, uwidth : ArbInt; plam, px, pa, v, u : ^arfloat1; s, norm : ArbFloat; begin if (n<1) or (k1<1) or (k2n) or (l<0) or (l>n-1) then begin term:=3; exit end; {wrong input} plam:=@lam; px:=@x; pa:=@a; getmem(v, n*sizeof(ArbFloat)); uwidth:=l+1; getmem(u, n*uwidth*sizeof(ArbFloat)); eigbs2(a, n, l, k1, k2, plam^[1], term); { kijk of norm(A-lambda.I)=0 } { zo ja, lever dan de eenheidsvectoren e(k1) t/m e(k2) af } norm:=0; j:=1; for i:=1 to n do begin if i<=l then m:=i else m:=l+1; s:=0; for k:=j to j+m-1 do if k=j+m-1 then s:=s+abs(pa^[k]-plam^[1]) else s:=s+abs(pa^[k]); if s>norm then norm:=s; j:=j+m end; if norm=0 then begin for i:=k1 to k2 do for j:=1 to n do if j=i then px^[(j-1)*rwidthx+i-k1+1]:=1 else px^[(j-1)*rwidthx+i-k1+1]:=0; freemem(v, n*sizeof(ArbFloat)); freemem(u, n*uwidth*sizeof(ArbFloat)); m2:=k2; term:=1; exit end; transf(a, n, l, u^[1], uwidth); i:=k1; m2:=k1-1; while (i <= k2) and (term=1) do begin bandev(u^[1], n, l, uwidth, plam^[i-k1+1], v^[1], term); if term=1 then begin m2:=i; for j:=1 to n do px^[(j-1)*rwidthx+i-k1+1]:=v^[j] end; i:=i+1 end; {i} freemem(v, n*sizeof(ArbFloat)); freemem(u, n*uwidth*sizeof(ArbFloat)); end; {eigbs4} procedure eigge1(var a: ArbFloat; n, rwidth: ArbInt; var lam: complex; var term: ArbInt); var pa, h, dummy : ^arfloat1; i, ns : ArbInt; begin if n<1 then begin term:=3; exit end; ns:=n*sizeof(ArbFloat); pa:=@a; getmem(dummy, ns); getmem(h, n*ns); for i:=1 to n do move(pa^[(i-1)*rwidth+1], h^[(i-1)*n+1], ns); orthes(h^[1], n, n, dummy^[1]); hessva(h^[1], n, n, lam, term); freemem(dummy, ns); freemem(h, n*ns); end; {eigge1} procedure eigge3(var a: ArbFloat; n, rwidtha: ArbInt; var lam, x: complex; rwidthx: ArbInt; var term: ArbInt); var pa, pd, u, v: ^arfloat1; m1, m2, i, ns: ArbInt; begin if n<1 then begin term:=3; exit end; ns:=n*sizeof(ArbFloat); getmem(pd, ns); getmem(u, n*ns); getmem(v, n*ns); pa:=@a; for i:=1 to n do move(pa^[(i-1)*rwidtha+1], u^[(i-1)*n+1], ns); balance(u^[1], n, n, m1, m2, pd^[1]); orttrans(u^[1], n, n, v^[1], n); hessvec(u^[1], n, n, lam, v^[1], n, term); if term=1 then begin balback(pd^[1], n, m1, m2, 1, n, v^[1], n); normeer(lam, n, v^[1], n); transx(v^[1], n, n, lam, x, rwidthx) end; freemem(pd, ns); freemem(u, n*ns); freemem(v, n*ns); end; {eigge3} procedure eiggg1(var a: ArbFloat; n, rwidtha: ArbInt; var b: ArbFloat; rwidthb: ArbInt; var lam: ArbFloat; var term: ArbInt); var u, v, pa, pb : ^arfloat1; i, ns : ArbInt; begin if n<1 then begin term:=3; exit end; pa:=@a; pb:=@b; ns:=n*sizeof(ArbFloat); getmem(u, n*ns); getmem(v, n*ns); for i:=1 to n do move(pa^[(i-1)*rwidtha+1], u^[(i-1)*n+1], ns); for i:=1 to n do move(pb^[(i-1)*rwidthb+1], v^[(i-1)*n+1], ns); reduc1(u^[1], n, n, v^[1], n, term); if term=1 then eiggs1(u^[1], n, n, lam, term); freemem(u, n*ns); freemem(v, n*ns); end; {eiggg1} procedure eiggg2(var a: ArbFloat; n, rwidtha, k1, k2: ArbInt; var b: ArbFloat; rwidthb: ArbInt; var lam: ArbFloat; var term: ArbInt); var u, v, pa, pb : ^arfloat1; i, ns : ArbInt; begin if (n<1) or (k1<1) or (k2n) then begin term:=3; exit end; pa:=@a; pb:=@b; ns:=n*sizeof(ArbFloat); getmem(u, n*ns); getmem(v, n*ns); for i:=1 to n do move(pa^[(i-1)*rwidtha+1], u^[(i-1)*n+1], ns); for i:=1 to n do move(pb^[(i-1)*rwidthb+1], v^[(i-1)*n+1], ns); reduc1(u^[1], n, n, v^[1], n, term); if term=1 then eiggs2(u^[1], n, n, k1, k2, lam, term); freemem(u, n*ns); freemem(v, n*ns) end; {eiggg2} procedure eiggg3(var a: ArbFloat; n, rwidtha: ArbInt; var b: ArbFloat; rwidthb: ArbInt; var lam, x: ArbFloat; rwidthx: ArbInt; var term: ArbInt); var u, v, pa, pb : ^arfloat1; i, ns : ArbInt; begin if n<1 then begin term:=3; exit end; pa:=@a; pb:=@b; ns:=n*sizeof(ArbFloat); getmem(u, n*ns); getmem(v, n*ns); for i:=1 to n do move(pa^[(i-1)*rwidtha+1], u^[(i-1)*n+1], ns); for i:=1 to n do move(pb^[(i-1)*rwidthb+1], v^[(i-1)*n+1], ns); reduc1(u^[1], n, n, v^[1], n, term); if term=1 then begin eiggs3(u^[1], n, n, lam, x, rwidthx, term); if term=1 then rebaka(v^[1], n, n, 1, n, x, rwidthx, term) end; freemem(u, n*ns); freemem(v, n*ns) end; {eiggg3} procedure eiggg4(var a: ArbFloat; n, rwidtha, k1, k2: ArbInt; var b: ArbFloat; rwidthb: ArbInt; var lam, x: ArbFloat; rwidthx: ArbInt; var m2, term: ArbInt); var u, v, pa, pb : ^arfloat1; i, ns, t : ArbInt; begin if (n<1) or (k1<1) or (k2n) then begin term:=3; exit end; pa:=@a; pb:=@b; ns:=n*sizeof(ArbFloat); getmem(u, n*ns); getmem(v, n*ns); for i:=1 to n do move(pa^[(i-1)*rwidtha+1], u^[(i-1)*n+1], ns); for i:=1 to n do move(pb^[(i-1)*rwidthb+1], v^[(i-1)*n+1], ns); reduc1(u^[1], n, n, v^[1], n, term); if term=1 then begin eiggs4(u^[1], n, n, k1, k2, lam, x, rwidthx, m2, term); if m2 < k2 then term:=4; if m2 > k1-1 then begin rebaka(v^[1], n, n, k1, m2, x, rwidthx, t); if t=2 then begin term:=4; m2:=k1-1 end end end; freemem(u, n*ns); freemem(v, n*ns) end; {eiggg4} procedure eigsv1(var a: ArbFloat; m, n, rwidth: ArbInt; var sig: ArbFloat; var term: ArbInt); var pa, pq, u, e : ^arfloat1; i, j, k, l, ns, ii, jj, kk : ArbInt; c, f, g, h, p, s, x, y, z, eps, tol : ArbFloat; conv, goon, cancel : boolean; begin if (n<1) or (m x then x:=y end; {i} eps:=macheps*x; for k:=n downto 1 do begin conv:=false; repeat l:=k; goon:=true; while goon do begin if abs(e^[l]) <= eps then begin goon:=false; cancel:=false end else if abs(pq^[l-1]) <= eps then begin goon:=false; cancel:=true end else l:=l-1 end; {goon} if cancel then begin c:=0; s:=1; i:=l; goon:=true; while goon do begin f:=s*e^[i]; e^[i]:=c*e^[i]; goon:=abs(f) > eps; if goon then begin g:=pq^[i]; h:=sqrt(f*f+g*g); pq^[i]:=h; c:=g/h; s:=-f/h; i:=i+1; goon:=i <= k end {goon} end {while goon} end; {cancel} z:=pq^[k]; if k=l then conv:=true else begin x:=pq^[l]; y:=pq^[k-1]; g:=e^[k-1]; h:=e^[k]; f:=((y-z)*(y+z)+(g-h)*(g+h))/(2*h*y); g:=sqrt(f*f+1); if f < 0 then s:=f-g else s:=f+g; f:=((x-z)*(x+z)+h*(y/s-h))/x; c:=1; s:=1; for i:=l+1 to k do begin g:=e^[i]; y:=pq^[i]; h:=s*g; g:=c*g; z:=sqrt(f*f+h*h); e^[i-1]:=z; c:=f/z; s:=h/z; f:=x*c+g*s; g:=-x*s+g*c; h:=y*s; y:=y*c; z:=sqrt(f*f+h*h); pq^[i-1]:=z; c:=f/z; s:=h/z; f:=c*g+s*y; x:=-s*g+c*y end; {i} e^[l]:=0; e^[k]:=f; pq^[k]:=x end {k <> l} until conv; if z < 0 then pq^[k]:=-z end; {k} for i:=1 to n do begin k:=i; p:=pq^[i]; for j:=i+1 to n do if pq^[j] < p then begin k:=j; p:=pq^[j] end; if k <> i then begin pq^[k]:=pq^[i]; pq^[i]:=p end end; {i} freemem(e, ns); freemem(u, m*ns) end; {eigsv1} procedure eigsv3(var a: ArbFloat; m, n, rwidtha: ArbInt; var sig, u: ArbFloat; rwidthu: ArbInt; var v: ArbFloat; rwidthv: ArbInt; var term: ArbInt); var pa, pu, pq, pv, e : ^arfloat1; i, j, k, l, ns, ii, jj, kk : ArbInt; c, f, g, h, p, s, x, y, z, eps, tol : ArbFloat; conv, goon, cancel : boolean; begin if (n<1) or (m x then x:=y end; {i} for i:=n downto 1 do begin ii:=(i-1)*rwidthu; if g <> 0 then begin h:=pu^[ii+i+1]*g; for j:=i+1 to n do pv^[(j-1)*rwidthv+i]:=pu^[ii+j]/h; for j:=i+1 to n do begin s:=0; for k:=i+1 to n do s:=s+pu^[ii+k]*pv^[(k-1)*rwidthv+j]; for k:=i+1 to n do begin kk:=(k-1)*rwidthv; pv^[kk+j]:=pv^[kk+j]+s*pv^[kk+i] end {k} end {j} end; {g} ii:=(i-1)*rwidthv; for j:=i+1 to n do begin pv^[ii+j]:=0; pv^[(j-1)*rwidthv+i]:=0 end; {j} pv^[ii+i]:=1; g:=e^[i] end; {i} for i:=n downto 1 do begin g:=pq^[i]; ii:=(i-1)*rwidthu; for j:=i+1 to n do pu^[ii+j]:=0; if g <> 0 then begin h:=pu^[ii+i]*g; for j:=i+1 to n do begin s:=0; for k:=i+1 to m do begin kk:=(k-1)*rwidthu; s:=s+pu^[kk+i]*pu^[kk+j] end; {k} f:=s/h; for k:=i to m do begin kk:=(k-1)*rwidthu; pu^[kk+j]:=pu^[kk+j]+f*pu^[kk+i] end {k} end; {j} for j:=i to m do begin jj:=(j-1)*rwidthu+i; pu^[jj]:=pu^[jj]/g end {j} end {g} else for j:=i to m do pu^[(j-1)*rwidthu+i]:=0; pu^[ii+i]:=pu^[ii+i]+1 end; {i} eps:=macheps*x; for k:=n downto 1 do begin conv:=false; repeat l:=k; goon:=true; while goon do begin if abs(e^[l]) <= eps then begin goon:=false; cancel:=false end else if abs(pq^[l-1]) <= eps then begin goon:=false; cancel:=true end else l:=l-1 end; {goon} if cancel then begin c:=0; s:=1; i:=l; goon:=true; while goon do begin f:=s*e^[i]; e^[i]:=c*e^[i]; goon:=abs(f) > eps; if goon then begin g:=pq^[i]; h:=sqrt(f*f+g*g); pq^[i]:=h; c:=g/h; s:=-f/h; for j:=1 to m do begin jj:=(j-1)*rwidthu; y:=pu^[jj+l-1]; z:=pu^[jj+i]; pu^[jj+l-1]:=y*c+z*s; pu^[jj+i]:=-y*s+z*c end; {j} i:=i+1; goon:=i <= k end {goon} end {while goon} end; {cancel} z:=pq^[k]; if k=l then conv:=true else begin x:=pq^[l]; y:=pq^[k-1]; g:=e^[k-1]; h:=e^[k]; f:=((y-z)*(y+z)+(g-h)*(g+h))/(2*h*y); g:=sqrt(f*f+1); if f < 0 then s:=f-g else s:=f+g; f:=((x-z)*(x+z)+h*(y/s-h))/x; c:=1; s:=1; for i:=l+1 to k do begin g:=e^[i]; y:=pq^[i]; h:=s*g; g:=c*g; z:=sqrt(f*f+h*h); e^[i-1]:=z; c:=f/z; s:=h/z; f:=x*c+g*s; g:=-x*s+g*c; h:=y*s; y:=y*c; for j:=1 to n do begin jj:=(j-1)*rwidthv; x:=pv^[jj+i-1]; z:=pv^[jj+i]; pv^[jj+i-1]:=x*c+z*s; pv^[jj+i]:=-x*s+z*c end; {j} z:=sqrt(f*f+h*h); pq^[i-1]:=z; c:=f/z; s:=h/z; f:=c*g+s*y; x:=-s*g+c*y; for j:=1 to m do begin jj:=(j-1)*rwidthu; y:=pu^[jj+i-1]; z:=pu^[jj+i]; pu^[jj+i-1]:=y*c+z*s; pu^[jj+i]:=-y*s+z*c end {j} end; {i} e^[l]:=0; e^[k]:=f; pq^[k]:=x end {k <> l} until conv; if z < 0 then begin pq^[k]:=-z; for j:=1 to n do begin jj:=(j-1)*rwidthv+k; pv^[jj]:=-pv^[jj] end {j} end {z} end; {k} for i:=1 to n do begin k:=i; p:=pq^[i]; for j:=i+1 to n do if pq^[j] < p then begin k:=j; p:=pq^[j] end; if k <> i then begin pq^[k]:=pq^[i]; pq^[i]:=p; for j:=1 to m do begin jj:=(j-1)*rwidthu; p:=pu^[jj+i]; pu^[jj+i]:=pu^[jj+k]; pu^[jj+k]:=p; end; for j:=1 to n do begin jj:=(j-1)*rwidthv; p:=pv^[jj+i]; pv^[jj+i]:=pv^[jj+k]; pv^[jj+k]:=p end { interchange in u and v column i with comlumn k } end end; {i} freemem(e, ns) end; {eigsv3} end.