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