inv.pas 8.7 KB

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