コード例 #1
0
ファイル: FourSort.c プロジェクト: andrewhsu/foursort
// calculate the median of 3
int med(void **A, int a, int b, int c,
	int (*compareXY ) (const void *, const void * ) ) {
  return
    compareXY( A[a], A[b] ) < 0 ?
    ( compareXY( A[b], A[c] ) < 0 ? b : compareXY( A[a], A[c] ) < 0 ? c : a)
    : compareXY( A[b], A[c] ) > 0 ? b : compareXY( A[a], A[c] ) > 0 ? c : a;
} // end med
コード例 #2
0
ファイル: FourSort.c プロジェクト: andrewhsu/foursort
void siftDown(void **a, int start, int end) {
  // input:  end represents the limit of how far down the heap to sift.
  int root = start;
  int child, swapi;
  // (While the root has at least one child)
  while ( root * 2 + 1 <= end ) {
    child = root * 2 + 1; // (root*2 + 1 points to the left child)
    swapi = root; // (keeps track of child to swap with)
    // (check if root is smaller than left child)
    // if ( a[swapi] < a[child] ) 
    if ( compareXY(a[swapi], a[child]) < 0 ) 
      swapi = child;
    // (check if right child exists, and if it's bigger 
    // than what we're currently swapping with)
    // if ( child+1 <= end && a[swapi] < a[child+1] )
    if ( child+1 <= end && compareXY(a[swapi],a[child+1]) < 0 )
      swapi = child + 1;
    // (check if we need to swap at all)
    if ( swapi != root ) {
      // swap(a[root], a[swapi]);
      iswap(root, swapi, a);
      root = swapi; // (repeat to continue sifting down the child now)
    } else return;
  }
} // end siftDown
コード例 #3
0
infoActionType clapChezNousJaune(int option) {
    static infoActionType infoAction = {ACTION_PAS_COMMENCEE,   // statut de l'action
                                        0,                      // Etape actuelle
                                        4,                      // Nombre d'étapes
                                        ACTION_ACTIONNEURS,     // Type de l'étape
                                        {0, 0, 0}};             // Destination de l'étape (si pertinent)
    actionStatutType trajStatut;
    enum {
        GOTO_CLAP1_START = 0,
        DEPLOIEMENT_BRAS = 1,
        GOTO_CLAP2_END = 2,
        REPLIEMENT_BRAS = 3,
        GOTO_CLAP2_START = 4,
        GOTO_CLAP1_END = 5,
        FINI = 255
    } etape = GOTO_CLAP1_START;

    infoAction.statut = ACTION_PAS_COMMENCEE;
    switch (option) {
        case RESET_ACTION:
            rentrerServoClap();
            etape = FINI;
            infoAction.statut = ACTION_FINIE;
            break;
        case DEFAULT_ACTION:
            etape = GOTO_CLAP1_START;
            infoAction.statut = ACTION_EN_COURS;
            break;
        case CLAP1_ONLY:
            etape = GOTO_CLAP1_START;
            infoAction.statut = ACTION_EN_COURS;
            break;
        case CLAP2_ONLY:
            etape = GOTO_CLAP2_START;
            infoAction.statut = ACTION_EN_COURS;
            break;
        default:
            break;
    }
    while (etape != FINI) {
        switch (etape) {
            case GOTO_CLAP1_START:
                trajStatut = trajectoryBasicAction(clap1StartPos);
                if (trajStatut == ACTION_FINIE) {
                    etape = DEPLOIEMENT_BRAS;
                } else if (trajStatut == ACTION_ERREUR) {
                    infoAction.statut = ACTION_REMISE;
                    etape = FINI;
                }
                break;
            case GOTO_CLAP2_START:
                trajStatut = trajectoryBasicAction(clap2StartPos);
                if (trajStatut == ACTION_FINIE) {
                    etape = DEPLOIEMENT_BRAS;
                } else if (trajStatut == ACTION_ERREUR) {
                    infoAction.statut = ACTION_REMISE;
                    etape = FINI;
                }
                break;
            case DEPLOIEMENT_BRAS:
                sortirServoClap();
                // on ne met pas de délai, on suppose que le bras sera sorti à temps pdt le mouvment
                if (option == CLAP1_ONLY) {
                    etape = GOTO_CLAP1_END;
                } else {
                    etape = GOTO_CLAP2_END;
                }
                break;
            case GOTO_CLAP1_END:
                trajStatut = trajectoryBasicAction(clap1EndPos);
                if (trajStatut == ACTION_FINIE) {
                    etape = REPLIEMENT_BRAS;
                } else if (trajStatut == ACTION_ERREUR) {
                    infoAction.statut = ACTION_REMISE;
                    etape = FINI;
                }
                break;
            case GOTO_CLAP2_END:
                trajStatut = trajectoryBasicAction(clap2EndPos);
                if (trajStatut == ACTION_FINIE) {
                    etape = REPLIEMENT_BRAS;
                } else if (trajStatut == ACTION_ERREUR) {
                    infoAction.statut = ACTION_REMISE;
                    etape = FINI;
                }
                if (compareXY(propulsionGetPosition(), Fish_bordure)) {      // on rentre le bras pour ne pas toucher le clap de l'adversaire
                    rentrerServoClap();
                }
                if (compareXY(propulsionGetPosition(), clap2StartPos)) {    // on ressort le bras pour notre 2ème clap
                    sortirServoClap();
                }
                break;
            case REPLIEMENT_BRAS:
                rentrerServoClap();
                infoAction.statut = ACTION_FINIE;
                etape = FINI;
                break;
            default:
                break;
        }
    }

    return (infoAction);
}
コード例 #4
0
ファイル: FourSort.c プロジェクト: andrewhsu/foursort
// insertionsort for small segments where the loop has been unrolled
void insertionsort(int N, int M) {
  if ( M <= N ) return;
  // M <= N + 10 
  register int i, s;
  int minimumPosition;
  void *minimum, *next, *ai;
  minimumPosition = N;
  minimum = A[N];
  for ( i = N+1; i <= M; i++ ) {
    ai = A[i];
    // if ( ai < minimum ) {
    if ( compareXY(ai, minimum) < 0 ) {
      minimum = ai;
      minimumPosition = i;
    }
  }
  if ( N != minimumPosition ) {
    A[minimumPosition] = A[N];
    A[N] = minimum;
  }
  s = N+1;
  // if ( M == s ) return;
  while ( s < M ) {
    s=s+1;
    next=A[s];
    ai = A[s-1];
    // if ( ai <= next ) continue;
    if ( compareXY(ai, next) <= 0 ) continue;
    A[s] = ai;
    ai = A[s-2];
    if ( compareXY(ai, next) <= 0 ) { A[s-1] = next; continue; }
    A[s-1] = ai;
    ai = A[s-3];
    if ( compareXY(ai, next) <= 0 ) { A[s-2] = next; continue; }
    A[s-2] = ai;
    ai = A[s-4];
    if ( compareXY(ai, next) <= 0 ) { A[s-3] = next; continue; }
    A[s-3] = ai;
    ai = A[s-5];
    if ( compareXY(ai, next) <= 0 ) { A[s-4] = next; continue; }
    A[s-4] = ai;
    ai = A[s-6];
    if ( compareXY(ai, next) <= 0 ) { A[s-5] = next; continue; }
    A[s-5] = ai;
    ai = A[s-7];
    if ( compareXY(ai, next) <= 0 ) { A[s-6] = next; continue; }
    A[s-6] = ai;
    ai = A[s-8];
    if ( compareXY(ai, next) <= 0 ) { A[s-7] = next; continue; }
    A[s-7] = ai;
    ai = A[s-9];
    if ( compareXY(ai, next) <= 0 ) { A[s-8] = next; continue; }
    A[s-8] = ai;
    ai = A[s-10];
    if ( compareXY(ai, next) <= 0 ) { A[s-9] = next; continue; }
    A[s-9] = ai;
    ai = A[s-11];
    if ( compareXY(ai, next) <= 0 ) { A[s-10] = next; continue; }
    A[s-10] = ai;
    ai = A[s-12];
    if ( compareXY(ai, next) <= 0 ) { A[s-11] = next; continue; }
    fprintf(stderr, "FourSort/ insertionsort() ");
    fprintf(stderr, "N: %d M: %d s: %d\n", N, M, s);
    exit(1);
  }
  return;
} // end insertionsort
コード例 #5
0
ファイル: FourSort.c プロジェクト: andrewhsu/foursort
/* Three partition sorting with a single pivot p
   Left elements are less than the pivot
   Middle elements are equal to the pivot
   Right elements are greater than the pivot
   Only middle elements are guaranteed to be non-empty
   This module is invoked on 'pathological' inputs */
void cut3duplicates(int N, int M, int pivotx, void (*cut)(), int depthLimit) {
  // pivotx is pivot index inside [N,M] of pivot: p
  register void *p = A[pivotx];
  // indices 
  register int i, j, lw, up;
  // values
  register void *x, *y, *AM;

  // initialize end points
  x = A[N]; AM = A[M];
  A[N] = A[M] = p;

  /* We employ again whack-a-mole. We know in which partition element x 
     should be.  Find a close, undecided position where x should go.  
     Store its content in y.  Drop x (simplified).  Set x to y and repeat. 
   */
  // initialize running indices
  i = N;
  j = M;
  //  if ( x < p ) goto StartL;
  if ( compareXY(x, p) < 0 ) goto StartL;
  //  if ( p < x ) goto StartR;
  if ( compareXY(p, x) < 0 ) goto StartR;
  goto CreateMiddle;

 StartL:
  /*
    |o---]-----------------------------[---o|
    N    i                             j    M
    x -> L
   */
    i++;
  y = A[i];
  if ( compareXY(y, p) < 0 ) goto StartL; 
  // if ( p < y ) { 
  if ( compareXY(p, y ) < 0 ) { 
    if ( i < j ) {
      A[i] = x;
      x = y;
      goto StartR;
    }
    // gap closed; i==j 
    /*
    |o-----------][----------------------o|
    N             i                       M
    x -> L        j
   */
    A[N] = x;
    // AM must be p
    A[M] = A[j];
    A[j] = AM;
    goto Finish;
  }
  // y = p -> M
  if ( i < j ) {
    A[i] = x;
    x = y;
    goto CreateMiddle;
  }
  /* We have:
     x -> L
     y -> M
     i = j
     N+i <= k < i -> A[k] < p
     i = j <= k < M -> p < A[k]
     Therefore: 
     x must go to A[N] and 
     p = A[M], the only location where y can go.
     Hence: i = j = M 
     This cannot happen under normal use because there must be
     more than one element equal to p when used by the other 
     members of Par/FourSort

    |o------------------------------------]o|
    N                                      M=i=j
    x -> L
   */
  A[N] = x;
  // AM must be p hence the next assignment is defensive
  A[M] = AM;
  i--;
  goto FinishL;

 StartR:
  /*
    |o---]-----------------------------[---o|
    N    i                             j    M
    x -> R
   */
  j--;
  y = A[j];
  if ( compareXY(p, y ) < 0 ) goto StartR;
  if ( compareXY(y, p) < 0 ) {
    if ( i < j ) {
      A[j] = x;
      x = y;
      goto StartL;
    }
    // gap closed; i==j
    /*
    |o-----------][----------------------o|
    N            i                        M
    x -> R       j
   */
    A[M] = x;
    // AM must be p
    A[N] = A[i]; A[i] = AM;
    goto Finish;
  }
  // y -> M
  if ( i < j ) {
    A[j] = x;
    x = y;
    goto CreateMiddle;
  }
  /* We have:
     x -> R
     y -> M
     i = j
     N+i <= k <= i -> A[k] < p
     i = j < k < M -> p < A[k]
     Therefore: 
     x must go to A[M] and 
     p = A[N], the only location where y can go.
     Hence: i = j = N
     This cannot happen under normal use because there must be
     more than one element equal to p when used by the other 
     members of Par/FourSort.

    |o][-----------------------------------o|
    N=i=j                                   M
    x -> R
   */
  A[M] = x;
  // AM must be p
  A[N] = AM;
  j++;
  goto FinishR;

 CreateMiddle:
  /*
    |o---]-----------------------------[---o|
    N    i                             j    M
    x -> M
   */
  /* This test can NOT be true:
     all elements <= i are less than p
     all elements >= j are greater than p
     Thus: contradiction
  if ( i+1 == j ) {
   /////
    |o--------------][---------------------o|
    N               ij                      M
    x -> M
   /////
    // if ( AM < p ) {
    if ( compareXY(AM, p) < 0 ) {
      A[N] = AM;
      A[M] = A[j]; A[j] = x;
      i++;
      goto Finish;
    } 
    //    if ( p < AM ) {  
    if ( compareXY(p, AM) < 0 ) {
      A[M] = AM;
      A[N] = A[i]; A[i] = x;
      j--;
      goto Finish;
    }
    // p = AM
    A[N] = A[i]; A[i] = x; 
    A[M] = A[j]; A[j] = AM; 
    goto Finish;
  }
  */
  lw = (i+j)/ 2;
  up = lw+1;
  y = A[lw];
  A[lw] = x;
  x = y;
  lw--;
  /*
    |o---]-----------+[-]+-------------[---o|
    N    i          lw   up            j    M
   x -> ?
   */
  // if ( x < p ){
  if ( compareXY(x, p) < 0 ) {
    goto LLgMgRL;
  }
  // if ( p < x ) {
  if ( compareXY(p, x) < 0 ) {
    goto LLgMgRR;
  }
  goto LLgMgRM1;

 LLgMgRL:
  /*
    |o---]-----------+[-]+-------------[---o|
    N    i          lw   up            j    M
    x -> L
   */
  i++;
  y = A[i];
  if ( compareXY(y, p) < 0 ) goto LLgMgRL;
  if ( compareXY(p, y ) < 0 ) {
    A[i] = x;
    x = y;
    goto LLgMgRR;
  }
  // y -> M
  if ( i <= lw ) {
    A[i] = x;
    x = y;
    goto LLgMgRM1;
  }
  // left gap closed
  /*
    |o---------][------]+-------------[---o|
    N           i       up            j    M
    x -> L
   */
  goto LLMgRL;
  
 LLgMgRR:
  /*
    |o---]-----------+[-]+-------------[---o|
    N    i          lw   up            j    M
    x -> R
   */
  j--;
  y = A[j];
  if ( compareXY(p, y ) < 0 ) goto LLgMgRR;
  if ( compareXY(y, p) < 0 ) {
    A[j] = x;
    x = y;
    goto LLgMgRL;
  }
  // y -> M
  if ( up <= j ) {
    A[j] = x;
    x = y;
    goto LLgMgRM2;
  }
  // right gap closed
  /*
    |o---]-----------+[---------][---------o|
    N    i          lw          j           M
    x -> R
   */
  goto LLgMRR;
  
 LLgMgRM1:
  /*
    |o---]-----------+[-]+-------------[---o|
    N    i          lw   up            j    M
    x -> M
   */
  y = A[lw];
  if ( compareXY(p, y ) < 0 ) {
    A[lw] = x;
    x = y;
    lw--; 
    goto LLgMgRR;
  } 
  if ( compareXY(p, y) == 0 ) {
   if ( i < lw ) {
      lw--;
      goto LLgMgRM2;
    }
    goto LMgRM;
  }
  // y -> L
  if ( i < lw ) {
    A[lw] = x;
    x = y;
    lw--;
    goto LLgMgRL;
  }
  // left gap closed
  i++; 
  goto LLMgRM;
    
 LLgMgRM2:
  /*
    |o---]-----------+[-]+-------------[---o|
    N    i          lw   up            j    M
    x -> M
   */
  y = A[up];
  if ( compareXY(y, p) < 0 ) {
    A[up] = x;
    x = y;
    up++;
    goto LLgMgRL;
  }
  if ( compareXY(p, y) == 0 ) {
    if ( up < j ) {
      up++;
      goto LLgMgRM1;
    }
    goto LLgMM;
  }
  // y -> R
  if ( up < j ) {
    A[up] = x;
    x = y;
    up++;
    goto LLgMgRR;
  }
  // right gap closed
  j--; 
  goto LLgMRM;

  // left gap closed
 LLMgRL:  
  /*
    |o---------][------]+-------------[---o|
    N           i       up            j    M
    x -> L
  */
  y = A[up];
  if ( compareXY(y, p) < 0 ) {
    A[up] = A[i]; A[i] = y;
    up++; i++;
    goto LLMgRL;
  }
  // if ( y == p ) {
  if ( compareXY(p, y) == 0 ) { 
    if ( up == M ) {
   /*
    |o---------][-------------------]o|
    N           i                     M
    x -> L
   */
      A[N] = x;
      if ( compareXY(p, AM) <= 0 ) {
	A[M] = AM;
	i--;
	goto FinishL;
      }
      /*
      // if ( p == AM ) { 
      if ( compareXY(p, AM) == 0 ) { 
	A[M] = AM;
	i--;
	goto FinishL;
      }
      */
      // compareXY(AM, p) < 0
      A[M] = A[i]; A[i] = AM;
      goto FinishL;
    }
    up++;
    goto LLMgRL;
  }
  // y -> R
  if ( up < j ) {
    A[up] = A[i]; A[i] = x;
    x = y;
    i++; up++;
    goto LLMgRR;
  }
  // right gap closed also
  /*
    |o---------][------][-----------------o|
    N           i       j                  M
    x -> L
   */
  // up == j; A[j] == y 
  if ( compareXY(p, AM) < 0 ) {
    A[N] = x; A[M] = AM;
    j--;
    goto Finish;
  }
  if ( compareXY(p, AM) == 0 ) {
    A[N] = x; A[M] = y; A[j] = AM;
    goto Finish;
  }
  // AM -> L and x -> L
  A[M] = y; A[j] = A[i];
  // if ( x <= AM ) { 
  if ( compareXY(x, AM ) <= 0 ) { 
    A[N] = x; 
    A[i] = AM;
  } else {
    A[N] = AM; 
    A[i] = x;
  }
  i++;
  goto Finish;

 LLMgRM:
  /*
    |o---------][------]+-------------[---o|
    N           i       up            j    M
    x -> M
   */
  y = A[up];
  if ( compareXY(y, p) < 0 ) {
    A[up] = A[i]; A[i] = y; 
    i++; up++;
    goto LLMgRM;
  }
  if ( compareXY(p, y) == 0 ) {
    if ( up == M ) { // R empty 
      /*
    |o---------][-------------------]o|
    N           i                     M
    x -> M
      */
      if ( compareXY(AM, p) < 0 ) {
	A[N] = AM;
	A[M] = x;
	i--;
	goto FinishL;
      }
      /*
      if ( compareXY(p, AM) < 0 ) {
	A[M] = AM;
	i--;
	A[N] = A[i]; A[i] = x;
	i--;
	goto FinishL;
      }
      */
      A[M] = AM;
      i--;
      A[N] = A[i]; A[i] = x;
      i--;
      goto FinishL;
    }
    up++;
    goto LLMgRM;
  }
  // y -> R
  if ( up < j ) {
    A[up] = x;
    x = y;
    up++;
    goto LLMgRR;
  }
  // right gap closed also
  /*
    |o---------][------][-----------------o|
    N           i       j                  M
    x -> M
   */
  // up == j; A[j] == y 
  if ( compareXY(p, AM) < 0 ) {
    A[M] = AM;
    i--;
    A[N] = A[i]; A[i] = x;
    j--;
    goto Finish;
  } 
  if ( compareXY(AM, p) < 0 ) {
    A[N] = AM; A[M] = y; A[j] = x;
    goto Finish;
  }
  // AM -> M
  i--;
  A[N] = A[i]; A[i] = x;
  A[M] = y; A[j] = AM;
  goto Finish;

 LLMgRR:
  /*
    |o---------][------]+-------------[---o|
    N           i       up            j    M
    x -> R
  */
  j--;
  y = A[j];
  if ( compareXY(p, y ) < 0 ) goto LLMgRR;
  if ( compareXY(y, p) < 0 ) {
    A[j] = x;
    x = y;
    goto LLMgRL;
  }
  // y -> M
  if ( up <= j ) {
    A[j] = x;
    x = y;
    goto LLMgRM;
  }
  // right gap closed also   y = A[j]
  /*
    |o---------][------][-----------------o|
    N           i      j                   M
    x -> R
   */
  A[M] = x;
  if ( compareXY(AM, p) < 0 ) {
    A[N] = AM; 
    goto Finish;
  }
  if ( compareXY(p, AM) == 0 ) {
    i--;
    A[N] = A[i]; A[i] = AM;
    goto Finish;
  }
  // AM -> R
  i--;
  A[N] = A[i]; A[i] = y; A[j] = AM;
  j--; 
  goto Finish;

  // right gap closed
 LLgMRR:
  /*
    |o---]-----------+[---------][---------o|
    N    i          lw          j           M
    x -> R
  */
  y = A[lw];
  if ( compareXY(p, y ) < 0 ) {
    A[lw] = A[j]; A[j] = y;
    lw--; j--;
    goto LLgMRR;    
  }
  if ( compareXY(p, y) == 0 ) {
    if ( N == lw ) { // L is empty 
      /*
    |o[-----------------------][---------o|
    N                         j           M
    x -> R
      */
      A[M] = x;
      if ( compareXY(AM, p) <= 0 ) {
	A[N] = AM;
	j++;
	goto FinishR;
      }
      /*
      if ( compareXY(p, AM) == 0 ) {
	A[N] = AM;
	j++;
	goto FinishR;
      }
      */
      // compareXY(p, AM) < 0
      A[N] = A[j]; A[j] = AM;
      goto FinishR;
    }
    lw--;
    goto LLgMRR; 
  }
  // y -> L
  if ( i < lw ) {
    A[lw] = A[j]; A[j] = x;
    x = y;
    lw--; j--;
    goto LLgMRL;
  }
  // left gap closed also
  /*
    |o---][---------------------][---------o|
    N    i                      j           M
    x -> R
  */
  // y == A[lw] == A[i]
  A[M] = x;
  if ( compareXY(AM, p) < 0 ) {
    A[N] = AM;
    i++;
    goto Finish;
  }
  if ( compareXY(p, AM) == 0 ) {
    A[N] = y; A[i] = AM;
    goto Finish;
  }
  // AM -> R
  A[N] = y; A[i] = A[j]; A[j] = AM;
  j--; 
  goto Finish;

 LLgMRM:
  /*
    |o---]-----------+[---------][---------o|
    N    i          lw          j           M
    x -> M
  */
  y = A[lw];
  if ( compareXY(p, y ) < 0 ) {
    A[lw] = A[j]; A[j] = y;
    lw--; j--;
    goto LLgMRM;    
  }
  if ( compareXY(p, y) == 0 ) {
    if ( N == lw ) { // L empty 
      /*
    |o[-----------------------][---------o|
    N                         j           M
    x -> M
      */
      if ( compareXY(AM, p) <= 0 ) {
	A[N] = AM;
	j++;
	A[M] = A[j];
	A[j] = x;
	j++;
	goto FinishR; 
      }
      /*
      // if ( p == AM ) {
      if ( compareXY(p, AM) == 0 ) { 
	A[N] = AM;
	j++;
	A[M] = A[j];
	A[j] = x;
	j++;
	goto FinishR; 
      }
      */
      // compareXY(p, AM) < 0
      A[M] = AM; A[N] = x;
      j++;
      goto FinishR; 
    }
    lw--;
    goto LLgMRM; 
  }
  // y -> L
  if ( i < lw ) {
    A[lw] = x;
    x = y;
    lw--;
    goto LLgMRL;
  }
  // left gap closed also
  /*
    |o---][---------------------][---------o|
    N    i                      j           M
    x -> M
  */
  // y == A[lw] == A[i]
  if ( compareXY(p, AM) < 0 ) {
    A[M] = AM; 
    A[N] = y; A[i] = x;
    goto Finish;
  }
  if ( compareXY(AM, p) < 0 ) {
    A[N] = AM; 
    j++;
    A[M] = A[j]; A[j] = x;
    i++;
    goto Finish;
  }
  // AM == p
  A[N] = y; A[i] = x;
  j++;
  A[M] = A[j]; A[j] = AM;
  goto Finish;

 LLgMRL:
  /*
    |o---]-----------+[---------][---------o|
    N    i          lw          j           M
    x -> L
   */
  i++;
  y = A[i];
  if ( compareXY(y, p) < 0 ) goto LLgMRL;
  if ( compareXY(p, y ) < 0 ) {
    A[i] = x;
    x = y;
    goto LLgMRR;
  }
  // y -> M
  if ( i <= lw ) {
    A[i] = x;
    x = y;
    goto LLgMRM;  
  }
  // left gap closed also  y = A[i];
   /*
    |o---][----------------------][---------o|
    N     i                      j           M
    x -> L
   */
  A[N] = x;
  if ( compareXY(p, AM) < 0 ) { 
    A[M] = AM;
    goto Finish;
  }
  if ( compareXY(p, AM) == 0 ) {
    j++;
    A[M] = A[j]; A[j] = AM;
    goto Finish;
  }
  // AM -> L
  j++;
  A[M] = A[j]; A[j] = y; A[i] = AM;
  i++;
  goto Finish;

 LMgRM:
   /*
    |o[---------------]+-------------[---o|
    N                  up            j    M
    x -> M
   */
  y = A[up];
  if ( compareXY(y, p) < 0 ) { // N == i 
    i++;
    A[up] = A[i]; A[i] = y;
    i++; up++;
    goto LLMgRM;
  }
  if ( compareXY(p, y) == 0 ) {
    if ( up == M ) {
   /*
    |o[----------------------------]o|
    N                                M
    x -> M
   */
      if ( compareXY(AM, p) <= 0 ) {
	A[N] = AM; A[M] = x;
	goto Finish0;
      }
      /*
      if ( compareXY(p, AM) == 0 ) {
	A[N] = AM; A[M] = x;
	goto Finish0;
      }
      */
      // compareXY(p, AM) < 0
      A[N] = x; A[M] = AM;
      goto Finish0;
    }
    up++;
    goto LMgRM;
  }
  // compareXY(p, y ) < 0
  if ( up < j ) {
    A[up] = x;
    x = y;
   /*
    |o[---------------]+-------------[---o|
    N                  up            j    M
    x -> R
   */
    goto LMgRR;
  }
  // right gap closed  y = A[up] = A[j] -> R
  /*
    |o[-----------------------------][---o|
    N                                j    M
    x -> M
   */
  if ( compareXY(AM, p) <= 0 ) {
    A[N] = AM;
    A[M] = y; A[j] = x;
    j++;
    goto FinishR;
  }
  /*
  if ( compareXY(AM, p) < 0 ) {
    A[N] = AM;
    A[M] = A[j]; A[j] = x;
    j++;
    goto FinishR;
  }
  if ( compareXY(p, AM) == 0 ) {
    A[N] = AM;
    A[M] = A[j]; A[j] = x;
    j++;
    goto FinishR;
  }
  */
  // AM -> R
  A[N] = x; A[M] = AM;
  goto FinishR;

 LLgMM:
   /*
    |o---]-----------+[------------------]o|
    N    i          lw                     M
    x -> M
   */
  y = A[lw];
  if ( compareXY(p, y ) < 0 ) {
    j--;
    A[lw] = A[j]; A[j] = y;
    lw--;
    j--;
    goto LLgMRM;
  }
  if ( compareXY(p, y) == 0 ) {
    if ( N == lw ) { // L empty also 
      /*
    |o[----------------------------]o|
    N                                M
    x -> M
      */
      if ( compareXY(AM, p) <= 0 ) {
	A[N] = AM; A[M] = x;
	goto Finish0;
      }
      /*
      if ( compareXY(p, AM) == 0 ) {
	A[N] = AM; A[M] = x;
	goto Finish0;
      }
      */
      // AM -> R
      A[N] = x; A[M] = AM;
      goto Finish0;
    }
    lw--;
    goto LLgMM;
  }
  // y -> L
  if ( i < lw ) {
    A[lw] = x;
    x = y;
    lw--;
    goto LLgML;
  }
  // left gap closed also  y = A[lw] = A[i] -> L
   /*
    |o---][-----------------------------]o|
    N    i                                M
    x -> M
   */
  if ( compareXY(AM, p) < 0 ) {
    A[N] = AM; A[M] = x;
    goto FinishL;
  }
  if ( compareXY(p, AM) == 0 ) {
    A[N] = y; A[i] = AM; A[M] = x;
    i--;
    goto FinishL;
  }
  // compareXY(p, AM) < 0
  A[M] = AM;
  A[N] = y; A[i] = x;
  i--;
  goto FinishL;

 LLgML:
   /*
    |o---]-----------+[------------------]o|
    N    i          lw                     M=j
    x -> L
   */
  i++;
  y = A[i];
  if ( compareXY(y, p) < 0 ) goto LLgML;
  if ( compareXY(p, y) == 0 ) {
    if ( i <= lw ) {
      A[i] = x;
      x = y;
      goto  LLgMM;
    }
    // left gap closed  y = A[i]
   /*
    |o--------------][------------------]o|
    N                i                    M=j
    x -> L
   */
    A[N] = x;
    if ( compareXY(p, AM) <= 0 ) {
      A[M] = AM;
      i--;
      goto FinishL;
    }
    /*
    // if ( p == AM ) {
    if ( compareXY(p, AM) == 0 ) { 
      A[M] = AM;
      i--;
      goto FinishL;
    }
    */
    // AM -> L
    A[M] = y; A[i] = AM;
    goto FinishL;
  }
  // y -> R
  A[i] = x;
  x = y;
  goto LLgMR;

 LLgMR:
   /*
    |o---]-----------+[------------------]o|
    N    i          lw                     M=j
    x -> R
   */
  y = A[lw];
  if ( compareXY(p, y ) < 0 ) {
    j--;
    A[lw] = A[j]; A[j] = y;
    j--; lw--;
    goto LLgMRR;
  }
  if ( compareXY(p, y) == 0 ) {
    if ( N == lw ) { // L is empty 
      /*
    |o[----------------------------]o|
    N                                M=j
    x -> R
      */
     if ( compareXY(AM, p) <= 0 ) { 
	A[N] = AM;
	A[M] = x;
	goto Finish0;
     }
     /*
     if ( compareXY(p, AM) == 0 ) { 
	A[N] = AM;
	A[M] = x;
	goto Finish0;
     }
     */
     // AM -> R
     j--;// = M-1
     A[N] = A[j];
     if ( x <= AM ) {
       A[j] = x; A[M] = AM;
     } else {
       A[j] = AM; A[M] = x;
     }
     goto Finish0;
    }
    lw--;
    goto LLgMR;
  }
  // y -> L
  if ( i < lw ) {
    j--;
    A[lw] = A[j]; A[j] = x;
    x = y;
    lw--; j--;
    goto LLgMRL;
  }
  // left gap closed y = A[lw] = A[i] -> L
 /*
    |o---][----------------------------]o|
    N    i                               M=j
    x -> R
   */
  if ( compareXY(AM, p) < 0 ) {
    A[N] = AM; A[M] = x;
    goto FinishL;
  }
  if ( compareXY(p, AM) == 0 ) {
    A[M] = x;
    A[N] = y; A[i] = AM;
    i--;
    goto FinishL;
  }
  // AM -> R
  j--;
  A[N] = y; A[i] = A[j];
  if ( x <= AM ) {
    A[j] = x; A[M] = AM;
  } else {
    A[j] = AM; A[M] = x;
  }
  i--;
  goto FinishL;

 LMgRR:
   /*
    |o[---------------]+-------------[---o|
    N                  up            j    M
    x -> R
   */
  j--;
  y = A[j];
  if ( compareXY(p, y ) < 0 ) goto LMgRR;
  if ( compareXY(y, p) < 0 ) {
    A[j] = x;
    x = y;
   /*
    |o[---------------]+-------------[---o|
    N                  up            j    M
    x -> L
   */
    goto LMgRL;
  }
  // y -> M
  if ( up <= j ) {
    A[j] = x;
    x = y;
    goto LMgRM;
  }
  // right gap closed  y = A[j]
  /*
    |o[---------------][----------------o|
    N                 j                  M
    x -> R
   */
  A[M] = x;
  if ( compareXY(AM, p) <= 0 ) {
    A[N] = AM;
    j++;
    goto FinishR;
  }
  /*
  if ( compareXY(p, AM) == 0 ) {
    A[N] = AM;
    j++;
    goto FinishR;
  }
  */
  // AM -> R
  A[N] = A[j]; A[j] = AM;
  goto FinishR;

 LMgRL:
   /*
    |o[---------------]+-------------[---o|
    N                  up            j    M
    x -> L
   */
  y = A[up];
  if ( compareXY(y, p) < 0 ) { // create L
    i++;
    A[up] = A[i]; A[i] = y;
    i++; up++;
    goto LLMgRL;    
  }
  if ( compareXY(p, y) == 0 ) {
    if ( up == M ) { // R is empty 
      /*
    |o[----------------------------]o|
    N                                M
    x -> L
      */
      if ( compareXY(p, AM) <= 0 ) {
	A[N] = x; A[M] = AM;
	goto Finish0;
      }
      /*
      if ( compareXY(p, AM) == 0 ) {
	A[N] = x; A[M] = AM;
	goto Finish0;
      }
      */
      // AM -> L
      i++;
      A[M] = A[i];
      if ( x <= AM ) {
       A[N] = x; A[i] = AM;
      } else {
	A[N] = AM; A[i] = x;
      }
      goto Finish0;
    }
    up++;
    goto LMgRL;
  }
  // y -> R
  if ( up < j ) {
    i++;
    A[up] = A[i]; A[i] = x;
    x = y;
    i++; up++;
    goto LLMgRR;
  }
  // right gap closed   y = A[up] = A[j]
  /*
    |o[-----------------------------][---o|
    N                                j    M
    x -> L
   */
  if ( compareXY(p, AM) < 0 ) {
    A[N] = x; A[M] = AM;
    goto FinishR;
  }
  if ( compareXY(p, AM) == 0 ) {
    A[N] = x; 
    A[M] = A[j]; A[j] = AM;
    j++;
    goto FinishR;
  }
  // AM -> L
  i++;
  A[M] = A[j]; A[j] = A[i];
  if ( x <= AM ) {
    A[N] = x; A[i] = AM;
  } else {
    A[N] = AM; A[i] = x;
  }
  j--;
  goto FinishR;

  int k;

 Finish0:
  return;

 FinishL:
    (*cut)(N, i, depthLimit);
  return;

 FinishR:
    (*cut)(j, M, depthLimit);
  return;

 Finish:
  /* holes filled
    |o---------][------][-----------------o|
    N           i      j                   M
  */
  /*
  for (k = N; k < i; k++) 
    if ( p <= A[k] ) {
      printf("Error L at k: %d \n", k);
      exit(1);
    }
  for (k = i; k <= j; k++) 
    if ( p != A[k] ) {
      printf("Error M at k: %d \n", k);
      // printf("N: %d i: %d j: %d M: %d\n", N, i, j, M);
      exit(1);
    }
  for (k = j+1; k <= M; k++) 
    if ( A[k] <= p ) {
      printf("Error R at k: %d \n", k);
      printf("N: %d i: %d j: %d M: %d\n", N, i, j, M);
      exit(1);
    }
  */
  if ( i - N  < M - j ) {
    (*cut)(N, i-1, depthLimit);
    (*cut)(j+1, M, depthLimit);
  } else {
    (*cut)(j+1, M, depthLimit);
    (*cut)(N, i-1);
  }
} // end of cut3duplicates
コード例 #6
0
ファイル: FourSort.c プロジェクト: andrewhsu/foursort
void cut2c(int N, int M, int depthLimit) {
  int L;
  Start:
  if ( depthLimit <= 0 ) {
    heapc(A, N, M);
    return;
  }
  L = M - N;
  if ( L < cut2Limit ) { 
    quicksort0c(N, M, depthLimit);
    return;
  }
  depthLimit--;
  
  // Check for duplicates
        int sixth = (M - N + 1) / 6;
        int e1 = N  + sixth;
        int e5 = M - sixth;
        int e3 = (N+M) / 2; // The midpoint
        int e4 = e3 + sixth;
        int e2 = e3 - sixth;

        // Sort these elements using a 5-element sorting network
        void *ae1 = A[e1], *ae2 = A[e2], *ae3 = A[e3], *ae4 = A[e4], *ae5 = A[e5];
	void *t;
        // if (ae1 > ae2) { t = ae1; ae1 = ae2; ae2 = t; }
	if ( compareXY(ae1, ae2) > 0 ) { t = ae1; ae1 = ae2; ae2 = t; }
        if ( compareXY(ae4, ae5) > 0 ) { t = ae4; ae4 = ae5; ae5 = t; }
        if ( compareXY(ae1, ae3) > 0 ) { t = ae1; ae1 = ae3; ae3 = t; }
        if ( compareXY(ae2, ae3) > 0 ) { t = ae2; ae2 = ae3; ae3 = t; }
        if ( compareXY(ae1, ae4) > 0 ) { t = ae1; ae1 = ae4; ae4 = t; }
        if ( compareXY(ae3, ae4) > 0 ) { t = ae3; ae3 = ae4; ae4 = t; }
        if ( compareXY(ae2, ae5) > 0 ) { t = ae2; ae2 = ae5; ae5 = t; }
        if ( compareXY(ae2, ae3) > 0 ) { t = ae2; ae2 = ae3; ae3 = t; }
        if ( compareXY(ae4, ae5) > 0 ) { t = ae4; ae4 = ae5; ae5 = t; }

        A[e1] = ae1; A[e2] = ae2; A[e3] = ae3; A[e4] = ae4; A[e5] = ae5;

	// Fix end points
	if ( compareXY(ae1, A[N]) < 0 ) iswap(N, e1, A);
	if ( compareXY(A[M], ae5) < 0 ) iswap(M, e5, A);

	int duplicate = -1;
	// if ( ae1, ae5 ) { duplicate = e1; } else
	if ( compareXY(ae1, ae5) == 0 ) { duplicate = e1; } else
	if ( compareXY(ae1, ae4) == 0 ) { duplicate = e1; } else
	if ( compareXY(ae2, ae5) == 0 ) { duplicate = e2; } else
	if ( compareXY(ae1, ae3) == 0 ) { duplicate = e1; } else
	if ( compareXY(ae2, ae4) == 0 ) { duplicate = e2; } else
	if ( compareXY(ae3, ae5) == 0 ) { duplicate = e3; } else
	if ( compareXY(ae1, ae2) == 0 ) { duplicate = e1; } else
	if ( compareXY(ae2, ae3) == 0 ) { duplicate = e2; } else
	if ( compareXY(ae3, ae4) == 0 ) { duplicate = e3; } else
	if ( compareXY(ae4, ae5) == 0 ) { duplicate = e4; };
	
	if ( 0 <= duplicate ) {
	  void cut2c();
	  cut3duplicates(N, M, duplicate, cut2c, depthLimit);
	  return;
	}

	register void *T = ae3; // pivot


	// test to play safe:
	// if ( T <= A[N] || A[M] < T ) {
	if ( compareXY(T, A[N]) <= 0 || compareXY(A[M], T) < 0 ) {
	  // give up because cannot find a good pivot
	  quicksort0c(N, M, depthLimit+1);
	  return;
	}

	register  int I, J; // indices
	register void *AI, *AJ; // array values


	// initialize running indices
	I= N;
	J= M;

	// The left segment has elements < T
	// The right segment has elements >= T
  Left:
	 I = I + 1;
	 AI = A[I];
	 // if (AI < T) goto Left;
	 if ( compareXY( AI,  T) < 0 ) goto Left;
  Right:
	 J = J - 1;
	 AJ = A[J];
	 // if ( T <= AJ ) goto Right;
	 if ( compareXY( T, AJ) <= 0 ) goto Right;
	 if ( I < J ) {
	   A[I] = AJ; A[J] = AI;
	   goto Left;
	 }
  	 if ( (I - N) < (M - J) ) { // smallest one first
	   cut2c(N, J, depthLimit);
	   N = I; 
	   goto Start;
	 }
	 cut2c(I, M, depthLimit);
	 M = J;
	 goto Start;
} // (*  OF cut2; *) ... the brackets reminds that this was Pascal code
コード例 #7
0
ファイル: FourSort.c プロジェクト: andrewhsu/foursort
// Quicksort equipped with a defense against quadratic explosion;
// calling heapsort if depthlimit exhausted
void quicksort0c(int N, int M, int depthLimit) {
  // printf("Enter quicksort0c N: %d M: %d %d\n", N, M, depthLimit);
  while ( N < M ) {
    int L = M - N;
    if ( L <= 10 ) {
      insertionsort(N, M);
      return;
    }
    if ( depthLimit <= 0 ) {
      heapc(A, N, M);
      return;
    }
    depthLimit--;
    // 10 < L
    // grab median of 3 or 9 to get a good pivot
    int pn = N;
    int pm = M;
    int p0 = (pn+pm)/2;
    if ( 40 < L ) { // do median of 9
      int d = L/8;
      pn = med(A, pn, pn + d, pn + 2 * d, compareXY);
      p0 = med(A, p0 - d, p0, p0 + d, compareXY);
      pm = med(A, pm - 2 * d, pm - d, pm, compareXY);
      /* Activation of the check for duplicates gives a slow down of 
	 1/4% on uniform input.  If you suspect that duplicates
	 causing quadratic deterioration are not caught higher-up by cut3
	 you may want to experiment with this check::::
      if ( L < 100 ) { // check for duplicates
	int duplicate = -1;
	if ( compareXY(A[pn], A[pm]) == 0 ) { duplicate = pn; } else
	if ( compareXY(A[pn], A[p0]) == 0 ) { duplicate = pn; } else
	if ( compareXY(A[pm], A[p0]) == 0 ) { duplicate = pm; };
	if ( 0 < duplicate ) {
	  void quicksort0();
	  cut3duplicates(N, M, duplicate, quicksort0, depthLimit);
	  return;
	}
      }
      */
    }
    p0 = med(A, pn, p0, pm, compareXY); // p0 is index to 'best' pivot ...
    iswap(N, p0, A); // ... and is put in first position as required by quicksort0c

    register void *p = A[N]; // pivot
    register int i, j;
    i = N;
    j = M;
    register void *ai; void *aj;

    /* Split array A[N,M], N<M in two segments using pivot p; 
       construct a partition with A[N,i), A(i,M] and N <= i <= M, and
       N <= k <= i -> A[k] <= p  and  i < k <= M -> p < A[k];
       Allow the worse cases: N=i or i=M.
       Recurse on A[N,i) and A(i,M) (or in the reverse order).
       This code does NOT do swapping; instead it disposes 
       ai/aj in a hole created by setting aj/ai first.  
    */
    /* Start state:
	  |-------------------------------|
          N=i                           j=M
	  N = i < j = M
          N <= k < i -> A[k] <= p    
          N < j < k <= M -> p < A[k]
	  A[N] = p
          N < i -> p < A[i]
    */
    while ( i < j ) {
      /*
	  |-------o---------------[--------|
          N       i               j        M
	  N <= i < j <= M
          N <= k < i -> A[k] <= p    
          N < j < k <= M -> p < A[k]
	  A[N] <= p
          N < i -> p < A[i]
          p + A[N,i) + A(i,M] is a permutation of the input array
      */
      aj = A[j];
      while ( compareXY(p, aj) < 0 ) { 
        /*
	  |-------o---------------[--------|
          N       i               j        M
	  N = i < j <= M or N < i <= j <= M
          N <= k < i -> A[k] <= p    
          N < j <= k <= M -> p < A[k]
	  A[N] <= p
	  N < i -> p < A[i}
	  p + A[N,i) + A(i,M] is a permutation of the input array
          p < aj = A[j]
	*/
	j--; 
	aj = A[j]; 
      }
      /*
	  |-------o---------------[--------|
          N       i               j        M
	  N = i = j < M or N < i & = i-1 <= j <= M
          N <= k < i -> A[k] <= p    
          j < k <= M -> p < A[k]
	  A[N] <= p
	  N < i -> p < A[i}
	  p + A[N,i) + A(i,M] is a permutation of the input array
          aj = A[j] <= p
	*/
      if ( j <= i ) {
	/*
	  |-------o-----------------------|
          N       i                       M
	  N = i = j < M or N < i & = i-1 = j < M
          N <= k < i -> A[k] <= p    
          i < k <= M -> p < A[k]
	  A[N] <= p
	  p + A[N,i) + A(i,M] is a permutation of the input array
      */
	break;
      }
      // i < j 
      A[i] = aj; // fill hole !
      /*
	  |-------]---------------o--------|
          N       i               j        M
	  N <= i < j <= M
          N <= k <= i -> A[k] <= p    
          j < k <= M -> p < A[k]
	  A[N] <= p
	  p + A[N,j) + A(j,M] is a permutation of the input array
	  aj = A[j] <= p
      */
      i++; ai = A[i];
      while ( i < j && compareXY(ai, p) <= 0 ) {
      /*
	  |-------]---------------o--------|
          N       i               j        M
	  N < i < j <= M
          N <= k <= i -> A[k] <= p    
          j < k <= M -> p < A[k]
	  A[N] <= p
	  p + A[N,j) + A(j,M] is a permutation of the input array
	  aj = A[j] <= p
      */
	i++; ai = A[i]; 
      }
      if ( j <= i ) 
      /*
	  |----------------------o--------|
          N                     i=j       M
	  N < i = j <= M
          N <= k < i -> A[k] <= p    
          j < k <= M -> p < A[k]
	  A[N] <= p
	  p + A[N,j) + A(j,M] is a permutation of the input array
      */
	break;
      // i < j  & p < ai = A[i] 
      A[j] = ai;
      j--;
      /*
	  |--------o--------------[--------|
          N        i              j        M
	  N < i <= j <= M
          N <= k < i -> A[k] <= p    
          j < k <= M -> p < A[k]
	  A[N] <= p
          N < i -> p < ai = A[i]
	  p + A[N,i) + A(i,M] is a permutation of the input array
      */
    }
    A[i] = p;
    /*
	  |--------]----------------------|
          N        i                      M
	  N <= i <= M
          N <= k <= i -> A[k] <= p    
          i < k <= M -> p < A[k]
	  A[N] <= p
	  A[N,i] + A(i,M] is a permutation of the input array
    */
    // Recurse on the smallest one and iterate on the other one
    int ia = i-1; int ib = i+1; 
    if ( i-N < M-i ) { 
      if ( N < ia ) quicksort0c(N, ia, depthLimit);  
      N = ib; 
    } else { 
      if ( ib < M ) quicksort0c(ib, M, depthLimit);  
      M = ia; 
    }
  }
} // end of quicksort0c
コード例 #8
0
ファイル: UseParFourSort.c プロジェクト: andrewhsu/foursort
void cut2S(int N, int M) {
	int I, J; // indices
	void *AI, *AJ; // array values
 Loop:
	if  ( M - N <= cut2SLimit ) { 
	  quicksort1(N, M);
	  return;
	}
	// Check for duplicates
        int sixth = (M - N + 1) / 6;
        int e1 = N  + sixth;
        int e5 = M - sixth;
        int e3 = (N+M) / 2; // The midpoint
        int e4 = e3 + sixth;
        int e2 = e3 - sixth;

        // Sort these elements using a 5-element sorting network
        void *ae1 = A[e1], *ae2 = A[e2], *ae3 = A[e3], *ae4 = A[e4], *ae5 = A[e5];
	void *t;
        // if (ae1 > ae2) { t = ae1; ae1 = ae2; ae2 = t; }
	if ( compareXY(ae1, ae2) > 0 ) { t = ae1; ae1 = ae2; ae2 = t; }
        if ( compareXY(ae4, ae5) > 0 ) { t = ae4; ae4 = ae5; ae5 = t; }
        if ( compareXY(ae1, ae3) > 0 ) { t = ae1; ae1 = ae3; ae3 = t; }
        if ( compareXY(ae2, ae3) > 0 ) { t = ae2; ae2 = ae3; ae3 = t; }
        if ( compareXY(ae1, ae4) > 0 ) { t = ae1; ae1 = ae4; ae4 = t; }
        if ( compareXY(ae3, ae4) > 0 ) { t = ae3; ae3 = ae4; ae4 = t; }
        if ( compareXY(ae2, ae5) > 0 ) { t = ae2; ae2 = ae5; ae5 = t; }
        if ( compareXY(ae2, ae3) > 0 ) { t = ae2; ae2 = ae3; ae3 = t; }
        if ( compareXY(ae4, ae5) > 0 ) { t = ae4; ae4 = ae5; ae5 = t; }

        A[e1] = ae1; A[e2] = ae2; A[e3] = ae3; A[e4] = ae4; A[e5] = ae5;

	// Fix end points
	if ( compareXY(ae1, A[N]) < 0 ) iswap(N, e1, A);
	if ( compareXY(A[M], ae5) < 0 ) iswap(M, e5, A);

	int duplicate = -1;
	// if ( ae1, ae5 ) { duplicate = e1; } else
	if ( compareXY(ae1, ae5) == 0 ) { duplicate = e1; } else
	if ( compareXY(ae1, ae4) == 0 ) { duplicate = e1; } else
	if ( compareXY(ae2, ae5) == 0 ) { duplicate = e2; } else
	if ( compareXY(ae1, ae3) == 0 ) { duplicate = e1; } else
	if ( compareXY(ae2, ae4) == 0 ) { duplicate = e2; } else
	if ( compareXY(ae3, ae5) == 0 ) { duplicate = e3; } else
	if ( compareXY(ae1, ae2) == 0 ) { duplicate = e1; } else
	if ( compareXY(ae2, ae3) == 0 ) { duplicate = e2; } else
	if ( compareXY(ae3, ae4) == 0 ) { duplicate = e3; } else
	if ( compareXY(ae4, ae5) == 0 ) { duplicate = e4; };
	
	if ( 0 <= duplicate ) {
	  void cut2S();
	  cut3duplicates(N, M, duplicate, cut2S, 0);
	  return;
	}

	register void *T = ae3; // pivot

	// initialize running indices
	I= N;
	J= M;
	// The left segment has elements < T
	// The right segment has elements >= T
	// /*
    Left:
	I = I + 1;
	AI = A[I];
	// if (AI < T) goto Left;
	if ( compareXY(AI, T) < 0 ) goto Left;
    Right:
	J = J - 1;
	AJ = A[J];
	// if ( T <= AJ ) goto Right;
	if ( compareXY(T, AJ) <= 0 ) goto Right;
	if ( I < J ) {
	    A[I] = AJ; A[J] = AI;
	    goto Left;
	}

	int left = I-N;
	int right = M-J;
	if ( left < right ) { // smallest one first
	    cut2S(N, J);
	    // cut2S(I, M);
	    N = I;
	    goto Loop;
	}
	cut2S(I, M);
	// cut2S(N, J);
	M = J;
	goto Loop;
    } // (*  OF cut2S; *) ... the brackets remind that this was Pascal code