/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/* 
 * tuplesort_mkheap.c
 * 		Multi level key quick sort.
 *
 * A multi level key Bentley McIlroy 3-way partitioning quick sort.
 * 	See [1] J. Bentley, M. McIlroy.  Engineering a sort function, 
 * 		Software Practice and Experience, Vol 23(11) Nov, 1993.
 * 	    [2] R. Sedgewick, J. Bentley. Quicksort is optimal.
 */

#include "postgres.h"
#include "utils/tuplesort.h"
#include "utils/tuplesort_mk.h"

#include "miscadmin.h"

#ifdef MKQSORT_VERIFY 
extern void mkqsort_verify(MKEntry *a, int l, int r, MKContext *mkctxt);
#endif

/**
 * Given an array, swap the entries at a[i] and a[j]
 */
static inline void mkqs_swap(MKEntry *a, int i, int j)
{
	if(i!=j)
	{
		MKEntry tmp = a[i];
		a[i] = a[j];
		a[j] = tmp;
	}
}

/**
 * Compare the two entries, only does comparison using compFlags and the level in the context
 */
static inline int32 mkqs_comp(MKEntry *a, MKEntry *b, MKLvContext *ctxt, MKContext *mkctxt)
{
	int ret = a->compflags - b->compflags;

	if (ret == 0 && !mke_is_null(a))
		ret = tupsort_compare_datum(a, b, ctxt, mkctxt);

	return ret;
}

/**
 *  Return the median of three multi-key entries
 */
static inline MKEntry *mkqs_med3(MKEntry *a, MKEntry *b, MKEntry *c, MKLvContext *ctxt, MKContext *mkctxt)
{
	return mkqs_comp(a, b, ctxt, mkctxt) < 0 ?
                        (mkqs_comp(b, c, ctxt, mkctxt) < 0 ? b : mkqs_comp(a, c, ctxt, mkctxt) < 0 ? c : a )
                        :
                        (mkqs_comp(b, c, ctxt, mkctxt) > 0 ? b : mkqs_comp(a, c, ctxt, mkctxt) > 0 ? c : a )
                        ;
}

/**
 * Choose a pivot from the array of elements (a) from between left (inclusive) and right (inclusive).
 *
 * lv/comp/ctxt combine to allow comparison.  Note that, as usual with the multi-key structure, comparison is only done
 *   up to a certain level.
 */
static inline MKEntry *mkqs_choose_pivot(MKEntry *a, int left, int right, int lv, MKLvContext *ctxt, MKContext *mkctxt)
{
	int s;
	int n = right - left + 1;
	MKEntry *pl, *pm, *pn;

	Assert(n >= 0);
	
	pm = a + (left + n/2);

	if(n > 7)
	{
		pl = a+left;
		pn = a+right;

		if(n > 40)
		{
			s = n/8;
			pl = mkqs_med3(pl, pl+s, pl+s*2, ctxt, mkctxt);
			pm = mkqs_med3(pm-s, pm, pm+s, ctxt, mkctxt);
			pn = mkqs_med3(pn-s*2, pn-s, pn, ctxt, mkctxt);
		}

		pm = mkqs_med3(pl, pm, pn, ctxt, mkctxt);
	}

	return pm;
}

/*
 * Three way partition quick sort.
 *
 * left and right are both INCLUSIVE
 */
static void mk_qsort_part3(MKEntry *a, int left, int right, int lv, MKContext *mkqs_ctxt, int *lastInLowOut, int *firstInHighOut)
{
	/* p, q points to the last equals we put to both end */
	int p = left-1;
	int q = right+1;

	int leftIndex,rightIndex;

	int k;
    MKLvContext *lvctxt = mkqs_ctxt->lvctxt + lv;

	MKEntry v = {0, };
	MKEntry *pv;

	Assert(left < right);

	/*
	 * leftIndex points to the known <= upper,
	 * rightIndex points to the known >= lower.
	 * 
	 * Initially, we know nothing, so point them to out of bounds.
	 */
	leftIndex = left-1;
	rightIndex = right+1;

	/* Choose a pivot */
	pv = mkqs_choose_pivot(a, left, right, lv, lvctxt, mkqs_ctxt);

	/* Save pivot in v */ 
	/* Hacking a ref count */
	if(mke_is_refc(pv))
		mkqs_ctxt->cpfr(&v, pv, lvctxt);
	else 
		v = *pv;

	while(1)
	{
		int tmpLeftIndex, cmp;

		cmp = -1;
		while(1)
		{
			/* increase leftIndex until a[leftIndex] >= pivot */
			while(++leftIndex < rightIndex &&
				 (cmp = mkqs_comp(a+leftIndex, &v, lvctxt, mkqs_ctxt)) < 0)
			{
				Assert(leftIndex >= left && leftIndex<= right);
				Assert(rightIndex >= left && rightIndex<= right+1);
				Assert(leftIndex <= rightIndex);
			}

			/* now i refers to the first value that is >= the pivot */
			if(leftIndex == rightIndex || cmp > 0)
				break;

			/* since leftIndex equals the pivot, put the equals one at the beginning and move one there to take its place. */
			mkqs_swap(a, ++p, leftIndex);
		}

		if(leftIndex == rightIndex)
		{ 
			/**
			 * Caught up, back down and done loop
			 */
			--leftIndex;
			break; 
		}

		/**
		 *  now, p points to the last value of a run of values equal to the pivot
		 *  leftIndex points one beyond a run of values <= the pivot (and between p+1 and leftIndex they are < the pivot)
		 */

		/* tmpLeftIndex points at the last of those <= pivot */
		tmpLeftIndex = leftIndex-1;

		/* same case as above, but from the upper end and transferring equal values to the q end */
		cmp = 1;
		while(1)
		{
			while(--rightIndex > tmpLeftIndex &&
					(cmp = mkqs_comp(&v, a+rightIndex, lvctxt, mkqs_ctxt)) < 0)
			{
				Assert(tmpLeftIndex >= left-1 && tmpLeftIndex <= right);
				Assert(rightIndex >= left && rightIndex<= right);
				Assert(tmpLeftIndex <= rightIndex);
			}

			if(tmpLeftIndex == rightIndex || cmp > 0)
				break;

			mkqs_swap(a, rightIndex, --q);
		}

		if(tmpLeftIndex == rightIndex)
		{
			--leftIndex; /* make leftIndex = tmpLeftIndex */
			++rightIndex; /* move rightIndex up to avoid overlap */
			break;
		}

		/* at this point, a[leftIndex] > pivot and a[rightIndex] < pivot, so swap them */
		/* note: there is an extra compare between leftIndex and pivot, and rightIndex and pivot because
		 * we don't alter leftIndex and rightIndex here.  But doing so may complicate other code */
		Assert(leftIndex < rightIndex);
		mkqs_swap(a, leftIndex, rightIndex);

		if(leftIndex+1 == rightIndex)
			break;
	}

	/* Now leftIndex points to where the run of values <= the pivot ends
     * And rightIndex points to where the run of values >= the pivot begins
     */
	Assert(leftIndex+1 == rightIndex);
	Assert(rightIndex>=left && leftIndex<=right);

	/**
	 * Push all the equal values at the beginning to the middle (at i)
	 */
	for(k=left; k<=p; ++k, --leftIndex)
	{
		Assert(k>=left && k<=right);
		Assert(leftIndex>=left && leftIndex<=right);
		mkqs_swap(a, k, leftIndex);
	}

	/**
	 * Push all the equal values at the end to the middle (at j)
	 */
	for(k=right; k>=q; --k, ++rightIndex)
	{
		Assert(k>=left && k<=right);
		Assert(rightIndex>=left && rightIndex<=right);
		mkqs_swap(a, rightIndex, k);
	}

	/*
	 * Now leftIndex points to the last value of the run of values < the pivot
	 * And rightIndex points to the last value of the run of values > the pivot
	 */
	Assert(leftIndex >= left-1 && leftIndex < right);
	Assert(rightIndex > left && rightIndex <= right+1);
	Assert(rightIndex >= leftIndex+2);

	/* Hack ref count */
	if(mke_is_refc(&v))
		mkqs_ctxt->cpfr(&v, NULL, lvctxt);

	*lastInLowOut = leftIndex;
	*firstInHighOut = rightIndex;
}

void mk_qsort_impl(MKEntry *a, int left, int right, int lv, bool lvdown, MKContext *ctxt, bool seenNull)
{
	int lastInLow;
	int firstInHigh;

	Assert(ctxt);
	Assert(lv < ctxt->total_lv);

    CHECK_FOR_INTERRUPTS();

	if(right <= left)
		return;
	
	/* Prepare at level lv */
	if(lvdown)
        mk_prepare_array(a, left, right, lv, ctxt);

	/* 
	 * According to Bentley & McIlroy [1] (1993), using insert sort for case 
	 * n < 7 is a significant saving.  However, according to Sedgewick & 
	 * Bentley [2] (2002), the wisdom of new millenium is not to special case
	 * smaller cases.  Here, we do not special case it because we want to save
	 * memtuple_getattr, and expensive comparisons that has been prepared.
	 *
	 * XXX Find out why we have a new wisdom in [2] and impl. & compare.
	 */
	mk_qsort_part3(a, left, right, lv, ctxt, &lastInLow, &firstInHigh);

	/* recurse to left chunk */
	mk_qsort_impl(a, left, lastInLow, lv, false, ctxt, seenNull);

	/* recurse to middle (equal) chunk */
	if(lv < ctxt->total_lv-1)
	{
		/*
		 * [lastInLow+1,firstInHigh-1] defines the pivot region which was all equal at level lv.  So increase the level and compare that region!
		 */
		mk_qsort_impl(a, lastInLow+1, firstInHigh-1, lv+1, true, ctxt, seenNull || mke_is_null(a+lastInLow+1)); /* a + lastInLow + 1 points to the pivot */
	}
	else
	{
		/* values are all equal to the deepest level...no need for more compares, but check uniqueness if requested */
		if(firstInHigh-1 > lastInLow+1 &&
				!seenNull &&
				!mke_is_null(a+lastInLow+1)) /* a + lastInLow + 1 points to the pivot */
		{
			if ( ctxt->enforceUnique )
			{
			    ERROR_UNIQUENESS_VIOLATED();
			}
			else if ( ctxt->unique)
			{
				int toFreeIndex;
				for ( toFreeIndex = lastInLow + 2; toFreeIndex < firstInHigh; toFreeIndex++) /* +2 because we want to keep one around! */
				{
					MKEntry *toFree = a + toFreeIndex;
					if ( ctxt->cpfr)
						ctxt->cpfr(toFree, NULL, ctxt->lvctxt + lv); // todo: verify off-by-one
					ctxt->freeTup(toFree);
					mke_set_empty(toFree);
				}
			}
		}
	}

	/* recurse to right chunk */
	mk_qsort_impl(a, firstInHigh, right, lv, false, ctxt, seenNull);

#ifdef MKQSORT_VERIFY 
	if(lv == 0)
		mkqsort_verify(a, left, right, ctxt);
#endif
}

#ifdef MKQSORT_VERIFY 
static int mkqsort_comp_entry_all_lv(MKEntry *a, MKEntry *b, MKContext *mkctxt)
{
	int i;
	int c;

	MKEntry aa = {0, }; 
	MKEntry bb = {0, }; 

	(*mkctxt->cpfr)(&aa, a, mk_get_ctxt(mkctxt, mke_get_lv(a)));
	(*mkctxt->cpfr)(&bb, b, mk_get_ctxt(mkctxt, mke_get_lv(b)));

	for(i=0; i<mkctxt->total_lv; ++i)
	{
		MKPrepare prep = mkctxt->prep[i];

		void *ctxt = mk_get_ctxt(mkctxt, i);
        int32 nf1, nf2;

		if(prep)
		{
			(prep)(&aa, ctxt);
			(prep)(&bb, ctxt);
		}

        nf1 = mke_get_nullbits(&aa);
        nf2 = mke_get_nullbits(&bb);

        c = nf1 - nf2;
        if (c!=0)
            return c;

        if (!mke_is_null(&aa))
        {
            Assert(!mke_is_null(&bb));
            c = (comp)(&aa, &bb, ctxt);

            if (c!=0)
                return c;
        }
	}

	return 0;
}

void mkqsort_verify(MKEntry *a, int i, int j, MKContext *mkctxt)
{
	int c;
	for(; i<j; ++i)
	{
		c = mkqsort_comp_entry_all_lv(a+i, a+i+1, mkctxt);
		Assert(c <= 0);
	}
}
#endif
