SDDSlib
Loading...
Searching...
No Matches
betai.c
Go to the documentation of this file.
1/**
2 * @file betai.c
3 * @brief Routines for computing the incomplete beta function.
4 *
5 * @copyright
6 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
7 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
8 *
9 * @license
10 * This file is distributed under the terms of the Software License Agreement
11 * found in the file LICENSE included with this distribution.
12 *
13 * @author M. Borland, R. Soliday
14 */
15
16#include "mdb.h"
17
18#if defined(_WIN32)
19# if _MSC_VER <= 1600
20# include "fdlibm.h"
21# endif
22#endif
23
24double betaIncSum(double x, double a, double b);
25double betaInc1(double x, double a, double b);
26
27#define BETAI_ACCURACY 1e-10
28
29/**
30 * @brief Compute the complete beta function component.
31 *
32 * Uses the gamma function to compute the value of Beta(a,b) = Γ(a)*Γ(b)/Γ(a+b).
33 *
34 * @param a First parameter.
35 * @param b Second parameter.
36 * @return The value of Beta(a,b).
37 */
38double betaComp(double a, double b) {
39#if defined(vxWorks)
40 fprintf(stderr, "lgamma function not implemented on vxWorks\n");
41 exit(1);
42#else
43 return exp(lgamma(a) + lgamma(b) - lgamma(a + b));
44#endif
45}
46
47double lnBetaComp(double a, double b) {
48#if defined(vxWorks)
49 fprintf(stderr, "lgamma function not implemented on vxWorks\n");
50 exit(1);
51#else
52 return lgamma(a) + lgamma(b) - lgamma(a + b);
53#endif
54}
55
56/**
57 * @brief Compute the incomplete beta function.
58 *
59 * Calculates the incomplete beta function I_x(a,b) for given parameters a, b and x.
60 * If necessary, parameters may be swapped internally to improve convergence.
61 *
62 * @param a First parameter (must be > 0).
63 * @param b Second parameter (must be > 0).
64 * @param x The integration limit (0 ≤ x ≤ 1).
65 * @return The value of I_x(a,b), or -1.0 if x is out of range.
66 */
67double betaInc(double a, double b, double x) {
68 double xLimit, sum, lnBab = 0;
69 short swapped = 0;
70
71 if (x < 0 || x > 1)
72 return -1.0;
73 if (a + b != 2) {
74 xLimit = (a + 1) / (a + b - 2);
75 if (x > xLimit) {
76 swapped = 1;
77 x = 1 - x;
78 SWAP_DOUBLE(a, b);
79 }
80 }
81 lnBab = lnBetaComp(a, b);
82 /* sum = pow(x, a)*pow(1-x, b)*betaIncSum(a, b, x)/(Bab*a); */
83 sum = exp(a * log(x) + b * log(1 - x) - lnBab) * betaIncSum(a, b, x) / a;
84 if (!swapped)
85 return sum;
86 return 1 - sum;
87}
88
89#define MAXIMUM_ITERATIONS 10000
90
91double betaIncSum(double a, double b, double x) {
92 double f1, f2;
93 double A0, B0, A_1, B_1, A1, B1, d;
94 double m, aM1, aP1, aPb, mT2;
95
96 /* evaluate the first step (d1) outside the loop to get started */
97 A_1 = B_1 = A0 = 1;
98 B0 = 1 - (a + b) / (a + 1) * x;
99 aPb = a + b;
100 aP1 = a + 1;
101 aM1 = a - 1;
102 m = 1;
103 do {
104 mT2 = m * 2;
105 d = m * (b - m) * x / ((aM1 + mT2) * (a + mT2));
106 A1 = A0 + d * A_1;
107 B1 = B0 + d * B_1;
108 f1 = A1 / B1;
109 A_1 = A0;
110 B_1 = B0;
111 A0 = A1;
112 B0 = B1;
113 d = -(a + m) * (aPb + m) * x / ((a + mT2) * (aP1 + mT2));
114 A1 = A0 + d * A_1;
115 B1 = B0 + d * B_1;
116 f2 = A1 / B1;
117 A_1 = A0;
118 B_1 = B0;
119 A0 = A1;
120 B0 = B1;
121 if (B1) {
122 /* rescale the recurrence to avoid over/underflow */
123 A_1 /= B1;
124 B_1 /= B1;
125 A0 /= B1;
126 B0 = 1;
127 }
128 m++;
129 } while (fabs(f1 - f2) > BETAI_ACCURACY && m < MAXIMUM_ITERATIONS);
130 /*
131 if (m>=MAXIMUM_ITERATIONS)
132 fprintf(stderr, "warning: too many iterations for incomplete beta function sum (%e, %e, %e) (betaInc)\n",
133 a, b, x);
134*/
135 return f2;
136}
137
138/* This isn't used, as it isn't as efficient as betaInc(), but it sure is simple! */
139double betaInc1(double a, double b, double x) {
140 double xp, sum, term;
141 long i;
142 xp = x;
143 i = sum = 0;
144 do {
145 sum += (term = betaComp(a + 1, i + 1.0) / betaComp(a + b, i + 1.0) * xp);
146 xp = x * xp;
147 i++;
148 } while (term > BETAI_ACCURACY);
149 return (sum + 1) * pow(x, a) * pow(1 - x, b) / (a * betaComp(a, b));
150}
double betaComp(double a, double b)
Compute the complete beta function component.
Definition betai.c:38
double betaInc(double a, double b, double x)
Compute the incomplete beta function.
Definition betai.c:67