module s2dw_core_mod
        ! Uses
    use s2dw_types_mod
    use s2dw_error_mod
    use s2dw_dl_mod
    use omp_lib
        ! Types
    public type s2dw_wav_abg
        ! Variables
    integer, private, parameter :: FFTW_ESTIMATE = 64
    integer, private, parameter :: FFTW_MEASURE = 0
    integer, private, parameter :: FFTW_FORWARD = -1
    integer, private, parameter :: FFTW_BACKWARD = 1
        ! Subroutines and functions
    public subroutine s2dw_core_init_kernels (K_gamma, Phi2, bl_scoeff, J, B, alpha)
    private function s2dw_core_phi2_integrand (k, bw, alpha) result (integrand)
    public subroutine s2dw_core_init_directionality (Slm, B, N)
    public function s2dw_core_admiss (admiss, K_gamma, Phi2, B, J) result (pass)
    public subroutine s2dw_core_analysis_flm2wav (wav, scoeff, flm, K_gamma, Slm, J, B, N, bl_scoeff, alpha)
    public subroutine s2dw_core_analysis_flm2wav_dynamic (wavdyn, scoeff, flm, K_gamma, Slm, J, B, N, bl_scoeff, alpha)
    public subroutine s2dw_core_synthesis_wav2flm (flm, wav, scoeff, K_gamma, Phi2, Slm, J, B, N, bl_scoeff, alpha)
    public subroutine s2dw_core_synthesis_wav2flm_dynamic (flm, wavdyn, scoeff, K_gamma, Phi2, Slm, J, B, N, bl_scoeff, alpha)
    public subroutine s2dw_core_free_wavdyn (wavdyn)
    private function s2dw_core_params_valid (J, B, alpha, N) result (valid)
    public function s2dw_core_comp_Jmax (B, alpha) result (J_max)
    public function s2dw_core_assimilate_int (x, y) result (assimilated)
    private function quad_weights (theta_t, B) result (w)
    private function binomial (n, r) result (b)
    private function logfact (n) result (logfactn)
    private subroutine trapzd (func, B, alpha, a_lim, b_lim, s, n)
    private function qtrap (func, B, alpha, a_lim, b_lim) result (integral)
    private function qsimp (func, B, alpha, a_lim, b_lim) result (integral)
end module s2dw_core_mod
 Functionality to perform scale discretised wavelet transform on the sphere.
Author: J. D. McEwen (mcewen@mrao.cam.ac.uk)
Version: 0.1 November 2007
public type s2dw_wav_abg
    real (kind=dp), allocatable, dimension (:,:,:) :: coeff
end type s2dw_wav_abg
 Structure to store wavelet coefficients for given scale.  Required for 
 dynamic memory allocation of wavelet coefficients.
integer, private, parameter :: FFTW_ESTIMATE = 64
integer, private, parameter :: FFTW_MEASURE = 0
integer, private, parameter :: FFTW_FORWARD = -1
integer, private, parameter :: FFTW_BACKWARD = 1
public subroutine s2dw_core_init_kernels (K_gamma, Phi2, bl_scoeff, J, B, alpha)
    real (kind=dp), intent(out), dimension (0:J,0:B-1) :: K_gamma
    real (kind=dp), intent(out), dimension (0:B-1) :: Phi2
    integer, intent(out) :: bl_scoeff
    integer, intent(in) :: J
    integer, intent(in) :: B
    real (kind=dp), intent(in) :: alpha
    ! Calls: s2dw_error
end subroutine s2dw_core_init_kernels
 Compute kernels, scaling functions and band limits.
Notes:
Author: J. D. McEwen
Version: 0.1 October 2007
s2dw_core_phi2_integrand
private function s2dw_core_phi2_integrand (k, bw, alpha) result (integrand)
    real (kind=dp), intent(in) :: k
    integer, intent(in) :: bw
    real (kind=dp), intent(in) :: alpha
    real (kind=dp) :: integrand
end function s2dw_core_phi2_integrand
 Integrand of definite integral to be calculated to compute the scaling 
 function.
Notes:
Author: J. D. McEwen
Version: 0.1 October 2007
s2dw_core_init_directionality
public subroutine s2dw_core_init_directionality (Slm, B, N)
    complex (kind=dpc), intent(out), dimension (0:B-1,0:N-1) :: Slm
    integer, intent(in) :: B
    integer, intent(in) :: N
    ! Calls: s2dw_error
end subroutine s2dw_core_init_directionality
 Compute wavelet directionality coefficients.
Variables:
Author: J. D. McEwen
Version: 0.1 October 2007
s2dw_core_admiss
public function s2dw_core_admiss (admiss, K_gamma, Phi2, B, J) result (pass)
    real (kind=dp), intent(out), dimension (0:B-1) :: admiss
    real (kind=dp), intent(in), dimension (0:J,0:B-1) :: K_gamma
    real (kind=dp), intent(in), dimension (0:B-1) :: Phi2
    integer, intent(in) :: B
    integer, intent(in) :: J
    logical :: pass
end function s2dw_core_admiss
 Compute resolution of the identity from scaled kernels and scaling 
 function and check equal to unity for all el.
Notes:
Author: J. D. McEwen
Version: 0.1 October 2007
s2dw_core_analysis_flm2wav
public subroutine s2dw_core_analysis_flm2wav (wav, scoeff, flm, K_gamma, Slm, J, B, N, bl_scoeff, alpha)
    real (kind=dp), intent(out), dimension (0:J, 0:2*B-2, 0:2*B-1, 0:N-1) :: wav
    complex (kind=dpc), intent(out), dimension (0:bl_scoeff-1, 0:bl_scoeff-1) :: scoeff
    complex (kind=dpc), intent(in), dimension (0:B-1, 0:B-1) :: flm
    real (kind=dp), intent(in), dimension (0:J, 0:B-1) :: K_gamma
    complex (kind=dpc), intent(in), dimension (0:B-1, 0:N-1) :: Slm
    integer, intent(in) :: J
    integer, intent(in) :: B
    integer, intent(in) :: N
    integer, intent(in) :: bl_scoeff
    real (kind=dp), intent(in) :: alpha
    ! Calls: dfftw_destroy_plan, dfftw_execute_dft_c2r, dfftw_plan_dft_c2r_1d, s2dw_dl_beta_operator, s2dw_error
end subroutine s2dw_core_analysis_flm2wav
 Compute wavelet and scaling coefficients from harmonic coefficients of 
 original signal using fast algorithm.
Notes:
Author: J. D. McEwen
Version: 0.1 October 2007
s2dw_core_analysis_flm2wav_dynamic
public subroutine s2dw_core_analysis_flm2wav_dynamic (wavdyn, scoeff, flm, K_gamma, Slm, J, B, N, bl_scoeff, alpha)
    type (s2dw_wav_abg), intent(out), allocatable, dimension (:) :: wavdyn
    complex (kind=dpc), intent(out), dimension (0:bl_scoeff-1, 0:bl_scoeff-1) :: scoeff
    complex (kind=dpc), intent(in), dimension (0:B-1, 0:B-1) :: flm
    real (kind=dp), intent(in), dimension (0:J, 0:B-1) :: K_gamma
    complex (kind=dpc), intent(in), dimension (0:B-1, 0:N-1) :: Slm
    integer, intent(in) :: J
    integer, intent(in) :: B
    integer, intent(in) :: N
    integer, intent(in) :: bl_scoeff
    real (kind=dp), intent(in) :: alpha
    ! Calls: dfftw_destroy_plan, dfftw_execute_dft_c2r, dfftw_plan_dft_c2r_1d, s2dw_dl_beta_operator, s2dw_error
end subroutine s2dw_core_analysis_flm2wav_dynamic
 Compute wavelet and scaling coefficients from harmonic coefficients of 
 original signal using fast algorithm, dynamically allocating the memory
 required for the wavelet coefficients dynamically.
Notes:
Author: J. D. McEwen
Version: 0.1 February 2008
s2dw_core_synthesis_wav2flm
public subroutine s2dw_core_synthesis_wav2flm (flm, wav, scoeff, K_gamma, Phi2, Slm, J, B, N, bl_scoeff, alpha)
    complex (kind=dpc), intent(out), dimension (0:B-1, 0:B-1) :: flm
    real (kind=dp), intent(in), dimension (0:J, 0:2*B-2, 0:2*B-1, 0:N-1) :: wav
    complex (kind=dpc), intent(in), dimension (0:bl_scoeff-1, 0:bl_scoeff-1) :: scoeff
    real (kind=dp), intent(in), dimension (0:J, 0:B-1) :: K_gamma
    real (kind=dp), intent(in), dimension (0:B-1) :: Phi2
    complex (kind=dpc), intent(in), dimension (0:B-1, 0:N-1) :: Slm
    integer, intent(in) :: J
    integer, intent(in) :: B
    integer, intent(in) :: N
    integer, intent(in) :: bl_scoeff
    real (kind=dp), intent(in) :: alpha
    ! Calls: dfftw_destroy_plan, dfftw_execute_dft_r2c, dfftw_plan_dft_r2c_1d, s2dw_dl_beta_operator, s2dw_error
end subroutine s2dw_core_synthesis_wav2flm
 Synthesis harmonic coefficients of signal from wavelet and scaling
 coefficients.
Notes:
Author: J. D. McEwen
Version: 0.1 October 2007
s2dw_core_synthesis_wav2flm_dynamic
public subroutine s2dw_core_synthesis_wav2flm_dynamic (flm, wavdyn, scoeff, K_gamma, Phi2, Slm, J, B, N, bl_scoeff, alpha)
    complex (kind=dpc), intent(out), dimension (0:B-1, 0:B-1) :: flm
    type (s2dw_wav_abg), intent(inout), allocatable, dimension (:) :: wavdyn
    complex (kind=dpc), intent(in), dimension (0:bl_scoeff-1, 0:bl_scoeff-1) :: scoeff
    real (kind=dp), intent(in), dimension (0:J, 0:B-1) :: K_gamma
    real (kind=dp), intent(in), dimension (0:B-1) :: Phi2
    complex (kind=dpc), intent(in), dimension (0:B-1, 0:N-1) :: Slm
    integer, intent(in) :: J
    integer, intent(in) :: B
    integer, intent(in) :: N
    integer, intent(in) :: bl_scoeff
    real (kind=dp), intent(in) :: alpha
    ! Calls: dfftw_destroy_plan, dfftw_execute_dft_r2c, dfftw_plan_dft_r2c_1d, s2dw_dl_beta_operator, s2dw_error
end subroutine s2dw_core_synthesis_wav2flm_dynamic
 Synthesise harmonic coefficients of signal from wavelet and scaling
 coefficients, where the memory of the wavelet coefficients has been 
 allocated dynamically (destroying wavelet coefficients in the process).
Notes:
Author: J. D. McEwen
Version: 0.1 February 2008
s2dw_core_free_wavdyn
public subroutine s2dw_core_free_wavdyn (wavdyn)
    type (s2dw_wav_abg), intent(inout), allocatable, dimension (:) :: wavdyn
end subroutine s2dw_core_free_wavdyn
 Free memory corresponding to dynamically allocated wavelet coefficients.
Variables:
Author: J. D. McEwen
Version: 0.1 February 2008
s2dw_core_params_valid
private function s2dw_core_params_valid (J, B, alpha, N) result (valid)
    integer, intent(in) :: J
    integer, intent(in) :: B
    real (kind=dp), intent(in) :: alpha
    integer, optional, intent(in) :: N
    logical :: valid
end function s2dw_core_params_valid
 Check size parameters valid.
Notes:
Author: J. D. McEwen
Version: 0.1 October 2007
s2dw_core_comp_Jmax
public function s2dw_core_comp_Jmax (B, alpha) result (J_max)
    integer, intent(in) :: B
    real (kind=dp), intent(in) :: alpha
    integer :: J_max
end function s2dw_core_comp_Jmax
 Compute maximum analysis depth allowed.
Variables:
Author: J. D. McEwen
Version: 0.1 November 2007
s2dw_core_assimilate_int
public function s2dw_core_assimilate_int (x, y) result (assimilated)
    real (kind=dp), intent(in) :: x
    integer, intent(out) :: y
    logical :: assimilated
end function s2dw_core_assimilate_int
 If a real value is very close to an integer then set to integer, 
 otherwise leave unaltered.  Necessary to avoid numerical precision 
 problems when using ceiling and floor functions.
Variables:
Author: J. D. McEwen
Version: 0.1 November 2007
quad_weights
private function quad_weights (theta_t, B) result (w)
    real (kind=dp), intent(in) :: theta_t
    integer, intent(in) :: B
    real (kind=dp) :: w
end function quad_weights
 Compute quadrature weights for exact quadrature with measure 
 dcos(theta).  Weights are derived by Driscoll and Healy.
Variables:
Author: J. D. McEwen
Version: 0.1 October 2007
binomial
private function binomial (n, r) result (b)
    integer, intent(in) :: n
    integer, intent(in) :: r
    integer :: b
end function binomial
 Compute Binomial coefficient nCr.
Variables:
Author: J. D. McEwen
Version: 0.1 October 2007
logfact
private function logfact (n) result (logfactn)
    integer, intent(in) :: n
    real (kind=dp) :: logfactn
    ! Calls: s2dw_error
end function logfact
 Computes the natural logarithm of an (integer) factorial.
Variables:
Author: J. D. McEwen
Version: 0.1 October 2007
trapzd
private subroutine trapzd (func, B, alpha, a_lim, b_lim, s, n)
    interface func
        function func (k, B, alpha) result (integrand)
            real (kind=dp), intent(in) :: k
            integer, intent(in) :: B
            real (kind=dp), intent(in) :: alpha
            real (kind=dp) :: integrand
        end function func
    end interface func
    integer, intent(in) :: B
    real (kind=dp), intent(in) :: alpha
    real (kind=dp), intent(IN) :: a_lim
    real (kind=dp), intent(IN) :: b_lim
    real (kind=dp), intent(INOUT) :: s
    integer, intent(IN) :: n
end subroutine trapzd
 Computes nth stage of refinement of extended trapezoidal rule.
 Adapted from numerical recipes for computing scaling functions squared.
Notes:
Author: J. D. McEwen
Version: 0.1 June 2005
qtrap
private function qtrap (func, B, alpha, a_lim, b_lim) result (integral)
    interface func
        function func (k, B, alpha) result (integrand)
            real (kind=dp), intent(in) :: k
            integer, intent(in) :: B
            real (kind=dp), intent(in) :: alpha
            real (kind=dp) :: integrand
        end function func
    end interface func
    integer, intent(in) :: B
    real (kind=dp), intent(in) :: alpha
    real (kind=dp), intent(in) :: a_lim
    real (kind=dp), intent(in) :: b_lim
    real (kind=dp) :: integral
    ! Calls: s2dw_error, trapzd
end function qtrap
 Computes the integral of the function func from a to b using the 
 trapezoid method.  Adapted from numerical recipes for computing scaling 
 functions squared.
Notes:
Author: J. D. McEwen
Version: 0.1 June 2005
qsimp
private function qsimp (func, B, alpha, a_lim, b_lim) result (integral)
    interface func
        function func (k, B, alpha) result (integrand)
            real (kind=dp), intent(in) :: k
            integer, intent(in) :: B
            real (kind=dp), intent(in) :: alpha
            real (kind=dp) :: integrand
        end function func
    end interface func
    integer, intent(in) :: B
    real (kind=dp), intent(in) :: alpha
    real (kind=dp), intent(IN) :: a_lim
    real (kind=dp), intent(IN) :: b_lim
    real (kind=dp) :: integral
    ! Calls: s2dw_error, trapzd
end function qsimp
 Computes the integral of the function func from a to b using
 Simpson's rule.  Adapted from numerical recipes for computing scaling 
 functions squared.
Notes:
Author: J. D. McEwen
Version: 0.1 June 2005