2015-07-31 16:01 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)
* src/vm/asort.c
% added new code for ASort()
Warning: new sorting algorithm is stable (does not change the
order of equal items). It means is not strictly Cl*pper
compatible and it can be seen some dummy ASort() tests
in HBTEST results.
This commit is contained in:
@@ -10,7 +10,14 @@
|
||||
* Change, ! Fix, % Optimization, + Addition, - Removal, ; Comment
|
||||
*/
|
||||
|
||||
2015-07-31 14:51 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)
|
||||
2015-07-31 16:01 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)
|
||||
* src/vm/asort.c
|
||||
% added new code for ASort()
|
||||
Warning: new sorting algorithm is stable (does not change the
|
||||
order of equal items). It means is not strictly Cl*pper
|
||||
compatible and it can be seen some dummy ASort() tests
|
||||
in HBTEST results.
|
||||
|
||||
2015-07-31 14:04 UTC+0200 Viktor Szakats (vszakats users.noreply.github.com)
|
||||
* include/hbapifs.h
|
||||
* src/rtl/filebuf.c
|
||||
|
||||
155
src/vm/asort.c
155
src/vm/asort.c
@@ -57,33 +57,34 @@
|
||||
#include "hbvmint.h"
|
||||
#include "hbapiitm.h"
|
||||
#include "hbvm.h"
|
||||
#include "hbstack.h"
|
||||
|
||||
static HB_BOOL hb_itemIsLess( PHB_ITEM pItem1, PHB_ITEM pItem2, PHB_ITEM pBlock, PHB_BASEARRAY pBaseArray, HB_SIZE nLast )
|
||||
static HB_BOOL hb_itemIsLess( PHB_BASEARRAY pBaseArray, PHB_ITEM pBlock,
|
||||
HB_SIZE nItem1, HB_SIZE nItem2 )
|
||||
{
|
||||
PHB_ITEM pItem1 = pBaseArray->pItems + nItem1,
|
||||
pItem2 = pBaseArray->pItems + nItem2;
|
||||
|
||||
if( pBlock )
|
||||
{
|
||||
PHB_ITEM pRet;
|
||||
|
||||
/* protection against array resizing by user codeblock */
|
||||
if( pBaseArray->nLen <= nItem1 || pBaseArray->nLen <= nItem2 )
|
||||
return HB_FALSE;
|
||||
|
||||
hb_vmPushEvalSym();
|
||||
hb_vmPush( pBlock );
|
||||
hb_vmPush( pItem1 );
|
||||
hb_vmPush( pItem2 );
|
||||
hb_vmSend( 2 );
|
||||
|
||||
if( pBaseArray->nLen <= nLast )
|
||||
return HB_FALSE;
|
||||
else
|
||||
{
|
||||
PHB_ITEM pRet = hb_param( -1, HB_IT_ANY );
|
||||
pRet = hb_param( -1, HB_IT_ANY );
|
||||
|
||||
/* CA-Cl*pper always takes return value as logical item
|
||||
* accepting 0, 1 as numeric representation of HB_FALSE/HB_TRUE
|
||||
*/
|
||||
if( HB_IS_LOGICAL( pRet ) ||
|
||||
HB_IS_NUMERIC( pRet ) )
|
||||
return hb_itemGetL( pRet );
|
||||
else
|
||||
return HB_TRUE;
|
||||
}
|
||||
/* CA-Cl*pper always takes return value as logical item
|
||||
* accepting 0, 1 as numeric representation of HB_FALSE/HB_TRUE
|
||||
*/
|
||||
return ( HB_IS_LOGICAL( pRet ) || HB_IS_NUMERIC( pRet ) ) ?
|
||||
hb_itemGetL( pRet ) : HB_TRUE;
|
||||
}
|
||||
|
||||
/* Do native compare when no codeblock is supplied */
|
||||
@@ -137,6 +138,8 @@ static HB_BOOL hb_itemIsLess( PHB_ITEM pItem1, PHB_ITEM pItem2, PHB_ITEM pBlock,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HB_CLP_STRICT
|
||||
|
||||
/* partition array pItems[lb..ub] */
|
||||
|
||||
static HB_ISIZ hb_arraySortQuickPartition( PHB_BASEARRAY pBaseArray, HB_ISIZ lb, HB_ISIZ ub, PHB_ITEM pBlock )
|
||||
@@ -154,10 +157,10 @@ static HB_ISIZ hb_arraySortQuickPartition( PHB_BASEARRAY pBaseArray, HB_ISIZ lb,
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
while( j >= i && ! hb_itemIsLess( pBaseArray->pItems + j, pBaseArray->pItems + lb, pBlock, pBaseArray, j ) )
|
||||
while( j >= i && ! hb_itemIsLess( pBaseArray, pBlock, j, lb ) )
|
||||
j--;
|
||||
|
||||
while( i < j && ! hb_itemIsLess( pBaseArray->pItems + lb, pBaseArray->pItems + i, pBlock, pBaseArray, i ) )
|
||||
while( i < j && ! hb_itemIsLess( pBaseArray, pBlock, lb, i ) )
|
||||
i++;
|
||||
|
||||
if( i >= j )
|
||||
@@ -208,6 +211,117 @@ static void hb_arraySortQuick( PHB_BASEARRAY pBaseArray, HB_ISIZ lb, HB_ISIZ ub,
|
||||
}
|
||||
}
|
||||
|
||||
static void hb_arraySortStart( PHB_BASEARRAY pBaseArray, PHB_ITEM pBlock,
|
||||
HB_SIZE nStart, HB_SIZE nCount )
|
||||
{
|
||||
hb_arraySortQuick( pBaseArray, nStart, nStart + nCount - 1, pBlock );
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static HB_BOOL hb_arraySortDO( PHB_BASEARRAY pBaseArray, PHB_ITEM pBlock,
|
||||
HB_SIZE * pSrc, HB_SIZE * pBuf, HB_SIZE nCount )
|
||||
{
|
||||
if( nCount > 1 )
|
||||
{
|
||||
HB_SIZE nCnt1, nCnt2, * pPtr1, * pPtr2, * pDst;
|
||||
HB_BOOL fBuf1, fBuf2;
|
||||
|
||||
nCnt1 = nCount >> 1;
|
||||
nCnt2 = nCount - nCnt1;
|
||||
pPtr1 = &pSrc[ 0 ];
|
||||
pPtr2 = &pSrc[ nCnt1 ];
|
||||
|
||||
fBuf1 = hb_arraySortDO( pBaseArray, pBlock, pPtr1, &pBuf[ 0 ], nCnt1 );
|
||||
fBuf2 = hb_arraySortDO( pBaseArray, pBlock, pPtr2, &pBuf[ nCnt1 ], nCnt2 );
|
||||
if( fBuf1 )
|
||||
pDst = pBuf;
|
||||
else
|
||||
{
|
||||
pDst = pSrc;
|
||||
pPtr1 = &pBuf[ 0 ];
|
||||
}
|
||||
if( ! fBuf2 )
|
||||
pPtr2 = &pBuf[ nCnt1 ];
|
||||
|
||||
while( nCnt1 > 0 && nCnt2 > 0 )
|
||||
{
|
||||
if( hb_itemIsLess( pBaseArray, pBlock, *pPtr2, *pPtr1 ) )
|
||||
{
|
||||
*pDst++ = *pPtr2++;
|
||||
nCnt2--;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pDst++ = *pPtr1++;
|
||||
nCnt1--;
|
||||
}
|
||||
}
|
||||
if( nCnt1 > 0 )
|
||||
{
|
||||
do
|
||||
*pDst++ = *pPtr1++;
|
||||
while( --nCnt1 );
|
||||
}
|
||||
else if( nCnt2 > 0 && fBuf1 == fBuf2 )
|
||||
{
|
||||
do
|
||||
*pDst++ = *pPtr2++;
|
||||
while( --nCnt2 );
|
||||
}
|
||||
return ! fBuf1;
|
||||
}
|
||||
return HB_TRUE;
|
||||
}
|
||||
|
||||
static void hb_arraySortStart( PHB_BASEARRAY pBaseArray, PHB_ITEM pBlock,
|
||||
HB_SIZE nStart, HB_SIZE nCount )
|
||||
{
|
||||
HB_SIZE * pBuffer, * pDest, * pPos, nPos, nTo;
|
||||
|
||||
pBuffer = ( HB_SIZE * ) hb_xgrab( sizeof( HB_SIZE ) * 2 * nCount );
|
||||
for( nPos = 0; nPos < nCount; ++nPos )
|
||||
pBuffer[ nPos ] = nStart + nPos;
|
||||
|
||||
if( hb_arraySortDO( pBaseArray, pBlock, pBuffer, &pBuffer[ nCount ], nCount ) )
|
||||
pPos = ( pDest = pBuffer ) + nCount;
|
||||
else
|
||||
pDest = ( pPos = pBuffer ) + nCount;
|
||||
|
||||
/* protection against array resizing by user codeblock */
|
||||
if( nStart + nCount >= pBaseArray->nLen )
|
||||
{
|
||||
if( pBaseArray->nLen > nStart )
|
||||
{
|
||||
for( nPos = nTo = 0; nPos < nCount; ++nPos )
|
||||
{
|
||||
if( pDest[ nPos ] < pBaseArray->nLen )
|
||||
pDest[ nTo++ ] = pDest[ nPos ];
|
||||
}
|
||||
nCount = nTo;
|
||||
}
|
||||
else
|
||||
nCount = 0;
|
||||
}
|
||||
|
||||
for( nPos = 0; nPos < nCount; ++nPos )
|
||||
pPos[ pDest[ nPos ] - nStart ] = nPos;
|
||||
|
||||
for( nPos = 0; nPos < nCount; ++nPos )
|
||||
{
|
||||
if( nPos != pDest[ nPos ] )
|
||||
{
|
||||
hb_itemSwap( pBaseArray->pItems + nPos,
|
||||
pBaseArray->pItems + pDest[ nPos ] );
|
||||
pDest[ pPos[ nPos ] ] = pDest[ nPos ];
|
||||
pPos[ pDest[ nPos ] - nStart ] = pPos[ nPos ];
|
||||
}
|
||||
}
|
||||
|
||||
hb_xfree( pBuffer );
|
||||
}
|
||||
#endif /* HB_CLP_STRICT */
|
||||
|
||||
HB_BOOL hb_arraySort( PHB_ITEM pArray, HB_SIZE * pnStart, HB_SIZE * pnCount, PHB_ITEM pBlock )
|
||||
{
|
||||
HB_TRACE( HB_TR_DEBUG, ( "hb_arraySort(%p, %p, %p, %p)", pArray, pnStart, pnCount, pBlock ) );
|
||||
@@ -218,7 +332,6 @@ HB_BOOL hb_arraySort( PHB_ITEM pArray, HB_SIZE * pnStart, HB_SIZE * pnCount, PHB
|
||||
HB_SIZE nLen = pBaseArray->nLen;
|
||||
HB_SIZE nStart;
|
||||
HB_SIZE nCount;
|
||||
HB_SIZE nEnd;
|
||||
|
||||
if( pnStart && *pnStart >= 1 )
|
||||
nStart = *pnStart;
|
||||
@@ -235,11 +348,9 @@ HB_BOOL hb_arraySort( PHB_ITEM pArray, HB_SIZE * pnStart, HB_SIZE * pnCount, PHB
|
||||
if( nStart + nCount > nLen ) /* check range */
|
||||
nCount = nLen - nStart + 1;
|
||||
|
||||
nEnd = nCount + nStart - 2;
|
||||
|
||||
/* Optimize when only one or no element is to be sorted */
|
||||
if( nCount > 1 )
|
||||
hb_arraySortQuick( pBaseArray, nStart - 1, nEnd, pBlock );
|
||||
hb_arraySortStart( pBaseArray, pBlock, nStart - 1, nCount );
|
||||
}
|
||||
|
||||
return HB_TRUE;
|
||||
|
||||
Reference in New Issue
Block a user