This is Unofficial EPICS BASE Doxygen Site
ellSort.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2014 Brookhaven Science Assoc., as Operator of Argonne
3 * National Laboratory.
4 * Copyright (c) 2016 Michael Davidsaver
5 * EPICS BASE is distributed subject to a Software License Agreement found
6 * in file LICENSE that is included with this distribution.
7 \*************************************************************************/
8 
9 /*
10  * Use of mergesort algorithm based on analysis by
11  * http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
12  */
13 #include <stdlib.h>
14 
15 #include "epicsAssert.h"
16 #include "ellLib.h"
17 
18 static void ellMoveN(ELLLIST* pTo, ELLLIST* pFrom, int count )
19 {
20  for(;count && ellCount(pFrom); count--) {
21  ELLNODE *node = ellGet(pFrom);
22  ellAdd(pTo, node);
23  }
24 }
25 
26 /* Stable (MergeSort) to given list.
27  * The comparison function cmp(A,B) is expected
28  * to return -1 for A<B, 0 for A==B, and 1 for A>B.
29  */
30 void ellSortStable(ELLLIST *pList, pListCmp cmp)
31 {
32  ELLLIST INP, P, Q;
33  size_t insize = 1; /* initial sub-list size */
34  if(ellCount(pList)<=1)
35  return;
36 
37  ellInit(&INP);
38  ellInit(&P);
39  ellInit(&Q);
40 
41  /* Process is to iteratively sort
42  * a sequence of sub-lists of size 'insize'
43  */
44 
45  while(insize < ellCount(pList)) {
46 
47  assert(ellCount(&INP)==0);
48 
49  /* shift previous results to inputs */
50  ellConcat(&INP, pList);
51 
52  while(ellCount(&INP))
53  {
54  ELLNODE *p, *q;
55 
56  /* Pull out the next pair of sub-lists */
57  ellMoveN(&Q, &INP, insize);
58  ellMoveN(&P, &INP, insize);
59 
60  /* merge these sub-lists */
61  while((p=ellFirst(&P)) && (q=ellFirst(&Q)))
62  {
63  if((*cmp)(p,q) < 0) {
64  ellAdd(pList, ellGet(&P));
65  } else {
66  ellAdd(pList, ellGet(&Q));
67  }
68  }
69 
70  /* concatenate any remaining to result */
71  if(ellFirst(&P))
72  ellConcat(pList, &P);
73  else if(ellFirst(&Q))
74  ellConcat(pList, &Q);
75 
76  assert(!ellFirst(&P) && !ellFirst(&Q));
77  }
78 
79  insize *= 2;
80  }
81 
82 }
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
#define ellCount(PLIST)
Report the number of nodes in a list.
Definition: ellLib.h:84
An EPICS-specific replacement for ANSI C&#39;s assert.
ELLNODE * ellGet(ELLLIST *pList)
Deletes and returns the first node from a list.
Definition: ellLib.c:147
A doubly-linked list library.
void ellAdd(ELLLIST *pList, ELLNODE *pNode)
Adds a node to the end of a list.
Definition: ellLib.c:24
List node type.
Definition: ellLib.h:45
void ellSortStable(ELLLIST *pList, pListCmp cmp)
Stable (MergeSort) of a given list.
Definition: ellSort.c:30
#define ellInit(PLIST)
Initialize a list type.
Definition: ellLib.h:76
void ellConcat(ELLLIST *pDstList, ELLLIST *pAddList)
Concatenates a list to the end of another list. The list to be added is left empty. Either list (or both) can be empty at the beginning of the operation.
Definition: ellLib.c:46
List header type.
Definition: ellLib.h:56
int(* pListCmp)(const ELLNODE *A, const ELLNODE *B)
Definition: ellLib.h:184
#define ellFirst(PLIST)
Find the first node in list.
Definition: ellLib.h:89