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