Listing 3: Creating a custom function.
void normal_curve_area(sqlite_func* context, int argc, const char **argv) { char** endptr; char result[65]; double x1, x2, mu, sigma; if(argc != 4) { return; } x1 = strtod((char*)argv[0], endptr); if((x1==0) && (argv[0]==*endptr)) return; x2 = strtod((char*)argv[1], endptr); if((x2==0) && (argv[1]==*endptr)) return; mu = strtod((char*)argv[2], endptr); if((x1==0) && (argv[2]==*endptr)) return; sigma = strtod((char*)argv[3], endptr); if((x1==0) && (argv[3]==*endptr)) return; sprintf(result, "%f", GetNormalCurveArea(x1,x2,mu,sigma)); sqlite_set_result_string(context, result, -1); } double GetNormalCurveArea(double x1, double x2, double mu, double sigma) { /* Maclaurin Series Expansion for exp(-x2/2) Michael Owens Description: This function takes two random variables, a lower limit (x1) and an upper limit (x2), on a Gaussian distribution and computes the total area between them. User Input Parameters: x2: upper limit x1: lower limit mu: population mean sigma: variance Nomenclature: sz: dummy variable for series expansion z = (x-mu)/sig cum: the cumulative value of z, or integral cum1 is the area from -r1 to 0 while cum2 is the area from 0 to r2. Limitations: The Limiting Values of z: A value greater than z=5 will give exactly 50% of the normal curve to four decimal places, and larger values will only encumber series convergence, therefore any values greater than 4 will be reset to 4. */ double j = 10; // Initialized for priming the while() block. double bound = 4.2; double z1 = (x1 - mu) / sigma; double z2 = (x2 - mu) / sigma; if (z1 < -bound) z1 = (double)-bound; if (z1 > bound) z1 = (double)bound; if (z2 < -bound) z2 = (double)-bound; if (z2 > bound) z2 = (double)bound; double cum1 = fabs(z1); double cum2 = fabs(z2); // Use absolute values for computing terms x1 = fabs(z1); x2 = fabs(z2); // Computations // Maclaurin Series: term by term addition // Area of lower limit if(cum1) SeriesExpansion(x1,cum1); else cum1 = 0; // Area of upper limit if(cum2) SeriesExpansion(x2,cum2); else cum2 = 0; // Determine the total area: double Area; if ((z2 + z2) < (fabs(z2 + z2))) // if z2 is negative Area = cum1 - cum2; // then z1 must be negative too. else if ((z1 + z1) < (fabs(z1 + z1))) // z2 is positve and if z1 negative Area = cum1 + cum2; else Area = fabs(cum2 - cum1); // if z1 is positive // Limiting area from origin to +infinity double CA; CA = pow(2*3.1415926535, 0.5); // Normalized area Area = Area/CA; // Area from origin to lower limit. return Area; } short SeriesExpansion(double &x, double &cum) { double SeriesTerm; double j = 10; for (int i = 1; j > 0.0001; i++) { int f = i; double factorial = f; if(f-1) { while(f-1) factorial *= --f; } if(!factorial) return 0; SeriesTerm = (pow(-1,i)); SeriesTerm *= (double)1/((2*i)+1); SeriesTerm *= (double)pow(x,(2*i+1)); SeriesTerm *= (double)1/((pow(2,i)*factorial)); cum += SeriesTerm; j = fabs(SeriesTerm); } return 1; }