Mercurial > hg > medcouple
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 |
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 |