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:
Przemysław Czerpak
2015-07-31 16:01:33 +02:00
parent 78c1d987db
commit 9e318add44
2 changed files with 141 additions and 23 deletions

View File

@@ -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

View File

@@ -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;