comparison jmedcouple.c++ @ 30:2e277129e81b

jmedcouple: whitespace fixes
author Jordi Gutiérrez Hermoso <jordigh@octave.org>
date Sun, 18 Jan 2015 20:42:25 -0500
parents cf8c8c825c6d
children 6c264f2053bc
comparison
equal deleted inserted replaced
29:cf8c8c825c6d 30:2e277129e81b
7 #include <algorithm> 7 #include <algorithm>
8 #include <utility> 8 #include <utility>
9 9
10 using namespace std; 10 using namespace std;
11 11
12 template <typename T> 12 template <typename T>
13 int signum(T val) { 13 int signum(T val) {
14 return (T(0) < val) - (val < T(0)); 14 return (T(0) < val) - (val < T(0));
15 } 15 }
16 16
17 template <typename Container, typename Out = typename Container::value_type> 17 template <typename Container, typename Out = typename Container::value_type>
18 Out sum(const Container& C) { 18 Out sum(const Container& C) {
19 return accumulate(C.begin(), C.end(), Out()); 19 return accumulate(C.begin(), C.end(), Out());
20 } 20 }
21 21
22 /* 22 /*
23 This computes the weighted median of array A with corresponding 23 This computes the weighted median of array A with corresponding
24 weights W. 24 weights W.
25 */ 25 */
58 else if (2*wright < wtot) 58 else if (2*wright < wtot)
59 beg = mid; 59 beg = mid;
60 else 60 else
61 return trial; 61 return trial;
62 } 62 }
63 63
64 return 0; 64 return 0;
65 } 65 }
66 66
67 double medcouple(const std::vector<double>& X, 67 double medcouple(const std::vector<double>& X,
68 double eps1 = numeric_limits<double>::epsilon(), 68 double eps1 = numeric_limits<double>::epsilon(),
69 double eps2 = numeric_limits<double>::min()) 69 double eps2 = numeric_limits<double>::min())
70 { 70 {
71 long n = X.size(), n2 = (n - 1)/2; 71 long n = X.size(), n2 = (n - 1)/2;
72 72
73 if (n < 3) 73 if (n < 3)
74 return 0; 74 return 0;
75 75
76 vector<double> Z = X; 76 vector<double> Z = X;
77 sort(Z.begin(), Z.end(), std::greater<double>()); 77 sort(Z.begin(), Z.end(), std::greater<double>());
78 78
79 double Zmed; 79 double Zmed;
80 if (n % 2 == 1) 80 if (n % 2 == 1)
81 Zmed = Z[n2]; 81 Zmed = Z[n2];
82 else 82 else
83 Zmed = (Z[n2] + Z[n2 + 1])/2; 83 Zmed = (Z[n2] + Z[n2 + 1])/2;
84 84
85 // Check if the median is at the edges up to relative epsilon 85 // Check if the median is at the edges up to relative epsilon
86 if (abs(Z[0] - Zmed) < eps1*(eps1 + abs(Zmed))) 86 if (abs(Z[0] - Zmed) < eps1*(eps1 + abs(Zmed)))
87 return -1.0; 87 return -1.0;
88 if (abs(Z[n - 1] - Zmed) < eps1*(eps1 + abs(Zmed))) 88 if (abs(Z[n - 1] - Zmed) < eps1*(eps1 + abs(Zmed)))
89 return 1.0; 89 return 1.0;
90 90
91 // Centre Z wrt median, so that median(Z) = 0. 91 // Centre Z wrt median, so that median(Z) = 0.
92 for_each(Z.begin(), Z.end(), [&](double& z){ z -= Zmed;}); 92 for_each(Z.begin(), Z.end(), [&](double& z){ z -= Zmed;});
93 93
94 // Scale inside [-0.5, 0.5], for greater numerical stability. 94 // Scale inside [-0.5, 0.5], for greater numerical stability.
95 double Zden = 2*max(Z[0], -Z[n - 1]); 95 double Zden = 2*max(Z[0], -Z[n - 1]);
98 98
99 double Zeps = eps1*(eps1 + abs(Zmed)); 99 double Zeps = eps1*(eps1 + abs(Zmed));
100 100
101 // These overlap on the entries that are tied with the median 101 // These overlap on the entries that are tied with the median
102 vector<double> Zplus, Zminus; 102 vector<double> Zplus, Zminus;
103 copy_if(Z.begin(), Z.end(), back_inserter(Zplus), 103 copy_if(Z.begin(), Z.end(), back_inserter(Zplus),
104 [=](double z){return z >= -Zeps;}); 104 [=](double z){return z >= -Zeps;});
105 copy_if(Z.begin(), Z.end(), back_inserter(Zminus), 105 copy_if(Z.begin(), Z.end(), back_inserter(Zminus),
106 [=](double z){return Zeps >= z;}); 106 [=](double z){return Zeps >= z;});
107 107
108 long 108 long
109 n_plus = Zplus.size(), 109 n_plus = Zplus.size(),
110 n_minus = Zminus.size(); 110 n_minus = Zminus.size();
111 111
112 /* 112 /*
113 Kernel function h for the medcouple, closing over the values of 113 Kernel function h for the medcouple, closing over the values of
114 Zplus and Zminus just defined above. 114 Zplus and Zminus just defined above.
126 else 126 else
127 h = (a + b)/(a - b); 127 h = (a + b)/(a - b);
128 128
129 return h; 129 return h;
130 }; 130 };
131 131
132 // Init left and right borders 132 // Init left and right borders
133 vector<long> L(n_plus, 0); 133 vector<long> L(n_plus, 0);
134 vector<long> R(n_plus, n_minus - 1); 134 vector<long> R(n_plus, n_minus - 1);
135 135
136 long Ltot = 0; 136 long Ltot = 0;
151 } 151 }
152 double Am = wmedian(A, W); 152 double Am = wmedian(A, W);
153 153
154 double Am_eps = eps1*(eps1 + abs(Am)); 154 double Am_eps = eps1*(eps1 + abs(Am));
155 155
156 //Compute new left and right boundaries, based on the weighted 156 // Compute new left and right boundaries, based on the weighted
157 //median 157 // median
158 vector<long> P(n_plus), Q(n_plus); 158 vector<long> P(n_plus), Q(n_plus);
159 159
160 { 160 {
161 long j = 0; 161 long j = 0;
162 for (long i = n_plus - 1; i >= 0; i--) { 162 for (long i = n_plus - 1; i >= 0; i--) {
176 } 176 }
177 177
178 long 178 long
179 sumP = sum(P) + n_plus, 179 sumP = sum(P) + n_plus,
180 sumQ = sum(Q); 180 sumQ = sum(Q);
181 181
182 if (medc_idx <= sumP - 1) { 182 if (medc_idx <= sumP - 1) {
183 R = P; 183 R = P;
184 Rtot = sumP; 184 Rtot = sumP;
185 } 185 }
186 else { 186 else {
207 double Am = A[medc_idx - Ltot]; 207 double Am = A[medc_idx - Ltot];
208 return Am; 208 return Am;
209 } 209 }
210 210
211 211
212
213 int main(int argc, char** argv) { 212 int main(int argc, char** argv) {
214 double 213 double
215 eps1 = numeric_limits<double>::epsilon(), 214 eps1 = numeric_limits<double>::epsilon(),
216 eps2 = numeric_limits<double>::min(); 215 eps2 = numeric_limits<double>::min();
217 216
239 cout << setprecision(16) 238 cout << setprecision(16)
240 << medcouple(data, eps1, eps2) << endl; 239 << medcouple(data, eps1, eps2) << endl;
241 240
242 return 0; 241 return 0;
243 } 242 }
244