*** ./postgresql-8.2.5/src/backend/utils/sort/tuplesort.c	2006-10-04 02:30:04.000000000 +0200
--- ./postgresql-8.2.5-REFINED/src/backend/utils/sort/tuplesort.c	2008-02-02 21:51:50.000000000 +0100
***************
*** 243,258 ****
  	 * heap --- during merge passes, memtuples[] entries beyond tapeRange are
  	 * never in the heap and are used to hold pre-read tuples.)  In state
  	 * SORTEDONTAPE, the array is not used.
! 	 */
! 	SortTuple  *memtuples;		/* array of SortTuple structs */
! 	int			memtupcount;	/* number of tuples currently present */
! 	int			memtupsize;		/* allocated length of memtuples array */
  
  	/*
  	 * While building initial runs, this is the current output run number
  	 * (starting at 0).  Afterwards, it is the number of initial runs we made.
! 	 */
  	int			currentRun;
  
  	/*
  	 * Unless otherwise noted, all pointer variables below are pointers to
--- 243,292 ----
  	 * heap --- during merge passes, memtuples[] entries beyond tapeRange are
  	 * never in the heap and are used to hold pre-read tuples.)  In state
  	 * SORTEDONTAPE, the array is not used.
! 	 */
! 
!     /*
! 	 * The memtuples array contains all of the tuples currently present into
! 	 * memory and it will be arranged into two heaps respectively HeapUP and
! 	 * HeapDOWN. So HeapUP and HeapDOWN will actually point to the root of those
! 	 * two heaps. Consider for example divisionIndex = memtupsize/2 -1, then HeapUP
! 	 * will be initially arranged in indexes [0,divisionIndex] while HeapDOWN in
! 	 * [divisionIndex+1,memtupsize-1]. HeapDOWN is an ordinary heap with initially
! 	 * its root placed at index divisionIndex+1 and its leaves at indexes
! 	 * towards memtupsize-1. On the other hand, HeapUP is a sort of "upside down"
! 	 * heap, that is initially its root lays initially at index divisionIndex
! 	 * and its leaves toward index 0 of the memtuples array.
! 	 */
! 	SortTuple  *memtuples;		/* array of SortTuple structs */
! 	int         HeapUP;	        /* index of HeapUP's root into memtuples */
! 	int         HeapDOWN;       /* index of HeapDOWN's root into memtuples */
! 
! 	int			memtupcount;    /* # of tuples currently present in 'memtuples'*/
! 	int         memtupcountUP;  /* # of tuples currently present in HeapUP*/
! 	int         memtupcountDOWN; /* # of tuples currently present in HeapDOWN*/
! 
! 	bool        HeapUPactive;   //Are we still using HeapUP to build the current logical run?
! 	bool        HeapDOWNactive; //Are we still using HeapDOWN to build the current logical run?
! 
! 	int			memtupsize;		/* allocated length of memtuples array */
! 	int			memtupsizeUP;		/* allocated length of memtuples array */
! 	int			memtupsizeDOWN;		/* allocated length of memtuples array */
  
  	/*
  	 * While building initial runs, this is the current output run number
  	 * (starting at 0).  Afterwards, it is the number of initial runs we made.
! 	 *
! 	 *  ++++++++++++++++++++++++++++++++++++++++++++++++
! 	 *                   MODIFIED
! 
  	int			currentRun;
+ 	 *
+         ++++++++++++++++++++++++++++++++++++++++++++++++
+      */
+ 
+      int currentRun; //left temporary here for 'mergeruns() use'
+      int currentRunUP;
+      int currentRunDOWN;
  
  	/*
  	 * Unless otherwise noted, all pointer variables below are pointers to
***************
*** 403,413 ****
  static void mergeonerun(Tuplesortstate *state);
  static void beginmerge(Tuplesortstate *state);
  static void mergepreread(Tuplesortstate *state);
! static void mergeprereadone(Tuplesortstate *state, int srcTape);
! static void dumptuples(Tuplesortstate *state, bool alltuples);
  static void tuplesort_heap_insert(Tuplesortstate *state, SortTuple *tuple,
! 					  int tupleindex, bool checkIndex);
! static void tuplesort_heap_siftup(Tuplesortstate *state, bool checkIndex);
  static unsigned int getlen(Tuplesortstate *state, int tapenum, bool eofOK);
  static void markrunend(Tuplesortstate *state, int tapenum);
  static int comparetup_heap(const SortTuple *a, const SortTuple *b,
--- 437,464 ----
  static void mergeonerun(Tuplesortstate *state);
  static void beginmerge(Tuplesortstate *state);
  static void mergepreread(Tuplesortstate *state);
! static void mergeprereadone(Tuplesortstate *state, int srcTape);
!     //DUMPTUPLES
! static void dumptuples(Tuplesortstate *state, bool alltuples);
! static void dumptuples_UP(Tuplesortstate *state, bool alltuples);
! static void dumptuples_DOWN(Tuplesortstate *state, bool alltuples);
!     //TUPLESORT_HEAP_INSERT
  static void tuplesort_heap_insert(Tuplesortstate *state, SortTuple *tuple,
! 					  int tupleindex, bool checkIndex);
! static void tuplesort_heap_insert_UP(Tuplesortstate *state, SortTuple *tuple,
!                       int tupleindex, bool checkIndex);
! static void tuplesort_heap_insert_DOWN(Tuplesortstate *state, SortTuple *tuple,
!                       int tupleindex, bool checkIndex);
!     //TUPLESORT_HEAP_SIFTUP
! static void tuplesort_heap_siftup(Tuplesortstate *state, bool checkIndex);
! static void tuplesort_heap_siftup_UP(Tuplesortstate *state, bool checkIndex);
! static void tuplesort_heap_siftup_DOWN(Tuplesortstate *state, bool checkIndex);
!     //RIGHT/LEFT SON FUNCTIONS
! static int leftSonUP(int nodeIndex, int rootIndexUP);
! static int leftSonDOWN(int nodeIndex, int rootIndexUP);
! static int rightSonUP(int nodeIndex, int rootIndexUP);
! static int rightSonDOWN(int nodeIndex, int rootIndexUP);
! 
  static unsigned int getlen(Tuplesortstate *state, int tapenum, bool eofOK);
  static void markrunend(Tuplesortstate *state, int tapenum);
  static int comparetup_heap(const SortTuple *a, const SortTuple *b,
***************
*** 499,505 ****
--- 550,565 ----
  	if (LACKMEM(state))
  		elog(ERROR, "insufficient memory allowed for sort");
  
+     /*  ++++++++++++++++++++++++++++++++++++++++++++++++
+ 	 *                   MODIFIED
+ 	 *
  	state->currentRun = 0;
+ 	 *
+      *  ++++++++++++++++++++++++++++++++++++++++++++++++
+      */
+ 
+ 	state->currentRunUP = 0;
+ 	state->currentRunDOWN = 1;
  
  	/*
  	 * maxTapes, tapeRange, and Algorithm D variables will be initialized by
***************
*** 832,838 ****
   */
  static void
  puttuple_common(Tuplesortstate *state, SortTuple *tuple)
! {
  	switch (state->status)
  	{
  		case TSS_INITIAL:
--- 892,901 ----
   */
  static void
  puttuple_common(Tuplesortstate *state, SortTuple *tuple)
! {
!     bool inHeapUP = false;
!     bool inHeapDOWN = false;
! 
  	switch (state->status)
  	{
  		case TSS_INITIAL:
***************
*** 864,871 ****
  
  			/*
  			 * Dump tuples until we are back under the limit.
! 			 */
! 			dumptuples(state, false);
  			break;
  		case TSS_BUILDRUNS:
  
--- 927,938 ----
  
  			/*
  			 * Dump tuples until we are back under the limit.
! 			MODIFICATO: IT WILL BE REMOVED THE ROOT OF THE HEAP THAT WILL HOST
! 			THE NEW INPUT TUPLE.
! 
! 			dumptuples(state, false);
! 			*/
! 
  			break;
  		case TSS_BUILDRUNS:
  
***************
*** 882,898 ****
  			 * Note there will always be at least one tuple in the heap at
  			 * this point; see dumptuples.
  			 */
! 			Assert(state->memtupcount > 0);
  			if (COMPARETUP(state, tuple, &state->memtuples[0]) >= 0)
  				tuplesort_heap_insert(state, tuple, state->currentRun, true);
  			else
  				tuplesort_heap_insert(state, tuple, state->currentRun + 1, true);
  
! 			/*
! 			 * If we are over the memory limit, dump tuples till we're under.
! 			 */
! 			dumptuples(state, false);
! 			break;
  		default:
  			elog(ERROR, "invalid tuplesort state");
  			break;
--- 949,1009 ----
  			 * Note there will always be at least one tuple in the heap at
  			 * this point; see dumptuples.
  			 */
! 	/*  ++++++++++++++++++++++++++++++++++++++++++++++++
! 	 *                   MODIFIED
! 	 *
!             Assert(state->memtupcount > 0);
  			if (COMPARETUP(state, tuple, &state->memtuples[0]) >= 0)
  				tuplesort_heap_insert(state, tuple, state->currentRun, true);
  			else
  				tuplesort_heap_insert(state, tuple, state->currentRun + 1, true);
  
!              If we are over the memory limit, dump tuples till we're under.
! 
!             dumptuples(state, false);
! 	 *
!      *  ++++++++++++++++++++++++++++++++++++++++++++++++
!      */
!             Assert(state->memtupcount > 0);
! 
! 
!             if(state->HeapUPactive && COMPARETUP(state, tuple, &state->memtuples[state->HeapUP]) <= 0)
! 			{
! 			    dumptuples_UP(state, false);
! 				tuplesort_heap_insert_UP(state, tuple, state->currentRunUP, true);
! 				inHeapUP = true;
! 				break;
! 			}
! 
! 			if (state->HeapDOWNactive && COMPARETUP(state, tuple, &state->memtuples[state->HeapDOWN]) >= 0)
! 			{
! 			    dumptuples_DOWN(state, false);
! 				tuplesort_heap_insert_DOWN(state, tuple, state->currentRunDOWN, true);
!                 inHeapDOWN = true;
!                 break;
! 			}
! 
! 			/* IF WE GET TO THIS POINT IT MEANS THE INPUT TUPLE WON'T FORM PART OF THE CURRENT RUN */
!             // At the moment we just place it into HeapUP at first. Waiting for a more efficient
!             // to manage that kind of element.
! 
! 			if(state->HeapUPactive)
! 			{
! 			    dumptuples_UP(state, false);
! 				tuplesort_heap_insert_UP(state, tuple, state->currentRunUP+2, true);
! 				inHeapUP = true;
! 				break;
! 			}
! 
! 			if(state->HeapDOWNactive)
! 			{
! 			    dumptuples_DOWN(state, false);
! 				tuplesort_heap_insert_DOWN(state, tuple, state->currentRunDOWN+2, true);
! 				inHeapUP = true;
! 				break;
! 			}
! 
! 
  		default:
  			elog(ERROR, "invalid tuplesort state");
  			break;
***************
*** 1290,1296 ****
  inittapes(Tuplesortstate *state)
  {
  	int			maxTapes,
- 				ntuples,
  				j;
  	long		tapeSpace;
  
--- 1401,1406 ----
***************
*** 1342,1366 ****
  	state->tp_tapenum = (int *) palloc0(maxTapes * sizeof(int));
  
  	/*
! 	 * Convert the unsorted contents of memtuples[] into a heap. Each tuple is
  	 * marked as belonging to run number zero.
  	 *
  	 * NOTE: we pass false for checkIndex since there's no point in comparing
  	 * indexes in this step, even though we do intend the indexes to be part
  	 * of the sort key...
! 	 */
  	ntuples = state->memtupcount;
! 	state->memtupcount = 0;		/* make the heap empty */
  	for (j = 0; j < ntuples; j++)
  	{
! 		/* Must copy source tuple to avoid possible overwrite */
  		SortTuple	stup = state->memtuples[j];
  
  		tuplesort_heap_insert(state, &stup, 0, false);
  	}
  	Assert(state->memtupcount == ntuples);
  
- 	state->currentRun = 0;
  
  	/*
  	 * Initialize variables of Algorithm D (step D1).
--- 1452,1504 ----
  	state->tp_tapenum = (int *) palloc0(maxTapes * sizeof(int));
  
  	/*
! 	 * OLD: Convert the unsorted contents of memtuples[] into a heap. Each tuple is
  	 * marked as belonging to run number zero.
  	 *
  	 * NOTE: we pass false for checkIndex since there's no point in comparing
  	 * indexes in this step, even though we do intend the indexes to be part
  	 * of the sort key...
! 	 */
! 
! 	 /*         MODIFICATO
  	ntuples = state->memtupcount;
! 	state->memtupcount = 0;		// make the heap empty
  	for (j = 0; j < ntuples; j++)
  	{
! 		// Must copy source tuple to avoid possible overwrite
  		SortTuple	stup = state->memtuples[j];
  
  		tuplesort_heap_insert(state, &stup, 0, false);
  	}
  	Assert(state->memtupcount == ntuples);
+     */
+ 
+ 	// NEW: qsort the unsorted array
+ 	if (state->memtupcount > 1)
+         qsort_arg((void *) state->memtuples, state->memtupcount,
+                            sizeof(SortTuple),
+                            (qsort_arg_comparator) state->comparetup,
+                            (void *) state);
+ 
+ 
+     // dividing logically 'memtuples' into two heaps
+     state->memtupcountUP = state->memtupcount >> 1;
+     state->HeapUP = state->memtupcountUP - 1;
+     state->HeapDOWN = state->memtupcountUP;
+     state->memtupcountDOWN = state->memtupcount - state->memtupcountUP;
+     state->HeapUPactive = true;
+     state->HeapDOWNactive = true;
+ 
+     //initializing run number for each element into HeapUP
+     state->currentRunUP = 0;
+     for(j=0; j<state->memtupcountUP; j++)
+         state->memtuples[j].tupindex = state->currentRunUP;
+ 
+     //initializing run number for each element into HeapDOWN
+     state->currentRunDOWN = 1;
+     for(j=0; j<state->memtupcountDOWN; j++)
+         state->memtuples[state->memtupcountUP + j].tupindex = state->currentRunDOWN;
  
  
  	/*
  	 * Initialize variables of Algorithm D (step D1).
***************
*** 1396,1407 ****
  	/* Step D3: advance j (destTape) */
  	if (state->tp_dummy[state->destTape] < state->tp_dummy[state->destTape + 1])
  	{
! 		state->destTape++;
! 		return;
  	}
  	if (state->tp_dummy[state->destTape] != 0)
  	{
! 		state->destTape = 0;
  		return;
  	}
  
--- 1534,1561 ----
  	/* Step D3: advance j (destTape) */
  	if (state->tp_dummy[state->destTape] < state->tp_dummy[state->destTape + 1])
  	{
! 		state->destTape++;
! 
! 		if(state->destTape+2 < state->tapeRange)
! 		{
! 		    state->destTapeUP = destTape + 1;
! 		    state->destTapeUP = destTape + 2;
! 		    return;
!         }
!         if(state->destTape-2 > 0)
!         {
!             state->destTapeUP = destTape - 1;
! 		    state->destTapeUP = destTape - 2;
! 		    return;
!         }
! 
! 		elog(ERROR, "NOT ENOUGH TAPES?");
  	}
  	if (state->tp_dummy[state->destTape] != 0)
  	{
! 		state->destTape = 0;
! 		state->destTapeUP = 1;
! 		state->destTapeUP = 2;
  		return;
  	}
  
***************
*** 1413,1419 ****
  		state->tp_dummy[j] = a + state->tp_fib[j + 1] - state->tp_fib[j];
  		state->tp_fib[j] = a + state->tp_fib[j + 1];
  	}
! 	state->destTape = 0;
  }
  
  /*
--- 1567,1575 ----
  		state->tp_dummy[j] = a + state->tp_fib[j + 1] - state->tp_fib[j];
  		state->tp_fib[j] = a + state->tp_fib[j + 1];
  	}
! 	state->destTape = 0;
! 	state->destTapeUP = 1;
! 	state->destTapeUP = 2;
  }
  
  /*
***************
*** 1863,1868 ****
--- 2019,2165 ----
  		}
  	}
  }
+ 
+ 
+ static void
+ dumptuples_UP(Tuplesortstate *state, bool alltuples)
+ {
+     int rootIndexUP = state->HeapUP;
+     bool randomAccess;
+ 
+     /* Storing the original value of randomAccess */
+ 	randomAccess = state->radomAccess;
+ 	/* That allows backward reading tuples */
+ 	state->radomAccess = true;
+ 
+ 	while (alltuples ||
+ 		   (LACKMEM(state) && state->memtupcountUP > 1) ||
+ 		   state->memtupcountUP >= state->memtupsizeUP)
+ 	{
+ 		/*
+ 		 * Dump the heap's frontmost entry, and sift up to remove it from the
+ 		 * heap.
+ 		 */
+ 		Assert(state->memtupcountUP > 0);
+ 		WRITETUP(state, state->tp_tapenum[state->destTape],
+ 				 &state->memtuples[rootIndexUP]);
+ 		tuplesort_heap_siftup_UP(state, true);
+ 
+ 		/*
+ 		 * If the heap is empty *or* top run number has changed, we've
+ 		 * finished the current run.
+ 		 */
+ 		if (state->memtupcountUP == 0 ||
+ 			state->currentRunUP != state->memtuples[rootIndexUP].tupindex)
+ 		{
+ 			markrunend(state, state->tp_tapenum[state->destTapeUP]);
+ 
+ 			state->currentRunUP += 2;
+ 			state->HeapUPactive = false;
+ 
+ #ifdef TRACE_SORT
+ 			if (trace_sort)
+ 				elog(LOG, "finished writing%s run UP %d to tape %d: %s",
+ 					 (state->memtupcountUP == 0) ? " final" : "",
+ 					 state->currentRunUP, state->destTape,
+ 					 pg_rusage_show(&state->ru_start));
+ #endif
+ 
+ 			/*
+ 			 * Done if heap is empty, else prepare for new LOGICAL run,
+ 			 * in case PHYSICAL run DOWN too is over.
+ 			 */
+ 			if (state->memtupcountUP == 0)
+ 				break;
+             if (!state->HeapDOWNactive)
+             {
+                 formLogicalRun(state);
+ 
+                 state->tp_runs[state->destTape]++;
+                 state->tp_dummy[state->destTape]--; /* per Alg D step D2 */
+                 state->HeapDOWNactive = true;
+                 state->HeapUPactive = true;
+ 
+                 Assert(state->currentRunUP == state->memtuples[rootIndexUP].tupindex);
+                 selectnewtape(state);
+             }
+ 		}
+ 	}
+ 
+     /* Restoring the original value of randomAccess */
+ 	state->radomAccess = randomAccess;
+ }
+ 
+ 
+ 
+ 
+ static void
+ dumptuples_DOWN(Tuplesortstate *state, bool alltuples)
+ {
+     int rootIndexDOWN = state->HeapDOWN;
+ 
+ 	while (alltuples ||
+ 		   (LACKMEM(state) && state->memtupcountDOWN > 1) ||
+ 		   state->memtupcountDOWN >= state->memtupsizeDOWN)
+ 	{
+ 		/*
+ 		 * Dump the heap's frontmost entry, and sift up to remove it from the
+ 		 * heap.
+ 		 */
+ 		Assert(state->memtupcountDOWN > 0);
+ 		WRITETUP(state, state->tp_tapenum[state->destTape],
+ 				 &state->memtuples[rootIndexDOWN]);
+ 		tuplesort_heap_siftup_DOWN(state, true);
+ 
+ 		/*
+ 		 * If the heap is empty *or* top run number has changed, we've
+ 		 * finished the current run.
+ 		 */
+ 
+ 		 //IMPORTANT!!! SEE CORRESPONDENCE RUN<-->TAPE
+ 
+ 		if (state->memtupcountDOWN == 0 ||
+ 			state->currentRunDOWN != state->memtuples[rootIndexDOWN].tupindex)
+ 		{
+ 		    state->HeapDOWNactive = false;
+ 
+ 		    if(!state->HeapUPactive)
+             {
+                 state->HeapUPactive = true;
+                 state->HeapDOWNactive = true;
+ 
+                 markrunend(state, state->tp_tapenum[state->destTape]);
+ 
+                 state->currentRunDOWN += 2;
+                 state->currentRunUP += 2;
+ 
+                 state->tp_runs[state->destTape]++;
+                 state->tp_dummy[state->destTape]--; /* per Alg D step D2 */
+ 
+ #ifdef TRACE_SORT
+                 if (trace_sort)
+                     elog(LOG, "finished writing%s run %d to tape %d: %s",
+                         (state->memtupcountDOWN == 0) ? " final" : "",
+                         state->currentRunDOWN, state->destTape,
+                         pg_rusage_show(&state->ru_start));
+ #endif
+             }
+ 
+             /*
+              * Done if heap is empty, else prepare for new run.
+              */
+ 
+              //INSIDE OR PUTSIDE OF THE PRECEDING 'IF'?!?!
+              if (state->memtupcountDOWN == 0)
+                     break;
+              Assert(state->currentRunDOWN == state->memtuples[rootIndexDOWN].tupindex);
+              selectnewtape(state);
+ 		}
+ 	}
+ }
+ 
+ 
+ 
  
  /*
   * tuplesort_rescan		- rewind and replay the scan
***************
*** 2021,2026 ****
--- 2318,2399 ----
  	memtuples[j] = *tuple;
  }
  
+ 
+ 
+ 
+ static void
+ tuplesort_heap_insert_DOWN(Tuplesortstate *state, SortTuple *tuple, int tupleindex, bool checkIndex)
+ {
+ 	SortTuple  *memtuples;
+ 	int			j;
+ 
+ 	/*
+ 	 * Save the tupleindex --- see notes above about writing on *tuple. It's a
+ 	 * historical artifact that tupleindex is passed as a separate argument
+ 	 * and not in *tuple, but it's notationally convenient so let's leave it
+ 	 * that way.
+ 	 */
+ 	tuple->tupindex = tupleindex;
+ 
+ 	memtuples = state->memtuples;
+ 	Assert(state->memtupcountDOWN < state->memtupsizeDOWN);
+ 
+ 	/*
+ 	 * Sift-up the new entry, per Knuth 5.2.3 exercise 16. Note that Knuth is
+ 	 * using 1-based array indexes, not 0-based.
+ 	 */
+ 	j = state->HeapDOWN + state->memtupcountDOWN++;
+ 	while (j > state->HeapDOWN)
+ 	{
+ 		int	i = (j - 1) >> 1;
+ 
+ 		if (HEAPCOMPARE(tuple, &memtuples[i]) >= 0)
+ 			break;
+ 		memtuples[j] = memtuples[i];
+ 		j = i;
+ 	}
+ 	memtuples[j] = *tuple;
+ }
+ 
+ 
+ static void
+ tuplesort_heap_insert_UP(Tuplesortstate *state, SortTuple *tuple, int tupleindex, bool checkIndex)
+ {
+ 	SortTuple  *memtuples;
+ 	int		j,
+             HeapUP;
+ 
+ 	/*
+ 	 * Save the tupleindex --- see notes above about writing on *tuple. It's a
+ 	 * historical artifact that tupleindex is passed as a separate argument
+ 	 * and not in *tuple, but it's notationally convenient so let's leave it
+ 	 * that way.
+ 	 */
+ 	tuple->tupindex = tupleindex;
+ 
+ 	memtuples = state->memtuples;
+ 	Assert(state->memtupcountUP < state->memtupsizeUP);
+ 
+ 	/*
+ 	 * Sift-up the new entry, per Knuth 5.2.3 exercise 16. Note that Knuth is
+ 	 * using 1-based array indexes, not 0-based.
+ 	 */
+ 	HeapUP = state->HeapUP;
+ 	j = HeapUP - state->memtupcountUP++;
+ 	while (j < HeapUP)
+ 	{
+ 		int	i = (j - 1) >> 1;
+ 
+ 		if (HEAPCOMPARE(tuple, &memtuples[i]) >= 0)
+ 			break;
+ 		memtuples[j] = memtuples[i];
+ 		j = i;
+ 	}
+ 	memtuples[j] = *tuple;
+ }
+ 
+ 
+ 
  /*
   * The tuple at state->memtuples[0] has been removed from the heap.
   * Decrement memtupcount, and sift up to maintain the heap invariant.
***************
*** 2054,2060 ****
  	}
  	memtuples[i] = *tuple;
  }
! 
  
  /*
   * Tape interface routines
--- 2427,2576 ----
  	}
  	memtuples[i] = *tuple;
  }
! 
! 
! 
! static int leftSonUP(int nodeIndex, int rootIndexUP)
! {    return (nodeIndex * 2 - 1 - rootIndexUP); }
! 
! static int rightSonUP(int nodeIndex, int rootIndexUP)
! {    return (nodeIndex * 2 - 2 - rootIndexUP); }
! 
! static int leftSonDOWN(int nodeIndex, int rootIndexDOWN)
! {    return (nodeIndex * 2 + 2 - rootIndexDOWN); }
! 
! static int rightSonDOWN(int nodeIndex, int rootIndexDOWN)
! {    return (nodeIndex * 2 + 1 - rootIndexDOWN); }
! 
! 
! static void
! tuplesort_heap_siftup_UP(Tuplesortstate *state, bool checkIndex)
! {
! 	SortTuple  *memtuples = state->memtuples;
! 	SortTuple  *tuple;
! 	int			i,
!                 n, //index of the last leaf of HeapUP
!                 memtupcount,
!                 memtupcountUP, memtupsizeUP, HeapUP;
!     bool        runningAfter;
! 
!     memtupcount = --state->memtupcount;
!     memtupcountUP = --state->memtupcountUP;
! 	if (memtupcountUP <= 0)
! 		return;
! 	memtupsizeUP = state->memtupsizeUP;
! 	HeapUP = state->HeapUP;
! 
! 	if(memtupsizeUP >= memtupcountUP)
! 	{   //index of the last element of the heap
! 	    n = HeapUP - memtupcountUP + 1;
! 	    tuple = &memtuples[n];		/* tuple that must be reinserted */
! 	    runningAfter = false;
!     }
!     else
!     {
!         n = memtupcount - (memtupcountUP - memtupsizeUP) -1 ;
! 	    runningAfter = true;
! 	    tuple = &memtuples[n];		/* tuple that must be reinserted */
!     }
! 
! 
! 	i = HeapUP;			/* i is where the "hole" is */
! 	for (;;)
! 	{
! 		int		j = leftSonUP(HeapUP, i);
! 
!         if ( !runningAfter && j > n )
! 		{
! 		    if (j - 1 < n &&
!                     HEAPCOMPARE(&memtuples[j], &memtuples[j - 1]) < 0 )
!                 j--;
!             if (HEAPCOMPARE(tuple, &memtuples[j]) >= 0)
!                 break;
!             memtuples[i] = memtuples[j];
!             i = j;
! 		    continue;
!         }
!         /*HEAPS RUNNING AFTER THEM EACH OTHER
!         if (runningAfter && )
! 		if (j + 1 < n &&
! 			HEAPCOMPARE(&memtuples[j], &memtuples[j + 1]) > 0)
! 			j++;
! 		if (HEAPCOMPARE(tuple, &memtuples[j]) <= 0)
! 			break;
! 		memtuples[i] = memtuples[j];
! 		i = j;
! 		*/
! 	}
! 	memtuples[i] = *tuple;
! }
! 
! 
! 
! 
! static void
! tuplesort_heap_siftup_DOWN(Tuplesortstate *state, bool checkIndex)
! {
! 	SortTuple  *memtuples = state->memtuples;
! 	SortTuple  *tuple;
! 	int			i,
!                 n, //index of the last leaf of HeapUP
!                 HeapDOWN,
!                 memtupcountDOWN, memtupsizeDOWN, memtupcount;
!     bool        runningAfter;
! 
!     memtupcount = --state->memtupcount;
!     memtupcountDOWN = --state->memtupcountDOWN;
! 	if (memtupcountDOWN <= 0)
! 		return;
! 	memtupsizeDOWN = state->memtupsizeDOWN;
! 	HeapDOWN = state->HeapDOWN;
! 
! 	if(memtupsizeDOWN >= memtupcountDOWN)
! 	{
! 	    n = HeapDOWN + memtupcountDOWN - 1;
! 	    tuple = &memtuples[n];		/* tuple that must be reinserted */
! 	    runningAfter = false;
!     }
!     else
!     {
!         n = memtupcountDOWN - (memtupsizeDOWN - 1) ;
! 	    runningAfter = true;
! 	    tuple = &memtuples[n];		/* tuple that must be reinserted */
!     }
! 
! 
! 	i = HeapDOWN;			/* i is where the "hole" is */
! 	for (;;)
! 	{
! 		int		j = rightSonDOWN(HeapDOWN,i);
! 
!         if ( !runningAfter && j < n )
! 		{
! 		    if (j + 1 < n &&
!                     HEAPCOMPARE(&memtuples[j], &memtuples[j + 1]) > 0 )
!                 j++;
!             if (HEAPCOMPARE(tuple, &memtuples[j]) <= 0)
!                 break;
!             memtuples[i] = memtuples[j];
!             i = j;
! 		    continue;
!         }
! 
!         /*HEAPS RUNNING AFTER THEM EACH OTHER
!         if (runningAfter && )
! 		if (j + 1 < n &&
! 			HEAPCOMPARE(&memtuples[j], &memtuples[j + 1]) > 0)
! 			j++;
! 		if (HEAPCOMPARE(tuple, &memtuples[j]) <= 0)
! 			break;
! 		memtuples[i] = memtuples[j];
! 		i = j;
! 		*/
! 	}
! 	memtuples[i] = *tuple;
! }
! 
  
  /*
   * Tape interface routines
