1 | CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC |
---|
2 | C Math functions used in crystal_dan_FINAL_VERSION_CHvsCV.f |
---|
3 | C From track_dan_new.f |
---|
4 | C |
---|
5 | C |
---|
6 | C |
---|
7 | C |
---|
8 | CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC |
---|
9 | |
---|
10 | |
---|
11 | |
---|
12 | double precision function RAN_GAUSS(cut) |
---|
13 | !********************************************************************* |
---|
14 | ! |
---|
15 | ! RAN_GAUSS - will generate a normal distribution from a uniform |
---|
16 | ! distribution between [0,1]. |
---|
17 | ! See "Communications of the ACM", V. 15 (1972), p. 873. |
---|
18 | ! |
---|
19 | ! cut - double precision - cut for distribution in units of sigma |
---|
20 | ! the cut must be greater than 0.5 |
---|
21 | ! |
---|
22 | !********************************************************************* |
---|
23 | implicit none |
---|
24 | |
---|
25 | logical flag |
---|
26 | real rndm4 |
---|
27 | double precision x, u1, u2, twopi, r,cut |
---|
28 | save |
---|
29 | |
---|
30 | c write(*,*) "In RAN_GAUSS: " |
---|
31 | c write(*,*) "flag = ",flag |
---|
32 | c write(*,*) "U1 = ", U1,"U2 = ", U2 |
---|
33 | twopi=8d0*atan(1d0) |
---|
34 | 1 if (flag) then |
---|
35 | r = dble(rndm4( )) |
---|
36 | r = max(r, 0.5d0**32) |
---|
37 | r = min(r, 1d0-0.5d0**32) |
---|
38 | u1 = sqrt(-2d0*log( r )) |
---|
39 | u2 = dble(rndm4( )) |
---|
40 | x = u1 * cos(twopi*u2) |
---|
41 | else |
---|
42 | x = u1 * sin(twopi*u2) |
---|
43 | endif |
---|
44 | |
---|
45 | c write(*,*) "flag = ",flag |
---|
46 | c write(*,*) "U1 = ", U1,"U2 = ", U2, "x = ", x |
---|
47 | |
---|
48 | flag = .not. flag |
---|
49 | |
---|
50 | ! cut the distribution if cut > 0.5 |
---|
51 | if (cut .gt. 0.5d0 .and. abs(x) .gt. cut) goto 1 |
---|
52 | |
---|
53 | RAN_GAUSS = x |
---|
54 | |
---|
55 | c write(*,*) "ran_gauss = ", RAN_GAUSS |
---|
56 | |
---|
57 | return |
---|
58 | end |
---|
59 | |
---|
60 | !CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC |
---|
61 | !CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC |
---|
62 | function rndm4() |
---|
63 | implicit none |
---|
64 | integer len, in |
---|
65 | real rndm4, a |
---|
66 | save |
---|
67 | parameter ( len = 30000 ) |
---|
68 | dimension a(len) |
---|
69 | data in/1/ |
---|
70 | ! |
---|
71 | if ( in.eq.1 ) then |
---|
72 | call ranlux(a,len) |
---|
73 | rndm4=a(1) |
---|
74 | in=2 |
---|
75 | ! write(6,'('' LEN: '',i5)')LEN |
---|
76 | else |
---|
77 | rndm4=a(in) |
---|
78 | in=in+1 |
---|
79 | if(in.eq.len+1)in=1 |
---|
80 | endif |
---|
81 | return |
---|
82 | end |
---|
83 | |
---|
84 | |
---|
85 | |
---|
86 | subroutine ranlux(rvec,lenv) |
---|
87 | ! Subtract-and-borrow random number generator proposed by |
---|
88 | ! Marsaglia and Zaman, implemented by F. James with the name |
---|
89 | ! RCARRY in 1991, and later improved by Martin Luescher |
---|
90 | ! in 1993 to produce "Luxury Pseudorandom Numbers". |
---|
91 | ! Fortran 77 coded by F. James, 1993 |
---|
92 | ! |
---|
93 | ! LUXURY LEVELS. |
---|
94 | ! ------ ------ The available luxury levels are: |
---|
95 | ! |
---|
96 | ! level 0 (p=24): equivalent to the original RCARRY of Marsaglia |
---|
97 | ! and Zaman, very long period, but fails many tests. |
---|
98 | ! level 1 (p=48): considerable improvement in quality over level 0, |
---|
99 | ! now passes the gap test, but still fails spectral test. |
---|
100 | ! level 2 (p=97): passes all known tests, but theoretically still |
---|
101 | ! defective. |
---|
102 | ! level 3 (p=223): DEFAULT VALUE. Any theoretically possible |
---|
103 | ! correlations have very small chance of being observed. |
---|
104 | ! level 4 (p=389): highest possible luxury, all 24 bits chaotic. |
---|
105 | ! |
---|
106 | !!! ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
---|
107 | !!! Calling sequences for RANLUX: ++ |
---|
108 | !!! CALL RANLUX (RVEC, LEN) returns a vector RVEC of LEN ++ |
---|
109 | !!! 32-bit random floating point numbers between ++ |
---|
110 | !!! zero (not included) and one (also not incl.). ++ |
---|
111 | !!! CALL RLUXGO(LUX,INT,K1,K2) initializes the generator from ++ |
---|
112 | !!! one 32-bit integer INT and sets Luxury Level LUX ++ |
---|
113 | !!! which is integer between zero and MAXLEV, or if ++ |
---|
114 | !!! LUX .GT. 24, it sets p=LUX directly. K1 and K2 ++ |
---|
115 | !!! should be set to zero unless restarting at a break++ |
---|
116 | !!! point given by output of RLUXAT (see RLUXAT). ++ |
---|
117 | !!! CALL RLUXAT(LUX,INT,K1,K2) gets the values of four integers++ |
---|
118 | !!! which can be used to restart the RANLUX generator ++ |
---|
119 | !!! at the current point by calling RLUXGO. K1 and K2++ |
---|
120 | !!! specify how many numbers were generated since the ++ |
---|
121 | !!! initialization with LUX and INT. The restarting ++ |
---|
122 | !!! skips over K1+K2*E9 numbers, so it can be long.++ |
---|
123 | !!! A more efficient but less convenient way of restarting is by: ++ |
---|
124 | !!! CALL RLUXIN(ISVEC) restarts the generator from vector ++ |
---|
125 | !!! ISVEC of 25 32-bit integers (see RLUXUT) ++ |
---|
126 | !!! CALL RLUXUT(ISVEC) outputs the current values of the 25 ++ |
---|
127 | !!! 32-bit integer seeds, to be used for restarting ++ |
---|
128 | !!! ISVEC must be dimensioned 25 in the calling program ++ |
---|
129 | !!! ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
---|
130 | implicit none |
---|
131 | integer lenv,isdext,iseeds,maxlev,ndskip,itwo24,next,j24,i24, & |
---|
132 | &inseed,mkount,kount,in24,nskip,lxdflt,jsdflt,jseed,lp,i,k,icons, & |
---|
133 | &inner,izip,izip2,ivec,isk,igiga,isd,k2,k1,inout,lout,ins,lux,ilx, & |
---|
134 | &iouter |
---|
135 | real rvec,seeds,twop12,twom12,twom24,carry,uni |
---|
136 | dimension rvec(lenv) |
---|
137 | dimension seeds(24), iseeds(24), isdext(25) |
---|
138 | parameter (maxlev=4, lxdflt=3) |
---|
139 | dimension ndskip(0:maxlev) |
---|
140 | dimension next(24) |
---|
141 | parameter (twop12=4096., igiga=1000000000,jsdflt=314159265) |
---|
142 | parameter (itwo24=2**24, icons=2147483563) |
---|
143 | save notyet, i24, j24, carry, seeds, twom24, twom12, luxlev |
---|
144 | save nskip, ndskip, in24, next, kount, mkount, inseed |
---|
145 | integer luxlev |
---|
146 | logical notyet |
---|
147 | data notyet, luxlev, in24, kount, mkount /.true., lxdflt, 0,0,0/ |
---|
148 | data i24,j24,carry/24,10,0./ |
---|
149 | ! default |
---|
150 | ! Luxury Level 0 1 2 *3* 4 |
---|
151 | data ndskip/0, 24, 73, 199, 365 / |
---|
152 | !Corresponds to p=24 48 97 223 389 |
---|
153 | ! time factor 1 2 3 6 10 on slow workstation |
---|
154 | ! 1 1.5 2 3 5 on fast mainframe |
---|
155 | ! |
---|
156 | ! NOTYET is .TRUE. if no initialization has been performed yet. |
---|
157 | ! Default Initialization by Multiplicative Congruential |
---|
158 | if (notyet) then |
---|
159 | notyet = .false. |
---|
160 | jseed = jsdflt |
---|
161 | inseed = jseed |
---|
162 | write(*,'(A,I12)') ' RANLUX DEFAULT INITIALIZATION: ',jseed |
---|
163 | luxlev = lxdflt |
---|
164 | nskip = ndskip(luxlev) |
---|
165 | lp = nskip + 24 |
---|
166 | in24 = 0 |
---|
167 | kount = 0 |
---|
168 | mkount = 0 |
---|
169 | ! WRITE(6,'(A,I2,A,I4)') ' RANLUX DEFAULT LUXURY LEVEL = ', |
---|
170 | ! & LUXLEV,' p =',LP |
---|
171 | twom24 = 1. |
---|
172 | do 25 i= 1, 24 |
---|
173 | twom24 = twom24 * 0.5 |
---|
174 | k = jseed/53668 |
---|
175 | jseed = 40014*(jseed-k*53668) -k*12211 |
---|
176 | if (jseed .lt. 0) jseed = jseed+icons |
---|
177 | iseeds(i) = mod(jseed,itwo24) |
---|
178 | 25 continue |
---|
179 | twom12 = twom24 * 4096. |
---|
180 | do 50 i= 1,24 |
---|
181 | seeds(i) = real(iseeds(i))*twom24 |
---|
182 | next(i) = i-1 |
---|
183 | 50 continue |
---|
184 | next(1) = 24 |
---|
185 | i24 = 24 |
---|
186 | j24 = 10 |
---|
187 | carry = 0. |
---|
188 | if (seeds(24) .eq. 0.) carry = twom24 |
---|
189 | endif |
---|
190 | ! |
---|
191 | ! The Generator proper: "Subtract-with-borrow", |
---|
192 | ! as proposed by Marsaglia and Zaman, |
---|
193 | ! Florida State University, March, 1989 |
---|
194 | ! |
---|
195 | do 100 ivec= 1, lenv |
---|
196 | uni = seeds(j24) - seeds(i24) - carry |
---|
197 | if (uni .lt. 0.) then |
---|
198 | uni = uni + 1. |
---|
199 | carry = twom24 |
---|
200 | else |
---|
201 | carry = 0. |
---|
202 | endif |
---|
203 | seeds(i24) = uni |
---|
204 | i24 = next(i24) |
---|
205 | j24 = next(j24) |
---|
206 | rvec(ivec) = uni |
---|
207 | ! small numbers (with less than 12 "significant" bits) are "padded". |
---|
208 | if (uni .lt. twom12) then |
---|
209 | rvec(ivec) = rvec(ivec) + twom24*seeds(j24) |
---|
210 | ! and zero is forbidden in case someone takes a logarithm |
---|
211 | if (rvec(ivec) .eq. 0.) rvec(ivec) = twom24*twom24 |
---|
212 | endif |
---|
213 | ! Skipping to luxury. As proposed by Martin Luscher. |
---|
214 | in24 = in24 + 1 |
---|
215 | if (in24 .eq. 24) then |
---|
216 | in24 = 0 |
---|
217 | kount = kount + nskip |
---|
218 | do 90 isk= 1, nskip |
---|
219 | uni = seeds(j24) - seeds(i24) - carry |
---|
220 | if (uni .lt. 0.) then |
---|
221 | uni = uni + 1. |
---|
222 | carry = twom24 |
---|
223 | else |
---|
224 | carry = 0. |
---|
225 | endif |
---|
226 | seeds(i24) = uni |
---|
227 | i24 = next(i24) |
---|
228 | j24 = next(j24) |
---|
229 | 90 continue |
---|
230 | endif |
---|
231 | 100 continue |
---|
232 | kount = kount + lenv |
---|
233 | if (kount .ge. igiga) then |
---|
234 | mkount = mkount + 1 |
---|
235 | kount = kount - igiga |
---|
236 | endif |
---|
237 | return |
---|
238 | ! |
---|
239 | ! Entry to input and float integer seeds from previous run |
---|
240 | entry rluxin(isdext) |
---|
241 | notyet = .false. |
---|
242 | twom24 = 1. |
---|
243 | do 195 i= 1, 24 |
---|
244 | next(i) = i-1 |
---|
245 | 195 twom24 = twom24 * 0.5 |
---|
246 | next(1) = 24 |
---|
247 | twom12 = twom24 * 4096. |
---|
248 | write(*,*) ' FULL INITIALIZATION OF RANLUX WITH 25 INTEGERS:' |
---|
249 | write(*,'(5X,5I12)') isdext |
---|
250 | do 200 i= 1, 24 |
---|
251 | seeds(i) = real(isdext(i))*twom24 |
---|
252 | 200 continue |
---|
253 | carry = 0. |
---|
254 | if (isdext(25) .lt. 0) carry = twom24 |
---|
255 | isd = iabs(isdext(25)) |
---|
256 | i24 = mod(isd,100) |
---|
257 | isd = isd/100 |
---|
258 | j24 = mod(isd,100) |
---|
259 | isd = isd/100 |
---|
260 | in24 = mod(isd,100) |
---|
261 | isd = isd/100 |
---|
262 | luxlev = isd |
---|
263 | if (luxlev .le. maxlev) then |
---|
264 | nskip = ndskip(luxlev) |
---|
265 | write(*,'(A,I2)') ' RANLUX LUXURY LEVEL SET BY RLUXIN TO: ', & |
---|
266 | &luxlev |
---|
267 | else if (luxlev .ge. 24) then |
---|
268 | nskip = luxlev - 24 |
---|
269 | write(*,'(A,I5)') ' RANLUX P-VALUE SET BY RLUXIN TO:',luxlev |
---|
270 | else |
---|
271 | nskip = ndskip(maxlev) |
---|
272 | write(*,'(A,I5)') ' RANLUX ILLEGAL LUXURY RLUXIN: ',luxlev |
---|
273 | luxlev = maxlev |
---|
274 | endif |
---|
275 | inseed = -1 |
---|
276 | return |
---|
277 | ! |
---|
278 | ! Entry to ouput seeds as integers |
---|
279 | entry rluxut(isdext) |
---|
280 | do 300 i= 1, 24 |
---|
281 | isdext(i) = int(seeds(i)*twop12*twop12) |
---|
282 | 300 continue |
---|
283 | isdext(25) = i24 + 100*j24 + 10000*in24 + 1000000*luxlev |
---|
284 | if (carry .gt. 0.) isdext(25) = -isdext(25) |
---|
285 | return |
---|
286 | ! |
---|
287 | ! Entry to output the "convenient" restart point |
---|
288 | entry rluxat(lout,inout,k1,k2) |
---|
289 | lout = luxlev |
---|
290 | inout = inseed |
---|
291 | k1 = kount |
---|
292 | k2 = mkount |
---|
293 | return |
---|
294 | ! |
---|
295 | ! Entry to initialize from one or three integers |
---|
296 | entry rluxgo(lux,ins,k1,k2) |
---|
297 | if (lux .lt. 0) then |
---|
298 | luxlev = lxdflt |
---|
299 | else if (lux .le. maxlev) then |
---|
300 | luxlev = lux |
---|
301 | else if (lux .lt. 24 .or. lux .gt. 2000) then |
---|
302 | luxlev = maxlev |
---|
303 | write(*,'(A,I7)') ' RANLUX ILLEGAL LUXURY RLUXGO: ',lux |
---|
304 | else |
---|
305 | luxlev = lux |
---|
306 | do 310 ilx= 0, maxlev |
---|
307 | if (lux .eq. ndskip(ilx)+24) luxlev = ilx |
---|
308 | 310 continue |
---|
309 | endif |
---|
310 | if (luxlev .le. maxlev) then |
---|
311 | nskip = ndskip(luxlev) |
---|
312 | write(*,'(A,I2,A,I4)') ' RANLUX LUXURY LEVEL SET BY RLUXGO :', & |
---|
313 | &luxlev,' P=', nskip+24 |
---|
314 | else |
---|
315 | nskip = luxlev - 24 |
---|
316 | write(*,'(A,I5)') ' RANLUX P-VALUE SET BY RLUXGO TO:',luxlev |
---|
317 | endif |
---|
318 | in24 = 0 |
---|
319 | if (ins .lt. 0) write(*,*) & |
---|
320 | &' Illegal initialization by RLUXGO, negative input seed' |
---|
321 | if (ins .gt. 0) then |
---|
322 | jseed = ins |
---|
323 | write(*,'(A,3I12)') ' RANLUX INITIALIZED BY RLUXGO FROM SEEDS', & |
---|
324 | &jseed, k1,k2 |
---|
325 | else |
---|
326 | jseed = jsdflt |
---|
327 | write(*,*)' RANLUX INITIALIZED BY RLUXGO FROM DEFAULT SEED' |
---|
328 | endif |
---|
329 | inseed = jseed |
---|
330 | notyet = .false. |
---|
331 | twom24 = 1. |
---|
332 | do 325 i= 1, 24 |
---|
333 | twom24 = twom24 * 0.5 |
---|
334 | k = jseed/53668 |
---|
335 | jseed = 40014*(jseed-k*53668) -k*12211 |
---|
336 | if (jseed .lt. 0) jseed = jseed+icons |
---|
337 | iseeds(i) = mod(jseed,itwo24) |
---|
338 | 325 continue |
---|
339 | twom12 = twom24 * 4096. |
---|
340 | do 350 i= 1,24 |
---|
341 | seeds(i) = real(iseeds(i))*twom24 |
---|
342 | next(i) = i-1 |
---|
343 | 350 continue |
---|
344 | next(1) = 24 |
---|
345 | i24 = 24 |
---|
346 | j24 = 10 |
---|
347 | carry = 0. |
---|
348 | if (seeds(24) .eq. 0.) carry = twom24 |
---|
349 | ! If restarting at a break point, skip K1 + IGIGA*K2 |
---|
350 | ! Note that this is the number of numbers delivered to |
---|
351 | ! the user PLUS the number skipped (if luxury .GT. 0). |
---|
352 | kount = k1 |
---|
353 | mkount = k2 |
---|
354 | if (k1+k2 .ne. 0) then |
---|
355 | do 500 iouter= 1, k2+1 |
---|
356 | inner = igiga |
---|
357 | if (iouter .eq. k2+1) inner = k1 |
---|
358 | do 450 isk= 1, inner |
---|
359 | uni = seeds(j24) - seeds(i24) - carry |
---|
360 | if (uni .lt. 0.) then |
---|
361 | uni = uni + 1. |
---|
362 | carry = twom24 |
---|
363 | else |
---|
364 | carry = 0. |
---|
365 | endif |
---|
366 | seeds(i24) = uni |
---|
367 | i24 = next(i24) |
---|
368 | j24 = next(j24) |
---|
369 | 450 continue |
---|
370 | 500 continue |
---|
371 | ! Get the right value of IN24 by direct calculation |
---|
372 | in24 = mod(kount, nskip+24) |
---|
373 | if (mkount .gt. 0) then |
---|
374 | izip = mod(igiga, nskip+24) |
---|
375 | izip2 = mkount*izip + in24 |
---|
376 | in24 = mod(izip2, nskip+24) |
---|
377 | endif |
---|
378 | ! Now IN24 had better be between zero and 23 inclusive |
---|
379 | if (in24 .gt. 23) then |
---|
380 | write(*,'(A/A,3I11,A,I5)') & |
---|
381 | &' Error in RESTARTING with RLUXGO:',' The values', ins, & |
---|
382 | &k1, k2, ' cannot occur at luxury level', luxlev |
---|
383 | in24 = 0 |
---|
384 | endif |
---|
385 | endif |
---|
386 | return |
---|
387 | end |
---|
388 | |
---|
389 | !cccccccccccccccccccccccccccccccccccccccccccccccccc |
---|
390 | subroutine funlxp (func,xfcum,x2low,x2high) |
---|
391 | ! F. JAMES, Sept, 1994 |
---|
392 | ! |
---|
393 | ! Prepares the user function FUNC for FUNLUX |
---|
394 | ! Inspired by and mostly copied from FUNPRE and FUNRAN |
---|
395 | ! except that |
---|
396 | ! 1. FUNLUX uses RANLUX underneath, |
---|
397 | ! 2. FUNLXP expands the first and last bins to cater for |
---|
398 | ! functions with long tails on left and/or right, |
---|
399 | ! 3. FUNLXP calls FUNPCT to do the actual finding of percentiles. |
---|
400 | ! 4. both FUNLXP and FUNPCT use RADAPT for Gaussian integration. |
---|
401 | ! |
---|
402 | implicit none |
---|
403 | external func |
---|
404 | integer ifunc,ierr |
---|
405 | real x2high,x2low,xfcum,rteps,xhigh,xlow,xrange,uncert,x2,tftot1, & |
---|
406 | &x3,tftot2,func |
---|
407 | real tftot |
---|
408 | common/funint/tftot |
---|
409 | dimension xfcum(200) |
---|
410 | parameter (rteps=0.0002) |
---|
411 | save ifunc |
---|
412 | data ifunc/0/ |
---|
413 | ifunc = ifunc + 1 |
---|
414 | ! FIND RANGE WHERE FUNCTION IS NON-ZERO. |
---|
415 | call funlz(func,x2low,x2high,xlow,xhigh) |
---|
416 | xrange = xhigh-xlow |
---|
417 | if(xrange .le. 0.) then |
---|
418 | write(*,'(A,2G15.5)') ' FUNLXP finds function range .LE.0', & |
---|
419 | &xlow,xhigh |
---|
420 | go to 900 |
---|
421 | endif |
---|
422 | call radapt(func,xlow,xhigh,1,rteps,0.,tftot ,uncert) |
---|
423 | ! WRITE(6,1003) IFUNC,XLOW,XHIGH,TFTOT |
---|
424 | 1003 format(' FUNLXP: integral of USER FUNCTION', & |
---|
425 | &i3,' from ',e12.5,' to ',e12.5,' is ',e14.6) |
---|
426 | ! |
---|
427 | ! WRITE (6,'(A,A)') ' FUNLXP preparing ', |
---|
428 | ! + 'first the whole range, then left tail, then right tail.' |
---|
429 | call funpct(func,ifunc,xlow,xhigh,xfcum,1,99,tftot,ierr) |
---|
430 | if (ierr .gt. 0) go to 900 |
---|
431 | x2 = xfcum(3) |
---|
432 | call radapt(func,xlow,x2,1,rteps,0.,tftot1 ,uncert) |
---|
433 | call funpct(func,ifunc,xlow,x2 ,xfcum,101,49,tftot1,ierr) |
---|
434 | if (ierr .gt. 0) go to 900 |
---|
435 | x3 = xfcum(98) |
---|
436 | call radapt(func,x3,xhigh,1,rteps,0.,tftot2 ,uncert) |
---|
437 | call funpct(func,ifunc,x3,xhigh,xfcum,151,49,tftot2,ierr) |
---|
438 | if (ierr .gt. 0) go to 900 |
---|
439 | ! WRITE(6,1001) IFUNC,XLOW,XHIGH |
---|
440 | 1001 format(' FUNLXP has prepared USER FUNCTION',i3, & |
---|
441 | &' between',g12.3,' and',g12.3,' for FUNLUX') |
---|
442 | return |
---|
443 | 900 continue |
---|
444 | write(*,*) ' Fatal error in FUNLXP. FUNLUX will not work.' |
---|
445 | end |
---|
446 | ! |
---|
447 | |
---|
448 | |
---|
449 | subroutine funlux(array,xran,len) |
---|
450 | ! Generation of LEN random numbers in any given distribution, |
---|
451 | ! by 4-point interpolation in the inverse cumulative distr. |
---|
452 | ! which was previously generated by FUNLXP |
---|
453 | implicit none |
---|
454 | real tftot |
---|
455 | common/funint/tftot |
---|
456 | integer len,ibuf,j,j1 |
---|
457 | real array,xran,gap,gapinv,tleft,bright,gaps,gapins,x,p,a,b |
---|
458 | dimension array(200) |
---|
459 | dimension xran(len) |
---|
460 | ! Bin width for main sequence, and its inverse |
---|
461 | parameter (gap= 1./99., gapinv=99.) |
---|
462 | ! Top of left tail, bottom of right tail (each tail replaces 2 bins) |
---|
463 | parameter (tleft= 2./99.,bright=97./99.) |
---|
464 | ! Bin width for minor sequences (tails), and its inverse |
---|
465 | parameter (gaps=tleft/49., gapins=1./gaps) |
---|
466 | ! |
---|
467 | ! The array ARRAY is assumed to have the following structure: |
---|
468 | ! ARRAY(1-100) contains the 99 bins of the inverse cumulative |
---|
469 | ! distribution of the entire function. |
---|
470 | ! ARRAY(101-150) contains the 49-bin blowup of main bins |
---|
471 | ! 1 and 2 (left tail of distribution) |
---|
472 | ! ARRAY(151-200) contains the 49-bin blowup of main bins |
---|
473 | ! 98 and 99 (right tail of distribution) |
---|
474 | ! |
---|
475 | call ranlux(xran,len) |
---|
476 | |
---|
477 | do 500 ibuf= 1, len |
---|
478 | x = xran(ibuf) |
---|
479 | j = int( x *gapinv) + 1 |
---|
480 | if (j .lt. 3) then |
---|
481 | j1 = int( x *gapins) |
---|
482 | j = j1 + 101 |
---|
483 | j = max(j,102) |
---|
484 | j = min(j,148) |
---|
485 | p = ( x -gaps*(j1-1)) * gapins |
---|
486 | a = (p+1.0) * array(j+2) - (p-2.0)*array(j-1) |
---|
487 | b = (p-1.0) * array(j) - p * array(j+1) |
---|
488 | xran(ibuf) = a*p*(p-1.0)*0.16666667 + b*(p+1.)*(p-2.)*0.5 |
---|
489 | else if (j .gt. 97) then |
---|
490 | j1 = int((x-bright)*gapins) |
---|
491 | j = j1 + 151 |
---|
492 | j = max(j,152) |
---|
493 | j = min(j,198) |
---|
494 | p = (x -bright -gaps*(j1-1)) * gapins |
---|
495 | a = (p+1.0) * array(j+2) - (p-2.0)*array(j-1) |
---|
496 | b = (p-1.0) * array(j) - p * array(j+1) |
---|
497 | xran(ibuf) = a*p*(p-1.0)*0.16666667 + b*(p+1.)*(p-2.)*0.5 |
---|
498 | else |
---|
499 | ! J = MAX(J,2) |
---|
500 | ! J = MIN(J,98) |
---|
501 | p = ( x -gap*(j-1)) * gapinv |
---|
502 | a = (p+1.) * array(j+2) - (p-2.)*array(j-1) |
---|
503 | b = (p-1.) * array(j) - p * array(j+1) |
---|
504 | xran(ibuf) = a*p*(p-1.)*0.16666667 + b*(p+1.)*(p-2.)*0.5 |
---|
505 | endif |
---|
506 | 500 continue |
---|
507 | tftot = x |
---|
508 | return |
---|
509 | end |
---|
510 | |
---|
511 | |
---|
512 | CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC |
---|
513 | C |
---|
514 | CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC |
---|
515 | subroutine funlz(func,x2low,x2high,xlow,xhigh) |
---|
516 | ! FIND RANGE WHERE FUNC IS NON-ZERO. |
---|
517 | ! WRITTEN 1980, F. JAMES |
---|
518 | ! MODIFIED, NOV. 1985, TO FIX BUG AND GENERALIZE |
---|
519 | ! TO FIND SIMPLY-CONNECTED NON-ZERO REGION (XLOW,XHIGH) |
---|
520 | ! ANYWHERE WITHIN THE GIVEN REGION (X2LOW,H2HIGH). |
---|
521 | ! WHERE 'ANYWHERE' MEANS EITHER AT THE LOWER OR UPPER |
---|
522 | ! EDGE OF THE GIVEN REGION, OR, IF IN THE MIDDLE, |
---|
523 | ! COVERING AT LEAST 1% OF THE GIVEN REGION. |
---|
524 | ! OTHERWISE IT IS NOT GUARANTEED TO FIND THE NON-ZERO REGION. |
---|
525 | ! IF FUNCTION EVERYWHERE ZERO, FUNLZ SETS XLOW=XHIGH=0. |
---|
526 | implicit none |
---|
527 | external func |
---|
528 | integer logn,nslice,i,k |
---|
529 | real xhigh,xlow,x2high,x2low,func,xmid,xh,xl,xnew |
---|
530 | xlow = x2low |
---|
531 | xhigh = x2high |
---|
532 | ! FIND OUT IF FUNCTION IS ZERO AT ONE END OR BOTH |
---|
533 | xmid = xlow |
---|
534 | if (func(xlow) .gt. 0.) go to 120 |
---|
535 | xmid = xhigh |
---|
536 | if (func(xhigh) .gt. 0.) go to 50 |
---|
537 | ! FUNCTION IS ZERO AT BOTH ENDS, |
---|
538 | ! LOOK FOR PLACE WHERE IT IS NON-ZERO. |
---|
539 | do 30 logn= 1, 7 |
---|
540 | nslice = 2**logn |
---|
541 | do 20 i= 1, nslice, 2 |
---|
542 | xmid = xlow + i * (xhigh-xlow) / nslice |
---|
543 | if (func(xmid) .gt. 0.) go to 50 |
---|
544 | 20 continue |
---|
545 | 30 continue |
---|
546 | ! FALLING THROUGH LOOP MEANS CANNOT FIND NON-ZERO VALUE |
---|
547 | write(*,554) |
---|
548 | write(*,555) xlow, xhigh |
---|
549 | xlow = 0. |
---|
550 | xhigh = 0. |
---|
551 | go to 220 |
---|
552 | ! |
---|
553 | 50 continue |
---|
554 | ! DELETE 'LEADING' ZERO RANGE |
---|
555 | xh = xmid |
---|
556 | xl = xlow |
---|
557 | do 70 k= 1, 20 |
---|
558 | xnew = 0.5*(xh+xl) |
---|
559 | if (func(xnew) .eq. 0.) go to 68 |
---|
560 | xh = xnew |
---|
561 | go to 70 |
---|
562 | 68 xl = xnew |
---|
563 | 70 continue |
---|
564 | xlow = xl |
---|
565 | write(*,555) x2low,xlow |
---|
566 | 120 continue |
---|
567 | if (func(xhigh) .gt. 0.) go to 220 |
---|
568 | ! DELETE 'TRAILING' RANGE OF ZEROES |
---|
569 | xl = xmid |
---|
570 | xh = xhigh |
---|
571 | do 170 k= 1, 20 |
---|
572 | xnew = 0.5*(xh+xl) |
---|
573 | if (func(xnew) .eq. 0.) go to 168 |
---|
574 | xl = xnew |
---|
575 | go to 170 |
---|
576 | 168 xh = xnew |
---|
577 | 170 continue |
---|
578 | xhigh = xh |
---|
579 | write(*,555) xhigh, x2high |
---|
580 | ! |
---|
581 | 220 continue |
---|
582 | return |
---|
583 | 554 format('0CANNOT FIND NON-ZERO FUNCTION VALUE') |
---|
584 | 555 format(' FUNCTION IS ZERO FROM X=',e12.5,' TO ',e12.5) |
---|
585 | end |
---|
586 | |
---|
587 | |
---|
588 | !ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc |
---|
589 | ! |
---|
590 | ! $Id: radapt.F,v 1.1.1.1 1996/04/01 15:02:13 mclareni Exp $ |
---|
591 | ! |
---|
592 | ! $Log: radapt.F,v $ |
---|
593 | ! Revision 1.1.1.1 1996/04/01 15:02:13 mclareni |
---|
594 | ! Mathlib gen |
---|
595 | ! |
---|
596 | ! |
---|
597 | subroutine radapt(f,a,b,nseg,reltol,abstol,res,err) |
---|
598 | |
---|
599 | ! RES = Estimated Integral of F from A to B, |
---|
600 | ! ERR = Estimated absolute error on RES. |
---|
601 | ! NSEG specifies how the adaptation is to be done: |
---|
602 | ! =0 means use previous binning, |
---|
603 | ! =1 means fully automatic, adapt until tolerance attained. |
---|
604 | ! =n>1 means first split interval into n equal segments, |
---|
605 | ! then adapt as necessary to attain tolerance. |
---|
606 | ! The specified tolerances are: |
---|
607 | ! relative: RELTOL ; absolute: ABSTOL. |
---|
608 | ! It stop s when one OR the other is satisfied, or number of |
---|
609 | ! segments exceeds NDIM. Either TOLA or TOLR (but not both!) |
---|
610 | ! can be set to zero, in which case only the other is used. |
---|
611 | |
---|
612 | implicit none |
---|
613 | external f |
---|
614 | integer nseg,ndim,nter,nsegd,i,iter,ibig |
---|
615 | real err,res,abstol,reltol,b,a,xlo,xhi,tval,ters,te,root,xhib, & |
---|
616 | &bin,xlob,bige,hf,xnew,r1,f |
---|
617 | double precision tvals,terss |
---|
618 | |
---|
619 | parameter (ndim=100) |
---|
620 | parameter (r1 = 1., hf = r1/2.) |
---|
621 | |
---|
622 | dimension xlo(ndim),xhi(ndim),tval(ndim),ters(ndim) |
---|
623 | save xlo,xhi,tval,ters,nter |
---|
624 | data nter /0/ |
---|
625 | |
---|
626 | if(nseg .le. 0) then |
---|
627 | if(nter .eq. 0) then |
---|
628 | nsegd=1 |
---|
629 | go to 2 |
---|
630 | endif |
---|
631 | tvals=0d0 |
---|
632 | terss=0d0 |
---|
633 | do 1 i = 1,nter |
---|
634 | call rgs56p(f,xlo(i),xhi(i),tval(i),te) |
---|
635 | ters(i)=te**2 |
---|
636 | tvals=tvals+tval(i) |
---|
637 | terss=terss+ters(i) |
---|
638 | 1 continue |
---|
639 | root= sqrt(2.*terss) |
---|
640 | go to 9 |
---|
641 | endif |
---|
642 | nsegd=min(nseg,ndim) |
---|
643 | 2 xhib=a |
---|
644 | bin=(b-a)/nsegd |
---|
645 | do 3 i = 1,nsegd |
---|
646 | xlo(i)=xhib |
---|
647 | xlob=xlo(i) |
---|
648 | xhi(i)=xhib+bin |
---|
649 | if(i .eq. nsegd) xhi(i)=b |
---|
650 | xhib=xhi(i) |
---|
651 | call rgs56p(f,xlob,xhib,tval(i),te) |
---|
652 | ters(i)=te**2 |
---|
653 | 3 continue |
---|
654 | nter=nsegd |
---|
655 | do 4 iter = 1,ndim |
---|
656 | tvals=tval(1) |
---|
657 | terss=ters(1) |
---|
658 | do 5 i = 2,nter |
---|
659 | tvals=tvals+tval(i) |
---|
660 | terss=terss+ters(i) |
---|
661 | 5 continue |
---|
662 | root= sqrt(2.*terss) |
---|
663 | if(root .le. abstol .or. root .le. reltol*abs(tvals)) go to 9 |
---|
664 | if(nter .eq. ndim) go to 9 |
---|
665 | bige=ters(1) |
---|
666 | ibig=1 |
---|
667 | do 6 i = 2,nter |
---|
668 | if(ters(i) .gt. bige) then |
---|
669 | bige=ters(i) |
---|
670 | ibig=i |
---|
671 | endif |
---|
672 | 6 continue |
---|
673 | nter=nter+1 |
---|
674 | xhi(nter)=xhi(ibig) |
---|
675 | xnew=hf*(xlo(ibig)+xhi(ibig)) |
---|
676 | xhi(ibig)=xnew |
---|
677 | xlo(nter)=xnew |
---|
678 | call rgs56p(f,xlo(ibig),xhi(ibig),tval(ibig),te) |
---|
679 | ters(ibig)=te**2 |
---|
680 | call rgs56p(f,xlo(nter),xhi(nter),tval(nter),te) |
---|
681 | ters(nter)=te**2 |
---|
682 | 4 continue |
---|
683 | 9 res=tvals |
---|
684 | err=root |
---|
685 | return |
---|
686 | end |
---|
687 | |
---|
688 | |
---|
689 | !cccccccccccccccccccccccccccccccccccccccccccccccccccccc |
---|
690 | |
---|
691 | ! |
---|
692 | ! $Id: rgs56p.F,v 1.1.1.1 1996/04/01 15:02:14 mclareni Exp $ |
---|
693 | ! |
---|
694 | ! $Log: rgs56p.F,v $ |
---|
695 | ! Revision 1.1.1.1 1996/04/01 15:02:14 mclareni |
---|
696 | ! Mathlib gen |
---|
697 | ! |
---|
698 | ! |
---|
699 | subroutine rgs56p(f,a,b,res,err) |
---|
700 | implicit none |
---|
701 | integer i |
---|
702 | real err,res,b,a,f,w6,x6,w5,x5,rang,r1,hf |
---|
703 | double precision e5,e6 |
---|
704 | |
---|
705 | parameter (r1 = 1., hf = r1/2.) |
---|
706 | dimension x5(5),w5(5),x6(6),w6(6) |
---|
707 | |
---|
708 | data (x5(i),w5(i),i=1,5) & |
---|
709 | &/4.6910077030668004e-02, 1.1846344252809454e-01, & |
---|
710 | &2.3076534494715846e-01, 2.3931433524968324e-01, & |
---|
711 | &5.0000000000000000e-01, 2.8444444444444444e-01, & |
---|
712 | &7.6923465505284154e-01, 2.3931433524968324e-01, & |
---|
713 | &9.5308992296933200e-01, 1.1846344252809454e-01/ |
---|
714 | |
---|
715 | data (x6(i),w6(i),i=1,6) & |
---|
716 | &/3.3765242898423989e-02, 8.5662246189585178e-02, & |
---|
717 | &1.6939530676686775e-01, 1.8038078652406930e-01, & |
---|
718 | &3.8069040695840155e-01, 2.3395696728634552e-01, & |
---|
719 | &6.1930959304159845e-01, 2.3395696728634552e-01, & |
---|
720 | &8.3060469323313225e-01, 1.8038078652406930e-01, & |
---|
721 | &9.6623475710157601e-01, 8.5662246189585178e-02/ |
---|
722 | |
---|
723 | rang=b-a |
---|
724 | e5=0d0 |
---|
725 | e6=0d0 |
---|
726 | do 1 i = 1,5 |
---|
727 | e5=e5+w5(i)*f(a+rang*x5(i)) |
---|
728 | e6=e6+w6(i)*f(a+rang*x6(i)) |
---|
729 | 1 continue |
---|
730 | e6=e6+w6(6)*f(a+rang*x6(6)) |
---|
731 | res=hf*(e6+e5)*rang |
---|
732 | err=abs((e6-e5)*rang) |
---|
733 | return |
---|
734 | end |
---|
735 | !GRD |
---|
736 | |
---|
737 | |
---|
738 | !CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC |
---|
739 | !C |
---|
740 | !CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC |
---|
741 | subroutine funpct(func,ifunc,xlow,xhigh,xfcum,nlo,nbins,tftot, & |
---|
742 | &ierr) |
---|
743 | ! Array XFCUM is filled from NLO to NLO+NBINS, which makes |
---|
744 | ! the number of values NBINS+1, or the number of bins NBINS |
---|
745 | implicit none |
---|
746 | external func |
---|
747 | integer ierr,nbins,nlo,ifunc,nz,ibin,maxz,iz,nitmax,ihome |
---|
748 | real tftot,xhigh,xlow,func,xfcum,rteps,tpctil,tz,tzmax,x,f,tcum, & |
---|
749 | &x1,f1,dxmax,fmin,fminz,xincr,tincr,xbest,dtbest,tpart,x2,precis, & |
---|
750 | &refx,uncert,tpart2,dtpar2,dtabs,aberr |
---|
751 | dimension xfcum(*) |
---|
752 | parameter (rteps=0.005, nz=10, maxz=20, nitmax=6,precis=1e-6) |
---|
753 | ! DOUBLE PRECISION TPCTIL, TZ, TCUM, XINCR, DTABS, |
---|
754 | ! & TINCR, TZMAX, XBEST, DTBEST, DTPAR2 |
---|
755 | ! |
---|
756 | ierr = 0 |
---|
757 | if (tftot .le. 0.) go to 900 |
---|
758 | tpctil = tftot/nbins |
---|
759 | tz = tpctil/nz |
---|
760 | tzmax = tz * 2. |
---|
761 | xfcum(nlo) = xlow |
---|
762 | xfcum(nlo+nbins) = xhigh |
---|
763 | x = xlow |
---|
764 | f = func(x) |
---|
765 | if (f .lt. 0.) go to 900 |
---|
766 | ! Loop over percentile bins |
---|
767 | do 600 ibin = nlo, nlo+nbins-2 |
---|
768 | tcum = 0. |
---|
769 | x1 = x |
---|
770 | f1 = f |
---|
771 | dxmax = (xhigh -x) / nz |
---|
772 | fmin = tz/dxmax |
---|
773 | fminz = fmin |
---|
774 | ! Loop over trapezoids within a supposed percentil |
---|
775 | do 500 iz= 1, maxz |
---|
776 | xincr = tz/max(f1,fmin,fminz) |
---|
777 | 350 x = x1 + xincr |
---|
778 | f = func(x) |
---|
779 | if (f .lt. 0.) go to 900 |
---|
780 | tincr = (x-x1) * 0.5 * (f+f1) |
---|
781 | if (tincr .lt. tzmax) go to 370 |
---|
782 | xincr = xincr * 0.5 |
---|
783 | go to 350 |
---|
784 | 370 continue |
---|
785 | tcum = tcum + tincr |
---|
786 | if (tcum .ge. tpctil*0.99) go to 520 |
---|
787 | fminz = tz*f/ (tpctil-tcum) |
---|
788 | f1 = f |
---|
789 | x1 = x |
---|
790 | 500 continue |
---|
791 | write(*,*) ' FUNLUX: WARNING. FUNPCT fails trapezoid.' |
---|
792 | ! END OF TRAPEZOID LOOP |
---|
793 | ! Adjust interval using Gaussian integration with |
---|
794 | ! Newton corrections since F is the derivative |
---|
795 | 520 continue |
---|
796 | x1 = xfcum(ibin) |
---|
797 | xbest = x |
---|
798 | dtbest = tpctil |
---|
799 | tpart = tpctil |
---|
800 | ! Allow for maximum NITMAX more iterations on RADAPT |
---|
801 | do 550 ihome= 1, nitmax |
---|
802 | 535 xincr = (tpctil-tpart) / max(f,fmin) |
---|
803 | x = xbest + xincr |
---|
804 | x2 = x |
---|
805 | if (ihome .gt. 1 .and. x2 .eq. xbest) then |
---|
806 | write(*,'(A,G12.3)') & |
---|
807 | &' FUNLUX: WARNING from FUNPCT: insufficient precision at X=',x |
---|
808 | go to 580 |
---|
809 | endif |
---|
810 | refx = abs(x)+precis |
---|
811 | call radapt(func,x1,x2,1,rteps,0.,tpart2,uncert) |
---|
812 | dtpar2 = tpart2-tpctil |
---|
813 | dtabs = abs(dtpar2) |
---|
814 | if(abs(xincr)/refx .lt. precis) goto 545 |
---|
815 | if(dtabs .lt. dtbest) goto 545 |
---|
816 | xincr = xincr * 0.5 |
---|
817 | goto 535 |
---|
818 | 545 dtbest = dtabs |
---|
819 | xbest = x |
---|
820 | tpart = tpart2 |
---|
821 | f = func(x) |
---|
822 | if(f .lt. 0.) goto 900 |
---|
823 | if(dtabs .lt. rteps*tpctil) goto 580 |
---|
824 | 550 continue |
---|
825 | write(*,'(A,I4)') & |
---|
826 | &' FUNLUX: WARNING from FUNPCT: cannot converge, bin',ibin |
---|
827 | ! |
---|
828 | 580 continue |
---|
829 | xincr = (tpctil-tpart) / max(f,fmin) |
---|
830 | x = xbest + xincr |
---|
831 | xfcum(ibin+1) = x |
---|
832 | f = func(x) |
---|
833 | if(f .lt. 0.) goto 900 |
---|
834 | 600 continue |
---|
835 | ! END OF LOOP OVER BINS |
---|
836 | x1 = xfcum(nlo+nbins-1) |
---|
837 | x2 = xhigh |
---|
838 | call radapt(func,x1,x2,1,rteps,0.,tpart ,uncert) |
---|
839 | aberr = abs(tpart-tpctil)/tftot |
---|
840 | ! WRITE(6,1001) IFUNC,XLOW,XHIGH |
---|
841 | if(aberr .gt. rteps) write(*,1002) aberr |
---|
842 | return |
---|
843 | 900 write(*,1000) x,f |
---|
844 | ierr = 1 |
---|
845 | return |
---|
846 | 1000 format(/' FUNLUX fatal error in FUNPCT: function negative:'/ & |
---|
847 | &,' at X=',e15.6,', F=',e15.6/) |
---|
848 | ! 1001 FORMAT(' FUNPCT has prepared USER FUNCTION',I3, |
---|
849 | ! + ' between',G12.3,' and',G12.3,' for FUNLUX.') |
---|
850 | 1002 format(' WARNING: Relative error in cumulative distribution', & |
---|
851 | &' may be as big as',f10.7) |
---|
852 | end |
---|
853 | |
---|
854 | |
---|