source: sasmodels/sasmodels/models/lib/sas_gamma.c @ e07b470

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

fix compile errors with sas gamma

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