eigh2.pas 29 KB

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