eigh2.pas 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848
  1. {
  2. This file is part of the Numlib package.
  3. Copyright (c) 1986-2000 by
  4. Kees van Ginneken, Wil Kortsmit and Loek van Reij of the
  5. Computational centre of the Eindhoven University of Technology
  6. FPC port Code by Marco van de Voort ([email protected])
  7. Documentation by Michael van Canneyt ([email protected])
  8. This is a helper unit for the unit eig. These functions aren't documented,
  9. so if you find out what it does, please mail it to us.
  10. See the file COPYING.FPC, included in this distribution,
  11. for details about the copyright.
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  15. **********************************************************************}
  16. unit eigh2;
  17. {$I DIRECT.INC}
  18. interface
  19. uses typ;
  20. procedure orthes(var a: ArbFloat; n, rwidth: ArbInt; var u: ArbFloat);
  21. procedure hessva(var h: ArbFloat; n, rwidth: ArbInt; var lam: complex;
  22. var term: ArbInt);
  23. procedure balance(var a: ArbFloat; n, rwidtha: ArbInt; var low, hi: ArbInt;
  24. var d: ArbFloat);
  25. procedure orttrans(var a: ArbFloat; n, rwidtha: ArbInt; var q: ArbFloat;
  26. rwidthq: ArbInt);
  27. procedure balback(var pd: ArbFloat; n, m1, m2, k1, k2: ArbInt; var pdx: ArbFloat;
  28. rwidth: ArbInt);
  29. procedure hessvec(var h: ArbFloat; n, rwidthh: ArbInt; var lam: complex;
  30. var v: ArbFloat; rwidthv: ArbInt; var term: ArbInt);
  31. procedure normeer(var lam: complex; n: ArbInt; var v: ArbFloat;
  32. rwidthv: ArbInt);
  33. procedure transx(var v: ArbFloat; n, rwidthv: ArbInt; var lam, x: complex;
  34. rwidthx: ArbInt);
  35. procedure reduc1(var a: ArbFloat; n, rwidtha: ArbInt; var b: ArbFloat;
  36. rwidthb: ArbInt; var term: ArbInt);
  37. procedure rebaka(var l: ArbFloat; n, rwidthl, k1, k2: ArbInt; var x: ArbFloat;
  38. rwidthx: ArbInt; var term: ArbInt);
  39. implementation
  40. procedure orthes(var a: ArbFloat; n, rwidth: ArbInt; var u: ArbFloat);
  41. var pa, pu, d : ^arfloat1;
  42. sig, sig2, h, f, g, tol : ArbFloat;
  43. k, i, j : ArbInt;
  44. begin
  45. pa:=@a; pu:=@u; tol:=midget/macheps;
  46. getmem(d, n*sizeof(ArbFloat));
  47. for k:=1 to n-2 do
  48. begin
  49. sig2:=0;
  50. for i:=k+2 to n do
  51. begin
  52. d^[i]:=pa^[(i-1)*rwidth+k]; f:=d^[i]; sig2:=sig2+sqr(f)
  53. end; {i}
  54. if sig2<tol then
  55. begin
  56. pu^[k]:=0; for i:=k+2 to n do pa^[(i-1)*rwidth+k]:=0
  57. end else
  58. begin
  59. f:=pa^[k*rwidth+k]; sig2:=sig2+sqr(f);
  60. if f<0 then sig:=sqrt(sig2) else sig:=-sqrt(sig2);
  61. pa^[k*rwidth+k]:=sig;
  62. h:=sig2-f*sig; d^[k+1]:=f-sig; pu^[k]:=d^[k+1];
  63. for j:=k+1 to n do
  64. begin
  65. f:=0; for i:=k+1 to n do f:=f+d^[i]*pa^[(i-1)*rwidth+j]; f:=f/h;
  66. for i:=k+1 to n do pa^[(i-1)*rwidth+j]:=pa^[(i-1)*rwidth+j]-f*d^[i]
  67. end; {j}
  68. for i:=1 to n do
  69. begin
  70. f:=0; for j:=k+1 to n do f:=f+d^[j]*pa^[(i-1)*rwidth+j]; f:=f/h;
  71. for j:=k+1 to n do pa^[(i-1)*rwidth+j]:=pa^[(i-1)*rwidth+j]-f*d^[j]
  72. end {i}
  73. end
  74. end; {k}
  75. freemem(d, n*sizeof(ArbFloat));
  76. end {orthes};
  77. procedure hessva(var h: ArbFloat; n, rwidth: ArbInt; var lam: complex;
  78. var term: ArbInt);
  79. var i, j, k, kk, k1, k2, k3, l, m, mr,
  80. ik, nn, na, n1, n2, its : ArbInt;
  81. meps, p, q, r, s, t, w, x, y, z : ArbFloat;
  82. test, notlast : boolean;
  83. ph : ^arfloat1;
  84. plam : ^arcomp1;
  85. begin
  86. ph:=@h; plam:=@lam;
  87. t:=0; term:=1; meps:=macheps; nn:=n;
  88. while (nn >= 1) and (term=1) do
  89. begin
  90. n1:=(nn-1)*rwidth; na:=nn-1; n2:=(na-1)*rwidth;
  91. its:=0;
  92. repeat
  93. l:=nn+1; test:=true;
  94. while test and (l>2) do
  95. begin
  96. l:=l-1;
  97. test:=abs(ph^[(l-1)*(rwidth+1)]) >
  98. meps*(abs(ph^[(l-2)*rwidth+l-1])+abs(ph^[(l-1)*rwidth+l]))
  99. end;
  100. if (l=2) and test then l:=l-1;
  101. if l<na then
  102. begin
  103. x:=ph^[n1+nn]; y:=ph^[n2+na]; w:=ph^[n1+na]*ph^[n2+nn];
  104. if (its=10) or (its=20) then
  105. begin
  106. {form exceptional shift}
  107. t:=t+x;
  108. for i:=1 to nn do ph^[(i-1)*rwidth+i]:=ph^[(i-1)*rwidth+i]-x;
  109. s:=abs(ph^[n1+na])+abs(ph^[n1+nn-2]);
  110. y:=0.75*s; x:=y; w:=-0.4375*sqr(s);
  111. end; {shift}
  112. {look for two consecutive small sub-diag elmts}
  113. m:=nn-1; test:= true ;
  114. repeat
  115. m:=m-1; mr:=m*rwidth;
  116. z:=ph^[mr-rwidth+m]; r:=x-z; s:=y-z;
  117. p:=(r*s-w)/ph^[mr+m]+ph^[mr-rwidth+m+1];
  118. q:=ph^[mr+m+1]-z-r-s; r:=ph^[mr+rwidth+m+1];
  119. s:=abs(p)+abs(q)+abs(r); p:=p/s; q:=q/s; r:=r/s;
  120. if m <> l then
  121. test:=abs(ph^[mr-rwidth+m-1])*(abs(q)+abs(r)) <=
  122. meps*abs(p)*(abs(ph^[mr-2*rwidth+m-1])+abs(z)+
  123. abs(ph^[mr+m+1]))
  124. until (m=l) or test;
  125. for i:=m+2 to nn do ph^[(i-1)*rwidth+i-2]:=0;
  126. for i:=m+3 to nn do ph^[(i-1)*rwidth+i-3]:=0;
  127. { double qp-step involving rows l to nn and columns m to nn}
  128. for k:=m to na do
  129. begin
  130. notlast:=k <> na;
  131. if k <> m then
  132. begin
  133. p:=ph^[(k-1)*(rwidth+1)]; q:=ph^[k*rwidth+k-1];
  134. if notlast then r:=ph^[(k+1)*rwidth+k-1] else r:=0;
  135. x:=abs(p)+abs(q)+abs(r);
  136. if x>0 then
  137. begin
  138. p:=p/x; q:=q/x; r:=r/x
  139. end
  140. end else x:=1;
  141. if x>0 then
  142. begin
  143. s:=sqrt(p*p+q*q+r*r); if p<0 then s:=-s;
  144. if k <> m then ph^[(k-1)*(rwidth+1)]:=-s*x else
  145. if l <> m then
  146. begin
  147. kk:=(k-1)*(rwidth+1); ph^[kk]:=-ph^[kk]
  148. end;
  149. p:=p+s; x:=p/s; y:=q/s; z:=r/s; q:=q/p; r:=r/p;
  150. { row moxification}
  151. for j:=k to nn do
  152. begin
  153. k1:=(k-1)*rwidth+j; k2:=k1+rwidth; k3:=k2+rwidth;
  154. p:=ph^[k1]+q*ph^[k2];
  155. if notlast then
  156. begin
  157. p:=p+r*ph^[k3]; ph^[k3]:=ph^[k3]-p*z;
  158. end;
  159. ph^[k2]:=ph^[k2]-p*y; ph^[k1]:=ph^[k1]-p*x;
  160. end; {j}
  161. if k+3<nn then j:=k+3 else j:=nn;
  162. { column modification}
  163. for i:=l to j do
  164. begin
  165. ik:=(i-1)*rwidth+k;
  166. p:=x*ph^[ik]+y*ph^[ik+1];
  167. if notlast then
  168. begin
  169. p:=p+z*ph^[ik+2]; ph^[ik+2]:=ph^[ik+2]-p*r;
  170. end;
  171. ph^[ik+1]:=ph^[ik+1]-p*q; ph^[ik]:=ph^[ik]-p;
  172. end {i}
  173. end {x <> 0}
  174. end {k};
  175. end; {l < na}
  176. its:=its+1
  177. until (l=na) or (l=nn) or (its=30);
  178. if l=nn then
  179. begin { one root found}
  180. plam^[nn].Init(ph^[n1+nn]+t, 0); nn:=na
  181. end else
  182. if l=na then
  183. begin { two roots found}
  184. x:=ph^[n1+nn]; y:=ph^[n2+na]; w:=ph^[n1+na]*ph^[n2+nn];
  185. p:=(y-x)/2; q:=p*p+w; y:=sqrt(abs(q)); x:=x+t;
  186. if q>0 then
  187. begin { ArbFloat pair}
  188. if p<0 then y:=-y; y:=p+y;
  189. plam^[na].Init(x+y, 0); plam^[nn].Init(x-w/y, 0)
  190. end else
  191. begin { complex pair}
  192. plam^[na].Init(x+p, y); plam^[nn].Init(x+p, -y)
  193. end;
  194. nn:=nn-2
  195. end else term:=2
  196. end {while }
  197. end {hessva};
  198. procedure balance(var a: ArbFloat; n, rwidtha: ArbInt; var low, hi: ArbInt;
  199. var d: ArbFloat);
  200. const radix = 2;
  201. var i, j, k, l, ii, jj: ArbInt;
  202. b2, b, c, f, g, r, s: ArbFloat;
  203. pa, pd: ^arfloat1;
  204. nonconv, cont: boolean;
  205. procedure exc(j, k: ArbInt);
  206. var i, ii, jj, kk: ArbInt;
  207. h: ArbFloat;
  208. begin
  209. pd^[k]:=j;
  210. if j <> k then
  211. begin
  212. for i:=1 to n do
  213. begin
  214. ii:=(i-1)*rwidtha;
  215. h:=pa^[ii+j]; pa^[ii+j]:=pa^[ii+k]; pa^[ii+k]:=h
  216. end; {i}
  217. for i:=1 to n do
  218. begin
  219. jj:=(j-1)*rwidtha+i; kk:=(k-1)*rwidtha+i;
  220. h:=pa^[jj]; pa^[jj]:=pa^[kk]; pa^[kk]:=h
  221. end; {i}
  222. end {j <> k}
  223. end {exc};
  224. begin
  225. pa:=@a; pd:=@d; b:=radix; b2:=b*b; l:=1; k:=n; cont:=true;
  226. while cont do
  227. begin
  228. j:=k+1;
  229. repeat
  230. j:=j-1; r:=0; jj:=(j-1)*rwidtha;
  231. for i:=1 to j-1 do r:=r+abs(pa^[jj+i]);
  232. for i:=j+1 to k do r:=r+abs(pa^[jj+i]);
  233. until (r=0) or (j=1);
  234. if r=0 then
  235. begin
  236. exc(j,k); k:=k-1
  237. end;
  238. cont:=(r=0) and (k >= 1);
  239. end;
  240. cont:= true ;
  241. while cont do
  242. begin
  243. j:=l-1;
  244. repeat
  245. j:=j+1; r:=0;
  246. for i:=l to j-1 do r:=r+abs(pa^[(i-1)*rwidtha+j]);
  247. for i:=j+1 to k do r:=r+abs(pa^[(i-1)*rwidtha+j])
  248. until (r=0) or (j=k);
  249. if r=0 then
  250. begin
  251. exc(j,l); l:=l+1
  252. end;
  253. cont:=(r=0) and (l <= k);
  254. end;
  255. for i:=l to k do pd^[i]:=1;
  256. low:=l; hi:=k; nonconv:=l <= k;
  257. while nonconv do
  258. begin
  259. for i:=l to k do
  260. begin
  261. c:=0; r:=0;
  262. for j:=l to i-1 do
  263. begin
  264. c:=c+abs(pa^[(j-1)*rwidtha+i]);
  265. r:=r+abs(pa^[(i-1)*rwidtha+j])
  266. end;
  267. for j:=i+1 to k do
  268. begin
  269. c:=c+abs(pa^[(j-1)*rwidtha+i]);
  270. r:=r+abs(pa^[(i-1)*rwidtha+j])
  271. end;
  272. g:=r/b; f:=1; s:=c+r;
  273. while c<g do
  274. begin
  275. f:=f*b; c:=c*b2
  276. end;
  277. g:=r*b;
  278. while c >= g do
  279. begin
  280. f:=f/b; c:=c/b2
  281. end;
  282. if (c+r)/f<0.95*s then
  283. begin
  284. g:=1/f; pd^[i]:=pd^[i]*f; ii:=(i-1)*rwidtha;
  285. for j:=l to n do pa^[ii+j]:=pa^[ii+j]*g;
  286. for j:=1 to k do pa^[(j-1)*rwidtha+i]:=pa^[(j-1)*rwidtha+i]*f;
  287. end else nonconv:=false
  288. end
  289. end {while}
  290. end; {balance}
  291. procedure orttrans(var a: ArbFloat; n, rwidtha: ArbInt; var q: ArbFloat;
  292. rwidthq: ArbInt);
  293. var i, j, k : ArbInt;
  294. sig, sig2, f, g, h, tol : ArbFloat;
  295. pa, pq, d : ^arfloat1;
  296. begin
  297. pa:=@a; pq:=@q; tol:=midget/macheps;
  298. getmem(d, n*sizeof(ArbFloat));
  299. for k:=1 to n-2 do
  300. begin
  301. sig2:=0;
  302. for i:=k+2 to n do
  303. begin
  304. d^[i]:=pa^[(i-1)*rwidtha+k]; f:=d^[i]; sig2:=sig2+sqr(f)
  305. end;
  306. if sig2<tol then
  307. begin
  308. d^[k+1]:=0; for i:=k+2 to n do pa^[(i-1)*rwidtha+k]:=0
  309. end else
  310. begin
  311. f:=pa^[k*rwidtha+k]; sig2:=sig2+sqr(f);
  312. if f<0 then sig:=sqrt(sig2) else sig:=-sqrt(sig2);
  313. pa^[k*rwidtha+k]:=sig; h:=sig2-f*sig; d^[k+1]:=f-sig;
  314. for j:=k+1 to n do
  315. begin
  316. f:=0; for i:=k+1 to n do f:=f+d^[i]*pa^[(i-1)*rwidtha+j];
  317. f:=f/h;
  318. for i:=k+1 to n do
  319. pa^[(i-1)*rwidtha+j]:=pa^[(i-1)*rwidtha+j]-f*d^[i];
  320. end;
  321. for i:=1 to n do
  322. begin
  323. f:=0; for j:=k+1 to n do f:=f+d^[j]*pa^[(i-1)*rwidtha+j];
  324. f:=f/h;
  325. for j:=k+1 to n do
  326. pa^[(i-1)*rwidtha+j]:=pa^[(i-1)*rwidtha+j]-f*d^[j];
  327. end
  328. end
  329. end; {k}
  330. for i:=1 to n do
  331. begin
  332. pq^[(i-1)*rwidthq+i]:=1;
  333. for j:=1 to i-1 do
  334. begin
  335. pq^[(i-1)*rwidthq+j]:=0; pq^[(j-1)*rwidthq+i]:=0
  336. end
  337. end;
  338. for k:=n-2 downto 1 do
  339. begin
  340. h:=pa^[k*rwidtha+k]*d^[k+1];
  341. if h <> 0
  342. then
  343. begin
  344. for i:=k+2 to n do d^[i]:=pa^[(i-1)*rwidtha+k];
  345. for i:=k+2 to n do pa^[(i-1)*rwidtha+k]:=0;
  346. for j:=k+1 to n do
  347. begin
  348. f:=0; for i:=k+1 to n do f:=f+d^[i]*pq^[(i-1)*rwidthq+j];
  349. f:=f/h;
  350. for i:=k+1 to n do
  351. pq^[(i-1)*rwidthq+j]:=pq^[(i-1)*rwidthq+j]+f*d^[i]
  352. end
  353. end
  354. end;
  355. freemem(d, n*sizeof(ArbFloat));
  356. end; {orttrans}
  357. procedure balback(var pd: ArbFloat; n, m1, m2, k1, k2: ArbInt; var pdx: ArbFloat;
  358. rwidth: ArbInt);
  359. var i, j, k, ii, kk: ArbInt;
  360. s: ArbFloat;
  361. ppd, ppdx: ^arfloat1;
  362. begin
  363. ppd:=@pd; ppdx:=@pdx;
  364. for i:=m1 to m2 do
  365. begin
  366. ii:=(i-1)*rwidth; s:=ppd^[i];
  367. for j:=k1 to k2 do ppdx^[ii+j]:=ppdx^[ii+j]*s;
  368. end;
  369. for i:=m1-1 downto 1 do
  370. begin
  371. k:=round(ppd^[i]); ii:=(i-1)*rwidth; kk:=(k-1)*rwidth;
  372. if k <> i then
  373. for j:=k1 to k2 do
  374. begin
  375. s:=ppdx^[ii+j]; ppdx^[ii+j]:=ppdx^[kk+j]; ppdx^[kk+j]:=s
  376. end
  377. end;
  378. for i:=m2+1 to n do
  379. begin
  380. k:=round(ppd^[i]); ii:=(i-1)*rwidth; kk:=(k-1)*rwidth;
  381. if k <> i then
  382. for j:=k1 to k2 do
  383. begin
  384. s:=ppdx^[ii+j]; ppdx^[ii+j]:=ppdx^[kk+j]; ppdx^[kk+j]:=s
  385. end
  386. end
  387. end; {balback}
  388. procedure cdiv(xr, xi, yr, yi: ArbFloat; var zr, zi: ArbFloat);
  389. var h:ArbFloat;
  390. begin
  391. if abs(yr)>abs(yi) then
  392. begin
  393. h:=yi/yr; yr:=h*yi+yr;
  394. zr:=(xr+h*xi)/yr; zi:=(xi-h*xr)/yr;
  395. end else
  396. begin
  397. h:=yr/yi; yi:=h*yr+yi;
  398. zr:=(h*xr+xi)/yi; zi:=(h*xi-xr)/yi
  399. end
  400. end; {cdiv}
  401. procedure hessvec(var h: ArbFloat; n, rwidthh: ArbInt; var lam: complex;
  402. var v: ArbFloat; rwidthv: ArbInt; var term: ArbInt);
  403. var iterate, stop, notlast, contin: boolean;
  404. i, j, k, l, m, na, its, en, n1, n2, ii, kk, ll,
  405. ik, i1, k0, k1, k2, mr: ArbInt;
  406. meps, p, q, r, s, t, w, x, y, z, ra, sa, vr, vi, norm: ArbFloat;
  407. ph, pv: ^arfloat1;
  408. plam : ^arcomp1;
  409. begin
  410. ph:=@h; pv:=@v; plam:=@lam;
  411. term:=1; en:=n; t:=0; meps:=macheps;
  412. while (term=1) and (en>=1) do
  413. begin
  414. its:=0; na:=en-1; iterate:=true;
  415. while iterate and (term=1) do
  416. begin
  417. l:=en; contin:=true;
  418. while (l>=2) and contin do
  419. begin
  420. ll:=(l-1)*rwidthh+l;
  421. if abs(ph^[ll-1])>meps*(abs(ph^[ll-rwidthh-1])+abs(ph^[ll]))
  422. then l:=l-1 else contin:=false
  423. end;
  424. n1:=(na-1)*rwidthh; n2:=(en-1)*rwidthh; x:=ph^[n2+en];
  425. if l=en then
  426. begin
  427. iterate:=false; plam^[en].Init(x+t, 0); ph^[n2+en]:=x+t;
  428. en:=en-1
  429. end else
  430. if l=en-1 then
  431. begin
  432. iterate:=false; y:=ph^[n1+na]; w:=ph^[n2+na]*ph^[n1+en];
  433. p:=(y-x)/2; q:=p*p+w; z:=sqrt(abs(q)); x:=x+t;
  434. ph^[n2+en]:=x; ph^[n1+na]:=y+t;
  435. if q>0 then
  436. begin
  437. if p<0 then z:=p-z else z:=p+z; plam^[na].Init(x+z, 0);
  438. s:=x-w/z; plam^[en].Init(s, 0);
  439. x:=ph^[n2+na]; r:=sqrt(x*x+z*z); p:=x/r; q:=z/r;
  440. for j:=na to n do
  441. begin
  442. z:=ph^[n1+j]; ph^[n1+j]:=q*z+p*ph^[n2+j];
  443. ph^[n2+j]:=q*ph^[n2+j]-p*z
  444. end;
  445. for i:=1 to en do
  446. begin
  447. ii:=(i-1)*rwidthh;
  448. z:=ph^[ii+na]; ph^[ii+na]:=q*z+p*ph^[ii+en];
  449. ph^[ii+en]:=q*ph^[ii+en]-p*z;
  450. end;
  451. for i:=1 to n do
  452. begin
  453. ii:=(i-1)*rwidthv;
  454. z:=pv^[ii+na]; pv^[ii+na]:=q*z+p*pv^[ii+en];
  455. pv^[ii+en]:=q*pv^[ii+en]-p*z;
  456. end
  457. end {q>0}
  458. else
  459. begin
  460. plam^[na].Init(x+p, z); plam^[en].Init(x+p, -z)
  461. end;
  462. en:=en-2;
  463. end {l=en-1}
  464. else
  465. begin
  466. y:=ph^[n1+na]; w:=ph^[n1+en]*ph^[n2+na];
  467. if (its=10) or (its=20)
  468. then
  469. begin
  470. t:=t+x;
  471. for i:=1 to en do
  472. ph^[(i-1)*rwidthh+i]:=ph^[(i-1)*rwidthh+i]-x;
  473. s:=abs(ph^[n2+na])+abs(ph^[n1+en-2]);
  474. y:=0.75*s; x:=y; w:=-0.4375*s*s;
  475. end;
  476. m:=en-1; stop:=false;
  477. repeat
  478. m:=m-1; mr:=m*rwidthh;
  479. z:=ph^[mr-rwidthh+m]; r:=x-z; s:=y-z;
  480. p:=(r*s-w)/ph^[mr+m]+ph^[mr-rwidthh+m+1];
  481. q:=ph^[mr+m+1]-z-r-s; r:=ph^[mr+rwidthh+m+1];
  482. s:=abs(p)+abs(q)+abs(r); p:=p/s; q:=q/s; r:=r/s;
  483. if m>l then
  484. stop:=abs(ph^[mr-rwidthh+m-1])*(abs(q)+abs(r))<=
  485. meps*abs(p)*(abs(ph^[mr-2*rwidthh+m-1])+
  486. abs(z)+abs(ph^[mr+m+1]))
  487. until stop or (m=l);
  488. for i:=m+2 to en do ph^[(i-1)*rwidthh+i-2]:=0;
  489. for i:=m+3 to en do ph^[(i-1)*rwidthh+i-3]:=0;
  490. for k:=m to na do
  491. begin
  492. k0:=(k-1)*rwidthh; k1:=k0+rwidthh; k2:=k1+rwidthh;
  493. notlast:=k<na; contin:=true;
  494. if k>m then
  495. begin
  496. p:=ph^[k0+k-1]; q:=ph^[k1+k-1];
  497. if notlast then r:=ph^[k2+k-1] else r:=0;
  498. x:=abs(p)+abs(q)+abs(r);
  499. if x>0 then
  500. begin
  501. p:=p/x; q:=q/x; r:=r/x
  502. end else contin:=false
  503. end;
  504. if contin then
  505. begin
  506. s:=sqrt(p*p+q*q+r*r);
  507. if p<0 then s:=-s;
  508. if k>m then ph^[k0+k-1]:=-s*x else
  509. if l <> m then ph^[k0+k-1]:=-ph^[k0+k-1];
  510. p:=p+s; x:=p/s; y:=q/s; z:=r/s; q:=q/p; r:=r/p;
  511. for j:=k to n do
  512. begin
  513. p:=ph^[k0+j]+q*ph^[k1+j];
  514. if notlast then
  515. begin
  516. p:=p+r*ph^[k2+j];
  517. ph^[k2+j]:=ph^[k2+j]-p*z
  518. end;
  519. ph^[k1+j]:=ph^[k1+j]-p*y;
  520. ph^[k0+j]:=ph^[k0+j]-p*x
  521. end; {j}
  522. if k+3<en then j:=k+3 else j:=en;
  523. for i:=1 to j do
  524. begin
  525. ik:=(i-1)*rwidthh+k;
  526. p:=x*ph^[ik]+y*ph^[ik+1];
  527. if notlast then
  528. begin
  529. p:=p+z*ph^[ik+2]; ph^[ik+2]:=ph^[ik+2]-p*r
  530. end;
  531. ph^[ik+1]:=ph^[ik+1]-p*q; ph^[ik]:=ph^[ik]-p
  532. end; {i}
  533. for i:=1 to n do
  534. begin
  535. ik:=(i-1)*rwidthv+k;
  536. p:=x*pv^[ik]+y*pv^[ik+1];
  537. if notlast then
  538. begin
  539. p:=p+z*pv^[ik+2]; pv^[ik+2]:=pv^[ik+2]-p*r
  540. end;
  541. pv^[ik+1]:=pv^[ik+1]-p*q; pv^[ik]:=pv^[ik]-p
  542. end {i}
  543. end {contin}
  544. end; {k}
  545. its:=its+1; if its >= 30 then term:=2
  546. end {ifl}
  547. end {iterate}
  548. end; {term=1}
  549. if term=1 then
  550. begin
  551. norm:=0; k:=1;
  552. for i:=1 to n do
  553. begin
  554. for j:=k to n do norm:=norm+abs(ph^[(i-1)*rwidthh+j]);
  555. k:=i
  556. end;
  557. if norm=0 then
  558. begin
  559. { matrix is nulmatrix: eigenwaarden zijn alle 0 en aan de
  560. eigenvectoren worden de eenheidsvectoren toegekend }
  561. for i:=1 to n do plam^[i].Init(0, 0);
  562. for i:=1 to n do
  563. fillchar(pv^[(i-1)*rwidthv+1], n*sizeof(ArbFloat), 0);
  564. for i:=1 to n do pv^[(i-1)*rwidthv+i]:=1;
  565. exit
  566. end; {norm=0}
  567. for en:=n downto 1 do
  568. begin
  569. p:=plam^[en].re; q:=plam^[en].im; na:=en-1;
  570. n1:=(na-1)*rwidthh; n2:=(en-1)*rwidthh;
  571. if q=0 then
  572. begin
  573. m:=en; ph^[n2+en]:=1;
  574. for i:=na downto 1 do
  575. begin
  576. ii:=(i-1)*rwidthh; i1:=ii+rwidthh;
  577. w:=ph^[ii+i]-p; r:=ph^[ii+en];
  578. for j:=m to na do r:=r+ph^[ii+j]*ph^[(j-1)*rwidthh+en];
  579. if plam^[i].im < 0 then
  580. begin
  581. z:=w; s:=r
  582. end else
  583. begin
  584. m:=i; if plam^[i].im=0 then
  585. if w=0 then ph^[ii+en]:=-r/(meps*norm)
  586. else ph^[ii+en]:=-r/w else
  587. begin
  588. x:=ph^[ii+i+1]; y:=ph^[i1+i];
  589. q:=sqr(plam^[i].xreal-p)+sqr(plam^[i].imag);
  590. ph^[ii+en]:=(x*s-z*r)/q; t:=ph^[ii+en];
  591. if abs(x)>abs(z) then ph^[i1+en]:=(-r-w*t)/x
  592. else ph^[i1+en]:=(-s-y*t)/z;
  593. end {plam^[i].imag > 0}
  594. end {plam^[i].imag >= 0}
  595. end {i}
  596. end {q=0}
  597. else
  598. if q<0 then
  599. begin
  600. m:=na;
  601. if abs(ph^[n2+na]) > abs(ph^[n1+en]) then
  602. begin
  603. ph^[n1+na]:=-(ph^[n2+en]-p)/ph^[n2+na];
  604. ph^[n1+en]:=-q/ph^[n2+na];
  605. end else
  606. cdiv(-ph^[n1+en], 0, ph^[n1+na]-p, q,
  607. ph^[n1+na], ph^[n1+en]);
  608. ph^[n2+na]:=1; ph^[n2+en]:=0;
  609. for i:=na-1 downto 1 do
  610. begin
  611. ii:=(i-1)*rwidthh; i1:=ii+rwidthh;
  612. w:=ph^[ii+i]-p; ra:=ph^[ii+en]; sa:=0;
  613. for j:=m to na do
  614. begin
  615. ra:=ra+ph^[ii+j]*ph^[(j-1)*rwidthh+na];
  616. sa:=sa+ph^[ii+j]*ph^[(j-1)*rwidthh+en]
  617. end;
  618. if plam^[i].imag < 0 then
  619. begin
  620. z:=w; r:=ra; s:=sa
  621. end else
  622. begin
  623. m:=i;
  624. if plam^[i].imag=0
  625. then cdiv(-ra, -sa, w, q, ph^[ii+na], ph^[ii+en])
  626. else
  627. begin
  628. x:=ph^[ii+i+1]; y:=ph^[i1+i];
  629. vr:=sqr(plam^[i].xreal-p)+sqr(plam^[i].imag)-q*q;
  630. vi:=(plam^[i].xreal-p)*q*2;
  631. if (vr=0) and (vi=0)
  632. then
  633. vr:=meps*norm*(abs(w)+abs(q)+abs(x)+
  634. abs(y)+abs(z));
  635. cdiv(x*r-z*ra+q*sa, x*s-z*sa-q*ra, vr, vi,
  636. ph^[ii+na], ph^[ii+en]);
  637. if abs(x)>abs(z)+abs(q)
  638. then
  639. begin
  640. ph^[i1+na]:=(-ra-w*ph^[ii+na]+q*ph^[ii+en])/x;
  641. ph^[i1+en]:=(-sa-w*ph^[ii+en]-q*ph^[ii+na])/x
  642. end
  643. else
  644. cdiv(-r-y*ph^[ii+na], -s-y*ph^[ii+en],
  645. z, q, ph^[i1+na], ph^[i1+en])
  646. end {plam^[i].imag > 0}
  647. end {plam^[i].imag >= 0}
  648. end {i}
  649. end
  650. end {backsubst};
  651. for j:=n downto 1 do
  652. begin
  653. m:=j; l:=j-1;
  654. if plam^[j].imag < 0 then
  655. begin
  656. for i:=1 to n do
  657. begin
  658. ii:=(i-1)*rwidthv; y:=0; z:=0;
  659. for k:=1 to m do
  660. begin
  661. kk:=(k-1)*rwidthh;
  662. y:=y+pv^[ii+k]*ph^[kk+l];
  663. z:=z+pv^[ii+k]*ph^[kk+j]
  664. end;
  665. pv^[ii+l]:=y; pv^[ii+j]:=z
  666. end {i}
  667. end else
  668. if plam^[j].imag=0 then
  669. for i:=1 to n do
  670. begin
  671. z:=0;
  672. ii:=(i-1)*rwidthv;
  673. for k:=1 to m do z:=z+pv^[ii+k]*ph^[(k-1)*rwidthh+j];
  674. pv^[ii+j]:=z;
  675. end {i}
  676. end {j}
  677. end {term=1}
  678. end; {hessvec}
  679. procedure normeer(var lam: complex; n: ArbInt; var v: ArbFloat;
  680. rwidthv: ArbInt);
  681. var i, j, k, ii, kk: ArbInt;
  682. max, s, t, vr, vi: ArbFloat;
  683. pv: ^arfloat1;
  684. plam: ^arcomp1;
  685. begin
  686. plam:=@lam; pv:=@v; j:=1;
  687. while j<=n do
  688. if plam^[j].imag=0 then
  689. begin
  690. s:=0; for i:=1 to n do s:=s+sqr(pv^[(i-1)*rwidthv+j]); s:=sqrt(s);
  691. for i:=1 to n do pv^[(i-1)*rwidthv+j]:=pv^[(i-1)*rwidthv+j]/s;
  692. j:=j+1
  693. end else
  694. begin
  695. max:=0; s:=0;
  696. for i:=1 to n do
  697. begin
  698. ii:=(i-1)*rwidthv;
  699. t:=sqr(pv^[ii+j])+sqr(pv^[ii+j+1]); s:=s+t;
  700. if t>max then
  701. begin
  702. max:=t; k:=i
  703. end
  704. end;
  705. kk:=(k-1)*rwidthv;
  706. s:=sqrt(max/s); t:=pv^[kk+j+1]/s; s:=pv^[kk+j]/s;
  707. for i:=1 to n do
  708. begin
  709. ii:=(i-1)*rwidthv;
  710. vr:=pv^[ii+j]; vi:=pv^[ii+j+1];
  711. cdiv(vr, vi, s, t, pv^[ii+j], pv^[ii+j+1]);
  712. end;
  713. pv^[kk+j+1]:=0; j:=j+2;
  714. end
  715. end; {normeer}
  716. procedure transx(var v: ArbFloat; n, rwidthv: ArbInt; var lam, x: complex;
  717. rwidthx: ArbInt);
  718. var i, j, ix, iv : ArbInt;
  719. pv : ^arfloat1;
  720. plam, px : ^arcomp1;
  721. begin
  722. pv:=@v; plam:=@lam; px:=@x;
  723. for i:=1 to n do
  724. if plam^[i].imag > 0 then
  725. for j:=1 to n do
  726. begin
  727. iv:=(j-1)*rwidthv+i; ix:=(j-1)*rwidthx+i;
  728. px^[ix].xreal:=pv^[iv]; px^[ix].imag:=pv^[iv+1]
  729. end else
  730. if plam^[i].imag < 0 then
  731. for j:=1 to n do
  732. begin
  733. iv:=(j-1)*rwidthv+i; ix:=(j-1)*rwidthx+i;
  734. px^[ix].xreal:=pv^[iv-1]; px^[ix].imag:=-pv^[iv]
  735. end else
  736. for j:=1 to n do
  737. begin
  738. iv:=(j-1)*rwidthv+i; ix:=(j-1)*rwidthx+i;
  739. px^[ix].xreal:=pv^[iv]; px^[ix].imag:=0
  740. end
  741. end; {transx}
  742. procedure reduc1(var a: ArbFloat; n, rwidtha: ArbInt; var b: ArbFloat;
  743. rwidthb: ArbInt; var term: ArbInt);
  744. var i, j, k, ia, ja, ib, jb : ArbInt;
  745. x, y : ArbFloat;
  746. pa, pb : ^arfloat1;
  747. begin
  748. pa:=@a; pb:=@b;
  749. term:=1; i:=0;
  750. while (i<n) and (term=1) do
  751. begin
  752. i:=i+1; j:=i-1; jb:=(j-1)*rwidthb; ib:=(i-1)*rwidthb;
  753. while (j<n) and (term=1) do
  754. begin
  755. j:=j+1; jb:=jb+rwidthb; x:=pb^[jb+i];
  756. for k:=1 to i-1 do x:=x-pb^[ib+k]*pb^[jb+k];
  757. if i=j then
  758. begin
  759. if x<=0 then term:=2 else
  760. begin
  761. y:=sqrt(x); pb^[ib+i]:=y
  762. end
  763. end else pb^[jb+i]:=x/y
  764. end {j}
  765. end; {i}
  766. if term=1 then
  767. begin
  768. for i:=1 to n do
  769. begin
  770. ib:=(i-1)*rwidthb; y:=pb^[ib+i];
  771. for j:=i to n do
  772. begin
  773. ja:=(j-1)*rwidtha; x:=pa^[ja+i];
  774. for k:=i-1 downto 1 do x:=x-pb^[ib+k]*pa^[ja+k];
  775. pa^[ja+i]:=x/y;
  776. end {j}
  777. end; {i}
  778. for j:=1 to n do
  779. begin
  780. ja:=(j-1)*rwidtha;
  781. for i:=j to n do
  782. begin
  783. ia:=(i-1)*rwidtha; ib:=(i-1)*rwidthb; x:=pa^[ia+j];
  784. for k:=i-1 downto j do x:=x-pa^[(k-1)*rwidtha+j]*pb^[ib+k];
  785. for k:=j-1 downto 1 do x:=x-pa^[ja+k]*pb^[ib+k];
  786. pa^[ia+j]:=x/pb^[ib+i]
  787. end {i}
  788. end {j}
  789. end {term=1};
  790. end; {reduc1}
  791. procedure rebaka(var l: ArbFloat; n, rwidthl, k1, k2: ArbInt; var x: ArbFloat;
  792. rwidthx: ArbInt; var term: ArbInt);
  793. var pl, px : ^arfloat1;
  794. i, j, k, il, ix : ArbInt;
  795. y : ArbFloat;
  796. begin
  797. pl:=@l; px:=@x; term:=1; il:=1;
  798. for i:=1 to n do
  799. begin
  800. if pl^[il]=0 then
  801. begin
  802. term:=2; exit
  803. end;
  804. il:=il+rwidthl+1
  805. end; {i}
  806. for j:=1 to k2-k1+1 do
  807. for i:=n downto 1 do
  808. begin
  809. il:=(i-1)*rwidthl; ix:=(i-1)*rwidthx; y:=px^[ix+j];
  810. for k:=i+1 to n do y:=y-pl^[(k-1)*rwidthl+i]*px^[(k-1)*rwidthx+j];
  811. px^[ix+j]:=y/pl^[il+i]
  812. end
  813. end; {rebaka}
  814. end.