eigh1.pas 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921
  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. The 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 eigh1;
  17. {$I DIRECT.INC}
  18. interface
  19. uses typ;
  20. procedure tred1(var a: ArbFloat; n, rwidth: ArbInt; var d, cd: ArbFloat;
  21. var term: ArbInt);
  22. procedure tred2(var a: ArbFloat; n, rwidtha: ArbInt; var d, cd, x: ArbFloat;
  23. rwidthx: ArbInt; var term: ArbInt);
  24. procedure tql1(var d, cd: ArbFloat; n: ArbInt;
  25. var lam: ArbFloat; var term: ArbInt);
  26. procedure tql2(var d, cd: ArbFloat; n: ArbInt; var lam, x: ArbFloat;
  27. rwidth: ArbInt; var term: ArbInt);
  28. procedure bisect(var d, cd: ArbFloat; n, k1, k2: ArbInt; eps: ArbFloat;
  29. var lam: ArbFloat; var term: ArbInt);
  30. procedure trbak1(var a: ArbFloat; n, rwidtha: ArbInt; var cd: ArbFloat;
  31. k1, k2: ArbInt; var x: ArbFloat; rwidthx: ArbInt);
  32. procedure trsturm1(var d, cd: ArbFloat; n, k1, k2: ArbInt; var lam: ArbFloat;
  33. var x: ArbFloat; rwidth: ArbInt; var m2, term: ArbInt);
  34. procedure transf(var a: ArbFloat; n, l: ArbInt; var b: ArbFloat; rwidthb: ArbInt);
  35. procedure bandrd1(var a: ArbFloat; n, m, rwidth: ArbInt; var d, cd: ArbFloat);
  36. procedure bandrd2(var a: ArbFloat; n, m, rwidtha: ArbInt; var d, cd, x: ArbFloat;
  37. rwidthx: ArbInt);
  38. procedure bandev(var a: ArbFloat; n, m, rwidth: ArbInt; lambda: ArbFloat;
  39. var v: ArbFloat; var term: ArbInt);
  40. implementation
  41. procedure tred1(var a: ArbFloat; n, rwidth: ArbInt; var d, cd: ArbFloat;
  42. var term: ArbInt);
  43. var i, ii, jj, j, k, l, sr : ArbInt;
  44. f, g, h, tol : ArbFloat;
  45. pa, pd, pcd : ^arfloat1;
  46. begin
  47. if n<1 then
  48. begin
  49. term:=3; exit
  50. end; {wrong input}
  51. pa:=@a; pd:=@d; pcd:=@cd;
  52. sr:=sizeof(ArbFloat);
  53. tol:=midget/macheps;
  54. for i:=1 to n do pd^[i]:=pa^[(i-1)*rwidth+i];
  55. for i:=n downto 1 do
  56. begin
  57. ii:=(i-1)*rwidth; l:=i-2; h:=0;
  58. if i=1 then f:=0 else f:=pa^[ii+i-1];
  59. for k:=1 to l do h:=h+sqr(pa^[ii+k]);
  60. if h <= tol then
  61. begin
  62. pcd^[i]:=f;
  63. for j:=1 to i-1 do pa^[ii+j]:=0;
  64. end else
  65. begin
  66. h:=h+f*f; l:=l+1;
  67. if f<0 then g:=sqrt(h) else g:=-sqrt(h);
  68. pcd^[i]:=g;
  69. h:=h-f*g; pa^[ii+i-1]:=f-g; f:=0;
  70. for j:=1 to l do
  71. begin
  72. g:=0;
  73. for k:=1 to j do g:=g+pa^[(j-1)*rwidth+k]*pa^[ii+k];
  74. for k:=j+1 to l do g:=g+pa^[(k-1)*rwidth+j]*pa^[ii+k];
  75. g:=g/h; pcd^[j]:=g; f:=f+g*pa^[ii+j]
  76. end; {j}
  77. h:=f/(h+h);
  78. for j:=1 to l do
  79. begin
  80. jj:=(j-1)*rwidth;
  81. f:=pa^[ii+j]; pcd^[j]:=pcd^[j]-h*f; g:=pcd^[j];
  82. for k:=1 to j do pa^[jj+k]:=pa^[jj+k]-f*pcd^[k]-g*pa^[ii+k]
  83. end {j}
  84. end; {h > tol}
  85. h:=pd^[i]; pd^[i]:=pa^[ii+i]; pa^[ii+i]:=h
  86. end; {i}
  87. term:=1
  88. end; {tred1}
  89. procedure tred2(var a: ArbFloat; n, rwidtha: ArbInt; var d, cd, x: ArbFloat;
  90. rwidthx: ArbInt; var term: ArbInt);
  91. var i, j, k, l, ii, jj, kk : ArbInt;
  92. f , g, h, hh, tol : ArbFloat;
  93. pa, pd, pcd, px : ^arfloat1;
  94. begin
  95. if n<1 then
  96. begin
  97. term:=3; exit
  98. end;
  99. tol:=midget/macheps;
  100. pa:=@a; pd:=@d; pcd:=@cd; px:=@x;
  101. for i:=1 to n do
  102. move(pa^[1+(i-1)*rwidtha], px^[1+(i-1)*rwidthx], i*sizeof(ArbFloat));
  103. for i:=n downto 2 do
  104. begin
  105. l:=i-2; ii:=(i-1)*rwidthx; f:=px^[i-1+ii];
  106. g:=0; for k:=1 to l do g:=g+sqr(px^[k+ii]);
  107. h:=g+f*f;
  108. if g<=tol then
  109. begin
  110. pcd^[i]:=f; pd^[i]:=0
  111. end else
  112. begin
  113. l:=l+1; if f<0 then g:=sqrt(h) else g:=-sqrt(h);
  114. pcd^[i]:=g;
  115. h:=h-f*g; px^[i-1+ii]:=f-g; f:=0;
  116. for j:=1 to l do
  117. begin
  118. jj:=(j-1)*rwidthx; px^[i+jj]:=px^[j+ii]/h;
  119. g:=0; for k:=1 to j do g:=g+px^[k+jj]*px^[k+ii];
  120. for k:=j+1 to l do g:=g+px^[j+(k-1)*rwidthx]*px^[k+ii];
  121. pcd^[j]:=g/h; f:=f+g*px^[i+jj]
  122. end;
  123. hh:=f/(h+h);
  124. for j:=1 to l do
  125. begin
  126. jj:=(j-1)*rwidthx; f:=px^[j+ii];
  127. pcd^[j]:=pcd^[j]-hh*f; g:=pcd^[j];
  128. for k:=1 to j do px^[k+jj]:=px^[k+jj]-f*pcd^[k]-g*px^[k+ii]
  129. end;
  130. pd^[i]:=h
  131. end
  132. end;
  133. pd^[1]:=0; pcd^[1]:=0;
  134. for i:=1 to n do
  135. begin
  136. ii:=(i-1)*rwidthx; l:=i-1;
  137. if pd^[i] <> 0 then
  138. for j:=1 to l do
  139. begin
  140. g:=0; for k:=1 to l do g:=g+px^[k+ii]*px^[j+(k-1)*rwidthx];
  141. for k:=1 to l do
  142. begin
  143. kk:=(k-1)*rwidthx; px^[j+kk]:=px^[j+kk]-g*px^[i+kk]
  144. end
  145. end;
  146. pd^[i]:=px^[i+ii]; px^[i+ii]:=1;
  147. for j:=1 to l do
  148. begin
  149. px^[j+ii]:=0; px^[i+(j-1)*rwidthx]:=0
  150. end
  151. end;
  152. term:=1;
  153. end {tred2};
  154. procedure tql1(var d, cd: ArbFloat; n: ArbInt;
  155. var lam: ArbFloat; var term: ArbInt);
  156. var i, j, l, m : ArbInt;
  157. meps, b, c, f, g, h, p, r, s : ArbFloat;
  158. conv, shift : boolean;
  159. pd, pcd, plam : ^arfloat1;
  160. begin
  161. if n<1 then
  162. begin
  163. term:=3; exit
  164. end; {wrong input}
  165. pd:=@d; pcd:=@cd; plam:=@lam;
  166. conv:=true; meps:=macheps;
  167. for i:=2 to n do pcd^[i-1]:=pcd^[i];
  168. pcd^[n]:=0; f:=0; b:=0; l:=0;
  169. while (l<n) and conv do
  170. begin
  171. l:=l+1; j:=0; h:=meps*(abs(pd^[l])+abs(pcd^[l]));
  172. if b<h then b:=h;
  173. m:=l-1; repeat m:=m+1 until abs(pcd^[m]) <= b;
  174. while (abs(pcd^[l])>b) and conv do
  175. begin
  176. g:=pd^[l]; p:=(pd^[l+1]-g)/(2*pcd^[l]);
  177. if abs(p)>1 then r:=abs(p)*sqrt(1+sqr(1/p)) else r:=sqrt(sqr(p)+1);
  178. if p<0 then pd^[l]:=pcd^[l]/(p-r) else pd^[l]:=pcd^[l]/(p+r);
  179. h:=g-pd^[l];
  180. for i:=l+1 to n do pd^[i]:=pd^[i]-h;
  181. f:=f+h; p:=pd^[m]; c:=1; s:=0;
  182. for i:=m-1 downto l do
  183. begin
  184. g:=c*pcd^[i]; h:=c*p;
  185. if abs(p) >= abs(pcd^[i]) then
  186. begin
  187. c:=pcd^[i]/p; r:=sqrt(c*c+1);
  188. pcd^[i+1]:=s*p*r; s:=c/r; c:=1/r
  189. end
  190. else
  191. begin
  192. c:=p/pcd^[i]; r:=sqrt(c*c+1);
  193. pcd^[i+1]:=s*pcd^[i]*r; s:=1/r; c:=c/r
  194. end;
  195. p:=c*pd^[i]-s*g; pd^[i+1]:=h+s*(c*g+s*pd^[i])
  196. end; {i}
  197. pcd^[l]:=s*p; pd^[l]:=c*p; j:=j+1; conv:=j <= 30
  198. end; {while}
  199. if conv then
  200. begin
  201. p:=pd^[l]+f; i:=l; shift:=true;
  202. while shift and (i>1) do
  203. begin
  204. if p>=plam^[i-1] then shift:= false else plam^[i]:=plam^[i-1];
  205. i:=i-1
  206. end; {while}
  207. if not shift then plam^[i+1]:=p else plam^[i]:=p
  208. end {if conv}
  209. end; {l}
  210. if conv then term:=1 else term:=2
  211. end; {tql1}
  212. procedure tql2(var d, cd: ArbFloat; n: ArbInt; var lam, x: ArbFloat;
  213. rwidth: ArbInt; var term: ArbInt);
  214. var i, j, k, l, m, kk, ki, ki1, jj, ji, jk, sr, ns, n1s : ArbInt;
  215. conv : boolean;
  216. meps, b, c, f, g, h, p, r, s : ArbFloat;
  217. pd, pcd, plam, px, c1d, ccd : ^arfloat1;
  218. begin
  219. if n<1 then
  220. begin
  221. term:=3; exit
  222. end;
  223. sr:=sizeof(ArbFloat); ns:=n*sizeof(ArbFloat); n1s:=ns-sr;
  224. getmem(c1d, ns); getmem(ccd, ns);
  225. pd:=@d; pcd:=@cd; plam:=@lam; px:=@x;
  226. move(pcd^[2], ccd^[1], n1s); ccd^[n]:=0; move(pd^[1], c1d^[1], ns);
  227. conv:= true; meps:=macheps; f:=0; b:=0; l:=0;
  228. while (l<n) and conv do
  229. begin
  230. l:=l+1; j:=0; h:=meps*(abs(c1d^[l])+abs(ccd^[l]));
  231. if b<h then b:=h;
  232. m:=l; while abs(ccd^[m])>b do m:=m+1;
  233. while (abs(ccd^[l])>b) and conv do
  234. begin
  235. g:=c1d^[l]; p:=(c1d^[l+1]-g)/(2*ccd^[l]);
  236. if abs(p)>1
  237. then r:=abs(p)*sqrt(1+sqr(1/p)) else r:=sqrt(sqr(p)+1);
  238. if p<0 then c1d^[l]:=ccd^[l]/(p-r) else c1d^[l]:=ccd^[l]/(p+r);
  239. h:=g-c1d^[l];
  240. for i:=l+1 to n do c1d^[i]:=c1d^[i]-h;
  241. f:=f+h; p:=c1d^[m]; c:=1; s:=0;
  242. for i:=m-1 downto l do
  243. begin
  244. g:=c*ccd^[i]; h:=c*p;
  245. if abs(p)>=abs(ccd^[i]) then
  246. begin
  247. c:=ccd^[i]/p; r:=sqrt(c*c+1);
  248. ccd^[i+1]:=s*p*r; s:=c/r; c:=1/r
  249. end else
  250. begin
  251. c:=p/ccd^[i]; r:=sqrt(c*c+1);
  252. ccd^[i+1]:=s*ccd^[i]*r; s:=1/r; c:=c/r
  253. end;
  254. p:=c*c1d^[i]-s*g; c1d^[i+1]:=h+s*(c*g+s*c1d^[i]);
  255. for k:=1 to n do
  256. begin
  257. kk:=(k-1)*rwidth; ki:=i+kk; ki1:=ki+1;
  258. h:=px^[ki1]; px^[ki1]:=s*px^[ki]+c*h;
  259. px^[ki]:=c*px^[ki]-s*h
  260. end
  261. end;
  262. ccd^[l]:=s*p; c1d^[l]:=c*p; j:=j+1; conv:=j<=30
  263. end;
  264. if conv
  265. then
  266. plam^[l]:=c1d^[l]+f
  267. end;
  268. if conv then
  269. for i:=1 to n do
  270. begin
  271. k:=i; p:=plam^[i];
  272. for j:=i+1 to n do
  273. if plam^[j]<p then
  274. begin
  275. k:=j; p:=plam^[j]
  276. end;
  277. if k <> i then
  278. begin
  279. plam^[k]:=plam^[i]; plam^[i]:=p;
  280. for j:=1 to n do
  281. begin
  282. jj:=(j-1)*rwidth; ji:=i+jj; jk:=k+jj;
  283. p:=px^[ji]; px^[ji]:=px^[jk]; px^[jk]:=p
  284. end
  285. end
  286. end;
  287. if conv then term:=1 else term:=2;
  288. freemem(c1d, ns); freemem(ccd, ns)
  289. end; {tql2}
  290. procedure bisect(var d, cd: ArbFloat; n, k1, k2: ArbInt; eps: ArbFloat;
  291. var lam: ArbFloat; var term: ArbInt);
  292. var a, i, k, sr : ArbInt;
  293. pd, pcd, plam, codsq, xlower : ^arfloat1;
  294. meps, eps1, q, xmin, xmax,
  295. xl, xu, lambdak, h, diagi : ArbFloat;
  296. begin
  297. if (n<1) or (k1<1) or (k2<k1) or (k2>n) then
  298. begin
  299. term:=3; exit
  300. end; {wrong input}
  301. term:=1;
  302. pd:=@d; pcd:=@cd; plam:=@lam;
  303. sr:=sizeof(ArbFloat);
  304. getmem(codsq, n*sr); getmem(xlower, n*sr);
  305. meps:=macheps;
  306. for i:=2 to n do codsq^[i]:=sqr(pcd^[i]);
  307. xmin:=pd^[n]; xmax:=xmin;
  308. if n > 1 then
  309. begin
  310. h:=abs(pcd^[n]); xmin:=xmin-h; xmax:=xmax+h
  311. end ;
  312. for i:=n-1 downto 1 do
  313. begin
  314. h:=abs(pcd^[i+1]);
  315. if i<>1 then h:=h+abs(pcd^[i]);
  316. diagi:=pd^[i];
  317. if diagi-h<xmin then xmin:=diagi-h;
  318. if diagi+h>xmax then xmax:=diagi+h
  319. end; {i}
  320. if xmin+xmax>0 then eps1:=meps*xmax
  321. else eps1:=-meps*xmin;
  322. if eps <= 0 then eps:=eps1;
  323. for i:=k1 to k2 do
  324. begin
  325. plam^[i-k1+1]:=xmax; xlower^[i]:=xmin
  326. end;
  327. xu:=xmax;
  328. for k:=k2 downto k1 do
  329. begin
  330. if xu>plam^[k-k1+1] then xu:=plam^[k-k1+1];
  331. i:=k; repeat xl:=xlower^[i]; i:=i-1 until (i<k1) or (xl>xmin);
  332. while xu-xl>2*meps*(abs(xl)+abs(xu))+eps do
  333. begin
  334. lambdak:=xl+(xu-xl)/2; q:=pd^[1]-lambdak;
  335. if q<0 then a:=1 else a:=0;
  336. for i:=2 to n do
  337. begin
  338. if q=0 then q:=meps;
  339. q:=pd^[i]-lambdak-codsq^[i]/q;
  340. if q<0 then a:=a+1
  341. end; {i}
  342. if a<k then
  343. begin
  344. if a<k1 then
  345. begin
  346. xl:=lambdak; xlower^[k]:=lambdak
  347. end else
  348. begin
  349. xl:=lambdak; xlower^[a+1]:=lambdak;
  350. if plam^[a-k1+1]>lambdak then plam^[a-k1+1]:=lambdak
  351. end
  352. end else xu:=lambdak
  353. end; {while}
  354. plam^[k-k1+1]:=xl+(xu-xl)/2
  355. end; {k}
  356. freemem(codsq, n*sr); freemem(xlower, n*sr)
  357. end; {bisect}
  358. procedure trbak1(var a: ArbFloat; n, rwidtha: ArbInt; var cd: ArbFloat;
  359. k1, k2: ArbInt; var x: ArbFloat; rwidthx: ArbInt);
  360. var i, j, k, l, ii, ind : ArbInt;
  361. h, s : ArbFloat;
  362. pa, px, pcd : ^arfloat1;
  363. begin
  364. pa:=@a; px:=@x; pcd:=@cd;
  365. for i:=3 to n do
  366. begin
  367. ii:=(i-1)*rwidtha;
  368. l:=i-1; h:=pcd^[i]*pa^[ii+i-1];
  369. if h <> 0 then
  370. for j:=1 to k2-k1+1 do
  371. begin
  372. s:=0; for k:=1 to l do s:=s+pa^[ii+k]*px^[(k-1)*rwidthx+j]; s:=s/h;
  373. for k:=1 to l do
  374. begin
  375. ind:=(k-1)*rwidthx+j; px^[ind]:=px^[ind]+s*pa^[ii+k]
  376. end; {k}
  377. end {j}
  378. end {i}
  379. end; {trbak1}
  380. procedure trsturm1(var d, cd: ArbFloat; n, k1, k2: ArbInt; var lam: ArbFloat;
  381. var x: ArbFloat; rwidth: ArbInt; var m2, term: ArbInt);
  382. var
  383. ns, nb, a, i, k, s, its, group, j : ArbInt;
  384. continu, nonfail : boolean;
  385. eps1, eps2, eps3, eps4, q, xmin, xmax, xl, xu,
  386. x1, x0, u, v, norm, meps, lambdak, h, diagi, codiagi : ArbFloat;
  387. codsq, d1, e, f, y, z, xlower, pd, pcd, plam, px : ^arfloat1;
  388. int : ^arbool1;
  389. begin
  390. if (n<1) or (k1<1) or (k1>k2) or (k2>n) then
  391. begin
  392. term:=3; exit
  393. end; {wrong input}
  394. pd:=@d; pcd:=@cd; plam:=@lam; px:=@x;
  395. ns:=n*sizeof(ArbFloat); nb:=n*sizeof(boolean);
  396. getmem(codsq, ns); getmem(d1, ns); getmem(e, ns); getmem(f, ns);
  397. getmem(y, ns); getmem(z, ns); getmem(xlower, ns); getmem(int, nb);
  398. meps:=macheps;
  399. norm:=abs(pd^[1]);
  400. for i:=2 to n do norm:=norm+abs(pd^[i])+abs(pcd^[i]);
  401. if norm=0 then
  402. begin
  403. { matrix is nulmatrix: eigenwaarden zijn alle 0 en aan de
  404. eigenvectoren worden de eenheidsvectoren e(k1) t/m e(k2) toegekend }
  405. for k:=k1 to k2 do plam^[k-k1+1]:=0;
  406. for i:=1 to n do
  407. fillchar(px^[(i-1)*rwidth+1], (k2-k1+1)*sizeof(ArbFloat), 0);
  408. for k:=k1 to k2 do px^[(k-1)*rwidth+k-k1+1]:=1;
  409. m2:=k2; term:=1;
  410. freemem(codsq, ns); freemem(d1, ns); freemem(e, ns); freemem(f, ns);
  411. freemem(y, ns); freemem(z, ns); freemem(xlower, ns); freemem(int, nb);
  412. exit
  413. end; {norm=0}
  414. for i:=2 to n do codsq^[i]:=sqr(pcd^[i]);
  415. xmin:=pd^[n]; xmax:=xmin;
  416. if n>1 then
  417. begin
  418. h:=abs(pcd^[n]); xmin:=xmin-h; xmax:=xmax+h
  419. end;
  420. for i:=n-1 downto 1 do
  421. begin
  422. diagi:=pd^[i];
  423. h:=abs(pcd^[i+1]);
  424. if i<>1 then h:=h+abs(pcd^[i]);
  425. if diagi-h<xmin then xmin:=diagi-h;
  426. if diagi+h>xmax then xmax:=diagi+h;
  427. end; {i}
  428. if xmax+xmin>0 then eps1:=meps*xmax else eps1:=-meps*xmin;
  429. for i:=k1 to k2 do
  430. begin
  431. plam^[i-k1+1]:=xmax; xlower^[i]:=xmin
  432. end;
  433. xu:=xmax;
  434. for k:=k2 downto k1 do
  435. begin
  436. if xu>plam^[k-k1+1] then xu:=plam^[k-k1+1];
  437. i:=k; repeat xl:=xlower^[i]; i:=i-1 until (i<k1) or (xl>xmin);
  438. while xu-xl>2*eps1 do
  439. begin
  440. lambdak:=xl+(xu-xl)/2; q:=pd^[1]-lambdak;
  441. if q<0 then a:=1 else a:=0;
  442. for i:=2 to n do
  443. begin
  444. if q=0 then q:=meps;
  445. q:=pd^[i]-lambdak-codsq^[i]/q;
  446. if q<0 then a:=a+1;
  447. end; {i}
  448. if a<k then
  449. begin
  450. if a<k1 then
  451. begin
  452. xl:=lambdak; xlower^[k]:=lambdak
  453. end else
  454. begin
  455. xlower^[a+1]:=lambdak; xl:=lambdak;
  456. if plam^[a-k1+1]>lambdak then plam^[a-k1+1]:=lambdak
  457. end
  458. end else xu:=lambdak
  459. end; {while}
  460. plam^[k-k1+1]:=xl+(xu-xl)/2;
  461. end; {k}
  462. eps2:=norm*1e-3; eps3:=meps*norm; eps4:=eps3*n;
  463. group:=0; s:=1; k:=k1; nonfail:=true; m2:=k1-1;
  464. while (k <= k2) and nonfail do
  465. begin
  466. x1:=plam^[k-k1+1];
  467. if k <> k1 then
  468. begin
  469. if x1-x0<eps2 then group:=group+1 else group:=0;
  470. if x1 <= x0 then x1:=x0+eps3
  471. end; {k <> k1}
  472. u:=eps4/sqrt(n);
  473. for i:=1 to n do z^[i]:=u;
  474. u:=pd^[1]-x1;
  475. if n=1 then v:=0 else v:=pcd^[2];
  476. for i:=2 to n do
  477. begin
  478. if pcd^[i]=0 then codiagi:=eps3 else codiagi:=pcd^[i];
  479. if abs(codiagi) >= abs(u) then
  480. begin
  481. xu:=u/codiagi; y^[i]:=xu; d1^[i-1]:=codiagi;
  482. e^[i-1]:=pd^[i]-x1;
  483. if i=n then f^[i-1]:=0 else f^[i-1]:=pcd^[i+1];
  484. u:=v-xu*e^[i-1]; v:=-xu*f^[i-1];
  485. int^[i]:=true
  486. end else
  487. begin
  488. xu:=codiagi/u; y^[i]:=xu; d1^[i-1]:=u; e^[i-1]:=v;
  489. f^[i-1]:=0; u:=pd^[i]-x1-xu*v;
  490. if i<n then v:=pcd^[i+1];
  491. int^[i]:=false
  492. end
  493. end; {i}
  494. if u=0 then d1^[n]:=eps3 else d1^[n]:=u;
  495. e^[n]:=0; f^[n]:=0;
  496. its:=1; continu:=true;
  497. while continu and nonfail do
  498. begin
  499. for i:=n downto 1 do
  500. begin
  501. z^[i]:=(z^[i]-u*e^[i]-v*f^[i])/d1^[i]; v:=u; u:=z^[i]
  502. end;
  503. for j:=m2-group+1 to m2 do
  504. begin
  505. xu:=0;
  506. for i:=1 to n do xu:=xu+z^[i]*px^[(i-1)*rwidth+j-k1+1];
  507. for i:=1 to n do z^[i]:=z^[i]-xu*px^[(i-1)*rwidth+j-k1+1]
  508. end; {j}
  509. norm:=0; for i:=1 to n do norm:=norm+abs(z^[i]);
  510. if norm<1 then
  511. begin
  512. if norm=0 then
  513. begin
  514. z^[s]:=eps4;
  515. if s<n then s:=s+1 else s:=1
  516. end else
  517. begin
  518. xu:=eps4/norm;
  519. for i:=1 to n do z^[i]:=z^[i]*xu
  520. end;
  521. for i:=2 to n do
  522. if int^[i] then
  523. begin
  524. u:=z^[i-1]; z^[i-1]:=z^[i]; z^[i]:=u-y^[i]*z^[i]
  525. end else z^[i]:=z^[i]-y^[i]*z^[i-1];
  526. its:=its+1; if its=5 then nonfail:=false;
  527. end {norm < 1}
  528. else continu:=false
  529. end; {while continu ^ nonfail}
  530. if nonfail then
  531. begin
  532. u:=0; for i:=1 to n do u:=u+sqr(z^[i]);
  533. xu:=1/sqrt(u); m2:=m2+1;
  534. for i:=1 to n do px^[(i-1)*rwidth+m2-k1+1]:=z^[i]*xu;
  535. x0:=x1; k:=k+1;
  536. end
  537. end; {k}
  538. if m2=k2 then term:=1 else term:=2;
  539. freemem(codsq, ns); freemem(d1, ns); freemem(e, ns); freemem(f, ns);
  540. freemem(y, ns); freemem(z, ns); freemem(xlower, ns); freemem(int, nb);
  541. end {trsturm1};
  542. procedure transf(var a: ArbFloat; n, l: ArbInt; var b: ArbFloat; rwidthb: ArbInt);
  543. { a bevat de linksonder bandelementen van een symmetrische matrix A met
  544. lengte n en bandbreedte l, rijsgewijs aaneengesloten.
  545. na afloop bevatten de kolommen van b de diagonalen van A, met dien
  546. vestande dat de hoofddiagonaal van A in de eerste kolom van b staat,
  547. de een na langste codiagonaal in de tweede kolom
  548. (behalve de onderste plaats) enzovoort.
  549. De niet opgevulde plaatsen komen in b dus rechtsonder te staan. }
  550. var pa, pb: ^arfloat1;
  551. ii, jj, i, j, rwa: ArbInt;
  552. begin
  553. pa:=@a; pb:=@b;
  554. ii:=1; jj:=0;
  555. for i:=1 to n do
  556. begin
  557. if i>l then rwa:=l+1 else rwa:=i;
  558. if i>l+1 then jj:=jj+rwidthb else jj:=jj+1;
  559. for j:=1 to rwa do pb^[jj+(j-1)*(rwidthb-1)]:=pa^[ii+j-1];
  560. ii:=ii+rwa;
  561. end
  562. end;
  563. procedure banddek(n, m1, m2: ArbInt; var au, l: ArbFloat; var p: ArbInt);
  564. var pa, pl, norm: ^arfloat1;
  565. pp: ^arint1;
  566. i, j, ll, ii, k, t, pk, ind, ind1: ArbInt;
  567. piv, c, x, maxnorm: ArbFloat;
  568. begin
  569. pa:=@au; pl:=@l; pp:=@p;
  570. getmem(norm, n*sizeof(ArbFloat));
  571. t:=m1; ll:=m1+m2+1;
  572. for i:=1 to m1 do
  573. begin
  574. ind:=(i-1)*ll;
  575. for j:=m1+1-i to ll do pa^[ind+j-t]:=pa^[ind+j];
  576. t:=t-1;
  577. for j:=ll-t to ll do pa^[ind+j]:=0
  578. end;
  579. t:=1;
  580. for i:=n downto n-m2+1 do
  581. begin
  582. ind:=(i-1)*ll;
  583. for j:=t+m1+1 to ll do pa^[ind+j]:=0;
  584. t:=t+1
  585. end;
  586. maxnorm:=0;
  587. for k:=1 to n do
  588. begin
  589. c:=0; ind:=(k-1)*ll;
  590. for j:=1 to ll do c:=c+abs(pa^[ind+j]);
  591. if c>maxnorm then maxnorm:=c;
  592. if c=0 then norm^[k]:=1 else norm^[k]:=c
  593. end;
  594. t:=m1;
  595. for k:=1 to n do
  596. begin
  597. ind:=(k-1)*ll;
  598. x:=abs(pa^[ind+1])/norm^[k]; pk:=k;
  599. t:=t+1; if t>n then t:=n;
  600. for i:=k+1 to t do
  601. begin
  602. c:=abs(pa^[(i-1)*ll+1])/norm^[i];
  603. if c>x then
  604. begin
  605. x:=c; pk:=i
  606. end
  607. end;
  608. ind1:=(pk-1)*ll;
  609. pp^[k]:=pk;
  610. if pk <> k then
  611. begin
  612. for j:=1 to ll do
  613. begin
  614. c:=pa^[ind+j]; pa^[ind+j]:=pa^[ind1+j]; pa^[ind1+j]:=c
  615. end;
  616. norm^[pk]:=norm^[k]
  617. end;
  618. piv:=pa^[ind+1];
  619. if piv <> 0 then
  620. begin
  621. for i:=k+1 to t do
  622. begin
  623. ii:=(i-1)*ll;
  624. c:=pa^[ii+1]/piv; pl^[(k-1)*m1+i-k]:=c;
  625. for j:=2 to ll do pa^[ii+j-1]:=pa^[ii+j]-c*pa^[ind+j];
  626. pa^[ii+ll]:=0
  627. end
  628. end else
  629. begin
  630. pa^[ind+1]:=macheps*maxnorm;
  631. for i:=k+1 to t do
  632. begin
  633. ii:=(i-1)*ll;
  634. pl^[(k-1)*m1+i-k]:=0;
  635. for j:=2 to ll do pa^[ii+j-1]:=pa^[ii+j];
  636. pa^[ii+ll]:=0
  637. end {i}
  638. end {piv=0}
  639. end; {k}
  640. freemem(norm, n*sizeof(ArbFloat))
  641. end; {banddek}
  642. procedure bandsol(n, m1, m2: ArbInt; var au, l: ArbFloat;
  643. var p: ArbInt; var b: ArbFloat);
  644. var pa, pl, pb: ^arfloat1;
  645. pp: ^arint1;
  646. ll, i, j, k, pk, t, w: ArbInt;
  647. x: ArbFloat;
  648. begin
  649. pa:=@au; pl:=@l; pb:=@b; pp:=@p;
  650. for k:=1 to n do
  651. begin
  652. pk:=pp^[k];
  653. if pk <> k then
  654. begin
  655. x:=pb^[k]; pb^[k]:=pb^[pk]; pb^[pk]:=x
  656. end;
  657. t:=k+m1; if t>n then t:=n;
  658. for i:=k+1 to t do pb^[i]:=pb^[i]-pl^[(k-1)*m1+i-k]*pb^[k]
  659. end; {k}
  660. t:=1; ll:=m1+m2+1;
  661. for i:=n downto 1 do
  662. begin
  663. x:=pb^[i]; w:=i-1;
  664. for j:=2 to t do x:=x-pa^[(i-1)*ll+j]*pb^[j+w];
  665. pb^[i]:=x/pa^[(i-1)*ll+1];
  666. if t<ll then t:=t+1
  667. end {i}
  668. end; {bandsol}
  669. procedure bandrd1(var a: ArbFloat; n, m, rwidth: ArbInt; var d, cd: ArbFloat);
  670. { wilkinson linear algebra ii/8 procedure bandrd; matv = false }
  671. var j, k, l, r, maxr, maxl, ugl, ikr, jj, jj1, i, ll : ArbInt;
  672. b, c, s, s2, c2, cs, u, u1, g : ArbFloat;
  673. pa, pd, pcd : ^arfloat1;
  674. begin
  675. pa:=@a; pd:=@d; pcd:=@cd;
  676. for k:=1 to n-2 do
  677. begin
  678. if n-k<m then maxr:=n-k else maxr:=m;
  679. for r:=maxr downto 2 do
  680. begin
  681. ikr:=(k-1)*rwidth+r+1; g:=pa^[ikr]; j:=k+r;
  682. while (g <> 0) and (j <= n) do
  683. begin
  684. if j=k+r then
  685. begin
  686. b:=-pa^[ikr-1]/pa^[ikr]; ugl:=k
  687. end else
  688. begin
  689. b:=-pa^[(j-m-2)*rwidth+m+1]/g; ugl:=j-m
  690. end;
  691. s:=1/sqrt(1+b*b); c:=b*s; c2:=c*c; s2:=s*s; cs:=c*s;
  692. jj:=(j-1)*rwidth+1; jj1:=jj-rwidth;
  693. u:=c2*pa^[jj1]-2*cs*pa^[jj1+1]+s2*pa^[jj];
  694. u1:=s2*pa^[jj1]+2*cs*pa^[jj1+1]+c2*pa^[jj];
  695. pa^[jj1+1]:=cs*(pa^[jj1]-pa^[jj])+(c2-s2)*pa^[jj1+1];
  696. pa^[jj1]:=u; pa^[jj]:=u1;
  697. for l:=ugl to j-2 do
  698. begin
  699. ll:=(l-1)*rwidth+j-l+1;
  700. u:=c*pa^[ll-1]-s*pa^[ll];
  701. pa^[ll]:=s*pa^[ll-1]+c*pa^[ll];
  702. pa^[ll-1]:=u;
  703. end; {l}
  704. if j <> k+r then
  705. begin
  706. i:=(j-m-2)*rwidth+m+1; pa^[i]:=c*pa^[i]-s*g
  707. end;
  708. if n-j < m-1 then maxl:=n-j else maxl:=m-1;
  709. for l:=1 to maxl do
  710. begin
  711. u:=c*pa^[jj1+l+1]-s*pa^[jj+l];
  712. pa^[jj+l]:=s*pa^[jj1+l+1]+c*pa^[jj+l];
  713. pa^[jj1+l+1]:=u
  714. end; {l}
  715. if j+m <= n then
  716. begin
  717. g:=-s*pa^[jj+m]; pa^[jj+m]:=c*pa^[jj+m]
  718. end;
  719. j:=j+m;
  720. end {j}
  721. end {r}
  722. end; {k}
  723. pd^[1]:=pa^[1]; pcd^[1]:=0;
  724. for j:=2 to n do
  725. begin
  726. pd^[j]:=pa^[(j-1)*rwidth+1];
  727. if m>0 then pcd^[j]:=pa^[(j-2)*rwidth+2] else pcd^[j]:=0
  728. end {j}
  729. end; {bandrd1}
  730. procedure bandrd2(var a: ArbFloat; n, m, rwidtha: ArbInt; var d, cd, x: ArbFloat;
  731. rwidthx: ArbInt);
  732. { wilkinson linear algebra ii/8 procedure bandrd; matv = true }
  733. var j, k, l, r, maxr, maxl, ugl, ikr, jj, jj1, i, ll, ns : ArbInt;
  734. b, c, s, s2, c2, cs, u, u1, g : ArbFloat;
  735. pa, pd, pcd, px : ^arfloat1;
  736. begin
  737. pa:=@a; pd:=@d; pcd:=@cd; px:=@x; ns:=n*sizeof(ArbFloat);
  738. for j:=1 to n do fillchar(px^[(j-1)*rwidthx+1], ns, 0);
  739. for j:=1 to n do px^[(j-1)*rwidthx+j]:=1;
  740. for k:=1 to n-2 do
  741. begin
  742. if n-k<m then maxr:=n-k else maxr:=m;
  743. for r:=maxr downto 2 do
  744. begin
  745. ikr:=(k-1)*rwidtha+r+1; g:=pa^[ikr]; j:=k+r;
  746. while (g <> 0) and (j <= n) do
  747. begin
  748. if j=k+r then
  749. begin
  750. b:=-pa^[ikr-1]/pa^[ikr]; ugl:=k
  751. end else
  752. begin
  753. b:=-pa^[(j-m-2)*rwidtha+m+1]/g; ugl:=j-m
  754. end;
  755. s:=1/sqrt(1+b*b); c:=b*s; c2:=c*c; s2:=s*s; cs:=c*s;
  756. jj:=(j-1)*rwidtha+1; jj1:=jj-rwidtha;
  757. u:=c2*pa^[jj1]-2*cs*pa^[jj1+1]+s2*pa^[jj];
  758. u1:=s2*pa^[jj1]+2*cs*pa^[jj1+1]+c2*pa^[jj];
  759. pa^[jj1+1]:=cs*(pa^[jj1]-pa^[jj])+(c2-s2)*pa^[jj1+1];
  760. pa^[jj1]:=u; pa^[jj]:=u1;
  761. for l:=ugl to j-2 do
  762. begin
  763. ll:=(l-1)*rwidtha+j-l+1; u:=c*pa^[ll-1]-s*pa^[ll];
  764. pa^[ll]:=s*pa^[ll-1]+c*pa^[ll]; pa^[ll-1]:=u;
  765. end; {l}
  766. if j <> k+r then
  767. begin
  768. i:=(j-m-2)*rwidtha+m+1; pa^[i]:=c*pa^[i]-s*g
  769. end;
  770. if n-j < m-1 then maxl:=n-j else maxl:=m-1;
  771. for l:=1 to maxl do
  772. begin
  773. u:=c*pa^[jj1+l+1]-s*pa^[jj+l];
  774. pa^[jj+l]:=s*pa^[jj1+l+1]+c*pa^[jj+l];
  775. pa^[jj1+l+1]:=u
  776. end; {l}
  777. if j+m <= n then
  778. begin
  779. g:=-s*pa^[jj+m]; pa^[jj+m]:=c*pa^[jj+m]
  780. end;
  781. for l:=1 to n do
  782. begin
  783. ll:=(l-1)*rwidthx+j; u:=c*px^[ll-1]-s*px^[ll];
  784. px^[ll]:=s*px^[ll-1]+c*px^[ll]; px^[ll-1]:=u
  785. end; {ll}
  786. j:=j+m;
  787. end {j}
  788. end {r}
  789. end; {k}
  790. pd^[1]:=pa^[1]; pcd^[1]:=0;
  791. for j:=2 to n do
  792. begin
  793. pd^[j]:=pa^[(j-1)*rwidtha+1];
  794. if m>0 then pcd^[j]:=pa^[(j-2)*rwidtha+2] else pcd^[j]:=0
  795. end {j}
  796. end; {bandrd2}
  797. procedure bandev(var a: ArbFloat; n, m, rwidth: ArbInt; lambda: ArbFloat;
  798. var v: ArbFloat; var term: ArbInt);
  799. var pa, pv, au, l, u : ^arfloat1;
  800. p : ^arint1;
  801. ind, ii, i, k, t, j, its, w, sr, ns, ll : ArbInt;
  802. meps, eps, s, norm, lambdak, x, y, r1, d1, ca : ArbFloat;
  803. begin
  804. pa:=@a; pv:=@v;
  805. sr:=sizeof(ArbFloat); ns:=n*sr; ll:=2*m+1;
  806. getmem(au, ll*ns); getmem(l, m*ns); getmem(u, ns);
  807. getmem(p, n*sizeof(ArbInt));
  808. norm:=0; meps:=macheps;
  809. for i:=1 to n do
  810. begin
  811. s:=0; if i-m<1 then k:=i-1 else k:=m; ii:=(i-1)*rwidth;
  812. if n-i<m then w:=n-i+1 else w:=m+1;
  813. for j:=1 to w do s:=s+abs(pa^[ii+j]);
  814. for j:=1 to k do s:=s+abs(pa^[(i-j-1)*rwidth+j+1]);
  815. if s>norm then norm:=s
  816. end; {norm}
  817. eps:=norm*meps;
  818. if eps<midget then
  819. begin
  820. pv^[1]:=1;
  821. for j:=2 to n do pv^[j]:=0;
  822. term:=1;
  823. freemem(au, ll*ns); freemem(l, m*ns); freemem(u, ns);
  824. freemem(p, n*sizeof(ArbInt));
  825. exit
  826. end; {eps<midget}
  827. for i:=1 to n do
  828. begin
  829. if n-i<m then w:=n-i else w:=m;
  830. ind:=(i-1)*ll; ii:=(i-1)*rwidth;
  831. move(pa^[ii+2], au^[ind+m+2], w*sr);
  832. fillchar(au^[ind+m+w+2], (m-w)*sr, 0);
  833. if i-1<m then w:=i-1 else w:=m;
  834. for j:=1 to w do au^[ind+m-j+1]:=pa^[(i-j-1)*rwidth+j+1];
  835. fillchar(au^[ind+1], (m-w)*sr, 0);
  836. au^[ind+m+1]:=pa^[ii+1]-lambda
  837. end; {i}
  838. banddek(n, m, m, au^[1], l^[1], p^[1]);
  839. t:=-m;
  840. for i:=n downto 1 do
  841. begin
  842. ind:=(i-1)*ll;
  843. x:=1; w:=i+m;
  844. for j:=1-m to t do x:=x-au^[ind+m+j+1]*pv^[j+w];
  845. pv^[i]:=x/au^[ind+1];
  846. if t<m then t:=t+1
  847. end; {i}
  848. x:=0;
  849. for i:=1 to n do
  850. if abs(pv^[i])>abs(x) then
  851. begin
  852. x:=pv^[i]; j:=i
  853. end;
  854. its:=0; x:=1/x;
  855. for i:=1 to n do
  856. begin
  857. u^[i]:=x*pv^[i]; pv^[i]:=u^[i]
  858. end; {i}
  859. repeat
  860. bandsol(n, m, m, au^[1], l^[1], p^[1], pv^[1]);
  861. y:=1/pv^[j]; x:=0;
  862. for i:=1 to n do
  863. if abs(pv^[i])>abs(x) then
  864. begin
  865. x:=pv^[i]; j:=i
  866. end; {i}
  867. x:=1/x; d1:=0;
  868. for i:=1 to n do
  869. begin
  870. r1:=abs((u^[i]-y*pv^[i])*x);
  871. if r1>d1 then d1:=r1; u^[i]:=x*pv^[i]; pv^[i]:=u^[i]
  872. end; {i}
  873. its:=its+1
  874. until (d1<=eps) or (its>5);
  875. if d1<=eps then
  876. begin
  877. term:=1; x:=0; for i:=1 to n do x:=x+sqr(pv^[i]); x:=1/sqrt(x);
  878. for i:=1 to n do pv^[i]:=pv^[i]*x;
  879. end else term:=2;
  880. freemem(au, ll*ns); freemem(l, m*ns); freemem(u, ns);
  881. freemem(p, n*sizeof(ArbInt));
  882. end; {bandev}
  883. end.