mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-06-26 04:38:18 +02:00
1450 lines
39 KiB
ObjectPascal
1450 lines
39 KiB
ObjectPascal
{
|
|
$Id$
|
|
This file is part of the Numlib package.
|
|
Copyright (c) 1986-2000 by
|
|
Kees van Ginneken, Wil Kortsmit and Loek van Reij of the
|
|
Computational centre of the Eindhoven University of Technology
|
|
|
|
FPC port Code by Marco van de Voort (marco@freepascal.org)
|
|
documentation by Michael van Canneyt (Michael@freepascal.org)
|
|
|
|
Unit to find roots of (various kinds of) equations
|
|
|
|
See the file COPYING.FPC, included in this distribution,
|
|
for details about the copyright.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
**********************************************************************}
|
|
|
|
Unit roo;
|
|
{$i direct.inc}
|
|
|
|
interface
|
|
|
|
uses typ, spe;
|
|
|
|
{Find the all roots of the binomial eq. x^n=a, with "a" a complex number}
|
|
|
|
Procedure roobin(n: ArbInt; a: complex; Var z: complex; Var term: ArbInt);
|
|
|
|
{Find root point of f(x)=0 with f(x) a continuous function on domain [a,b]
|
|
If f(a)*f(b)<=0 then there must be (at least) one rootpoint}
|
|
|
|
Procedure roof1r(f: rfunc1r; a, b, ae, re: ArbFloat; Var x: ArbFloat;
|
|
Var term: ArbInt);
|
|
|
|
{Determine all zeropoints for a given n'th degree polynomal with real
|
|
coefficients}
|
|
|
|
Procedure roopol(Var a: ArbFloat; n: ArbInt; Var z: complex;
|
|
Var k, term: ArbInt);
|
|
|
|
{Find roots for a simple 2th degree eq x^2+px+q=0 with p and q real}
|
|
|
|
Procedure rooqua(p, q: ArbFloat; Var z1, z2: complex);
|
|
|
|
{Roofnr is undocumented, but verry big}
|
|
|
|
Procedure roofnr(f: roofnrfunc; n: ArbInt; Var x, residu: ArbFloat; re: ArbFloat;
|
|
Var term: ArbInt);
|
|
|
|
{ term : 1 succesful termination
|
|
2 Couldn't reach the specified precision
|
|
Value X is the best one which could be found.
|
|
3 Wrong input
|
|
4 Too many functionvalues calculated, try to recalc with the
|
|
calculated X
|
|
5 Not enough progress. Possibly there is no solution, or the
|
|
solution is too close to 0. Try to choose a different
|
|
initial startingvalue
|
|
6 Process wants to calculate a function value outside the by
|
|
"deff" defined area.
|
|
}
|
|
|
|
implementation
|
|
|
|
Procedure roobin(n: ArbInt; a: complex; Var z: complex; Var term: ArbInt);
|
|
{ This procedure solves the binomial equation z**n = a, with a complex}
|
|
|
|
Var i, j, k : ArbInt;
|
|
w, fie, dfie, r : ArbFloat;
|
|
pz : ^arcomp1;
|
|
Begin
|
|
If n<1 Then
|
|
Begin
|
|
term := 2;
|
|
exit
|
|
End;
|
|
term := 1;
|
|
pz := @z;
|
|
dfie := 2*pi/n;
|
|
k := 1;
|
|
If a.im=0 Then
|
|
Begin
|
|
If a.re>0 Then
|
|
Begin
|
|
r := spepow(a.re, 1/n);
|
|
pz^[1].Init(r, 0);
|
|
k := k+1;
|
|
i := (n-1) Div 2;
|
|
If Not odd(n) Then
|
|
Begin
|
|
pz^[k].Init(-r, 0);
|
|
k := k+1
|
|
End;
|
|
For j:=1 To i Do
|
|
Begin
|
|
w := j*dfie;
|
|
pz^[k].Init(r*cos(w), r*sin(w));
|
|
pz^[k+1] := pz^[k];
|
|
pz^[k+1].Conjugate;
|
|
k := k+2
|
|
End
|
|
End
|
|
Else
|
|
Begin
|
|
fie := pi/n;
|
|
r := spepow(-a.re, 1/n);
|
|
i := n Div 2-1;
|
|
If odd(n) Then
|
|
Begin
|
|
pz^[k].Init(-r, 0);
|
|
k := k+1
|
|
End;
|
|
For j:=0 To i Do
|
|
Begin
|
|
w := fie+j*dfie;
|
|
pz^[k].Init(r*cos(w), r*sin(w));
|
|
pz^[k+1] := pz^[k];
|
|
pz^[k+1].Conjugate;
|
|
k := k+2
|
|
End
|
|
End
|
|
End
|
|
Else
|
|
Begin
|
|
If abs(a.re)>=abs(a.im) Then
|
|
r := spepow(abs(a.re)*sqrt(1+sqr(a.im/a.re)), 1/n)
|
|
Else r := spepow(abs(a.im)*sqrt(1+sqr(a.re/a.im)), 1/n);
|
|
fie := a.arg/n;
|
|
i := n Div 2;
|
|
For j:=0 To n-1 Do
|
|
Begin
|
|
w := fie+(j-i)*dfie;
|
|
pz^[j+1].Init(r*cos(w), r*sin(w))
|
|
End
|
|
End
|
|
End {roobin};
|
|
|
|
Procedure roof1r(f: rfunc1r; a, b, ae, re: ArbFloat; Var x: ArbFloat;
|
|
Var term: ArbInt);
|
|
|
|
Var fa, fb, c, fc, m, tol, w1, w2 : ArbFloat;
|
|
k : ArbInt;
|
|
stop : boolean;
|
|
|
|
Begin
|
|
fa := f(a);
|
|
fb := f(b);
|
|
If (spesgn(fa)*spesgn(fb)=1) Or (ae<0) Or (re<0)
|
|
Then {wrong input}
|
|
Begin
|
|
term := 3;
|
|
exit
|
|
End;
|
|
If abs(fb)>abs(fa) Then
|
|
Begin
|
|
c := b;
|
|
fc := fb;
|
|
x := a;
|
|
b := a;
|
|
fb := fa;
|
|
a := c;
|
|
fa := fc
|
|
End
|
|
Else
|
|
Begin
|
|
c := a;
|
|
fc := fa;
|
|
x := b
|
|
End;
|
|
k := 0;
|
|
tol := ae+re*spemax(abs(a), abs(b));
|
|
w1 := abs(b-a);
|
|
stop := false;
|
|
while (abs(b-a)>tol) and (fb<>0) and (Not stop) Do
|
|
Begin
|
|
m := (a+b)/2;
|
|
If (k>=2) Or (fb=fc) Then x := m
|
|
Else
|
|
Begin
|
|
x := (b*fc-c*fb)/(fc-fb);
|
|
If abs(b-x)<tol Then x := b-tol*spesgn(b-a);
|
|
If spesgn(x-m)=spesgn(x-b) Then x := m
|
|
End;
|
|
c := b;
|
|
fc := fb;
|
|
b := x;
|
|
fb := f(x);
|
|
If spesgn(fa)*spesgn(fb)>0 Then
|
|
Begin
|
|
a := c;
|
|
fa := fc;
|
|
k := 0
|
|
End
|
|
Else k := k+1;
|
|
If abs(fb)>=abs(fa) Then
|
|
Begin
|
|
c := b;
|
|
fc := fb;
|
|
x := a;
|
|
b := a;
|
|
fb := fa;
|
|
a := c;
|
|
fa := fc;
|
|
k := 0
|
|
End;
|
|
tol := ae+re*spemax(abs(a), abs(b));
|
|
w2 := abs(b-a);
|
|
If w2>=w1 Then
|
|
Begin
|
|
stop := true;
|
|
term := 2
|
|
End;
|
|
w1 := w2
|
|
End;
|
|
If Not stop Then term := 1
|
|
End {roof1r};
|
|
|
|
Procedure roopol(Var a: ArbFloat; n: ArbInt; Var z: complex;
|
|
Var k, term: ArbInt);
|
|
|
|
Const max = 50;
|
|
|
|
Type rnep2 = array[-2..$ffe0 div SizeOf(ArbFloat)] Of ArbFloat;
|
|
|
|
Var rk, i, j, l, m, length, term1 : ArbInt;
|
|
p, q, r, s, f, df, delp, delq, delr, telp, telq, sn, sn1,
|
|
sn2, noise, noise1, noise2, g, absr, maxcoef, coef, d, t,
|
|
maxx, fac, meps : ArbFloat;
|
|
convergent, linear, quadratic : boolean;
|
|
u, v : complex;
|
|
pa : ^arfloat1;
|
|
pb, pc, ph : ^rnep2;
|
|
pz : ^arcomp1;
|
|
|
|
Function gcd(n, m: ArbInt): ArbInt;
|
|
{ This function computes the greatest common divisor of m and n}
|
|
|
|
Var r : ArbInt;
|
|
Begin
|
|
r := n Mod m;
|
|
while r>0 Do
|
|
Begin
|
|
n := m;
|
|
m := r;
|
|
r := n Mod m
|
|
End;
|
|
gcd := m
|
|
End {gcd};
|
|
Begin
|
|
If n<1 Then
|
|
Begin
|
|
term := 3;
|
|
exit
|
|
End;
|
|
length := (n+3)*sizeof(ArbFloat);
|
|
getmem(pb, length);
|
|
getmem(pc, length);
|
|
getmem(ph, length);
|
|
meps := macheps;
|
|
pa := @a;
|
|
pz := @z;
|
|
pb^[-2] := 0;
|
|
pb^[-1] := 0;
|
|
pc^[-2] := 0;
|
|
pc^[-1] := 0;
|
|
ph^[-1] := 0;
|
|
ph^[0] := 1;
|
|
For i:=1 To n Do
|
|
ph^[i] := pa^[i];
|
|
k := 0;
|
|
while (n>0) and (ph^[n]=0) Do
|
|
Begin
|
|
k := k+1;
|
|
pz^[k].Init(0, 0);
|
|
n := n-1
|
|
End;
|
|
If n>0 Then
|
|
Begin
|
|
l := n;
|
|
i := 1;
|
|
while (l>1) and (i<n) Do
|
|
Begin
|
|
If ph^[i] <> 0 Then l := gcd(l, n-i);
|
|
i := i+1
|
|
End;
|
|
If l>1 Then
|
|
Begin
|
|
n := n Div l;
|
|
For i:=1 To n Do
|
|
ph^[i] := ph^[l*i]
|
|
End
|
|
End;
|
|
convergent := true ;
|
|
while (n>0) and convergent Do
|
|
Begin
|
|
linear := false;
|
|
quadratic := false ;
|
|
If n=1 Then
|
|
Begin
|
|
r := -ph^[1]/ph^[0];
|
|
linear := true
|
|
End;
|
|
If n=2 Then
|
|
Begin
|
|
p := ph^[1]/ph^[0];
|
|
q := ph^[2]/ph^[0];
|
|
quadratic := true
|
|
End;
|
|
If n>2 Then
|
|
Begin
|
|
If (ph^[n-1]=0) Or (ph^[n-2]=0) Then
|
|
Begin
|
|
maxcoef := abs(ph^[n-1]/ph^[n]);
|
|
For i:=2 To n Do
|
|
Begin
|
|
coef := spepow(abs(ph^[n-i]/ph^[n]),1/i);
|
|
If maxcoef<coef Then maxcoef := coef
|
|
End;
|
|
maxcoef := 2*maxcoef
|
|
End;
|
|
If ph^[n-1]=0 Then r := -spesgn(ph^[0])*spesgn(ph^[n])/maxcoef
|
|
Else r := -ph^[n]/ph^[n-1];
|
|
If ph^[n-2]=0 Then
|
|
Begin
|
|
p := 0;
|
|
q := -1/sqr(maxcoef)
|
|
End
|
|
Else
|
|
Begin
|
|
q := ph^[n]/ph^[n-2];
|
|
p := (ph^[n-1]-q*ph^[n-3])/ph^[n-2]
|
|
End;
|
|
m := 0;
|
|
while (m<max) and (Not linear) and (Not quadratic) Do
|
|
Begin
|
|
m := m+1;
|
|
For j:=0 To n Do
|
|
pb^[j] := ph^[j]-p*pb^[j-1]-q*pb^[j-2];
|
|
For j:=0 To n-2 Do
|
|
pc^[j] := pb^[j]-p*pc^[j-1]-q*pc^[j-2];
|
|
pc^[n-1] := -p*pc^[n-2]-q*pc^[n-3];
|
|
s := sqr(pc^[n-2])-pc^[n-1]*pc^[n-3];
|
|
telp := pb^[n-1]*pc^[n-2]-pb^[n]*pc^[n-3];
|
|
telq := pb^[n]*pc^[n-2]-pb^[n-1]*pc^[n-1];
|
|
If s=0 Then
|
|
Begin
|
|
delp := telp;
|
|
delq := telq
|
|
End
|
|
Else
|
|
Begin
|
|
delp := telp/s;
|
|
delq := telq/s
|
|
End;
|
|
noise1 := 0;
|
|
sn1 := 0;
|
|
sn := 1;
|
|
noise2 := 4*abs(pb^[n])+3*abs(p*pb^[n-1]);
|
|
For j:=n-1 Downto 0 Do
|
|
Begin
|
|
g := 4*abs(pb^[j])+3*abs(p*pb^[j-1]);
|
|
noise1 := noise1+g*abs(sn);
|
|
sn2 := sn1;
|
|
sn1 := sn;
|
|
sn := -p*sn1-q*sn2;
|
|
noise2 := noise2+g*abs(sn)
|
|
End;
|
|
d := p*p-4*q;
|
|
absr := abs(r);
|
|
f := ph^[0];
|
|
df := 0;
|
|
noise := abs(f)/2;
|
|
For j:=1 To n Do
|
|
Begin
|
|
df := f+r*df;
|
|
f := ph^[j]+r*f;
|
|
noise := abs(f)+absr*noise
|
|
End;
|
|
If df=0 Then delr := f
|
|
Else delr := f/df;
|
|
If (abs(telp)<=meps*(noise1*abs(pc^[n-2])+
|
|
noise2*abs(pc^[n-3])))
|
|
And
|
|
(abs(telq)<=meps*(noise1* abs(pc^[n-1])+
|
|
noise2*abs(pc^[n-2])))
|
|
Then quadratic := true
|
|
Else
|
|
Begin
|
|
p := p+delp;
|
|
q := q+delq
|
|
End;
|
|
If abs(f)<=2*meps*noise Then linear := true
|
|
Else r := r-delr
|
|
End
|
|
End;
|
|
convergent := linear Or quadratic;
|
|
If linear Then
|
|
Begin
|
|
If l=1 Then
|
|
Begin
|
|
k := k+1;
|
|
pz^[k].xreal := r;
|
|
pz^[k].imag := 0
|
|
End
|
|
Else
|
|
Begin
|
|
u.init(r, 0);
|
|
roobin(l, u, pz^[k+1], term1);
|
|
k := k+l
|
|
End;
|
|
maxx := 0;
|
|
rk := 0;
|
|
fac := 1;
|
|
For j:=n Downto 0 Do
|
|
Begin
|
|
s := abs(ph^[j]*fac);
|
|
fac := fac*r;
|
|
If s>maxx Then
|
|
Begin
|
|
maxx := s;
|
|
rk := j-1
|
|
End
|
|
End;
|
|
For j:=1 To rk Do
|
|
ph^[j] := ph^[j]+r*ph^[j-1];
|
|
If rk<n-1 Then
|
|
Begin
|
|
s := ph^[n-1];
|
|
ph^[n-1] := -ph^[n]/r;
|
|
For j:=n-2 Downto rk+1 Do
|
|
Begin
|
|
t := ph^[j];
|
|
ph^[j] := (ph^[j+1]-s)/r;
|
|
s := t
|
|
End
|
|
End;
|
|
n := n-1;
|
|
End
|
|
Else
|
|
If quadratic Then
|
|
Begin
|
|
If l=1 Then
|
|
Begin
|
|
rooqua(p,q,pz^[k+1],pz^[k+2]);
|
|
k := k+2
|
|
End
|
|
Else
|
|
Begin
|
|
rooqua(p,q,u,v);
|
|
roobin(l,u,pz^[k+1],term1);
|
|
roobin(l,v,pz^[k+l+1],term1);
|
|
k := k+2*l
|
|
End;
|
|
n := n-2;
|
|
For j:=1 To n Do
|
|
ph^[j] := ph^[j]-p*ph^[j-1]-q*ph^[j-2]
|
|
End
|
|
End;
|
|
If k<n Then term := 2
|
|
Else term := 1;
|
|
freemem(pb, length);
|
|
freemem(pc, length);
|
|
freemem(ph, length);
|
|
End {roopol};
|
|
|
|
Procedure rooqua(p, q: ArbFloat; Var z1, z2: complex);
|
|
|
|
Var s, d : ArbFloat;
|
|
Begin
|
|
p := -p/2;
|
|
d := sqr(p)-q;
|
|
If d<0 Then
|
|
Begin
|
|
z1.Init(p, sqrt(-d));
|
|
z2 := z1;
|
|
z2.conjugate
|
|
End
|
|
Else
|
|
Begin
|
|
If p>0 Then s := p+sqrt(d)
|
|
Else s := p-sqrt(d);
|
|
If s=0 Then
|
|
Begin
|
|
z1.Init(0, 0);
|
|
z2 := z1
|
|
End
|
|
Else
|
|
Begin
|
|
z1.Init(s, 0);
|
|
z2.Init(q/s, 0)
|
|
End
|
|
End
|
|
End {rooqua};
|
|
|
|
Procedure roo001(uplo, trans, diag: char; n: ArbInt; Var ap1, x1: ArbFloat;
|
|
incx: ArbInt);
|
|
|
|
Var
|
|
ap : arfloat1 absolute ap1;
|
|
x : arfloat1 absolute x1;
|
|
temp : ArbFloat;
|
|
i, info, ix, j, jx, k, kk, kx: ArbInt;
|
|
nounit: boolean;
|
|
Begin
|
|
info := 0;
|
|
uplo := upcase(uplo);
|
|
trans := upcase(trans);
|
|
diag := upcase(diag);
|
|
If n=0 Then exit;
|
|
nounit := diag='N';
|
|
If incx<=0 Then kx := 1-(n-1)*incx
|
|
Else kx := 1;
|
|
If trans='N' Then
|
|
Begin
|
|
If uplo='U' Then
|
|
Begin
|
|
kk := 1;
|
|
jx := kx;
|
|
For j:=1 To n Do
|
|
Begin
|
|
If x[jx]<>0 Then
|
|
Begin
|
|
temp := x[jx];
|
|
ix := kx;
|
|
For k:=kk To kk+j-2 Do
|
|
Begin
|
|
x[ix] := x[ix]+temp*ap[k];
|
|
inc(ix, incx)
|
|
End;
|
|
If nounit Then x[jx] := x[jx]*ap[kk+j-1]
|
|
End;
|
|
inc(jx, incx);
|
|
inc(kk, j)
|
|
End
|
|
End
|
|
Else
|
|
Begin
|
|
kk := n*(n+1) Div 2;
|
|
inc(kx, (n-1)*incx);
|
|
jx := kx;
|
|
For j:=n Downto 1 Do
|
|
Begin
|
|
If x[jx]<>0 Then
|
|
Begin
|
|
temp := x[jx];
|
|
ix := kx;
|
|
For k:=kk Downto kk-(n-(j+1)) Do
|
|
Begin
|
|
x[ix] := x[ix]+temp*ap[k];
|
|
dec(ix, incx)
|
|
End;
|
|
If nounit Then x[jx] := x[jx]*ap[kk-n+j]
|
|
End;
|
|
dec(jx, incx);
|
|
dec(kk, n-j+1)
|
|
End
|
|
End
|
|
End
|
|
Else
|
|
Begin
|
|
If uplo='U' Then
|
|
Begin
|
|
kk := n*(n+1) Div 2;
|
|
jx := kx+(n-1)*incx;
|
|
For j:= n Downto 1 Do
|
|
Begin
|
|
temp := x[jx];
|
|
ix := jx;
|
|
If nounit Then temp := temp*ap[kk];
|
|
For k:= kk-1 Downto kk-j+1 Do
|
|
Begin
|
|
dec(ix, incx);
|
|
temp := temp+ap[k]*x[ix]
|
|
End;
|
|
x[jx] := temp;
|
|
dec(jx, incx);
|
|
dec(kk, j)
|
|
End
|
|
End
|
|
Else
|
|
Begin
|
|
kk := 1;
|
|
jx := kx;
|
|
For j:=1 To n Do
|
|
Begin
|
|
temp := x[jx];
|
|
ix := jx;
|
|
If nounit Then temp := temp*ap[kk];
|
|
For k:=kk+1 To kk+n-j Do
|
|
Begin
|
|
inc(ix, incx);
|
|
temp := temp+ap[k]*x[ix]
|
|
End;
|
|
x[jx] := temp;
|
|
inc(jx, incx);
|
|
inc(kk, n-j+1)
|
|
End
|
|
End
|
|
End
|
|
End;
|
|
|
|
Procedure roo002(uplo, trans, diag: char; n: ArbInt;
|
|
Var ap1, x1: ArbFloat; incx: ArbInt );
|
|
|
|
Var ap : arfloat1 absolute ap1;
|
|
x : arfloat1 absolute x1;
|
|
temp : ArbFloat;
|
|
i, info, ix, j, jx, k, kk, kx: ArbInt;
|
|
nounit: boolean;
|
|
Begin
|
|
info := 0;
|
|
uplo := upcase(uplo);
|
|
trans := upcase(trans);
|
|
diag := upcase(diag);
|
|
If n=0 Then exit;
|
|
nounit := diag='N';
|
|
If incx<=0 Then kx := 1-(n-1)*incx
|
|
Else kx := 1;
|
|
If trans='N' Then
|
|
Begin
|
|
If uplo='U' Then
|
|
Begin
|
|
kk := n*(n+1) Div 2;
|
|
jx := kx+(n-1)*incx;
|
|
For j:=n Downto 1 Do
|
|
Begin
|
|
If x[jx]<>0 Then
|
|
Begin
|
|
If nounit Then x[jx] := x[jx]/ap[kk];
|
|
temp := x[jx];
|
|
ix := jx;
|
|
For k:=kk-1 Downto kk-j+1 Do
|
|
Begin
|
|
dec(ix, incx);
|
|
x[ix] := x[ix]-temp*ap[k];
|
|
End
|
|
End;
|
|
dec(jx, incx);
|
|
dec(kk, j)
|
|
End
|
|
End
|
|
Else
|
|
Begin
|
|
kk := 1;
|
|
jx := kx;
|
|
For j:=1 To n Do
|
|
Begin
|
|
If x[jx]<>0 Then
|
|
Begin
|
|
If nounit Then x[jx] := x[jx]/ap[kk];
|
|
temp := x[jx];
|
|
ix := jx;
|
|
For k:= kk+1 To kk+n-j Do
|
|
Begin
|
|
inc(ix, incx);
|
|
x[ix] := x[ix]-temp*ap[k]
|
|
End;
|
|
End;
|
|
inc(jx, incx);
|
|
inc(kk, n-j+1)
|
|
End
|
|
End
|
|
End
|
|
Else
|
|
Begin
|
|
If uplo='U' Then
|
|
Begin
|
|
kk := 1;
|
|
jx := kx;
|
|
For j:= 1 To n Do
|
|
Begin
|
|
temp := x[jx];
|
|
ix := kx;
|
|
For k:= kk To kk+j-2 Do
|
|
Begin
|
|
temp := temp-ap[k]*x[ix];
|
|
inc(ix, incx);
|
|
End;
|
|
If nounit Then temp := temp/ap[kk+j-1];
|
|
x[jx] := temp;
|
|
inc(jx, incx);
|
|
inc(kk, j)
|
|
End
|
|
End
|
|
Else
|
|
Begin
|
|
kk := n*(n+1) Div 2;
|
|
kx := kx+(n-1)*incx;
|
|
jx := kx;
|
|
For j:=n Downto 1 Do
|
|
Begin
|
|
temp := x[jx];
|
|
ix := kx;
|
|
For k:= kk Downto kk-(n-(j+1)) Do
|
|
Begin
|
|
temp := temp-ap[k]*x[ix];
|
|
dec(ix, incx)
|
|
End;
|
|
If nounit Then temp := temp/ap[kk-n+j];
|
|
x[jx] := temp;
|
|
dec(jx, incx);
|
|
dec(kk, n-j+1)
|
|
End
|
|
End
|
|
End
|
|
End;
|
|
|
|
Procedure roo003( n: ArbInt; Var x1: ArbFloat; incx: ArbInt;
|
|
Var scale, sumsq: ArbFloat );
|
|
|
|
Var absxi : ArbFloat;
|
|
i, ix : ArbInt;
|
|
x : arfloat1 absolute x1;
|
|
Begin
|
|
ix := 1;
|
|
If n>0 Then
|
|
For i:=1 To n Do
|
|
Begin
|
|
If x[ix]<>0 Then
|
|
Begin
|
|
absxi := abs(x[ix]);
|
|
If (scale<absxi) Then
|
|
Begin
|
|
sumsq := 1+sumsq*sqr(scale/absxi);
|
|
scale := absxi
|
|
End
|
|
Else sumsq := sumsq + sqr(absxi/scale)
|
|
End;
|
|
inc(ix, incx)
|
|
End
|
|
End;
|
|
|
|
Function norm2( n: ArbInt; Var x1: ArbFloat; incx: ArbInt): ArbFloat;
|
|
|
|
Var scale, ssq : ArbFloat;
|
|
sqt: ArbFloat;
|
|
Begin
|
|
If n<1 Then norm2 := 0
|
|
Else
|
|
If n=1 Then norm2 := abs(x1)
|
|
Else
|
|
Begin
|
|
scale := 0;
|
|
ssq := 1;
|
|
roo003(n, x1, incx, scale, ssq );
|
|
sqt := sqrt( ssq );
|
|
If scale<(giant/sqt) Then norm2 := scale*sqt
|
|
Else norm2 := giant
|
|
End
|
|
End;
|
|
|
|
Procedure roo004(n: ArbInt; Var r1, diag1, qtb1: ArbFloat;
|
|
delta: ArbFloat; Var x1: ArbFloat);
|
|
|
|
Var
|
|
r : arfloat1 absolute r1;
|
|
diag : arfloat1 absolute diag1;
|
|
qtb : arfloat1 absolute qtb1;
|
|
x : arfloat1 absolute x1;
|
|
wa1, wa2 : ^arfloat1;
|
|
alpha, bnorm, gnorm, qnorm, sgnorm, temp: ArbFloat;
|
|
i, j, jj, l : ArbInt;
|
|
Begin
|
|
getmem(wa1, n*sizeof(ArbFloat));
|
|
getmem(wa2, n*sizeof(ArbFloat));
|
|
jj := 1;
|
|
For j:=1 To n Do
|
|
Begin
|
|
wa1^[j] := r[jj];
|
|
If r[jj]=0 Then
|
|
Begin
|
|
temp := 0;
|
|
l := j;
|
|
For i:=1 To j-1 Do
|
|
Begin
|
|
If abs(r[l])>temp Then temp := abs(r[l]);
|
|
inc(l, n-i)
|
|
End;
|
|
If temp=0 Then r[jj] := macheps
|
|
Else r[jj] := macheps*temp
|
|
End;
|
|
inc(jj, n-j+1)
|
|
End;
|
|
move(qtb, x, n*sizeof(ArbFloat));
|
|
roo002('l','t','n', n, r1, x1, 1);
|
|
jj := 1;
|
|
For j:=1 To n Do
|
|
Begin
|
|
r[jj] := wa1^[j];
|
|
inc(jj, n - j + 1)
|
|
End;
|
|
For j:=1 To n Do
|
|
wa2^[j] := diag[j]*x[j];
|
|
qnorm := norm2(n, wa2^[1], 1);
|
|
If qnorm>delta Then
|
|
Begin
|
|
move(qtb, wa1^, n*sizeof(ArbFloat));
|
|
roo001('l','n','n', n, r1, wa1^[1], 1);
|
|
For i:=1 To n Do
|
|
wa1^[i] := wa1^[i]/diag[i];
|
|
gnorm := norm2(n, wa1^[1], 1);
|
|
sgnorm := 0;
|
|
alpha := delta/qnorm;
|
|
If gnorm<>0 Then
|
|
Begin
|
|
For j:=1 To n Do
|
|
wa1^[j] := (wa1^[j]/gnorm)/diag[j];
|
|
move(wa1^, wa2^, n*sizeof(ArbFloat));
|
|
roo001('l','t','n',n,r1,wa2^[1],1);
|
|
temp := norm2(n, wa2^[1],1);
|
|
sgnorm := (gnorm/temp)/temp;
|
|
alpha := 0;
|
|
If sgnorm<delta Then
|
|
Begin
|
|
bnorm := norm2(n, qtb1, 1);
|
|
temp := (bnorm/gnorm)*(bnorm/qnorm)*(sgnorm/delta);
|
|
temp := temp-(delta/qnorm)*sqr(sgnorm/delta) +
|
|
sqrt(sqr(temp-delta/qnorm) +
|
|
(1-sqr(delta/qnorm))*(1-sqr(sgnorm/delta)));
|
|
alpha := ((delta/qnorm)*(1-sqr(sgnorm/delta)))/temp
|
|
End
|
|
End;
|
|
If sgnorm<delta Then temp := (1-alpha)*sgnorm
|
|
Else temp := (1-alpha)*delta;
|
|
For j:=1 To n Do
|
|
x[j] := temp*wa1^[j] + alpha*x[j]
|
|
End;
|
|
freemem(wa2, n*sizeof(ArbFloat));
|
|
freemem(wa1, n*sizeof(ArbFloat));
|
|
End;
|
|
|
|
Procedure roo005(fcn: roofnrfunc; n: ArbInt; Var x1, fvec1, fjac1: ArbFloat;
|
|
ldfjac: ArbInt; Var iflag: ArbInt; ml, mu: ArbInt;
|
|
epsfcn: ArbFloat; Var wa1, wa2: arfloat1);
|
|
|
|
Var eps, h, temp: ArbFloat;
|
|
i, j, k, msum: ArbInt;
|
|
x : arfloat1 absolute x1;
|
|
fvec : arfloat1 absolute fvec1;
|
|
fjac : arfloat1 absolute fjac1;
|
|
deff : boolean;
|
|
Begin
|
|
If epsfcn>macheps Then eps := sqrt(epsfcn)
|
|
Else eps := sqrt(macheps);
|
|
msum := ml+mu+1;
|
|
If msum>=n Then
|
|
Begin
|
|
For j:=1 To n Do
|
|
Begin
|
|
temp := x[j];
|
|
h := eps*abs(temp);
|
|
If h=0 Then h := eps;
|
|
x[j] := temp+h;
|
|
deff := true;
|
|
fcn(x1, wa1[1], deff);
|
|
If Not deff Then iflag := -1;
|
|
If iflag<0 Then exit;
|
|
x[j] := temp;
|
|
For i:= 1 To n Do
|
|
fjac[j+(i-1)*ldfjac] := (wa1[i]-fvec[i])/h
|
|
End
|
|
End
|
|
Else
|
|
Begin
|
|
For k:=1 To msum Do
|
|
Begin
|
|
j := k;
|
|
while j <= n Do
|
|
Begin
|
|
wa2[j] := x[j];
|
|
h := eps*abs(wa2[j]);
|
|
If h=0 Then h := eps;
|
|
x[j] := wa2[j]+h;
|
|
inc(j, msum)
|
|
End;
|
|
deff := true;
|
|
fcn(x1, wa1[1], deff);
|
|
If Not deff Then iflag := -1;
|
|
If iflag<0 Then exit;
|
|
j := k;
|
|
while j<= n Do
|
|
Begin
|
|
x[j] := wa2[j];
|
|
h := eps*abs(wa2[j]);
|
|
If h=0 Then h := eps;
|
|
For i:=1 To n Do
|
|
Begin
|
|
fjac[j+(i-1)*ldfjac] := 0;
|
|
If (i>=(j-mu)) And (i<=(j+ml))
|
|
Then fjac[j+(i-1)*ldfjac] := (wa1[i]-fvec[i])/h
|
|
End;
|
|
inc(j, msum)
|
|
End
|
|
End
|
|
End
|
|
End;
|
|
|
|
Procedure roo006(trans: char; m, n: ArbInt; alpha: ArbFloat; Var a1: ArbFloat;
|
|
lda: ArbInt; Var x1: ArbFloat; incx : ArbInt; beta: ArbFloat;
|
|
Var y1: ArbFloat; incy : ArbInt);
|
|
|
|
Var temp : ArbFloat;
|
|
i, info, ix, iy, j, jx, jy, kx, ky, lenx, leny: ArbInt;
|
|
x : arfloat1 absolute x1;
|
|
y : arfloat1 absolute y1;
|
|
a : arfloat1 absolute a1;
|
|
Begin
|
|
info := 0;
|
|
trans := upcase(trans);
|
|
If (m=0) Or (n=0) Or ((alpha=0) And (beta=1)) Then exit;
|
|
If trans='N' Then
|
|
Begin
|
|
lenx := n;
|
|
leny := m
|
|
End
|
|
Else
|
|
Begin
|
|
lenx := m;
|
|
leny := n
|
|
End;
|
|
If incx>0 Then kx := 1
|
|
Else kx := 1-(lenx-1)*incx;
|
|
If incy>0 Then ky := 1
|
|
Else ky := 1-(leny-1)*incy;
|
|
If (beta<>1) Then
|
|
Begin
|
|
iy := ky;
|
|
If beta=0 Then
|
|
For i:=1 To leny Do
|
|
Begin
|
|
y[iy] := 0;
|
|
inc(iy, incy)
|
|
End
|
|
Else
|
|
For i:=1 To leny Do
|
|
Begin
|
|
y[iy] := beta*y[iy];
|
|
inc(iy, incy)
|
|
End;
|
|
End;
|
|
If alpha=0 Then exit;
|
|
If trans='N' Then
|
|
Begin
|
|
jx := kx;
|
|
For j:=1 To n Do
|
|
Begin
|
|
If x[jx]<>0 Then
|
|
Begin
|
|
temp := alpha*x[jx];
|
|
iy := ky;
|
|
For i:=1 To m Do
|
|
Begin
|
|
y[iy] := y[iy]+temp*a[j+(i-1)*lda];
|
|
inc(iy, incy)
|
|
End
|
|
End;
|
|
inc(jx, incx)
|
|
End
|
|
End
|
|
Else
|
|
Begin
|
|
jy := ky;
|
|
For j:=1 To n Do
|
|
Begin
|
|
temp := 0;
|
|
ix := kx;
|
|
For i:=1 To m Do
|
|
Begin
|
|
temp := temp+a[j+(i-1)*lda]*x[ix];
|
|
inc(ix, incx)
|
|
End;
|
|
y[jy] := y[jy]+alpha*temp;
|
|
inc(jy, incy)
|
|
End
|
|
End
|
|
End;
|
|
|
|
Procedure roo007(m, n: ArbInt; alpha: ArbFloat; Var x1: ArbFloat; incx: ArbInt;
|
|
Var y1: ArbFloat; incy: ArbInt; Var a1: ArbFloat; lda: ArbInt);
|
|
|
|
Var temp: ArbFloat;
|
|
i, info, ix, j, jy, kx: ArbInt;
|
|
x : arfloat1 absolute x1;
|
|
y : arfloat1 absolute y1;
|
|
a : arfloat1 absolute a1;
|
|
Begin
|
|
info := 0;
|
|
If (m=0) Or (n=0) Or (alpha=0) Then exit;
|
|
If incy>0 Then jy := 1
|
|
Else jy := 1-(n-1)*incy;
|
|
If incx>0 Then kx := 1
|
|
Else kx := 1-(m-1)*incx;
|
|
For j:=1 To n Do
|
|
Begin
|
|
If y[jy]<>0 Then
|
|
Begin
|
|
temp := alpha*y[jy];
|
|
ix := kx;
|
|
For i:=1 To m Do
|
|
Begin
|
|
a[j +(i-1)*lda] := a[j + (i-1)*lda] + x[ix]*temp;
|
|
inc(ix, incx)
|
|
End
|
|
End;
|
|
inc(jy, incy)
|
|
End
|
|
End;
|
|
|
|
Procedure roo008(n: ArbInt; Var q1: ArbFloat; ldq: ArbInt; Var wa: arfloat1);
|
|
|
|
Var q: arfloat1 absolute q1;
|
|
i, j, k: ArbInt;
|
|
Begin
|
|
For j:=2 To n Do
|
|
For i:=1 To j-1 Do
|
|
q[j+(i-1)*ldq] := 0;
|
|
For k:=n Downto 1 Do
|
|
Begin
|
|
If (q[k+(k-1)*ldq]<>0) And (k<>n) Then
|
|
Begin
|
|
roo006('t', n-k+1, n-k, 1, q[k+1+(k-1)*ldq], ldq,
|
|
q[k +(k-1)*ldq], ldq, 0, wa[k+1], 1);
|
|
roo007(n-k+1, n-k, -1/q[k+(k-1)*ldq], q[k+(k-1)*ldq], ldq,
|
|
wa[k+1], 1, q[k+1+(k-1)*ldq], ldq)
|
|
End;
|
|
For i:=k + 1 To n Do
|
|
q[k+(i-1)*ldq] := -q[k+(i-1)*ldq];
|
|
q[k+(k-1)*ldq] := 1-q[k+(k-1)*ldq]
|
|
End;
|
|
End;
|
|
|
|
Procedure roo009(n: ArbInt; Var a1: ArbFloat; lda: ArbInt;
|
|
Var rdiag1, acnorm1: ArbFloat);
|
|
|
|
Var a : arfloat1 absolute a1;
|
|
rdiag : arfloat1 absolute rdiag1;
|
|
acnorm : arfloat1 absolute acnorm1;
|
|
ajnorm : ArbFloat;
|
|
i, j : ArbInt;
|
|
Begin
|
|
For j:=1 To n Do
|
|
acnorm[j] := norm2(n, a[j], lda);
|
|
For j:=1 To n Do
|
|
Begin
|
|
ajnorm := norm2(n-j+1, a[j+(j-1)*lda], lda);
|
|
If ajnorm<>0 Then
|
|
Begin
|
|
If a[j+(j-1)*lda]<0 Then ajnorm := -ajnorm;
|
|
For i:=j To n Do
|
|
a[j+(i-1)*lda] := a[j+(i-1)*lda]/ajnorm;
|
|
a[j+(j-1)*lda] := a[j+(j-1)*lda]+1;
|
|
If j<>n Then
|
|
Begin
|
|
roo006('t', n-j+1, n-j, 1, a[j+1+(j-1)*lda], lda,
|
|
a[j+(j-1)*lda], lda, 0, rdiag[j+1], 1);
|
|
roo007(n-j+1, n-j, -1/a[j+(j-1)*lda], a[j+(j-1)*lda], lda,
|
|
rdiag[j+1], 1, a[j+1+(j-1)*lda], lda)
|
|
End
|
|
End;
|
|
rdiag[j] := -ajnorm
|
|
End
|
|
End;
|
|
|
|
Procedure roo010(n: ArbInt; Var x1: ArbFloat; incx: ArbInt;
|
|
Var y1: ArbFloat; incy: ArbInt; c, s:ArbFloat );
|
|
|
|
Var temp1: ArbFloat;
|
|
x : arfloat1 absolute x1;
|
|
y : arfloat1 absolute y1;
|
|
i, ix, iy: ArbInt;
|
|
Begin
|
|
If incy>=0 Then iy := 1
|
|
Else iy := 1-(n-1)*incy;
|
|
If incx>=0 Then ix := 1
|
|
Else ix := 1-(n-1)*incx;
|
|
For i:=1 To n Do
|
|
Begin
|
|
temp1 := x[ix];
|
|
x[ix] := s*y[iy]+c*temp1;
|
|
y[iy] := c*y[iy]-s*temp1;
|
|
inc(ix, incx);
|
|
inc(iy, incy)
|
|
End
|
|
End;
|
|
|
|
Procedure roo011(m, n: ArbInt; Var a1: ArbFloat; lda: ArbInt; Var v1, w1: ArbFloat);
|
|
|
|
Var a: arfloat1 absolute a1;
|
|
v: arfloat1 absolute v1;
|
|
w: arfloat1 absolute w1;
|
|
sine, cosine: ArbFloat;
|
|
j, nm1, nmj: ArbInt;
|
|
Begin
|
|
nm1 := n-1;
|
|
For nmj:=1 To nm1 Do
|
|
Begin
|
|
j := n-nmj;
|
|
If (abs(v[j])>1) Then
|
|
Begin
|
|
cosine := 1/v[j];
|
|
sine := sqrt(1-sqr(cosine))
|
|
End
|
|
Else
|
|
Begin
|
|
sine := v[j];
|
|
cosine := sqrt(1-sqr(sine))
|
|
End;
|
|
roo010(m, a[n], lda, a[j], lda, cosine, sine)
|
|
End;
|
|
For j:=1 To nm1 Do
|
|
Begin
|
|
If (abs(w[j])>1) Then
|
|
Begin
|
|
cosine := 1/w[j];
|
|
sine := sqrt(1-sqr(cosine))
|
|
End
|
|
Else
|
|
Begin
|
|
sine := w[j];
|
|
cosine := sqrt(1-sqr(sine))
|
|
End;
|
|
roo010(m, a[j], lda, a[n], lda, cosine, sine)
|
|
End
|
|
End;
|
|
|
|
Procedure roo012(m, n: ArbInt; Var s1: ArbFloat; ls: ArbInt;
|
|
Var u1, v1, w1: ArbFloat; Var sing: boolean);
|
|
|
|
Const one = 1.0;
|
|
p5 = 0.5;
|
|
p25 = 0.25;
|
|
zero = 0.0;
|
|
|
|
Var cosine, cotan, sine, tangnt, tau: ArbFloat;
|
|
i, j, jj, l, nm1, nmj: ArbInt;
|
|
s : arfloat1 absolute s1;
|
|
u : arfloat1 absolute u1;
|
|
v : arfloat1 absolute v1;
|
|
w : arfloat1 absolute w1;
|
|
Begin
|
|
jj := (n*(2*m-n+1)) Div 2 - (m-n);
|
|
If m>=n Then move(s[jj], w[n], (m-n+1)*sizeof(ArbFloat));
|
|
nm1 := n-1;
|
|
For nmj:=1 To nm1 Do
|
|
Begin
|
|
j := n-nmj;
|
|
jj := jj-(m-j+1);
|
|
w[j] := zero;
|
|
If (v[j]<>zero) Then
|
|
Begin
|
|
If (abs(v[n])<abs(v[j])) Then
|
|
Begin
|
|
cotan := v[n]/v[j];
|
|
sine := p5/sqrt(p25+p25*sqr(cotan));
|
|
cosine := sine*cotan;
|
|
If (abs(cosine)*giant)>one
|
|
Then tau := one/cosine
|
|
Else tau := one
|
|
End
|
|
Else
|
|
Begin
|
|
tangnt := v[j]/v[n];
|
|
cosine := p5/sqrt(p25+p25*sqr(tangnt));
|
|
sine := cosine*tangnt;
|
|
tau := sine;
|
|
End;
|
|
v[n] := sine*v[j]+cosine*v[n];
|
|
v[j] := tau;
|
|
roo010(m-j+1, w[j], 1, s[jj], 1, cosine, sine)
|
|
End
|
|
End;
|
|
For i:=1 To m Do
|
|
w[i] := w[i]+v[n]*u[i];
|
|
sing := false;
|
|
For j:=1 To nm1 Do
|
|
Begin
|
|
If w[j]<>zero Then
|
|
Begin
|
|
If abs(s[jj])<abs(w[j]) Then
|
|
Begin
|
|
cotan := s[jj]/w[j];
|
|
sine := p5/sqrt(p25+p25*sqr(cotan));
|
|
cosine := sine*cotan;
|
|
If (abs(cosine)*giant)>one Then tau := one/cosine
|
|
Else tau := one
|
|
End
|
|
Else
|
|
Begin
|
|
tangnt := w[j]/s[jj];
|
|
cosine := p5/sqrt(p25+p25*sqr(tangnt));
|
|
sine := cosine*tangnt;
|
|
tau := sine
|
|
End;
|
|
roo010(m-j+1, s[jj], 1, w[j], 1, cosine, sine);
|
|
w[j] := tau
|
|
End;
|
|
If (s[jj]=zero) Then sing := true;
|
|
inc(jj, m-j+1)
|
|
End;
|
|
If m>=n Then move(w[n], s[jj], (m-n+1)*sizeof(ArbFloat));
|
|
If s[jj]=zero Then sing := true
|
|
End;
|
|
|
|
Procedure roo013(fcn: roofnrfunc; n: ArbInt; Var x1, fvec1: ArbFloat;
|
|
xtol: ArbFloat; maxfev, ml, mu: ArbInt; epsfcn: ArbFloat;
|
|
Var diag1: ArbFloat; factor: ArbFloat; Var info: ArbInt;
|
|
Var fjac1: ArbFloat; ldfjac: ArbInt;
|
|
Var r1: ArbFloat; lr: ArbInt; Var qtf1: ArbFloat);
|
|
|
|
Const p1 = 0.1;
|
|
p5 = 0.5;
|
|
p001 = 0.001;
|
|
p0001 = 0.0001;
|
|
|
|
Var diag : arfloat1 absolute diag1;
|
|
fjac : arfloat1 absolute fjac1;
|
|
fvec : arfloat1 absolute fvec1;
|
|
qtf : arfloat1 absolute qtf1;
|
|
r : arfloat1 absolute r1;
|
|
wa1, wa2, wa3, wa4: ^arfloat1;
|
|
x : arfloat1 absolute x1;
|
|
actred, delta, fnorm, fnorm1, pnorm,
|
|
prered, ratio, sum, temp, xnorm : ArbFloat;
|
|
i, iflag, iter, j, jm1, l, msum, ncfail, ncsuc, nfev,
|
|
nslow1, nslow2, ns : ArbInt;
|
|
jeval, sing, deff: boolean;
|
|
Begin
|
|
info := 1;
|
|
iflag := 0;
|
|
nfev := 0;
|
|
ns := n*sizeof(ArbFloat);
|
|
For j:=1 To n Do
|
|
If diag[j]<=0 Then exit;
|
|
iflag := 1;
|
|
deff := true;
|
|
fcn(x1, fvec1, deff);
|
|
If Not deff Then iflag := -1;
|
|
nfev := 1;
|
|
If iflag<0 Then
|
|
Begin
|
|
info := iflag;
|
|
exit
|
|
End;
|
|
fnorm := norm2(n, fvec1, 1);
|
|
msum := ml+mu+1;
|
|
If msum>n Then msum := n;
|
|
getmem(wa1, ns);
|
|
getmem(wa2, ns);
|
|
getmem(wa3, ns);
|
|
getmem(wa4, ns);
|
|
iter := 1;
|
|
ncsuc := 0;
|
|
ncfail := 0;
|
|
nslow1 := 0;
|
|
nslow2 := 0;
|
|
while (info=1) and (iflag>=0) Do
|
|
Begin
|
|
jeval := true;
|
|
iflag := 2;
|
|
roo005(fcn, n, x1, fvec1, fjac1, ldfjac, iflag, ml, mu, epsfcn,
|
|
wa1^, wa2^);
|
|
inc(nfev, msum);
|
|
If iflag>=0 Then
|
|
Begin
|
|
roo009(n, fjac1, ldfjac, wa1^[1], wa2^[1]);
|
|
If iter=1 Then
|
|
Begin
|
|
For j:=1 To n Do
|
|
wa3^[j] := diag[j]*x[j];
|
|
xnorm := norm2(n, wa3^[1], 1);
|
|
delta := factor*xnorm;
|
|
If delta=0 Then delta := factor;
|
|
End;
|
|
For i:=1 To n Do
|
|
qtf[i] := fvec[i];
|
|
For j:=1 To n Do
|
|
If fjac[j+(j-1)*ldfjac]<>0 Then
|
|
Begin
|
|
sum := 0;
|
|
For i:=j To n Do
|
|
sum := sum+fjac[j+(i-1)*ldfjac]*qtf[i];
|
|
temp := -sum/fjac[j+(j-1)*ldfjac];
|
|
For i:=j To n Do
|
|
qtf[i] := qtf[i]+fjac[j+(i-1)*ldfjac]*temp
|
|
End;
|
|
sing := false;
|
|
For j:=1 To n Do
|
|
Begin
|
|
l := j;
|
|
jm1 := j-1;
|
|
For i:=1 To jm1 Do
|
|
Begin
|
|
r[l] := fjac[j+(i-1)*ldfjac];
|
|
inc(l, n-i)
|
|
End;
|
|
r[l] := wa1^[j];
|
|
If wa1^[j]=0 Then sing := true
|
|
End;
|
|
roo008(n, fjac1, ldfjac, wa1^);
|
|
Repeat
|
|
roo004(n, r1, diag1, qtf1, delta, wa1^[1]);
|
|
For j:=1 To n Do
|
|
Begin
|
|
wa1^[j] := -wa1^[j];
|
|
wa2^[j] := x[j]+wa1^[j];
|
|
wa3^[j] := diag[j]*wa1^[j]
|
|
End;
|
|
pnorm := norm2(n, wa3^[1], 1);
|
|
If iter=1 Then If pnorm<delta Then delta := pnorm;
|
|
iflag := 1;
|
|
deff := true;
|
|
fcn(wa2^[1], wa4^[1], deff);
|
|
If Not deff Then iflag := -1;
|
|
inc(nfev);
|
|
If iflag>0 Then
|
|
Begin
|
|
fnorm1 := norm2(n, wa4^[1], 1);
|
|
If fnorm1<fnorm Then actred := 1-sqr(fnorm1/fnorm)
|
|
Else actred := -1;
|
|
move(wa1^, wa3^, n*sizeof(ArbFloat));
|
|
roo001('l','t','n', n, r1, wa3^[1], 1);
|
|
For i:=1 To n Do
|
|
wa3^[i] := wa3^[i] + qtf[i];
|
|
temp := norm2(n, wa3^[1], 1);
|
|
If temp<fnorm
|
|
Then prered := 1 - sqr(temp/fnorm)
|
|
Else prered := 1;
|
|
If prered>0 Then ratio := actred/prered
|
|
Else ratio := 0;
|
|
If ratio<p1 Then
|
|
Begin
|
|
ncsuc := 0;
|
|
inc(ncfail);
|
|
delta := p5*delta
|
|
End
|
|
Else
|
|
Begin
|
|
ncfail := 0;
|
|
inc(ncsuc);
|
|
If (ratio>=p5) Or (ncsuc>1)
|
|
Then If delta<pnorm/p5 Then delta := pnorm/p5;
|
|
If abs(ratio-1)<=p1 Then delta := pnorm/p5
|
|
End;
|
|
If ratio>=p0001 Then
|
|
Begin
|
|
For j:=1 To n Do
|
|
Begin
|
|
x[j] := wa2^[j];
|
|
wa2^[j] := diag[j]*x[j];
|
|
fvec[j] := wa4^[j]
|
|
End;
|
|
xnorm := norm2(n, wa2^[1], 1);
|
|
fnorm := fnorm1;
|
|
inc(iter)
|
|
End;
|
|
inc(nslow1);
|
|
If actred>=p001 Then nslow1 := 0;
|
|
If jeval Then inc(nslow2);
|
|
If actred>=p1 Then nslow2 := 0;
|
|
If (delta<=xtol*xnorm) Or
|
|
(fnorm=0) Or (pnorm=0) Then info := 0
|
|
Else If nfev>=maxfev Then info := 2
|
|
Else If delta<=macheps*xnorm Then info := 3
|
|
Else If nslow2=5 Then info := 4
|
|
Else If nslow1=10 Then info := 5;
|
|
If (info=1) And (ncfail<>2) Then
|
|
Begin
|
|
roo006('t', n, n, 1, fjac1, ldfjac, wa4^[1], 1, 0,
|
|
wa2^[1], 1);
|
|
If ratio>=p0001 Then move(wa2^, qtf, ns);
|
|
For j:=1 To n Do
|
|
Begin
|
|
wa2^[j] := (wa2^[j]-wa3^[j])/pnorm;
|
|
wa1^[j] := diag[j]*((diag[j]*wa1^[j])/pnorm)
|
|
End;
|
|
roo012(n, n, r1, lr, wa1^[1], wa2^[1], wa3^[1], sing);
|
|
roo011(n, n, fjac1, ldfjac, wa2^[1], wa3^[1]);
|
|
roo011(1, n, qtf1, 1, wa2^[1], wa3^[1]);
|
|
jeval := false
|
|
End
|
|
End
|
|
Until (iflag<0) Or (ncfail=2) Or (info<>1)
|
|
End
|
|
End;
|
|
freemem(wa4, ns);
|
|
freemem(wa3, ns);
|
|
freemem(wa2, ns);
|
|
freemem(wa1, ns);
|
|
If iflag<0 Then info := iflag;
|
|
End;
|
|
|
|
Procedure roofnr(f: roofnrfunc; n: ArbInt; Var x, residu: ArbFloat; re: ArbFloat;
|
|
Var term: ArbInt);
|
|
|
|
Var j, lr, ns : ArbInt;
|
|
wa1, wa2, wa3, wa4, fx : ^arfloat1;
|
|
Begin
|
|
ns := n*sizeof(ArbFloat);
|
|
If n<=0 Then term := 3
|
|
Else
|
|
Begin
|
|
If re<0 Then term := 3
|
|
Else
|
|
Begin
|
|
lr := (n*(n+1)) Div 2;
|
|
getmem(wa1, ns);
|
|
getmem(wa2, ns);
|
|
getmem(wa3, lr*sizeof(ArbFloat));
|
|
getmem(wa4, n*ns);
|
|
getmem(fx, ns);
|
|
For j:=1 To n Do
|
|
wa1^[j] := 1;
|
|
roo013(f, n, x, fx^[1], re, 200*(n+1), n-1, n-1, 0, wa1^[1],
|
|
100.0, term, wa4^[1], n, wa3^[1], lr, wa2^[1]);
|
|
residu := Norm2(n, fx^[1], 1);
|
|
freemem(fx, ns);
|
|
freemem(wa4, n*ns);
|
|
freemem(wa3, lr*sizeof(ArbFloat));
|
|
freemem(wa2, ns);
|
|
freemem(wa1, ns);
|
|
If term<0 Then term := 6
|
|
Else
|
|
Case term Of
|
|
0: term := 1;
|
|
2: term := 4;
|
|
3: term := 2;
|
|
4, 5: term := 5;
|
|
End
|
|
End
|
|
End
|
|
End;
|
|
End.
|
|
{
|
|
$Log$
|
|
Revision 1.1 2000-07-13 06:34:15 michael
|
|
+ Initial import
|
|
|
|
Revision 1.2 2000/01/25 20:21:42 marco
|
|
* small updates, crlf fix, and RTE 207 problem
|
|
|
|
Revision 1.1 2000/01/24 22:08:58 marco
|
|
* initial version
|
|
|
|
|
|
}
|