#:include "common.fypp" #:set BETA_REAL_KINDS_TYPES = [item for item in REAL_KINDS_TYPES if item[0] in ('sp', 'dp', 'xdp')] #:set BETA_CMPLX_KINDS_TYPES = [item for item in CMPLX_KINDS_TYPES if item[0] in ('sp', 'dp', 'xdp')] #:set RC_KINDS_TYPES = BETA_REAL_KINDS_TYPES + BETA_CMPLX_KINDS_TYPES module stdlib_stats_distribution_beta use ieee_arithmetic, only: ieee_value, ieee_quiet_nan, ieee_is_nan use stdlib_kinds, only : sp, dp, xdp use stdlib_error, only : error_stop use stdlib_optval, only : optval use stdlib_stats_distribution_uniform, only : uni=>rvs_uniform use stdlib_stats_distribution_gamma, only : rgamma=>rvs_gamma use stdlib_specialfunctions_gamma, only : beta, incomplete_beta, log_beta implicit none private public :: rvs_beta public :: pdf_beta public :: cdf_beta interface rvs_beta !! Version experimental !! !! Beta Distribution Random Variates !! ([Specification](../page/specs/stdlib_stats_distribution_beta.html# !! rvs_beta-beta-distribution-random-variates)) !! #:for k1, t1 in RC_KINDS_TYPES module procedure beta_dist_rvs_${t1[0]}$${k1}$ ! 2 arguments #:endfor #:for k1, t1 in RC_KINDS_TYPES module procedure beta_dist_rvs_array_${t1[0]}$${k1}$ ! 3 arguments #:endfor end interface rvs_beta interface pdf_beta !! Version experimental !! !! Beta Distribution Probability Density Function !! ([Specification](../page/specs/stdlib_stats_distribution_beta.html# !! pdf_beta-beta-distribution-probability-density-function)) !! #:for k1, t1 in RC_KINDS_TYPES module procedure beta_dist_pdf_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in RC_KINDS_TYPES module procedure beta_dist_pdf_impure_${t1[0]}$${k1}$ #:endfor end interface pdf_beta interface cdf_beta !! Version experimental !! !! Beta Distribution Cumulative Distribution Function !! ([Specification](../page/specs/stdlib_stats_distribution_beta.html# !! cdf_beta-beta-distribution-cumulative-distribution-function)) !! #:for k1, t1 in RC_KINDS_TYPES module procedure beta_dist_cdf_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in RC_KINDS_TYPES module procedure beta_dist_cdf_impure_${t1[0]}$${k1}$ #:endfor end interface cdf_beta contains #:for k1, t1 in BETA_REAL_KINDS_TYPES impure elemental function beta_dist_rvs_${t1[0]}$${k1}$(a, b, loc) & result(res) ! Beta random variate using gamma variates ! If a < 1 or b < 1, uses uniform method, otherwise uses gamma method ! ${t1}$, intent(in) :: a, b ${t1}$, intent(in), optional :: loc ${t1}$ :: res, x, y, xx(2) ${t1}$ :: loc_ ${t1}$, parameter :: zero = 0.0_${k1}$, one = 1.0_${k1}$ loc_ = optval(loc, 0.0_${k1}$) if(a <= zero .or. b <= zero) then res = ieee_value(1.0_${k1}$, ieee_quiet_nan) return end if if(a < one .or. b < one) then ! Use uniform method for small parameters do xx = uni(zero, one, 2) x = xx(1) ** (one / a) y = xx(2) ** (one / b) y = x + y if(y <= one .and. y /= zero) exit end do else ! Use gamma method for larger parameters do x = rgamma(a, one) y = rgamma(b, one) y = x + y if(y /= zero) exit end do end if res = x / y + loc_ end function beta_dist_rvs_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in BETA_CMPLX_KINDS_TYPES impure elemental function beta_dist_rvs_${t1[0]}$${k1}$(a, b, loc) & result(res) ! Complex parameter beta distributed. The real part and imaginary part are ! independent of each other. ! ${t1}$, intent(in) :: a, b ${t1}$, intent(in), optional :: loc ${t1}$ :: res ${t1}$ :: loc_ loc_ = optval(loc, cmplx(0.0_${k1}$, 0.0_${k1}$, kind=${k1}$)) res = cmplx(beta_dist_rvs_r${k1}$(a%re, b%re) + loc_%re, & beta_dist_rvs_r${k1}$(a%im, b%im) + loc_%im, kind=${k1}$) end function beta_dist_rvs_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in BETA_REAL_KINDS_TYPES function beta_dist_rvs_array_${t1[0]}$${k1}$(a, b, array_size, loc) & result(res) ! ${t1}$, intent(in) :: a, b integer, intent(in) :: array_size ${t1}$, intent(in), optional :: loc ${t1}$ :: res(array_size) integer :: i ${t1}$ :: loc_ loc_ = optval(loc, 0.0_${k1}$) do i = 1, array_size res(i) = beta_dist_rvs_${t1[0]}$${k1}$(a, b, loc_) end do end function beta_dist_rvs_array_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in BETA_CMPLX_KINDS_TYPES function beta_dist_rvs_array_${t1[0]}$${k1}$(a, b, array_size, loc) & result(res) ! Complex parameter beta distributed. The real part and imaginary part are ! independent of each other. ! ${t1}$, intent(in) :: a, b integer, intent(in) :: array_size ${t1}$, intent(in), optional :: loc ${t1}$ :: res(array_size) integer :: i ${t1}$ :: loc_ loc_ = optval(loc, cmplx(0.0_${k1}$, 0.0_${k1}$, kind=${k1}$)) do i = 1, array_size res(i) = beta_dist_rvs_${t1[0]}$${k1}$(a, b, loc_) end do end function beta_dist_rvs_array_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in BETA_REAL_KINDS_TYPES elemental function beta_dist_pdf_${t1[0]}$${k1}$(x, a, b, loc) & result(res) ! Beta distribution probability density function ! ${t1}$, intent(in) :: x, a, b ${t1}$, intent(in), optional :: loc real(${k1}$) :: res ${t1}$ :: xs ${t1}$ :: loc_ ${t1}$, parameter :: zero = 0.0_${k1}$, one = 1.0_${k1}$ if(a <= zero .or. b <= zero) then res = ieee_value(1.0_${k1}$, ieee_quiet_nan) return end if loc_ = optval(loc, 0.0_${k1}$) xs = x - loc_ if(xs <= zero .or. xs >= one) then res = zero return end if ! Use log formulation for numerical stability res = exp((a - one) * log(xs) + (b - one) * log(one - xs) - log_beta(a, b)) end function beta_dist_pdf_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in BETA_REAL_KINDS_TYPES impure elemental function beta_dist_pdf_impure_${t1[0]}$${k1}$(x, a, b, err, loc) & result(res) ! Beta distribution probability density function (impure wrapper) ! ${t1}$, intent(in) :: x, a, b integer, intent(out) :: err ${t1}$, intent(in), optional :: loc real(${k1}$) :: res res = beta_dist_pdf_${t1[0]}$${k1}$(x, a, b, loc) err = merge(1, 0, ieee_is_nan(res)) end function beta_dist_pdf_impure_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in BETA_CMPLX_KINDS_TYPES elemental function beta_dist_pdf_${t1[0]}$${k1}$(x, a, b, loc) & result(res) ! Complex parameter beta distributed. The real part and imaginary part are ! independent of each other. ! ${t1}$, intent(in) :: x, a, b ${t1}$, intent(in), optional :: loc real(${k1}$) :: res ${t1}$ :: loc_ loc_ = optval(loc, cmplx(0.0_${k1}$, 0.0_${k1}$, kind=${k1}$)) res = beta_dist_pdf_r${k1}$(x%re, a%re, b%re, loc_%re) res = res * beta_dist_pdf_r${k1}$(x%im, a%im, b%im, loc_%im) end function beta_dist_pdf_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in BETA_CMPLX_KINDS_TYPES impure elemental function beta_dist_pdf_impure_${t1[0]}$${k1}$(x, a, b, err, loc) & result(res) ! Complex parameter beta distributed. The real part and imaginary part are ! independent of each other. ! ${t1}$, intent(in) :: x, a, b integer, intent(out) :: err ${t1}$, intent(in), optional :: loc real(${k1}$) :: res ${t1}$ :: loc_ loc_ = optval(loc, cmplx(0.0_${k1}$, 0.0_${k1}$, kind=${k1}$)) res = beta_dist_pdf_r${k1}$(x%re, a%re, b%re, loc_%re) res = res * beta_dist_pdf_r${k1}$(x%im, a%im, b%im, loc_%im) err = merge(1, 0, ieee_is_nan(res)) end function beta_dist_pdf_impure_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in BETA_REAL_KINDS_TYPES elemental function beta_dist_cdf_${t1[0]}$${k1}$(x, a, b, loc) & result(res) ! Beta distribution cumulative distribution function ! ${t1}$, intent(in) :: x, a, b ${t1}$, intent(in), optional :: loc real(${k1}$) :: res ${t1}$ :: xs ${t1}$ :: loc_ ${t1}$, parameter :: zero = 0.0_${k1}$, one = 1.0_${k1}$ loc_ = optval(loc, 0.0_${k1}$) xs = x - loc_ if(a <= zero .or. b <= zero) then res = ieee_value(1.0_${k1}$, ieee_quiet_nan) return end if if(xs <= zero) then res = zero return end if if(xs >= one) then res = one return end if res = real(incomplete_beta(xs, a, b), kind=${k1}$) end function beta_dist_cdf_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in BETA_REAL_KINDS_TYPES impure elemental function beta_dist_cdf_impure_${t1[0]}$${k1}$(x, a, b, err, loc) & result(res) ! Beta distribution cumulative distribution function (impure wrapper) ! ${t1}$, intent(in) :: x, a, b integer, intent(out) :: err ${t1}$, intent(in), optional :: loc real(${k1}$) :: res res = beta_dist_cdf_${t1[0]}$${k1}$(x, a, b, loc) err = merge(1, 0, ieee_is_nan(res)) end function beta_dist_cdf_impure_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in BETA_CMPLX_KINDS_TYPES elemental function beta_dist_cdf_${t1[0]}$${k1}$(x, a, b, loc) & result(res) ! Complex parameter beta distributed. The real part and imaginary part are ! independent of each other. ! ${t1}$, intent(in) :: x, a, b ${t1}$, intent(in), optional :: loc real(${k1}$) :: res ${t1}$ :: loc_ loc_ = optval(loc, cmplx(0.0_${k1}$, 0.0_${k1}$, kind=${k1}$)) res = beta_dist_cdf_r${k1}$(x%re, a%re, b%re, loc_%re) res = res * beta_dist_cdf_r${k1}$(x%im, a%im, b%im, loc_%im) end function beta_dist_cdf_${t1[0]}$${k1}$ #:endfor #:for k1, t1 in BETA_CMPLX_KINDS_TYPES impure elemental function beta_dist_cdf_impure_${t1[0]}$${k1}$(x, a, b, err, loc) & result(res) ! Complex parameter beta distributed. The real part and imaginary part are ! independent of each other. ! ${t1}$, intent(in) :: x, a, b integer, intent(out) :: err ${t1}$, intent(in), optional :: loc real(${k1}$) :: res ${t1}$ :: loc_ loc_ = optval(loc, cmplx(0.0_${k1}$, 0.0_${k1}$, kind=${k1}$)) res = beta_dist_cdf_${t1[0]}$${k1}$(x, a, b, loc_) err = merge(1, 0, ieee_is_nan(res)) end function beta_dist_cdf_impure_${t1[0]}$${k1}$ #:endfor end module stdlib_stats_distribution_beta