mdt.pas 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962
  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. Unit with undocumented procedures. If you recognize the algoritms, please
  10. contact one of the above people.
  11. This is probably only one actual procedure/algoritm, but (faster)
  12. variants exist for special matrices. (like band, tridiagonal etc)
  13. Contrary to the other undocumented units, this unit is exported in the
  14. DLL.
  15. See the file COPYING.FPC, included in this distribution,
  16. for details about the copyright.
  17. This program is distributed in the hope that it will be useful,
  18. but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  20. **********************************************************************}
  21. Unit mdt;
  22. interface
  23. {$I DIRECT.INC}
  24. uses typ, dsl, omv;
  25. Procedure mdtgen(n, rwidth: ArbInt; Var alu: ArbFloat; Var p: ArbInt;
  26. Var ca:ArbFloat; Var term: ArbInt);
  27. Procedure mdtgtr(n: ArbInt; Var l, d, u, l1, d1, u1, u2: ArbFloat;
  28. Var p: boolean; Var ca: ArbFloat; Var term: ArbInt);
  29. Procedure mdtgsy(n, rwidth: ArbInt; Var a: ArbFloat; Var pp:ArbInt;
  30. Var qq:boolean; Var ca:ArbFloat; Var term:ArbInt);
  31. Procedure mdtgpd(n, rwidth: ArbInt; Var al, ca: ArbFloat; Var term: ArbInt);
  32. Procedure mdtgba(n, lb, rb, rwa: ArbInt; Var a: ArbFloat; rwl: ArbInt;
  33. Var l:ArbFloat; Var p: ArbInt; Var ca: ArbFloat; Var term:ArbInt);
  34. Procedure mdtgpb(n, lb, rwidth: ArbInt; Var al, ca: ArbFloat;
  35. Var term: ArbInt);
  36. Procedure mdtdtr(n: ArbInt; Var l, d, u, l1, d1, u1: ArbFloat;
  37. Var term:ArbInt);
  38. implementation
  39. Procedure mdtgen(n, rwidth: ArbInt; Var alu: ArbFloat; Var p: ArbInt;
  40. Var ca:ArbFloat; Var term: ArbInt);
  41. Var
  42. indi, indk, nsr, ind, i, j, k, indexpivot : ArbInt;
  43. normr, sumrowi, pivot, l, normt, maxim, h, s : ArbFloat;
  44. palu, sumrow, t : ^arfloat1;
  45. pp : ^arint1;
  46. singular : boolean;
  47. Begin
  48. If (n<1) Or (rwidth<1) Then
  49. Begin
  50. term := 3;
  51. exit
  52. End; {wrong input}
  53. palu := @alu;
  54. pp := @p;
  55. nsr := n*sizeof(ArbFloat);
  56. getmem(sumrow, nsr);
  57. getmem(t, nsr);
  58. normr := 0;
  59. singular := false ;
  60. For i:=1 To n Do
  61. Begin
  62. ind := (i-1)*rwidth;
  63. pp^[i] := i;
  64. sumrowi := 0;
  65. For j:=1 To n Do
  66. sumrowi := sumrowi+abs(palu^[ind+j]);
  67. sumrow^[i] := sumrowi;
  68. h := 2*random-1;
  69. t^[i] := sumrowi*h;
  70. h := abs(h);
  71. If normr<h Then normr := h;
  72. If sumrowi=0 Then
  73. singular := true
  74. End; {i}
  75. For k:=1 To n Do
  76. Begin
  77. maxim := 0;
  78. indexpivot := k;
  79. For i:=k To n Do
  80. Begin
  81. ind := (i-1)*rwidth;
  82. sumrowi := sumrow^[i];
  83. If sumrowi <> 0 Then
  84. Begin
  85. h := abs(palu^[ind+k])/sumrowi;
  86. If maxim<h Then
  87. Begin
  88. maxim := h;
  89. indexpivot := i
  90. End {maxim<h}
  91. End {sumrow <> 0}
  92. End; {i}
  93. If maxim=0 Then
  94. singular := true
  95. Else
  96. Begin
  97. If indexpivot <> k Then
  98. Begin
  99. ind := (indexpivot-1)*rwidth;
  100. indk := (k-1)*rwidth;
  101. For j:=1 To n Do
  102. Begin
  103. h := palu^[ind+j];
  104. palu^[ind+j] := palu^[indk+j];
  105. palu^[indk+j] := h
  106. End; {j}
  107. h := t^[indexpivot];
  108. t^[indexpivot] := t^[k];
  109. t^[k] := h;
  110. pp^[k] := indexpivot;
  111. sumrow^[indexpivot] := sumrow^[k]
  112. End; {indexpivot <> k}
  113. pivot := palu^[(k-1)*rwidth+k];
  114. For i:=k+1 To n Do
  115. Begin
  116. ind := (i-1)*rwidth;
  117. l := palu^[ind+k]/pivot;
  118. palu^[ind+k] := l;
  119. If l <> 0 Then
  120. Begin
  121. For j:=k+1 To n Do
  122. palu^[ind+j] := palu^[ind+j]-l*palu^[(k-1)*rwidth+j];
  123. If Not singular Then
  124. t^[i] := t^[i]-l*t^[k]
  125. End {l <> 0}
  126. End {i}
  127. End {maxim <> 0}
  128. End; {k}
  129. If Not singular Then
  130. Begin
  131. normt := 0;
  132. For i:=n Downto 1 Do
  133. Begin
  134. indi := (i-1)*rwidth;
  135. s := 0;
  136. For j:=i+1 To n Do
  137. s := s+t^[j]*palu^[indi+j];
  138. t^[i] := (t^[i]-s)/palu^[indi+i];
  139. h := abs(t^[i]);
  140. If normt<h Then
  141. normt := h
  142. End; {i}
  143. ca := normt/normr
  144. End; {not singular}
  145. If singular Then
  146. Begin
  147. term := 4;
  148. ca := giant
  149. End
  150. Else
  151. term := 1;
  152. freemem(sumrow, nsr);
  153. freemem(t, nsr)
  154. End; {mdtgen}
  155. Procedure mdtgtr(n: ArbInt; Var l, d, u, l1, d1, u1, u2: ArbFloat;
  156. Var p: boolean; Var ca: ArbFloat; Var term: ArbInt);
  157. Var
  158. i, j, k, nmin1, sr : ArbInt;
  159. normr, normt, sumrowi, h, lj, di, ui, ll : ArbFloat;
  160. sing : boolean;
  161. pd, pu, pd1, pu1, pu2, t, sumrow : ^arfloat1;
  162. pl, pl1 : ^arfloat2;
  163. pp : ^arbool1;
  164. Begin
  165. If n<1 Then
  166. Begin
  167. term := 3;
  168. exit
  169. End; {wrong input}
  170. pl := @l;
  171. pd := @d;
  172. pu := @u;
  173. pl1 := @l1;
  174. pd1 := @d1;
  175. pu1 := @u1;
  176. pu2 := @u2;
  177. pp := @p;
  178. sr := sizeof(ArbFloat);
  179. move(pl^, pl1^, (n-1)*sr);
  180. move(pd^, pd1^, n*sr);
  181. move(pu^, pu1^, (n-1)*sr);
  182. getmem(t, n*sr);
  183. getmem(sumrow, n*sr);
  184. normr := 0;
  185. sing := false;
  186. nmin1 := n-1;
  187. For i:=1 To n Do
  188. Begin
  189. pp^[i] := false;
  190. If i=1 Then
  191. sumrowi := abs(pd^[1])+abs(pu^[1])
  192. Else
  193. If i=n Then
  194. sumrowi := abs(pl^[n])+abs(pd^[n])
  195. Else
  196. sumrowi := abs(pl^[i])+abs(pd^[i])+abs(pu^[i]);
  197. sumrow^[i] := sumrowi;
  198. h := 2*random-1;
  199. t^[i] := sumrowi*h;
  200. h := abs(h);
  201. If normr<h Then
  202. normr := h;
  203. If sumrowi=0 Then
  204. sing := true
  205. End; {i}
  206. j := 1;
  207. while (j <> n) Do
  208. Begin
  209. i := j;
  210. j := j+1;
  211. lj := pl1^[j];
  212. If lj <> 0 Then
  213. Begin
  214. di := pd1^[i];
  215. If di=0 Then
  216. pp^[i] := true
  217. Else
  218. pp^[i] := abs(di/sumrow^[i])<abs(lj/sumrow^[j]);
  219. If pp^[i] Then
  220. Begin
  221. ui := pu1^[i];
  222. pd1^[i] := lj;
  223. pu1^[i] := pd1^[j];
  224. pl1^[j] := di/lj;
  225. ll := pl1^[j];
  226. pd1^[j] := ui-ll*pd1^[j];
  227. If i<nmin1 Then
  228. Begin
  229. pu2^[i] := pu1^[j];
  230. pu1^[j] := -ll*pu2^[i]
  231. End; {i<nmin1}
  232. sumrow^[j] := sumrow^[i];
  233. If (Not sing) Then
  234. Begin
  235. h := t^[i];
  236. t^[i] := t^[j];
  237. t^[j] := h-ll*t^[i]
  238. End {not sing}
  239. End {pp^[i]}
  240. Else
  241. Begin
  242. pl1^[j] := lj/di;
  243. ll := pl1^[j];
  244. pd1^[j] := pd1^[j]-ll*pu1^[i];
  245. If i<nmin1 Then
  246. pu2^[i] := 0;
  247. If (Not sing) Then
  248. t^[j] := t^[j]-ll*t^[i]
  249. End {not pp^[i]}
  250. End {lj<>0}
  251. Else
  252. Begin
  253. If i<nmin1 Then
  254. pu2^[i] := 0;
  255. If pd1^[i]=0 Then
  256. sing := true
  257. End {lj=0}
  258. End; {j}
  259. If pd1^[n]=0 Then
  260. sing := true;
  261. If (Not sing) Then
  262. Begin
  263. normt := 0;
  264. t^[n] := t^[n]/pd1^[n];
  265. h := abs(t^[n]);
  266. If normt<h Then
  267. normt := h;
  268. If n > 1 Then
  269. Begin
  270. t^[nmin1] := (t^[nmin1]-pu1^[nmin1]*t^[n])/pd1^[nmin1];
  271. h := abs(t^[nmin1])
  272. End; {n > 1}
  273. If normt<h Then
  274. normt := h;
  275. For i:=n-2 Downto 1 Do
  276. Begin
  277. t^[i] := (t^[i]-pu1^[i]*t^[i+1]-pu2^[i]*t^[i+2])/pd1^[i];
  278. h := abs(t^[i]);
  279. If normt<h Then
  280. normt := h
  281. End; {i}
  282. ca := normt/normr
  283. End; {not sing}
  284. If (sing) Then
  285. Begin
  286. term := 4;
  287. ca := giant
  288. End {sing}
  289. Else
  290. term := 1;
  291. freemem(t, n*sr);
  292. freemem(sumrow, n*sr)
  293. End; {mdtgtr}
  294. Procedure mdtgsy(n, rwidth: ArbInt; Var a: ArbFloat; Var pp:ArbInt;
  295. Var qq:boolean; Var ca:ArbFloat; Var term:ArbInt);
  296. Var
  297. i, j, kmin1, k, kplus1, kmin2, imin2, nsr, nsi, nsb, ii,
  298. imin1, jmin1, indexpivot, iplus1, indi, indj, indk, indp : ArbInt;
  299. ra, h, absh, maxim, pivot, ct, norma, sumrowi, normt, normr, s : ArbFloat;
  300. alt, l, d, t, u, v, l1, d1, u1, t1 : ^arfloat1;
  301. p : ^arint1;
  302. q : ^arbool1;
  303. Begin
  304. If (n<1) Or (rwidth<1) Then
  305. Begin
  306. term := 3;
  307. exit
  308. End; {if}
  309. alt := @a;
  310. p := @pp;
  311. q := @qq;
  312. nsr := n*sizeof(ArbFloat);
  313. nsi := n*sizeof(ArbInt);
  314. nsb := n*sizeof(boolean);
  315. getmem(l, nsr);
  316. getmem(d, nsr);
  317. getmem(t, nsr);
  318. getmem(u, nsr);
  319. getmem(v, nsr);
  320. getmem(l1, nsr);
  321. getmem(d1, nsr);
  322. getmem(u1, nsr);
  323. getmem(t1, nsr);
  324. norma := 0;
  325. For i:=1 To n Do
  326. Begin
  327. indi := (i-1)*rwidth;
  328. p^[i] := i;
  329. sumrowi := 0;
  330. For j:=1 To i Do
  331. sumrowi := sumrowi+abs(alt^[indi+j]);
  332. For j:=i+1 To n Do
  333. sumrowi := sumrowi+abs(alt^[(j-1)*rwidth+i]);
  334. If norma<sumrowi Then
  335. norma := sumrowi
  336. End; {i}
  337. kmin1 := -1;
  338. k := 0;
  339. kplus1 := 1;
  340. while k<n Do
  341. Begin
  342. kmin2 := kmin1;
  343. kmin1 := k;
  344. k := kplus1;
  345. kplus1 := kplus1+1;
  346. indk := kmin1*rwidth;
  347. If k>3 Then
  348. Begin
  349. t^[2] := alt^[rwidth+2]*alt^[indk+1]+alt^[2*rwidth+2]*alt^[indk+2];
  350. For i:=3 To kmin2 Do
  351. Begin
  352. indi := (i-1)*rwidth;
  353. t^[i] := alt^[indi+i-1]*alt^[indk+i-2]+alt^[indi+i]
  354. *alt^[indk+i-1]+alt^[indi+rwidth+i]*alt^[indk+i]
  355. End; {i}
  356. t^[kmin1] := alt^[indk-rwidth+kmin2]*alt^[indk+k-3]
  357. +alt^[indk-rwidth+kmin1]*alt^[indk+kmin2]
  358. +alt^[indk+kmin1];
  359. h := alt^[indk+k];
  360. For j:=2 To kmin1 Do
  361. h := h-t^[j]*alt^[indk+j-1];
  362. t^[k] := h;
  363. alt^[indk+k] := h-alt^[indk+kmin1]*alt^[indk+kmin2]
  364. End {k>3}
  365. Else
  366. If k=3 Then
  367. Begin
  368. t^[2] := alt^[rwidth+2]*alt^[2*rwidth+1]+alt^[2*rwidth+2];
  369. h := alt^[2*rwidth+3]-t^[2]*alt^[2*rwidth+1];
  370. t^[3] := h;
  371. alt^[2*rwidth+3] := h-alt^[2*rwidth+2]*alt^[2*rwidth+1]
  372. End {k=3}
  373. Else
  374. If k=2 Then
  375. t^[2] := alt^[rwidth+2];
  376. maxim := 0;
  377. For i:=kplus1 To n Do
  378. Begin
  379. indi := (i-1)*rwidth;
  380. h := alt^[indi+k];
  381. For j:=2 To k Do
  382. h := h-t^[j]*alt^[indi+j-1];
  383. absh := abs(h);
  384. If maxim<absh Then
  385. Begin
  386. maxim := absh;
  387. indexpivot := i
  388. End; {if}
  389. alt^[indi+k] := h
  390. End; {i}
  391. If maxim <> 0 Then
  392. Begin
  393. If indexpivot>kplus1 Then
  394. Begin
  395. indp := (indexpivot-1)*rwidth;
  396. indk := k*rwidth;
  397. p^[kplus1] := indexpivot;
  398. For j:=1 To k Do
  399. Begin
  400. h := alt^[indk+j];
  401. alt^[indk+j] := alt^[indp+j];
  402. alt^[indp+j] := h
  403. End; {j}
  404. For j:=indexpivot Downto kplus1 Do
  405. Begin
  406. indj := (j-1)*rwidth;
  407. h := alt^[indj+kplus1];
  408. alt^[indj+kplus1] := alt^[indp+j];
  409. alt^[indp+j] := h
  410. End; {j}
  411. For i:=indexpivot To n Do
  412. Begin
  413. indi := (i-1)*rwidth;
  414. h := alt^[indi+kplus1];
  415. alt^[indi+kplus1] := alt^[indi+indexpivot];
  416. alt^[indi+indexpivot] := h
  417. End {i}
  418. End; {if}
  419. pivot := alt^[k*rwidth+k];
  420. For i:=k+2 To n Do
  421. alt^[(i-1)*rwidth+k] := alt^[(i-1)*rwidth+k]/pivot
  422. End {maxim <> 0}
  423. End; {k}
  424. d^[1] := alt^[1];
  425. i := 1;
  426. while i<n Do
  427. Begin
  428. imin1 := i;
  429. i := i+1;
  430. u^[imin1] := alt^[(i-1)*rwidth+imin1];
  431. l^[imin1] := u^[imin1];
  432. d^[i] := alt^[(i-1)*rwidth+i]
  433. End; {i}
  434. mdtgtr(n, l^[1], d^[1], u^[1], l1^[1], d1^[1], u1^[1], v^[1],
  435. q^[1], ct, term);
  436. alt^[1] := d1^[1];
  437. alt^[rwidth+1] := l1^[1];
  438. alt^[rwidth+2] := d1^[2];
  439. alt^[2] := u1^[1];
  440. imin1 := 1;
  441. i := 2;
  442. while i<n Do
  443. Begin
  444. imin2 := imin1;
  445. imin1 := i;
  446. i := i+1;
  447. indi := imin1*rwidth;
  448. alt^[indi+imin1] := l1^[imin1];
  449. alt^[indi+i] := d1^[i];
  450. alt^[(imin1-1)*rwidth+i] := u1^[imin1];
  451. alt^[(imin2-1)*rwidth+i] := v^[imin2]
  452. End; {i}
  453. If term=1 Then
  454. Begin
  455. normr := 0;
  456. For i:=1 To n Do
  457. Begin
  458. t^[i] := 2*random-1;
  459. h := t^[i];
  460. h := abs(h);
  461. If normr<h Then
  462. normr := h
  463. End; {i}
  464. i := 0;
  465. while i<n Do
  466. Begin
  467. imin1 := i;
  468. i := i+1;
  469. j := 1;
  470. h := t^[i];
  471. while j<imin1 Do
  472. Begin
  473. jmin1 := j;
  474. j := j+1;
  475. h := h-alt^[(i-1)*rwidth+jmin1]*t^[j]
  476. End; {j}
  477. t^[i] := h
  478. End; {i}
  479. dslgtr(n, l1^[1], d1^[1], u1^[1], v^[1], q^[1], t^[1], t1^[1], term);
  480. i := n+1;
  481. imin1 := n;
  482. normt := 0;
  483. while i>2 Do
  484. Begin
  485. iplus1 := i;
  486. i := imin1;
  487. imin1 := imin1-1;
  488. h := t1^[i];
  489. For j:=iplus1 To n Do
  490. h := h-alt^[(j-1)*rwidth+imin1]*t1^[j];
  491. t1^[i] := h;
  492. h := abs(h);
  493. If normt<h Then
  494. normt := h
  495. End; {i}
  496. ca := norma*normt/normr
  497. End {term=1}
  498. Else ca := giant;
  499. freemem(l, nsr);
  500. freemem(d, nsr);
  501. freemem(t, nsr);
  502. freemem(u, nsr);
  503. freemem(v, nsr);
  504. freemem(l1, nsr);
  505. freemem(d1, nsr);
  506. freemem(u1, nsr);
  507. freemem(t1, nsr)
  508. End; {mdtgsy}
  509. Procedure mdtgpd(n, rwidth: ArbInt; Var al, ca: ArbFloat; Var term: ArbInt);
  510. Var
  511. posdef : boolean;
  512. i, j, k, kmin1, indk, indi : ArbInt;
  513. h, lkk, normr, normt, sumrowi, norma : ArbFloat;
  514. pal, t : ^arfloat1;
  515. Begin
  516. If (n<1) Or (rwidth<1) Then
  517. Begin
  518. term := 3;
  519. exit
  520. End; {wrong input}
  521. getmem(t, sizeof(ArbFloat)*n);
  522. pal := @al;
  523. normr := 0;
  524. posdef := true;
  525. norma := 0;
  526. For i:=1 To n Do
  527. Begin
  528. sumrowi := 0;
  529. For j:=1 To i Do
  530. sumrowi := sumrowi+abs(pal^[(i-1)*rwidth+j]);
  531. For j:=i+1 To n Do
  532. sumrowi := sumrowi+abs(pal^[(j-1)*rwidth+i]);
  533. If norma<sumrowi Then
  534. norma := sumrowi;
  535. t^[i] := 2*random-1;
  536. h := t^[i];
  537. h := abs(h);
  538. If normr<h Then
  539. normr := h
  540. End; {i}
  541. k := 0;
  542. while (k<n) and posdef Do
  543. Begin
  544. kmin1 := k;
  545. k := k+1;
  546. indk := (k-1)*rwidth;
  547. lkk := pal^[indk+k];
  548. For j:=1 To kmin1 Do
  549. lkk := lkk-sqr(pal^[indk+j]);
  550. If lkk <= 0 Then
  551. posdef := false
  552. Else
  553. Begin
  554. pal^[indk+k] := sqrt(lkk);
  555. lkk := pal^[indk+k];
  556. For i:=k+1 To n Do
  557. Begin
  558. indi := (i-1)*rwidth;
  559. h := pal^[indi+k];
  560. For j:=1 To kmin1 Do
  561. h := h-pal^[indk+j]*pal^[indi+j];
  562. pal^[indi+k] := h/lkk
  563. End; {i}
  564. h := t^[k];
  565. For j:=1 To kmin1 Do
  566. h := h-pal^[indk+j]*t^[j];
  567. t^[k] := h/lkk
  568. End {posdef}
  569. End; {k}
  570. If posdef Then
  571. Begin
  572. normt := 0;
  573. For i:=n Downto 1 Do
  574. Begin
  575. h := t^[i];
  576. For j:=i+1 To n Do
  577. h := h-pal^[(j-1)*rwidth+i]*t^[j];
  578. t^[i] := h/pal^[(i-1)*rwidth+i];
  579. h := abs(t^[i]);
  580. If normt<h Then
  581. normt := h
  582. End; {i}
  583. ca := norma*normt/normr
  584. End; {posdef}
  585. If posdef Then
  586. term := 1
  587. Else
  588. term := 2;
  589. freemem(t, sizeof(ArbFloat)*n);
  590. End; {mdtgpd}
  591. Procedure mdtgba(n, lb, rb, rwa: ArbInt; Var a: ArbFloat; rwl: ArbInt;
  592. Var l:ArbFloat; Var p: ArbInt; Var ca: ArbFloat; Var term:ArbInt);
  593. Var
  594. sr, i, j, k, ipivot, m, lbj, lbi, ubi, ls,
  595. ii, jj, ll, s, js, jl, ubj : ArbInt;
  596. ra, normr, sumrowi, pivot, normt, maxim, h : ArbFloat;
  597. pl, au, sumrow, t, row : ^arfloat1;
  598. pp : ^arint1;
  599. Begin
  600. If (n<1) Or (lb<0) Or (rb<0) Or (lb>n-1) Or (rb>n-1) Or (rwl<0) Or (rwa<1) Then
  601. Begin
  602. term := 3;
  603. exit
  604. End; {term=3}
  605. sr := sizeof(ArbFloat);
  606. au := @a;
  607. pl := @l;
  608. pp := @p;
  609. ll := lb+rb+1;
  610. ls := ll*sr;
  611. getmem(sumrow, n*sr);
  612. getmem(t, n*sr);
  613. getmem(row, ls);
  614. lbi := n-rb+1;
  615. lbj := 0;
  616. jj := 1;
  617. For i:=lb Downto 1 Do
  618. Begin
  619. move(au^[i+jj], au^[jj], (ll-i)*sr);
  620. fillchar(au^[jj+ll-i], i*sr, 0);
  621. jj := jj+rwa
  622. End; {i}
  623. jj := (n-rb)*rwa+ll;
  624. For i:=1 To rb Do
  625. Begin
  626. fillchar(au^[jj], i*sr, 0);
  627. jj := jj+rwa-1
  628. End; {i}
  629. normr := 0;
  630. term := 1;
  631. ii := 1;
  632. For i:=1 To n Do
  633. Begin
  634. pp^[i] := i;
  635. sumrowi := omvn1v(au^[ii], ll);
  636. ii := ii+rwa;
  637. sumrow^[i] := sumrowi;
  638. h := 2*random-1;
  639. t^[i] := sumrowi*h;
  640. h := abs(h);
  641. If normr<h Then
  642. normr := h;
  643. If sumrowi=0 Then
  644. term := 4
  645. End; {i}
  646. ubi := lb;
  647. jj := 1;
  648. For k:=1 To n Do
  649. Begin
  650. maxim := 0;
  651. ipivot := k;
  652. ii := jj;
  653. If ubi<n Then
  654. ubi := ubi+1;
  655. For i:=k To ubi Do
  656. Begin
  657. sumrowi := sumrow^[i];
  658. If sumrowi <> 0 Then
  659. Begin
  660. h := abs(au^[ii])/sumrowi;
  661. ii := ii+rwa;
  662. If maxim<h Then
  663. Begin
  664. maxim := h;
  665. ipivot := i
  666. End {maxim<h}
  667. End {sumrowi <> 0}
  668. End; {i}
  669. If maxim=0 Then
  670. Begin
  671. lbj := 1;
  672. ubj := ubi-k;
  673. For j:=lbj To ubj Do
  674. pl^[(k-1)*rwl+j] := 0;
  675. For i:=k+1 To ubi Do
  676. Begin
  677. ii := (i-1)*rwa;
  678. For j:=2 To ll Do
  679. au^[ii+j-1] := au^[ii+j];
  680. au^[ii+ll] := 0
  681. End; {i}
  682. term := 4
  683. End {maxim=0}
  684. Else
  685. Begin
  686. If ipivot <> k Then
  687. Begin
  688. ii := (ipivot-1)*rwa+1;
  689. move(au^[ii], row^, ls);
  690. move(au^[jj], au^[ii], ls);
  691. move(row^, au^[jj], ls);
  692. h := t^[ipivot];
  693. t^[ipivot] := t^[k];
  694. t^[k] := h;
  695. pp^[k] := ipivot;
  696. sumrow^[ipivot] := sumrow^[k]
  697. End; {ipivot <> k}
  698. pivot := au^[jj];
  699. jl := 0;
  700. ii := jj;
  701. For i:=k+1 To ubi Do
  702. Begin
  703. jl := jl+1;
  704. ii := ii+rwa;
  705. h := au^[ii]/pivot;
  706. pl^[(k-1)*rwl+jl] := h;
  707. For j:=0 To ll-2 Do
  708. au^[ii+j] := au^[ii+j+1]-h*au^[jj+j+1];
  709. au^[ii+ll-1] := 0;
  710. If term=1 Then
  711. t^[i] := t^[i]-h*t^[k]
  712. End {i}
  713. End; {maxim <> 0}
  714. jj := jj+rwa
  715. End; {k}
  716. If term=1 Then
  717. Begin
  718. normt := 0;
  719. ubj := -lb-1;
  720. jj := n*rwa+1;
  721. For i:=n Downto 1 Do
  722. Begin
  723. jj := jj-rwa;
  724. If ubj<rb Then
  725. ubj := ubj+1;
  726. h := t^[i];
  727. For j:=1 To ubj+lb Do
  728. h := h-au^[jj+j]*t^[i+j];
  729. t^[i] := h/au^[jj];
  730. h := abs(t^[i]);
  731. If normt<h Then
  732. normt := h
  733. End; {i}
  734. ca := normt/normr
  735. End {term=1}
  736. Else
  737. ca := giant;
  738. freemem(sumrow, n*sr);
  739. freemem(t, n*sr);
  740. freemem(row, ls)
  741. End; {mdtgba}
  742. Procedure mdtgpb(n, lb, rwidth: ArbInt; Var al, ca: ArbFloat;
  743. Var term: ArbInt);
  744. Var
  745. posdef : boolean;
  746. i, j, k, r, p, q, ll, llmin1, jmin1, indi : ArbInt;
  747. h, normr, normt, sumrowi, alim, norma : ArbFloat;
  748. pal, t : ^arfloat1;
  749. Procedure decomp(i, r: ArbInt);
  750. Var
  751. k, ii, ir : ArbInt;
  752. Begin
  753. ii := (i-1)*rwidth;
  754. ir := (r-1)*rwidth;
  755. h := pal^[ii+j];
  756. q := ll-j+p;
  757. For k:=p To jmin1 Do
  758. Begin
  759. h := h-pal^[ii+k]*pal^[ir+q];
  760. q := q+1
  761. End; {k}
  762. If j<ll Then
  763. pal^[ii+j] := h/pal^[ir+ll]
  764. End; {decomp}
  765. Procedure lmin1t(i: ArbInt);
  766. Var
  767. k:ArbInt;
  768. Begin
  769. h := t^[i];
  770. q := i;
  771. For k:=llmin1 Downto p Do
  772. Begin
  773. q := q-1;
  774. h := h-pal^[indi+k]*t^[q]
  775. End; {k}
  776. t^[i] := h/alim
  777. End; {lmin1t}
  778. Begin
  779. If (lb<0) Or (lb>n-1) Or (n<1) Or (rwidth<1) Then
  780. Begin
  781. term := 3;
  782. exit
  783. End; {wrong input}
  784. pal := @al;
  785. getmem(t, n*sizeof(ArbFloat));
  786. ll := lb+1;
  787. normr := 0;
  788. p := ll+1;
  789. norma := 0;
  790. For i:=1 To n Do
  791. Begin
  792. If p>1 Then
  793. p := p-1;
  794. indi := (i-1)*rwidth+p;
  795. sumrowi := omvn1v(pal^[indi], ll-p+1);
  796. r := i;
  797. j := ll;
  798. while (r<n) and (j>1) Do
  799. Begin
  800. r := r+1;
  801. j := j-1;
  802. sumrowi := sumrowi+abs(pal^[(r-1)*rwidth+j])
  803. End; {r,j}
  804. If norma<sumrowi Then
  805. norma := sumrowi;
  806. h := 2*random-1;
  807. t^[i] := h;
  808. h := abs(h);
  809. If normr<h Then
  810. normr := h
  811. End; {i}
  812. llmin1 := ll-1;
  813. p := ll+1;
  814. i := 0;
  815. posdef := true ;
  816. while (i<n) and posdef Do
  817. Begin
  818. i := i+1;
  819. indi := (i-1)*rwidth;
  820. If p>1 Then
  821. p := p-1;
  822. r := i-ll+p;
  823. j := p-1;
  824. while j<llmin1 Do
  825. Begin
  826. jmin1 := j;
  827. j := j+1;
  828. decomp(i, r);
  829. r := r+1
  830. End; {j}
  831. jmin1 := llmin1;
  832. j := ll;
  833. decomp(i, i);
  834. If h <= 0 Then
  835. posdef := false
  836. Else
  837. Begin
  838. alim := sqrt(h);
  839. pal^[indi+ll] := alim;
  840. lmin1t(i)
  841. End
  842. End; {i}
  843. If posdef Then
  844. Begin
  845. normt := 0;
  846. p := ll+1;
  847. For i:=n Downto 1 Do
  848. Begin
  849. If p>1 Then
  850. p := p-1;
  851. q := i;
  852. h := t^[i];
  853. For k:=llmin1 Downto p Do
  854. Begin
  855. q := q+1;
  856. h := h-pal^[(q-1)*rwidth+k]*t^[q]
  857. End; {k}
  858. t^[i] := h/pal^[(i-1)*rwidth+ll];
  859. h := abs(t^[i]);
  860. If normt<h Then
  861. normt := h
  862. End; {i}
  863. ca := norma*normt/normr
  864. End; {posdef}
  865. If posdef Then
  866. term := 1
  867. Else
  868. term := 2;
  869. freemem(t, n*sizeof(ArbFloat));
  870. End; {mdtgpb}
  871. Procedure mdtdtr(n: ArbInt; Var l, d, u, l1, d1, u1: ArbFloat;
  872. Var term:ArbInt);
  873. Var
  874. i, j, s : ArbInt;
  875. lj, di : ArbFloat;
  876. pd, pu, pd1, pu1 : ^arfloat1;
  877. pl, pl1 : ^arfloat2;
  878. Begin
  879. If n<1 Then
  880. Begin
  881. term := 3;
  882. exit
  883. End; {wrong input}
  884. pl := @l;
  885. pd := @d;
  886. pu := @u;
  887. pl1 := @l1;
  888. pd1 := @d1;
  889. pu1 := @u1;
  890. s := sizeof(ArbFloat);
  891. move(pl^, pl1^, (n-1)*s);
  892. move(pd^, pd1^, n*s);
  893. move(pu^, pu1^, (n-1)*s);
  894. j := 1;
  895. di := pd1^[j];
  896. If di=0 Then
  897. term := 2
  898. Else
  899. term := 1;
  900. while (term=1) and (j <> n) Do
  901. Begin
  902. i := j;
  903. j := j+1;
  904. lj := pl1^[j]/di;
  905. pl1^[j] := lj;
  906. di := pd1^[j]-lj*pu1^[i];
  907. pd1^[j] := di;
  908. If di=0 Then
  909. term := 2
  910. End {j}
  911. End; {mdtdtr}
  912. Begin
  913. randseed := 12345
  914. End.
  915. {
  916. $Log$
  917. Revision 1.1 2000-01-24 22:08:58 marco
  918. * initial version
  919. }
  920.