Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 79 additions & 61 deletions squirrel/sqbaselib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -726,75 +726,93 @@ static bool _sort_compare(HSQUIRRELVM v,SQObjectPtr &a,SQObjectPtr &b,SQInteger
return true;
}

static bool _hsort_sift_down(HSQUIRRELVM v,SQArray *arr, SQInteger root, SQInteger bottom, SQInteger func)
{
SQInteger maxChild;
SQInteger done = 0;
SQInteger ret;
SQInteger root2;
while (((root2 = root * 2) <= bottom) && (!done))
{
if (root2 == bottom) {
maxChild = root2;
}
else {
if(!_sort_compare(v,arr->_values[root2],arr->_values[root2 + 1],func,ret))
return false;
if (ret > 0) {
maxChild = root2;
}
else {
maxChild = root2 + 1;
}
}
/*
** The lua_auxsort code is adapted from from lua 5.1.5
** {======================================================
** Quicksort
** (based on 'Algorithms in MODULA-3', Robert Sedgewick;
** Addison-Wesley, 1993.)
** =======================================================
*/

if(!_sort_compare(v,arr->_values[root],arr->_values[maxChild],func,ret))
static bool lua_auxsort (HSQUIRRELVM v, SQArray *arr, SQInteger l, SQInteger u,
SQInteger func) {
while (l < u) { /* for tail recursion */
SQInteger i, j, ret;
bool rc;
/* sort elements a[l], a[(l+u)/2] and a[u] */
if(!_sort_compare(v,arr->_values[u],arr->_values[l],func,ret))
return false;
if (ret < 0) /* a[u] < a[l]? */
_Swap(arr->_values[l],arr->_values[u]); /* swap a[l] - a[u] */
if (u-l == 1) break; /* only 2 elements */
i = (l+u)/2;
if(!_sort_compare(v,arr->_values[i],arr->_values[l],func,ret))
return false;
if (ret < 0) /* a[i]<a[l]? */
_Swap(arr->_values[i],arr->_values[l]);
else {
if(!_sort_compare(v,arr->_values[u],arr->_values[i],func,ret))
return false;
if (ret < 0) /* a[u]<a[i]? */
_Swap(arr->_values[i],arr->_values[u]);
}
if (u-l == 2) break; /* only 3 elements */
SQObjectPtr P = arr->_values[i]; /* Pivot */
_Swap(arr->_values[i],arr->_values[u-1]);
/* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */
i = l; j = u-1;
for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */
/* repeat ++i until a[i] >= P */
while ((rc = _sort_compare(v,arr->_values[++i],P,func,ret)) && (ret < 0)) {
if (i>u)
{
sq_throwerror(v, _SC("invalid order function for sorting"));
return false;
if (ret < 0) {
if (root == maxChild) {
v->Raise_Error(_SC("inconsistent compare function"));
return false; // We'd be swapping ourselve. The compare function is incorrect
}

_Swap(arr->_values[root],arr->_values[maxChild]);
root = maxChild;
}
else {
done = 1;
}
if(!rc) return false;
/* repeat --j until a[j] <= P */
while ((rc = _sort_compare(v,P, arr->_values[--j],func,ret)) && (ret < 0)) {
if (j<l)
{
sq_throwerror(v, _SC("invalid order function for sorting"));
return false;
}
}
if(!rc) return false;
if (j<i) {
break;
}
_Swap(arr->_values[i],arr->_values[j]);
}
return true;
}

static bool _hsort(HSQUIRRELVM v,SQObjectPtr &arr, SQInteger SQ_UNUSED_ARG(l), SQInteger SQ_UNUSED_ARG(r),SQInteger func)
{
SQArray *a = _array(arr);
SQInteger i;
SQInteger array_size = a->Size();
for (i = (array_size / 2); i >= 0; i--) {
if(!_hsort_sift_down(v,a, i, array_size - 1,func)) return false;
_Swap(arr->_values[u-1],arr->_values[i]); /* swap pivot (a[u-1]) with a[i] */
/* a[l..i-1] <= a[i] == P <= a[i+1..u] */
/* adjust so that smaller half is in [j..i] and larger one in [l..u] */
if (i-l < u-i) {
j=l; i=i-1; l=i+2;
}

for (i = array_size-1; i >= 1; i--)
{
_Swap(a->_values[0],a->_values[i]);
if(!_hsort_sift_down(v,a, 0, i-1,func)) return false;
else {
j=i+1; i=u; u=j-2;
}
return true;
}

static SQInteger array_sort(HSQUIRRELVM v)
{
SQInteger func = -1;
SQObjectPtr &o = stack_get(v,1);
if(_array(o)->Size() > 1) {
if(sq_gettop(v) == 2) func = 2;
if(!_hsort(v, o, 0, _array(o)->Size()-1, func))
return SQ_ERROR;
if(!lua_auxsort(v, arr, j, i, func)) /* call recursively for upper interval */
return false;
} /* repeat the routine for the larger one */
return true;
}

static SQRESULT array_sort(HSQUIRRELVM v) {
SQInteger func = -1;
SQObjectPtr &o = stack_get(v,1);
SQArray *arr = _array(o);
if(arr->Size() > 1) {
if(sq_gettop(v) == 2) func = 2;
if(!lua_auxsort(v, arr, 0, arr->Size()-1, func))
return SQ_ERROR;

}
sq_settop(v,1);
return 1;
}
sq_settop(v,1);
return 1;
}

static SQInteger array_slice(HSQUIRRELVM v)
Expand Down
2 changes: 1 addition & 1 deletion squirrel/sqclosure.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ struct SQOuter : public CHAINABLE_OBJ
SQObjectPtr *_valptr; /* pointer to value on stack, or _value below */
SQInteger _idx; /* idx in stack array, for relocation */
SQObjectPtr _value; /* value of outer after stack frame is closed */
SQOuter *_next; /* pointer to next outer when frame is open */
SQOuter *_next_outer; /* pointer to next outer when frame is open */
};

//////////////////////////////////////////////
Expand Down
8 changes: 4 additions & 4 deletions squirrel/sqvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1632,10 +1632,10 @@ void SQVM::FindOuter(SQObjectPtr &target, SQObjectPtr *stackindex)
target = SQObjectPtr(p);
return;
}
pp = &p->_next;
pp = &p->_next_outer;
}
otr = SQOuter::Create(_ss(this), stackindex);
otr->_next = *pp;
otr->_next_outer = *pp;
otr->_idx = (stackindex - _stack._vals);
__ObjAddRef(otr);
*pp = otr;
Expand Down Expand Up @@ -1695,7 +1695,7 @@ void SQVM::RelocateOuters()
SQOuter *p = _openouters;
while (p) {
p->_valptr = _stack._vals + p->_idx;
p = p->_next;
p = p->_next_outer;
}
}

Expand All @@ -1704,7 +1704,7 @@ void SQVM::CloseOuters(SQObjectPtr *stackindex) {
while ((p = _openouters) != NULL && p->_valptr >= stackindex) {
p->_value = *(p->_valptr);
p->_valptr = &p->_value;
_openouters = p->_next;
_openouters = p->_next_outer;
__ObjRelease(p);
}
}
Expand Down
1 change: 0 additions & 1 deletion squirrel/sqvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,6 @@ typedef sqvector<CallInfo> CallInfoVec;
CallInfo *ci;
SQUserPointer _foreignptr;
//VMs sharing the same state
SQSharedState *_sharedstate;
SQInteger _nnativecalls;
SQInteger _nmetamethodscall;
SQRELEASEHOOK _releasehook;
Expand Down
Loading