mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
251 lines
6.2 KiB
251 lines
6.2 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: sort.c
|
|
*
|
|
*
|
|
* Created: 20-Mar-1995 09:52:19
|
|
* Author: Eric Kutter [erick]
|
|
*
|
|
* Copyright (c) 1993 Microsoft Corporation
|
|
*
|
|
*
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.hxx"
|
|
|
|
typedef struct _SORTSTACK
|
|
{
|
|
ULONG iStart;
|
|
ULONG c;
|
|
} SORTSTACK;
|
|
|
|
#define MAXSORT 20
|
|
|
|
typedef struct _SORTDATA
|
|
{
|
|
PBYTE pjBuf;
|
|
ULONG iStack;
|
|
ULONG cjElem;
|
|
SORTCOMP pfnComp;
|
|
SORTSTACK sStack[MAXSORT];
|
|
|
|
} SORTDATA;
|
|
|
|
/******************************Public*Routine******************************\
|
|
* vSortSwap()
|
|
*
|
|
* Swap the data pointed to by pj1 and pj2, each containing cj bytes.
|
|
*
|
|
* Note: this assumes cj is a multiple of 4.
|
|
*
|
|
* NOTE: vSortSwap should be inline.
|
|
*
|
|
* History:
|
|
* 18-Mar-1995 -by- Eric Kutter [erick]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID vSortSwap(
|
|
PBYTE pj1,
|
|
PBYTE pj2,
|
|
ULONG cj)
|
|
{
|
|
PLONG pl1 = (PLONG)pj1;
|
|
PLONG pl2 = (PLONG)pj2;
|
|
|
|
do
|
|
{
|
|
LONG l;
|
|
|
|
l = *pl1;
|
|
*pl1++ = *pl2;
|
|
*pl2++ = l;
|
|
|
|
} while (cj -= 4);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* vSortPush()
|
|
*
|
|
* Add a range to the stack to be sorted.
|
|
*
|
|
* If there are 0 or 1 elements, just return, sorting done.
|
|
* If there are 2, 3, 4, or 5 elements, just do a bubble sort. sorting done.
|
|
* If the stack is full, just do a bubble sort. sorting done.
|
|
* Otherwise, add a new range to the stack.
|
|
*
|
|
* History:
|
|
* 18-Mar-1995 -by- Eric Kutter [erick]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID vSortPush(
|
|
SORTDATA *psd,
|
|
ULONG iStart,
|
|
ULONG c)
|
|
{
|
|
PBYTE pj = psd->pjBuf + iStart;
|
|
|
|
#if DBGSORT
|
|
DbgPrintf("vSortPush - iStack = %ld, iStart = %ld, c = %ld\n",psd->iStack,iStart,c);
|
|
#endif
|
|
|
|
if (c > psd->cjElem)
|
|
{
|
|
ULONG i,j;
|
|
ULONG cjElem = psd->cjElem;
|
|
|
|
//for (i = 0; i < (c - cjElem); i += cjElem)
|
|
{
|
|
// if ((*psd->pfnComp)(&pj[i],&pj[i+cjElem]) > 0)
|
|
{
|
|
if ((c <= (4 * psd->cjElem)) || (psd->iStack == MAXSORT))
|
|
{
|
|
// we have 4 or fewer elements. Just do a buble sort. With 4 elements
|
|
// this will be a 6 compares and upto 6 swaps.
|
|
// We make c-1 passes over then entire array. Each pass guarantees that
|
|
// the next smallest element is shifted to location i. After the first pass
|
|
// the smallest element is in location 0. After the second pass the second
|
|
// smallest element is in location 1. etc.
|
|
|
|
|
|
#if DBGSORT
|
|
if (c > (4 * cjElem))
|
|
DbgPrintf("******* Stack too deep: c = %ld\n",c / cjElem);
|
|
#endif
|
|
|
|
for (i = 0; i < (c - cjElem); i += cjElem)
|
|
for (j = c - cjElem; j > i; j -= cjElem)
|
|
if ((*psd->pfnComp)(&pj[j-cjElem],&pj[j]) > 0)
|
|
vSortSwap(&pj[j-cjElem],&pj[j],cjElem);
|
|
}
|
|
else
|
|
{
|
|
psd->sStack[psd->iStack].iStart = iStart;
|
|
psd->sStack[psd->iStack].c = c;
|
|
psd->iStack++;
|
|
}
|
|
// break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* EngSort()
|
|
*
|
|
* This is an implementation of the c-runtime qsort.
|
|
*
|
|
* History:
|
|
* 18-Mar-1995 -by- Eric Kutter [erick]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
extern "C" VOID EngSort(
|
|
PBYTE pjBuf,
|
|
ULONG c,
|
|
ULONG cjElem,
|
|
SORTCOMP pfnComp)
|
|
{
|
|
SORTDATA sd;
|
|
|
|
#if DBGSORT
|
|
ULONG cOrg = c;
|
|
ULONG i;
|
|
|
|
DbgPrintf("\n\nvDrvSort - c = %d\n",c);
|
|
|
|
#endif
|
|
|
|
ASSERTGDI((cjElem & 0x3) == 0,"EngSort not dword aligned");
|
|
|
|
if (cjElem & 3)
|
|
return;
|
|
|
|
sd.pjBuf = pjBuf;
|
|
sd.iStack = 0;
|
|
sd.pfnComp = pfnComp;
|
|
sd.cjElem = cjElem;
|
|
|
|
vSortPush(&sd,0,c * cjElem);
|
|
|
|
while (sd.iStack)
|
|
{
|
|
PBYTE pj;
|
|
ULONG iStart;
|
|
ULONG iLow;
|
|
ULONG iHi;
|
|
|
|
--sd.iStack;
|
|
iStart = sd.sStack[sd.iStack].iStart;
|
|
pj = &pjBuf[iStart];
|
|
c = sd.sStack[sd.iStack].c;
|
|
|
|
#if DBGSORT
|
|
|
|
for (i = 0; i < cOrg;++i)
|
|
vPrintElem(&pjBuf[i * cjElem]);
|
|
DbgPrintf("\n");
|
|
|
|
DbgPrintf("iStart = %ld, c = %ld, iStack = %lx - ",iStart/cjElem,c/cjElem,sd.iStack);
|
|
|
|
for (i = 0; i < c;i += cjElem)
|
|
vPrintElem(&pj[i]);
|
|
DbgPrintf("\n");
|
|
|
|
#endif
|
|
|
|
// pick a random value to use for dividing. Don't use the first since this
|
|
// will reduce the chances of worst case if the list is sorted in reverse order.
|
|
|
|
vSortSwap(&pj[0],&pj[(c / cjElem) / 2 * cjElem],cjElem);
|
|
|
|
// initialize the starting and ending indexes. Note that all operations
|
|
// use cjElem as the increment instead of 1.
|
|
|
|
iLow = 0;
|
|
iHi = c - cjElem;
|
|
|
|
// divide the array into two pieces, all elements <= before current one
|
|
|
|
for (;;)
|
|
{
|
|
// while (pj[iHi] > pj[0]))
|
|
|
|
while ((iHi > iLow) && ((*pfnComp)(&pj[iHi],&pj[0]) >= 0))
|
|
iHi -= cjElem;
|
|
|
|
// while (pj[iLow] <= pj[0]))
|
|
|
|
while ((iLow < iHi) && ((*pfnComp)(&pj[iLow],&pj[0]) <= 0))
|
|
iLow += cjElem;
|
|
|
|
if (iHi == iLow)
|
|
break;
|
|
|
|
vSortSwap(&pj[iLow],&pj[iHi],cjElem);
|
|
|
|
iHi -= cjElem;
|
|
//if (iLow < iHi)
|
|
// iLow += cjElem;
|
|
|
|
#if DBGSORT
|
|
DbgPrintf("\tiLow = %ld, iHi = %ld\n",iLow/cjElem,iHi/cjElem);
|
|
#endif
|
|
}
|
|
|
|
// now add the two pieces to stack
|
|
// 0 -> (iLow - 1), (iLow + 1) -> (c - 1)
|
|
|
|
if (iLow != 0)
|
|
{
|
|
vSortSwap(&pj[0],&pj[iLow],cjElem);
|
|
if (iLow > 1)
|
|
vSortPush(&sd,iStart,iLow);
|
|
}
|
|
|
|
c = c - iLow - cjElem;
|
|
if (c > 1)
|
|
vSortPush(&sd,iStart + iLow + cjElem,c);
|
|
}
|
|
|
|
}
|