You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3857 lines
146 KiB
FortranFixed

! INTMODULE contains the modules:
! - ADAPTMOD
! - RCRUDEMOD
! - KROBOVMOD
! - KRBVRCMOD
! - DKBVRCMOD
!
! which contains several different Multidimensional Integration Subroutines
!
! See descriptions below
!
* ADAPTMOD is a module containing a:
*
* Adaptive Multidimensional Integration Subroutine
*
* Author: Alan Genz
* Department of Mathematics
* Washington State University
* Pullman, WA 99164-3113 USA
*
* Revised pab 21.11.2000
* A bug found by Igor in dksmrc: VK was not correctly randomized
* is now fixed
* Revised pab 07.10.2000,
* 1) Removed LENWRK and WORK from input in ADAPT.
* 2) Defined LENWRK internally and Put a save statement before WORK instead
* 3) Bug fix in ADBASE: DIVAXN was undetermined when MINCLS<0. Solution:
* put a save statement on DIVAXN in order to save/keep its last value.
* 4) MAXDIM is now a global variable defining the maximum number of dimensions
* it is possible to integrate.
*
* revised pab 07.09.2000
* - solaris compiler complained on the DATA statements
* for the P and C matrices in the krbvrc and krobov routine
* => made separate DATA statements for P and C and moved them
* to right after the variable definitions.
* revised pab 10.03.2000
* - updated to f90 (i.e. changed to assumed shape arrays + changing integers to DBLE)
* - put it into a module
*
* This subroutine computes an approximation to the integral
*
* 1 1 1
* I I ... I FUNCTN(NDIM,X) dx(NDIM)...dx(2)dx(1)
* 0 0 0
*
*************** Parameters for SADAPT ********************************
*
********Input Parameters
*
* N INTEGER, the number of variables.
* MAXPTS INTEGER, maximum number of function values allowed. This
* parameter can be used to limit the time taken. A
* sensible strategy is to start with MAXPTS = 1000*N, and then
* increase MAXPTS if ERROR is too large.
* FUNCTN Externally declared real user defined integrand. Its
* parameters must be (N, Z), where Z is a real array of
* length N.
* ABSEPS REAL absolute error tolerance.
* RELEPS REAL relative error tolerance.
*
*******Output Parameters
*
* ERROR REAL estimated absolute error, with 99% confidence level.
* VALUE REAL estimated value for the integral
* INFORM INTEGER, termination status parameter:
* if INFORM = 0, normal completion with ERROR < EPS;
* if INFORM = 1, completion with ERROR > EPS and MAXPTS
* function vaules used; increase MAXPTS to
* decrease ERROR;
* if INFORM = 2, N > 20 or N < 1.
*
*************** Parameters for ADAPT ********************************
*
****** Input Parameters
*
* NDIM Integer number of integration variables.
* MINCLS Integer minimum number of FUNCTN calls to be allowed; MINCLS
* must not exceed MAXCLS. If MINCLS < 0, then ADAPT assumes
* that a previous call of ADAPT has been made with the same
* integrand and continues that calculation.
* MAXCLS Integer maximum number of FUNCTN calls to be used; MAXCLS
* must be >= RULCLS, the number of function calls required for
* one application of the basic integration rule.
* IF ( NDIM .EQ. 1 ) THEN
* RULCLS = 11
* ELSE IF ( NDIM .LT. 15 ) THEN
* RULCLS = 2**NDIM + 2*NDIM*(NDIM+3) + 1
* ELSE
* RULCLS = 1 + NDIM*(24-NDIM*(6-NDIM*4))/3
* ENDIF
* FUNCTN Externally declared real user defined integrand. Its
* parameters must be (NDIM, Z), where Z is a real array of
* length NDIM.
* ABSREQ Real required absolute accuracy.
* RELREQ Real required relative accuracy.
*
****** Output Parameters
*
* MINCLS Actual number of FUNCTN calls used by ADAPT.
* ABSEST Real estimated absolute accuracy.
* FINEST Real estimated value of integral.
* INFORM INFORM = 0 for normal exit, when ABSEST <= ABSREQ or
* ABSEST <= |FINEST|*RELREQ with MINCLS <= MAXCLS.
* INFORM = 1 if MAXCLS was too small for ADAPT to obtain the
* result FINEST to within the requested accuracy.
* INFORM = 2 if MINCLS > MAXCLS, LENWRK < 16*NDIM + 27 or
* RULCLS > MAXCLS.
*
*
*
* ADAPT revised by pab 07.10.2000,
* 1) Removed LENWRK and WORK from input.
* 2) Defined LENWRK internally and Put a save statement before WORK instead
*
* WORK Real array (length LENWRK) of working storage. This contains
* information that is needed for additional calls of ADAPT
* using the same integrand (input MINCLS < 0).
* LENWRK Integer length of real array WORK (working storage); ADAPT
* needs LENWRK >= 16*NDIM + 27. For maximum efficiency LENWRK
* should be about 2*NDIM*MAXCLS/RULCLS if MAXCLS FUNCTN
* calls are needed. If LENWRK is significantly less than this,
* ADAPT may be less efficient.
MODULE ADAPTMOD
IMPLICIT NONE
INTEGER,PRIVATE, PARAMETER :: MAXDIM=20
PRIVATE
PUBLIC :: ADAPT, SADAPT
INTERFACE SADAPT
MODULE PROCEDURE SADAPT
END INTERFACE
INTERFACE ADAPT
MODULE PROCEDURE ADAPT
END INTERFACE
INTERFACE ADBASE
MODULE PROCEDURE ADBASE
END INTERFACE
INTERFACE BSINIT
MODULE PROCEDURE BSINIT
END INTERFACE
INTERFACE RULNRM
MODULE PROCEDURE RULNRM
END INTERFACE
INTERFACE DIFFER
MODULE PROCEDURE DIFFER
END INTERFACE
INTERFACE BASRUL
MODULE PROCEDURE BASRUL
END INTERFACE
INTERFACE FULSUM
MODULE PROCEDURE FULSUM
END INTERFACE
INTERFACE TRESTR
MODULE PROCEDURE TRESTR
END INTERFACE
!--------------------------------
CONTAINS
!***********************************************************
! MAIN INTEGRATION ROUTINE SADAPT
!***********************************************************
SUBROUTINE SADAPT(N,MAXPTS,FUNCTN,ABSEPS,
& RELEPS,ERROR,VALUE,INFORM)
IMPLICIT NONE
*
* A subroutine for computing multivariate integrals
* This subroutine uses an algorithm given in the paper
* "Numerical Computation of Multivariate Normal Probabilities", in
* J. of Computational and Graphical Stat., 1(1992), pp. 141-149, by
* Alan Genz
* Department of Mathematics
* Washington State University
* Pullman, WA 99164-3113
* Email : alangenz@wsu.edu
*
* revised pab 15.03.2000
* - changed name from SADMVN to SADAPT
* - Made it general for any integral not just the multivariate normal integral
*
********Input Parameters
*
* N INTEGER, the number of variables.
* MAXPTS INTEGER, maximum number of function values allowed. This
* parameter can be used to limit the time taken. A
* sensible strategy is to start with MAXPTS = 1000*N, and then
* increase MAXPTS if ERROR is too large.
* FUNCTN Externally declared real user defined integrand. Its
* parameters must be (N, Z), where Z is a real array of
* length N.
* ABSEPS REAL absolute error tolerance.
* RELEPS REAL relative error tolerance.
*
*******Output Parameters
*
* ERROR REAL estimated absolute error, with 99% confidence level.
* VALUE REAL estimated value for the integral
* INFORM INTEGER, termination status parameter:
* if INFORM = 0, normal completion with ERROR < EPS;
* if INFORM = 1, completion with ERROR > EPS and MAXPTS
* function vaules used; increase MAXPTS to
* decrease ERROR;
* if INFORM = 2, N > 20 or N < 1.
*
INTEGER, INTENT(IN) :: N, MAXPTS
INTEGER, INTENT(OUT) :: INFORM
!INTEGER :: NL, LENWRK,
INTEGER :: RULCLS, TOTCLS, NEWCLS, MAXCLS
DOUBLE PRECISION, INTENT(IN) :: ABSEPS, RELEPS
DOUBLE PRECISION, INTENT(OUT) :: ERROR, VALUE
DOUBLE PRECISION :: OLDVAL
!PARAMETER ( NL = 20 )
!PARAMETER ( LENWRK = 20*NL**2 )
!DOUBLE PRECISION, DIMENSION(LENWRK) :: WORK
INTERFACE
DOUBLE PRECISION FUNCTION FUNCTN(N,Z)
DOUBLE PRECISION,DIMENSION(:), INTENT(IN) :: Z
INTEGER, INTENT(IN) :: N
END FUNCTION FUNCTN
END INTERFACE
IF ( N .GT. MAXDIM .OR. N .LT. 1 ) THEN
INFORM = 2
VALUE = 0.d0
ERROR = 1.d0
RETURN
ENDIF
INFORM = 1
*
* Call the subregion adaptive integration subroutine
*
RULCLS = 1
CALL ADAPT( N, RULCLS, 0, FUNCTN, ABSEPS, RELEPS,
& ERROR, VALUE, INFORM )
MAXCLS = MIN( 10*RULCLS, MAXPTS )
TOTCLS = 0
CALL ADAPT(N, TOTCLS, MAXCLS, FUNCTN, ABSEPS, RELEPS,
& ERROR, VALUE, INFORM)
IF ( ERROR .GT. MAX( ABSEPS, RELEPS*ABS(VALUE) ) ) THEN
10 OLDVAL = VALUE
MAXCLS = MAX( 2*RULCLS,MIN(INT(3*MAXCLS/2),MAXPTS-TOTCLS))
NEWCLS = -1
CALL ADAPT(N, NEWCLS, MAXCLS, FUNCTN, ABSEPS, RELEPS,
& ERROR, VALUE, INFORM)
TOTCLS = TOTCLS + NEWCLS
ERROR = ABS(VALUE-OLDVAL) +
& SQRT(DBLE(RULCLS)*ERROR**2/DBLE(TOTCLS))
IF ( ERROR .GT. MAX( ABSEPS, RELEPS*ABS(VALUE) ) ) THEN
IF ( MAXPTS - TOTCLS .GT. 2*RULCLS ) GO TO 10
ELSE
INFORM = 0
END IF
ENDIF
END SUBROUTINE SADAPT
!***********************************************************
! MAIN INTEGRATION ROUTINE ADAPT
!***********************************************************
SUBROUTINE ADAPT(NDIM, MINCLS, MAXCLS, FUNCTN,
& ABSREQ, RELREQ, ABSEST, FINEST, INFORM)
IMPLICIT NONE
*
* Adaptive Multidimensional Integration Subroutine
*
* Author: Alan Genz
* Department of Mathematics
* Washington State University
* Pullman, WA 99164-3113 USA
*
* This subroutine computes an approximation to the integral
*
* 1 1 1
* I I ... I FUNCTN(NDIM,X) dx(NDIM)...dx(2)dx(1)
* 0 0 0
*
*************** Parameters for ADAPT ********************************
*
****** Input Parameters
*
* NDIM Integer number of integration variables.
* MINCLS Integer minimum number of FUNCTN calls to be allowed; MINCLS
* must not exceed MAXCLS. If MINCLS < 0, then ADAPT assumes
* that a previous call of ADAPT has been made with the same
* integrand and continues that calculation.
* MAXCLS Integer maximum number of FUNCTN calls to be used; MAXCLS
* must be >= RULCLS, the number of function calls required for
* one application of the basic integration rule.
* IF ( NDIM .EQ. 1 ) THEN
* RULCLS = 11
* ELSE IF ( NDIM .LT. 15 ) THEN
* RULCLS = 2**NDIM + 2*NDIM*(NDIM+3) + 1
* ELSE
* RULCLS = 1 + NDIM*(24-NDIM*(6-NDIM*4))/3
* ENDIF
* FUNCTN Externally declared real user defined integrand. Its
* parameters must be (NDIM, Z), where Z is a real array of
* length NDIM.
* ABSREQ Real required absolute accuracy.
* RELREQ Real required relative accuracy.
*
****** Output Parameters
*
* MINCLS Actual number of FUNCTN calls used by ADAPT.
* ABSEST Real estimated absolute accuracy.
* FINEST Real estimated value of integral.
* INFORM INFORM = 0 for normal exit, when ABSEST <= ABSREQ or
* ABSEST <= |FINEST|*RELREQ with MINCLS <= MAXCLS.
* INFORM = 1 if MAXCLS was too small for ADAPT to obtain the
* result FINEST to within the requested accuracy.
* INFORM = 2 if MINCLS > MAXCLS, LENWRK < 16*NDIM + 27 or
* RULCLS > MAXCLS.
*
************************************************************************
*
* Begin driver routine. This routine partitions the working storage
* array and then calls the main subroutine ADBASE.
*
* Revised pab 07.10.2000,
* 1) Removed LENWRK and WORK from input.
* 2) Defined LENWRK internally and Put a save statement before WORK instead
*
* LENWRK Integer length of real array WORK (working storage); ADAPT
* needs LENWRK >= 16*NDIM + 27. For maximum efficiency LENWRK
* should be about 2*NDIM*MAXCLS/RULCLS if MAXCLS FUNCTN
* calls are needed. If LENWRK is significantly less than this,
* ADAPT may be less efficient.
*
* WORK Real array (length LENWRK) of working storage. This contains
* information that is needed for additional calls of ADAPT
* using the same integrand (input MINCLS < 0).
*
INTEGER, INTENT(IN) :: NDIM, MAXCLS
INTEGER, INTENT(INOUT) :: MINCLS
INTEGER, INTENT(OUT) :: INFORM
DOUBLE PRECISION, INTENT(IN) :: ABSREQ, RELREQ
DOUBLE PRECISION, INTENT(OUT) :: ABSEST, FINEST
* Local variables
INTEGER, PARAMETER :: LENWRK=20*MAXDIM*MAXDIM
DOUBLE PRECISION, DIMENSION(LENWRK) :: WORK ! length lenwrk
DOUBLE PRECISION, DIMENSION(:,:), ALLOCATABLE :: POINTS,WEGHTS,LUM
INTEGER :: SBRGNS, MXRGNS, RULCLS, LENRUL,
& INERRS, INVALS, INPTRS, INLWRS, INUPRS, INMSHS, INPNTS, INWGTS,
& INLOWR, INUPPR, INWDTH, INMESH, INWORK
INTERFACE
DOUBLE PRECISION FUNCTION FUNCTN(N,Z)
DOUBLE PRECISION,DIMENSION(:), INTENT(IN) :: Z
INTEGER, INTENT(IN) :: N
END FUNCTION FUNCTN
END INTERFACE
SAVE WORK
! print *,'adapt, ndim', ndim
IF ( NDIM .EQ. 1 ) THEN
LENRUL = 5
RULCLS = 9
ELSE IF ( NDIM .LT. 12 ) THEN
LENRUL = 6
RULCLS = 2**NDIM + 2*NDIM*(NDIM+2) + 1
ELSE
LENRUL = 6
! RULCLS = 1 + 2*NDIM*(1+2*NDIM) ! old call pab 15.03.2003
RULCLS = 1851 + 2*NDIM*(1+2*NDIM)
ENDIF
IF ( LENWRK .GE. LENRUL*(NDIM+4) + 10*NDIM + 3 .AND.
& RULCLS. LE. MAXCLS .AND. MINCLS .LE. MAXCLS ) THEN
MXRGNS = ( LENWRK - LENRUL*(NDIM+4) - 7*NDIM )/( 3*NDIM + 3 )
INERRS = 1
INVALS = INERRS + MXRGNS
INPTRS = INVALS + MXRGNS
INLWRS = INPTRS + MXRGNS
INUPRS = INLWRS + MXRGNS*NDIM
INMSHS = INUPRS + MXRGNS*NDIM
INWGTS = INMSHS + MXRGNS*NDIM
INPNTS = INWGTS + LENRUL*4
INLOWR = INPNTS + LENRUL*NDIM
INUPPR = INLOWR + NDIM
INWDTH = INUPPR + NDIM
INMESH = INWDTH + NDIM
INWORK = INMESH + NDIM
ALLOCATE(POINTS(NDIM,LENRUL))
ALLOCATE(WEGHTS(LENRUL,4))
ALLOCATE(LUM(NDIM,MXRGNS*3))
IF (MINCLS .LT. 0 ) THEN
SBRGNS = WORK(LENWRK)
LUM = reshape(WORK(INLWRS:INWGTS-1),(/ NDIM,MXRGNS*3/))
WEGHTS = reshape(WORK(INWGTS:INPNTS-1),(/ LENRUL , 4 /))
POINTS = reshape(WORK(INPNTS:INLOWR-1),(/ NDIM, LENRUL/))
!ELSE
! WORK=0.D0;LUM=0.D0;WEGHTS=0.D0;POINTS=0.D0
ENDIF
CALL ADBASE(NDIM, MINCLS, MAXCLS, FUNCTN, ABSREQ, RELREQ,
& ABSEST, FINEST, SBRGNS, MXRGNS, RULCLS, LENRUL,
& WORK(INERRS:INVALS-1), WORK(INVALS:INPTRS-1),
& WORK(INPTRS:INLWRS-1), LUM(:,1:MXRGNS),
& LUM(:,MXRGNS+1:2*MXRGNS),LUM(:,2*MXRGNS+1:3*MXRGNS),
& WEGHTS,POINTS,WORK(INLOWR:INUPPR-1),WORK(INUPPR:INWDTH-1),
& WORK(INWDTH:INMESH-1), WORK(INMESH:INWORK-1),
& WORK(INWORK:INWORK+2*NDIM-1), INFORM)
WORK(LENWRK) = SBRGNS
! LUM = LOWERS UPPERS MESHES
WORK(INLWRS:INWGTS-1) = reshape(LUM ,(/ NDIM*MXRGNS*3/))
WORK(INWGTS:INPNTS-1) = reshape(WEGHTS,(/ LENRUL*4 /))
WORK(INPNTS:INLOWR-1) = reshape(POINTS,(/ NDIM*LENRUL/))
DEALLOCATE(POINTS)
DEALLOCATE(WEGHTS)
DEALLOCATE(LUM)
ELSE
INFORM = 2
MINCLS = RULCLS
ENDIF
RETURN
END SUBROUTINE ADAPT
SUBROUTINE BSINIT(NDIM, W, LENRUL, G)
IMPLICIT NONE
*
* For initializing basic rule weights and symmetric sum parameters.
*
INTEGER, INTENT(IN) :: NDIM, LENRUL
DOUBLE PRECISION , DIMENSION(:,:), INTENT(OUT) :: W, G
* DOUBLE PRECISION W(LENRUL,4), G(NDIM,LENRUL)
* Local variables
INTEGER :: I, J
INTEGER, PARAMETER :: NUMNUL=4, SDIM=12
INTEGER, DIMENSION(6) :: RULPTS
DOUBLE PRECISION LAM1, LAM2, LAM3, LAM4, LAMP, RULCON
*
* The following code determines rule parameters and weights for a
* degree 7 rule (W(1,1),...,W(5,1)), two degree 5 comparison rules
* (W(1,2),...,W(5,2) and W(1,3),...,W(5,3)) and a degree 3
* comparison rule (W(1,4),...W(5,4)).
*
* If NDIM = 1, then LENRUL = 5 and total points = 9.
* If NDIM < SDIM, then LENRUL = 6 and
* total points = 1+2*NDIM*(NDIM+2)+2**NDIM.
* If NDIM > = SDIM, then LENRUL = 6 and
* total points = 1+2*NDIM*(1+2*NDIM).
*
! print *,'BSINIT, ndim', ndim
! DO I = 1,LENRUL
! DO J = 1,NDIM
! G(J,I) = 0.d0
! END DO
! DO J = 1,NUMNUL
! W(I,J) = 0.d0
! END DO
! END DO
G = 0.D0
W = 0.D0
I = 2*NDIM
RULPTS(5) = I*(NDIM-1)
RULPTS(4) = I
RULPTS(3) = I
RULPTS(2) = I
RULPTS(1) = 1
LAMP = 0.85d0
LAM3 = 0.4707d0
LAM2 = 4d0/(15.d0 - 5.d0/LAM3)
LAM4 = 1.D0/(27.D0*LAM3*LAM3*LAM3)
W(5,1) = ( 3.d0 - 5.d0*LAM3 )/( 180.d0*(LAM2-LAM3)*LAM2*LAM2)
IF ( NDIM .LT. SDIM ) THEN
RULPTS(LENRUL) = 2**NDIM
LAM1 = 8.d0*LAM3*(31.d0*LAM3-15.d0)/
& ( (3.d0*LAM3-1.d0)*(5.d0*LAM3-3.d0)*35.d0 )
W(LENRUL,1) = LAM4/DBLE(RULPTS(LENRUL))
ELSE
LAM1 = ( LAM3*(15.d0 - 21.d0*LAM2) +
& 35.d0*DBLE(NDIM-1)*(LAM2-LAM3)/9.d0 )
& / ( LAM3*(21.d0 - 35.d0*LAM2) +
& 35.d0*DBLE(NDIM-1)*(LAM2/LAM3-1.d0)/9.d0 )
W(6,1) = LAM4*0.25D0
RULPTS(6) = 2*NDIM*(NDIM-1)
ENDIF
W(3,1) = ( 15.d0 - 21.d0*(LAM3+LAM1) + 35.d0*LAM3*LAM1 )
& /(210.d0*LAM2*(LAM2-LAM3)*(LAM2-LAM1))-DBLE(2*(NDIM-1))*W(5,1)
W(2,1) = ( 15.d0 - 21.d0*(LAM3+LAM2) + 35.d0*LAM3*LAM2 )
& /( 210.d0*LAM1*(LAM1-LAM3)*(LAM1-LAM2) )
LAM3 = SQRT(LAM3)
IF ( NDIM .LT. SDIM ) THEN
G(1:NDIM,LENRUL) = LAM3
ELSE
G(1,6) = LAM3
G(2,6) = LAM3
ENDIF
IF ( NDIM .GT. 1 ) THEN
W(5,2) = 1.d0/(6.d0*LAM2)**2
W(5,3) = W(5,2)
ENDIF
W(3,2) = ( 3.d0 - 5.d0*LAM1 )/( 30.d0*LAM2*(LAM2-LAM1) )
& - DBLE(2*(NDIM-1))*W(5,2)
W(2,2) = ( 3.d0 - 5.d0*LAM2 )/( 30.d0*LAM1*(LAM1-LAM2) )
W(4,3) = ( 3.d0 - 5.d0*LAM2 )/( 30.d0*LAMP*(LAMP-LAM2) )
W(3,3) = ( 3.d0 - 5.d0*LAMP )/( 30.d0*LAM2*(LAM2-LAMP) )
& - DBLE(2*(NDIM-1))*W(5,3)
W(2,4) = 1.d0/(6.d0*LAM1)
LAMP = SQRT(LAMP)
LAM2 = SQRT(LAM2)
LAM1 = SQRT(LAM1)
G(1,2) = LAM1
G(1,3) = LAM2
G(1,4) = LAMP
IF ( NDIM .GT. 1 ) THEN
G(1,5) = LAM2
G(2,5) = LAM2
ENDIF
DO J = 1, NUMNUL
W(1,J) = 1.d0
DO I = 2,LENRUL
W(1,J) = W(1,J) - DBLE(RULPTS(I))*W(I,J)
END DO
END DO
RULCON = 0.5d0
CALL RULNRM( LENRUL, NUMNUL, RULPTS, W, RULCON )
END SUBROUTINE BSINIT
!
!
SUBROUTINE RULNRM( LENRUL, NUMNUL, RULPTS, W, RULCON )
IMPLICIT NONE
INTEGER, INTENT(IN) :: LENRUL, NUMNUL
INTEGER, DIMENSION(:), INTENT(IN) :: RULPTS
DOUBLE PRECISION, DIMENSION(:,:), INTENT(INOUT) :: W !(LENRUL, *),
DOUBLE PRECISION, INTENT(IN) :: RULCON
* Local variables
INTEGER :: I, J, K
DOUBLE PRECISION :: ALPHA, NORMCF, NORMNL
*
* Compute orthonormalized null rules.
*
! print *,'RULNRM, lenrul, numnul', lenrul,NUMNUL
NORMCF = 0.d0
DO I = 1,LENRUL
NORMCF = NORMCF + DBLE(RULPTS(I))*W(I,1)*W(I,1)
END DO
DO K = 2,NUMNUL
DO I = 1,LENRUL
W(I,K) = W(I,K) - W(I,1)
END DO
DO J = 2,K-1
ALPHA = 0.d0
DO I = 1,LENRUL
ALPHA = ALPHA + DBLE(RULPTS(I))*W(I,J)*W(I,K)
END DO
ALPHA = -ALPHA/NORMCF
DO I = 1,LENRUL
W(I,K) = W(I,K) + ALPHA*W(I,J)
END DO
END DO
NORMNL = 0.d0
DO I = 1,LENRUL
NORMNL = NORMNL + DBLE(RULPTS(I))*W(I,K)*W(I,K)
END DO
ALPHA = SQRT(NORMCF/NORMNL)
DO I = 1,LENRUL
W(I,K) = ALPHA*W(I,K)
END DO
END DO
DO J = 2, NUMNUL
DO I = 1,LENRUL
W(I,J) = W(I,J)*RULCON
END DO
END DO
RETURN
END SUBROUTINE RULNRM
!
!
SUBROUTINE ADBASE(NDIM, MINCLS, MAXCLS, FUNCTN, ABSREQ, RELREQ,
& ABSEST, FINEST, SBRGNS, MXRGNS, RULCLS, LENRUL,
& ERRORS, VALUES, PONTRS, LOWERS,
& UPPERS, MESHES, WEGHTS, POINTS,
& LOWER, UPPER, WIDTH, MESH, WORK, INFORM)
IMPLICIT NONE
*
* Main adaptive integration subroutine
*
INTEGER,INTENT(IN) :: NDIM, MAXCLS, MXRGNS,LENRUL, RULCLS
INTEGER, INTENT(INOUT) :: MINCLS, SBRGNS
INTEGER, INTENT(OUT) :: INFORM
DOUBLE PRECISION, INTENT(IN) :: ABSREQ, RELREQ
DOUBLE PRECISION, INTENT(OUT) :: ABSEST, FINEST
DOUBLE PRECISION, DIMENSION(:), INTENT(INOUT) :: ERRORS, VALUES,
& PONTRS, LOWER, UPPER, WIDTH, MESH, WORK
DOUBLE PRECISION, DIMENSION(:,:), INTENT(INOUT) :: WEGHTS, POINTS
! shape (LENRUL,4) and (NDIM,LENRUL)
DOUBLE PRECISION, DIMENSION(:,:), INTENT(INOUT) :: LOWERS, UPPERS,
& MESHES !SHAPE (NDIM,MXRGNS),
INTEGER :: I, J,NWRGNS, DIVAXN, TOP, RGNCLS, FUNCLS, DIFCLS
INTERFACE
DOUBLE PRECISION FUNCTION FUNCTN(N,Z)
DOUBLE PRECISION,DIMENSION(:), INTENT(IN) :: Z
INTEGER, INTENT(IN) :: N
END FUNCTION FUNCTN
END INTERFACE
*
* Initialization of subroutine
*
! print *,'ADBASE, ndim', ndim, shape(POINTS)
SAVE DIVAXN ! added pab 07.11.2000 (divaxn may have negative values otherwise)
INFORM = 2
FUNCLS = 0
CALL BSINIT(NDIM, WEGHTS, LENRUL, POINTS)
IF ( MINCLS .GE. 0) THEN
*
* When MINCLS >= 0 determine initial subdivision of the
* integration region and apply basic rule to each subregion.
*
SBRGNS = 0
DO I = 1,NDIM
LOWER(I) = 0.d0
MESH(I) = 1.d0
WIDTH(I) = 1.d0/(2.d0*MESH(I))
UPPER(I) = 1.d0
END DO
DIVAXN = 0
RGNCLS = RULCLS
NWRGNS = 1
10 CONTINUE
!IF (abs(DIVAXN).GT.NDIM) PRINT *,'adbase DIVAXN1',DIVAXN
CALL DIFFER(NDIM, LOWER, UPPER, WIDTH, WORK(1:NDIM),
& WORK(NDIM+1:2*NDIM), FUNCTN, DIVAXN, DIFCLS)
FUNCLS = FUNCLS + DIFCLS
IF (DBLE(RGNCLS)*(MESH(DIVAXN)+1.d0)/MESH(DIVAXN)
& .LE. DBLE(MINCLS-FUNCLS) ) THEN
RGNCLS = NINT(DBLE(RGNCLS)*(MESH(DIVAXN)+1.d0)/MESH(DIVAXN))
NWRGNS = NINT(DBLE(NWRGNS)*(MESH(DIVAXN)+1.d0)/MESH(DIVAXN))
MESH(DIVAXN) = MESH(DIVAXN) + 1.d0
WIDTH(DIVAXN) = 1.d0/( 2.d0*MESH(DIVAXN) )
GO TO 10
ENDIF
IF ( NWRGNS .LE. MXRGNS ) THEN
DO I = 1,NDIM
UPPER(I) = LOWER(I) + 2.d0*WIDTH(I)
MESH(I) = 1.d0
END DO
ENDIF
*
* Apply basic rule to subregions and store results in heap.
*
20 SBRGNS = SBRGNS + 1
CALL BASRUL(NDIM, LOWER, UPPER, WIDTH, FUNCTN,
& WEGHTS, LENRUL, POINTS, WORK(1:NDIM), WORK(NDIM+1:2*NDIM),
& ERRORS(SBRGNS),VALUES(SBRGNS))
CALL TRESTR(SBRGNS, SBRGNS, PONTRS, ERRORS)
DO I = 1,NDIM
LOWERS(I,SBRGNS) = LOWER(I)
UPPERS(I,SBRGNS) = UPPER(I)
MESHES(I,SBRGNS) = MESH(I)
END DO
DO I = 1,NDIM
LOWER(I) = UPPER(I)
UPPER(I) = LOWER(I) + 2.d0*WIDTH(I)
IF (LOWER(I)+WIDTH(I) .LT. 1.D0) GO TO 20
LOWER(I) = 0.d0
UPPER(I) = LOWER(I) + 2.d0*WIDTH(I)
END DO
FUNCLS = FUNCLS + SBRGNS*RULCLS
ENDIF
*
* Check for termination
*
30 FINEST = 0.d0
ABSEST = 0.d0
DO I = 1, SBRGNS
FINEST = FINEST + VALUES(I)
ABSEST = ABSEST + ERRORS(I)
END DO
IF ( ABSEST .GT. MAX( ABSREQ, RELREQ*ABS(FINEST) )
& .OR. FUNCLS .LT. MINCLS ) THEN
*
* Prepare to apply basic rule in (parts of) subregion with
* largest error.
*
TOP = PONTRS(1)
RGNCLS = RULCLS
DO I = 1,NDIM
LOWER(I) = LOWERS(I,TOP)
UPPER(I) = UPPERS(I,TOP)
MESH(I) = MESHES(I,TOP)
WIDTH(I) = (UPPER(I)-LOWER(I))/(2.D0*MESH(I))
RGNCLS = NINT(DBLE(RGNCLS)*MESH(I))
END DO
!IF (abs(DIVAXN).GT.NDIM) PRINT *,'adbase DIVAXN2',DIVAXN
CALL DIFFER(NDIM, LOWER, UPPER, WIDTH, WORK(1:NDIM),
& WORK(NDIM+1:2*NDIM), FUNCTN, DIVAXN, DIFCLS)
FUNCLS = FUNCLS + DIFCLS
RGNCLS = NINT(DBLE(RGNCLS)*(MESH(DIVAXN)+1.D0))/MESH(DIVAXN)
IF ( FUNCLS + RGNCLS .LE. MAXCLS ) THEN
IF ( SBRGNS + 1 .LE. MXRGNS ) THEN
*
* Prepare to subdivide into two pieces.
*
NWRGNS = 1
WIDTH(DIVAXN) = 0.5d0*WIDTH(DIVAXN)
ELSE
NWRGNS = 0
WIDTH(DIVAXN) = WIDTH(DIVAXN)
& *MESH(DIVAXN)/( MESH(DIVAXN) + 1.d0 )
MESHES(DIVAXN,TOP) = MESH(DIVAXN) + 1.d0
ENDIF
IF ( NWRGNS .GT. 0 ) THEN
*
* Only allow local subdivision when space is available.
*
DO J = SBRGNS+1,SBRGNS+NWRGNS
DO I = 1,NDIM
LOWERS(I,J) = LOWER(I)
UPPERS(I,J) = UPPER(I)
MESHES(I,J) = MESH(I)
END DO
END DO
UPPERS(DIVAXN,TOP) = LOWER(DIVAXN) + 2.d0*WIDTH(DIVAXN)
LOWERS(DIVAXN,SBRGNS+1) = UPPERS(DIVAXN,TOP)
ENDIF
FUNCLS = FUNCLS + RGNCLS
CALL BASRUL(NDIM, LOWERS(:,TOP), UPPERS(:,TOP), WIDTH,
& FUNCTN, WEGHTS, LENRUL, POINTS, WORK(1:NDIM),
& WORK(NDIM+1:2*NDIM),ERRORS(TOP), VALUES(TOP))
CALL TRESTR(TOP, SBRGNS, PONTRS, ERRORS)
DO I = SBRGNS+1, SBRGNS+NWRGNS
*
* Apply basic rule and store results in heap.
*
CALL BASRUL(NDIM, LOWERS(:,I), UPPERS(:,I), WIDTH,
& FUNCTN, WEGHTS, LENRUL, POINTS, WORK(1:NDIM),
& WORK(NDIM+1:2*NDIM),ERRORS(I), VALUES(I))
CALL TRESTR(I, I, PONTRS, ERRORS)
END DO
SBRGNS = SBRGNS + NWRGNS
GO TO 30
ELSE
INFORM = 1
ENDIF
ELSE
INFORM = 0
ENDIF
MINCLS = FUNCLS
RETURN
END SUBROUTINE ADBASE
SUBROUTINE BASRUL( NDIM, A, B, WIDTH, FUNCTN, W, LENRUL, G,
& CENTER, Z, RGNERT, BASEST )
IMPLICIT NONE
*
* For application of basic integration rule
*
INTEGER, INTENT(IN) :: LENRUL, NDIM
DOUBLE PRECISION, DIMENSION(: ), INTENT(IN) :: A, B, WIDTH !(NDIM)
DOUBLE PRECISION, DIMENSION(:,:), INTENT(IN) :: W !(LENRUL,4),
DOUBLE PRECISION, DIMENSION(:,:), INTENT(INOUT) :: G !(NDIM,LENRUL),
DOUBLE PRECISION, DIMENSION(: ), INTENT(INOUT) :: CENTER, Z !(NDIM)
DOUBLE PRECISION, INTENT(OUT) :: RGNERT, BASEST
INTEGER :: I
DOUBLE PRECISION :: FSYMSM, RGNCMP, RGNVAL,
& RGNVOL, RGNCPT, RGNERR
INTERFACE
DOUBLE PRECISION FUNCTION FUNCTN(N,Z)
DOUBLE PRECISION,DIMENSION(:), INTENT(IN) :: Z
INTEGER, INTENT(IN) :: N
END FUNCTION FUNCTN
END INTERFACE
*
* Compute Volume and Center of Subregion
*
! print *,'BASRULE, ndim', ndim
RGNVOL = 1.d0
DO I = 1,NDIM
RGNVOL = 2.d0*RGNVOL*WIDTH(I)
CENTER(I) = A(I) + WIDTH(I)
END DO
BASEST = 0.d0
RGNERT = 0.d0
*
* Compute basic rule and error
*
10 RGNVAL = 0.d0
RGNERR = 0.d0
RGNCMP = 0.d0
RGNCPT = 0.d0
DO I = 1,LENRUL
FSYMSM = FULSUM(NDIM, CENTER, WIDTH, Z, G(:,I), FUNCTN)
* Basic Rule
RGNVAL = RGNVAL + W(I,1)*FSYMSM
* First comparison rule
RGNERR = RGNERR + W(I,2)*FSYMSM
* Second comparison rule
RGNCMP = RGNCMP + W(I,3)*FSYMSM
* Third Comparison rule
RGNCPT = RGNCPT + W(I,4)*FSYMSM
END DO
*
* Error estimation
*
RGNERR = SQRT(RGNCMP*RGNCMP + RGNERR*RGNERR)
RGNCMP = SQRT(RGNCPT*RGNCPT + RGNCMP*RGNCMP)
IF ( 4.d0*RGNERR .LT. RGNCMP ) RGNERR = 0.5d0*RGNERR
IF ( 2.d0*RGNERR .GT. RGNCMP ) RGNERR = MAX( RGNERR, RGNCMP )
RGNERT = RGNERT + RGNVOL*RGNERR
BASEST = BASEST + RGNVOL*RGNVAL
*
* When subregion has more than one piece, determine next piece and
* loop back to apply basic rule.
*
DO I = 1,NDIM
CENTER(I) = CENTER(I) + 2.d0*WIDTH(I)
IF ( CENTER(I) .LT. B(I) ) GO TO 10
CENTER(I) = A(I) + WIDTH(I)
END DO
RETURN
END SUBROUTINE BASRUL
DOUBLE PRECISION FUNCTION FULSUM(S, CENTER, HWIDTH, X, G, F)
IMPLICIT NONE
*
**** To compute fully symmetric basic rule sum
*
INTEGER, INTENT(IN) :: S
DOUBLE PRECISION, DIMENSION(:), INTENT(IN) :: CENTER, HWIDTH
DOUBLE PRECISION, DIMENSION(:), INTENT(INOUT) :: X, G ! shape S
INTEGER :: IXCHNG, LXCHNG, I, L
DOUBLE PRECISION :: INTSUM, GL, GI
INTERFACE
DOUBLE PRECISION FUNCTION F(N,Z)
DOUBLE PRECISION,DIMENSION(:), INTENT(IN) :: Z
INTEGER, INTENT(IN) :: N
END FUNCTION F
END INTERFACE
! print *,'FULSUM, S', S, shape(X)
FULSUM = 0.d0
*
* Compute centrally symmetric sum for permutation of G
*
10 INTSUM = 0.d0
!DO I = 1,S
! X(I) = CENTER(I) + G(I)*HWIDTH(I)
!END DO
X = CENTER + G*HWIDTH
20 INTSUM = INTSUM + F(S,X)
DO I = 1,S
G(I) = -G(I)
X(I) = CENTER(I) + G(I)*HWIDTH(I)
IF ( G(I) .LT. 0.d0 ) GO TO 20
END DO
FULSUM = FULSUM + INTSUM
*
* Find next distinct permuation of G and loop back for next sum
*
DO I = 2,S
IF ( G(I-1) .GT. G(I) ) THEN
GI = G(I)
IXCHNG = I - 1
DO L = 1,(I-1)/2
GL = G(L)
G(L) = G(I-L)
G(I-L) = GL
IF ( GL .LE. GI ) IXCHNG = IXCHNG - 1
IF ( G(L) .GT. GI ) LXCHNG = L
END DO
IF ( G(IXCHNG) .LE. GI ) IXCHNG = LXCHNG
G(I) = G(IXCHNG)
G(IXCHNG) = GI
GO TO 10
ENDIF
END DO
*
* End loop for permutations of G and associated sums
*
* Restore original order to G's
*
DO I = 1,S/2
GI = G(I)
G(I) = G(S+1-I)
G(S+1-I) = GI
END DO
RETURN
END FUNCTION FULSUM
SUBROUTINE DIFFER(NDIM, A, B, WIDTH, Z, DIF, FUNCTN,
& DIVAXN, DIFCLS)
IMPLICIT NONE
*
* Compute fourth differences and subdivision axes
*
INTEGER, INTENT(IN) :: NDIM
INTEGER, INTENT(INOUT) :: DIVAXN
INTEGER, INTENT(OUT) :: DIFCLS
DOUBLE PRECISION, DIMENSION(:), INTENT(IN) :: A, B, WIDTH ! (NDIM)
DOUBLE PRECISION, DIMENSION(:),INTENT(OUT) :: Z, DIF ! (NDIM)
DOUBLE PRECISION :: FRTHDF, FUNCEN, WIDTHI
INTEGER :: I
INTERFACE
DOUBLE PRECISION FUNCTION FUNCTN(N,Z)
DOUBLE PRECISION,DIMENSION(:), INTENT(IN) :: Z
INTEGER, INTENT(IN) :: N
END FUNCTION FUNCTN
END INTERFACE
! print *,'DIFFER, ndim', ndim, shape(Z)
DIFCLS = 0
! IF (abs(DIVAXN).GT.NDIM) PRINT *,'DIFFER DIVAXN1',DIVAXN
DIVAXN = MOD(DIVAXN, NDIM ) + 1
!print *,'DIFFER, divaxn2', divaxn
IF ( NDIM .GT. 1 ) THEN
!DO I = 1,NDIM
! DIF(I) = 0.d0
! Z(I) = A(I) + WIDTH(I)
!END DO
DIF = 0.D0
Z(1:NDIM) = A(1:NDIM) + WIDTH(1:NDIM)
! print *,'Z', Z
10 FUNCEN = FUNCTN(NDIM, Z)
DO I = 1,NDIM
WIDTHI = 0.2d0*WIDTH(I)
FRTHDF = 6.d0*FUNCEN
Z(I) = Z(I) - 4.d0*WIDTHI
FRTHDF = FRTHDF + FUNCTN(NDIM,Z)
Z(I) = Z(I) + 2.d0*WIDTHI
FRTHDF = FRTHDF - 4.d0*FUNCTN(NDIM,Z)
Z(I) = Z(I) + 4.d0*WIDTHI
FRTHDF = FRTHDF - 4.d0*FUNCTN(NDIM,Z)
Z(I) = Z(I) + 2.d0*WIDTHI
FRTHDF = FRTHDF + FUNCTN(NDIM,Z)
* Do not include differences below roundoff
! IF ( FUNCEN + FRTHDF/8.d0 .NE. FUNCEN )
IF ( FUNCEN + FRTHDF*0.125D0 .NE. FUNCEN )
& DIF(I) = DIF(I) + ABS(FRTHDF)*WIDTH(I)
Z(I) = Z(I) - 4.d0*WIDTHI
END DO
DIFCLS = DIFCLS + 4*NDIM + 1
DO I = 1,NDIM
Z(I) = Z(I) + 2.D0*WIDTH(I)
IF ( Z(I) .LT. B(I) ) GO TO 10
Z(I) = A(I) + WIDTH(I)
END DO
!IF (abs(DIVAXN).GT.NDIM) PRINT *,'DIFFER DIVAXN',DIVAXN,shape(dif),ndim
DO I = 1,NDIM
IF ( DIF(DIVAXN) .LT. DIF(I) ) DIVAXN = I
END DO
ENDIF
RETURN
END SUBROUTINE DIFFER
SUBROUTINE TRESTR(POINTR, SBRGNS, PONTRS, RGNERS)
IMPLICIT NONE
****BEGIN PROLOGUE TRESTR
****PURPOSE TRESTR maintains a heap for subregions.
****DESCRIPTION TRESTR maintains a heap for subregions.
* The subregions are ordered according to the size of the
* greatest error estimates of each subregion (RGNERS).
*
* PARAMETERS
*
* POINTR Integer.
* The index for the subregion to be inserted in the heap.
* SBRGNS Integer.
* Number of subregions in the heap.
* PONTRS Real array of dimension SBRGNS.
* Used to store the indices for the greatest estimated errors
* for each subregion.
* RGNERS Real array of dimension SBRGNS.
* Used to store the greatest estimated errors for each
* subregion.
*
****ROUTINES CALLED NONE
****END PROLOGUE TRESTR
*
* Global variables.
*
INTEGER, INTENT(IN) ::POINTR, SBRGNS
DOUBLE PRECISION, DIMENSION(:), INTENT(INOUT) :: PONTRS
DOUBLE PRECISION, DIMENSION(:), INTENT(IN) :: RGNERS
*
* Local variables.
*
* RGNERR Intermediate storage for the greatest error of a subregion.
* SUBRGN Position of child/parent subregion in the heap.
* SUBTMP Position of parent/child subregion in the heap.
*
INTEGER SUBRGN, SUBTMP
DOUBLE PRECISION RGNERR
*
****FIRST PROCESSING STATEMENT TRESTR
*
! print *,'TRESTR'
RGNERR = RGNERS(POINTR)
IF ( POINTR.EQ.NINT(PONTRS(1))) THEN
*
* Move the new subregion inserted at the top of the heap
* to its correct position in the heap.
*
SUBRGN = 1
10 SUBTMP = 2*SUBRGN
IF ( SUBTMP .LE. SBRGNS ) THEN
IF ( SUBTMP .NE. SBRGNS ) THEN
*
* Find maximum of left and right child.
*
IF ( RGNERS(NINT(PONTRS(SUBTMP))) .LT.
& RGNERS(NINT(PONTRS(SUBTMP+1))) ) SUBTMP = SUBTMP + 1
ENDIF
*
* Compare maximum child with parent.
* If parent is maximum, then done.
*
IF ( RGNERR .LT. RGNERS(NINT(PONTRS(SUBTMP))) ) THEN
*
* Move the pointer at position subtmp up the heap.
*
PONTRS(SUBRGN) = PONTRS(SUBTMP)
SUBRGN = SUBTMP
GO TO 10
ENDIF
ENDIF
ELSE
*
* Insert new subregion in the heap.
*
SUBRGN = SBRGNS
20 SUBTMP = SUBRGN/2
IF ( SUBTMP .GE. 1 ) THEN
*
* Compare child with parent. If parent is maximum, then done.
*
IF ( RGNERR .GT. RGNERS(NINT(PONTRS(SUBTMP))) ) THEN
*
* Move the pointer at position subtmp down the heap.
*
PONTRS(SUBRGN) = PONTRS(SUBTMP)
SUBRGN = SUBTMP
GO TO 20
ENDIF
ENDIF
ENDIF
PONTRS(SUBRGN) = DBLE(POINTR)
*
****END TRESTR
*
RETURN
END SUBROUTINE TRESTR
END MODULE ADAPTMOD
* RCRUDEMOD is a module containing two:
*
* Automatic Multidimensional Integration Subroutines
*
* AUTHOR: Alan Genz
* Department of Mathematics
* Washington State University
* Pulman, WA 99164-3113
* Email: AlanGenz@wsu.edu
*
* Last Change: 5/15/98
* revised pab 10.03.2000
* - updated to f90 (i.e. changed to assumed shape arrays + changing integers to DBLE)
* - put it into a module
* - added ranlhmc
*
* RCRUDEMOD computes an approximation to the integral
*
* 1 1 1
* I I ... I F(X) dx(NDIM)...dx(2)dx(1)
* 0 0 0
! References:
! Alan Genz (1992)
! 'Numerical Computation of Multivariate Normal Probabilites'
! J. computational Graphical Statistics, Vol.1, pp 141--149 (RANMC)
!
! William H. Press, Saul Teukolsky,
! William T. Wetterling and Brian P. Flannery (1997)
! "Numerical recipes in Fortran 77", Vol. 1, pp 55-63 (SVDCMP,PYTHAG)
!
! Donald E. Knuth (1973) "The art of computer programming,",
! Vol. 3, pp 84- (sorting and searching) (SORTRE)
! You may initialize the random generator before you
! call RANLHMC or RANMC by the following lines:
!
! call random_seed(SIZE=seed_size)
! allocate(seed(seed_size))
! call random_seed(GET=seed(1:seed_size)) ! get current seed
! seed(1)=seed1 ! change seed
! call random_seed(PUT=seed(1:seed_size))
! deallocate(seed)
MODULE RCRUDEMOD
IMPLICIT NONE
PRIVATE
PUBLIC :: RANMC
INTEGER :: NDIMMAX
INTERFACE RANMC
MODULE PROCEDURE RANMC
END INTERFACE
INTERFACE RCRUDE
MODULE PROCEDURE RCRUDE
END INTERFACE
INTERFACE SVDCMP
MODULE PROCEDURE SVDCMP
END INTERFACE
INTERFACE PYTHAG
MODULE PROCEDURE PYTHAG
END INTERFACE
INTERFACE SPEARCORR
MODULE PROCEDURE SPEARCORR
END INTERFACE
INTERFACE SORTRE
MODULE PROCEDURE SORTRE
END INTERFACE
INTERFACE BINSORT
MODULE PROCEDURE BINSORT
END INTERFACE
INTERFACE SWAPRE
MODULE PROCEDURE SWAPRE
END INTERFACE
INTERFACE SWAPINT
MODULE PROCEDURE SWAPINT
END INTERFACE
PARAMETER (NDIMMAX=1000)
!--------------------------------
CONTAINS
SUBROUTINE RANMC( N, MAXPTS, FUNCTN, ABSEPS,
& RELEPS, ERROR, VALUE, INFORM )
IMPLICIT NONE
*
* A subroutine for computing multivariate integrals.
* This subroutine uses the Monte-Carlo algorithm given in the paper
* "Numerical Computation of Multivariate Normal Probabilities", in
* J. of Computational and Graphical Stat., 1(1992), pp. 141-149, by
* Alan Genz
* Department of Mathematics
* Washington State University
* Pullman, WA 99164-3113
* Email : alangenz@wsu.edu
*
* This subroutine computes an approximation to the integral
*
* 1 1 1
* I I ... I FUNCTN(NDIM,X) dx(NDIM)...dx(2)dx(1)
* 0 0 0
*
*************** Parameters for RANMC ********************************
*
****** Input Parameters
*
* N INTEGER, the number of variables.
* MAXPTS INTEGER, maximum number of function values allowed. This
* parameter can be used to limit the time taken. A
* sensible strategy is to start with MAXPTS = 1000*N, and then
* increase MAXPTS if ERROR is too large.
* ABSEPS REAL absolute error tolerance.
* RELEPS REAL relative error tolerance.
*
****** Output Parameters
*
* ERROR REAL estimated absolute error, with 99% confidence level.
* VALUE REAL estimated value for the integral
* INFORM INTEGER, termination status parameter:
* if INFORM = 0, normal completion with ERROR < EPS;
* if INFORM = 1, completion with ERROR > EPS and MAXPTS
* function vaules used; increase MAXPTS to
* decrease ERROR;
* if INFORM = 2, N > 100 or N < 1.
*
INTEGER :: N, MAXPTS, MPT, INFORM, IVLS
DOUBLE PRECISION :: ABSEPS, RELEPS, ERROR, VALUE, EPS
INTERFACE
DOUBLE PRECISION FUNCTION FUNCTN(N,Z)
DOUBLE PRECISION,DIMENSION(:), INTENT(IN) :: Z
INTEGER, INTENT(IN) :: N
END FUNCTION FUNCTN
END INTERFACE
INFORM=0
IF ( N .GT. NDIMMAX .OR. N .LT. 1 ) THEN
INFORM = 2
VALUE = 0.d0
ERROR = 1.d0
RETURN
ENDIF
*
* Call then Monte-Carlo integration subroutine
*
MPT = 25 + 10*N
CALL RCRUDE(N, MPT, FUNCTN, ERROR, VALUE, 0)
IVLS = MPT
10 EPS = MAX( ABSEPS, RELEPS*ABS(VALUE) )
IF ( ERROR .GT. EPS .AND. IVLS .LT. MAXPTS ) THEN
MPT = MAX( MIN( INT(MPT*(ERROR/(EPS))**2),
& MAXPTS-IVLS ), 10 )
CALL RCRUDE(N, MPT, FUNCTN, ERROR, VALUE, 1)
IVLS = IVLS + MPT
GO TO 10
ENDIF
IF ( ERROR. GT. EPS .AND. IVLS .GE. MAXPTS ) INFORM = 1
!IF (INFORM.EQ.1) print *,'ranmc eps',EPS
END SUBROUTINE RANMC
SUBROUTINE RCRUDE(NDIM, MAXPTS, FUNCTN, ABSEST, FINEST, IR)
IMPLICIT NONE
*
* Crude Monte-Carlo Algorithm with simple antithetic variates
* and weighted results on restart
*
INTEGER :: NDIM, MAXPTS, M, IR, NPTS
DOUBLE PRECISION :: FINEST, ABSEST, FUN,
& VARSQR, VAREST, VARPRD, FINDIF, FINVAL
DOUBLE PRECISION, DIMENSION(NDIMMAX) :: X
INTERFACE
DOUBLE PRECISION FUNCTION FUNCTN(N,Z)
DOUBLE PRECISION,DIMENSION(:), INTENT(IN) :: Z
INTEGER, INTENT(IN) :: N
END FUNCTION FUNCTN
END INTERFACE
SAVE VAREST
IF ( IR .LE. 0 ) THEN
VAREST = 0.d0
FINEST = 0.d0
ENDIF
FINVAL = 0.d0
VARSQR = 0.d0
NPTS = INT(MAXPTS/2)
DO M = 1,NPTS
CALL random_number(X(1:NDIM))
FUN = FUNCTN(NDIM, X(1:NDIM))
X(1:NDIM) = 1.d0 - X(1:NDIM)
FUN = (FUNCTN(NDIM, X(1:NDIM)) + FUN )*0.5d0
FINDIF = ( FUN - FINVAL )/DBLE(M)
VARSQR = DBLE( M - 2 )*VARSQR/DBLE(M) + FINDIF*FINDIF
FINVAL = FINVAL + FINDIF
END DO
VARPRD = VAREST*VARSQR
FINEST = FINEST + ( FINVAL - FINEST )/(1.d0 + VARPRD)
IF ( VARSQR .GT. 0 ) VAREST = (1.d0 + VARPRD)/VARSQR
ABSEST = 3.d0*SQRT( VARSQR/( 1.d0 + VARPRD ) )
MAXPTS=2*NPTS
END SUBROUTINE RCRUDE
SUBROUTINE BINSORT(indices,rarray)
IMPLICIT NONE
TYPE ENTRY
DOUBLE PRECISION, POINTER :: VAL
INTEGER :: IX
TYPE( ENTRY), POINTER :: NEXT
END TYPE ENTRY
DOUBLE PRECISION, DIMENSION(:), INTENT(in) :: rarray
INTEGER, DIMENSION(:), INTENT(inout) :: indices
DOUBLE PRECISION, DIMENSION(SIZE(rarray)),TARGET :: A
TYPE(ENTRY), DIMENSION(:), ALLOCATABLE,TARGET :: B
TYPE(ENTRY), POINTER :: FIRST,CURRENT
! local variables
INTEGER :: i,im,n
DOUBLE PRECISION :: mx, mn
! Bucket sort:
! This subroutine sorts the indices according to rarray. The Assumption is that rarray consists of
! uniformly distributed numbers. If the assumption holds it runs in O(n) time
n=size(indices)
IF (n.EQ.1) RETURN
!indices=(/(i,i=1,n)/)
mx = MAXVAL(rarray)
mn = MINVAL(rarray)
A=(rarray-mn)/(mx-mn) ! make sure the numbers are between 0 and 1
!print *,'binsort ind=',indices
!print *,'binsort rar=',rarray
!print *,'binsort rar=',A
ALLOCATE(B(0:n-1))
!IF (ASSOCIATED(B(0)%VAL)) print *,'binsort B(0)=',B(0)%VAL
DO I=0,n-1
NULLIFY(B(I)%VAL)
NULLIFY(B(I)%NEXT)
ENDDO
DO I=1,n
IM=min(ABS(FLOOR(n*A(I))),N-1)
IF (ASSOCIATED(B(IM)%VAL)) THEN ! insert the new item by insertion sorting
ALLOCATE(CURRENT)
IF (A(I).LT.B(IM)%VAL) THEN
CURRENT = B(IM)
B(IM) = ENTRY(A(I),indices(I),CURRENT)
ELSE
FIRST => B(IM)
DO WHILE(ASSOCIATED(FIRST%NEXT).AND.
& FIRST%NEXT%VAL.LT.A(I))
FIRST=FIRST%NEXT
END DO
CURRENT = ENTRY(A(I),indices(I),FIRST%NEXT)
FIRST%NEXT => CURRENT
ENDIF
ELSE
B(IM)%VAL => A(I)
B(IM)%IX = indices(I)
ENDIF
END DO
IM=0
I=0
DO WHILE (IM.LT.N .AND. I.LT.N)
IF (ASSOCIATED(B(I)%VAL)) THEN
IM=IM+1
indices(IM)=B(I)%IX
DO WHILE (ASSOCIATED(B(I)%NEXT))
CURRENT => B(I)%NEXT
B(I)%NEXT => B(I)%NEXT%NEXT
IM=IM+1
indices(IM)=CURRENT%IX
DEALLOCATE(CURRENT)
END DO
ENDIF
I=I+1
END DO
DEALLOCATE(B)
!print *,'binsort ind=',indices
RETURN
END SUBROUTINE BINSORT
SUBROUTINE SORTRE(indices,rarray)
IMPLICIT NONE
DOUBLE PRECISION, DIMENSION(:), INTENT(inout) :: rarray
INTEGER, DIMENSION(:), INTENT(inout) :: indices
! local variables
INTEGER :: i,im,j,k,m,n
! diminishing increment sort as described by
! Donald E. Knuth (1973) "The art of computer programming,",
! Vol. 3, pp 84- (sorting and searching)
n=size(indices)
! if the below is commented out then assume indices are already initialized
!indices=(/(i,i=1,n)/)
!100 continue
if (n.le.1) goto 800
m=1
200 continue
m=m+m
if (m.lt.n) goto 200
m=m-1
300 continue
m=m/2
if (m.eq.0) goto 800
k=n-m
j=1
400 continue
i=j
500 continue
im=i+m
if (rarray(i).gt.rarray(im)) goto 700
600 continue
j=j+1
if (j.gt.k) goto 300
goto 400
700 continue
CALL swapre(rarray(i),rarray(im))
CALL swapint(indices(i),indices(im))
i=i-m
if (i.lt.1) goto 600
goto 500
800 continue
RETURN
END SUBROUTINE SORTRE
SUBROUTINE swapRe(m,n)
IMPLICIT NONE
DOUBLE PRECISION, INTENT(inout) :: m,n
DOUBLE PRECISION :: tmp
tmp=m
m=n
n=tmp
END SUBROUTINE swapRe
SUBROUTINE swapint(m,n)
IMPLICIT NONE
INTEGER, INTENT(inout) :: m,n
INTEGER :: tmp
tmp=m
m=n
n=tmp
END SUBROUTINE swapint
!______________________________________________________
SUBROUTINE spearcorr(C,D)
IMPLICIT NONE
DOUBLE PRECISION, dimension(:,:), INTENT(out) :: C
integer, dimension(:,:),intent(in) :: D ! rank matrix
double precision, dimension(:,:),allocatable :: DD !,DDT
double precision, dimension(:),allocatable :: tmp
INTEGER :: N,M,ix,iy
DOUBLE PRECISION :: dN
! this procedure calculates spearmans correlation coefficient
! between the columns of D
N=size(D,dim=1);M=SIZE(D,dim=2)
dN=dble(N)
allocate(DD(1:N,1:M))
DD=dble(D)
! if (.false.) then ! old call
! allocate(DDt(1:M,1:N))
! DDT=transpose(DD)
! C = matmul(DDt,DD)*12.d0/(dn*(dn*dn-1.d0))
! C=(C-3.d0*(dn+1.d0)/(dn-1.d0))
! deallocate(DDT)
! else
allocate(tmp(1:N))
do ix=1, m-1
do iy=ix+1,m
tmp= DD(1:N,ix)-DD(1:N,iy)
C(ix,iy)=1.d0-6.d0*SUM(tmp*tmp)/dn/(dn*dn-1.d0)
C(iy,ix)=C(ix,iy)
enddo
C(ix,ix) = 1.d0
enddo
C(m,m)=1.d0
deallocate(tmp)
! endif
deallocate(DD)
return
END SUBROUTINE spearcorr
SUBROUTINE SVDCMP(A,W,V)
IMPLICIT NONE
DOUBLE PRECISION, DIMENSION(: ), INTENT(out) :: W
DOUBLE PRECISION, DIMENSION(:,:), INTENT(inout) :: A
DOUBLE PRECISION, DIMENSION(:,:), INTENT(OUT) :: V
!LOCAL VARIABLES
DOUBLE PRECISION, DIMENSION(:), allocatable :: RV1
DOUBLE PRECISION :: G,S,SCALE,ANORM,F,H,C,X,Y,Z
INTEGER M,N,NM,I,J,K,L,ITS
!PARAMETER (NMAX=100)
C Maximum anticipated values of N
C DIMENSION A(MP,NP),W(NP),V(NP,NP),RV1(NMAX)
C Given a matrix A, with logical dimensions M by N and physical
C dimensions MP by NP, this routine computes its singular value
C decomposition, A=U.W.V^T, see Numerical Recipes, by Press W.,H.
C Flannery, B. P., Teukolsky S.A. and Vetterling W., T. Cambrige
C University Press 1986, Chapter 2.9. The matrix U replaces A on
C output. The diagonal matrix of singular values W is output as a vector
C W. The matrix V (not the transpose V^T) is output as V. M must be
C greater or equal to N; if it is smaller, then A should be filled up
C to square with zero rows.
C
M=size(A,dim=1);N=size(A,dim=2)
!Mp=M;Np=N
allocate(RV1(1:N))
IF (M.LT.N) then
! Print *,'SVDCMP: You must augment A with extra zero rows.'
endif
C Householder reduction to bidiagonal form
G=0.d0
SCALE=0.d0
ANORM=0.d0
DO 25 I=1,N
L=I+1
RV1(I)=SCALE*G
G=0.D0
S=0.D0
SCALE=0.D0
IF (I.LE.M) THEN
DO K=I,M
SCALE=SCALE+ABS(A(K,I))
enddo
IF (SCALE.NE.0.D0) THEN
DO K=I,M
A(K,I)=A(K,I)/SCALE
S=S+A(K,I)*A(K,I)
enddo
F=A(I,I)
G=-SIGN(SQRT(S),F)
H=F*G-S
A(I,I)=F-G
IF (I.NE.N) THEN
DO J=L,N
S=0.D0
DO K=I,M
S=S+A(K,I)*A(K,J)
enddo
F=S/H
DO K=I,M
A(K,J)=A(K,J)+F*A(K,I)
enddo
enddo
ENDIF
DO K=I,M
A(K,I)=SCALE*A(K,I)
enddo
ENDIF
ENDIF
W(I)=SCALE*G
G=0.d0
S=0.d0
SCALE=0.d0
IF ((I.LE.M).AND.(I.NE.N)) THEN
DO K=L,N
SCALE=SCALE+ABS(A(I,K))
enddo
IF (SCALE.NE.0.0) THEN
DO K=L,N
A(I,K)=A(I,K)/SCALE
S=S+A(I,K)*A(I,K)
enddo
F=A(I,L)
G=-SIGN(SQRT(S),F)
H=F*G-S
A(I,L)=F-G
DO K=L,N
RV1(K)=A(I,K)/H
enddo
IF (I.NE.M) THEN
DO J=L,M
S=0.D0
DO K=L,N
S=S+A(J,K)*A(I,K)
enddo
DO K=L,N
A(J,K)=A(J,K)+S*RV1(K)
enddo
enddo
ENDIF
DO K=L,N
A(I,K)=SCALE*A(I,K)
enddo
ENDIF
ENDIF
ANORM=MAX(ANORM,(ABS(W(I))+ABS(RV1(I))))
25 CONTINUE
c print *,'25'
C Accumulation of right-hand transformations.
DO I=N,1,-1
IF (I.LT.N) THEN
IF (G.NE.0.d0) THEN
DO J=L,N
V(J,I)=(A(I,J)/A(I,L))/G
C Double division to avoid possible underflow.
enddo
DO J=L,N
S=0.d0
DO K=L,N
S=S+A(I,K)*V(K,J)
enddo
DO K=L,N
V(K,J)=V(K,J)+S*V(K,I)
enddo
enddo
ENDIF
DO J=L,N
V(I,J)=0.d0
V(J,I)=0.d0
enddo
ENDIF
V(I,I)=1.d0
G=RV1(I)
L=I
enddo
c print *,'32'
C Accumulation of the left-hang transformation
DO 39 I=N,1,-1
L=I+1
G=W(I)
IF (I.LT.N) THEN
DO J=L,N
A(I,J)=0.d0
enddo
ENDIF
IF (G.NE.0.d0) THEN
G=1.d0/G
IF (I.NE.N) THEN
DO J=L,N
S=0.d0
DO K=L,M
S=S+A(K,I)*A(K,J)
enddo
F=(S/A(I,I))*G
DO K=I,M
A(K,J)=A(K,J)+F*A(K,I)
enddo
enddo
ENDIF
DO J=I,M
A(J,I)=A(J,I)*G
enddo
ELSE
DO J=I,M
A(J,I)=0.d0
enddo
ENDIF
A(I,I)=A(I,I)+1.d0
39 CONTINUE
c print *,'39'
C Diagonalization of the bidiagonal form
C Loop over singular values
DO 49 K=N,1,-1
C Loop allowed iterations
DO 48 ITS=1,30
C Test for spliting
DO L=K,1,-1
NM=L-1
C Note that RV1(1) is always zero
! old call which may cause inconsistent results
! IF((ABS(RV1(L))+ANORM).EQ.ANORM) GO TO 2
! IF((ABS(W(NM))+ANORM).EQ.ANORM) GO TO 1
! NEW CALL
IF (((ABS(RV1(L))+ANORM).GE.NEAREST(ANORM,-1.d0)).AND.
& ((ABS(RV1(L))+ANORM).LE.NEAREST(ANORM,1.d0)) ) GO TO 2
IF (((ABS(W(NM))+ANORM).GE.NEAREST(ANORM,-1.d0)).AND.
& ((ABS(W(NM))+ANORM).LE.NEAREST(ANORM,1.d0)) ) GO TO 1
enddo
c print *,'41'
1 C=0.d0
S=1.d0
DO I=L,K
F=S*RV1(I)
! old call which may cause inconsistent results
IF (((ABS(F)+ANORM).LT.ANORM).OR.
& ((ABS(F)+ANORM).GT.ANORM)) THEN
G=W(I)
H=SQRT(F*F+G*G)
W(I)=H
H=1.D0/H
C= (G*H)
S=-(F*H)
DO J=1,M
Y=A(J,NM)
Z=A(J,I)
A(J,NM)=(Y*C)+(Z*S)
A(J,I)=-(Y*S)+(Z*C)
enddo
ENDIF
enddo
c print *,'43'
2 Z=W(K)
IF (L.EQ.K) THEN
C Convergence
IF (Z.LT.0.d0) THEN
C Singular values are made nonnegative
W(K)=-Z
DO J=1,N
V(J,K)=-V(J,K)
enddo
ENDIF
GO TO 3
ENDIF
IF (ITS.EQ.30) then
! print *,'SVDCMP: No convergence in 30 iterations'
endif
X=W(L)
NM=K-1
Y=W(NM)
G=RV1(NM)
H=RV1(K)
F=((Y-Z)*(Y+Z)+(G-H)*(G+H))/(2.d0*H*Y)
G=SQRT(F*F+1.D0)
F=((X-Z)*(X+Z)+H*((Y/(F+SIGN(G,F)))-H))/X
C Next QR transformation
C=1.d0
S=1.d0
DO 47 J=L,NM
I=J+1
G=RV1(I)
Y=W(I)
H=S*G
G=C*G
Z=SQRT(F*F+H*H)
RV1(J)=Z
C=F/Z
S=H/Z
F= (X*C)+(G*S)
G=-(X*S)+(G*C)
H=Y*S
Y=Y*C
DO NM=1,N
X=V(NM,J)
Z=V(NM,I)
V(NM,J)= (X*C)+(Z*S)
V(NM,I)=-(X*S)+(Z*C)
enddo
c print *,'45',F,H
Z=pythag(F,H)
W(J)=Z
C Rotation can be arbitrary if Z=0.
IF (Z.NE.0.d0) THEN
c print *,1/Z
Z=1.d0/Z
c print *,'*'
C=F*Z
S=H*Z
ENDIF
F= (C*G)+(S*Y)
X=-(S*G)+(C*Y)
DO NM=1,M
Y=A(NM,J)
Z=A(NM,I)
A(NM,J)= (Y*C)+(Z*S)
A(NM,I)=-(Y*S)+(Z*C)
enddo
c print *,'46'
47 CONTINUE
c print *,'47'
RV1(L)=0.D0
RV1(K)=F
W(K)=X
48 CONTINUE
3 CONTINUE
49 CONTINUE
c print *,'49'
deallocate(RV1)
RETURN
END SUBROUTINE SVDCMP
FUNCTION pythag(a,b) RESULT (VALUE)
DOUBLE PRECISION, INTENT(IN) :: a,b
DOUBLE PRECISION :: VALUE
DOUBLE PRECISION :: absa,absb
absa=abs(a)
absb=abs(b)
IF (absa.GT.absb) THEN
VALUE=absa*SQRT(1.d0+(absb/absa)**2)
ELSE
IF (absb.EQ.0) THEN
VALUE=0.D0
ELSE
VALUE=absb*SQRT(1.d0+(absa/absb)**2)
ENDIF
ENDIF
RETURN
END FUNCTION PYTHAG
END MODULE RCRUDEMOD
* KRBVRCMOD is a module containing a:
*
* Automatic Multidimensional Integration Subroutine
*
* AUTHOR: Alan Genz
* Department of Mathematics
* Washington State University
* Pulman, WA 99164-3113
* Email: AlanGenz@wsu.edu
*
* Last Change: 5/15/98
* revised pab 10.03.2000
* - updated to f90 (i.e. changed to assumed shape arrays + changing integers to DBLE)
* - put it into a module
*
* KRBVRC computes an approximation to the integral
*
* 1 1 1
* I I ... I F(X) dx(NDIM)...dx(2)dx(1)
* 0 0 0
*
*
* KRBVRC uses randomized Korobov rules for the first 20 variables.
* The primary references are
* "Randomization of Number Theoretic Methods for Multiple Integration"
* R. Cranley and T.N.L. Patterson, SIAM J Numer Anal, 13, pp. 904-14,
* and
* "Optimal Parameters for Multidimensional Integration",
* P. Keast, SIAM J Numer Anal, 10, pp.831-838.
* If there are more than 20 variables, the remaining variables are
* integrated using Richtmeyer rules. A reference is
* "Methods of Numerical Integration", P.J. Davis and P. Rabinowitz,
* Academic Press, 1984, pp. 482-483.
*
*************** Parameters for KRBVRC ********************************************
****** Input parameters
* NDIM Number of variables, must exceed 1, but not exceed 100
* MINVLS Integer minimum number of function evaluations allowed.
* MINVLS must not exceed MAXVLS. If MINVLS < 0 then the
* routine assumes a previous call has been made with
* the same integrand and continues that calculation.
* MAXVLS Integer maximum number of function evaluations allowed.
* FUNCTN EXTERNALly declared user defined function to be integrated.
* It must have parameters (NDIM,Z), where Z is a real array
* of dimension NDIM.
*
* ABSEPS Required absolute accuracy.
* RELEPS Required relative accuracy.
*
****** Output parameters
*
* MINVLS Actual number of function evaluations used.
* ABSERR Estimated absolute accuracy of FINEST.
* FINEST Estimated value of integral.
* INFORM INFORM = 0 for normal exit, when
* ABSERR <= MAX(ABSEPS, RELEPS*ABS(FINEST))
* and
* INTVLS <= MAXCLS.
* INFORM = 1 If MAXVLS was too small to obtain the required
* accuracy. In this case a value FINEST is returned with
* estimated absolute accuracy ABSERR.
************************************************************************
! William H. Press, Saul Teukolsky,
! William T. Wetterling and Brian P. Flannery (1997)
! "Numerical recipes in Fortran 77", Vol. 1, pp 299--305 (SOBSEQ)
! You may initialize the random generator before you
! call KRBVRC by the following lines:
!
! call random_seed(SIZE=seed_size)
! allocate(seed(seed_size))
! call random_seed(GET=seed(1:seed_size)) ! get current seed
! seed(1)=seed1 ! change seed
! call random_seed(PUT=seed(1:seed_size))
! deallocate(seed)
!
MODULE KRBVRCMOD
IMPLICIT NONE
PRIVATE
PUBLIC :: KRBVRC
!
INTERFACE KRBVRC
MODULE PROCEDURE KRBVRC
END INTERFACE
!
INTERFACE DKSMRC
MODULE PROCEDURE DKSMRC
END INTERFACE
!
INTERFACE DKRCHT
MODULE PROCEDURE DKRCHT
END INTERFACE
INTERFACE SOBSEQ
MODULE PROCEDURE SOBSEQ
END INTERFACE
!
CONTAINS
!***********************************************************
! MAIN INTEGRATION ROUTINE KRBVRC
!***********************************************************
SUBROUTINE KRBVRC( NDIM, MINVLS, MAXVLS, FUNCTN, ABSEPS, RELEPS,
& ABSERR, FINEST, INFORM )
*
* Automatic Multidimensional Integration Subroutine
*
* AUTHOR: Alan Genz
* Department of Mathematics
* Washington State University
* Pulman, WA 99164-3113
* Email: AlanGenz@wsu.edu
*
* Last Change: 5/15/98
*
* KRBVRC computes an approximation to the integral
*
* 1 1 1
* I I ... I F(X) dx(NDIM)...dx(2)dx(1)
* 0 0 0
*
*
* KRBVRC uses randomized Korobov rules for the first 20 variables.
* The primary references are
* "Randomization of Number Theoretic Methods for Multiple Integration"
* R. Cranley and T.N.L. Patterson, SIAM J Numer Anal, 13, pp. 904-14,
* and
* "Optimal Parameters for Multidimensional Integration",
* P. Keast, SIAM J Numer Anal, 10, pp.831-838.
* If there are more than 20 variables, the remaining variables are
* integrated using Richtmeyer rules. A reference is
* "Methods of Numerical Integration", P.J. Davis and P. Rabinowitz,
* Academic Press, 1984, pp. 482-483.
*
*************** Parameters ********************************************
****** Input parameters
* NDIM Number of variables, must exceed 1, but not exceed 100
* MINVLS Integer minimum number of function evaluations allowed.
* MINVLS must not exceed MAXVLS. If MINVLS < 0 then the
* routine assumes a previous call has been made with
* the same integrand and continues that calculation.
* MAXVLS Integer maximum number of function evaluations allowed.
* FUNCTN EXTERNALly declared user defined function to be integrated.
* It must have parameters (NDIM,Z), where Z is a real array
* of dimension NDIM.
*
* ABSEPS Required absolute accuracy.
* RELEPS Required relative accuracy.
****** Output parameters
* MINVLS Actual number of function evaluations used.
* ABSERR Estimated absolute accuracy of FINEST.
* FINEST Estimated value of integral.
* INFORM INFORM = 0 for normal exit, when
* ABSERR <= MAX(ABSEPS, RELEPS*ABS(FINEST))
* and
* INTVLS <= MAXCLS.
* INFORM = 1 If MAXVLS was too small to obtain the required
* accuracy. In this case a value FINEST is returned with
* estimated absolute accuracy ABSERR.
* INFORM = 2 If NDIM>100 or NDIM<1
************************************************************************
INTEGER, INTENT(IN) :: NDIM, MAXVLS
INTEGER, INTENT(INOUT) :: MINVLS
INTEGER, INTENT(OUT) :: INFORM
DOUBLE PRECISION, INTENT(IN) :: ABSEPS, RELEPS
DOUBLE PRECISION, INTENT(OUT) :: FINEST, ABSERR
INTEGER :: NP,PLIM,NLIM,KLIM,KLIMI,SAMPLS,I,INTVLS,MINSMP,NK
PARAMETER ( PLIM = 25, NLIM = 100, KLIM = 20, MINSMP = 8 )
INTEGER , DIMENSION(PLIM) :: P
INTEGER , DIMENSION(PLIM,KLIM-1) :: C
DOUBLE PRECISION :: DIFINT,FINVAL,VARSQR,VAREST,VARPRD,VALUE
DOUBLE PRECISION, PARAMETER :: ONE = 1.D0 , ZERO = 0.D0
DOUBLE PRECISION, DIMENSION(2*NLIM) :: X = 0.d0
DOUBLE PRECISION, DIMENSION(KLIM ) :: VK = 0.d0
INTERFACE
DOUBLE PRECISION FUNCTION FUNCTN(N,Z)
DOUBLE PRECISION,DIMENSION(:), INTENT(IN) :: Z
INTEGER, INTENT(IN) :: N
END FUNCTION FUNCTN
END INTERFACE
DATA P / 31, 47, 73, 113, 173, 263, 397, 593, 907, 1361,
& 2053, 3079, 4621, 6947, 10427, 15641, 23473, 35221,
& 52837, 79259, 118891, 178349, 267523, 401287, 601943/
DATA (C( 1,I), I = 1, 19)/ 12, 9, 9,
& 13, 12, 12, 12, 12, 12, 12, 12,
& 12, 3, 3, 3, 12, 7, 7, 12/
DATA (C( 2,I), I = 1, 19)/ 13, 11, 17,
& 10, 15, 15, 15, 15, 15, 15, 22,
& 15, 15, 6, 6, 6, 15, 15, 9/
DATA (C( 3,I), I = 1, 19)/ 27, 28, 10,
& 11, 11, 20, 11, 11, 28, 13, 13,
& 28, 13, 13, 13, 14, 14, 14, 14/
DATA (C( 4,I), I = 1, 19)/ 35, 27, 27,
& 36, 22, 29, 29, 20, 45, 5, 5,
& 5, 21, 21, 21, 21, 21, 21, 21/
DATA (C( 5,I), I = 1, 19)/ 64, 66, 28,
& 28, 44, 44, 55, 67, 10, 10, 10,
& 10, 10, 10, 38, 38, 10, 10, 10/
DATA (C( 6,I), I = 1, 19)/ 111, 42, 54,
& 118, 20, 31, 31, 72, 17, 94, 14,
& 14, 11, 14, 14, 14, 94, 10, 10/
DATA (C( 7,I), I = 1, 19)/ 163, 154, 83,
& 43, 82, 92, 150, 59, 76, 76, 47,
& 11, 11, 100, 131, 116, 116, 116, 116/
DATA (C( 8,I), I = 1, 19)/ 246, 189, 242,
& 102, 250, 250, 102, 250, 280, 118, 196,
& 118, 191, 215, 121, 121, 49, 49, 49/
DATA (C( 9,I), I = 1, 19)/ 347, 402, 322,
& 418, 215, 220, 339, 339, 339, 337, 218,
& 315, 315, 315, 315, 167, 167, 167, 167/
DATA (C(10,I), I = 1, 19)/ 505, 220, 601,
& 644, 612, 160, 206, 206, 206, 422, 134,
& 518, 134, 134, 518, 652, 382, 206, 158/
DATA (C(11,I), I = 1, 19)/ 794, 325, 960,
& 528, 247, 247, 338, 366, 847, 753, 753,
& 236, 334, 334, 461, 711, 652, 381, 381/
DATA (C(12,I), I = 1, 19)/ 1189, 888, 259,
& 1082, 725, 811, 636, 965, 497, 497, 1490,
& 1490, 392, 1291, 508, 508, 1291, 1291, 508/
DATA (C(13,I), I = 1, 19)/ 1763, 1018, 1500,
& 432, 1332, 2203, 126, 2240, 1719, 1284, 878,
& 1983, 266, 266, 266, 266, 747, 747, 127/
DATA (C(14,I), I = 1, 19)/ 2872, 3233, 1534,
& 2941, 2910, 393, 1796, 919, 446, 919, 919,
& 1117, 103, 103, 103, 103, 103, 103, 103/
DATA (C(15,I), I = 1, 19)/ 4309, 3758, 4034,
& 1963, 730, 642, 1502, 2246, 3834, 1511, 1102,
& 1102, 1522, 1522, 3427, 3427, 3928, 915, 915/
DATA (C(16,I), I = 1, 19)/ 6610, 6977, 1686,
& 3819, 2314, 5647, 3953, 3614, 5115, 423, 423,
& 5408, 7426, 423, 423, 487, 6227, 2660, 6227/
DATA (C(17,I), I = 1, 19)/ 9861, 3647, 4073,
& 2535, 3430, 9865, 2830, 9328, 4320, 5913, 10365,
& 8272, 3706, 6186, 7806, 7806, 7806, 8610, 2563/
DATA (C(18,I), I = 1, 19)/ 10327, 7582, 7124,
& 8214, 9600, 10271, 10193, 10800, 9086, 2365, 4409,
& 13812, 5661, 9344, 9344, 10362, 9344, 9344, 8585/
DATA (C(19,I), I = 1, 19)/ 19540, 19926, 11582,
& 11113, 24585, 8726, 17218, 419, 4918, 4918, 4918,
& 15701, 17710, 4037, 4037, 15808, 11401, 19398, 25950/
DATA (C(20,I), I = 1, 19)/ 34566, 9579, 12654,
& 26856, 37873, 38806, 29501, 17271, 3663, 10763, 18955,
& 1298, 26560, 17132, 17132, 4753, 4753, 8713, 18624/
DATA (C(21,I), I = 1, 19)/ 31929, 49367, 10982,
& 3527, 27066, 13226, 56010, 18911, 40574, 20767, 20767,
& 9686, 47603, 47603, 11736, 11736, 41601, 12888, 32948/
DATA (C(22,I), I = 1, 19)/ 40701, 69087, 77576,
& 64590, 39397, 33179, 10858, 38935, 43129, 35468, 35468,
& 2196, 61518, 61518, 27945, 70975, 70975, 86478, 86478/
DATA (C(23,I), I = 1, 19)/ 103650, 125480, 59978,
& 46875, 77172, 83021, 126904, 14541, 56299, 43636, 11655,
& 52680, 88549, 29804, 101894, 113675, 48040, 113675, 34987/
DATA (C(24,I), I = 1, 19)/ 165843, 90647, 59925,
& 189541, 67647, 74795, 68365, 167485, 143918, 74912, 167289,
& 75517, 8148, 172106, 126159, 35867, 35867, 35867, 121694/
DATA (C(25,I), I = 1, 19)/ 130365, 236711, 110235,
& 125699, 56483, 93735, 234469, 60549, 1291, 93937, 245291,
& 196061, 258647, 162489, 176631, 204895, 73353, 172319, 28881/
*
SAVE P, C, SAMPLS, NP, VAREST
IF ( NDIM .GT. NLIM .OR. NDIM .LT. 1 ) THEN
INFORM = 2
FINEST = ZERO
ABSERR = ONE
RETURN
ENDIF
INFORM = 1
INTVLS = 0
KLIMI = KLIM
IF ( MINVLS .GE. 0 ) THEN
FINEST = ZERO
VAREST = ZERO
SAMPLS = MINSMP
DO I = 1, PLIM
NP = I
IF ( MINVLS .LT. 2*SAMPLS*P(I) ) GO TO 10
END DO
SAMPLS = MAX( MINSMP, MINVLS/( 2*P(NP) ) )
ENDIF
10 VK(1) = ONE/DBLE(P(NP))
NK = MIN( NDIM, KLIM )
DO I = 2, NK
VK(I) = MOD(DBLE(C(NP,NK-1))*VK(I-1), ONE )
END DO
FINVAL = ZERO
VARSQR = ZERO
DO I = 1, SAMPLS
CALL DKSMRC( NDIM, KLIMI, VALUE, P(NP), VK, FUNCTN, X )
DIFINT = ( VALUE - FINVAL )/DBLE(I)
FINVAL = FINVAL + DIFINT
VARSQR = DBLE( I - 2 )*VARSQR/DBLE(I) + DIFINT*DIFINT
END DO
INTVLS = INTVLS + 2*SAMPLS*P(NP)
VARPRD = VAREST*VARSQR
FINEST = FINEST + ( FINVAL - FINEST )/( ONE + VARPRD )
IF ( VARSQR .GT. ZERO ) VAREST = ( ONE + VARPRD )/VARSQR
ABSERR = 3.d0*SQRT( VARSQR/( ONE + VARPRD ) )
IF ( ABSERR .GT. MAX( ABSEPS, ABS(FINEST)*RELEPS ) ) THEN
IF ( NP .LT. PLIM ) THEN
NP = NP + 1
ELSE
SAMPLS = MIN( 3*SAMPLS/2, ( MAXVLS - INTVLS )/( 2*P(NP) ) )
SAMPLS = MAX( MINSMP, SAMPLS )
ENDIF
IF ( INTVLS + 2*SAMPLS*P(NP) .LE. MAXVLS ) GO TO 10
ELSE
INFORM = 0
ENDIF
MINVLS = INTVLS
*
END SUBROUTINE KRBVRC
*
SUBROUTINE DKSMRC( NDIM, KLIM, SUMKRO, PRIME, VK, FUNCTN, X )
INTEGER, INTENT(IN):: NDIM, KLIM, PRIME
DOUBLE PRECISION, INTENT(OUT) :: SUMKRO
DOUBLE PRECISION, DIMENSION(:), INTENT(INOUT) :: VK,X
INTEGER :: K, J, JP, NK
DOUBLE PRECISION :: ONE, XT, MVNUNI
PARAMETER ( ONE = 1.d0 )
INTERFACE
DOUBLE PRECISION FUNCTION FUNCTN(N,Z)
DOUBLE PRECISION,DIMENSION(:), INTENT(IN) :: Z
INTEGER, INTENT(IN) :: N
END FUNCTION FUNCTN
END INTERFACE
SUMKRO = 0.d0
*
* Randomize Variable Order
*
NK = MIN( NDIM, KLIM )
DO J = 1, NK-1
CALL random_number(MVNUNI)
! JP = J + NINT(MVNUNI*DBLE( NK + 1 - J ))
JP = J + NINT(MVNUNI*DBLE( NK - J )) ! pab 21.11.2000
XT = VK(J)
VK(J) = VK(JP)
VK(JP) = XT
END DO
*
* Determine Random Shifts for each Variable
*
CALL random_number(X(NDIM+1:2*NDIM))
*
* Compute periodized and symmetrized lattice rule sum
*
DO K = 1, PRIME
X(1:NK) = MOD( DBLE(K)*VK(1:NK), ONE )
IF ( NDIM. GT. KLIM ) CALL DKRCHT(KLIM, NDIM-KLIM, X) !X(KLIM+1:NDIM) )
DO J = 1, NDIM
XT = X(J) + X(NDIM+J)
IF ( XT .GT. ONE ) XT = XT - 1.d0
X(J) = ABS( 2.d0*XT - 1.d0 )
END DO
SUMKRO = SUMKRO+(FUNCTN(NDIM,X)-SUMKRO)/DBLE(2*K-1)
X(1:NDIM) = 1.d0 - X(1:NDIM)
SUMKRO = SUMKRO+(FUNCTN(NDIM,X)-SUMKRO)/DBLE(2*K)
END DO
END SUBROUTINE DKSMRC
*
SUBROUTINE DKRCHT(KLIM, S, QUASI )
*
* This subroutine generates a new quasi-random Richtmeyer vector.
* A reference is
* "Methods of Numerical Integration", P.J. Davis and P. Rabinowitz,
* Academic Press, 1984, pp. 482-483.
*
* INPUTS:
* KLIM - Lower start value
* S - the number of dimensions;
* DKRCHT is initialized for each new S or S < 1.
*
* OUTPUTS:
* QUASI - a new quasi-random S-vector
*
* revised pab 28.05.2003
* - added klim in order to avoid copying of arrays in and out
* revised pab 01.11.1999
* updated to fortran 90
INTEGER, INTENT(IN) :: S,KLIM
DOUBLE PRECISION , DIMENSION(:) :: QUASI
INTEGER :: MXDIM, MXHSUM, B
PARAMETER ( MXDIM = 80, MXHSUM = 48, B = 2 )
INTEGER :: HISUM, I, OLDS
DOUBLE PRECISION , DIMENSION(MXDIM) :: PSQT
INTEGER, DIMENSION(MXDIM ) :: PRIME
INTEGER, DIMENSION(0:MXHSUM) :: N
DOUBLE PRECISION :: ONE, RN
PARAMETER ( ONE = 1.D0 )
PARAMETER ( PRIME = (/
& 2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
& 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
& 73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
& 127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
& 179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
& 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
& 283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
& 353, 359, 367, 373, 379, 383, 389, 397, 401, 409/))
* Primes to continue
* 419 421 431 433 439 443 449 457 461 463 467 479 487 491 499
* 503 509 521 523 541 547 557 563 569 571 577 587 593 599
SAVE OLDS, PSQT, HISUM, N
DATA OLDS / 0 /
IF ( S .NE. OLDS .OR. S .LT. 1 ) THEN
OLDS = ABS(S) ! pab 14.03.2000
N(0) = 0
HISUM = 0
DO I = 1, OLDS
RN = DBLE(PRIME(I))
PSQT(I) = SQRT( RN )
END DO
END IF
DO I = 0, HISUM
N(I) = N(I) + 1
IF ( N(I) .LT. B ) GO TO 10
N(I) = 0
END DO
HISUM = HISUM + 1
IF ( HISUM .GT. MXHSUM ) HISUM = 0
N(HISUM) = 1
10 RN = 0.d0
DO I = HISUM, 0, -1
RN = DBLE(N(I)) + DBLE(B)*RN
END DO
DO I = 1, OLDS
QUASI(KLIM+I) = MOD( RN*PSQT(I), ONE )
END DO
END SUBROUTINE DKRCHT
!
! SOBSEQ is not taken in to use:
!
SUBROUTINE SOBSEQ(N,X)
IMPLICIT NONE
DOUBLE PRECISION,DIMENSION(:), INTENT(OUT):: X
INTEGER, INTENT(IN) :: N
INTEGER,PARAMETER ::MAXBIT=30,MAXDIM=6
INTEGER :: I,IM, IN,IPP,J,K,L, OLDN
INTEGER, DIMENSION(MAXDIM) :: IP,MDEG,IX
INTEGER, DIMENSION(MAXDIM,MAXBIT) ::IU
INTEGER, DIMENSION(MAXDIM*MAXBIT) ::IV
DOUBLE PRECISION :: FAC
SAVE IP,MDEG,IX,IV,IN,FAC, OLDN
DATA OLDN / 0 /
DATA IP /0,1,1,2,1,4 /, MDEG /1,2,3,3,4,4 /
DATA IX /0,0,0,0,0,0 /
DATA IV /1,1,1,1,1,1,3,1,3,3,1,1,5,
& 7,7,3,3,5,15,11,5,15,13,9,156*0/
!(MAXDIM*MAXBIT-24)
EQUIVALENCE (IV,IU) ! to allow both 1D and 2D addressing
! returns sobols sequence of quasi-random numbers between 0 1
! When n is new or is negative, internally initializes a set of MAXBIT
! direction numbers for each of MAXDIM different sobol
! sequences. When n is positive (but < MAXDIM)
! returns as the vector x(1:n) the next values from n of these sequences
! (n must not be changed between initializations)
!
! This routine is initialised for maximum of n=6 dimensions
! and a word length of 30 bits. These parameter may be increased by
!changing MAXBIT and MAXDIM and add more initializing data to
! ip (primitive polynomials), mdeg (their degrees) and iv
! (the starting value for the recurrence relation)
!reference
! William H. Press, Saul Teukolsky, William T. Wetterling and Brian P. Flannery (1997)
! "Numerical recipes in Fortran 77", Vol. 1, pp 299--305
IF (N.LT.0 .OR. OLDN.NE.N ) THEN ! INITIALIZE, DO NOT RETURN VECTOR
OLDN = ABS(N)
IX=0
IN=0 ! RANDOM STARTPOINT: CALL RANDOM_NUMBER(P); IN=P*2^MAXBIT
! AND REMOVE WARNING MESSAGE BELOW
!IF (IV(1).NE.1) RETURN
IF (IV(1).EQ.1) THEN
FAC=1.D0/2.D0**MAXBIT
DO K=1,MAXDIM
DO J=1,MDEG(K) ! STORED VALUES NEED NORMALIZATION
IU(K,J)=IU(K,J)*2**(MAXBIT-J)
ENDDO
DO J=1,MDEG(K)+1,MAXBIT ! USE RECCURENCE TO GET OTHER VALUES
IPP=IP(K)
I=IU(K,J-MDEG(K))
I=IEOR(I,I/2**MDEG(K))
DO L=MDEG(K)-1,1,-1
IF (IAND(IPP,1).NE.0) I=IEOR(I,IU(K,J-L))
IPP=IPP/2
ENDDO
IU(K,J)=I
ENDDO
ENDDO
ENDIF
ENDIF ! CALCULATE THE NEXT VECTOR IN THE SEQUENCE
IM=IN
DO J=1,MAXBIT ! FIND THE RIGHTMOST ZERO BIT
IF (IAND(IM,1).EQ.0) GOTO 1
IM=IM/2
ENDDO
! PRINT *,'MAXBIT TOO SMALL IN SOBSEQ'
1 IM=(J-1)*MAXDIM
DO K=1,MIN(OLDN,MAXDIM) !XOR THE
IX(K)=IEOR(IX(K),IV(IM+K))
X(K)=IX(K)*FAC
ENDDO
IN=IN+1 ! INCREMENT COUNTER
RETURN
END SUBROUTINE SOBSEQ
END MODULE KRBVRCMOD
MODULE DKBVRCMOD
IMPLICIT NONE
PRIVATE
PUBLIC :: DKBVRC
!
INTERFACE DKBVRC
MODULE PROCEDURE DKBVRC
END INTERFACE
!
INTERFACE DKSMRC
MODULE PROCEDURE DKSMRC
END INTERFACE
!
CONTAINS
SUBROUTINE DKBVRC( NDIM, MINVLS, MAXVLS, FUNCTN, ABSEPS, RELEPS,
& ABSERR, FINEST, INFORM )
*
* Automatic Multidimensional Integration Subroutine
*
* AUTHOR: Alan Genz
* Department of Mathematics
* Washington State University
* Pulman, WA 99164-3113
* Email: AlanGenz@wsu.edu
*
* Last Change: 1/15/03
*
! revised pab June 2004
! updated to F90
*
* DKBVRC computes an approximation to the integral
*
* 1 1 1
* I I ... I F(X) dx(NDIM)...dx(2)dx(1)
* 0 0 0
*
*
* DKBVRC uses randomized Korobov rules for the first 100 variables.
* The primary references are
* "Randomization of Number Theoretic Methods for Multiple Integration"
* R. Cranley and T.N.L. Patterson, SIAM J Numer Anal, 13, pp. 904-14,
* and
* "Optimal Parameters for Multidimensional Integration",
* P. Keast, SIAM J Numer Anal, 10, pp.831-838.
* If there are more than 100 variables, the remaining variables are
* integrated using the rules described in the reference
* "On a Number-Theoretical Integration Method"
* H. Niederreiter, Aequationes Mathematicae, 8(1972), pp. 304-11.
*
*************** Parameters ********************************************
****** Input parameters
* NDIM Number of variables, must exceed 1, but not exceed 1000
* MINVLS Integer minimum number of function evaluations allowed.
* MINVLS must not exceed MAXVLS. If MINVLS < 0 then the
* routine assumes a previous call has been made with
* the same integrand and continues that calculation.
* MAXVLS Integer maximum number of function evaluations allowed.
* FUNCTN EXTERNALly declared user defined function to be integrated.
* It must have parameters (NDIM,Z), where Z is a real array
* of dimension NDIM.
*
* ABSEPS Required absolute accuracy.
* RELEPS Required relative accuracy.
****** Output parameters
* MINVLS Actual number of function evaluations used.
* ABSERR Estimated absolute accuracy of FINEST.
* FINEST Estimated value of integral.
* INFORM INFORM = 0 for normal exit, when
* ABSERR <= MAX(ABSEPS, RELEPS*ABS(FINEST))
* and
* INTVLS <= MAXCLS.
* INFORM = 1 If MAXVLS was too small to obtain the required
* accuracy. In this case a value FINEST is returned with
* estimated absolute accuracy ABSERR.
* INFORM = 2 If NDIM>1000 or NDIM<1
************************************************************************
INTEGER, INTENT(IN) :: NDIM, MAXVLS
INTEGER, INTENT(INOUT) :: MINVLS
INTEGER, INTENT(OUT) :: INFORM
DOUBLE PRECISION, INTENT(IN) :: ABSEPS, RELEPS
DOUBLE PRECISION, INTENT(OUT) :: FINEST, ABSERR
INTEGER :: NP,PLIM,NLIM,KLIM,KLIMI,SAMPLS,I,INTVLS,MINSMP
PARAMETER ( PLIM = 28, NLIM = 1000, KLIM = 100, MINSMP = 8 )
INTEGER P(PLIM), C(PLIM,KLIM-1)
DOUBLE PRECISION :: DIFINT, FINVAL, VARSQR, VAREST, VARPRD, VALUE
DOUBLE PRECISION, PARAMETER :: ONE= 1.D0,ZERO = 0.D0
DOUBLE PRECISION X(2*NLIM), VK(NLIM)
INTERFACE
DOUBLE PRECISION FUNCTION FUNCTN(N,Z)
DOUBLE PRECISION,DIMENSION(:), INTENT(IN) :: Z
INTEGER, INTENT(IN) :: N
END FUNCTION FUNCTN
END INTERFACE
SAVE P, C, SAMPLS, NP, VAREST
IF ( NDIM .GT. NLIM .OR. NDIM .LT. 1 ) THEN
INFORM = 2
FINEST = ZERO
ABSERR = ONE
RETURN
ENDIF
INFORM = 1
INTVLS = 0
KLIMI = KLIM
IF ( MINVLS .GE. 0 ) THEN
FINEST = ZERO
VAREST = ZERO
SAMPLS = MINSMP
DO I = 1, PLIM
NP = I
IF ( MINVLS .LT. 2*SAMPLS*P(I) ) GO TO 10
END DO
SAMPLS = MAX( MINSMP, MINVLS/( 2*P(NP) ) )
ENDIF
10 VK(1) = ONE/P(NP)
DO I = 2, NDIM
IF ( I .LE. KLIM ) THEN
VK(I) = MOD( C(NP, MIN(NDIM-1,KLIM-1))*VK(I-1), ONE )
ELSE
VK(I) = INT( P(NP)*2**(DBLE(I-KLIM)/(NDIM-KLIM+1)) )
VK(I) = MOD( VK(I)/P(NP), ONE )
END IF
END DO
FINVAL = ZERO
VARSQR = ZERO
DO I = 1, SAMPLS
CALL DKSMRC( NDIM, KLIMI, VALUE, P(NP), VK, FUNCTN, X )
DIFINT = ( VALUE - FINVAL )/DBLE(I)
FINVAL = FINVAL + DIFINT
VARSQR = DBLE( I - 2 )*VARSQR/DBLE(I) + DIFINT**2
END DO
INTVLS = INTVLS + 2*SAMPLS*P(NP)
VARPRD = VAREST*VARSQR
FINEST = FINEST + ( FINVAL - FINEST )/( ONE + VARPRD )
IF ( VARSQR .GT. ZERO ) VAREST = ( ONE + VARPRD )/VARSQR
ABSERR = 3.0D0*SQRT( VARSQR/( ONE + VARPRD ) )
IF ( ABSERR .GT. MAX( ABSEPS, ABS(FINEST)*RELEPS ) ) THEN
IF ( NP .LT. PLIM ) THEN
NP = NP + 1
ELSE
SAMPLS = MIN( 3*SAMPLS/2, ( MAXVLS - INTVLS )/( 2*P(NP) ) )
SAMPLS = MAX( MINSMP, SAMPLS )
ENDIF
IF ( INTVLS + 2*SAMPLS*P(NP) .LE. MAXVLS ) GO TO 10
ELSE
INFORM = 0
ENDIF
MINVLS = INTVLS
*
* Optimal Parameters for Lattice Rules
*
DATA P( 1),(C( 1,I),I = 1,99)/ 31, 12, 2*9, 13, 8*12, 3*3, 12,
& 2*7, 9*12, 3*3, 12, 2*7, 9*12, 3*3, 12, 2*7, 9*12, 3*3, 12, 2*7,
& 8*12, 7, 3*3, 3*7, 21*3/
DATA P( 2),(C( 2,I),I = 1,99)/ 47, 13, 11, 17, 10, 6*15,
& 22, 2*15, 3*6, 2*15, 9, 13, 3*2, 13, 2*11, 10, 9*15, 3*6, 2*15,
& 9, 13, 3*2, 13, 2*11, 10, 9*15, 3*6, 2*15, 9, 13, 3*2, 13, 2*11,
& 2*10, 8*15, 6, 2, 3, 2, 3, 12*2/
DATA P( 3),(C( 3,I),I = 1,99)/ 73, 27, 28, 10, 2*11, 20,
& 2*11, 28, 2*13, 28, 3*13, 16*14, 2*31, 3*5, 31, 13, 6*11, 7*13,
& 16*14, 2*31, 3*5, 11, 13, 7*11, 2*13, 11, 13, 4*5, 14, 13, 8*5/
DATA P( 4),(C( 4,I),I = 1,99)/ 113, 35, 2*27, 36, 22, 2*29,
& 20, 45, 3*5, 16*21, 29, 10*17, 12*23, 21, 27, 3*3, 24, 2*27,
& 17, 3*29, 17, 4*5, 16*21, 3*17, 6, 2*17, 6, 3, 2*6, 5*3/
DATA P( 5),(C( 5,I),I = 1,99)/ 173, 64, 66, 2*28, 2*44, 55,
& 67, 6*10, 2*38, 5*10, 12*49, 2*38, 31, 2*4, 31, 64, 3*4, 64,
& 6*45, 19*66, 11, 9*66, 45, 11, 7, 3, 3*2, 27, 5, 2*3, 2*5, 7*2/
DATA P( 6),(C( 6,I),I = 1,99)/ 263, 111, 42, 54, 118, 20,
& 2*31, 72, 17, 94, 2*14, 11, 3*14, 94, 4*10, 7*14, 3*11, 7*8,
& 5*18, 113, 2*62, 2*45, 17*113, 2*63, 53, 63, 15*67, 5*51, 12,
& 51, 12, 51, 5, 2*3, 2*2, 5/
DATA P( 7),(C( 7,I),I = 1,99)/ 397, 163, 154, 83, 43, 82,
& 92, 150, 59, 2*76, 47, 2*11, 100, 131, 6*116, 9*138, 21*101,
& 6*116, 5*100, 5*138, 19*101, 8*38, 5*3/
DATA P( 8),(C( 8,I),I = 1,99)/ 593, 246, 189, 242, 102,
& 2*250, 102, 250, 280, 118, 196, 118, 191, 215, 2*121,
& 12*49, 34*171, 8*161, 17*14, 6*10, 103, 4*10, 5/
DATA P( 9),(C( 9,I),I = 1,99)/ 907, 347, 402, 322, 418,
& 215, 220, 3*339, 337, 218, 4*315, 4*167, 361, 201, 11*124,
& 2*231, 14*90, 4*48, 23*90, 10*243, 9*283, 16, 283, 16, 2*283/
DATA P(10),(C(10,I),I = 1,99)/ 1361, 505, 220, 601, 644,
& 612, 160, 3*206, 422, 134, 518, 2*134, 518, 652, 382,
& 206, 158, 441, 179, 441, 56, 2*559, 14*56, 2*101, 56,
& 8*101, 7*193, 21*101, 17*122, 4*101/
DATA P(11),(C(11,I),I = 1,99)/ 2053, 794, 325, 960, 528,
& 2*247, 338, 366, 847, 2*753, 236, 2*334, 461, 711, 652,
& 3*381, 652, 7*381, 226, 7*326, 126, 10*326, 2*195, 19*55,
& 7*195, 11*132, 13*387/
DATA P(12),(C(12,I),I = 1,99)/ 3079, 1189, 888, 259, 1082, 725,
& 811, 636, 965, 2*497, 2*1490, 392, 1291, 2*508, 2*1291, 508,
& 1291, 2*508, 4*867, 934, 7*867, 9*1284, 4*563, 3*1010, 208,
& 838, 3*563, 2*759, 564, 2*759, 4*801, 5*759, 8*563, 22*226/
DATA P(13),(C(13,I),I = 1,99)/ 4621, 1763, 1018, 1500, 432,
& 1332, 2203, 126, 2240, 1719, 1284, 878, 1983, 4*266,
& 2*747, 2*127, 2074, 127, 2074, 1400, 10*1383, 1400, 7*1383,
& 507, 4*1073, 5*1990, 9*507, 17*1073, 6*22, 1073, 6*452, 318,
& 4*301, 2*86, 15/
DATA P(14),(C(14,I),I = 1,99)/ 6947, 2872, 3233, 1534, 2941,
& 2910, 393, 1796, 919, 446, 2*919, 1117, 7*103, 2311, 3117, 1101,
& 2*3117, 5*1101, 8*2503, 7*429, 3*1702, 5*184, 34*105, 13*784/
DATA P(15),(C(15,I),I = 1,99)/ 10427, 4309, 3758, 4034, 1963,
& 730, 642, 1502, 2246, 3834, 1511, 2*1102, 2*1522, 2*3427,
& 3928, 2*915, 4*3818, 3*4782, 3818, 4782, 2*3818, 7*1327, 9*1387,
& 13*2339, 18*3148, 3*1776, 3*3354, 925, 2*3354, 5*925, 8*2133/
DATA P(16),(C(16,I),I = 1,99)/ 15641, 6610, 6977, 1686, 3819,
& 2314, 5647, 3953, 3614, 5115, 2*423, 5408, 7426, 2*423,
& 487, 6227, 2660, 6227, 1221, 3811, 197, 4367, 351,
& 1281, 1221, 3*351, 7245, 1984, 6*2999, 3995, 4*2063, 1644,
& 2063, 2077, 3*2512, 4*2077, 19*754, 2*1097, 4*754, 248, 754,
& 4*1097, 4*222, 754,11*1982/
DATA P(17),(C(17,I),I = 1,99)/ 23473, 9861, 3647, 4073, 2535,
& 3430, 9865, 2830, 9328, 4320, 5913, 10365, 8272, 3706, 6186,
& 3*7806, 8610, 2563, 2*11558, 9421, 1181, 9421, 3*1181, 9421,
& 2*1181, 2*10574, 5*3534, 3*2898, 3450, 7*2141, 15*7055, 2831,
& 24*8204, 3*4688, 8*2831/
DATA P(18),(C(18,I),I = 1,99)/ 35221, 10327, 7582, 7124, 8214,
& 9600, 10271, 10193, 10800, 9086, 2365, 4409, 13812,
& 5661, 2*9344, 10362, 2*9344, 8585, 11114, 3*13080, 6949,
& 3*3436, 13213, 2*6130, 2*8159, 11595, 8159, 3436, 18*7096,
& 4377, 7096, 5*4377, 2*5410, 32*4377, 2*440, 3*1199/
DATA P(19),(C(19,I),I = 1,99)/ 52837, 19540, 19926, 11582,
& 11113, 24585, 8726, 17218, 419, 3*4918, 15701, 17710,
& 2*4037, 15808, 11401, 19398, 2*25950, 4454, 24987, 11719,
& 8697, 5*1452, 2*8697, 6436, 21475, 6436, 22913, 6434, 18497,
& 4*11089, 2*3036, 4*14208, 8*12906, 4*7614, 6*5021, 24*10145,
& 6*4544, 4*8394/
DATA P(20),(C(20,I),I = 1,99)/ 79259, 34566, 9579, 12654,
& 26856, 37873, 38806, 29501, 17271, 3663, 10763, 18955,
& 1298, 26560, 2*17132, 2*4753, 8713, 18624, 13082, 6791,
& 1122, 19363, 34695, 4*18770, 15628, 4*18770, 33766, 6*20837,
& 5*6545, 14*12138, 5*30483, 19*12138, 9305, 13*11107, 2*9305/
DATA P(21),(C(21,I),I = 1,99)/118891, 31929, 49367, 10982, 3527,
& 27066, 13226, 56010, 18911, 40574, 2*20767, 9686, 2*47603,
& 2*11736, 41601, 12888, 32948, 30801, 44243, 2*53351, 16016,
& 2*35086, 32581, 2*2464, 49554, 2*2464, 2*49554, 2464, 81, 27260,
& 10681, 7*2185, 5*18086, 2*17631, 3*18086, 37335, 3*37774,
& 13*26401, 12982, 6*40398, 3*3518, 9*37799, 4*4721, 4*7067/
DATA P(22),(C(22,I),I = 1,99)/178349, 40701, 69087, 77576, 64590,
& 39397, 33179, 10858, 38935, 43129, 2*35468, 5279, 2*61518, 27945,
& 2*70975, 2*86478, 2*20514, 2*73178, 2*43098, 4701,
& 2*59979, 58556, 69916, 2*15170, 2*4832, 43064, 71685, 4832,
& 3*15170, 3*27679, 2*60826, 2*6187, 5*4264, 45567, 4*32269,
& 9*62060, 13*1803, 12*51108, 2*55315, 5*54140, 13134/
DATA P(23),(C(23,I),I = 1,99)/267523, 103650, 125480, 59978,
& 46875, 77172, 83021, 126904, 14541, 56299, 43636, 11655,
& 52680, 88549, 29804, 101894, 113675, 48040, 113675,
& 34987, 48308, 97926, 5475, 49449, 6850, 2*62545, 9440,
& 33242, 9440, 33242, 9440, 33242, 9440, 62850, 3*9440,
& 3*90308, 9*47904, 7*41143, 5*36114, 24997, 14*65162, 7*47650,
& 7*40586, 4*38725, 5*88329/
DATA P(24),(C(24,I),I = 1,99)/401287, 165843, 90647, 59925,
& 189541, 67647, 74795, 68365, 167485, 143918, 74912,
& 167289, 75517, 8148, 172106, 126159,3*35867, 121694,
& 52171, 95354, 2*113969, 76304, 2*123709, 144615, 123709,
& 2*64958, 32377, 2*193002, 25023, 40017, 141605, 2*189165,
& 141605, 2*189165, 3*141605, 189165, 20*127047, 10*127785,
& 6*80822, 16*131661, 7114, 131661/
DATA P(25),(C(25,I),I = 1,99)/601943, 130365, 236711, 110235,
& 125699, 56483, 93735, 234469, 60549, 1291, 93937,
& 245291, 196061, 258647, 162489, 176631, 204895, 73353,
& 172319, 28881, 136787,2*122081, 275993, 64673, 3*211587,
& 2*282859, 211587, 242821, 3*256865, 122203, 291915, 122203,
& 2*291915, 122203, 2*25639, 291803, 245397, 284047,
& 7*245397, 94241, 2*66575, 19*217673, 10*210249, 15*94453/
DATA P(26),(C(26,I),I = 1,99)/902933, 333459, 375354, 102417,
& 383544, 292630, 41147, 374614, 48032, 435453, 281493, 358168,
& 114121, 346892, 238990, 317313, 164158, 35497, 2*70530, 434839,
& 3*24754, 393656, 2*118711, 148227, 271087, 355831, 91034,
& 2*417029, 2*91034, 417029, 91034, 2*299843, 2*413548, 308300,
& 3*413548, 3*308300, 413548, 5*308300, 4*15311, 2*176255, 6*23613,
& 172210, 4* 204328, 5*121626, 5*200187, 2*121551, 12*248492,
& 5*13942/
DATA P(27), (C(27,I), I = 1,99)/ 1354471, 500884, 566009, 399251,
& 652979, 355008, 430235, 328722, 670680, 2*405585, 424646,
& 2*670180, 641587, 215580, 59048, 633320, 81010, 20789, 2*389250,
& 2*638764, 2*389250, 398094, 80846, 2*147776, 296177, 2*398094,
& 2*147776, 396313, 3*578233, 19482, 620706, 187095, 620706,
& 187095, 126467, 12*241663, 321632, 2*23210, 3*394484, 3*78101,
& 19*542095, 3*277743, 12*457259/
DATA P(28), (C(28,I), I = 1, 99)/ 2031713, 858339, 918142, 501970,
& 234813, 460565, 31996, 753018, 256150, 199809, 993599, 245149,
& 794183, 121349, 150619, 376952, 2*809123, 804319, 67352, 969594,
& 434796, 969594, 804319, 391368, 761041, 754049, 466264, 2*754049,
& 466264, 2*754049, 282852, 429907, 390017, 276645, 994856, 250142,
& 144595, 907454, 689648, 4*687580, 978368, 687580, 552742, 105195,
& 942843, 768249, 4*307142, 7*880619, 11*117185, 11*60731,
& 4*178309, 8*74373, 3*214965/
*
END SUBROUTINE DKBVRC
*
SUBROUTINE DKSMRC( NDIM, KLIM, SUMKRO, PRIME, VK, FUNCTN, X )
INTEGER, INTENT(IN):: NDIM, KLIM, PRIME
DOUBLE PRECISION, INTENT(OUT) :: SUMKRO
DOUBLE PRECISION, DIMENSION(:), INTENT(INOUT) :: VK,X
INTEGER :: K, J, JP, NK
DOUBLE PRECISION :: ONE, XT, MVNUNI
PARAMETER ( ONE = 1.d0 )
INTERFACE
DOUBLE PRECISION FUNCTION FUNCTN(N,Z)
DOUBLE PRECISION,DIMENSION(:), INTENT(IN) :: Z
INTEGER, INTENT(IN) :: N
END FUNCTION FUNCTN
END INTERFACE
SUMKRO = 0.D0
*
* Randomize Variable Order
*
NK = MIN( NDIM, KLIM )
DO J = 1, NK - 1
CALL random_number(MVNUNI)
! JP = J + MVNUNI()*( NK + 1 - J )
JP = J + NINT(MVNUNI*DBLE( NK - J )) ! pab 12 May 2004
XT = VK(J)
VK(J) = VK(JP)
VK(JP) = XT
END DO
*
* Determine Random Shifts for each Variable
*
CALL random_number(X(NDIM+1:2*NDIM))
DO K = 1, PRIME
X(1:NDIM) = ABS( 2.d0*MOD( DBLE(K)*VK(1:NDIM) +
& X(NDIM+1:2*NDIM), ONE ) - ONE )
! DO J = 1, NDIM
! X(J) = ABS( 2*MOD( K*VK(J) + X(NDIM+J), ONE ) - ONE )
! END DO
SUMKRO = SUMKRO + ( FUNCTN(NDIM,X) - SUMKRO )/DBLE( 2*K - 1 )
X(1:NDIM) = ONE - X(1:NDIM)
SUMKRO = SUMKRO + ( FUNCTN(NDIM,X) - SUMKRO )/DBLE( 2*K )
END DO
END SUBROUTINE DKSMRC
END MODULE DKBVRCMOD
MODULE PRECISIONMOD
IMPLICIT NONE
PUBLIC
! Note double precision is the fastest choice for x86 machines
! double (15,307) single (6,37) precision constants
INTEGER, PARAMETER :: gP = SELECTED_REAL_KIND(15,307)
END MODULE PRECISIONMOD
MODULE SSOBOLMOD
USE PRECISIONMOD
IMPLICIT NONE
PRIVATE
PUBLIC :: initSobol, sobolSeq, sobnied
! BLOCK DATA BDSOBL
!
! INITIALIZES LABELLED COMMON /SOBDAT/
! FOR "INSOBL".
!
! THE ARRAY POLY GIVES SUCCESSIVE PRIMITIVE
! POLYNOMIALS CODED IN BINARY, E.G.
! 45 = 100101
! HAS BITS 5, 2, AND 0 SET (COUNTING FROM THE
! RIGHT) AND THEREFORE REPRESENTS
! X**5 + X**2 + X**0
!
! THESE POLYNOMIALS ARE IN THE ORDER USED BY
! SOBOL IN USSR COMPUT. MATHS. MATH. PHYS. 16 (1977),
! 236-242. A MORE COMPLETE TABLE IS GIVEN IN SOBOL AND
! LEVITAN, THE PRODUCTION OF POINTS UNIFORMLY
! DISTRIBUTED IN A MULTIDIMENSIONAL CUBE (IN RUSSIAN),
! PREPRINT IPM AKAD. NAUK SSSR, NO. 40, MOSCOW 1976.
!
! THE INITIALIZATION OF THE ARRAY mVINIT IS FROM THE
! LATTER PAPER. FOR A POLYNOMIAL OF DEGREE M, M INITIAL
! VALUES ARE NEEDED : THESE ARE THE VALUES GIVEN HERE.
! SUBSEQUENT VALUES ARE CALCULATED IN "INSOBL".
!
! ASSUME WE ARE WORKING ON A COMPUTER WITH
! WORD LENGTH AT LEAST mMaxBit BITS EXCLUDING SIGN.
integer :: mI
integer, parameter :: mMaxBit = 31
integer, parameter :: mMaxDim = 40
integer, parameter :: mMaxAtMost = 2**(mMaxBit-1)
!COMMON SOBOL
! mSV TABLE OF DIRECTION NUMBERS
! mS DIMENSION
! mMAXCOL LAST COLUMN OF V TO BE USED
! mCOUNT SEQUENCE NUMBER OF THIS CALL
! mLASTQ NUMERATORS FOR LAST VECTOR GENERATED
! mRECIPD (1/DENOMINATOR) FOR THESE NUMERATORS
INTEGER, dimension(mMaxDim,mMaxBit), SAVE :: mSV
INTEGER, dimension(mMaxDim), SAVE :: mLASTQ
INTEGER, SAVE :: mS,mMAXCOL,mCOUNT,mATMOST
REAL(KIND=gP), save :: mRECIPD
! COMMON SOBDAT
INTEGER, save, dimension(2:mMaxDim) :: mPOLY
integer, save, dimension(2:mMaxDim,8) :: mVINIT
DATA mPOLY /3,7,11,13,19,25,37,59,47,
& 61,55,41,67,97,91,109,103,115,131,
& 193,137,145,143,241,157,185,167,229,171,
& 213,191,253,203,211,239,247,285,369,299/
!
DATA (mVINIT(mI,1),mI=2,40) /39*1/
DATA (mVINIT(mI,2),mI=3,40) /1,3,1,3,1,3,3,1,
& 3,1,3,1,3,1,1,3,1,3,
& 1,3,1,3,3,1,3,1,3,1,
& 3,1,1,3,1,3,1,3,1,3/
DATA (mVINIT(mI,3),mI=4,40) /7,5,1,3,3,7,5,
& 5,7,7,1,3,3,7,5,1,1,
& 5,3,3,1,7,5,1,3,3,7,
& 5,1,1,5,7,7,5,1,3,3/
DATA (mVINIT(mI,4),mI=6,40) /1,7,9,13,11,
& 1,3,7,9,5,13,13,11,3,15,
& 5,3,15,7,9,13,9,1,11,7,
& 5,15,1,15,11,5,3,1,7,9/
DATA (mVINIT(mI,5),mI=8,40) /9,3,27,
& 15,29,21,23,19,11,25,7,13,17,
& 1,25,29,3,31,11,5,23,27,19,
& 21,5,1,17,13,7,15,9,31,9/
DATA (mVINIT(mI,6),mI=14,40) /37,33,7,5,11,39,63,
& 27,17,15,23,29,3,21,13,31,25,
& 9,49,33,19,29,11,19,27,15,25/
DATA (mVINIT(mI,7),mI=20,40) /13,
& 33,115,41,79,17,29,119,75,73,105,
& 7,59,65,21,3,113,61,89,45,107/
DATA (mVINIT(mI,8),mI=38,40) /7,23,39/
INTERFACE getMSBP
MODULE PROCEDURE getMSBP
END INTERFACE
INTERFACE initSobol
MODULE PROCEDURE initSobol
END INTERFACE
INTERFACE GENSCRML
MODULE PROCEDURE GENSCRML
END INTERFACE
INTERFACE GENSCRMU
MODULE PROCEDURE GENSCRMU
END INTERFACE
INTERFACE sobolSeq
MODULE PROCEDURE sobolSeq
END INTERFACE
INTERFACE sobnied
MODULE PROCEDURE sobnied
END INTERFACE
INTERFACE dksmrc
MODULE PROCEDURE dksmrc
END INTERFACE
INTERFACE uni
MODULE PROCEDURE uni
END INTERFACE
CONTAINS
FUNCTION getMSBP(J) result (nb)
!getMSBP Returns the Most Significant Bit position
!
! CALL ix = getMSBP(x);
!
! ix = Most Significant Bit position
! x = number
!
! getMSBP calculates the most significant bit position in X that contains a
! one, i.e.,
! MSB(X) = max(i|2^i<=x) for X~=0
!
integer, intent(in) :: J
integer :: nb
integer :: I
nb = 0
I = J/2
DO WHILE (I>0)
nb = nb + 1
I = I / 2
ENDDO
end function getMSBP
SUBROUTINE initSobol(INFORM,TAUS,NDIM, ATMOST,
* NUMDS,IFLAG)
! InitSobol Initializes the sobol sequence
! Inputs:
! NDIM : Number of dimensions
! ATMOST : Maximum sequence length, i.e., upper bound on the number
! of calls the user intends to make on "ssobseq"
! NUMDS : Number of Digits to Scramble if IFLAG==1 or IFLAG==3
! IFLAG : integer defining scrambling of sequences:
! 0 : No Scrambling
! 1 : Owen type Scrambling
! 2 : Faure-Tezuka type Scrambling
! 3 : Owen + Faure-Tezuka type Scrambling
! Uses the member variables: mPOLY and mVINIT
! Outputs:
! INFORM = 0 If no error occurred otherwise
! 2 If NDIM < 1 .OR. mMaxDim < NDIM
! 3 If ATMOST < 1 .OR. mMaxAtMost <= ATMOST
! 4 If ((IFLAG==1 OR IFLAG==3) AND (mMaxBit < NUMDS))
! TAUS = Defines "FAVORABLE" values as
! discussed in BRATLEY/FOX. These have the form
! N = 2**K WHERE K .GE. (TAUS+NDIM-1) for integration
! and k .gt. taus for global optimization.
! If NDIM>12 then TAUS = -1
! Initializes the member variables:
! mSV, mS, mMAXCOL, mCOUNT, mLASTQ, mRECIPD, mATMOST
! Used in SOBOLSEQ
!
! InitSobol initializes member variables for scrambled sobol sequence
!
!
! THIS IS MODIFIED ROUTINE OF "INSOBL".
!
! NEXT CHECK "ATMOST", AN UPPER BOUND ON THE NUMBER
! OF CALLS THE USER INTENDS TO MAKE ON "GOSOBL". IF
! THIS IS POSITIVE AND LESS THAN mMaxAtMost = 2**(mMaxBit-1),
! THEN FLAG(2) = .TRUE.
! (WE ASSUME WE ARE WORKING ON A COMPUTER WITH
! WORD LENGTH AT LEAST mMaxBit BITS EXCLUDING SIGN.)
! THE NUMBER OF COLUMNS OF THE ARRAY V WHICH
! ARE INITIALIZED IS
! mMAXCOL = NUMBER OF BITS IN ATMOST.
! IN "GOSOBL" WE CHECK THAT THIS IS NOT EXCEEDED.
!
! THE LEADING ELEMENTS OF EACH ROW OF V ARE
! INITIALIZED USING "mVINIT" FROM "BDSOBL".
! EACH ROW CORRESPONDS TO A PRIMITIVE POLYNOMIAL
! (AGAIN, SEE "BDSOBL"). IF THE POLYNOMIAL HAS
! DEGREE M, ELEMENTS AFTER THE FIRST M ARE CALCULATED.
!
! THE NUMBERS IN V ARE ACTUALLY BINARY FRACTIONS.
! LSM ARE LOWER TRIAUGULAR SCRAMBLING MATRICES.
! USM ARE UPPER TRIAUGULAR SCRMABLING MATRIX.
! mSV ARE SCAMBLING GENERATING MATRICES AND THE NUMBERS
! ARE BINARY FRACTIONS.
! "mRECIPD" HOLDS 1/(THE COMMON DENOMINATOR OF ALL
! OF THEM).
!
!
! "INSSOBL" IMPLICITLY COMPUTES THE FIRST SHIFTED
! VECTOR "mLASTQ", AND RETURN IT TO THE CALLING
! PROGRAM. SUBSEQUENT VECTORS COME FROM "GOSSOBL".
! "mLASTQ" HOLDS NUMERATORS OF THE LAST VECTOR GENERATED.
!
!
integer, intent(in) :: NDIM,ATMOST,NUMDS,IFLAG
INTEGER, INTENT(OUT) :: INFORM,TAUS
! REAL(kind=gP), dimension(:), intent(out) :: QUASI
INTEGER, dimension(mMaxDim,mMaxBit) :: V, LSM
integer, dimension(mMaxBit,mMaxBit) :: USM
integer, dimension(mMaxDim,mMaxBit,mMaxBit) :: TV
integer, dimension(mMaxDim) :: SHIFT
integer, dimension(mMaxBit) :: USHIFT
INTEGER, dimension(13),save :: TAU
INTEGER I,J,K,P,M,NEWV,L,PP
INTEGER TEMP1,TEMP2,TEMP3,TEMP4,MAXX
REAL(KIND=gP) :: LL
LOGICAL, dimension(8) :: INCLUD
! EXTERNAL IEOR
! COMMON /SOBDAT/ mPOLY,mVINIT
! COMMON /SOBOL/ mS,mMAXCOL,mSV,mCOUNT,mLASTQ,mRECIPD
! SAVE /SOBDAT/,/SOBOL/
DATA TAU /0,0,1,3,5,8,11,15,19,23,27,31,35/
inform = 0
mMAXCOL = 0
mS = NDIM
mATMOST = ATMOST
IF (mS < 1 .OR. mMaxDim < mS) THEN
INFORM = 2
RETURN
ENDIF
IF ( mATMOST < 1 .OR. mMaxAtMost <= mATMOST) THEN
INFORM = 3
RETURN
ENDIF
if ((IFLAG.EQ.1 .or. IFLAG.EQ.3) .AND. (mMaxBit < NUMDS)) then
INFORM = 4
return
endif
IF (mS .LE. 13) THEN
TAUS = TAU(mS)
ELSE
TAUS = -1
! RETURN A DUMMY VALUE TO THE CALLING PROGRAM
ENDIF
! FIND NUMBER OF BITS IN ATMOST
mMAXCOL = getMSBP(mATMOST)+1
! INITIALIZE V
V(1,1:mMAXCOL) = 1
DO I = 2, mS ! 100
! FIND DEGREE OF POLYNOMIAL I FROM BINARY ENCODING
J = mPOLY(I)
M = getMSBP(J)
! WE EXPAND THIS BIT PATTERN TO SEPARATE COMPONENTS
! OF THE LOGICAL ARRAY INCLUD.
DO K = M, 1, -1
INCLUD(K) = (MOD(J,2) .EQ. 1)
J = J / 2
enddo ! K
! THE LEADING ELEMENTS OF ROW I COME FROM mVINIT
V(I,1:M) = mVINIT(I, 1:M)
!
! CALCULATE REMAINING ELEMENTS OF ROW I AS EXPLAINED
! IN BRATLEY AND FOX, SECTION 2
DO J = M+1, mMAXCOL
NEWV = V(I, J-M)
L = 1
DO K = 1, M
L = 2 * L
IF (INCLUD(K)) NEWV = IEOR(NEWV, L * V(I, J-K))
enddo ! K
V(I,J) = NEWV
enddo ! J
enddo ! I
!
! MULTIPLY COLUMNS OF V BY APPROPRIATE POWER OF 2
!
L = 1
DO J = mMAXCOL-1, 1, -1
L = 2 * L
V(1:mS,J) = V(1:mS,J) * L
enddo ! J
!
! COMPUTING GENERATOR MATRICES OF USER CHOICE
!
IF (IFLAG .EQ. 0) THEN
FORALL (I = 1:mS, J = 1:mMAXCOL) mSV(I,J) = V(I,J)
SHIFT(1:mS) = 0
LL = DBLE(2**(mMAXCOL))
ELSE
IF ((IFLAG .EQ. 1) .OR. (IFLAG .EQ. 3)) THEN
CALL GENSCRML(NUMDS,LSM,SHIFT)
DO I = 1,mS
DO J = 1,mMAXCOL
L = 1
TEMP2 = 0
DO P = NUMDS,1,-1
TEMP1 = 0
DO K = 1,mMAXCOL
TEMP1 = TEMP1+
& (IBITS(LSM(I,P),K-1,1)*IBITS(V(I,J),K-1,1))
enddo ! K
TEMP1 = MOD(TEMP1,2)
TEMP2 = TEMP2+TEMP1*L
L = 2 * L
enddo ! P
mSV(I,J) = TEMP2
enddo ! J
enddo ! I
LL= DBLE(2**(NUMDS))
ENDIF
IF ((IFLAG .EQ. 2) .OR. (IFLAG .EQ. 3)) THEN
CALL GENSCRMU(USM,USHIFT)
IF (IFLAG .EQ. 2) THEN
MAXX = mMAXCOL
ELSE
MAXX = NUMDS
ENDIF
DO I = 1,mS
DO J = 1,mMAXCOL
P = MAXX
DO K = 1,MAXX
IF (IFLAG .EQ. 2) THEN
TV(I,P,J) = IBITS(V(I,J),K-1,1)
ELSE
TV(I,P,J) = IBITS(mSV(I,J),K-1,1)
ENDIF
P = P-1
enddo ! K
enddo ! J
DO PP = 1,mMAXCOL
TEMP2 = 0
TEMP4 = 0
L = 1
DO J = MAXX,1,-1
TEMP1 = 0
TEMP3 = 0
DO P = 1,mMAXCOL
TEMP1 = TEMP1 + TV(I,J,P)*USM(P,PP)
IF (PP .EQ. 1) THEN
TEMP3 = TEMP3 + TV(I,J,P)*USHIFT(P)
ENDIF
enddo ! P
TEMP1 = MOD(TEMP1,2)
TEMP2 = TEMP2 + TEMP1*L
IF (PP .EQ. 1) THEN
TEMP3 = MOD(TEMP3,2)
TEMP4 = TEMP4 + TEMP3*L
ENDIF
L = 2*L
enddo ! J
mSV(I,PP) = TEMP2
IF (PP .EQ. 1) THEN
IF (IFLAG .EQ. 3) THEN
SHIFT(I) = IEOR(TEMP4, SHIFT(I))
ELSE
SHIFT(I) = TEMP4
ENDIF
ENDIF
enddo ! PP
enddo ! I
LL = DBLE(2**(MAXX))
ENDIF
ENDIF
!
! mRECIPD IS 1/(COMMON DENOMINATOR OF THE ELEMENTS IN V)
!
mRECIPD = 1.0_gP / LL
! SET UP FIRST VECTOR AND VALUES FOR "SOBOLSEQ"
mCOUNT = 0
mLASTQ(1:mS) = SHIFT(1:mS)
! QUASI(1:mS) = DBLE(mLASTQ(1:mS))*mRECIPD
RETURN
END subroutine initSobol
FUNCTION UNI() result (val)
*
* Random number generator, adapted from F. James
* "A Review of Random Number Generators"
* Comp. Phys. Comm. 60(1990), pp. 329-344.
*
real(kind=gP) SEEDS(24), TWOM24, CARRY,val
PARAMETER ( TWOM24 = 1.0_gP/16777216.0_gP )
INTEGER I, J
SAVE I, J, CARRY, SEEDS
DATA I, J, CARRY / 24, 10, 0.0 /
DATA SEEDS /
& 0.8804418, 0.2694365, 0.0367681, 0.4068699, 0.4554052, 0.2880635,
& 0.1463408, 0.2390333, 0.6407298, 0.1755283, 0.7132940, 0.4913043,
& 0.2979918, 0.1396858, 0.3589528, 0.5254809, 0.9857749, 0.4612127,
& 0.2196441, 0.7848351, 0.4096100, 0.9807353, 0.2689915, 0.5140357/
! & 0.8804418_gP, 0.2694365_gP, 0.0367681_gP, 0.4068699_gP,
! & 0.4554052_gP, 0.2880635_gP,
! & 0.1463408_gP, 0.2390333_gP, 0.6407298_gP, 0.1755283_gP,
! & 0.7132940_gP, 0.4913043_gP,
! & 0.2979918_gP, 0.1396858_gP, 0.3589528_gP, 0.5254809_gP,
! & 0.9857749_gP, 0.4612127_gP,
! & 0.2196441_gP, 0.7848351_gP, 0.4096100_gP, 0.9807353_gP,
! & 0.2689915_gP, 0.5140357_gP/
CALL random_number(val)
return
val = SEEDS(I) - SEEDS(J) - CARRY
IF ( val .LT. 0.0_gP ) THEN
val = val + 1.0_gP
CARRY = TWOM24
ELSE
CARRY = 0.0_gP
ENDIF
SEEDS(I) = val
I = 24 - MOD( 25-I, 24 )
J = 24 - MOD( 25-J, 24 )
RETURN
END function uni
SUBROUTINE GENSCRML(NUMDS,LSM,SHIFT)
! GENERATING LOWER TRIANGULAR SCRMABLING MATRICES AND SHIFT VECTORS.
! INPUTS :
! FROM INSSOBL : NUMDS
! FROM BLOCK DATA "SOBOL" : mS, mMAXCOL,
!
! OUTPUTS :
! TO initSobol : LSM, SHIFT
integer,intent(in) :: NUMDS
integer, dimension(mMaxDim,mMaxBit), intent(inout) :: LSM
integer, dimension(mMaxDim), intent(inout) :: SHIFT
INTEGER :: P,I,J,TEMP,STEMP,L,LL
! REAL(KIND=gP) :: UNI
! COMMON /SOBOL/ mS,mMAXCOL
! SAVE /SOBOL/
DO 10 P = 1,mS
SHIFT(P) = 0
L = 1
DO 20 I = NUMDS,1,-1
LSM(P,I) = 0
! CALL random_number(UNI)
STEMP = MOD((int(UNI()*1000.0_gP)),2)
SHIFT(P) = SHIFT(P)+STEMP*L
L = 2 * L
LL = 1
DO 30 J = mMAXCOL,1,-1
IF (J .EQ. I) THEN
TEMP = 1
ELSE IF (J .LT. I) THEN
! CALL random_number(UNI)
TEMP = MOD((int(UNI()*1000.0_gP)),2)
ELSE
TEMP = 0
ENDIF
LSM(P,I) = LSM(P,I) + TEMP*LL
LL = 2 * LL
30 CONTINUE
20 CONTINUE
10 CONTINUE
RETURN
END SUBROUTINE GENSCRML
SUBROUTINE GENSCRMU(USM,USHIFT)
! GENERATING UPPER TRIANGULAR SCRMABLING MATRICES AND
! SHIFT VECTORS.
! INPUTS :
! FROM BLOCK DATA "SOBOL" : mS, mMAXCOL,
!
! OUTPUTS :
! TO INSSOBL : USM, USHIFT
integer, dimension(mMaxBit,mMaxBit), intent(inout) :: USM
integer, dimension(mMaxBit), intent(inout) :: USHIFT
INTEGER I,J,TEMP
! REAL(KIND=gP) :: UNI
! COMMON /SOBOL/ mS,mMAXCOL
! SAVE /SOBOL/
DO 20 I = 1,mMAXCOL
! CALL random_number(UNI)
USHIFT(I) = MOD((int(UNI()*1000.0_gP)),2)
DO 30 J = 1,mMAXCOL
IF (J .EQ. I) THEN
TEMP = 1
ELSE IF (J .GT. I) THEN
! CALL random_number(UNI)
TEMP = MOD((int(UNI()*1000.0_gP)),2)
ELSE
TEMP = 0
ENDIF
USM(I,J) = TEMP
30 CONTINUE
20 CONTINUE
RETURN
END SUBROUTINE GENSCRMU
SUBROUTINE sobolSeq(QUASI,INFORM)
!SOBOLSEQ GENERATES A NEW QUASIRANDOM VECTOR WITH EACH CALL
!
! IT ADAPTS THE IDEAS OF ANTONOV AND SALEEV,
! USSR COMPUT. MATHS. MATH. PHYS. 19 (1980),
! 252 - 256
!
! The user must call "initSobol" before calling
! "sobolSeq". After calling "initsobol", test
! if inform == 0. if inform>0 then
! do not call "sobolSeq".
! "sobolSeq" checks that the user does not make more calls
! than he said he would : see the comments
! to "initSobol".
!
! INPUTS:
! FROM USER'S CALLING PROGRAM:
! NONE
!
! FROM LABELLED COMMON /SOBOL/:
! mSV TABLE OF DIRECTION NUMBERS
! mS DIMENSION
! mMAXCOL LAST COLUMN OF mSV TO BE USED
! mCOUNT SEQUENCE NUMBER OF THIS CALL
! mLASTQ NUMERATORS FOR LAST VECTOR GENERATED
! mRECIPD (1/DENOMINATOR) FOR THESE NUMERATORS
!
REAL(KIND=gP), dimension(:), intent(out) :: QUASI
integer, intent(inout) :: inform
INTEGER :: I,L
! INTEGER mSV(40,31),mS,mMAXCOL,mCOUNT,mLASTQ(40)
! COMMON /SOBOL/ S,mMAXCOL,mSV,mCOUNT,mLASTQ,mRECIPD
! SAVE /SOBOL/
!
! FORALL ( I = 1:mS)
! QUASI(I) = DBLE(mLASTQ(I)) * mRECIPD
! END FORALL
QUASI(1:mS) = DBLE(mLASTQ(1:mS))*mRECIPD
! FIND POSITION OF RIGHTMOST ZERO BIT IN mCOUNT
L = 1
I = mCOUNT
do while (MOD(I,2) .EQ. 1)
I = I / 2
L = L + 1
ENDDO
! CHECK THAT THE USER IS NOT CHEATING
IF (L > mMAXCOL) THEN
INFORM = 4
! WARNING: Reached the end of the sobol sequence
! Next call will wrap around and return the same numbers
! as for mCOUNT = 0
! Call initSobol to increase mATMOST before calling sobolseq again.
else
INFORM = 0
! Calculate the new components of quasi,
! first the numerators
FORALL ( I = 1:mS)
mLASTQ(I) = IEOR(mLASTQ(I), mSV(I,L))
END FORALL
mCOUNT = mCOUNT + 1
ENDIF
RETURN
END SUBROUTINE sobolSeq
!***********************************************************
! MAIN INTEGRATION ROUTINE SOBNIED
!***********************************************************
SUBROUTINE SOBNIED( NDIM, MINVLS, MAXVLS, FUNCTN, ABSEPS, RELEPS,
& ABSERR, FINEST, INFORM )
use precisionmod
implicit none
*
* Automatic Multidimensional Integration Subroutine
*
* AUTHOR: Per A. Brodtkorb
! Norwegian Defence Research Establishment
! P.O. Box 115
! N-3191 Horten
! Norway
! Email: Per.Brodtkorb@ffi.no
!
* Last Change: 6/19/2004
*
* SOBNIED computes an approximation to the integral
*
* 1 1 1
* I I ... I F(X) dx(NDIM)...dx(2)dx(1)
* 0 0 0
*
*
* SOBNIED uses scrambled SOBOL sequences for the first 40 variables.
* The primary reference is
* If there are more than 40 variables, the remaining variables are
* integrated using the rule described in the reference
* "On a Number-Theoretical Integration Method"
* H. Niederreiter, Aequationes Mathematicae, 8(1972), pp. 304-11.
*
*************** Parameters ********************************************
****** Input parameters
* NDIM Number of variables, must exceed 1, but not exceed 100
* MINVLS Integer minimum number of function evaluations allowed.
* MINVLS must not exceed MAXVLS. If MINVLS < 0 then the
* routine assumes a previous call has been made with
* the same integrand and continues that calculation.
* MAXVLS Integer maximum number of function evaluations allowed.
* FUNCTN EXTERNALly declared user defined function to be integrated.
* It must have parameters (NDIM,Z), where Z is a real array
* of dimension NDIM.
*
* ABSEPS Required absolute accuracy.
* RELEPS Required relative accuracy.
****** Output parameters
* MINVLS Actual number of function evaluations used.
* ABSERR Estimated absolute accuracy of FINEST.
* FINEST Estimated value of integral.
* INFORM INFORM = 0 for normal exit, when
* ABSERR <= MAX(ABSEPS, RELEPS*ABS(FINEST))
* and
* INTVLS <= MAXCLS.
* INFORM = 1 If MAXVLS was too small to obtain the required
* accuracy. In this case a value FINEST is returned with
* estimated absolute accuracy ABSERR.
* INFORM = 2 If NDIM>1040 or NDIM<1
************************************************************************
INTEGER, INTENT(IN) :: NDIM, MAXVLS
INTEGER, INTENT(INOUT) :: MINVLS
INTEGER, INTENT(OUT) :: INFORM
REAL(KIND=gP), INTENT(IN) :: ABSEPS, RELEPS
REAL(KIND=gP), INTENT(OUT) :: FINEST, ABSERR
INTEGER :: NP,PLIM,NLIM,KLIM,KLIMI,SAMPLS,I,INTVLS,MINSMP,NK
integer :: numRep, J, TAUS
INTEGER, parameter :: NUMDS=30,IFLAG=1
PARAMETER ( PLIM = 28, NLIM = 1040, KLIM = mMaxDim, MINSMP = 8 )
INTEGER , DIMENSION(PLIM) :: P
REAL(KIND=gP) :: DIFINT,FINVAL,VARSQR,VAREST,VARPRD,VALUE
REAL(KIND=gP), PARAMETER :: ONE = 1.D0 , ZERO = 0.D0
REAL(KIND=gP), DIMENSION(2*NLIM) :: X = 0.d0
REAL(KIND=gP), DIMENSION(NLIM) :: VK = 0.d0
logical :: NPtooSmall,errorTooLarge,numSamplesOk
INTERFACE
REAL(KIND=gP) FUNCTION FUNCTN(N,Z)
use precisionmod
REAL(KIND=gP),DIMENSION(:), INTENT(IN) :: Z
INTEGER, INTENT(IN) :: N
END FUNCTION FUNCTN
END INTERFACE
DATA P / 31, 47, 73, 113, 173, 263, 397, 593, 907, 1361,
& 2053, 3079, 4621, 6947, 10427, 15641, 23473, 35221,
& 52837, 79259, 118891, 178349, 267523, 401287, 601943,
& 902933,1354471,2031713/
SAVE P, SAMPLS, NP, VAREST
IF ( NDIM .GT. NLIM .OR. NDIM .LT. 1 ) THEN
INFORM = 2
FINEST = ZERO
ABSERR = ONE
RETURN
ENDIF
NK = MIN( NDIM, KLIM )
IF ( MINVLS >= 0 ) THEN
FINEST = ZERO
VAREST = ZERO
SAMPLS = MINSMP
NP = 1
NPtooSmall = ( MINVLS >= 2*SAMPLS*P(NP) )
do while(NPtooSmall .AND. NP<PLIM)
NP = NP + 1
NPtooSmall = ( MINVLS >= 2*SAMPLS*P(NP) )
enddo
if (NPtooSmall) then
SAMPLS = MAX( MINSMP, MINVLS/( 2*P(NP) ) )
endif
ENDIF
numRep = 1 !max(1,nint(MAXVLS/mMaxAtMost))
INFORM = 1
INTVLS = 0
KLIMI = KLIM
errorTooLarge = .TRUE.
do J = 1,numRep
CALL initSobol(inform,TAUS,NK,MAXVLS/numRep,NUMDS,IFLAG)
if (inform.ne.0) then
FINEST = ZERO
ABSERR = ONE
RETURN
endif
INFORM = 1
numSamplesOk = ( INTVLS + 2*SAMPLS*P(NP) <= MAXVLS )
do while (errorTooLarge .and. numSamplesOk)
DO I = 1, NDIM-NK
VK(I) = INT( P(NP)*2**(DBLE(I)/(NDIM-KLIM+1)) )
VK(I) = MOD( VK(I)/P(NP), ONE )
END DO
FINVAL = ZERO
VARSQR = ZERO
DO I = 1, SAMPLS
CALL DKSMRC( NDIM, KLIMI, VALUE, P(NP),VK, FUNCTN, X )
DIFINT = ( VALUE - FINVAL )/DBLE(I)
FINVAL = FINVAL + DIFINT
VARSQR = DBLE( I - 2 )*VARSQR/DBLE(I) + DIFINT*DIFINT
END DO
INTVLS = INTVLS + 2*SAMPLS*P(NP)
VARPRD = VAREST*VARSQR
FINEST = FINEST + ( FINVAL - FINEST )/( ONE + VARPRD )
IF ( VARSQR > ZERO ) VAREST = ( ONE + VARPRD )/VARSQR
ABSERR = 3.0_gP*SQRT( VARSQR/( ONE + VARPRD ) )
errorTooLarge = (ABSERR > MAX(ABSEPS, ABS(FINEST)*RELEPS))
IF ( errorTooLarge ) THEN
IF ( NP < PLIM ) THEN
NP = NP + 1
ELSE
SAMPLS = MIN(3*SAMPLS/2, (MAXVLS - INTVLS)/(2*P(NP)))
SAMPLS = MAX( MINSMP, SAMPLS )
ENDIF
numSamplesOk = ( INTVLS + 2*SAMPLS*P(NP) <= MAXVLS )
ELSE
INFORM = 0
ENDIF
enddo
enddo
MINVLS = INTVLS
END SUBROUTINE SOBNIED
SUBROUTINE DKSMRC( NDIM, KLIM, SUMKRO, PRIME, VK,FUNCTN, X )
use precisionmod
implicit none
INTEGER, INTENT(IN):: NDIM, KLIM, PRIME
REAL(KIND=gP), INTENT(OUT) :: SUMKRO
REAL(KIND=gP), DIMENSION(:), INTENT(INOUT) :: VK,X
INTEGER :: K, NK, inform
REAL(KIND=gP) :: ONE, XT, MVNUNI
PARAMETER ( ONE = 1.0_gP )
INTERFACE
REAL(KIND=gP) FUNCTION FUNCTN(N,Z)
use precisionmod
REAL(KIND=gP),DIMENSION(:), INTENT(IN) :: Z
INTEGER, INTENT(IN) :: N
END FUNCTION FUNCTN
END INTERFACE
SUMKRO = 0.0_gP
NK = MIN( NDIM, KLIM )
* Determine Random Shifts for each Variable
if (NK<NDIM) THEN
CALL random_number(X(NDIM+NK:2*NDIM))
ENDIF
DO K = 1, PRIME
CALL sobolSeq(X,inform)
if (NK<NDIM) THEN
X(NK+1:NDIM) = ABS( 2.0_gP*MOD( DBLE(K)*VK(1:NDIM-NK) +
& X(NDIM+1+NK:2*NDIM), ONE ) - ONE )
endif
SUMKRO = SUMKRO + ( FUNCTN(NDIM,X) - SUMKRO )/DBLE( 2*K - 1 )
! X(1:NDIM) = ONE - X(1:NDIM)
CALL sobolSeq(X,inform)
if (NK<NDIM) THEN
X(NK+1:NDIM) = ONE - X(NK+1:NDIM)
endif
SUMKRO = SUMKRO + ( FUNCTN(NDIM,X) - SUMKRO )/DBLE( 2*K )
END DO
END SUBROUTINE DKSMRC
END MODULE SSOBOLMOD
* KROBOVMOD is a module containing a:
*
* Automatic Multidimensional Integration Subroutine
*
* AUTHOR: Alan Genz
* Department of Mathematics
* Washington State University
* Pulman, WA 99164-3113
* Email: AlanGenz@wsu.edu
*
* Last Change: 4/15/98
*
* revised pab 10.03.2000
* - updated to f90 (i.e. changed to assumed shape arrays + changing integers to DBLE)
* - put it into a module
*
* KROBOV computes an approximation to the integral
*
* 1 1 1
* I I ... I F(X) dx(NDIM)...dx(2)dx(1)
* 0 0 0
*
*
* KROBOV uses randomized Korobov rules. The primary references are
* "Randomization of Number Theoretic Methods for Multiple Integration"
* R. Cranley and T.N.L. Patterson, SIAM J Numer Anal, 13, pp. 904-14,
* and
* "Optimal Parameters for Multidimensional Integration",
* P. Keast, SIAM J Numer Anal, 10, pp.831-838.
*
*************** Parameters ********************************************
****** Input parameters
* NDIM Number of variables, must exceed 1, but not exceed 100
* MINVLS Integer minimum number of function evaluations allowed.
* MINVLS must not exceed MAXVLS. If MINVLS < 0 then the
* routine assumes a previous call has been made with
* the same integrand and continues that calculation.
* MAXVLS Integer maximum number of function evaluations allowed.
* FUNCTN EXTERNALly declared user defined function to be integrated.
* It must have parameters (NDIM,Z), where Z is a real array
* of dimension NDIM.
* ABSEPS Required absolute accuracy.
* RELEPS Required relative accuracy.
****** Output parameters
* MINVLS Actual number of function evaluations used.
* ABSERR Estimated absolute accuracy of FINEST.
* FINEST Estimated value of integral.
* INFORM INFORM = 0 for normal exit, when
* ABSERR <= MAX(ABSEPS, RELEPS*ABS(FINEST))
* and
* INTVLS <= MAXCLS.
* INFORM = 1 If MAXVLS was too small to obtain the required
* accuracy. In this case a value FINEST is returned with
* estimated absolute accuracy ABSERR.
************************************************************************
! You may initialize the random generator before you
! call KROBOV by the following lines:
!
! call random_seed(SIZE=seed_size)
! allocate(seed(seed_size))
! call random_seed(GET=seed(1:seed_size)) ! get current seed
! seed(1)=seed1 ! change seed
! call random_seed(PUT=seed(1:seed_size))
! deallocate(seed)
MODULE KROBOVMOD
IMPLICIT NONE
PRIVATE
PUBLIC :: KROBOV
INTERFACE KROBOV
MODULE PROCEDURE KROBOV
END INTERFACE
INTERFACE KROSUM
MODULE PROCEDURE KROSUM
END INTERFACE
CONTAINS
!***********************************************************
! MAIN INTEGRATION ROUTINE KROBOV
!***********************************************************
SUBROUTINE KROBOV( NDIM, MINVLS, MAXVLS, FUNCTN, ABSEPS, RELEPS,
& ABSERR, FINEST, INFORM )
*
* Automatic Multidimensional Integration Subroutine
*
* AUTHOR: Alan Genz
* Department of Mathematics
* Washington State University
* Pulman, WA 99164-3113
* Email: AlanGenz@wsu.edu
*
* Last Change: 4/15/98
*
* KROBOV computes an approximation to the integral
*
* 1 1 1
* I I ... I F(X) dx(NDIM)...dx(2)dx(1)
* 0 0 0
*
*
* KROBOV uses randomized Korobov rules. The primary references are
* "Randomization of Number Theoretic Methods for Multiple Integration"
* R. Cranley and T.N.L. Patterson, SIAM J Numer Anal, 13, pp. 904-14,
* and
* "Optimal Parameters for Multidimensional Integration",
* P. Keast, SIAM J Numer Anal, 10, pp.831-838.
*
*************** Parameters ********************************************
****** Input parameters
* NDIM Number of variables, must exceed 1, but not exceed 100
* MINVLS Integer minimum number of function evaluations allowed.
* MINVLS must not exceed MAXVLS. If MINVLS < 0 then the
* routine assumes a previous call has been made with
* the same integrand and continues that calculation.
* MAXVLS Integer maximum number of function evaluations allowed.
* FUNCTN EXTERNALly declared user defined function to be integrated.
* It must have parameters (NDIM,Z), where Z is a real array
* of dimension NDIM.
* ABSEPS Required absolute accuracy.
* RELEPS Required relative accuracy.
****** Output parameters
* MINVLS Actual number of function evaluations used.
* ABSERR Estimated absolute accuracy of FINEST.
* FINEST Estimated value of integral.
* INFORM INFORM = 0 for normal exit, when
* ABSERR <= MAX(ABSEPS, RELEPS*ABS(FINEST))
* and
* INTVLS <= MAXCLS.
* INFORM = 1 If MAXVLS was too small to obtain the required
* accuracy. In this case a value FINEST is returned with
* estimated absolute accuracy ABSERR.
* INFORM = 2 If NDIM>100 or NDIM<1
************************************************************************
IMPLICIT NONE
INTEGER, INTENT(IN) :: NDIM, MAXVLS
INTEGER, INTENT(INOUT) ::MINVLS
INTEGER, INTENT(OUT) ::INFORM
DOUBLE PRECISION, INTENT(IN) :: ABSEPS, RELEPS
DOUBLE PRECISION, INTENT(OUT) :: FINEST, ABSERR
! Local variables:
INTEGER :: NP, PLIM, NLIM, SAMPLS, I, INTVLS, MINSMP
PARAMETER ( PLIM = 20, NLIM = 100, MINSMP = 6 )
INTEGER, DIMENSION(PLIM,NLIM) :: C
INTEGER, DIMENSION(PLIM) :: P
DOUBLE PRECISION :: DIFINT, FINVAL, VARSQR, VAREST, VARPRD, VALUE
DOUBLE PRECISION, DIMENSION(NLIM) :: ALPHA, X, VK
DOUBLE PRECISION :: ONE
PARAMETER ( ONE = 1.d0 )
INTERFACE
DOUBLE PRECISION FUNCTION FUNCTN(N,Z)
DOUBLE PRECISION,DIMENSION(:), INTENT(IN) :: Z
INTEGER, INTENT(IN) :: N
END FUNCTION FUNCTN
END INTERFACE
DATA P /113, 173, 263,397,593,907,1361,2053,3079,4621,6947,
& 10427, 15641,23473, 35221, 52837, 79259,
& 118891, 178349, 267523 /
DATA ( C( 1,I), I = 1, 99 ) /
& 42, 54, 55, 32, 13, 26, 26, 13, 26,
& 14, 13, 26, 35, 2, 2, 2, 2, 56,
& 28, 7, 7, 28, 4, 49, 4, 40, 48,
& 5, 35, 27, 16, 16, 2, 2, 7, 28,
& 4, 49, 4, 56, 8, 2, 2, 56, 7,
& 16, 28, 7, 7, 28, 4, 49, 4, 37,
& 55, 21, 33, 40, 16, 16, 28, 7, 16,
& 28, 4, 49, 4, 56, 35, 2, 2, 2,
& 16, 16, 28, 4, 16, 28, 4, 49, 4,
& 40, 40, 5, 42, 27, 16, 16, 28, 4,
& 16, 28, 4, 49, 4, 8, 8, 2, 2/
DATA ( C( 2,I), I = 1, 99 ) /
& 64, 34, 57, 9, 72, 86, 16, 75, 75,
& 70, 42, 2, 86, 62, 62, 30, 30, 5,
& 42, 70, 70, 70, 53, 70, 70, 53, 42,
& 62, 53, 53, 53, 69, 75, 5, 53, 86,
& 2, 5, 30, 75, 59, 2, 69, 5, 5,
& 63, 62, 5, 69, 30, 44, 30, 86, 86,
& 2, 69, 5, 5, 2, 2, 61, 69, 17,
& 2, 2, 2, 53, 69, 2, 2, 86, 69,
& 13, 2, 2, 37, 43, 65, 2, 2, 30,
& 86, 45, 16, 32, 18, 86, 86, 86, 9,
& 63, 63, 11, 76, 76, 76, 63, 60, 70/
DATA ( C( 3,I), I = 1, 99 ) /
& 111, 67, 98, 36, 48, 110, 2, 131, 2,
& 2, 124, 124, 48, 2, 2, 124, 124, 70,
& 70, 48, 126, 48, 126, 56, 65, 48, 48,
& 70, 2, 92, 124, 92, 126, 131, 124, 70,
& 70, 70, 20, 105, 70, 2, 2, 27, 108,
& 27, 39, 2, 131, 131, 92, 92, 48, 2,
& 126, 20, 126, 2, 2, 131, 38, 117, 2,
& 131, 68, 58, 38, 90, 38, 108, 38, 2,
& 131, 131, 131, 68, 14, 94, 131, 131, 131,
& 108, 18, 131, 56, 85, 117, 117, 9, 131,
& 131, 55, 92, 92, 92, 131, 131, 48, 48/
DATA ( C( 4,I), I = 1, 99 ) /
& 151, 168, 46, 197, 69, 64, 2, 198, 191,
& 134, 134, 167, 124, 16, 124, 124, 124, 124,
& 141, 134, 128, 2, 2, 32, 32, 32, 31,
& 31, 64, 64, 99, 4, 4, 167, 124, 124,
& 124, 124, 124, 124, 107, 85, 79, 85, 111,
& 85, 128, 31, 31, 31, 31, 64, 167, 4,
& 107, 167, 124, 124, 124, 124, 124, 124, 107,
& 183, 2, 2, 2, 62, 32, 31, 31, 31,
& 31, 31, 167, 4, 107, 167, 124, 124, 124,
& 124, 124, 124, 107, 142, 184, 184, 65, 65,
& 183, 31, 31, 31, 31, 31, 167, 4, 107/
DATA ( C( 5,I), I = 1, 99 ) /
& 229, 40, 268, 42, 153, 294, 71, 2, 130,
& 199, 199, 199, 149, 199, 149, 153, 130, 149,
& 149, 15, 119, 294, 31, 82, 260, 122, 209,
& 209, 122, 296, 130, 130, 260, 260, 30, 206,
& 94, 209, 94, 122, 209, 209, 122, 122, 209,
& 130, 2, 130, 130, 38, 38, 79, 82, 94,
& 82, 122, 122, 209, 209, 122, 122, 168, 220,
& 62, 60, 168, 282, 282, 82, 209, 122, 94,
& 209, 122, 122, 122, 122, 258, 148, 286, 256,
& 256, 62, 62, 82, 122, 82, 82, 122, 122,
& 122, 209, 122, 15, 79, 79, 79, 79, 168/
DATA ( C( 6,I), I = 1, 99 ) /
& 264, 402, 406, 147, 452, 153, 224, 2, 2,
& 224, 224, 449, 101, 182, 449, 101, 451, 181,
& 181, 101, 101, 377, 85, 453, 453, 453, 85,
& 197, 451, 2, 2, 101, 449, 449, 449, 173,
& 173, 2, 453, 453, 2, 426, 66, 367, 426,
& 101, 453, 2, 32, 32, 32, 101, 2, 2,
& 453, 223, 147, 449, 290, 2, 453, 2, 83,
& 223, 101, 453, 2, 83, 83, 147, 2, 453,
& 147, 147, 147, 147, 147, 147, 147, 453, 153,
& 153, 147, 2, 224, 290, 320, 453, 147, 431,
& 383, 290, 290, 2, 162, 162, 147, 2, 162/
DATA ( C( 7,I), I = 1, 99 ) /
& 505, 220, 195, 410, 199, 248, 460, 471, 2,
& 331, 662, 547, 209, 547, 547, 209, 2, 680,
& 680, 629, 370, 574, 63, 63, 259, 268, 259,
& 547, 209, 209, 209, 547, 547, 209, 209, 547,
& 547, 108, 63, 63, 108, 63, 63, 108, 259,
& 268, 268, 547, 209, 209, 209, 209, 547, 209,
& 209, 209, 547, 108, 63, 63, 63, 405, 285,
& 234, 259, 259, 259, 259, 209, 209, 209, 209,
& 209, 209, 209, 209, 547, 289, 289, 234, 285,
& 316, 2, 410, 259, 259, 259, 268, 209, 209,
& 209, 209, 547, 547, 209, 209, 209, 285, 316/
DATA ( C( 8,I), I = 1, 99 ) /
& 468, 635, 849, 687, 948, 37, 1014, 513, 2,
& 2, 2, 2, 2, 1026, 2, 2, 1026, 201,
& 201, 2, 1026, 413, 1026, 1026, 2, 2, 703,
& 703, 2, 2, 393, 393, 678, 413, 1026, 2,
& 2, 1026, 1026, 2, 405, 953, 2, 1026, 123,
& 123, 953, 953, 123, 405, 794, 123, 647, 613,
& 1026, 647, 768, 953, 405, 953, 405, 918, 918,
& 123, 953, 953, 918, 953, 536, 405, 70, 124,
& 1005, 529, 207, 405, 405, 953, 953, 123, 918,
& 918, 953, 405, 918, 953, 468, 405, 794, 794,
& 647, 613, 548, 405, 953, 405, 953, 123, 918/
DATA ( C( 9,I), I = 1, 99 ) /
& 1189, 1423, 287, 186, 341, 77, 733, 733, 1116,
& 2, 1539, 2, 2, 2, 2, 2, 1116, 847,
& 1174, 2, 827, 713, 910, 944, 139, 1174, 1174,
& 1539, 1397, 1397, 1174, 370, 33, 1210, 2, 370,
& 1423, 370, 370, 1423, 1423, 1423, 434, 1423, 901,
& 139, 1174, 427, 427, 200, 1247, 114, 114, 1441,
& 139, 728, 1116, 1174, 139, 113, 113, 113, 1406,
& 1247, 200, 200, 200, 200, 1247, 1247, 27, 427,
& 427, 1122, 1122, 696, 696, 427, 1539, 435, 1122,
& 758, 1247, 1247, 1247, 200, 200, 200, 1247, 114,
& 27, 118, 118, 113, 118, 453, 453, 1084, 1406/
DATA ( C(10,I), I = 1, 99 ) /
& 1764, 1349, 1859, 693, 78, 438, 531, 68, 2234,
& 2310, 2310, 2310, 2, 2310, 2310, 2102, 2102, 178,
& 314, 921, 1074, 1074, 1074, 2147, 314, 1869, 178,
& 178, 1324, 1324, 510, 2309, 1541, 1541, 1541, 1541,
& 342, 1324, 1324, 1324, 1324, 510, 570, 570, 2197,
& 173, 1202, 998, 1324, 1324, 178, 1324, 1324, 1541,
& 1541, 1541, 342, 1541, 886, 178, 1324, 1324, 1324,
& 510, 784, 784, 501, 652, 1541, 1541, 1324, 178,
& 1324, 178, 1324, 1541, 342, 1541, 2144, 784, 2132,
& 1324, 1324, 1324, 1324, 510, 652, 1804, 1541, 1541,
& 1541, 2132, 1324, 1324, 1324, 178, 510, 1541, 652/
DATA ( C(11,I), I = 1, 99 ) /
& 2872, 1238, 387, 2135, 235, 1565, 221, 1515, 2950,
& 486, 3473, 2, 2950, 982, 2950, 3122, 2950, 3172,
& 2091, 2091, 9, 3449, 3122, 2846, 3122, 3122, 1947,
& 2846, 3122, 772, 1387, 2895, 1387, 3, 3, 3,
& 1320, 1320, 2963, 2963, 1320, 1320, 2380, 108, 1284,
& 702, 1429, 907, 3220, 3125, 1320, 2963, 1320, 1320,
& 2963, 1320, 1639, 3168, 1660, 2895, 2895, 2895, 2895,
& 1639, 1297, 1639, 404, 3168, 2963, 2943, 2943, 550,
& 1387, 1387, 2895, 2895, 2895, 1387, 2895, 1387, 2895,
& 1320, 1320, 2963, 1320, 1320, 1320, 2963, 1320, 2,
& 3473, 2, 3473, 772, 2550, 9, 1320, 2963, 1320/
DATA ( C(12,I), I = 1, 99 ) /
& 4309, 2339, 4154, 4480, 4967, 630, 5212, 2592, 4715,
& 1808, 1808, 5213, 2, 216, 4014, 3499, 3499, 4204,
& 2701, 2701, 5213, 4157, 1209, 4157, 4460, 335, 4460,
& 1533, 4575, 4013, 4460, 1881, 2701, 4030, 4030, 1881,
& 4030, 1738, 249, 335, 57, 2561, 2561, 2561, 1533,
& 1533, 1533, 4013, 4013, 4013, 4013, 4013, 1533, 856,
& 856, 468, 468, 468, 2561, 468, 2022, 2022, 2434,
& 138, 4605, 1100, 2561, 2561, 57, 57, 3249, 468,
& 468, 468, 57, 468, 1738, 313, 856, 6, 3877,
& 468, 557, 468, 57, 468, 4605, 2022, 2, 4605,
& 138, 1100, 57, 2561, 57, 57, 2022, 5213, 3249/
DATA ( C(13,I), I = 1, 99 ) /
& 6610, 1658, 3022, 2603, 5211, 265, 4985, 3, 4971,
& 2127, 1877, 1877, 2, 2925, 3175, 3878, 1940, 1940,
& 1940, 5117, 5117, 5771, 5117, 5117, 5117, 5117, 5117,
& 5771, 5771, 5117, 3658, 3658, 3658, 3658, 3658, 3658,
& 5255, 2925, 2619, 1714, 4100, 6718, 6718, 4100, 2322,
& 842, 4100, 6718, 5119, 4728, 5255, 5771, 5771, 5771,
& 5117, 5771, 5117, 5117, 5117, 5117, 5117, 5117, 5771,
& 5771, 1868, 4483, 4728, 3658, 5255, 3658, 5255, 3658,
& 3658, 5255, 5255, 3658, 6718, 6718, 842, 2322, 6718,
& 4100, 6718, 4100, 4100, 5117, 5771, 5771, 5117, 5771,
& 5771, 5771, 5771, 5117, 5117, 5117, 5771, 5771, 1868/
DATA ( C(14,I), I = 1, 99 ) /
& 9861, 7101, 6257, 7878, 11170, 11638, 7542, 2592, 2591,
& 6074, 1428, 8925, 11736, 8925, 5623, 5623, 1535, 6759,
& 9953, 9953, 11459, 9953, 7615, 7615, 11377, 11377, 2762,
& 11734, 11459, 6892, 1535, 6759, 4695, 1535, 6892, 2,
& 2, 6892, 6892, 4177, 4177, 6339, 6950, 1226, 1226,
& 1226, 4177, 6892, 6890, 3640, 3640, 1226, 10590, 10590,
& 6950, 6950, 6950, 1226, 6950, 6950, 7586, 7586, 7565,
& 7565, 3640, 3640, 6950, 7565, 6950, 3599, 3599, 3599,
& 2441, 4885, 4885, 4885, 7565, 7565, 1226, 1226, 1226,
& 6950, 7586, 1346, 2441, 6339, 3640, 6950, 10590, 6339,
& 6950, 6950, 6950, 1226, 1226, 6950, 836, 6891, 7565/
DATA ( C(15,I), I = 1, 99 ) /
& 13482, 5629, 6068, 11974, 4732, 14946, 12097, 17609, 11740,
& 15170, 10478, 10478, 17610, 2, 2, 7064, 7064, 7064,
& 5665, 1771, 2947, 4453, 12323, 17610, 14809, 14809, 5665,
& 5665, 2947, 2947, 2947, 2947, 12323, 12323, 4453, 4453,
& 2026, 11772, 2026, 11665, 12323, 12323, 3582, 2940, 2940,
& 6654, 4449, 9254, 11470, 304, 304, 11470, 304, 11470,
& 6156, 9254, 11772, 6654, 11772, 6156, 11470, 11470, 11772,
& 11772, 11772, 11470, 11470, 304, 11470, 11470, 304, 11470,
& 304, 11470, 304, 304, 304, 6654, 11508, 304, 304,
& 6156, 3582, 11470, 11470, 11470, 17274, 6654, 6654, 6744,
& 6711, 6654, 6156, 3370, 6654, 12134, 3370, 6654, 3582/
DATA ( C(16,I), I = 1, 99 ) /
& 13482, 5629, 6068, 11974, 4732, 14946, 12097, 17609, 11740,
& 15170, 10478, 10478, 17610, 2, 2, 7064, 7064, 7064,
& 5665, 1771, 2947, 4453, 12323, 17610, 14809, 14809, 5665,
& 5665, 2947, 2947, 2947, 2947, 12323, 12323, 4453, 4453,
& 2026, 11772, 2026, 11665, 12323, 12323, 3582, 2940, 2940,
& 6654, 4449, 9254, 11470, 304, 304, 11470, 304, 11470,
& 6156, 9254, 11772, 6654, 11772, 6156, 11470, 11470, 11772,
& 11772, 11772, 11470, 11470, 304, 11470, 11470, 304, 11470,
& 304, 11470, 304, 304, 304, 6654, 11508, 304, 304,
& 6156, 3582, 11470, 11470, 11470, 17274, 6654, 6654, 6744,
& 6711, 6654, 6156, 3370, 6654, 12134, 3370, 6654, 3582/
DATA ( C(17,I), I = 1, 99 ) /
& 34566, 38838, 23965, 17279, 35325, 33471, 330, 36050, 26419,
& 3012, 38428, 36430, 36430, 36755, 39629, 5749, 5749, 36755,
& 5749, 14353, 14353, 14353, 32395, 32395, 32395, 32395, 32396,
& 32396, 32396, 32396, 27739, 14353, 36430, 36430, 36430, 15727,
& 38428, 28987, 28987, 27739, 38428, 27739, 18786, 14353, 15727,
& 28987, 19151, 19757, 19757, 19757, 14353, 22876, 19151, 24737,
& 24737, 4412, 30567, 30537, 19757, 30537, 19757, 30537, 30537,
& 4412, 24737, 28987, 19757, 19757, 19757, 30537, 30537, 33186,
& 4010, 4010, 4010, 17307, 15217, 32789, 37709, 4010, 4010,
& 4010, 33186, 33186, 4010, 11057, 39388, 33186, 1122, 15089,
& 39629, 2, 2, 23899, 16466, 16466, 17038, 9477, 9260/
DATA ( C(18,I), I = 1, 99 ) /
& 31929, 40295, 2610, 5177, 17271, 23770, 9140, 952, 39631,
& 3, 11424, 49719, 38267, 25172, 2, 2, 59445, 2,
& 59445, 38267, 44358, 14673, 53892, 14674, 14673, 14674, 41368,
& 17875, 17875, 30190, 20444, 55869, 15644, 25499, 15644, 20983,
& 44358, 15644, 15644, 485, 41428, 485, 485, 485, 41428,
& 53798, 50230, 53798, 50253, 50253, 35677, 35677, 17474, 7592,
& 4098, 17474, 485, 41428, 485, 41428, 485, 41428, 485,
& 41428, 41428, 41428, 41428, 41428, 9020, 22816, 4098, 4098,
& 4098, 7592, 42517, 485, 50006, 50006, 22816, 22816, 9020,
& 485, 41428, 41428, 41428, 41428, 50006, 485, 41428, 41428,
& 41428, 41428, 22816, 41428, 41428, 485, 485, 485, 9020/
DATA ( C(19,I), I = 1, 99 ) /
& 73726, 16352, 16297, 74268, 60788, 8555, 1077, 25486, 86595,
& 59450, 19958, 62205, 62205, 4825, 4825, 89174, 89174, 62205,
& 19958, 62205, 19958, 27626, 63080, 62205, 62205, 62205, 19958,
& 8914, 83856, 30760, 47774, 47774, 19958, 62205, 39865, 39865,
& 74988, 75715, 75715, 74988, 34522, 74988, 74988, 25101, 44621,
& 44621, 44621, 25101, 25101, 25101, 44621, 47768, 41547, 44621,
& 10273, 74988, 74988, 74988, 74988, 74988, 74988, 34522, 34522,
& 67796, 67796, 30208, 2, 67062, 18500, 29251, 29251, 2,
& 67796, 67062, 38649, 59302, 6225, 67062, 6475, 6225, 46772,
& 38649, 67062, 46772, 46772, 67062, 46772, 25372, 67062, 6475,
& 25372, 67062, 67062, 67062, 6225, 67062, 67062, 68247, 80676/
DATA ( C(20,I), I = 1, 99 )/
& 103650, 50089, 70223, 41805, 74847,112775, 40889, 64866, 44053,
& 1754,129471, 13630, 53467, 53467, 61378,133761, 2,133761,
& 2,133761,133761, 65531, 65531, 65531, 38080,133761,133761,
& 131061, 5431, 65531, 78250, 11397, 38841, 38841,107233,107233,
& 111286, 19065, 38841, 19065, 19065, 16099,127638, 82411, 96659,
& 96659, 82411, 96659, 82411, 51986,101677, 39264, 39264,101677,
& 39264, 39264, 47996, 96659, 82411, 47996, 10971, 10004, 82411,
& 96659, 82411, 82411, 82411, 96659, 96659, 96659, 82411, 96659,
& 51986,110913, 51986, 51986,110913, 82411, 54713, 54713, 22360,
& 117652, 22360, 78250, 78250, 91996, 22360, 91996, 97781, 91996,
& 97781, 91996, 97781, 97781, 91996, 97781, 97781, 36249, 39779/
SAVE P, C, SAMPLS, NP, VAREST
IF ( NDIM .GT. NLIM .OR. NDIM .LT. 1 ) THEN
INFORM = 2
FINEST = 0.d0
ABSERR = 1.d0
RETURN
ENDIF
INFORM = 1
INTVLS = 0
IF ( MINVLS .GE. 0 ) THEN
FINEST = 0.d0
VAREST = 0.d0
SAMPLS = MINSMP
DO I = 1, PLIM
NP = I
IF ( MINVLS .LT. 2*SAMPLS*P(I) ) GO TO 10
END DO
SAMPLS = MAX( MINSMP, INT(MINVLS/( 2*P(NP)) ) )
ENDIF
10 VK(1) = ONE/DBLE(P(NP))
DO I = 2, NDIM
VK(I) = MOD( DBLE(C(NP,NDIM-1))*VK(I-1), ONE )
END DO
FINVAL = 0.d0
VARSQR = 0.d0
*
* Compute mean and standard error for SAMPLS randomized lattice rules
*
DO I = 1, SAMPLS
CALL KROSUM( NDIM, VALUE, P(NP), VK, FUNCTN, ALPHA, X )
DIFINT = ( VALUE - FINVAL )/DBLE(I)
FINVAL = FINVAL + DIFINT
VARSQR = DBLE(I - 2)*VARSQR/DBLE(I) + DIFINT*DIFINT
END DO
INTVLS = INTVLS + 2*SAMPLS*P(NP)
VARPRD = VAREST*VARSQR
FINEST = FINEST + ( FINVAL - FINEST )/( 1.d0 + VARPRD )
IF ( VARSQR .GT. 0.d0 ) VAREST = ( 1.d0 + VARPRD )/VARSQR
ABSERR = 3.d0*SQRT( VARSQR/( 1.d0 + VARPRD ) )
IF ( ABSERR .GT. MAX( ABSEPS, ABS(FINEST)*RELEPS ) ) THEN
IF ( NP .LT. PLIM ) THEN
NP = NP + 1
ELSE
SAMPLS = MIN( 3*SAMPLS/2, ( MAXVLS - INTVLS )/( 2*P(NP) ) )
SAMPLS = MAX( MINSMP, SAMPLS )
ENDIF
IF ( INTVLS + 2*SAMPLS*P(NP) .LE. MAXVLS ) GO TO 10
ELSE
INFORM = 0
ENDIF
MINVLS = INTVLS
END SUBROUTINE KROBOV
*
SUBROUTINE KROSUM( NDIM, SUMKRO, PRIME, VK, FUNCTN, ALPHA, X )
INTEGER, INTENT(IN):: NDIM, PRIME
DOUBLE PRECISION, INTENT(OUT) :: SUMKRO
DOUBLE PRECISION, DIMENSION(:), INTENT(INOUT) :: ALPHA,X ! size NDIM
INTEGER :: K !, J
DOUBLE PRECISION :: ONE
DOUBLE PRECISION, DIMENSION(:), INTENT(IN) :: VK
INTERFACE
DOUBLE PRECISION FUNCTION FUNCTN(N,Z)
DOUBLE PRECISION,DIMENSION(:), INTENT(IN) :: Z
INTEGER, INTENT(IN) :: N
END FUNCTION FUNCTN
END INTERFACE
PARAMETER ( ONE = 1.d0 )
SUMKRO = 0.d0
CALL random_number(ALPHA(1:NDIM))
DO K = 1, PRIME
X(1:NDIM) = MOD( DBLE(K)*VK(1:NDIM) + ALPHA(1:NDIM), ONE )
X(1:NDIM) = ABS( 2.d0*X(1:NDIM) - ONE )
! PRINT *,'KROSUM W=',X(1:NDIM)
SUMKRO = SUMKRO+(FUNCTN(NDIM,X)-SUMKRO)/DBLE(2*K-1)
X(1:NDIM) = ONE - X(1:NDIM)
SUMKRO = SUMKRO+(FUNCTN(NDIM,X)-SUMKRO)/DBLE(2*K)
END DO
END SUBROUTINE KROSUM
END MODULE KROBOVMOD