Canoe
Comprehensive Atmosphere N' Ocean Engine
gamma.c
Go to the documentation of this file.
1 #include <math.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 
5 #define ITMAX 100
6 #define EPS 3.0e-7
7 #define FPMIN 1.0e-30
8 
9 // Returns the incomplete gamma function P (a, x) evaluated by its series
10 // representation as gamser . Also returns ln Γ(a) as gln .
11 void gser(double *gamser, double a, double x, double *gln) {
12  int n;
13  double sum, del, ap;
14  *gln = lgamma(a);
15  if (x <= 0.0) {
16  if (x < 0.0) fprintf(stderr, "x less than 0 in routine gser");
17  *gamser = 0.0;
18  return;
19  } else {
20  ap = a;
21  del = sum = 1.0 / a;
22  for (n = 1; n <= ITMAX; n++) {
23  ++ap;
24  del *= x / ap;
25  sum += del;
26  if (fabs(del) < fabs(sum) * EPS) {
27  *gamser = sum * exp(-x + a * log(x) - (*gln));
28  return;
29  }
30  }
31  fprintf(stderr, "a too large, ITMAX too small in routine gser");
32  return;
33  }
34 }
35 
36 // Returns the incomplete gamma function Q(a, x) evaluated by its continued
37 // fraction represen- tation as gammcf . Also returns ln Γ(a) as gln .
38 void gcf(double *gammcf, double a, double x, double *gln) {
39  int i;
40  double an, b, c, d, del, h;
41  *gln = lgamma(a);
42  b = x + 1.0 - a;
43  // Set up for evaluating continued fraction
44  // by modified Lentz’s method (§5.2)
45  c = 1.0 / FPMIN;
46  // with b 0 = 0.
47  d = 1.0 / b;
48  h = d;
49  for (i = 1; i <= ITMAX; i++) {
50  // Iterate to convergence.
51  an = -i * (i - a);
52  b += 2.0;
53  d = an * d + b;
54  if (fabs(d) < FPMIN) d = FPMIN;
55  c = b + an / c;
56  if (fabs(c) < FPMIN) c = FPMIN;
57  d = 1.0 / d;
58  del = d * c;
59  h *= del;
60  if (fabs(del - 1.0) < EPS) break;
61  }
62  if (i > ITMAX) fprintf(stderr, "a too large, ITMAX too small in gcf");
63  *gammcf = exp(-x + a * log(x) - (*gln)) * h;
64 }
65 
66 // Returns the incomplete gamma function P (a, x).
67 double gammp(double a, double x) {
68  double gamser, gammcf, gln;
69  if (x < 0.0 || a <= 0.0)
70  fprintf(stderr, "Invalid arguments in routine gammp");
71  // Use the series representation.
72  if (x < (a + 1.0)) {
73  gser(&gamser, a, x, &gln);
74  return gamser;
75  } else { // Use the continued fraction representation
76  gcf(&gammcf, a, x, &gln);
77  return 1.0 - gammcf; // and take its complement.
78  }
79 }
80 
81 // Returns the incomplete gamma function Q(a, x) ≡ 1 − P (a, x).
82 double gammq(double a, double x) {
83  double gamser, gammcf, gln;
84  if (x < 0.0 || a <= 0.0)
85  fprintf(stderr, "Invalid arguments in routine gammq");
86  // Use the series representation
87  if (x < (a + 1.0)) {
88  gser(&gamser, a, x, &gln);
89  return 1.0 - gamser; // and take its complement.
90  } else { // Use the continued fraction representation.
91  gcf(&gammcf, a, x, &gln);
92  return gammcf;
93  }
94 }
95 
96 #undef ITMAX
97 #undef EPS
98 #undef FPMIN
Real ap[18][3]
#define ITMAX
Definition: gamma.c:5
double gammq(double a, double x)
Definition: gamma.c:82
void gser(double *gamser, double a, double x, double *gln)
Definition: gamma.c:11
#define FPMIN
Definition: gamma.c:7
void gcf(double *gammcf, double a, double x, double *gln)
Definition: gamma.c:38
#define EPS
Definition: gamma.c:6
double gammp(double a, double x)
Definition: gamma.c:67