eigh1.pas 29 KB

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