diff 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
line wrap: on
line diff
--- a/jmedcouple.c++
+++ b/jmedcouple.c++
@@ -24,26 +24,25 @@
   weights W.
 */
 double wmedian(const vector<double>& A,
-               const vector<int>& W)
+               const vector<long>& W)
 {
-  typedef pair<double,int> aw_t;
+  typedef pair<double, long> aw_t;
 
-  int n = A.size();
+  long n = A.size();
   vector<aw_t> AW(n);
-  for (int i = 0; i < n; i ++) 
+  for (long i = 0; i < n; i ++)
     AW[i] = make_pair(A[i], W[i]);
 
   long wtot = sum(W);
 
-  int beg = 0;
-  int end = n - 1;
+  long beg = 0;
+  long end = n - 1;
 
   while (true) {
-    int mid = (beg + end)/2;
+    long mid = (beg + end)/2;
     nth_element(AW.begin(), AW.begin() + mid, AW.end(),
                 [](const aw_t& l, const aw_t& r){return l.first > r.first;});
     double trial = AW[mid].first;
-
     long wleft = 0, wright = 0;
 
     for (aw_t& aw: AW ) {
@@ -69,7 +68,7 @@
                  double eps1 = numeric_limits<double>::epsilon(), 
                  double eps2 = numeric_limits<double>::min())
 {
-  size_t n = X.size(), n2 = (n - 1)/2;
+  long n = X.size(), n2 = (n - 1)/2;
   
   if (n < 3)
     return 0;
@@ -106,7 +105,7 @@
   copy_if(Z.begin(), Z.end(), back_inserter(Zminus), 
           [=](double z){return Zeps >= z;});
 
-  size_t 
+  long
     n_plus = Zplus.size(), 
     n_minus = Zminus.size();
 
@@ -117,7 +116,7 @@
     In case a and be are within epsilon of the median, the kernel
     is the signum of their position.
   */
-  auto h_kern = [&](int i, int j) {
+  auto h_kern = [&](long i, long j) {
     double a = Zplus[i];
     double b = Zminus[j];
 
@@ -131,8 +130,8 @@
   };
  
   // Init left and right borders
-  vector<int> L(n_plus, 0);
-  vector<int> R(n_plus, n_minus - 1);
+  vector<long> L(n_plus, 0);
+  vector<long> R(n_plus, n_minus - 1);
 
   long Ltot = 0;
   long Rtot = n_minus*n_plus;
@@ -140,10 +139,11 @@
   
   // kth pair algorithm (Johnson & Mizoguchi)
   while (Rtot - Ltot > n_plus) {
+
     // First, compute the median inside the given bounds
     vector<double> A;
-    vector<int> W;
-    for (int i = 0; i < n_plus; i++) {
+    vector<long> W;
+    for (long i = 0; i < n_plus; i++) {
       if (L[i] <= R[i]) {
         A.push_back(h_kern(i, (L[i] + R[i])/2));
         W.push_back(R[i] - L[i] + 1);
@@ -155,11 +155,11 @@
 
     //Compute new left and right boundaries, based on the weighted
     //median
-    vector<int> P(n_plus), Q(n_plus);
+    vector<long> P(n_plus), Q(n_plus);
 
     {
-      int j = 0;
-      for (int i = n_plus - 1; i >= 0; i--) {
+      long j = 0;
+      for (long i = n_plus - 1; i >= 0; i--) {
         while (j < n_minus and h_kern(i, j) - Am > Am_eps)
           j++;
         P[i] = j - 1;
@@ -167,8 +167,8 @@
     }
 
     {
-      int j = n_minus - 1;
-      for (int i = 0; i < n_plus; i++) {
+      long j = n_minus - 1;
+      for (long i = 0; i < n_plus; i++) {
         while (j >= 0 and h_kern(i, j) - Am < -Am_eps)
           j--;
         Q[i] = j + 1;
@@ -197,8 +197,8 @@
   // to find it in, just between the left and right boundaries. This
   // space is of size Rtot - Ltot which is <= n_plus
   vector<double> A;
-  for (int i = 0; i < n_plus; i++) {
-    for (int j = L[i]; j <= R[i]; j++)
+  for (long i = 0; i < n_plus; i++) {
+    for (long j = L[i]; j <= R[i]; j++)
       A.push_back(h_kern(i, j));
   }
   nth_element(A.begin(), A.begin() + medc_idx - Ltot, A.end(),