inv.pas 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  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. Calculate inverses for different kinds of matrices (different with respect
  9. to symmetry)
  10. See the file COPYING.FPC, included in this distribution,
  11. for details about the copyright.
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  15. **********************************************************************}
  16. unit inv;
  17. {$I DIRECT.INC}
  18. interface
  19. uses typ;
  20. {Calc inverse for a matrix with unknown symmetry. General version. }
  21. procedure invgen(n, rwidth: ArbInt; var ai: ArbFloat; var term: ArbInt);
  22. {Calc inverse for a symmetrical matrix}
  23. procedure invgsy(n, rwidth: ArbInt; var ai: ArbFloat; var term: ArbInt);
  24. {Calc inverse for a positive definite symmetrical matrix}
  25. procedure invgpd(n, rwidth: ArbInt; var ai: ArbFloat; var term: ArbInt);
  26. implementation
  27. uses mdt, dsl;
  28. procedure invgen(n, rwidth: ArbInt; var ai: ArbFloat; var term: ArbInt);
  29. var
  30. success : boolean;
  31. inn, ii, i, j, k, kk, indexpivot : ArbInt;
  32. ca, h, pivot, s : ArbFloat;
  33. pa, save : ^arfloat1;
  34. p : ^arint1;
  35. begin
  36. if (n<1) or (rwidth<1) then
  37. begin
  38. term:=3; exit
  39. end; {wrong input}
  40. pa:=@ai;
  41. getmem(p, n*sizeof(ArbInt)); getmem(save, n*sizeof(ArbFloat));
  42. mdtgen(n, rwidth, pa^[1], p^[1], ca, term);
  43. if term=1 then
  44. begin
  45. inn:=(n-1)*rwidth+n; pivot:=pa^[inn];
  46. if pivot=0 then success:=false else
  47. begin
  48. success:=true; pa^[inn]:=1/pivot; k:=n;
  49. while (k>1) and success do
  50. begin
  51. k:=k-1; kk:=(k-1)*rwidth;
  52. for i:=k+1 to n do save^[i]:=-pa^[(i-1)*rwidth+k];
  53. for i:=k+1 to n do
  54. begin
  55. ii:=(i-1)*rwidth;
  56. s:=0;
  57. for j:=k+1 to n do s:=s+pa^[ii+j]*save^[j];
  58. pa^[ii+k]:=s
  59. end; {i}
  60. for j:=k+1 to n do save^[j]:=pa^[kk+j];
  61. pivot:=pa^[kk+k];
  62. if pivot=0 then success:=false else
  63. begin
  64. s:=0;
  65. for i:=k+1 to n do s:=s-save^[i]*pa^[(i-1)*rwidth+k];
  66. pa^[kk+k]:=(1+s)/pivot;
  67. for j:=k+1 to n do
  68. begin
  69. s:=0;
  70. for i:=k+1 to n do s:=s-save^[i]*pa^[(i-1)*rwidth+j];
  71. pa^[(k-1)*rwidth+j]:=s/pivot
  72. end {j}
  73. end {pivot <> 0}
  74. end; {k}
  75. if success then
  76. for k:=n downto 1 do
  77. begin
  78. indexpivot:=p^[k];
  79. if indexpivot <> k then
  80. for i:=1 to n do
  81. begin
  82. ii:=(i-1)*rwidth;
  83. h:=pa^[ii+k]; pa^[ii+k]:=pa^[ii+indexpivot];
  84. pa^[ii+indexpivot]:=h
  85. end {i}
  86. end {k}
  87. end; {pivot <> 0}
  88. if (not success) then term:=2
  89. end else term:=2;
  90. freemem(p, n*sizeof(ArbInt)); freemem(save, n*sizeof(ArbFloat));
  91. end; {invgen}
  92. procedure invgsy(n, rwidth: ArbInt; var ai: ArbFloat; var term: ArbInt);
  93. var ind, ind1, i, m, pk, j,
  94. kmin1, k, imin2, nsr,
  95. imin1, jmin1, iplus1 : ArbInt;
  96. success : boolean;
  97. di, h, ca : ArbFloat;
  98. pa, l, d, u, v, e, e1, x : ^arfloat1;
  99. p : ^arint1;
  100. q : ^arbool1;
  101. begin
  102. if (n<1) or (rwidth<1) then
  103. begin
  104. term:=3; exit
  105. end; {wrong input}
  106. pa:=@ai;
  107. getmem(p, n*sizeof(ArbInt)); getmem(q, n*sizeof(boolean));
  108. nsr:=n*sizeof(ArbFloat);
  109. getmem(l, nsr); getmem(d, nsr); getmem(u, nsr);
  110. getmem(v, nsr); getmem(e, nsr); getmem(e1, nsr);
  111. getmem(x, ((n+1)*nsr) div 2);
  112. mdtgsy(n, rwidth, pa^[1], p^[1], q^[1], ca, term);
  113. if term=1 then
  114. begin
  115. success:=true; i:=1; ind:=1;
  116. while (i<>n+1) and success do
  117. begin
  118. success:=pa^[ind]<>0; ind:=ind+rwidth+1; i:=i+1
  119. end; {i}
  120. if success then
  121. begin
  122. d^[1]:=pa^[1]; di:=d^[1]; l^[1]:=pa^[rwidth+1];
  123. d^[2]:=pa^[rwidth+2]; di:=d^[2]; u^[1]:=pa^[2];
  124. imin1:=1; i:=2;
  125. while i<n do
  126. begin
  127. imin2:=imin1; imin1:=i; i:=i+1; ind:=imin1*rwidth;
  128. l^[imin1]:=pa^[ind+imin1]; d^[i]:=pa^[ind+i]; di:=d^[i];
  129. u^[imin1]:=pa^[ind-rwidth+i]; v^[imin2]:=pa^[ind-2*rwidth+i]
  130. end; {i}
  131. m:=0; k:=0;
  132. while k<n do
  133. begin
  134. kmin1:=k; k:=k+1;
  135. for i:=1 to kmin1 do e^[i]:=0;
  136. e^[k]:=1; i:=k;
  137. while i<n do
  138. begin
  139. imin1:=i; i:=i+1; h:=0;
  140. if k=1 then j:=1 else j:=kmin1;
  141. while j<imin1 do
  142. begin
  143. jmin1:=j; j:=j+1;
  144. h:=h-pa^[(i-1)*rwidth+jmin1]*e^[j]
  145. end; {j}
  146. e^[i]:=h
  147. end; {i}
  148. dslgtr(n, l^[1], d^[1], u^[1], v^[1], q^[1],
  149. e^[1], e1^[1], term);
  150. i:=n+1; imin1:=n;
  151. while i>2 do
  152. begin
  153. iplus1:=i; i:=imin1; imin1:=imin1-1; h:=e1^[i];
  154. for j:=iplus1 to n do
  155. h:=h-pa^[(j-1)*rwidth+imin1]*e1^[j];
  156. e1^[i]:=h
  157. end; {i}
  158. for i:=k to n do
  159. begin
  160. m:=m+1; x^[m]:=e1^[i]
  161. end
  162. end; {k}
  163. m:=0;
  164. for k:=1 to n do for i:=k to n do
  165. begin
  166. m:=m+1; pa^[(i-1)*rwidth+k]:=x^[m]
  167. end; {i,k}
  168. for k:=n-1 downto 2 do
  169. begin
  170. pk:=p^[k];
  171. if pk <> k then
  172. begin
  173. kmin1:=k-1; ind:=(k-1)*rwidth; ind1:=(pk-1)*rwidth;
  174. for j:=1 to kmin1 do
  175. begin
  176. h:=pa^[ind+j];
  177. pa^[ind+j]:=pa^[ind1+j]; pa^[ind1+j]:=h
  178. end; {j}
  179. for j:=pk downto k do
  180. begin
  181. ind:=(j-1)*rwidth;
  182. h:=pa^[ind+k];
  183. pa^[ind+k]:=pa^[ind1+j]; pa^[ind1+j]:=h
  184. end; {j}
  185. for i:=pk to n do
  186. begin
  187. ind:=(i-1)*rwidth;
  188. h:=pa^[ind+k];
  189. pa^[ind+k]:=pa^[ind+pk]; pa^[ind+pk]:=h
  190. end {i}
  191. end {pk <> k}
  192. end {k}
  193. end; {success}
  194. if (not success) then term:=2 else
  195. for i:=1 to n do
  196. begin
  197. ind:=(i-1)*rwidth;
  198. for j:=i+1 to n do pa^[ind+j]:=pa^[(j-1)*rwidth+i]
  199. end {i}
  200. end else term:=2;
  201. freemem(l, nsr); freemem(d, nsr); freemem(u, nsr);
  202. freemem(v, nsr); freemem(e, nsr); freemem(e1, nsr);
  203. freemem(x, ((n+1)*nsr) div 2);
  204. end; {invgsy}
  205. procedure invgpd(n, rwidth: ArbInt; var ai: ArbFloat; var term: ArbInt);
  206. var success : boolean;
  207. i, j, k, ind : ArbInt;
  208. tk, h, ca : ArbFloat;
  209. pa, t : ^arfloat1;
  210. begin
  211. if (n<1) or (rwidth<1) then
  212. begin
  213. term:=3; exit
  214. end; {wrong input}
  215. pa:=@ai;
  216. mdtgpd(n, rwidth, pa^[1], ca, term);
  217. getmem(t, n*sizeof(ArbFloat));
  218. if term=1 then
  219. begin
  220. success:=true; ind:=1; k:=1;
  221. while (k<>n+1) and success do
  222. begin
  223. success:=pa^[ind]<>0; k:=k+1; ind:=ind+rwidth+1
  224. end; {k}
  225. if success then
  226. begin
  227. for k:=n downto 1 do
  228. begin
  229. for i:=k to n do t^[i]:=pa^[(i-1)*rwidth+k];
  230. tk:=t^[k];
  231. for i:=n downto k do
  232. begin
  233. if i=k then h:=1/tk else h:=0;
  234. ind:=(i-1)*rwidth;
  235. for j:=k+1 to i do h:=h-pa^[ind+j]*t^[j];
  236. for j:=i+1 to n do h:=h-pa^[(j-1)*rwidth+i]*t^[j];
  237. pa^[ind+k]:=h/tk
  238. end {i}
  239. end {k}
  240. end; {success}
  241. if (not success) then term:=2 else
  242. for i:=1 to n do
  243. begin
  244. ind:=(i-1)*rwidth;
  245. for j:=i+1 to n do pa^[ind+j]:=pa^[(j-1)*rwidth+i]
  246. end; {i}
  247. end; {term=1}
  248. freemem(t, n*sizeof(ArbFloat));
  249. end; {invgpd}
  250. end.