diff --git a/src/fsort_template.h b/src/fsort_template.h
index c00ac378f694d84ec93213379dca185ed4b1d76b..edd0ce2dbbf6bf84a516c77d4482a14458766f21 100644
--- a/src/fsort_template.h
+++ b/src/fsort_template.h
@@ -1,5 +1,5 @@
 /*
- * $Id: fsort_template.h,v 1.5 1999/04/30 07:25:42 hubbe Exp $
+ * $Id: fsort_template.h,v 1.6 1999/05/03 07:04:16 hubbe Exp $
  */
 
 #ifndef SWAP
@@ -19,62 +19,151 @@
 #define PARENT(X) (((X)-1)>>1)
 #define CHILD1(X) (((X)<<1)+1)
 
-static void ID(register TYPE *bas,
-	       register TYPE *last
+#define MKNAME(X) MKNAME2(ID,X)
+#define MKNAME2(X,Y) PIKE_CONCAT(X,Y)
+
+static void MKNAME(_do_sort)(register TYPE *bas,
+			       register TYPE *last,
+			       int max_recursion
 #ifdef EXTRA_ARGS
-	       EXTRA_ARGS
+			       EXTRA_ARGS
 #else
 #define UNDEF_XARGS
 #define XARGS
 #endif
   )
 {
-  register TYPE tmp;
-  long howmany,x,y,z;
-#ifdef PIKE_DEBUG
-  extern int d_flag;
-#endif
+  register TYPE *a,*b, tmp;
 
-  howmany=((((char *)last)-((char *)bas))/SIZE)+1;
-  if(howmany<2) return;
-
-  for(x=PARENT(howmany-1);x>=0;x--)
+  while(bas < last)
   {
-    y=x;
-    while(1)
+    a = STEP(bas,1);
+    if(a == last)
     {
-      z=CHILD1(y);
-      if(z>=howmany) break;
-      if(z+1 < howmany && CMP(STEP(bas,z),STEP(bas,z+1))<=0) z++;
-      if(CMP( STEP(bas, y), STEP(bas, z)) >0) break;
-      SWAP( STEP(bas, y), STEP(bas, z));
-      y=z;
-    }
-  }
+      if( CMP(bas,last) > 0) SWAP(bas,last);
+      return;
+    }else{
+      if(--max_recursion <= 0)
+      {
+	long howmany,x,y,z;
+#ifdef PIKE_DEBUG
+	extern int d_flag;
+#endif
+	
+	howmany=((((char *)last)-((char *)bas))/SIZE)+1;
+	if(howmany<2) return;
+	
+	for(x=PARENT(howmany-1);x>=0;x--)
+	{
+	  y=x;
+	  while(1)
+	  {
+	    z=CHILD1(y);
+	    if(z>=howmany) break;
+	    if(z+1 < howmany && CMP(STEP(bas,z),STEP(bas,z+1))<=0) z++;
+	    if(CMP( STEP(bas, y), STEP(bas, z)) >0) break;
+	    SWAP( STEP(bas, y), STEP(bas, z));
+	    y=z;
+	  }
+	}
+	
+	for(x=howmany-1;x;x--)
+	{
+	  SWAP( STEP(bas,x), bas);
+	  y=0;
+	  while(1)
+	  {
+	    z=CHILD1(y);
+	    if(z>=x) break;
+	    if(z+1 < x && CMP(STEP(bas,z),STEP(bas,z+1))<=0) z++;
+	    if(CMP( STEP(bas, y), STEP(bas, z)) >0) break;
+	    SWAP( STEP(bas, y), STEP(bas, z));
+	    y=z;
+	  }
+	}
+	
+#ifdef PIKE_DEBUG
+	if(d_flag>1)
+	  for(x=howmany-1;x;x--)
+	    if( CMP( STEP(bas,x-1), STEP(bas,x)  ) > 0)
+	      fatal("Sorting failed!\n");
+#endif
+	
+	return;
+      }
 
-  for(x=howmany-1;x;x--)
-  {
-    SWAP( STEP(bas,x), bas);
-    y=0;
-    while(1)
-    {
-      z=CHILD1(y);
-      if(z>=x) break;
-      if(z+1 < x && CMP(STEP(bas,z),STEP(bas,z+1))<=0) z++;
-      if(CMP( STEP(bas, y), STEP(bas, z)) >0) break;
-      SWAP( STEP(bas, y), STEP(bas, z));
-      y=z;
+      b=STEP(bas,((((char *)last)-((char *)bas))/SIZE)>>1);
+      SWAP(bas,b);
+      b=last;
+      while(a < b)
+      {
+#if 1
+	while(a<b)
+	{
+	  while(1)
+	  {
+	    if(a<=b && CMP(a,bas) <= 0)
+	      INC(a);
+	    else
+	    {
+	      while(a< b && CMP(bas,b) <= 0) DEC(b);
+	      break;
+	    }
+	    if(a< b && CMP(bas,b) <= 0)
+	      DEC(b);
+	    else
+	    {
+	      while(a<=b && CMP(a,bas) <= 0) INC(a);
+	      break;
+	    }
+	  }
+	  
+	  if(a<b)
+	  {
+	    SWAP(a,b);
+	    INC(a);
+	    if(b > STEP(a,1)) DEC(b);
+	  }
+	}
+#else
+	while(a<=b && CMP(a,bas) < 0) INC(a);
+	while(a< b && CMP(bas,b) < 0) DEC(b);
+	if(a<b)
+	{
+	  SWAP(a,b);
+	  INC(a);
+	  if(b > STEP(a,1)) DEC(b);
+	}
+#endif
+      }
+      DEC(a);
+      SWAP(a,bas);
+      DEC(a);
+      
+      if(  (char *)a - (char *)bas < (char *)last - (char *)b )
+      {
+	MKNAME(_do_sort)(bas,a,max_recursion XARGS);
+	bas=b;
+      } else {
+	MKNAME(_do_sort)(b,last,max_recursion XARGS);
+	last=a;
+      }
     }
   }
+}
 
-#ifdef PIKE_DEBUG
-  if(d_flag>1)
-    for(x=howmany-1;x;x--)
-      if( CMP( STEP(bas,x-1), STEP(bas,x)  ) > 0)
-	fatal("Sorting failed!\n");
+void ID(register TYPE *bas,
+	register TYPE *last
+#ifdef EXTRA_ARGS
+	EXTRA_ARGS
 #endif
+  )
+{
+  extern int my_log2(unsigned INT32 x);
+  MKNAME(_do_sort)(bas,last, my_log2( last-bas ) * 2 XARGS);;
 }
 
+
 #undef INC
 #undef DEC
 #undef PARENT