vif-math.f
1 ! @section Synopsis
2 !
3 ! Auxiliary math functions for VIF.
4 !
5 ! @author J. Marcel van der Veer
6 !
7 ! @section copyright
8 !
9 ! This file is part of VIF - vintage fortran compiler.
10 ! Copyright 2020-2025 J. Marcel van der Veer <algol68g@xs4all.nl>.
11 !
12 ! @section license
13 !
14 ! This program is free software; you can redistribute it and/or modify it
15 ! under the terms of the gnu general public license as published by the
16 ! free software foundation; either version 3 of the license, or
17 ! (at your option) any later version.
18 !
19 ! This program is distributed in the hope that it will be useful, but
20 ! without any warranty; without even the implied warranty of merchantability
21 ! or fitness for a particular purpose. See the GNU general public license for
22 ! more details. You should have received a copy of the GNU general public
23 ! license along with this program. If not, see <http://www.gnu.org/licenses/>.
24 !
25
26 subroutine rand48(ix,iy,yfl)
27 !
28 ! Generates random numbers between 0 and 1 (SUN version).
29 !
30 ! ix - initial seed
31 ! iy - new seed value
32 ! yfl - random number double precision
33 !
34 ! Adapted from CASCADE: netlib.org/ieeecs/cascade
35 ! The CASCADE library is in the public domain.
36 !
37 double precision yfl, drand48
38 integer ix, iy, iseed
39 logical first
40 data first /.true./
41 save first, iseed
42 !
43 ! if this is the first call, initialize topmost 32 bits of the seed
44 !
45 if (first .or. iseed .ne. ix) then
46 call srand48 (ix)
47 first = .false.
48 end if
49 !
50 ! Use SUN-supplied function drand48
51 !
52 iy = ix
53 iseed = ix
54 yfl = drand48()
55 !
56 return
57 end
58
59 subroutine gauss(ix,x)
60 ! The routine gauss generates a random number from a gaussian
61 ! distribution, with a mean of zero and a standard deviation of one.
62 !
63 ! VAX/VMS version
64 !
65 ! Variables:
66 !
67 ! ix - initial seed integer; gauss updates it with a new seed value
68 !
69 ! x - the output gaussian variable
70 !
71 ! Adapted from CASCADE: netlib.org/ieeecs/cascade
72 ! The CASCADE library is in the public domain.
73 !
74 double precision x, y, sum
75 sum=0.0
76 do 10 i=1,5
77 call rand48(ix,iy,y)
78 ix = iy
79 sum=sum+y
80 10 continue
81 x=6.0d0*(sum/5.0d0)-3.0d0
82 return
83 end
84
85 real*8 function zero in (ax, bx, f, tol, ierr)
86 implicit real*8 (a - h, o - z)
87 !
88 ! Compute a zero of the function f(x) in the interval [ax, bx].
89 !
90 ! It is assumed that f(ax) and f(bx) have opposite signs.
91 ! Zeroin returns a zero in the given interval ax, bx to within a
92 ! tolerance 4 * macheps * abs(x) + tol, where macheps
93 ! is the relative machine precision.
94 !
95 ! Adapted from zeroin.f from netlib.org/fmm.
96 ! That function is a slightly modified translation of the ALGOL 60
97 ! procedure zero given in
98 !
99 ! Richard Brent, Algorithms for Minimization without Derivatives,
100 ! Prentice - Hall, inc. (1973).
101 !
102 ! Parameters:
103 !
104 ! ax left endpoint of initial interval
105 ! bx right endpoint of initial interval
106 ! f function subprogram which evaluates f(x) for any x in the interval ax, bx
107 ! tol desired length of the interval of uncertainty of the final result (>= 0.0d0)
108 !
109 ! Result:
110 !
111 ! Approximation of a zero of f in the interval ax, bx
112 ! ierr = 0 'zero in' found a root
113 ! ierr = 1 'zero in' did not find a root
114 !
115 ! Compare to SLATEC routines DFZERO and FZERO.
116 !
117
118 ! Initialization.
119 eps = d1mach(3)
120 a = ax
121 b = bx
122 fa = f(a)
123 fb = f(b)
124 ! Begin.
125 1 c = a
126 fc = fa
127 d = b - a
128 e = d
129 2 if (dabs(fc) < dabs(fb)) then
130 a = b
131 b = c
132 c = a
133 fa = fb
134 fb = fc
135 fc = fa
136 end if
137 ! Convergence check.
138 tol1 = 2.0d0 * eps * dabs(b) + 0.5d0 * tol
139 xm = .5d0 * (c - b)
140 if (dabs(xm) <= tol1 | fb == 0.0d0) go to 5
141 ! Is bisection necessary?
142 if (dabs(e) < tol1 | dabs(fa) <= dabs(fb)) go to 3
143 ! Is quadratic interpolation possible?
144 if (a == c) then
145 ! Linear interpolation.
146 s = fb / fa
147 p = 2.0d0 * xm * s
148 q = 1.0d0 - s
149 else
150 ! Inverse quadratic interpolation.
151 q = fa / fc
152 r = fb / fc
153 s = fb / fa
154 p = s * (2.0d0 * xm * q * (q - r) - (b - a) * (r - 1.0d0))
155 q = (q - 1.0d0) * (r - 1.0d0) * (s - 1.0d0)
156 end if
157 ! Adjust signs.
158 if (p > 0.0d0) q = -q
159 p = dabs(p)
160 ! Is interpolation acceptable?
161 if ((2.0d0 * p) >= (3.0d0 * xm * q - dabs(tol1 * q))) go to 3
162 if (p >= dabs(0.5d0 * e * q)) go to 3
163 e = d
164 d = p / q
165 go to 4
166 ! Bisection.
167 3 d = xm
168 e = d
169 ! Complete step.
170 4 a = b
171 fa = fb
172 if (dabs(d) > tol1) b = b + d
173 if (dabs(d) <= tol1) b = b + dsign(tol1, xm)
174 fb = f(b)
175 if ((fb * (fc / dabs(fc))) > 0.0d0) go to 1
176 go to 2
177 ! Done.
178 5 zero in = b
179 if (dabs (fb) <= tol) then
180 ierr = 0
181 else
182 ierr = 1
183 end if
184 return
185 end
© 2002-2025 J.M. van der Veer (jmvdveer@xs4all.nl)
|