0
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
1 /* |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
2 Algorithm for the skewness estimator medcouple (MC) |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
3 -------------------------------------------------- |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
4 ( originally matlabmc.c and also mc/mcrsoft/spmc.c ) |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
5 */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
6 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
7 #include <stdio.h> |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
8 #include <stdlib.h> |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
9 #include <math.h> |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
10 #include <algorithm> |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
11 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
12 #include <inttypes.h> |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
13 // -> int64_t |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
14 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
15 template <typename T> int sign(T val) { |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
16 return (T(0) < val) - (val < T(0)); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
17 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
18 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
19 /* Interface routines to be called via .C() and those from API : */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
20 #include "wgt_himed.c" |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
21 /* |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
22 including |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
23 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
24 whimed_i(a,iw,n): the weighted high median of an array a of length n, |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
25 using the positive integer weights iw[]. |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
26 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
27 * which is in ./wgt_himed.c_templ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
28 * ~~~~~~~~~~~~~~~~~ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
29 */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
30 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
31 /* Includes the auxiliary function |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
32 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
33 h_kern(a,b, ai,bi,ab, eps): the values h(a,b) needed to compute the mc |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
34 */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
35 static |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
36 double h_kern(double a, double b, int ai, int bi, int ab, double eps); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
37 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
38 /* MM: The tolerance 'eps1' and 'eps2' can now be passed from R; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
39 * the original code had only one 'eps' for both and hardcoded |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
40 * eps = 0.0000000000001; /.* == 1e-13 )) *./ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
41 */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
42 /* MK: eps1: for (relative) "equality" checks |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
43 * eps2: used to check for over- and underflow, respectively |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
44 * therefore I suggest eps1 = DBL_EPS and eps2 = DBL_MIN |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
45 */ |
2
|
46 double mc_C(double *z, int n, double *eps, int trace_lev) |
0
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
47 { |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
48 /* NOTE: |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
49 eps = c(eps1, eps2) |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
50 iter := c(maxit, trace.lev) as input |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
51 = c(it, converged) as output |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
52 */ |
2
|
53 int it = 0; |
0
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
54 bool converged = true; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
55 double medc; // "the" result |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
56 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
57 if (n < 3) { |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
58 return 0.; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
59 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
60 /* copy data before sort()ing in place, also reflecting it */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
61 /* NOTE: x[0] is empty --- so 1-indexing is used (MM: danger!) */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
62 double *x = (double *) malloc((n+1)*sizeof(double)); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
63 x[0] = 0; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
64 for (int i = 0; i < n; i++) |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
65 x[i+1] = -z[i]; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
66 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
67 std::sort(&x[1], &x[1] + n); /* full sort */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
68 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
69 double xmed; // := median( x[1:n] ) = - median( z[0:(n-1)] ): |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
70 if (n%2) { /* n even */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
71 xmed = x[(n/2)+1]; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
72 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
73 else { /* n odd */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
74 int ind = (n/2); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
75 xmed = (x[ind] + x[ind+1])/2; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
76 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
77 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
78 if (fabs(x[1] - xmed) < eps[0] * (eps[0] + fabs(xmed))) { |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
79 return -1; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
80 } else if (fabs(x[n] - xmed) < eps[0] * (eps[0] + fabs(xmed))) { |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
81 return 1; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
82 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
83 /* else : median is not at the border ------------------- */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
84 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
85 if(trace_lev) |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
86 printf("mc_C(z[1:%d], trace_lev=%d): Median = %g (not at the border)\n", |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
87 n, trace_lev, -xmed); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
88 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
89 int i,j; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
90 /* center x[] wrt median --> such that then median( x[1:n] ) == 0 */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
91 for (i = 1; i <= n; i++) |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
92 x[i] -= xmed; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
93 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
94 /* Now scale to inside [-0.5, 0.5] and flip sign such that afterwards |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
95 * x[1] >= x[2] >= ... >= x[n] */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
96 double xden = -2 * std::max(-x[1], x[n]); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
97 for (i = 1; i <= n; i++) |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
98 x[i] /= xden; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
99 xmed /= xden; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
100 if(trace_lev >= 2) |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
101 printf(" x[] has been rescaled (* 1/s) with s = %g\n", -xden); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
102 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
103 j = 1; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
104 double x_eps = eps[0] * (eps[0] + fabs(xmed)); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
105 while (x[j] > x_eps && j <= n) { /* test relative to xmed */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
106 /* x1[j] = x[j]; */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
107 j++; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
108 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
109 if(trace_lev >= 2) |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
110 printf(" x1[] := {x | x_j > x_eps = %g} has %d (='j-1') entries\n", |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
111 x_eps, j-1); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
112 i = 1; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
113 double *x2 = x+j-1; /* pointer -- corresponding to x2[i] = x[j]; */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
114 while (x[j] > -x_eps && j <= n) { /* test relative to xmed */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
115 /* x1[j] = x[j]; */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
116 /* x2[i] = x[j]; */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
117 j++; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
118 i++; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
119 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
120 /* now x1[] := {x | x_j > -eps} also includes the median (0) */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
121 if(trace_lev >= 2) |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
122 printf("'median-x' {x | -eps < x_i <= eps} has %d (= 'k') entries\n", |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
123 i-1); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
124 int h1 = j-1, /* == size of x1[] == the sum of those two sizes above */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
125 /* conceptually, x2[] := {x | x_j <= eps} (which includes the median 0) */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
126 h2 = i + (n-j);// == size of x2[] == maximal size of whimed() arrays |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
127 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
128 if(trace_lev) |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
129 printf(" now allocating 2+5 work arrays of size (1+) h2=%d each:\n", h2); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
130 /* work arrays for whimed_i() : allocate *once* only !! */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
131 double *acand = (double *) malloc(h2*sizeof(double)), |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
132 *a_srt = (double *) malloc(h2*sizeof(double)); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
133 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
134 int *iw_cand= (int *) malloc(h2*sizeof(int)), |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
135 /* work arrays for the fast-median-of-table algorithm: |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
136 * currently still with 1-indexing */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
137 *left = (int *) malloc((h2+1)*sizeof(int)), |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
138 *right = (int *) malloc((h2+1)*sizeof(int)), |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
139 *p = (int *) malloc((h2+1)*sizeof(int)), |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
140 *q = (int *) malloc((h2+1)*sizeof(int)); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
141 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
142 for (i = 1; i <= h2; i++) { |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
143 left [i] = 1; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
144 right[i] = h1; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
145 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
146 int64_t nr = ((int64_t) h1) * ((int64_t) h2), // <-- careful to *NOT* overflow |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
147 knew = nr/2 +1; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
148 if(trace_lev >= 2) |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
149 printf(" (h1,h2, nr, knew) = (%d,%d, %.0f, %.0f)\n", |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
150 h1,h2, (double)nr, (double)knew); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
151 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
152 double trial = -2./* -Wall */; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
153 double *work= (double *) malloc(n*sizeof(double)); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
154 int *iwt = (int *) malloc(n*sizeof(int)); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
155 bool IsFound = false; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
156 int nl = 0, |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
157 neq = 0; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
158 /* MK: 'neq' counts the number of observations in the |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
159 * inside the tolerance range, i.e., where left > right + 1, |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
160 * since we would miss those when just using 'nl-nr'. |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
161 * This is to prevent index overflow in work[] later on. |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
162 * left might be larger than right + 1 since we are only |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
163 * testing with accuracy eps_trial and therefore there might |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
164 * be more than one observation in the `tolerance range` |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
165 * between < and <=. |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
166 */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
167 while (!IsFound && (nr-nl+neq > n) && it < 1e5) |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
168 { |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
169 int64_t sum_p, sum_q; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
170 it++; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
171 j = 0; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
172 for (i = 1; i <= h2; i++) |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
173 if (left[i] <= right[i]) { |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
174 iwt[j] = right[i] - left[i]+1; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
175 int k = left[i] + (iwt[j]/2); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
176 work[j] = h_kern(x[k], x2[i], k, i, h1+1, eps[1]); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
177 j++; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
178 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
179 if(trace_lev >= 4) { |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
180 printf(" before whimed(): work and iwt, each [0:(%d-1)]:\n", j); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
181 if(j >= 100) { |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
182 for(i=0; i < 90; i++) printf(" %8g", work[i]); printf("\n ... "); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
183 for(i=j-4; i < j; i++)printf(" %8g", work[i]); printf("\n"); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
184 for(i=0; i < 90; i++) printf(" %8d", iwt [i]); printf("\n ... "); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
185 for(i=j-4; i < j; i++)printf(" %8d", iwt [i]); printf("\n"); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
186 } else { // j <= 99 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
187 for(i=0; i < j; i++) printf(" %8g", work[i]); printf("\n"); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
188 for(i=0; i < j; i++) printf(" %8d", iwt [i]); printf("\n"); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
189 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
190 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
191 trial = whimed_i(work, iwt, j, acand, a_srt, iw_cand); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
192 double eps_trial = eps[0] * (eps[0] + fabs(trial)); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
193 if(trace_lev >= 3) |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
194 printf("%2s it=%2d, whimed(*, n=%6d)= %8g ", " ", it, j, trial); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
195 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
196 j = 1; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
197 for (i = h2; i >= 1; i--) { |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
198 while (j <= h1 && h_kern(x[j],x2[i],j,i,h1+1,eps[1]) - trial > eps_trial) { |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
199 // while (j <= h1 && h_kern(x[j],x2[i],j,i,h1+1,eps[1]) > trial) { |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
200 if (trace_lev >= 5) |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
201 printf("\nj=%3d, i=%3d, x[j]=%g, x2[i]=%g, h=%g", |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
202 j, i, x[j], x2[i], |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
203 h_kern(x[j],x2[i],j,i,h1+1,eps[1])); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
204 j++; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
205 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
206 /* for(; j <= h1; j++) { */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
207 /* register double h = h_kern(x[j],x2[i],j,i,h1+1,eps[1]); */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
208 /* if(h > trial) break; */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
209 /* } */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
210 p[i] = j-1; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
211 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
212 j = h1; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
213 for (i = 1, sum_p=0, sum_q=0; i <= h2; i++) { |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
214 while (j >= 1 && trial - h_kern(x[j],x2[i],j,i,h1+1,eps[1]) > eps_trial) |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
215 // while (j >= 1 && h_kern(x[j],x2[i],j,i,h1+1,eps[1]) < trial) |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
216 j--; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
217 q[i] = j+1; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
218 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
219 sum_p += p[i]; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
220 sum_q += j;/* = q[i]-1 */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
221 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
222 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
223 if(trace_lev >= 3) { |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
224 if (trace_lev == 3) |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
225 printf("sum_(p,q)= (%.0f,%.0f)", (double)sum_p, (double)sum_q); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
226 else { /* trace_lev >= 4 */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
227 printf("\n%3s p[1:%d]:", "", h2); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
228 bool lrg = h2 >= 100; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
229 int i_m = lrg ? 95 : h2; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
230 for(i = 1; i <= i_m; i++) printf(" %2d", p[i]); if(lrg) printf(" ..."); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
231 printf(" sum=%4.0f\n%3s q[1:%d]:", (double)sum_p, "", h2); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
232 for(i = 1; i <= i_m; i++) printf(" %2d", q[i]); if(lrg) printf(" ..."); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
233 printf(" sum=%4.0f\n", (double)sum_q); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
234 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
235 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
236 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
237 if (knew <= sum_p) { |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
238 if(trace_lev >= 3) |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
239 printf("; sum_p >= kn\n"); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
240 for (i = 1, neq = 0; i <= h2; i++) { |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
241 right[i] = p[i]; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
242 if (left[i] > right[i]+1) neq += left[i]-right[i]-1; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
243 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
244 nr = sum_p; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
245 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
246 else { /* knew > sum_p */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
247 IsFound = (knew <= sum_q); /* i.e. sum_p < knew <= sum_q */; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
248 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
249 if(trace_lev >= 3) |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
250 printf("; s_p < kn ?<=? s_q: %s\n", IsFound ? "TRUE": "no"); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
251 if(IsFound) { |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
252 medc = trial; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
253 } else { /* knew > sum_q */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
254 for (i = 1; i <= h2; i++) { |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
255 left[i] = q[i]; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
256 if (left[i] > right[i]+1) neq += left[i]-right[i]-1; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
257 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
258 nl = sum_q; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
259 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
260 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
261 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
262 } /* end while loop */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
263 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
264 converged = IsFound || (nr-nl+neq <= n); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
265 if(!converged) { |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
266 /* still: */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
267 medc = trial; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
268 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
269 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
270 if (converged && !IsFound) { /* e.g., for mc(1:4) : */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
271 j = 0; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
272 for (i = 1; i <= h2; i++) { |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
273 if (left[i] <= right[i]) { |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
274 for (int k = left[i]; k <= right[i]; k++) { |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
275 work[j] = -h_kern(x[k],x2[i],k,i,h1+1,eps[1]); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
276 j++; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
277 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
278 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
279 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
280 if(trace_lev) |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
281 printf(" not found [it=%d, (nr,nl) = (%d,%d)]," |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
282 " -> (knew-nl, j) = (%d,%d)\n", |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
283 it, nr, nl, knew-nl, j); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
284 /* using rPsort(work, n,k), since we don't need work[] anymore:*/ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
285 std::nth_element(work, work + knew-nl-1, work + j); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
286 medc = - work[knew-nl-1]; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
287 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
288 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
289 if(converged && trace_lev >= 2) |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
290 printf("converged in %d iterations\n", it); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
291 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
292 return medc; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
293 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
294 } /* end{ mc_C } */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
295 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
296 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
297 static |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
298 double h_kern(double a, double b, int ai, int bi, int ab, double eps) |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
299 { |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
300 /* if (fabs(a-b) <= DBL_MIN) */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
301 /* check for zero division and positive b */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
302 if (fabs(a-b) < 2.0*eps || b > 0) |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
303 return sign((double)(ab - (ai+bi))); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
304 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
305 /* else */ |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
306 return (a+b)/(a-b); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
307 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
308 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
309 #include <vector> |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
310 #include <iostream> |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
311 #include <string> |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
312 #include <fstream> |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
313 #include <iomanip> |
2
|
314 #include <sstream> |
0
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
315 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
316 int main(int argc, char** argv) { |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
317 using namespace std; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
318 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
319 vector<double> eps = {numeric_limits<double>::epsilon(), |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
320 numeric_limits<double>::min()}; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
321 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
322 string fname; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
323 if (argc > 1) { |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
324 fname = argv[1]; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
325 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
326 else { |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
327 cerr << "Please provide input file." << endl; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
328 return 1; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
329 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
330 |
2
|
331 double trace_lev = 0; |
|
332 if(argc > 2) { |
|
333 stringstream ss; |
|
334 ss << argv[2]; |
|
335 ss >> trace_lev; |
|
336 } |
|
337 |
0
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
338 ifstream ifs(fname); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
339 if (not ifs) { |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
340 cerr << "File " << fname << " not found." << endl; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
341 return 1; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
342 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
343 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
344 vector<double> data; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
345 double datum; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
346 while (ifs >> datum) { |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
347 data.push_back(datum); |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
348 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
349 |
2
|
350 cout << setprecision(16) << mc_C(&data[0], data.size(), &eps[0], trace_lev) << endl; |
0
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
351 |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
352 return 0; |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
353 } |
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff
changeset
|
354 |