annotate jmedcouple.c++ @ 29:cf8c8c825c6d

jmedcouple: change all ints to long, to avoid overflow
author Jordi Gutiérrez Hermoso <jordigh@octave.org>
date Sun, 18 Jan 2015 20:42:02 -0500
parents 65f6fad65f49
children 2e277129e81b
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
25
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
1 #include <vector>
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
2 #include <limits>
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
3 #include <iostream>
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
4 #include <string>
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
5 #include <fstream>
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
6 #include <iomanip>
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
7 #include <algorithm>
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
8 #include <utility>
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
9
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
10 using namespace std;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
11
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
12 template <typename T>
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
13 int signum(T val) {
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
14 return (T(0) < val) - (val < T(0));
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
15 }
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
16
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
17 template <typename Container, typename Out = typename Container::value_type>
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
18 Out sum(const Container& C) {
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
19 return accumulate(C.begin(), C.end(), Out());
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
20 }
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
21
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
22 /*
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
23 This computes the weighted median of array A with corresponding
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
24 weights W.
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
25 */
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
26 double wmedian(const vector<double>& A,
29
cf8c8c825c6d jmedcouple: change all ints to long, to avoid overflow
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 28
diff changeset
27 const vector<long>& W)
25
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
28 {
29
cf8c8c825c6d jmedcouple: change all ints to long, to avoid overflow
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 28
diff changeset
29 typedef pair<double, long> aw_t;
25
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
30
29
cf8c8c825c6d jmedcouple: change all ints to long, to avoid overflow
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 28
diff changeset
31 long n = A.size();
25
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
32 vector<aw_t> AW(n);
29
cf8c8c825c6d jmedcouple: change all ints to long, to avoid overflow
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 28
diff changeset
33 for (long i = 0; i < n; i ++)
25
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
34 AW[i] = make_pair(A[i], W[i]);
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
35
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
36 long wtot = sum(W);
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
37
29
cf8c8c825c6d jmedcouple: change all ints to long, to avoid overflow
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 28
diff changeset
38 long beg = 0;
cf8c8c825c6d jmedcouple: change all ints to long, to avoid overflow
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 28
diff changeset
39 long end = n - 1;
25
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
40
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
41 while (true) {
29
cf8c8c825c6d jmedcouple: change all ints to long, to avoid overflow
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 28
diff changeset
42 long mid = (beg + end)/2;
25
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
43 nth_element(AW.begin(), AW.begin() + mid, AW.end(),
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
44 [](const aw_t& l, const aw_t& r){return l.first > r.first;});
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
45 double trial = AW[mid].first;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
46 long wleft = 0, wright = 0;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
47
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
48 for (aw_t& aw: AW ) {
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
49 if (aw.first > trial)
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
50 wleft += aw.second;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
51 else
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
52 // This also includes a == trial, i.e. the "middle" weight.
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
53 wright += aw.second;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
54 }
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
55
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
56 if (2*wleft > wtot)
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
57 end = mid;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
58 else if (2*wright < wtot)
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
59 beg = mid;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
60 else
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
61 return trial;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
62 }
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
63
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
64 return 0;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
65 }
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
66
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
67 double medcouple(const std::vector<double>& X,
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
68 double eps1 = numeric_limits<double>::epsilon(),
28
65f6fad65f49 jmedcouple: get rid of unused trace_lev parameter
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 27
diff changeset
69 double eps2 = numeric_limits<double>::min())
25
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
70 {
29
cf8c8c825c6d jmedcouple: change all ints to long, to avoid overflow
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 28
diff changeset
71 long n = X.size(), n2 = (n - 1)/2;
25
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
72
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
73 if (n < 3)
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
74 return 0;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
75
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
76 vector<double> Z = X;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
77 sort(Z.begin(), Z.end(), std::greater<double>());
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
78
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
79 double Zmed;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
80 if (n % 2 == 1)
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
81 Zmed = Z[n2];
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
82 else
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
83 Zmed = (Z[n2] + Z[n2 + 1])/2;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
84
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
85 // Check if the median is at the edges up to relative epsilon
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
86 if (abs(Z[0] - Zmed) < eps1*(eps1 + abs(Zmed)))
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
87 return -1.0;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
88 if (abs(Z[n - 1] - Zmed) < eps1*(eps1 + abs(Zmed)))
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
89 return 1.0;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
90
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
91 // Centre Z wrt median, so that median(Z) = 0.
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
92 for_each(Z.begin(), Z.end(), [&](double& z){ z -= Zmed;});
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
93
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
94 // Scale inside [-0.5, 0.5], for greater numerical stability.
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
95 double Zden = 2*max(Z[0], -Z[n - 1]);
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
96 for_each(Z.begin(), Z.end(), [&](double& z){z /= Zden;});
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
97 Zmed /= Zden;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
98
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
99 double Zeps = eps1*(eps1 + abs(Zmed));
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
100
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
101 // These overlap on the entries that are tied with the median
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
102 vector<double> Zplus, Zminus;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
103 copy_if(Z.begin(), Z.end(), back_inserter(Zplus),
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
104 [=](double z){return z >= -Zeps;});
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
105 copy_if(Z.begin(), Z.end(), back_inserter(Zminus),
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
106 [=](double z){return Zeps >= z;});
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
107
29
cf8c8c825c6d jmedcouple: change all ints to long, to avoid overflow
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 28
diff changeset
108 long
25
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
109 n_plus = Zplus.size(),
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
110 n_minus = Zminus.size();
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
111
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
112 /*
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
113 Kernel function h for the medcouple, closing over the values of
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
114 Zplus and Zminus just defined above.
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
115
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
116 In case a and be are within epsilon of the median, the kernel
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
117 is the signum of their position.
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
118 */
29
cf8c8c825c6d jmedcouple: change all ints to long, to avoid overflow
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 28
diff changeset
119 auto h_kern = [&](long i, long j) {
25
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
120 double a = Zplus[i];
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
121 double b = Zminus[j];
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
122
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
123 double h;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
124 if (abs(a - b) <= 2*eps2)
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
125 h = signum(n_plus - 1 - i - j);
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
126 else
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
127 h = (a + b)/(a - b);
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
128
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
129 return h;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
130 };
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
131
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
132 // Init left and right borders
29
cf8c8c825c6d jmedcouple: change all ints to long, to avoid overflow
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 28
diff changeset
133 vector<long> L(n_plus, 0);
cf8c8c825c6d jmedcouple: change all ints to long, to avoid overflow
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 28
diff changeset
134 vector<long> R(n_plus, n_minus - 1);
25
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
135
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
136 long Ltot = 0;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
137 long Rtot = n_minus*n_plus;
27
40cbfb64e952 jmedcouple: change type of medc_idx to long
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 25
diff changeset
138 long medc_idx = Rtot/2;
25
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
139
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
140 // kth pair algorithm (Johnson & Mizoguchi)
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
141 while (Rtot - Ltot > n_plus) {
29
cf8c8c825c6d jmedcouple: change all ints to long, to avoid overflow
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 28
diff changeset
142
25
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
143 // First, compute the median inside the given bounds
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
144 vector<double> A;
29
cf8c8c825c6d jmedcouple: change all ints to long, to avoid overflow
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 28
diff changeset
145 vector<long> W;
cf8c8c825c6d jmedcouple: change all ints to long, to avoid overflow
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 28
diff changeset
146 for (long i = 0; i < n_plus; i++) {
25
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
147 if (L[i] <= R[i]) {
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
148 A.push_back(h_kern(i, (L[i] + R[i])/2));
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
149 W.push_back(R[i] - L[i] + 1);
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
150 }
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
151 }
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
152 double Am = wmedian(A, W);
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
153
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
154 double Am_eps = eps1*(eps1 + abs(Am));
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
155
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
156 //Compute new left and right boundaries, based on the weighted
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
157 //median
29
cf8c8c825c6d jmedcouple: change all ints to long, to avoid overflow
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 28
diff changeset
158 vector<long> P(n_plus), Q(n_plus);
25
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
159
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
160 {
29
cf8c8c825c6d jmedcouple: change all ints to long, to avoid overflow
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 28
diff changeset
161 long j = 0;
cf8c8c825c6d jmedcouple: change all ints to long, to avoid overflow
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 28
diff changeset
162 for (long i = n_plus - 1; i >= 0; i--) {
25
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
163 while (j < n_minus and h_kern(i, j) - Am > Am_eps)
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
164 j++;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
165 P[i] = j - 1;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
166 }
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
167 }
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
168
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
169 {
29
cf8c8c825c6d jmedcouple: change all ints to long, to avoid overflow
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 28
diff changeset
170 long j = n_minus - 1;
cf8c8c825c6d jmedcouple: change all ints to long, to avoid overflow
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 28
diff changeset
171 for (long i = 0; i < n_plus; i++) {
25
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
172 while (j >= 0 and h_kern(i, j) - Am < -Am_eps)
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
173 j--;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
174 Q[i] = j + 1;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
175 }
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
176 }
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
177
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
178 long
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
179 sumP = sum(P) + n_plus,
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
180 sumQ = sum(Q);
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
181
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
182 if (medc_idx <= sumP - 1) {
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
183 R = P;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
184 Rtot = sumP;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
185 }
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
186 else {
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
187 if (medc_idx > sumQ - 1) {
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
188 L = Q;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
189 Ltot = sumQ;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
190 }
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
191 else
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
192 return Am;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
193 }
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
194 }
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
195
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
196 // Didn't find the median, but now we have a very small search space
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
197 // to find it in, just between the left and right boundaries. This
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
198 // space is of size Rtot - Ltot which is <= n_plus
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
199 vector<double> A;
29
cf8c8c825c6d jmedcouple: change all ints to long, to avoid overflow
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 28
diff changeset
200 for (long i = 0; i < n_plus; i++) {
cf8c8c825c6d jmedcouple: change all ints to long, to avoid overflow
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 28
diff changeset
201 for (long j = L[i]; j <= R[i]; j++)
25
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
202 A.push_back(h_kern(i, j));
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
203 }
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
204 nth_element(A.begin(), A.begin() + medc_idx - Ltot, A.end(),
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
205 [](double x, double y) {return x > y;});
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
206
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
207 double Am = A[medc_idx - Ltot];
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
208 return Am;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
209 }
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
210
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
211
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
212
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
213 int main(int argc, char** argv) {
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
214 double
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
215 eps1 = numeric_limits<double>::epsilon(),
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
216 eps2 = numeric_limits<double>::min();
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
217
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
218 string fname;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
219 if (argc > 1) {
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
220 fname = argv[1];
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
221 }
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
222 else {
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
223 cerr << "Please provide input file." << endl;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
224 return 1;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
225 }
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
226
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
227 ifstream ifs(fname);
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
228 if (not ifs) {
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
229 cerr << "File " << fname << " not found." << endl;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
230 return 1;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
231 }
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
232
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
233 vector<double> data;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
234 double datum;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
235 while (ifs >> datum) {
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
236 data.push_back(datum);
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
237 }
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
238
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
239 cout << setprecision(16)
28
65f6fad65f49 jmedcouple: get rid of unused trace_lev parameter
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 27
diff changeset
240 << medcouple(data, eps1, eps2) << endl;
25
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
241
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
242 return 0;
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
243 }
518ef922033e Add C++ translation of Python code
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
diff changeset
244