source: sasview/sansmodels/src/c_models/libfunc.c @ db298c0

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since db298c0 was 5da3cc5, checked in by Kieran Campbell <kieranrcampbell@…>, 12 years ago

Implemented erf(x) in libfunc.c and added pass down to C++ of multfactor

  • Property mode set to 100644
File size: 3.5 KB
Line 
1// by jcho
2
3#include <math.h>
4
5#include "libmultifunc/libfunc.h"
6
7#include <stdio.h>
8
9
10
11//used in Si func
12
13int factorial(int i) {
14
15        int k, j;
16        if (i<2){
17                return 1;
18        }
19
20        k=1;
21
22        for(j=1;j<i;j++) {
23                k=k*(j+1);
24        }
25
26        return k;
27
28}
29
30
31
32// Used in pearl nec model
33
34// Sine integral function: approximated within 1%!!!
35
36// integral of sin(x)/x up to namx term nmax=6 looks the best.
37
38double Si(double x)
39
40{
41        int i;
42        int nmax=6;
43        double out;
44        long double power;
45        double pi = 4.0*atan(1.0);
46
47        if (x >= pi*6.2/4.0){
48                double out_sin = 0.0;
49                double out_cos = 0.0;
50                out = pi/2.0;
51
52                for (i=0; i<nmax-2; i+=1) {
53                        out_cos += pow(-1.0, i) * (double)factorial(2*i) / pow(x, 2*i+1);
54                        out_sin += pow(-1.0, i) * (double)factorial(2*i+1) / pow(x, 2*i+2);
55                }
56
57                out -= cos(x) * out_cos;
58                out -= sin(x) * out_sin;
59                return out;
60        }
61
62        out = 0.0;
63
64        for (i=0; i<nmax; i+=1) {
65                if (i==0) {
66                        out += x;
67                        continue;
68                }
69
70                power = pow(x,(2 * i + 1));
71                out += (double)pow(-1, i) * power / ((2.0 * (double)i + 1.0) * (double)factorial(2 * i + 1));
72
73                //printf ("Si=%g %g %d\n", x, out, i);
74        }
75
76        return out;
77}
78
79
80
81double sinc(double x)
82{
83  if (x==0.0){
84    return 1.0;
85  }
86  return sin(x)/x;
87}
88
89
90double gamln(double xx) {
91
92    double x,y,tmp,ser;
93    static double cof[6]={76.18009172947146,-86.50532032941677,
94    24.01409824083091,-1.231739572450155,
95    0.1208650973866179e-2,-0.5395239384953e-5};
96    int j;
97
98    y=x=xx;
99    tmp=x+5.5;
100    tmp -= (x+0.5)*log(tmp);
101    ser=1.000000000190015;
102    for (j=0;j<=5;j++) ser += cof[j]/++y;
103    return -tmp+log(2.5066282746310005*ser/x);
104}
105
106/** Modifications below by kieranrcampbell@gmail.com
107    Institut Laue-Langevin, July 2012
108**/
109
110/**
111   Implements eq 6.2.5 (small gamma) of Numerical Recipes in C, essentially
112   the incomplete gamma function multiplied by the gamma function.
113   Required for implementation of fast error function (erf)
114**/
115
116
117#define ITMAX 100
118#define EPS 3.0e-7
119#define FPMIN 1.0e-30
120
121void gser(float *gamser, float a, float x, float *gln) {
122  int n;
123  float sum,del,ap;
124
125  *gln = gamln(a);
126  if(x <= 0.0) {
127    if (x < 0.0) printf("Error: x less than 0 in routine gser");
128    *gamser = 0.0;
129    return;
130  } else {
131    ap = a;
132    del = sum = 1.0/a;
133   
134    for(n=1;n<=ITMAX;n++) {
135      ++ap;
136      del *= x/ap;
137      sum += del;
138      if(fabs(del) < fabs(sum)*EPS) {
139        *gamser = sum * exp(-x + a * log(x) - (*gln));
140        return;
141      }
142    }
143    printf("a too large, ITMAX too small in routine gser");
144    return;
145
146  }
147
148
149}
150
151/**
152   Implements the incomplete gamma function Q(a,x) evaluated by its continued fraction
153   representation
154**/
155
156void gcf(float *gammcf, float a, float x, float *gln) {
157  int i;
158  float an,b,c,d,del,h;
159
160  *gln = gamln(a);
161  b = x+1.0-a;
162  c = 1.0/FPMIN;
163  d = 1.0/b;
164  h=d;
165  for (i=1;i <= ITMAX; i++) {
166    an = -i*(i-a);
167    b += 2.0;
168    d = an*d + b;
169    if (fabs(d) < FPMIN) d = FPMIN;
170    c = b+an/c;
171    if (fabs(c) < FPMIN) c = FPMIN;
172    d = 1.0/d;
173    del = d*c;
174    h += del;
175    if (fabs(del-1.0) < EPS) break;
176  }
177  if (i > ITMAX) printf("a too large, ITMAX too small in gcf");
178  *gammcf = exp(-x+a*log(x)-(*gln))*h;
179  return;
180}
181
182
183/**
184   Represents incomplete error function, P(a,x)
185**/
186float gammp(float a, float x) {
187  float gamser,gammcf,gln;
188  if(x < 0.0 || a <= 0.0) printf("Invalid arguments in routine gammp");
189  if (x < (a+1.0)) {
190    gser(&gamser,a,x,&gln);
191    return gamser;
192  } else {
193    gcf(&gammcf,a,x,&gln);
194    return 1.0 - gammcf;
195  }
196}
197
198/**
199    Implementation of the error function, erf(x)
200**/
201
202float erff(float x) {
203  return x < 0.0 ? -gammp(0.5,x*x) : gammp(0.5,x*x);
204}
205
Note: See TracBrowser for help on using the repository browser.