00001 #ident "$Header: /home/cvsuser/cvsroot/JSOC/proj/libs/stats/dstats.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
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #define SWAP(a,b) temp=(a);(a)=(b);(b)=temp;
00017
00018 static double median(int n, double arr[])
00019 {
00020 int k, i, ir, j, l, mid;
00021 double a, temp;
00022
00023 if (n < 1)
00024 return __builtin_nan("");
00025
00026 k = n / 2;
00027 l = 0;
00028 ir = n - 1;
00029 for (;;) {
00030 if (ir <= l + 1) {
00031 if (ir == l + 1 && arr[ir] < arr[l]) {
00032 SWAP(arr[l], arr[ir])
00033 }
00034 return arr[k];
00035 } else {
00036 mid = (l + ir) >> 1;
00037 SWAP(arr[mid], arr[l + 1])
00038 if (arr[l] > arr[ir]) {
00039 SWAP(arr[l], arr[ir])
00040 }
00041 if (arr[l + 1] > arr[ir]) {
00042 SWAP(arr[l + 1], arr[ir])
00043 }
00044 if (arr[l] > arr[l + 1]) {
00045 SWAP(arr[l], arr[l + 1])
00046 }
00047 i = l + 1;
00048 j = ir;
00049 a = arr[l + 1];
00050 for (;;) {
00051 do
00052 i++;
00053 while (arr[i] < a);
00054 do
00055 j--;
00056 while (arr[j] > a);
00057 if (j < i)
00058 break;
00059 SWAP(arr[i], arr[j])
00060 }
00061 arr[l + 1] = arr[j];
00062 arr[j] = a;
00063 if (j >= k)
00064 ir = j - 1;
00065 if (j <= k)
00066 l = i;
00067 }
00068 }
00069 }
00070
00071 #define OK 0
00072 #define OUT_OF_MEMORY -1
00073 #define TOO_FEW_GOOD_POINTS -2
00074
00075 int dstats(int n, double arr[], double *min, double *max, double *medn,
00076 double *mean, double *sig, double *skew, double *kurt, int *ngood)
00077 {
00078 int i;
00079 int nv = 0;
00080 double *dat, dmin = DBL_MAX, dmax = -DBL_MAX;
00081 double s = 0.0, s2 = 0.0, s3 = 0.0, s4 = 0.0, avg, var;
00082
00083 *min = *max = *medn = *mean = *sig = *skew = *kurt = __builtin_nan("");
00084
00085 if (!(dat = (double *) malloc(n * sizeof(double))))
00086 return OUT_OF_MEMORY;
00087
00088 for (i = 0; i < n; ++i) {
00089 double t = arr[i];
00090 int fpclass = fpclassify(t);
00091 if (fpclass == FP_NAN || fpclass == FP_INFINITE)
00092 continue;
00093 dat[nv++] = t;
00094 if (dmin > t)
00095 dmin = t;
00096 if (dmax < t)
00097 dmax = t;
00098 s += t;
00099 }
00100 *ngood = nv;
00101
00102 if (nv < 2) {
00103 if (nv == 1)
00104 *min = *max = *medn = *mean = s;
00105 free(dat);
00106 return TOO_FEW_GOOD_POINTS;
00107 }
00108
00109 if (dmin == dmax) {
00110 *min = *max = *medn = *mean = dmin;
00111 *sig = *skew = *kurt = 0;
00112 free(dat);
00113 return OK;
00114 }
00115
00116 avg = s / nv;
00117 for (i = 0; i < nv; ++i) {
00118 double tt;
00119 double t = dat[i] - avg;
00120 tt = t * t;
00121 s2 += tt;
00122 tt *= t;
00123 s3 += tt;
00124 tt *= t;
00125 s4 += tt;
00126 }
00127
00128 *min = dmin;
00129 *max = dmax;
00130 *medn = median(nv, dat);
00131 *mean = avg;
00132 var = s2 / (nv - 1);
00133 *sig = sqrt(var);
00134 *skew = s3 / (var * *sig * nv);
00135 *kurt = s4 / (var * var * nv) - 3.0;
00136
00137 free(dat);
00138 return OK;
00139 }