Files
epics-base/modules/libcom/src/ellLib/ellSort.c
Andrew Johnson 3c99391d93 Added SPDX License ID to all EPICS-original source files
In some cases the license-identification header was missing,
so I added that as well. Replaced the remaining headers that
specifically identified "Versions 3.13.7 and higher".

Makefiles and the build system were deliberately excluded.
2020-08-03 11:53:01 -05:00

84 lines
2.2 KiB
C

/*************************************************************************\
* Copyright (c) 2014 Brookhaven Science Assoc., as Operator of Argonne
* National Laboratory.
* Copyright (c) 2016 Michael Davidsaver
* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Use of mergesort algorithm based on analysis by
* http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
*/
#include <stdlib.h>
#include "epicsAssert.h"
#include "ellLib.h"
static void ellMoveN(ELLLIST* pTo, ELLLIST* pFrom, int count )
{
for(;count && ellCount(pFrom); count--) {
ELLNODE *node = ellGet(pFrom);
ellAdd(pTo, node);
}
}
/* Stable (MergeSort) to given list.
* The comparison function cmp(A,B) is expected
* to return -1 for A<B, 0 for A==B, and 1 for A>B.
*/
void ellSortStable(ELLLIST *pList, pListCmp cmp)
{
ELLLIST INP, P, Q;
size_t insize = 1; /* initial sub-list size */
if(ellCount(pList)<=1)
return;
ellInit(&INP);
ellInit(&P);
ellInit(&Q);
/* Process is to iteratively sort
* a sequence of sub-lists of size 'insize'
*/
while(insize < ellCount(pList)) {
assert(ellCount(&INP)==0);
/* shift previous results to inputs */
ellConcat(&INP, pList);
while(ellCount(&INP))
{
ELLNODE *p, *q;
/* Pull out the next pair of sub-lists */
ellMoveN(&Q, &INP, insize);
ellMoveN(&P, &INP, insize);
/* merge these sub-lists */
while((p=ellFirst(&P)) && (q=ellFirst(&Q)))
{
if((*cmp)(p,q) < 0) {
ellAdd(pList, ellGet(&P));
} else {
ellAdd(pList, ellGet(&Q));
}
}
/* concatenate any remaining to result */
if(ellFirst(&P))
ellConcat(pList, &P);
else if(ellFirst(&Q))
ellConcat(pList, &Q);
assert(!ellFirst(&P) && !ellFirst(&Q));
}
insize *= 2;
}
}