home *** CD-ROM | disk | FTP | other *** search
- // sort.cpp RHS 7/29/91
-
- #include "sort.h"
- /*-----------------------------------------------------------------------*
-
- Name Swap - exchanges two objects
-
- Usage void near pascal Swap (void *left,
- void *right);
-
- Description exchanges the elWidth byte wide objects pointed to
- by left and right.
-
- Return value Nothing
-
- *------------------------------------------------------------------------*/
-
- void near pascal swap2(FARPPV left, FARPPV right)
- {
- asm push Ds
- asm cld
- // note that elWidth is never 0, since it's tested at entry to QSort
- asm mov Cx, 4
- asm les Di, right
- asm lds Si, left
-
- asm shr Cx, 1 // test for an odd number of bytes
- asm jnc xch_wordLoop
-
- asm mov Al, Es:[Di]
- asm movsb // swap bytes, advancing pointers
- asm mov [Si-1], Al
- asm jz xch_end // if CX was originally 1
-
- xch_wordLoop:
- asm mov Ax, Es:[Di]
- asm movsw // swap words, advancing pointers
- asm mov [Si-2], Ax
- asm loop xch_wordLoop
-
- xch_end:
- asm pop Ds
- return;
- }
-
- void near pascal Sort::Swap(void FAR *left, void FAR *right)
- {
- int i;
- unsigned char c;
-
- for(i = 0; i < elWidth; i++)
- {
- c = *((unsigned char far *)right);
- *((unsigned char *)right)++ = *((unsigned char far *)left);
- *((unsigned char far *)left)++ = c;
- }
- return;
- }
-
- /*
- Optimize pointer comparisons knowing segments are identical,
- except in HUGE model.
- */
-
-
- /*-----------------------------------------------------------------------*
-
- Name QSort - performs the quicker sort
-
- Usage void near pascal QSort (char *base,
- size_t numEl);
-
- Description performs the quicker sort on the numEl element array
- pointed to by base.
-
- Return value Nothing
-
- *------------------------------------------------------------------------*/
- #pragma warn -sig
- void near pascal Sort::QSort(char FAR *base, size_t numEl)
- {
- char FAR *left, FAR *right;
- unsigned lNum;
-
- TailRecursionOpt:
- if(numEl < 2)
- {
- if(numEl == 2)
- if(PCmpFunc(base, right = elWidth + base) > 0)
- swap2((FARPPV) base, (FARPPV) right);
- return;
- }
-
- right = (numEl - 1) * elWidth + base;
- left = (numEl >> 1) * elWidth + base;
-
- // sort the pivot, left, and right elements for "median of 3"
-
- if(PCmpFunc(left, right) > 0)
- swap2((FARPPV) left, (FARPPV) right);
-
- if(PCmpFunc(left, base) > 0)
- swap2((FARPPV) left, (FARPPV) base);
-
- else if(PCmpFunc(base, right) > 0)
- swap2((FARPPV) base, (FARPPV) right);
-
-
- if(numEl == 3)
- {
- swap2((FARPPV) base, (FARPPV) left);
- return;
- }
-
- // now for the classic Hoare algorithm
-
- left = elWidth + base;
- do
- {
- while(PCmpFunc(left, base) < 0)
- if(left < right)
- left += elWidth;
- else
- goto Break;
-
- while(left < right)
- if(PCmpFunc(base, right) <= 0)
- right -= elWidth;
- else
- {
- swap2((FARPPV) left, (FARPPV) right);
- left += elWidth;
- right -= elWidth;
- break;
- }
- }
- while(left < right);
-
- Break:
- if(PCmpFunc(left, base) < 0)
- swap2((FARPPV) left, (FARPPV) base);
-
-
- lNum = (left - base) / elWidth;
-
- if(numEl -= lNum)
- QSort(left, numEl);
-
- numEl = lNum;
- goto TailRecursionOpt;
- }
-
- #pragma warn .sig
- void Sort::QuickSort(void FAR *base, size_t numEl, size_t width, CmpFunc *compar)
- {
- if((elWidth = width) == 0)
- return;
-
- PCmpFunc = compar;
-
- QSort((char FAR *)base, numEl);
- }
-