ipf.pas 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893
  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. Interpolate and (curve) fitting.
  10. Slegpb in this unit patched parameters slightly. Units IPF and sle
  11. were not in the same revision in this numlib copy (which was a
  12. copy of the work directory of the author) .
  13. Contains two undocumented functions. If you recognize the algoritm,
  14. mail us.
  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. {
  22. }
  23. unit ipf;
  24. {$I direct.inc}
  25. interface
  26. uses typ, mdt, dsl, sle, spe;
  27. { Determine natural cubic spline "s" for data set (x,y), output to (a,d2a)
  28. term=1 success,
  29. =2 failure calculating "s"
  30. =3 wrong input (e.g. x,y is not sorted increasing on x)}
  31. procedure ipffsn(n: ArbInt; var x, y, a, d2a: ArbFloat; var term: ArbInt);
  32. {calculate d2s from x,y, which can be used to calculate s}
  33. procedure ipfisn(n: ArbInt; var x, y, d2s: ArbFloat; var term: ArbInt);
  34. {Calculate function value for dataset (x,y), with n.c. spline d2s for
  35. x value t. Return (corrected) y value.
  36. s calculated from x,y, with e.g. ipfisn}
  37. function ipfspn(n: ArbInt; var x, y, d2s: ArbFloat; t: ArbFloat;
  38. var term: ArbInt): ArbFloat;
  39. {Calculate n-degree polynomal b for dataset (x,y) with n elements
  40. using the least squares method.}
  41. procedure ipfpol(m, n: ArbInt; var x, y, b: ArbFloat; var term: ArbInt);
  42. {**** undocumented ****}
  43. function spline( n : ArbInt;
  44. x : complex;
  45. var ac : complex;
  46. var gammar: ArbFloat;
  47. u1 : ArbFloat;
  48. pf : complex): ArbFloat;
  49. {**** undocumented ****}
  50. procedure splineparameters
  51. ( n : ArbInt;
  52. var ac, alfadc : complex;
  53. var lambda,
  54. gammar, u1,
  55. kwsom, energie : ArbFloat;
  56. var pf : complex);
  57. implementation
  58. procedure ipffsn(n: ArbInt; var x, y, a, d2a: ArbFloat; var term: ArbInt);
  59. var i, j, sr, n1s, ns1, ns2: ArbInt;
  60. s, lam, lam0, lam1, lambda, ey, ca, p, q, r: ArbFloat;
  61. px, py, pd, pa, pd2a,
  62. h, z, diagb, dinv, qty, qtdinvq, c, t, tl: ^arfloat1;
  63. ub: boolean;
  64. procedure solve; {n, py, qty, h, qtdinvq, dinv, lam, t, pa, pd2a, term}
  65. var i: ArbInt;
  66. p, q, r, ca: ArbFloat;
  67. f, c: ^arfloat1;
  68. begin
  69. getmem(f, 3*ns1); getmem(c, ns1);
  70. for i:=1 to n-1 do
  71. begin
  72. f^[3*i]:=qtdinvq^[3*i]+lam*t^[2*i];
  73. if i > 1
  74. then
  75. f^[3*i-1]:=qtdinvq^[3*i-1]+lam*t^[2*i-1];
  76. if i > 2
  77. then
  78. f^[3*i-2]:=qtdinvq^[3*i-2];
  79. if lam=0
  80. then
  81. c^[i]:=qty^[i]
  82. else
  83. c^[i]:=lam*qty^[i]
  84. end;
  85. slegpb(n-1, 2,{ 3,} f^[1], c^[1], pd2a^[1], ca, term);
  86. if term=2
  87. then
  88. begin
  89. freemem(f, 3*ns1); freemem(c, ns1);
  90. exit
  91. end;
  92. p:=1/h^[1];
  93. if lam=0
  94. then
  95. r:=1
  96. else
  97. r:=1/lam;
  98. q:=1/h^[2]; pa^[1]:=py^[1]-r*dinv^[1]*p*pd2a^[1];
  99. pa^[2]:=py^[2]-r*dinv^[2]*(pd2a^[2]*q-(p+q)*pd2a^[1]); p:=q;
  100. for i:=3 to n-1 do
  101. begin
  102. q:=1/h^[i];
  103. pa^[i]:=py^[i]-r*dinv^[i]*
  104. (p*pd2a^[i-2]-(p+q)*pd2a^[i-1]+q*pd2a^[i]);
  105. p:=q
  106. end;
  107. q:=1/h^[n];
  108. pa^[n]:=py^[n]-r*dinv^[n]*(p*pd2a^[n-2]-(p+q)*pd2a^[n-1]);
  109. pa^[n+1]:=py^[n+1]-r*dinv^[n+1]*q*pd2a^[n-1];
  110. if lam=0
  111. then
  112. for i:=1 to n-1 do
  113. pd2a^[i]:=0;
  114. freemem(f, 3*ns1); freemem(c, ns1);
  115. end; {solve}
  116. function e(var c, h: ArbFloat; n:ArbInt): ArbFloat;
  117. var i:ArbInt;
  118. s:ArbFloat;
  119. pc, ph: ^arfloat1;
  120. begin
  121. ph:=@h; pc:=@c;
  122. s:=ph^[1]*pc^[1]*pc^[1];
  123. for i:=1 to n-2 do
  124. s:=s+(pc^[i]*(pc^[i]+pc^[i+1])+pc^[i+1]*pc^[i+1])*ph^[i+1];
  125. e:=(s+pc^[n-1]*pc^[n-1]*ph^[n])/3
  126. end; {e}
  127. function cr(lambda: ArbFloat): ArbFloat;
  128. var s, crs: ArbFloat;
  129. i: ArbInt;
  130. begin
  131. cr:=0; lam:=lambda;
  132. solve; { n, py, qty, h, qtdinvq, dinv, lam, t, pa, pd2a, term }
  133. if term=2
  134. then
  135. exit;
  136. crs:=ey;
  137. if lam <> 0
  138. then
  139. begin
  140. crs:=crs+e(pd2a^[1], h^[1], n);
  141. s:=0;
  142. for i:=1 to n-1 do
  143. s:=s+pd2a^[i]*qty^[i];
  144. crs:=crs-2*s
  145. end;
  146. s:=0;
  147. for i:=1 to n+1 do
  148. s:=s+sqr(pa^[i]-py^[i])*diagb^[i];
  149. cr:=crs-s
  150. end; {cr}
  151. procedure roof1r(a, b, ae, re: ArbFloat; var x: ArbFloat);
  152. var fa, fb, c, fc, m, tol, w1, w2 : ArbFloat;
  153. k : ArbInt;
  154. stop : boolean;
  155. begin
  156. fa:=cr(a);
  157. if term=2
  158. then
  159. exit;
  160. fb:=cr(b);
  161. if term=2
  162. then
  163. exit;
  164. if abs(fb)>abs(fa)
  165. then
  166. begin
  167. c:=b; fc:=fb; x:=a; b:=a; fb:=fa; a:=c; fa:=fc
  168. end
  169. else
  170. begin
  171. c:=a; fc:=fa; x:=b
  172. end;
  173. k:=0;
  174. tol:=ae+re*spemax(abs(a), abs(b));
  175. w1:=abs(b-a); stop:=false;
  176. while (abs(b-a)>tol) and (fb<>0) and (not stop) do
  177. begin
  178. m:=(a+b)/2;
  179. if (k>=2) or (fb=fc)
  180. then
  181. x:=m
  182. else
  183. begin
  184. x:=(b*fc-c*fb)/(fc-fb);
  185. if abs(b-x)<tol
  186. then
  187. x:=b-tol*spesgn(b-a);
  188. if spesgn(x-m)=spesgn(x-b)
  189. then
  190. x:=m
  191. end;
  192. c:=b; fc:=fb; b:=x; fb:=cr(x);
  193. if term=2
  194. then
  195. exit;
  196. if spesgn(fa)*spesgn(fb)>0
  197. then
  198. begin
  199. a:=c; fa:=fc; k:=0
  200. end
  201. else
  202. k:=k+1;
  203. if abs(fb)>=abs(fa)
  204. then
  205. begin
  206. c:=b; fc:=fb; x:=a; b:=a; fb:=fa; a:=c; fa:=fc; k:=0
  207. end;
  208. tol:=ae+re*spemax(abs(a), abs(b));
  209. w2:=abs(b-a);
  210. if w2>=w1
  211. then
  212. stop:=true;
  213. w1:=w2
  214. end
  215. end; {roof1r}
  216. procedure NoodGreep;
  217. var I, j: ArbInt;
  218. begin
  219. i:=1;
  220. while i <= n do
  221. begin
  222. if (pd^[i] <= 0) or (px^[i+1] <= px^[i])
  223. then
  224. begin
  225. term:=3;
  226. exit
  227. end;
  228. i:=i+1
  229. end;
  230. if pd^[n+1] <= 0
  231. then
  232. begin
  233. term:=3;
  234. exit
  235. end;
  236. for i:=1 to n+1 do
  237. dinv^[i]:=1/pd^[i];
  238. for i:=1 to n do
  239. h^[i]:=px^[i+1]-px^[i];
  240. t^[2]:=(h^[1]+h^[2])/3;
  241. for i:=2 to n-1 do
  242. begin
  243. t^[2*i]:=(h^[i]+h^[i+1])/3; t^[2*i-1]:=h^[i]/6
  244. end;
  245. move(t^[1], tl^[1], ns2);
  246. mdtgpb(n-1, 1, 2, tl^[1], ca, term);
  247. if term=2
  248. then
  249. exit;
  250. z^[1]:=1/(h^[1]*tl^[2]);
  251. for j:=2 to n-1 do
  252. z^[j]:=-(tl^[2*j-1]*z^[j-1])/tl^[2*j];
  253. s:=0;
  254. for j:=1 to n-1 do
  255. s:=s+sqr(z^[j]);
  256. diagb^[1]:=s;
  257. z^[1]:=(-1/h^[1]-1/h^[2])/tl^[2];
  258. if n>2
  259. then
  260. z^[2]:=(1/h^[2]-tl^[3]*z^[1])/tl^[4];
  261. for j:=3 to n-1 do
  262. z^[j]:=-tl^[2*j-1]*z^[j-1]/tl^[2*j];
  263. s:=0;
  264. for j:=1 to n-1 do
  265. s:=s+sqr(z^[j]);
  266. diagb^[2]:=s;
  267. for i:=2 to n-2 do
  268. begin
  269. z^[i-1]:=1/(h^[i]*tl^[2*(i-1)]);
  270. z^[i]:=(-1/h^[i]-1/h^[i+1]-tl^[2*i-1]*z^[i-1])/tl^[2*i];
  271. z^[i+1]:=(1/h^[i+1]-tl^[2*i+1]*z^[i])/tl^[2*(i+1)];
  272. for j:=i+2 to n-1 do
  273. z^[j]:=-tl^[2*j-1]*z^[j-1]/tl^[2*j];
  274. s:=0;
  275. for j:=i-1 to n-1 do
  276. s:=s+sqr(z^[j]);
  277. diagb^[i+1]:=s
  278. end;
  279. z^[n-2]:=1/(h^[n-1]*tl^[2*(n-2)]);
  280. z^[n-1]:=(-1/h^[n-1]-1/h^[n]-tl^[2*n-3]*z^[n-2])/tl^[2*(n-1)];
  281. s:=0;
  282. for j:=n-2 to n-1 do
  283. s:=s+sqr(z^[j]);
  284. diagb^[n]:=s;
  285. diagb^[n+1]:=1/sqr(h^[n]*tl^[2*(n-1)]);
  286. p:=1/h^[1];
  287. for i:=2 to n do
  288. begin
  289. q:=1/h^[i]; qty^[i-1]:=py^[i+1]*q-py^[i]*(p+q)+py^[i-1]*p;
  290. p:=q
  291. end;
  292. p:=1/h^[1]; q:=1/h^[2]; r:=1/h^[3];
  293. qtdinvq^[3]:=dinv^[1]*p*p+dinv^[2]*(p+q)*(p+q)+dinv^[3]*q*q;
  294. if n>2
  295. then
  296. begin
  297. qtdinvq^[6]:=dinv^[2]*q*q+dinv^[3]*(q+r)*(q+r)+dinv^[4]*r*r;
  298. qtdinvq^[5]:=-(dinv^[2]*(p+q)+dinv^[3]*(q+r))*q;
  299. p:=q; q:=r;
  300. for i:=3 to n-1 do
  301. begin
  302. r:=1/h^[i+1];
  303. qtdinvq^[3*i]:=dinv^[i]*q*q+dinv^[i+1]*(q+r)*(q+r)+dinv^[i+2]*r*r;
  304. qtdinvq^[3*i-1]:=-(dinv^[i]*(p+q)+dinv^[i+1]*(q+r))*q;
  305. qtdinvq^[3*i-2]:=dinv^[i]*p*q;
  306. p:=q; q:=r
  307. end
  308. end;
  309. dslgpb(n-1, 1, 2, tl^[1], qty^[1], c^[1], term);
  310. if term=2
  311. then
  312. exit;
  313. ey:=e(c^[1], h^[1], n);
  314. lam0:=0;
  315. s:=cr(lam0);
  316. if term=2
  317. then
  318. exit;
  319. if s >= 0
  320. then
  321. begin
  322. lambda:=0; term:=4
  323. end
  324. else
  325. begin
  326. lam1:=1e-8; ub:=false;
  327. while (not ub) and (lam1<=1.1e8) do
  328. begin
  329. s:=cr(lam1);
  330. if term=2
  331. then
  332. exit;
  333. if s >= 0
  334. then
  335. ub:=true
  336. else
  337. begin
  338. lam0:=lam1; lam1:=10*lam1
  339. end
  340. end;
  341. if not ub
  342. then
  343. begin
  344. term:=4; lambda:=lam0
  345. end
  346. else
  347. roof1r(lam0, lam1, 0, 1e-6, lambda);
  348. if term=2
  349. then
  350. exit
  351. end;
  352. end;
  353. begin
  354. term:=1;
  355. if n < 2
  356. then
  357. begin
  358. term:=3; exit
  359. end;
  360. sr:=sizeof(ArbFloat);
  361. n1s:=(n+1)*sr;
  362. ns2:=2*(n-1)*sr;
  363. ns1:=(n-1)*sr;
  364. getmem(dinv, n1s);
  365. getmem(h, n*sr);
  366. getmem(t, ns2);
  367. getmem(tl, ns2);
  368. getmem(z, ns1);
  369. getmem(diagb, n1s);
  370. getmem(qtdinvq, 3*ns1);
  371. getmem(c, ns1);
  372. getmem(qty, ns1);
  373. getmem(pd, n1s);
  374. { pd:=@d; }
  375. px:=@x;
  376. py:=@y;
  377. pa:=@a;
  378. pd2a:=@d2a;
  379. { de gewichten van de punten worden op 1 gezet}
  380. for i:=1 to n+1 do
  381. pd^[i]:=1;
  382. NoodGreep;
  383. freemem(dinv, n1s);
  384. freemem(h, n*sr);
  385. freemem(t, ns2);
  386. freemem(tl, ns2);
  387. freemem(z, ns1);
  388. freemem(diagb, n1s);
  389. freemem(qtdinvq, 3*ns1);
  390. freemem(c, ns1);
  391. freemem(qty, ns1);
  392. freemem(pd, n1s);
  393. end; {ipffsn}
  394. procedure ortpol(m, n: ArbInt; var x, alfa, beta: ArbFloat);
  395. var
  396. i, j, ms : ArbInt;
  397. xppn1, ppn1, ppn, p, alfaj, betaj : ArbFloat;
  398. px, pal, pbe, pn, pn1 : ^arfloat1;
  399. temp : pointer;
  400. begin
  401. mark(temp);
  402. px:=@x; pal:=@alfa; pbe:=@beta; ms:=m*sizeof(ArbFloat);
  403. getmem(pn, ms); getmem(pn1, ms);
  404. xppn1:=0; ppn1:=m;
  405. for i:=1 to m do
  406. begin
  407. pn^[i]:=0; pn1^[i]:=1; xppn1:=xppn1+px^[i]
  408. end;
  409. pal^[1]:=xppn1/ppn1; pbe^[1]:=0;
  410. for j:=2 to n do
  411. begin
  412. alfaj:=pal^[j-1]; betaj:=pbe^[j-1];
  413. ppn:=ppn1; ppn1:=0; xppn1:=0;
  414. for i:=1 to m do
  415. begin
  416. p:=(px^[i]-alfaj)*pn1^[i]-betaj*pn^[i];
  417. pn^[i]:=pn1^[i]; pn1^[i]:=p; p:=p*p;
  418. ppn1:=ppn1+p; xppn1:=xppn1+px^[i]*p
  419. end; {i}
  420. pal^[j]:=xppn1/ppn1; pbe^[j]:=ppn1/ppn
  421. end; {j}
  422. release(temp)
  423. end; {ortpol}
  424. procedure ortcoe(m, n: ArbInt; var x, y, alfa, beta, a: ArbFloat);
  425. var i, j, mr : ArbInt;
  426. fpn, ppn, p, alphaj, betaj : ArbFloat;
  427. px, py, pal, pbe, pa, pn, pn1 : ^arfloat1;
  428. temp : pointer;
  429. begin
  430. mark(temp); mr:=m*sizeof(ArbFloat);
  431. px:=@x; py:=@y; pal:=@alfa; pbe:=@beta; pa:=@a;
  432. getmem(pn, mr); getmem(pn1, mr);
  433. fpn:=0;
  434. for i:=1 to m do
  435. begin
  436. pn^[i]:=0; pn1^[i]:=1; fpn:=fpn+py^[i]
  437. end; {i}
  438. pa^[1]:=fpn/m;
  439. for j:=1 to n do
  440. begin
  441. fpn:=0; ppn:=0; alphaj:=pal^[j]; betaj:=pbe^[j];
  442. for i:=1 to m do
  443. begin
  444. p:=(px^[i]-alphaj)*pn1^[i]-betaj*pn^[i];
  445. pn^[i]:=pn1^[i]; pn1^[i]:=p;
  446. fpn:=fpn+py^[i]*p; ppn:=ppn+p*p
  447. end; {i}
  448. pa^[j+1]:=fpn/ppn
  449. end; {j}
  450. release(temp)
  451. end; {ortcoe}
  452. procedure polcoe(n:ArbInt; var alfa, beta, a, b: ArbFloat);
  453. var k, j : ArbInt;
  454. pal, pbe : ^arfloat1;
  455. pa, pb : ^arfloat0;
  456. begin
  457. pal:=@alfa; pbe:=@beta; pa:=@a; pb:=@b;
  458. move(pa^[0], pb^[0], (n+1)*sizeof(ArbFloat));
  459. for j:=0 to n-1 do
  460. for k:=n-j-1 downto 0 do
  461. begin
  462. pb^[k+j]:=pb^[k+j]-pal^[k+1]*pb^[k+j+1];
  463. if k+j<>n-1
  464. then
  465. pb^[k+j]:=pb^[k+j]-pbe^[k+2]*pb^[k+j+2]
  466. end
  467. end; {polcoe}
  468. procedure ipfpol(m, n: ArbInt; var x, y, b: ArbFloat; var term: ArbInt);
  469. var i, ns: ArbInt;
  470. fsum: ArbFloat;
  471. px, py, alfa, beta: ^arfloat1;
  472. pb, a: ^arfloat0;
  473. begin
  474. if (n<0) or (m<1)
  475. then
  476. begin
  477. term:=3; exit
  478. end;
  479. term:=1;
  480. if n = 0
  481. then
  482. begin
  483. py:=@y; pb:=@b;
  484. fsum:=0;
  485. for i:=1 to m do
  486. fsum:=fsum+py^[i];
  487. pb^[0]:=fsum/m
  488. end
  489. else
  490. begin
  491. if n>m-1
  492. then
  493. begin
  494. pb:=@b;
  495. fillchar(pb^[m], (n-m+1)*sizeof(ArbFloat), 0);
  496. n:=m-1
  497. end;
  498. ns:=n*sizeof(ArbFloat);
  499. getmem(alfa, ns); getmem(beta, ns);
  500. getmem(a, (n+1)*sizeof(ArbFloat));
  501. ortpol(m, n, x, alfa^[1], beta^[1]);
  502. ortcoe(m, n, x, y, alfa^[1], beta^[1], a^[0]);
  503. polcoe(n, alfa^[1], beta^[1], a^[0], b);
  504. freemem(alfa, ns); freemem(beta, ns);
  505. freemem(a, (n+1)*sizeof(ArbFloat));
  506. end
  507. end; {ipfpol}
  508. procedure ipfisn(n: ArbInt; var x, y, d2s: ArbFloat; var term: ArbInt);
  509. var
  510. s, i : ArbInt;
  511. p, q, ca : ArbFloat;
  512. px, py, h, b, t : ^arfloat0;
  513. pd2s : ^arfloat1;
  514. begin
  515. px:=@x; py:=@y; pd2s:=@d2s;
  516. term:=1;
  517. if n < 2
  518. then
  519. begin
  520. term:=3; exit
  521. end; {n<2}
  522. s:=sizeof(ArbFloat);
  523. getmem(h, n*s);
  524. getmem(b, (n-1)*s);
  525. getmem(t, 2*(n-1)*s);
  526. for i:=0 to n-1 do
  527. h^[i]:=px^[i+1]-px^[i];
  528. q:=1/6; p:=2*q;
  529. t^[1]:=p*(h^[0]+h^[1]);
  530. for i:=2 to n-1 do
  531. begin
  532. t^[2*i-1]:=p*(h^[i-1]+h^[i]); t^[2*i-2]:=q*h^[i-1]
  533. end; {i}
  534. p:=1/h^[0];
  535. for i:=2 to n do
  536. begin
  537. q:=1/h^[i-1]; b^[i-2]:=py^[i]*q-py^[i-1]*(p+q)+py^[i-2]*p; p:=q
  538. end;
  539. slegpb(n-1, 1, {2,} t^[0], b^[0], pd2s^[1], ca, term);
  540. freemem(h, n*s);
  541. freemem(b, (n-1)*s);
  542. freemem(t, 2*(n-1)*s);
  543. end; {ipfisn}
  544. function ipfspn(n: ArbInt; var x, y, d2s: ArbFloat; t:ArbFloat;
  545. var term: ArbInt): ArbFloat;
  546. var
  547. px, py : ^arfloat0;
  548. pd2s : ^arfloat1;
  549. i, j, m : ArbInt;
  550. d, s3, h, dy : ArbFloat;
  551. begin
  552. i:=1; term:=1;
  553. if n<2
  554. then
  555. begin
  556. term:=3; exit
  557. end; {n<2}
  558. px:=@x; py:=@y; pd2s:=@d2s;
  559. if t <= px^[0]
  560. then
  561. begin
  562. h:=px^[1]-px^[0];
  563. dy:=(py^[1]-py^[0])/h-h*pd2s^[1]/6;
  564. ipfspn:=py^[0]+(t-px^[0])*dy
  565. end { t <= x[0] }
  566. else
  567. if t >= px^[n]
  568. then
  569. begin
  570. h:=px^[n]-px^[n-1];
  571. dy:=(py^[n]-py^[n-1])/h+h*pd2s^[n-1]/6;
  572. ipfspn:=py^[n]+(t-px^[n])*dy
  573. end { t >= x[n] }
  574. else
  575. begin
  576. i:=0; j:=n;
  577. while j <> i+1 do
  578. begin
  579. m:=(i+j) div 2;
  580. if t>=px^[m]
  581. then
  582. i:=m
  583. else
  584. j:=m
  585. end; {j}
  586. h:=px^[i+1]-px^[i];
  587. d:=t-px^[i];
  588. if i=0
  589. then
  590. begin
  591. s3:=pd2s^[1]/h;
  592. dy:=(py^[1]-py^[0])/h-h*pd2s^[1]/6;
  593. ipfspn:=py^[0]+d*(dy+d*d*s3/6)
  594. end
  595. else
  596. if i=n-1
  597. then
  598. begin
  599. s3:=-pd2s^[n-1]/h;
  600. dy:=(py^[n]-py^[n-1])/h-h*pd2s^[n-1]/3;
  601. ipfspn:=py^[n-1]+d*(dy+d*(pd2s^[n-1]/2+d*s3/6))
  602. end
  603. else
  604. begin
  605. s3:=(pd2s^[i+1]-pd2s^[i])/h;
  606. dy:=(py^[i+1]-py^[i])/h-h*(2*pd2s^[i]+pd2s^[i+1])/6;
  607. ipfspn:=py^[i]+d*(dy+d*(pd2s^[i]/2+d*s3/6))
  608. end
  609. end { x[0] < t < x[n] }
  610. end; {ipfspn}
  611. function p(x, a, z:complex): ArbFloat;
  612. begin
  613. x.sub(a);
  614. p:=x.Inp(z)
  615. end;
  616. function e(x, y: complex): ArbFloat;
  617. const c1: ArbFloat = 0.01989436788646;
  618. var s: ArbFloat;
  619. begin x.sub(y);
  620. s := x.norm;
  621. if s=0 then e:=0 else e:=c1*s*ln(s)
  622. end;
  623. function spline( n : ArbInt;
  624. x : complex;
  625. var ac : complex;
  626. var gammar: ArbFloat;
  627. u1 : ArbFloat;
  628. pf : complex): ArbFloat;
  629. var i : ArbInt;
  630. s : ArbFloat;
  631. a : arcomp0 absolute ac;
  632. gamma : arfloat0 absolute gammar;
  633. begin
  634. s := u1 + p(x, a[n-2], pf);
  635. for i:=0 to n do s := s + gamma[i]*e(x,a[i]);
  636. spline := s
  637. end;
  638. procedure splineparameters
  639. ( n : ArbInt;
  640. var ac, alfadc : complex;
  641. var lambda,
  642. gammar, u1,
  643. kwsom, energie : ArbFloat;
  644. var pf : complex);
  645. procedure SwapC(var v, w: complex);
  646. var x: complex;
  647. begin
  648. x := v; v := w; w := x
  649. end;
  650. procedure pxpy(a, b, c: complex; var p:complex);
  651. var det: ArbFloat;
  652. begin
  653. b.sub(a); c.sub(a); det := b.xreal*c.imag-b.imag*c.xreal;
  654. b.sub(c); p.Init(b.imag/det, -b.xreal/det)
  655. end;
  656. procedure pfxpfy(a, b, c: complex; f: vector; var pf: complex);
  657. begin
  658. b.sub(a); c.sub(a);
  659. f.j := f.j-f.i; f.k := f.k-f.i;
  660. pf.init(f.j*c.imag - f.k*b.imag, -f.j*c.xreal + f.k*b.xreal);
  661. pf.scale(1/(b.xreal*c.imag - b.imag*c.xreal))
  662. end;
  663. function InpV(n: ArbInt; var v1, v2: ArbFloat): ArbFloat;
  664. var i: ArbInt;
  665. a1: arfloat0 absolute v1;
  666. a2: arfloat0 absolute v2;
  667. s : ArbFloat;
  668. begin
  669. s := 0;
  670. for i:=0 to n-1 do s := s + a1[i]*a2[i];
  671. InpV := s
  672. end;
  673. PROCEDURE SPDSOL( N : INTEGER;
  674. VAR AP : pointer;
  675. VAR B : ArbFloat);
  676. VAR I, J, K : INTEGER;
  677. H : ArbFloat;
  678. a : ^ar2dr absolute ap;
  679. bx : arfloat0 absolute b;
  680. BEGIN
  681. for k:=0 to n do
  682. BEGIN
  683. h := sqrt(a^[k]^[k]-InpV(k, a^[k]^[0], a^[k]^[0]));
  684. a^[k]^[k] := h;
  685. FOR I:=K+1 TO N do a^[i]^[k] := (a^[i]^[k] - InpV(k, a^[k]^[0], a^[i]^[0]))/h;
  686. BX[K] := (bx[k] - InpV(k, a^[k]^[0], bx[0]))/h
  687. END;
  688. FOR I:=N DOWNTO 0 do
  689. BEGIN
  690. H := BX[I];
  691. FOR J:=I+1 TO N DO H := H - A^[J]^[I]*BX[J];
  692. BX[I] := H/A^[I]^[I]
  693. END
  694. END;
  695. var i, j, i1 : ArbInt;
  696. x, h,
  697. absdet,
  698. absdetmax,
  699. s, s1, ca: ArbFloat;
  700. alfa, dv, hulp,
  701. u, v, w : vector;
  702. e22 : array[0..2] of vector;
  703. e21, b : ^arvect0;
  704. k, c : ^ar2dr;
  705. gamma : arfloat0 absolute gammar;
  706. an2, an1, an, z,
  707. vz, wz : complex;
  708. a : arcomp0 absolute ac;
  709. alfad : arcomp0 absolute alfadc;
  710. begin
  711. i1:=0;
  712. x:=a[0].xreal;
  713. for i:=1 to n do
  714. begin
  715. h:=a[i].xreal;
  716. if h<x then begin i1:=i; x:=h end
  717. end;
  718. SwapC(a[n-2], a[i1]);
  719. SwapC(alfad[n-2], alfad[i1]);
  720. x:=a[0].xreal;
  721. i1 := 0;
  722. for i:=1 to n do
  723. begin
  724. h:=a[i].xreal;
  725. if h>x then begin i1:=i; x:=h end
  726. end;
  727. SwapC(a[n-1], a[i1]);
  728. SwapC(alfad[n-1], alfad[i1]);
  729. vz := a[n-2]; vz.sub(a[n-1]);
  730. absdetmax := -1;
  731. for i:=0 to n do
  732. begin
  733. wz := a[i]; wz.sub(a[n-2]);
  734. absdet := abs(wz.imag*vz.xreal-wz.xreal*vz.imag);
  735. if absdet>absdetmax then begin i1:=i; absdetmax:=absdet end
  736. end;
  737. SwapC(a[n], a[i1]);
  738. SwapC(alfad[n], alfad[i1]);
  739. an2 := a[n-2]; an1 := a[n-1]; an := a[n];
  740. alfa.i := alfad[n-2].xreal; dv.i := alfad[n-2].imag;
  741. alfa.j := alfad[n-1].xreal; dv.j := alfad[n-1].imag;
  742. alfa.k := alfad[n ].xreal; dv.k := alfad[n ].imag;
  743. n := n - 3;
  744. GetMem(k, (n+1)*SizeOf(pointer));
  745. for j:=0 to n do GetMem(k^[j], (j+1)*SizeOf(ArbFloat));
  746. GetMem(e21, (n+1)*SizeOf(vector));
  747. GetMem(b, (n+1)*SizeOf(vector));
  748. pxpy(an2,an1,an,z); for i:=0 to n do b^[i].i:=1+p(a[i],an2,z);
  749. pxpy(an1,an,an2,z); for i:=0 to n do b^[i].j:=1+p(a[i],an1,z);
  750. pxpy(an,an2,an1,z); for i:=0 to n do b^[i].k:=1+p(a[i],an,z);
  751. e22[0].init(0,e(an1,an2),e(an,an2));
  752. e22[1].init(e(an1,an2),0,e(an,an1));
  753. e22[2].init(e(an,an2),e(an,an1),0);
  754. for j:=0 to n do e21^[j].init(e(an2,a[j]),e(an1,a[j]),e(an,a[j]));
  755. GetMem(c, (n+1)*SizeOf(pointer));
  756. for j:=0 to n do GetMem(c^[j], (j+1)*SizeOf(ArbFloat));
  757. for i:=0 to n do
  758. for j:=0 to i do
  759. begin
  760. if j=i then s:=0 else s:=e(a[i],a[j]);
  761. hulp.init(b^[j].Inprod(e22[0]), b^[j].Inprod(e22[1]), b^[j].Inprod(e22[2]));
  762. hulp.sub(e21^[j]);
  763. k^[i]^[j] := s+b^[i].InProd(hulp)-b^[j].Inprod(e21^[i]);
  764. if j=i then s:=1/alfad[i].imag else s:=0;
  765. hulp.init(b^[j].i/dv.i, b^[j].j/dv.j, b^[j].k/dv.k);
  766. c^[i]^[j] := k^[i]^[j] + (s + b^[i].Inprod(hulp))/lambda
  767. end;
  768. for i:=0 to n do gamma[i]:=alfad[i].xreal - b^[i].Inprod(alfa);
  769. SpdSol(n, pointer(c), gamma[0]);
  770. for j:=n downto 0 do FreeMem(c^[j], (j+1)*SizeOf(ArbFloat));
  771. FreeMem(c, (n+1)*SizeOf(pointer));
  772. s:=0; for j:=0 to n do s:=s+b^[j].i*gamma[j]; w.i:=s; gamma[n+1] := -s;
  773. s:=0; for j:=0 to n do s:=s+b^[j].j*gamma[j]; w.j:=s; gamma[n+2] := -s;
  774. s:=0; for j:=0 to n do s:=s+b^[j].k*gamma[j]; w.k:=s; gamma[n+3] := -s;
  775. FreeMem(b, (n+1)*SizeOf(vector));
  776. u.init(w.i/dv.i, w.j/dv.j, w.k/dv.k);
  777. u.scale(1/lambda);
  778. u.add(alfa);
  779. s:=0; for j:=0 to n do s:=s+e21^[j].i*gamma[j]; v.i := e22[0].inprod(w)-s;
  780. s:=0; for j:=0 to n do s:=s+e21^[j].j*gamma[j]; v.j := e22[1].inprod(w)-s;
  781. s:=0; for j:=0 to n do s:=s+e21^[j].k*gamma[j]; v.k := e22[2].inprod(w)-s;
  782. FreeMem(e21, (n+1)*SizeOf(vector));
  783. u.add(v);
  784. pfxpfy(an2, an1, an, u, pf); u1:=u.i;
  785. kwsom := 0; for j:=0 to n do kwsom:=kwsom+sqr(gamma[j])/alfad[j].imag;
  786. kwsom := kwsom+sqr(w.i)/dv.i+sqr(w.j)/dv.j+sqr(w.k)/dv.k;
  787. kwsom := kwsom/sqr(lambda);
  788. s:=0;
  789. for i:=0 to n do
  790. begin s1:=0;
  791. for j:=0 to i do s1:=s1+k^[i]^[j]*gamma[j];
  792. for j:=i+1 to n do s1:=s1+k^[j]^[i]*gamma[j];
  793. s := gamma[i]*s1+s
  794. end;
  795. for j:=n downto 0 do FreeMem(k^[j], (j+1)*SizeOf(ArbFloat));
  796. FreeMem(k, (n+1)*SizeOf(pointer));
  797. energie := s
  798. end {splineparameters};
  799. end.
  800. {
  801. $Log$
  802. Revision 1.2 2000-01-25 20:21:42 marco
  803. * small updates, crlf fix, and RTE 207 problem
  804. Revision 1.1 2000/01/24 22:08:58 marco
  805. * initial version
  806. }