eigh2.pas 29 KB

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