Exemple #1
0
        /*
        ** Choose an element in the middle (2nd-3th quarters) of [lo,up]
        ** "randomized" by 'rnd'
        */
        private static IdxT choosePivot(IdxT lo, IdxT up, uint rnd)
        {
            IdxT r4 = (up - lo) / 4;        /* range/4 */
            IdxT p  = rnd % (r4 * 2) + (lo + r4);

            lua_assert(lo + r4 <= p && p <= up - r4);
            return(p);
        }
Exemple #2
0
        /*
        ** Does the partition: Pivot P is at the top of the stack.
        ** precondition: a[lo] <= P == a[up-1] <= a[up],
        ** so it only needs to do the partition from lo + 1 to up - 2.
        ** Pos-condition: a[lo .. i - 1] <= a[i] == P <= a[i + 1 .. up]
        ** returns 'i'.
        */
        private static IdxT partition(lua_State L, IdxT lo, IdxT up)
        {
            IdxT i = lo;        /* will be incremented before first use */
            IdxT j = up - 1;    /* will be decremented before first use */

            /* loop invariant: a[lo .. i] <= P <= a[j .. up] */
            for (;;)
            {
                /* next loop: repeat ++i while a[i] < P */
                while (partition_f1(L, ref i))
                {
                    if (i == up - 1)    /* a[i] < P  but a[up - 1] == P  ?? */
                    {
                        luaL_error(L, "invalid order function for sorting");
                    }
                    lua_pop(L, 1);    /* remove a[i] */
                }
                /* after the loop, a[i] >= P and a[lo .. i - 1] < P */
                /* next loop: repeat --j while P < a[j] */
                while (partition_f2(L, ref j))
                {
                    if (j < i)    /* j < i  but  a[j] > P ?? */
                    {
                        luaL_error(L, "invalid order function for sorting");
                    }
                    lua_pop(L, 1);    /* remove a[j] */
                }
                /* after the loop, a[j] <= P and a[j + 1 .. up] >= P */
                if (j < i)        /* no elements out of place? */
                /* a[lo .. i - 1] <= P <= a[j + 1 .. i .. up] */
                {
                    lua_pop(L, 1);    /* pop a[j] */
                    /* swap pivot (a[up - 1]) with a[i] to satisfy pos-condition */
                    set2(L, up - 1, i);
                    return(i);
                }
                /* otherwise, swap a[i] - a[j] to restore invariant and repeat */
                set2(L, i, j);
            }
        }
Exemple #3
0
 /*
 ** QuickSort algorithm (recursive function)
 */
 private static void auxsort(lua_State L, IdxT lo, IdxT up,
                             uint rnd)
 {
     while (lo < up)  /* loop for tail recursion */
     {
         uint p;      /* Pivot index */
         uint n;      /* to be used later */
         /* sort elements 'lo', 'p', and 'up' */
         lua_geti(L, 1, (lua_Integer)lo);
         lua_geti(L, 1, (lua_Integer)up);
         if (0 != sort_comp(L, -1, -2)) /* a[up] < a[lo]? */
         {
             set2(L, lo, up);           /* swap a[lo] - a[up] */
         }
         else
         {
             lua_pop(L, 2);                  /* remove both values */
         }
         if (up - lo == 1)                   /* only 2 elements? */
         {
             return;                         /* already sorted */
         }
         if (up - lo < RANLIMIT || rnd == 0) /* small interval or no randomize? */
         {
             p = (lo + up) / 2;              /* middle element is a good pivot */
         }
         else                                /* for larger intervals, it is worth a random pivot */
         {
             p = choosePivot(lo, up, rnd);
         }
         lua_geti(L, 1, (lua_Integer)p);
         lua_geti(L, 1, (lua_Integer)lo);
         if (0 != sort_comp(L, -2, -1)) /* a[p] < a[lo]? */
         {
             set2(L, p, lo);            /* swap a[p] - a[lo] */
         }
         else
         {
             lua_pop(L, 1);                 /* remove a[lo] */
             lua_geti(L, 1, (lua_Integer)up);
             if (0 != sort_comp(L, -1, -2)) /* a[up] < a[p]? */
             {
                 set2(L, p, up);            /* swap a[up] - a[p] */
             }
             else
             {
                 lua_pop(L, 2);
             }
         }
         if (up - lo == 2)                      /* only 3 elements? */
         {
             return;                            /* already sorted */
         }
         lua_geti(L, 1, (lua_Integer)p);        /* get middle element (Pivot) */
         lua_pushvalue(L, -1);                  /* push Pivot */
         lua_geti(L, 1, (lua_Integer)(up - 1)); /* push a[up - 1] */
         set2(L, p, up - 1);                    /* swap Pivot (a[p]) with a[up - 1] */
         p = partition(L, lo, up);
         /* a[lo .. p - 1] <= a[p] == P <= a[p + 1 .. up] */
         if (p - lo < up - p)            /* lower interval is smaller? */
         {
             auxsort(L, lo, p - 1, rnd); /* call recursively for lower interval */
             n  = p - lo;                /* size of smaller interval */
             lo = p + 1;                 /* tail call for [p + 1 .. up] (upper interval) */
         }
         else
         {
             auxsort(L, p + 1, up, rnd); /* call recursively for upper interval */
             n  = up - p;                /* size of smaller interval */
             up = p - 1;                 /* tail call for [lo .. p - 1]  (lower interval) */
         }
         if ((up - lo) / 128u > n)       /* partition too imbalanced? */
         {
             rnd = l_randomizePivot();   /* try a new randomization */
         }
     }                                   /* tail call auxsort(L, lo, up, rnd) */
 }
Exemple #4
0
 private static void set2(lua_State L, IdxT i, IdxT j)
 {
     lua_seti(L, 1, (lua_Integer)i);
     lua_seti(L, 1, (lua_Integer)j);
 }