00001 #ident "$Header: /home/cvsuser/cvsroot/JSOC/proj/libs/stats/dstats2.c,v 1.4 2013/07/05 18:35:19 phil Exp $" 00002 00003 #include <stdlib.h> 00004 #include <math.h> 00005 #include <float.h> 00006 #include <string.h> 00007 00008 #define NBINS 65536 00009 #define OK 0 00010 #define TOO_FEW_GOOD_POINTS -2 00011 00012 int dstats2(int n, double arr[], double *min, double *max, double *medn, 00013 double *mean, double *sig, double *skew, double *kurt, int *ngood) 00014 { 00015 int i, bin, nv = 0; 00016 double dmin = DBL_MAX, dmax = -DBL_MAX; 00017 double s = 0.0, s2 = 0.0, s3 = 0.0, s4 = 0.0, avg, var; 00018 static int hist[NBINS]; 00019 double delta; 00020 00021 *min = *max = *medn = *mean = *sig = *skew = *kurt = __builtin_nan(""); 00022 00023 for (i = 0; i < n; ++i) { 00024 double t = arr[i]; 00025 int fpclass = fpclassify(t); 00026 if (fpclass == FP_NAN || fpclass == FP_INFINITE) 00027 continue; 00028 if (dmin > t) 00029 dmin = t; 00030 if (dmax < t) 00031 dmax = t; 00032 s += t; 00033 ++nv; 00034 } 00035 *ngood = nv; 00036 00037 if (nv < 2) { 00038 if (nv == 1) 00039 *min = *max = *medn = *mean = s; 00040 return TOO_FEW_GOOD_POINTS; 00041 } 00042 00043 if (dmin == dmax) { 00044 *min = *max = *medn = *mean = dmin; 00045 *sig = *skew = *kurt = 0; 00046 return OK; 00047 } 00048 00049 delta = (dmax - dmin) / NBINS; 00050 memset(hist, 0, sizeof(int)*NBINS); 00051 avg = s / nv; 00052 for (i = 0; i < n; ++i) { 00053 double tmp = arr[i]; 00054 double t = tmp - avg; 00055 double tt; 00056 int fpclass = fpclassify(t); 00057 if (fpclass == FP_NAN || fpclass == FP_INFINITE) 00058 continue; 00059 tt = t * t; 00060 s2 += tt; 00061 tt *= t; 00062 s3 += tt; 00063 tt *= t; 00064 s4 += tt; 00065 bin = (tmp - dmin) / delta; 00066 if (bin >= NBINS) 00067 bin = NBINS - 1; 00068 ++hist[bin]; 00069 } 00070 00071 bin = 0; 00072 n = hist[bin]; 00073 while (2*n < nv) 00074 n += hist[++bin]; 00075 *medn = dmin + delta * (bin + 0.5); 00076 00077 *min = dmin; 00078 *max = dmax; 00079 *mean = avg; 00080 var = s2 / (nv - 1); 00081 *sig = sqrt(var); 00082 *skew = s3 / (var * *sig * nv); 00083 *kurt = s4 / (var * var * nv) - 3.0; 00084 00085 return OK; 00086 }