source: sasmodels/sasmodels/models/lib/sas_gamma.c @ 1596de3

core_shell_microgelscostrafo411magnetic_modelrelease_v0.94release_v0.95ticket-1257-vesicle-productticket_1156ticket_1265_superballticket_822_more_unit_tests
Last change on this file since 1596de3 was 1596de3, checked in by Paul Kienzle <pkienzle@…>, 8 years ago

code formatting

  • Property mode set to 100644
File size: 2.3 KB
Line 
1/*
2The wrapper for gamma function from OpenCL and standard libraries
3The OpenCL gamma function fails miserably on values lower than 1.0
4while works fine on larger values.
5We use gamma definition Gamma(t + 1) = t * Gamma(t) to compute
6to function for values lower than 1.0. Namely Gamma(t) = 1/t * Gamma(t + 1)
7*/
8
9#if defined(NEED_TGAMMA)
10static double cephes_stirf(double x)
11{
12        const double MAXSTIR=143.01608;
13        const double SQTPI=2.50662827463100050242E0;
14        double y, w, v;
15
16        w = 1.0 / x;
17
18        w = ((((
19                7.87311395793093628397E-4*w
20                - 2.29549961613378126380E-4)*w
21                - 2.68132617805781232825E-3)*w
22                + 3.47222221605458667310E-3)*w
23                + 8.33333333333482257126E-2)*w
24                + 1.0;
25        y = exp(x);
26        if (x > MAXSTIR)
27        { /* Avoid overflow in pow() */
28                v = pow(x, 0.5 * x - 0.25);
29                y = v * (v / y);
30        }
31        else
32        {
33                y = pow(x, x - 0.5) / y;
34        }
35        y = SQTPI * y * w;
36        return(y);
37}
38
39static double tgamma(double x) {
40        double p, q, z;
41        int sgngam;
42        int i;
43
44        sgngam = 1;
45        if (isnan(x))
46                return(x);
47        q = fabs(x);
48
49        if (q > 33.0)
50        {
51                if (x < 0.0)
52                {
53                        p = floor(q);
54                        if (p == q)
55                        {
56                                return (NAN);
57                        }
58                        i = p;
59                        if ((i & 1) == 0)
60                                sgngam = -1;
61                        z = q - p;
62                        if (z > 0.5)
63                        {
64                                p += 1.0;
65                                z = q - p;
66                        }
67                        z = q * sin(M_PI * z);
68                        if (z == 0.0)
69                        {
70                                return(NAN);
71                        }
72                        z = fabs(z);
73                        z = M_PI / (z * cephes_stirf(q));
74                }
75                else
76                {
77                        z = cephes_stirf(x);
78                }
79                return(sgngam * z);
80        }
81
82        z = 1.0;
83        while (x >= 3.0)
84        {
85                x -= 1.0;
86                z *= x;
87        }
88
89        while (x < 0.0)
90        {
91                if (x > -1.E-9)
92                        goto small;
93                z /= x;
94                x += 1.0;
95        }
96
97        while (x < 2.0)
98        {
99                if (x < 1.e-9)
100                        goto small;
101                z /= x;
102                x += 1.0;
103        }
104
105        if (x == 2.0)
106                return(z);
107
108        x -= 2.0;
109        p = (((((
110                +1.60119522476751861407E-4*x
111                + 1.19135147006586384913E-3)*x
112                + 1.04213797561761569935E-2)*x
113                + 4.76367800457137231464E-2)*x
114                + 2.07448227648435975150E-1)*x
115                + 4.94214826801497100753E-1)*x
116                + 9.99999999999999996796E-1;
117        q = ((((((
118                -2.31581873324120129819E-5*x
119                + 5.39605580493303397842E-4)*x
120                - 4.45641913851797240494E-3)*x
121                + 1.18139785222060435552E-2)*x
122                + 3.58236398605498653373E-2)*x
123                - 2.34591795718243348568E-1)*x
124                + 7.14304917030273074085E-2)*x
125                + 1.00000000000000000320E0;
126        return(z * p / q);
127
128small:
129        if (x == 0.0)
130        {
131                return (NAN);
132        }
133        else
134                return(z / ((1.0 + 0.5772156649015329 * x) * x));
135}
136#endif // NEED_TGAMMA
137
138
139inline double sas_gamma( double x) { return tgamma(x+1)/x; }
Note: See TracBrowser for help on using the repository browser.