2
0

eigh1.pas 29 KB

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