summaryrefslogtreecommitdiff
path: root/src/compression/merge_sort.c
diff options
context:
space:
mode:
authorDaniel Spangberg <daniels@kemi.uu.se>2013-05-15 12:31:28 (GMT)
committerDaniel Spangberg <daniels@kemi.uu.se>2013-05-15 12:31:28 (GMT)
commit2882416b599514f5a7e60b07c6a20b53a32f9027 (patch)
treefe8fd58b5023c7835af4096f32389e7cb8aaa6bb /src/compression/merge_sort.c
parent43f0748e4a4335e0eb9f81cc8a4728616ac08cf1 (diff)
Added tng_compress trajectory compression algorithms
Diffstat (limited to 'src/compression/merge_sort.c')
-rw-r--r--src/compression/merge_sort.c130
1 files changed, 130 insertions, 0 deletions
diff --git a/src/compression/merge_sort.c b/src/compression/merge_sort.c
new file mode 100644
index 0000000..75dd550
--- /dev/null
+++ b/src/compression/merge_sort.c
@@ -0,0 +1,130 @@
+/* This code is part of the tng compression routines.
+ *
+ * Written by Daniel Spangberg
+ * Copyright (c) 2010, 2013, The GROMACS development team.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "warnmalloc.h"
+#include "merge_sort.h"
+
+static void ms_inner(void *base, size_t size,
+ int start, int end,
+ int (*compar)(const void *v1,const void *v2,const void *private),
+ const void *private,
+ char *workarray)
+{
+ int middle;
+ if ((end-start)>1)
+ {
+ char *cbase=(char *)base;
+ middle=start+(end-start)/2;
+#if 0
+ printf("For start %d end %d obtained new middle: %d\n",start,end,middle);
+#endif
+ ms_inner(base,size,
+ start,middle,
+ compar,private,workarray);
+ ms_inner(base,size,
+ middle,end,
+ compar,private,workarray);
+#if 0
+ printf("For start %d end %d Before merge: Comparing element %d with %d\n",start,end,middle-1,middle);
+#endif
+ if (compar(cbase+(middle-1)*size,cbase+middle*size,private)>0)
+ {
+ /* Merge to work array. */
+ int i, n=end-start;
+ int ileft=start;
+ int iright=middle;
+ for (i=0; i<n; i++)
+ {
+ if (ileft==middle)
+ {
+ memcpy(workarray+i*size,cbase+iright*size,size);
+ iright++;
+ }
+ else if (iright==end)
+ {
+ memcpy(workarray+i*size,cbase+ileft*size,size);
+ ileft++;
+ }
+ else
+ {
+#if 0
+ printf("For start %d end %d In merge: Comparing element %d with %d\n",start,end,ileft,iright);
+#endif
+ if (compar(cbase+ileft*size,cbase+iright*size,private)>0)
+ {
+ memcpy(workarray+i*size,cbase+iright*size,size);
+ iright++;
+ }
+ else
+ {
+ memcpy(workarray+i*size,cbase+ileft*size,size);
+ ileft++;
+ }
+ }
+ }
+ /* Copy result back. */
+ memcpy(cbase+start*size,workarray,(end-start)*size);
+ }
+ }
+}
+
+
+void Ptngc_merge_sort(void *base, size_t nmemb, size_t size,
+ int (*compar)(const void *v1,const void *v2,const void *private),
+ void *private)
+{
+ char *warr=warnmalloc(nmemb*size);
+ ms_inner(base,size,0,nmemb,compar,private,warr);
+ free(warr);
+}
+
+
+#ifdef TEST
+
+static int compint(const void *v1, const void *v2,const void *private)
+{
+ const int *i1=(const int *)v1;
+ const int *i2=(const int *)v2;
+ if (*i1<*i2)
+ return -1;
+ else if (*i1>*i2)
+ return 1;
+ else
+ return 0;
+}
+
+static int qcompint(const void *v1, const void *v2)
+{
+ return compint(v1,v2,NULL);
+}
+
+#define N 1000000
+int main()
+{
+ int *arr=warnmalloc(N*sizeof *arr);
+ int i;
+ for (i=0; i<N; i++)
+ scanf("%d",arr+i);
+#if 1
+ merge_sort(arr,N,sizeof *arr,compint,NULL);
+#else
+ qsort(arr,N,sizeof *arr,qcompint);
+#endif
+ for (i=0; i<N; i++)
+ printf("%d %d\n",i,arr[i]);
+ return 0;
+}
+#endif
contact: Jan Huwald // Impressum