home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of Shareware - Software Farm 2
/
wosw_2.zip
/
wosw_2
/
PASCAL
/
NRPAS13.ZIP
/
DBRENT.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1991-04-29
|
3KB
|
112 lines
FUNCTION dbrent(ax,bx,cx,tol: real; VAR xmin: real): real;
(* Programs using routine DBRENT must define the external
functions func(x:real):real and dfunc(x:real):real which are,
respectively, the function whose minimum is to be found,
and its derivative. *)
LABEL 1,2,3;
CONST
itmax=100;
zeps=1.0e-10;
VAR
a,b,d,d1,d2: real;
du,dv,dw,dx: real;
e,fu,fv,fw,fx: real;
iter: integer;
olde,tol1,tol2: real;
u,u1,u2,v,w,x,xm: real;
ok1,ok2: boolean;
FUNCTION sign(a,b: real): real;
BEGIN
IF (b > 0.0) THEN sign := abs(a) ELSE sign := -abs(a)
END;
BEGIN
IF ax < cx THEN a := ax ELSE a := cx;
IF ax > cx THEN b := ax ELSE b := cx;
v := bx;
w := v;
x := v;
e := 0.0;
fx := func(x);
fv := fx;
fw := fx;
dx := dfunc(x);
dv := dx;
dw := dx;
FOR iter := 1 TO itmax DO BEGIN
xm := 0.5*(a+b);
tol1 := tol*abs(x)+zeps;
tol2 := 2.0*tol1;
IF (abs(x-xm) <= (tol2-0.5*(b-a))) THEN GOTO 3;
IF (abs(e) > tol1) THEN BEGIN
d1 := 2.0*(b-a);
d2 := d1;
IF (dw <> dx) THEN d1 := (w-x)*dx/(dx-dw);
IF (dv <> dx) THEN d2 := (v-x)*dx/(dx-dv);
u1 := x+d1;
u2 := x+d2;
ok1 := ((a-u1)*(u1-b) > 0.0) AND (dx*d1 <= 0.0);
ok2 := ((a-u2)*(u2-b) > 0.0) AND (dx*d2 <= 0.0);
olde := e;
e := d;
IF (NOT (ok1 OR ok2)) THEN GOTO 1
ELSE IF (ok1 AND ok2) THEN BEGIN
IF (abs(d1) < abs(d2)) THEN BEGIN
d := d1
END ELSE BEGIN
d := d2
END
END ELSE IF (ok1) THEN BEGIN
d := d1
END ELSE BEGIN
d := d2
END;
IF (abs(d) > abs(0.5*olde)) THEN GOTO 1;
u := x+d;
IF (((u-a) < tol2) OR ((b-u) < tol2)) THEN BEGIN
d := sign(tol1,xm-x)
END;
GOTO 2
END;
1: IF (dx >= 0.0) THEN e := a-x ELSE e := b-x;
d := 0.5*e;
2: IF (abs(d) >= tol1) THEN BEGIN
u := x+d;
fu := func(u)
END ELSE BEGIN
u := x+sign(tol1,d);
fu := func(u);
IF (fu > fx) THEN GOTO 3
END;
du := dfunc(u);
IF (fu <= fx) THEN BEGIN
IF (u >= x) THEN a := x ELSE b := x;
v := w;
fv := fw;
dv := dw;
w := x;
fw := fx;
dw := dx;
x := u;
fx := fu;
dx := du
END ELSE BEGIN
IF (u < x) THEN a := u ELSE b := u;
IF ((fu <= fw) OR (w = x)) THEN BEGIN
v := w;
fv := fw;
dv := dw;
w := u;
fw := fu;
dw := du
END ELSE IF ((fu < fv) OR (v = x) OR (v = w)) THEN BEGIN
v := u;
fv := fu;
dv := du
END
END
END;
writeln('pause in routine DBRENT - too many iterations');
3: xmin := x;
dbrent := fx
END;