From e15d51510048927f172f1bf1f27ede65907d940d Mon Sep 17 00:00:00 2001
From: Leon Bottou <leon@bottou.org>
Date: Mon, 8 Apr 2019 22:25:55 -0400
Subject: [PATCH] bug 299 fixed

---
 libdjvu/GContainer.h | 87 ++++++++++++++++++++++++--------------------
 1 file changed, 48 insertions(+), 39 deletions(-)

diff --git a/libdjvu/GContainer.h b/libdjvu/GContainer.h
index 96b067c..0140211 100644
--- a/libdjvu/GContainer.h
+++ b/libdjvu/GContainer.h
@@ -550,52 +550,61 @@ public:
 template <class TYPE> void
 GArrayTemplate<TYPE>::sort(int lo, int hi)
 {
-  if (hi <= lo)
-    return;
-  if (hi > hibound || lo<lobound)
-    G_THROW( ERR_MSG("GContainer.illegal_subscript") );
   TYPE *data = (TYPE*)(*this);
-  // Test for insertion sort
-  if (hi <= lo + 50)
+  while(true)
     {
-      for (int i=lo+1; i<=hi; i++)
+      if (hi <= lo)
+        return;
+      if (hi > hibound || lo<lobound)
+        G_THROW( ERR_MSG("GContainer.illegal_subscript") );
+      // Test for insertion sort
+      if (hi <= lo + 50)
         {
-          int j = i;
-          TYPE tmp = data[i];
-          while ((--j>=lo) && !(data[j]<=tmp))
-            data[j+1] = data[j];
-          data[j+1] = tmp;
+          for (int i=lo+1; i<=hi; i++)
+            {
+              int j = i;
+              TYPE tmp = data[i];
+              while ((--j>=lo) && !(data[j]<=tmp))
+                data[j+1] = data[j];
+              data[j+1] = tmp;
+            }
+          return;
         }
-      return;
-    }
-  // -- determine suitable quick-sort pivot
-  TYPE tmp = data[lo];
-  TYPE pivot = data[(lo+hi)/2];
-  if (pivot <= tmp)
-    { tmp = pivot; pivot=data[lo]; }
-  if (data[hi] <= tmp)
-    { pivot = tmp; }
-  else if (data[hi] <= pivot)
-    { pivot = data[hi]; }
-  // -- partition set
-  int h = hi;
-  int l = lo;
-  while (l < h)
-    {
-      while (! (pivot <= data[l])) l++;
-      while (! (data[h] <= pivot)) h--;
-      if (l < h)
+      // -- determine median-of-three pivot
+      TYPE tmp = data[lo];
+      TYPE pivot = data[(lo+hi)/2];
+      if (pivot <= tmp)
+        { tmp = pivot; pivot=data[lo]; }
+      if (data[hi] <= tmp)
+        { pivot = tmp; }
+      else if (data[hi] <= pivot)
+        { pivot = data[hi]; }
+      // -- partition set
+      int h = hi;
+      int l = lo;
+      while (l < h)
         {
-          tmp = data[l];
-          data[l] = data[h];
-          data[h] = tmp;
-          l = l+1;
-          h = h-1;
+          while (! (pivot <= data[l])) l++;
+          while (! (data[h] <= pivot)) h--;
+          if (l < h)
+            {
+              tmp = data[l];
+              data[l] = data[h];
+              data[h] = tmp;
+              l = l+1;
+              h = h-1;
+            }
+        }
+      // -- recurse, small partition first
+      //    tail-recursion elimination
+      if (h - lo <= hi - l) {
+        sort(lo,h);
+        lo = l; // sort(l,hi)
+      } else {
+        sort(l,hi);
+        hi = h; // sort(lo,h)
       }
     }
-  // -- recursively restart
-  sort(lo, h);
-  sort(l, hi);
 }
 
 template<class TYPE> inline TYPE&
-- 
2.22.1