diff --git a/src/fsort.c b/src/fsort.c
index 7cf6896a6c838eb8c768bb0eafc990c068cb3165..71256c7121681011c22b59e1f9876e44a0196ae7 100644
--- a/src/fsort.c
+++ b/src/fsort.c
@@ -14,89 +14,62 @@ static long size;
 static char *tmp_area;
 
 #define SWAP(X,Y) { tmp=*(X); *(X)=*(Y); *(Y)=tmp; }
+#define STEP(X,Y) ((X)+(Y))
 
-#define FSORT(ID,TYPE) \
-static void ID(register TYPE *bas,register TYPE *last) \
-{ \
-  register TYPE *a,*b, tmp; \
-  if(bas >= last) return; \
-  a = bas + 1; \
-  if(a == last) \
-  { \
-    if( (*cmpfun)((void *)bas,(void *)last) > 0) SWAP(bas,last);  \
-  }else{ \
-    b=bas+((last-bas)>>1); \
-    SWAP(bas,b); \
-    b=last; \
-    while(a < b) \
-    { \
-      while(a<=b && (*cmpfun)((void *)a,(void *)bas) < 0) a++; \
-      while(a< b && (*cmpfun)((void *)bas,(void *)b) < 0) b--; \
-      if(a<b) \
-      { \
-        SWAP(a,b); \
-        a++; \
-        if(b > a+1) b--; \
-      } \
-    } \
-    a--; \
-    SWAP(a,bas); \
-    a--; \
-    ID(bas,a); \
-    ID(b,last); \
-  } \
-}
+#define ID fsort_1
+typedef struct a1 { char b[1]; } b1;
+#define TYPE b1
+#include "fsort_template.h"
+#undef ID
+#undef TYPE
 
-#define FSWAP(X,Y) \
- { \
-    MEMCPY(tmp_area,X,size); \
-    MEMCPY(X,Y,size); \
-    MEMCPY(Y,tmp_area,size); \
- }
+#define ID fsort_2
+typedef struct a2 { char b[2]; } b2;
+#define TYPE b2
+#include "fsort_template.h"
+#undef ID
+#undef TYPE
 
-static void fsort_n(register char *bas,register char *last)
-{
-  register char *a,*b;
-  register int dum;
+#define ID fsort_4
+typedef struct a4 { char b[4]; } b4;
+#define TYPE b4
+#include "fsort_template.h"
+#undef ID
+#undef TYPE
 
-  if(bas>=last) return;
-  a=bas+size;
-  if(a==last)
-  {
-    if((*cmpfun)(bas,last) > 0) FSWAP(bas,last);
-  }else{
-    dum=(last-bas)>>1;
-    dum-=dum % size;
-    FSWAP(bas,bas+dum);
-    b=last;
-    while(a<b)
-    {
-      while(a<=b && (*cmpfun)(a,bas) < 0) a+=size;
-      while(a< b && (*cmpfun)(bas,b) < 0) b-=size;
-      if(a<b)
-      {
-	FSWAP(a,b);
-	a+=size;
-	if(b-a>size) b-=size;
-      }
-    }
-    a-=size;
-    FSWAP(bas,a);
-    a-=size;
-    fsort_n(bas,a);
-    fsort_n(b,last);
-  }
-}
 
-typedef struct a { char b[1]; } onebyte;
-typedef struct b { char b[2]; } twobytes;
-typedef struct c { char b[4]; } fourbytes;
-typedef struct d { char b[8]; } eightbytes;
+#define ID fsort_8
+typedef struct a8 { char b[8]; } b8;
+#define TYPE b8
+#include "fsort_template.h"
+#undef ID
+#undef TYPE
+
+#define ID fsort_16
+typedef struct a16 { char b[16]; } b16;
+#define TYPE b16
+#include "fsort_template.h"
+#undef ID
+#undef TYPE
+
+#undef SWAP
+#undef STEP
+
+
+#define SWAP(X,Y) do { \
+    MEMCPY(tmp_area,X,size); \
+    MEMCPY(X,Y,size); \
+    MEMCPY(Y,tmp_area,size); \
+ } while(0)
 
-FSORT(fsort_1, onebyte)
-FSORT(fsort_2, twobytes)
-FSORT(fsort_4, fourbytes)
-FSORT(fsort_8, eightbytes)
+#define STEP(X,Y) ((X)+(Y)*size)
+#define TYPE char
+#define ID fsort_n
+#include "fsort_template.h"
+#undef ID
+#undef TYPE
+#undef SWAP
+#undef STEP
 
 void fsort(void *base,
 	   long elms,
@@ -110,10 +83,11 @@ void fsort(void *base,
 
   switch(elmSize)
   {
-  case 1: fsort_1((onebyte *)base,(elms-1)+(onebyte *)base); break;
-  case 2: fsort_2((twobytes *)base,(elms-1)+(twobytes *)base); break;
-  case 4: fsort_4((fourbytes *)base,(elms-1)+(fourbytes *)base); break;
-  case 8: fsort_8((eightbytes *)base,(elms-1)+(eightbytes *)base); break;
+  case  1:  fsort_1(( b1 *)base,(elms-1)+( b1 *)base); break;
+  case  2:  fsort_2(( b2 *)base,(elms-1)+( b2 *)base); break;
+  case  4:  fsort_4(( b4 *)base,(elms-1)+( b4 *)base); break;
+  case  8:  fsort_8(( b8 *)base,(elms-1)+( b8 *)base); break;
+  case 16: fsort_16((b16 *)base,(elms-1)+(b16 *)base); break;
   default:
     tmp_area=(char *)alloca(elmSize);
     fsort_n((char *)base,((char *)base) + size * (elms - 1));
diff --git a/src/fsort_template.h b/src/fsort_template.h
new file mode 100644
index 0000000000000000000000000000000000000000..6c0e9fc6123cc6142e57c45d0a2ffb0d9cbfc441
--- /dev/null
+++ b/src/fsort_template.h
@@ -0,0 +1,68 @@
+#define INC(X) X=STEP(X,1)
+#define DEC(X) X=STEP(X,-1)
+#define SIZE ((long)STEP((TYPE *)0,1))
+
+static void ID(register TYPE *bas, register TYPE *last)
+{
+  register TYPE *a,*b, tmp;
+  if(bas >= last) return;
+  a = STEP(bas,1);
+  if(a == last)
+  {
+    if( (*cmpfun)((void *)bas,(void *)last) > 0) SWAP(bas,last); 
+  }else{
+    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 && (*cmpfun)((void *)a,(void *)bas) <= 0)
+	    INC(a);
+	  else
+	  {
+	    while(a< b && (*cmpfun)((void *)bas,(void *)b) <= 0) DEC(b);
+	    break;
+	  }
+	  if(a< b && (*cmpfun)((void *)bas,(void *)b) <= 0)
+	    DEC(b);
+	  else
+	  {
+	    while(a<=b && (*cmpfun)((void *)a,(void *)bas) <= 0) INC(a);
+	    break;
+	  }
+	}
+
+	if(a<b)
+	{
+	  SWAP(a,b);
+	  INC(a);
+	  if(b > STEP(a,1)) DEC(b);
+	}
+      }
+#else
+      while(a<=b && (*cmpfun)((void *)a,(void *)bas) < 0) INC(a);
+      while(a< b && (*cmpfun)((void *)bas,(void *)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);
+    ID(bas,a);
+    ID(b,last);
+  }
+}
+
+#undef INC
+#undef DEC
+#undef SIZE