roo.pas 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457
  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 to find roots of (various kinds of) equations
  9. See the file COPYING.FPC, included in this distribution,
  10. for details about the copyright.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14. **********************************************************************}
  15. {$mode objfpc}{$H+}
  16. {$modeswitch nestedprocvars}
  17. {$IFNDEF FPC_DOTTEDUNITS}
  18. Unit roo;
  19. {$ENDIF FPC_DOTTEDUNITS}
  20. {$i direct.inc}
  21. interface
  22. {$IFDEF FPC_DOTTEDUNITS}
  23. uses NumLib.Typ, NumLib.Spe;
  24. {$ELSE FPC_DOTTEDUNITS}
  25. uses typ, spe;
  26. {$ENDIF FPC_DOTTEDUNITS}
  27. {Find the all roots of the binomial eq. x^n=a, with "a" a complex number}
  28. Procedure roobin(n: ArbInt; a: complex; Var z: complex; Var term: ArbInt);
  29. {Find root point of f(x)=0 with f(x) a continuous function on domain [a,b]
  30. If f(a)*f(b)<=0 then there must be (at least) one rootpoint}
  31. Procedure roof1r(f: rfunc1r; a, b, ae, re: ArbFloat; Var x: ArbFloat;
  32. Var term: ArbInt);
  33. Procedure roof1rn(f: rfunc1rn; a, b, ae, re: ArbFloat; Var x: ArbFloat;
  34. Var term: ArbInt);
  35. {Determine all zeropoints for a given n'th degree polynomal with real
  36. coefficients}
  37. Procedure roopol(Var a: ArbFloat; n: ArbInt; Var z: complex;
  38. Var k, term: ArbInt);
  39. {Find roots for a simple 2th degree eq x^2+px+q=0 with p and q real}
  40. Procedure rooqua(p, q: ArbFloat; Var z1, z2: complex);
  41. {Solve a system of non-linear equations}
  42. Procedure roofnr(f: roofnrfunc; n: ArbInt; Var x, residu: ArbFloat; re: ArbFloat;
  43. Var term: ArbInt);
  44. { term : 1 succesful termination
  45. 2 Couldn't reach the specified precision
  46. Value X is the best one which could be found.
  47. 3 Wrong input
  48. 4 Too many functionvalues calculated, try to recalc with the
  49. calculated X
  50. 5 Not enough progress. Possibly there is no solution, or the
  51. solution is too close to 0. Try to choose a different
  52. initial startingvalue
  53. 6 Process wants to calculate a function value outside the by
  54. "deff" defined area.
  55. }
  56. implementation
  57. Procedure roobin(n: ArbInt; a: complex; Var z: complex; Var term: ArbInt);
  58. { This procedure solves the binomial equation z**n = a, with a complex}
  59. Var i, j, k : ArbInt;
  60. w, fie, dfie, r : ArbFloat;
  61. pz : ^arcomp1;
  62. Begin
  63. If n<1 Then
  64. Begin
  65. term := 2;
  66. exit
  67. End;
  68. term := 1;
  69. pz := @z;
  70. dfie := 2*pi/n;
  71. k := 1;
  72. If a.im=0 Then
  73. Begin
  74. If a.re>0 Then
  75. Begin
  76. r := spepow(a.re, 1/n);
  77. pz^[1].Init(r, 0);
  78. k := k+1;
  79. i := (n-1) Div 2;
  80. If Not odd(n) Then
  81. Begin
  82. pz^[k].Init(-r, 0);
  83. k := k+1
  84. End;
  85. For j:=1 To i Do
  86. Begin
  87. w := j*dfie;
  88. pz^[k].Init(r*cos(w), r*sin(w));
  89. pz^[k+1] := pz^[k];
  90. pz^[k+1].Conjugate;
  91. k := k+2
  92. End
  93. End
  94. Else
  95. Begin
  96. fie := pi/n;
  97. r := spepow(-a.re, 1/n);
  98. i := n Div 2-1;
  99. If odd(n) Then
  100. Begin
  101. pz^[k].Init(-r, 0);
  102. k := k+1
  103. End;
  104. For j:=0 To i Do
  105. Begin
  106. w := fie+j*dfie;
  107. pz^[k].Init(r*cos(w), r*sin(w));
  108. pz^[k+1] := pz^[k];
  109. pz^[k+1].Conjugate;
  110. k := k+2
  111. End
  112. End
  113. End
  114. Else
  115. Begin
  116. If abs(a.re)>=abs(a.im) Then
  117. r := spepow(abs(a.re)*sqrt(1+sqr(a.im/a.re)), 1/n)
  118. Else r := spepow(abs(a.im)*sqrt(1+sqr(a.re/a.im)), 1/n);
  119. fie := a.arg/n;
  120. i := n Div 2;
  121. For j:=0 To n-1 Do
  122. Begin
  123. w := fie+(j-i)*dfie;
  124. pz^[j+1].Init(r*cos(w), r*sin(w))
  125. End
  126. End
  127. End {roobin};
  128. Procedure roof1r(f: rfunc1r; a, b, ae, re: ArbFloat; Var x: ArbFloat;
  129. Var term: ArbInt);
  130. function nested_f(x: ArbFloat): ArbFloat;
  131. begin
  132. Result := f(x);
  133. end;
  134. begin
  135. roof1rn(@nested_f, a, b, ae, re, x, term);
  136. end;
  137. Procedure roof1rn(f: rfunc1rn; a, b, ae, re: ArbFloat; Var x: ArbFloat;
  138. Var term: ArbInt);
  139. Var fa, fb, c, fc, m, tol, w1, w2 : ArbFloat;
  140. k : ArbInt;
  141. stop : boolean;
  142. Begin
  143. fa := f(a);
  144. fb := f(b);
  145. If (spesgn(fa)*spesgn(fb)=1) Or (ae<0) Or (re<0)
  146. Then {wrong input}
  147. Begin
  148. term := 3;
  149. exit
  150. End;
  151. If abs(fb)>abs(fa) Then
  152. Begin
  153. c := b;
  154. fc := fb;
  155. x := a;
  156. b := a;
  157. fb := fa;
  158. a := c;
  159. fa := fc
  160. End
  161. Else
  162. Begin
  163. c := a;
  164. fc := fa;
  165. x := b
  166. End;
  167. k := 0;
  168. tol := ae+re*spemax(abs(a), abs(b));
  169. w1 := abs(b-a);
  170. stop := false;
  171. while (abs(b-a)>tol) and (fb<>0) and (Not stop) Do
  172. Begin
  173. m := (a+b)/2;
  174. If (k>=2) Or (fb=fc) Then x := m
  175. Else
  176. Begin
  177. x := (b*fc-c*fb)/(fc-fb);
  178. If abs(b-x)<tol Then x := b-tol*spesgn(b-a);
  179. If spesgn(x-m)=spesgn(x-b) Then x := m
  180. End;
  181. c := b;
  182. fc := fb;
  183. b := x;
  184. fb := f(x);
  185. If spesgn(fa)*spesgn(fb)>0 Then
  186. Begin
  187. a := c;
  188. fa := fc;
  189. k := 0
  190. End
  191. Else k := k+1;
  192. If abs(fb)>=abs(fa) Then
  193. Begin
  194. c := b;
  195. fc := fb;
  196. x := a;
  197. b := a;
  198. fb := fa;
  199. a := c;
  200. fa := fc;
  201. k := 0
  202. End;
  203. tol := ae+re*spemax(abs(a), abs(b));
  204. w2 := abs(b-a);
  205. If w2>=w1 Then
  206. Begin
  207. stop := true;
  208. term := 2
  209. End;
  210. w1 := w2
  211. End;
  212. If Not stop Then term := 1
  213. End {roof1r};
  214. Procedure roopol(Var a: ArbFloat; n: ArbInt; Var z: complex;
  215. Var k, term: ArbInt);
  216. Const max = 50;
  217. Type rnep2 = array[-2..$ffe0 div SizeOf(ArbFloat)] Of ArbFloat;
  218. Var rk, i, j, l, m, length, term1 : ArbInt;
  219. p, q, r, s, f, df, delp, delq, delr, telp, telq, sn, sn1,
  220. sn2, noise, noise1, noise2, g, absr, maxcoef, coef, d, t,
  221. maxx, fac, meps : ArbFloat;
  222. convergent, linear, quadratic : boolean;
  223. u, v : complex;
  224. pa : ^arfloat1;
  225. pb, pc, ph : ^rnep2;
  226. pz : ^arcomp1;
  227. Function gcd(n, m: ArbInt): ArbInt;
  228. { This function computes the greatest common divisor of m and n}
  229. Var r : ArbInt;
  230. Begin
  231. r := n Mod m;
  232. while r>0 Do
  233. Begin
  234. n := m;
  235. m := r;
  236. r := n Mod m
  237. End;
  238. gcd := m
  239. End {gcd};
  240. Begin
  241. If n<1 Then
  242. Begin
  243. term := 3;
  244. exit
  245. End;
  246. length := (n+3)*sizeof(ArbFloat);
  247. getmem(pb, length);
  248. getmem(pc, length);
  249. getmem(ph, length);
  250. meps := macheps;
  251. pa := @a;
  252. pz := @z;
  253. pb^[-2] := 0;
  254. pb^[-1] := 0;
  255. pc^[-2] := 0;
  256. pc^[-1] := 0;
  257. ph^[-1] := 0;
  258. ph^[0] := 1;
  259. For i:=1 To n Do
  260. ph^[i] := pa^[i];
  261. k := 0;
  262. while (n>0) and (ph^[n]=0) Do
  263. Begin
  264. k := k+1;
  265. pz^[k].Init(0, 0);
  266. n := n-1
  267. End;
  268. If n>0 Then
  269. Begin
  270. l := n;
  271. i := 1;
  272. while (l>1) and (i<n) Do
  273. Begin
  274. If ph^[i] <> 0 Then l := gcd(l, n-i);
  275. i := i+1
  276. End;
  277. If l>1 Then
  278. Begin
  279. n := n Div l;
  280. For i:=1 To n Do
  281. ph^[i] := ph^[l*i]
  282. End
  283. End;
  284. convergent := true ;
  285. while (n>0) and convergent Do
  286. Begin
  287. linear := false;
  288. quadratic := false ;
  289. If n=1 Then
  290. Begin
  291. r := -ph^[1]/ph^[0];
  292. linear := true
  293. End;
  294. If n=2 Then
  295. Begin
  296. p := ph^[1]/ph^[0];
  297. q := ph^[2]/ph^[0];
  298. quadratic := true
  299. End;
  300. If n>2 Then
  301. Begin
  302. If (ph^[n-1]=0) Or (ph^[n-2]=0) Then
  303. Begin
  304. maxcoef := abs(ph^[n-1]/ph^[n]);
  305. For i:=2 To n Do
  306. Begin
  307. coef := spepow(abs(ph^[n-i]/ph^[n]),1/i);
  308. If maxcoef<coef Then maxcoef := coef
  309. End;
  310. maxcoef := 2*maxcoef
  311. End;
  312. If ph^[n-1]=0 Then r := -spesgn(ph^[0])*spesgn(ph^[n])/maxcoef
  313. Else r := -ph^[n]/ph^[n-1];
  314. If ph^[n-2]=0 Then
  315. Begin
  316. p := 0;
  317. q := -1/sqr(maxcoef)
  318. End
  319. Else
  320. Begin
  321. q := ph^[n]/ph^[n-2];
  322. p := (ph^[n-1]-q*ph^[n-3])/ph^[n-2]
  323. End;
  324. m := 0;
  325. while (m<max) and (Not linear) and (Not quadratic) Do
  326. Begin
  327. m := m+1;
  328. For j:=0 To n Do
  329. pb^[j] := ph^[j]-p*pb^[j-1]-q*pb^[j-2];
  330. For j:=0 To n-2 Do
  331. pc^[j] := pb^[j]-p*pc^[j-1]-q*pc^[j-2];
  332. pc^[n-1] := -p*pc^[n-2]-q*pc^[n-3];
  333. s := sqr(pc^[n-2])-pc^[n-1]*pc^[n-3];
  334. telp := pb^[n-1]*pc^[n-2]-pb^[n]*pc^[n-3];
  335. telq := pb^[n]*pc^[n-2]-pb^[n-1]*pc^[n-1];
  336. If s=0 Then
  337. Begin
  338. delp := telp;
  339. delq := telq
  340. End
  341. Else
  342. Begin
  343. delp := telp/s;
  344. delq := telq/s
  345. End;
  346. noise1 := 0;
  347. sn1 := 0;
  348. sn := 1;
  349. noise2 := 4*abs(pb^[n])+3*abs(p*pb^[n-1]);
  350. For j:=n-1 Downto 0 Do
  351. Begin
  352. g := 4*abs(pb^[j])+3*abs(p*pb^[j-1]);
  353. noise1 := noise1+g*abs(sn);
  354. sn2 := sn1;
  355. sn1 := sn;
  356. sn := -p*sn1-q*sn2;
  357. noise2 := noise2+g*abs(sn)
  358. End;
  359. d := p*p-4*q;
  360. absr := abs(r);
  361. f := ph^[0];
  362. df := 0;
  363. noise := abs(f)/2;
  364. For j:=1 To n Do
  365. Begin
  366. df := f+r*df;
  367. f := ph^[j]+r*f;
  368. noise := abs(f)+absr*noise
  369. End;
  370. If df=0 Then delr := f
  371. Else delr := f/df;
  372. If (abs(telp)<=meps*(noise1*abs(pc^[n-2])+
  373. noise2*abs(pc^[n-3])))
  374. And
  375. (abs(telq)<=meps*(noise1* abs(pc^[n-1])+
  376. noise2*abs(pc^[n-2])))
  377. Then quadratic := true
  378. Else
  379. Begin
  380. p := p+delp;
  381. q := q+delq
  382. End;
  383. If abs(f)<=2*meps*noise Then linear := true
  384. Else r := r-delr
  385. End
  386. End;
  387. convergent := linear Or quadratic;
  388. If linear Then
  389. Begin
  390. If l=1 Then
  391. Begin
  392. k := k+1;
  393. pz^[k].xreal := r;
  394. pz^[k].imag := 0
  395. End
  396. Else
  397. Begin
  398. u.init(r, 0);
  399. roobin(l, u, pz^[k+1], term1);
  400. k := k+l
  401. End;
  402. maxx := 0;
  403. rk := 0;
  404. fac := 1;
  405. For j:=n Downto 0 Do
  406. Begin
  407. s := abs(ph^[j]*fac);
  408. fac := fac*r;
  409. If s>maxx Then
  410. Begin
  411. maxx := s;
  412. rk := j-1
  413. End
  414. End;
  415. For j:=1 To rk Do
  416. ph^[j] := ph^[j]+r*ph^[j-1];
  417. If rk<n-1 Then
  418. Begin
  419. s := ph^[n-1];
  420. ph^[n-1] := -ph^[n]/r;
  421. For j:=n-2 Downto rk+1 Do
  422. Begin
  423. t := ph^[j];
  424. ph^[j] := (ph^[j+1]-s)/r;
  425. s := t
  426. End
  427. End;
  428. n := n-1;
  429. End
  430. Else
  431. If quadratic Then
  432. Begin
  433. If l=1 Then
  434. Begin
  435. rooqua(p,q,pz^[k+1],pz^[k+2]);
  436. k := k+2
  437. End
  438. Else
  439. Begin
  440. rooqua(p,q,u,v);
  441. roobin(l,u,pz^[k+1],term1);
  442. roobin(l,v,pz^[k+l+1],term1);
  443. k := k+2*l
  444. End;
  445. n := n-2;
  446. For j:=1 To n Do
  447. ph^[j] := ph^[j]-p*ph^[j-1]-q*ph^[j-2]
  448. End
  449. End;
  450. If k<n Then term := 2
  451. Else term := 1;
  452. freemem(pb, length);
  453. freemem(pc, length);
  454. freemem(ph, length);
  455. End {roopol};
  456. Procedure rooqua(p, q: ArbFloat; Var z1, z2: complex);
  457. Var s, d : ArbFloat;
  458. Begin
  459. p := -p/2;
  460. d := sqr(p)-q;
  461. If d<0 Then
  462. Begin
  463. z1.Init(p, sqrt(-d));
  464. z2 := z1;
  465. z2.conjugate
  466. End
  467. Else
  468. Begin
  469. If p>0 Then s := p+sqrt(d)
  470. Else s := p-sqrt(d);
  471. If s=0 Then
  472. Begin
  473. z1.Init(0, 0);
  474. z2 := z1
  475. End
  476. Else
  477. Begin
  478. z1.Init(s, 0);
  479. z2.Init(q/s, 0)
  480. End
  481. End
  482. End {rooqua};
  483. Procedure roo001(uplo, trans, diag: AnsiChar; n: ArbInt; Var ap1, x1: ArbFloat;
  484. incx: ArbInt);
  485. Var
  486. ap : arfloat1 absolute ap1;
  487. x : arfloat1 absolute x1;
  488. temp : ArbFloat;
  489. info, ix, j, jx, k, kk, kx: ArbInt;
  490. nounit: boolean;
  491. Begin
  492. info := 0;
  493. uplo := upcase(uplo);
  494. trans := upcase(trans);
  495. diag := upcase(diag);
  496. If n=0 Then exit;
  497. nounit := diag='N';
  498. If incx<=0 Then kx := 1-(n-1)*incx
  499. Else kx := 1;
  500. If trans='N' Then
  501. Begin
  502. If uplo='U' Then
  503. Begin
  504. kk := 1;
  505. jx := kx;
  506. For j:=1 To n Do
  507. Begin
  508. If x[jx]<>0 Then
  509. Begin
  510. temp := x[jx];
  511. ix := kx;
  512. For k:=kk To kk+j-2 Do
  513. Begin
  514. x[ix] := x[ix]+temp*ap[k];
  515. inc(ix, incx)
  516. End;
  517. If nounit Then x[jx] := x[jx]*ap[kk+j-1]
  518. End;
  519. inc(jx, incx);
  520. inc(kk, j)
  521. End
  522. End
  523. Else
  524. Begin
  525. kk := n*(n+1) Div 2;
  526. inc(kx, (n-1)*incx);
  527. jx := kx;
  528. For j:=n Downto 1 Do
  529. Begin
  530. If x[jx]<>0 Then
  531. Begin
  532. temp := x[jx];
  533. ix := kx;
  534. For k:=kk Downto kk-(n-(j+1)) Do
  535. Begin
  536. x[ix] := x[ix]+temp*ap[k];
  537. dec(ix, incx)
  538. End;
  539. If nounit Then x[jx] := x[jx]*ap[kk-n+j]
  540. End;
  541. dec(jx, incx);
  542. dec(kk, n-j+1)
  543. End
  544. End
  545. End
  546. Else
  547. Begin
  548. If uplo='U' Then
  549. Begin
  550. kk := n*(n+1) Div 2;
  551. jx := kx+(n-1)*incx;
  552. For j:= n Downto 1 Do
  553. Begin
  554. temp := x[jx];
  555. ix := jx;
  556. If nounit Then temp := temp*ap[kk];
  557. For k:= kk-1 Downto kk-j+1 Do
  558. Begin
  559. dec(ix, incx);
  560. temp := temp+ap[k]*x[ix]
  561. End;
  562. x[jx] := temp;
  563. dec(jx, incx);
  564. dec(kk, j)
  565. End
  566. End
  567. Else
  568. Begin
  569. kk := 1;
  570. jx := kx;
  571. For j:=1 To n Do
  572. Begin
  573. temp := x[jx];
  574. ix := jx;
  575. If nounit Then temp := temp*ap[kk];
  576. For k:=kk+1 To kk+n-j Do
  577. Begin
  578. inc(ix, incx);
  579. temp := temp+ap[k]*x[ix]
  580. End;
  581. x[jx] := temp;
  582. inc(jx, incx);
  583. inc(kk, n-j+1)
  584. End
  585. End
  586. End
  587. End;
  588. Procedure roo002(uplo, trans, diag: AnsiChar; n: ArbInt;
  589. Var ap1, x1: ArbFloat; incx: ArbInt );
  590. Var ap : arfloat1 absolute ap1;
  591. x : arfloat1 absolute x1;
  592. temp : ArbFloat;
  593. info, ix, j, jx, k, kk, kx: ArbInt;
  594. nounit: boolean;
  595. Begin
  596. info := 0;
  597. uplo := upcase(uplo);
  598. trans := upcase(trans);
  599. diag := upcase(diag);
  600. If n=0 Then exit;
  601. nounit := diag='N';
  602. If incx<=0 Then kx := 1-(n-1)*incx
  603. Else kx := 1;
  604. If trans='N' Then
  605. Begin
  606. If uplo='U' Then
  607. Begin
  608. kk := n*(n+1) Div 2;
  609. jx := kx+(n-1)*incx;
  610. For j:=n Downto 1 Do
  611. Begin
  612. If x[jx]<>0 Then
  613. Begin
  614. If nounit Then x[jx] := x[jx]/ap[kk];
  615. temp := x[jx];
  616. ix := jx;
  617. For k:=kk-1 Downto kk-j+1 Do
  618. Begin
  619. dec(ix, incx);
  620. x[ix] := x[ix]-temp*ap[k];
  621. End
  622. End;
  623. dec(jx, incx);
  624. dec(kk, j)
  625. End
  626. End
  627. Else
  628. Begin
  629. kk := 1;
  630. jx := kx;
  631. For j:=1 To n Do
  632. Begin
  633. If x[jx]<>0 Then
  634. Begin
  635. If nounit Then x[jx] := x[jx]/ap[kk];
  636. temp := x[jx];
  637. ix := jx;
  638. For k:= kk+1 To kk+n-j Do
  639. Begin
  640. inc(ix, incx);
  641. x[ix] := x[ix]-temp*ap[k]
  642. End;
  643. End;
  644. inc(jx, incx);
  645. inc(kk, n-j+1)
  646. End
  647. End
  648. End
  649. Else
  650. Begin
  651. If uplo='U' Then
  652. Begin
  653. kk := 1;
  654. jx := kx;
  655. For j:= 1 To n Do
  656. Begin
  657. temp := x[jx];
  658. ix := kx;
  659. For k:= kk To kk+j-2 Do
  660. Begin
  661. temp := temp-ap[k]*x[ix];
  662. inc(ix, incx);
  663. End;
  664. If nounit Then temp := temp/ap[kk+j-1];
  665. x[jx] := temp;
  666. inc(jx, incx);
  667. inc(kk, j)
  668. End
  669. End
  670. Else
  671. Begin
  672. kk := n*(n+1) Div 2;
  673. kx := kx+(n-1)*incx;
  674. jx := kx;
  675. For j:=n Downto 1 Do
  676. Begin
  677. temp := x[jx];
  678. ix := kx;
  679. For k:= kk Downto kk-(n-(j+1)) Do
  680. Begin
  681. temp := temp-ap[k]*x[ix];
  682. dec(ix, incx)
  683. End;
  684. If nounit Then temp := temp/ap[kk-n+j];
  685. x[jx] := temp;
  686. dec(jx, incx);
  687. dec(kk, n-j+1)
  688. End
  689. End
  690. End
  691. End;
  692. Procedure roo003( n: ArbInt; Var x1: ArbFloat; incx: ArbInt;
  693. Var scale, sumsq: ArbFloat );
  694. Var absxi : ArbFloat;
  695. i, ix : ArbInt;
  696. x : arfloat1 absolute x1;
  697. Begin
  698. ix := 1;
  699. If n>0 Then
  700. For i:=1 To n Do
  701. Begin
  702. If x[ix]<>0 Then
  703. Begin
  704. absxi := abs(x[ix]);
  705. If (scale<absxi) Then
  706. Begin
  707. sumsq := 1+sumsq*sqr(scale/absxi);
  708. scale := absxi
  709. End
  710. Else sumsq := sumsq + sqr(absxi/scale)
  711. End;
  712. inc(ix, incx)
  713. End
  714. End;
  715. Function norm2( n: ArbInt; Var x1: ArbFloat; incx: ArbInt): ArbFloat;
  716. Var scale, ssq : ArbFloat;
  717. sqt: ArbFloat;
  718. Begin
  719. If n<1 Then norm2 := 0
  720. Else
  721. If n=1 Then norm2 := abs(x1)
  722. Else
  723. Begin
  724. scale := 0;
  725. ssq := 1;
  726. roo003(n, x1, incx, scale, ssq );
  727. sqt := sqrt( ssq );
  728. If scale<(giant/sqt) Then norm2 := scale*sqt
  729. Else norm2 := giant
  730. End
  731. End;
  732. Procedure roo004(n: ArbInt; Var r1, diag1, qtb1: ArbFloat;
  733. delta: ArbFloat; Var x1: ArbFloat);
  734. Var
  735. r : arfloat1 absolute r1;
  736. diag : arfloat1 absolute diag1;
  737. qtb : arfloat1 absolute qtb1;
  738. x : arfloat1 absolute x1;
  739. wa1, wa2 : ^arfloat1;
  740. alpha, bnorm, gnorm, qnorm, sgnorm, temp: ArbFloat;
  741. i, j, jj, l : ArbInt;
  742. Begin
  743. getmem(wa1, n*sizeof(ArbFloat));
  744. getmem(wa2, n*sizeof(ArbFloat));
  745. jj := 1;
  746. For j:=1 To n Do
  747. Begin
  748. wa1^[j] := r[jj];
  749. If r[jj]=0 Then
  750. Begin
  751. temp := 0;
  752. l := j;
  753. For i:=1 To j-1 Do
  754. Begin
  755. If abs(r[l])>temp Then temp := abs(r[l]);
  756. inc(l, n-i)
  757. End;
  758. If temp=0 Then r[jj] := macheps
  759. Else r[jj] := macheps*temp
  760. End;
  761. inc(jj, n-j+1)
  762. End;
  763. move(qtb, x, n*sizeof(ArbFloat));
  764. roo002('l','t','n', n, r1, x1, 1);
  765. jj := 1;
  766. For j:=1 To n Do
  767. Begin
  768. r[jj] := wa1^[j];
  769. inc(jj, n - j + 1)
  770. End;
  771. For j:=1 To n Do
  772. wa2^[j] := diag[j]*x[j];
  773. qnorm := norm2(n, wa2^[1], 1);
  774. If qnorm>delta Then
  775. Begin
  776. move(qtb, wa1^, n*sizeof(ArbFloat));
  777. roo001('l','n','n', n, r1, wa1^[1], 1);
  778. For i:=1 To n Do
  779. wa1^[i] := wa1^[i]/diag[i];
  780. gnorm := norm2(n, wa1^[1], 1);
  781. sgnorm := 0;
  782. alpha := delta/qnorm;
  783. If gnorm<>0 Then
  784. Begin
  785. For j:=1 To n Do
  786. wa1^[j] := (wa1^[j]/gnorm)/diag[j];
  787. move(wa1^, wa2^, n*sizeof(ArbFloat));
  788. roo001('l','t','n',n,r1,wa2^[1],1);
  789. temp := norm2(n, wa2^[1],1);
  790. sgnorm := (gnorm/temp)/temp;
  791. alpha := 0;
  792. If sgnorm<delta Then
  793. Begin
  794. bnorm := norm2(n, qtb1, 1);
  795. temp := (bnorm/gnorm)*(bnorm/qnorm)*(sgnorm/delta);
  796. temp := temp-(delta/qnorm)*sqr(sgnorm/delta) +
  797. sqrt(sqr(temp-delta/qnorm) +
  798. (1-sqr(delta/qnorm))*(1-sqr(sgnorm/delta)));
  799. alpha := ((delta/qnorm)*(1-sqr(sgnorm/delta)))/temp
  800. End
  801. End;
  802. If sgnorm<delta Then temp := (1-alpha)*sgnorm
  803. Else temp := (1-alpha)*delta;
  804. For j:=1 To n Do
  805. x[j] := temp*wa1^[j] + alpha*x[j]
  806. End;
  807. freemem(wa2, n*sizeof(ArbFloat));
  808. freemem(wa1, n*sizeof(ArbFloat));
  809. End;
  810. Procedure roo005(fcn: roofnrfunc; n: ArbInt; Var x1, fvec1, fjac1: ArbFloat;
  811. ldfjac: ArbInt; Var iflag: ArbInt; ml, mu: ArbInt;
  812. epsfcn: ArbFloat; Var wa1, wa2: arfloat1);
  813. Var eps, h, temp: ArbFloat;
  814. i, j, k, msum: ArbInt;
  815. x : arfloat1 absolute x1;
  816. fvec : arfloat1 absolute fvec1;
  817. fjac : arfloat1 absolute fjac1;
  818. deff : boolean;
  819. Begin
  820. If epsfcn>macheps Then eps := sqrt(epsfcn)
  821. Else eps := sqrt(macheps);
  822. msum := ml+mu+1;
  823. If msum>=n Then
  824. Begin
  825. For j:=1 To n Do
  826. Begin
  827. temp := x[j];
  828. h := eps*abs(temp);
  829. If h=0 Then h := eps;
  830. x[j] := temp+h;
  831. deff := true;
  832. fcn(x1, wa1[1], deff);
  833. If Not deff Then iflag := -1;
  834. If iflag<0 Then exit;
  835. x[j] := temp;
  836. For i:= 1 To n Do
  837. fjac[j+(i-1)*ldfjac] := (wa1[i]-fvec[i])/h
  838. End
  839. End
  840. Else
  841. Begin
  842. For k:=1 To msum Do
  843. Begin
  844. j := k;
  845. while j <= n Do
  846. Begin
  847. wa2[j] := x[j];
  848. h := eps*abs(wa2[j]);
  849. If h=0 Then h := eps;
  850. x[j] := wa2[j]+h;
  851. inc(j, msum)
  852. End;
  853. deff := true;
  854. fcn(x1, wa1[1], deff);
  855. If Not deff Then iflag := -1;
  856. If iflag<0 Then exit;
  857. j := k;
  858. while j<= n Do
  859. Begin
  860. x[j] := wa2[j];
  861. h := eps*abs(wa2[j]);
  862. If h=0 Then h := eps;
  863. For i:=1 To n Do
  864. Begin
  865. fjac[j+(i-1)*ldfjac] := 0;
  866. If (i>=(j-mu)) And (i<=(j+ml))
  867. Then fjac[j+(i-1)*ldfjac] := (wa1[i]-fvec[i])/h
  868. End;
  869. inc(j, msum)
  870. End
  871. End
  872. End
  873. End;
  874. Procedure roo006(trans: AnsiChar; m, n: ArbInt; alpha: ArbFloat; Var a1: ArbFloat;
  875. lda: ArbInt; Var x1: ArbFloat; incx : ArbInt; beta: ArbFloat;
  876. Var y1: ArbFloat; incy : ArbInt);
  877. Var temp : ArbFloat;
  878. i, info, ix, iy, j, jx, jy, kx, ky, lenx, leny: ArbInt;
  879. x : arfloat1 absolute x1;
  880. y : arfloat1 absolute y1;
  881. a : arfloat1 absolute a1;
  882. Begin
  883. info := 0;
  884. trans := upcase(trans);
  885. If (m=0) Or (n=0) Or ((alpha=0) And (beta=1)) Then exit;
  886. If trans='N' Then
  887. Begin
  888. lenx := n;
  889. leny := m
  890. End
  891. Else
  892. Begin
  893. lenx := m;
  894. leny := n
  895. End;
  896. If incx>0 Then kx := 1
  897. Else kx := 1-(lenx-1)*incx;
  898. If incy>0 Then ky := 1
  899. Else ky := 1-(leny-1)*incy;
  900. If (beta<>1) Then
  901. Begin
  902. iy := ky;
  903. If beta=0 Then
  904. For i:=1 To leny Do
  905. Begin
  906. y[iy] := 0;
  907. inc(iy, incy)
  908. End
  909. Else
  910. For i:=1 To leny Do
  911. Begin
  912. y[iy] := beta*y[iy];
  913. inc(iy, incy)
  914. End;
  915. End;
  916. If alpha=0 Then exit;
  917. If trans='N' Then
  918. Begin
  919. jx := kx;
  920. For j:=1 To n Do
  921. Begin
  922. If x[jx]<>0 Then
  923. Begin
  924. temp := alpha*x[jx];
  925. iy := ky;
  926. For i:=1 To m Do
  927. Begin
  928. y[iy] := y[iy]+temp*a[j+(i-1)*lda];
  929. inc(iy, incy)
  930. End
  931. End;
  932. inc(jx, incx)
  933. End
  934. End
  935. Else
  936. Begin
  937. jy := ky;
  938. For j:=1 To n Do
  939. Begin
  940. temp := 0;
  941. ix := kx;
  942. For i:=1 To m Do
  943. Begin
  944. temp := temp+a[j+(i-1)*lda]*x[ix];
  945. inc(ix, incx)
  946. End;
  947. y[jy] := y[jy]+alpha*temp;
  948. inc(jy, incy)
  949. End
  950. End
  951. End;
  952. Procedure roo007(m, n: ArbInt; alpha: ArbFloat; Var x1: ArbFloat; incx: ArbInt;
  953. Var y1: ArbFloat; incy: ArbInt; Var a1: ArbFloat; lda: ArbInt);
  954. Var temp: ArbFloat;
  955. i, info, ix, j, jy, kx: ArbInt;
  956. x : arfloat1 absolute x1;
  957. y : arfloat1 absolute y1;
  958. a : arfloat1 absolute a1;
  959. Begin
  960. info := 0;
  961. If (m=0) Or (n=0) Or (alpha=0) Then exit;
  962. If incy>0 Then jy := 1
  963. Else jy := 1-(n-1)*incy;
  964. If incx>0 Then kx := 1
  965. Else kx := 1-(m-1)*incx;
  966. For j:=1 To n Do
  967. Begin
  968. If y[jy]<>0 Then
  969. Begin
  970. temp := alpha*y[jy];
  971. ix := kx;
  972. For i:=1 To m Do
  973. Begin
  974. a[j +(i-1)*lda] := a[j + (i-1)*lda] + x[ix]*temp;
  975. inc(ix, incx)
  976. End
  977. End;
  978. inc(jy, incy)
  979. End
  980. End;
  981. Procedure roo008(n: ArbInt; Var q1: ArbFloat; ldq: ArbInt; Var wa: arfloat1);
  982. Var q: arfloat1 absolute q1;
  983. i, j, k: ArbInt;
  984. Begin
  985. For j:=2 To n Do
  986. For i:=1 To j-1 Do
  987. q[j+(i-1)*ldq] := 0;
  988. For k:=n Downto 1 Do
  989. Begin
  990. If (q[k+(k-1)*ldq]<>0) And (k<>n) Then
  991. Begin
  992. roo006('t', n-k+1, n-k, 1, q[k+1+(k-1)*ldq], ldq,
  993. q[k +(k-1)*ldq], ldq, 0, wa[k+1], 1);
  994. roo007(n-k+1, n-k, -1/q[k+(k-1)*ldq], q[k+(k-1)*ldq], ldq,
  995. wa[k+1], 1, q[k+1+(k-1)*ldq], ldq)
  996. End;
  997. For i:=k + 1 To n Do
  998. q[k+(i-1)*ldq] := -q[k+(i-1)*ldq];
  999. q[k+(k-1)*ldq] := 1-q[k+(k-1)*ldq]
  1000. End;
  1001. End;
  1002. Procedure roo009(n: ArbInt; Var a1: ArbFloat; lda: ArbInt;
  1003. Var rdiag1, acnorm1: ArbFloat);
  1004. Var a : arfloat1 absolute a1;
  1005. rdiag : arfloat1 absolute rdiag1;
  1006. acnorm : arfloat1 absolute acnorm1;
  1007. ajnorm : ArbFloat;
  1008. i, j : ArbInt;
  1009. Begin
  1010. For j:=1 To n Do
  1011. acnorm[j] := norm2(n, a[j], lda);
  1012. For j:=1 To n Do
  1013. Begin
  1014. ajnorm := norm2(n-j+1, a[j+(j-1)*lda], lda);
  1015. If ajnorm<>0 Then
  1016. Begin
  1017. If a[j+(j-1)*lda]<0 Then ajnorm := -ajnorm;
  1018. For i:=j To n Do
  1019. a[j+(i-1)*lda] := a[j+(i-1)*lda]/ajnorm;
  1020. a[j+(j-1)*lda] := a[j+(j-1)*lda]+1;
  1021. If j<>n Then
  1022. Begin
  1023. roo006('t', n-j+1, n-j, 1, a[j+1+(j-1)*lda], lda,
  1024. a[j+(j-1)*lda], lda, 0, rdiag[j+1], 1);
  1025. roo007(n-j+1, n-j, -1/a[j+(j-1)*lda], a[j+(j-1)*lda], lda,
  1026. rdiag[j+1], 1, a[j+1+(j-1)*lda], lda)
  1027. End
  1028. End;
  1029. rdiag[j] := -ajnorm
  1030. End
  1031. End;
  1032. Procedure roo010(n: ArbInt; Var x1: ArbFloat; incx: ArbInt;
  1033. Var y1: ArbFloat; incy: ArbInt; c, s:ArbFloat );
  1034. Var temp1: ArbFloat;
  1035. x : arfloat1 absolute x1;
  1036. y : arfloat1 absolute y1;
  1037. i, ix, iy: ArbInt;
  1038. Begin
  1039. If incy>=0 Then iy := 1
  1040. Else iy := 1-(n-1)*incy;
  1041. If incx>=0 Then ix := 1
  1042. Else ix := 1-(n-1)*incx;
  1043. For i:=1 To n Do
  1044. Begin
  1045. temp1 := x[ix];
  1046. x[ix] := s*y[iy]+c*temp1;
  1047. y[iy] := c*y[iy]-s*temp1;
  1048. inc(ix, incx);
  1049. inc(iy, incy)
  1050. End
  1051. End;
  1052. Procedure roo011(m, n: ArbInt; Var a1: ArbFloat; lda: ArbInt; Var v1, w1: ArbFloat);
  1053. Var a: arfloat1 absolute a1;
  1054. v: arfloat1 absolute v1;
  1055. w: arfloat1 absolute w1;
  1056. sine, cosine: ArbFloat;
  1057. j, nm1, nmj: ArbInt;
  1058. Begin
  1059. nm1 := n-1;
  1060. For nmj:=1 To nm1 Do
  1061. Begin
  1062. j := n-nmj;
  1063. If (abs(v[j])>1) Then
  1064. Begin
  1065. cosine := 1/v[j];
  1066. sine := sqrt(1-sqr(cosine))
  1067. End
  1068. Else
  1069. Begin
  1070. sine := v[j];
  1071. cosine := sqrt(1-sqr(sine))
  1072. End;
  1073. roo010(m, a[n], lda, a[j], lda, cosine, sine)
  1074. End;
  1075. For j:=1 To nm1 Do
  1076. Begin
  1077. If (abs(w[j])>1) Then
  1078. Begin
  1079. cosine := 1/w[j];
  1080. sine := sqrt(1-sqr(cosine))
  1081. End
  1082. Else
  1083. Begin
  1084. sine := w[j];
  1085. cosine := sqrt(1-sqr(sine))
  1086. End;
  1087. roo010(m, a[j], lda, a[n], lda, cosine, sine)
  1088. End
  1089. End;
  1090. Procedure roo012(m, n: ArbInt; Var s1: ArbFloat; ls: ArbInt;
  1091. Var u1, v1, w1: ArbFloat; Var sing: boolean);
  1092. Const one = 1.0;
  1093. p5 = 0.5;
  1094. p25 = 0.25;
  1095. zero = 0.0;
  1096. Var cosine, cotan, sine, tangnt, tau: ArbFloat;
  1097. i, j, jj, nm1, nmj: ArbInt;
  1098. s : arfloat1 absolute s1;
  1099. u : arfloat1 absolute u1;
  1100. v : arfloat1 absolute v1;
  1101. w : arfloat1 absolute w1;
  1102. Begin
  1103. jj := (n*(2*m-n+1)) Div 2 - (m-n);
  1104. If m>=n Then move(s[jj], w[n], (m-n+1)*sizeof(ArbFloat));
  1105. nm1 := n-1;
  1106. For nmj:=1 To nm1 Do
  1107. Begin
  1108. j := n-nmj;
  1109. jj := jj-(m-j+1);
  1110. w[j] := zero;
  1111. If (v[j]<>zero) Then
  1112. Begin
  1113. If (abs(v[n])<abs(v[j])) Then
  1114. Begin
  1115. cotan := v[n]/v[j];
  1116. sine := p5/sqrt(p25+p25*sqr(cotan));
  1117. cosine := sine*cotan;
  1118. If (abs(cosine)*giant)>one
  1119. Then tau := one/cosine
  1120. Else tau := one
  1121. End
  1122. Else
  1123. Begin
  1124. tangnt := v[j]/v[n];
  1125. cosine := p5/sqrt(p25+p25*sqr(tangnt));
  1126. sine := cosine*tangnt;
  1127. tau := sine;
  1128. End;
  1129. v[n] := sine*v[j]+cosine*v[n];
  1130. v[j] := tau;
  1131. roo010(m-j+1, w[j], 1, s[jj], 1, cosine, sine)
  1132. End
  1133. End;
  1134. For i:=1 To m Do
  1135. w[i] := w[i]+v[n]*u[i];
  1136. sing := false;
  1137. For j:=1 To nm1 Do
  1138. Begin
  1139. If w[j]<>zero Then
  1140. Begin
  1141. If abs(s[jj])<abs(w[j]) Then
  1142. Begin
  1143. cotan := s[jj]/w[j];
  1144. sine := p5/sqrt(p25+p25*sqr(cotan));
  1145. cosine := sine*cotan;
  1146. If (abs(cosine)*giant)>one Then tau := one/cosine
  1147. Else tau := one
  1148. End
  1149. Else
  1150. Begin
  1151. tangnt := w[j]/s[jj];
  1152. cosine := p5/sqrt(p25+p25*sqr(tangnt));
  1153. sine := cosine*tangnt;
  1154. tau := sine
  1155. End;
  1156. roo010(m-j+1, s[jj], 1, w[j], 1, cosine, sine);
  1157. w[j] := tau
  1158. End;
  1159. If (s[jj]=zero) Then sing := true;
  1160. inc(jj, m-j+1)
  1161. End;
  1162. If m>=n Then move(w[n], s[jj], (m-n+1)*sizeof(ArbFloat));
  1163. If s[jj]=zero Then sing := true
  1164. End;
  1165. Procedure roo013(fcn: roofnrfunc; n: ArbInt; Var x1, fvec1: ArbFloat;
  1166. xtol: ArbFloat; maxfev, ml, mu: ArbInt; epsfcn: ArbFloat;
  1167. Var diag1: ArbFloat; factor: ArbFloat; Var info: ArbInt;
  1168. Var fjac1: ArbFloat; ldfjac: ArbInt;
  1169. Var r1: ArbFloat; lr: ArbInt; Var qtf1: ArbFloat);
  1170. Const p1 = 0.1;
  1171. p5 = 0.5;
  1172. p001 = 0.001;
  1173. p0001 = 0.0001;
  1174. Var diag : arfloat1 absolute diag1;
  1175. fjac : arfloat1 absolute fjac1;
  1176. fvec : arfloat1 absolute fvec1;
  1177. qtf : arfloat1 absolute qtf1;
  1178. r : arfloat1 absolute r1;
  1179. wa1, wa2, wa3, wa4: ^arfloat1;
  1180. x : arfloat1 absolute x1;
  1181. actred, delta, fnorm, fnorm1, pnorm,
  1182. prered, ratio, sum, temp, xnorm : ArbFloat;
  1183. i, iflag, iter, j, jm1, l, msum, ncfail, ncsuc, nfev,
  1184. nslow1, nslow2, ns : ArbInt;
  1185. jeval, sing, deff: boolean;
  1186. Begin
  1187. info := 1;
  1188. iflag := 0;
  1189. nfev := 0;
  1190. ns := n*sizeof(ArbFloat);
  1191. For j:=1 To n Do
  1192. If diag[j]<=0 Then exit;
  1193. iflag := 1;
  1194. deff := true;
  1195. fcn(x1, fvec1, deff);
  1196. If Not deff Then iflag := -1;
  1197. nfev := 1;
  1198. If iflag<0 Then
  1199. Begin
  1200. info := iflag;
  1201. exit
  1202. End;
  1203. fnorm := norm2(n, fvec1, 1);
  1204. msum := ml+mu+1;
  1205. If msum>n Then msum := n;
  1206. getmem(wa1, ns);
  1207. getmem(wa2, ns);
  1208. getmem(wa3, ns);
  1209. getmem(wa4, ns);
  1210. iter := 1;
  1211. ncsuc := 0;
  1212. ncfail := 0;
  1213. nslow1 := 0;
  1214. nslow2 := 0;
  1215. while (info=1) and (iflag>=0) Do
  1216. Begin
  1217. jeval := true;
  1218. iflag := 2;
  1219. roo005(fcn, n, x1, fvec1, fjac1, ldfjac, iflag, ml, mu, epsfcn,
  1220. wa1^, wa2^);
  1221. inc(nfev, msum);
  1222. If iflag>=0 Then
  1223. Begin
  1224. roo009(n, fjac1, ldfjac, wa1^[1], wa2^[1]);
  1225. If iter=1 Then
  1226. Begin
  1227. For j:=1 To n Do
  1228. wa3^[j] := diag[j]*x[j];
  1229. xnorm := norm2(n, wa3^[1], 1);
  1230. delta := factor*xnorm;
  1231. If delta=0 Then delta := factor;
  1232. End;
  1233. For i:=1 To n Do
  1234. qtf[i] := fvec[i];
  1235. For j:=1 To n Do
  1236. If fjac[j+(j-1)*ldfjac]<>0 Then
  1237. Begin
  1238. sum := 0;
  1239. For i:=j To n Do
  1240. sum := sum+fjac[j+(i-1)*ldfjac]*qtf[i];
  1241. temp := -sum/fjac[j+(j-1)*ldfjac];
  1242. For i:=j To n Do
  1243. qtf[i] := qtf[i]+fjac[j+(i-1)*ldfjac]*temp
  1244. End;
  1245. sing := false;
  1246. For j:=1 To n Do
  1247. Begin
  1248. l := j;
  1249. jm1 := j-1;
  1250. For i:=1 To jm1 Do
  1251. Begin
  1252. r[l] := fjac[j+(i-1)*ldfjac];
  1253. inc(l, n-i)
  1254. End;
  1255. r[l] := wa1^[j];
  1256. If wa1^[j]=0 Then sing := true
  1257. End;
  1258. roo008(n, fjac1, ldfjac, wa1^);
  1259. Repeat
  1260. roo004(n, r1, diag1, qtf1, delta, wa1^[1]);
  1261. For j:=1 To n Do
  1262. Begin
  1263. wa1^[j] := -wa1^[j];
  1264. wa2^[j] := x[j]+wa1^[j];
  1265. wa3^[j] := diag[j]*wa1^[j]
  1266. End;
  1267. pnorm := norm2(n, wa3^[1], 1);
  1268. If iter=1 Then If pnorm<delta Then delta := pnorm;
  1269. iflag := 1;
  1270. deff := true;
  1271. fcn(wa2^[1], wa4^[1], deff);
  1272. If Not deff Then iflag := -1;
  1273. inc(nfev);
  1274. If iflag>0 Then
  1275. Begin
  1276. fnorm1 := norm2(n, wa4^[1], 1);
  1277. If fnorm1<fnorm Then actred := 1-sqr(fnorm1/fnorm)
  1278. Else actred := -1;
  1279. move(wa1^, wa3^, n*sizeof(ArbFloat));
  1280. roo001('l','t','n', n, r1, wa3^[1], 1);
  1281. For i:=1 To n Do
  1282. wa3^[i] := wa3^[i] + qtf[i];
  1283. temp := norm2(n, wa3^[1], 1);
  1284. If temp<fnorm
  1285. Then prered := 1 - sqr(temp/fnorm)
  1286. Else prered := 1;
  1287. If prered>0 Then ratio := actred/prered
  1288. Else ratio := 0;
  1289. If ratio<p1 Then
  1290. Begin
  1291. ncsuc := 0;
  1292. inc(ncfail);
  1293. delta := p5*delta
  1294. End
  1295. Else
  1296. Begin
  1297. ncfail := 0;
  1298. inc(ncsuc);
  1299. If (ratio>=p5) Or (ncsuc>1)
  1300. Then If delta<pnorm/p5 Then delta := pnorm/p5;
  1301. If abs(ratio-1)<=p1 Then delta := pnorm/p5
  1302. End;
  1303. If ratio>=p0001 Then
  1304. Begin
  1305. For j:=1 To n Do
  1306. Begin
  1307. x[j] := wa2^[j];
  1308. wa2^[j] := diag[j]*x[j];
  1309. fvec[j] := wa4^[j]
  1310. End;
  1311. xnorm := norm2(n, wa2^[1], 1);
  1312. fnorm := fnorm1;
  1313. inc(iter)
  1314. End;
  1315. inc(nslow1);
  1316. If actred>=p001 Then nslow1 := 0;
  1317. If jeval Then inc(nslow2);
  1318. If actred>=p1 Then nslow2 := 0;
  1319. If (delta<=xtol*xnorm) Or
  1320. (fnorm=0) Or (pnorm=0) Then info := 0
  1321. Else If nfev>=maxfev Then info := 2
  1322. Else If delta<=macheps*xnorm Then info := 3
  1323. Else If nslow2=5 Then info := 4
  1324. Else If nslow1=10 Then info := 5;
  1325. If (info=1) And (ncfail<>2) Then
  1326. Begin
  1327. roo006('t', n, n, 1, fjac1, ldfjac, wa4^[1], 1, 0,
  1328. wa2^[1], 1);
  1329. If ratio>=p0001 Then move(wa2^, qtf, ns);
  1330. For j:=1 To n Do
  1331. Begin
  1332. wa2^[j] := (wa2^[j]-wa3^[j])/pnorm;
  1333. wa1^[j] := diag[j]*((diag[j]*wa1^[j])/pnorm)
  1334. End;
  1335. roo012(n, n, r1, lr, wa1^[1], wa2^[1], wa3^[1], sing);
  1336. roo011(n, n, fjac1, ldfjac, wa2^[1], wa3^[1]);
  1337. roo011(1, n, qtf1, 1, wa2^[1], wa3^[1]);
  1338. jeval := false
  1339. End
  1340. End
  1341. Until (iflag<0) Or (ncfail=2) Or (info<>1)
  1342. End
  1343. End;
  1344. freemem(wa4, ns);
  1345. freemem(wa3, ns);
  1346. freemem(wa2, ns);
  1347. freemem(wa1, ns);
  1348. If iflag<0 Then info := iflag;
  1349. End;
  1350. Procedure roofnr(f: roofnrfunc; n: ArbInt; Var x, residu: ArbFloat; re: ArbFloat;
  1351. Var term: ArbInt);
  1352. Var j, lr, ns : ArbInt;
  1353. wa1, wa2, wa3, wa4, fx : ^arfloat1;
  1354. Begin
  1355. ns := n*sizeof(ArbFloat);
  1356. If n<=0 Then term := 3
  1357. Else
  1358. Begin
  1359. If re<0 Then term := 3
  1360. Else
  1361. Begin
  1362. lr := (n*(n+1)) Div 2;
  1363. getmem(wa1, ns);
  1364. getmem(wa2, ns);
  1365. getmem(wa3, lr*sizeof(ArbFloat));
  1366. getmem(wa4, n*ns);
  1367. getmem(fx, ns);
  1368. For j:=1 To n Do
  1369. wa1^[j] := 1;
  1370. roo013(f, n, x, fx^[1], re, 200*(n+1), n-1, n-1, 0, wa1^[1],
  1371. 100.0, term, wa4^[1], n, wa3^[1], lr, wa2^[1]);
  1372. residu := Norm2(n, fx^[1], 1);
  1373. freemem(fx, ns);
  1374. freemem(wa4, n*ns);
  1375. freemem(wa3, lr*sizeof(ArbFloat));
  1376. freemem(wa2, ns);
  1377. freemem(wa1, ns);
  1378. If term<0 Then term := 6
  1379. Else
  1380. Case term Of
  1381. 0: term := 1;
  1382. 2: term := 4;
  1383. 3: term := 2;
  1384. 4, 5: term := 5;
  1385. End
  1386. End
  1387. End
  1388. End;
  1389. End.