mdt.pas 24 KB

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