1 /++ 2 This module contains algorithms for the $(LINK2 https://en.wikipedia.org/wiki/Beta_distribution, Beta Distribution). 3 4 An alternate parameterization of this distribution is provided in $(MREF mir,stat,distribution,beta_proportion). 5 6 License: $(HTTP www.apache.org/licenses/LICENSE-2.0, Apache-2.0) 7 8 Authors: John Michael Hall 9 10 Copyright: 2022-3 Mir Stat Authors. 11 12 +/ 13 14 module mir.stat.distribution.beta; 15 16 import mir.internal.utility: isFloatingPoint; 17 18 /++ 19 Computes the beta probability density function (PDF). 20 21 Params: 22 x = value to evaluate PDF 23 alpha = shape parameter #1 24 beta = shape parameter #2 25 26 See_also: 27 $(LINK2 https://en.wikipedia.org/wiki/Beta_distribution, Beta Distribution) 28 +/ 29 @safe pure nothrow @nogc 30 T betaPDF(T)(const T x, const T alpha, const T beta) 31 if (isFloatingPoint!T) 32 in (x >= 0, "x must be greater than or equal to 0") 33 in (x <= 1, "x must be less than or equal to 1") 34 in (alpha > 0, "alpha must be greater than zero") 35 in (beta > 0, "beta must be greater than zero") 36 { 37 import mir.math.common: pow; 38 import std.mathspecial: betaFunc = beta; 39 40 return pow(x, (alpha - 1)) * pow((1 - x), (beta - 1)) / betaFunc(alpha, beta); 41 } 42 43 /// 44 version(mir_stat_test) 45 @safe pure nothrow @nogc 46 unittest { 47 import mir.math.common: approxEqual; 48 49 assert(0.5.betaPDF(1, 1) == 1); 50 assert(0.75.betaPDF(1, 2).approxEqual(0.5)); 51 assert(0.25.betaPDF(0.5, 4).approxEqual(0.9228516)); 52 } 53 54 /++ 55 Computes the beta cumulatve distribution function (CDF). 56 57 Params: 58 x = value to evaluate CDF 59 alpha = shape parameter #1 60 beta = shape parameter #2 61 62 See_also: 63 $(LINK2 https://en.wikipedia.org/wiki/Beta_distribution, Beta Distribution) 64 +/ 65 @safe pure nothrow @nogc 66 T betaCDF(T)(const T x, const T alpha, const T beta) 67 if (isFloatingPoint!T) 68 in (x >= 0, "x must be greater than or equal to 0") 69 in (x <= 1, "x must be less than or equal to 1") 70 in (alpha > 0, "alpha must be greater than zero") 71 in (beta > 0, "beta must be greater than zero") 72 { 73 import std.mathspecial: betaIncomplete; 74 75 return betaIncomplete(alpha, beta, x); 76 } 77 78 /// 79 version(mir_stat_test) 80 @safe pure nothrow @nogc 81 unittest { 82 import mir.math.common: approxEqual; 83 84 assert(0.5.betaCDF(1, 1).approxEqual(0.5)); 85 assert(0.75.betaCDF(1, 2).approxEqual(0.9375)); 86 assert(0.25.betaCDF(0.5, 4).approxEqual(0.8588867)); 87 } 88 89 /++ 90 Computes the beta complementary cumulative distribution function (CCDF). 91 92 Params: 93 x = value to evaluate CCDF 94 alpha = shape parameter #1 95 beta = shape parameter #2 96 97 See_also: 98 $(LINK2 https://en.wikipedia.org/wiki/Beta_distribution, Beta Distribution) 99 +/ 100 @safe pure nothrow @nogc 101 T betaCCDF(T)(const T x, const T alpha, const T beta) 102 if (isFloatingPoint!T) 103 in (x >= 0, "x must be greater than or equal to 0") 104 in (x <= 1, "x must be less than or equal to 1") 105 in (alpha > 0, "alpha must be greater than zero") 106 in (beta > 0, "beta must be greater than zero") 107 { 108 import std.mathspecial: betaIncomplete; 109 110 return betaIncomplete(beta, alpha, 1 - x); 111 } 112 113 /// 114 version(mir_stat_test) 115 @safe pure nothrow @nogc 116 unittest { 117 import mir.math.common: approxEqual; 118 119 assert(0.5.betaCCDF(1, 1).approxEqual(0.5)); 120 assert(0.75.betaCCDF(1, 2).approxEqual(0.0625)); 121 assert(0.25.betaCCDF(0.5, 4).approxEqual(0.1411133)); 122 } 123 124 /++ 125 Computes the beta inverse cumulative distribution function (InvCDF). 126 127 Params: 128 p = value to evaluate InvCDF 129 alpha = shape parameter #1 130 beta = shape parameter #2 131 132 See_also: 133 $(LINK2 https://en.wikipedia.org/wiki/Beta_distribution, Beta Distribution) 134 +/ 135 @safe pure nothrow @nogc 136 T betaInvCDF(T)(const T p, const T alpha, const T beta) 137 if (isFloatingPoint!T) 138 in (p >= 0, "p must be greater than or equal to 0") 139 in (p <= 1, "p must be less than or equal to 1") 140 in (alpha > 0, "alpha must be greater than zero") 141 in (beta > 0, "beta must be greater than zero") 142 { 143 import std.mathspecial: betaIncompleteInverse; 144 145 return betaIncompleteInverse(alpha, beta, p); 146 } 147 148 /// 149 version(mir_stat_test) 150 @safe pure nothrow @nogc 151 unittest { 152 import mir.math.common: approxEqual; 153 154 assert(0.5.betaInvCDF(1, 1).approxEqual(0.5)); 155 assert(0.9375.betaInvCDF(1, 2).approxEqual(0.75)); 156 assert(0.8588867.betaInvCDF(0.5, 4).approxEqual(0.25)); 157 } 158 159 /++ 160 Computes the beta log probability density function (LPDF). 161 162 Params: 163 x = value to evaluate LPDF 164 alpha = shape parameter #1 165 beta = shape parameter #2 166 167 See_also: 168 $(LINK2 https://en.wikipedia.org/wiki/Beta_distribution, Beta Distribution) 169 +/ 170 @safe pure nothrow @nogc 171 T betaLPDF(T)(const T x, const T alpha, const T beta) 172 if (isFloatingPoint!T) 173 in (x >= 0, "x must be greater than or equal to 0") 174 in (x <= 1, "x must be less than or equal to 1") 175 in (alpha > 0, "alpha must be greater than zero") 176 in (beta > 0, "beta must be greater than zero") 177 { 178 import mir.math.internal.log_beta: logBeta; 179 import mir.math.internal.xlogy: xlogy, xlog1py; 180 181 return xlogy(alpha - 1, x) + xlog1py(beta - 1, -x) - logBeta(alpha, beta); 182 } 183 184 /// 185 version(mir_stat_test) 186 @safe pure nothrow @nogc 187 unittest { 188 import mir.math.common: approxEqual, log; 189 190 assert(0.5.betaLPDF(1, 1).approxEqual(log(betaPDF(0.5, 1, 1)))); 191 assert(0.75.betaLPDF(1, 2).approxEqual(log(betaPDF(0.75, 1, 2)))); 192 assert(0.25.betaLPDF(0.5, 4).approxEqual(log(betaPDF(0.25, 0.5, 4)))); 193 }