#ifdef DOC_BUILD_INTERNAL
#endif
#include "sorting.h"
intptr_t* srtg_Partition( intptr_t *a, intptr_t *l, intptr_t *end)
{
  intptr_t pivot, swap;
  intptr_t *front;
  pivot = *l;
  front = l+1;
  if (front == end) {
    if (*front < pivot) {
      *l = *end;
      *end = pivot;
    }
    return end;
  }
  while (front < end) {
    while (front < end && *front <= pivot)
      front++;
    while (*end > pivot)
      end--;
    if (front < end) {
      swap = *front;
      *front = *end;
      *end = swap;
      front++;
      end--;
    }
    if (front == end && *end > pivot)
      end--;
  }
  *l = *end;
  *end = pivot;
  return end;
}
void srtg_QuickSort( intptr_t *a, intptr_t *l, intptr_t *r)
{
  intptr_t *j;
  if ( l < r )
    {
      j = srtg_Partition( a, l, r);
      srtg_QuickSort( a, l, j-1);
      srtg_QuickSort( a, j+1, r);
    }
}
intptr_t* srtg_APartition( intptr_t *a, intptr_t *l, intptr_t *end, intptr_t (*AccessInt)(POINTER))
{
  intptr_t pivot, pivotvalue, swap;
  intptr_t *front;
  pivotvalue = AccessInt((POINTER)*l);
  pivot = *l;
  front = l+1;
  if (front == end) {
    if (AccessInt((POINTER)*front) < pivotvalue) {
      *l = *end;
      *end = pivot;
    }
    return end;
  }
  while (front < end) {
    while (front < end && AccessInt((POINTER)*front) <= pivotvalue)
      front++;
    while (AccessInt((POINTER)*end) > pivotvalue)
      end--;
    if (front < end) {
      swap = *front;
      *front = *end;
      *end = swap;
      end--;
      front++;
    }
    if (front == end && AccessInt((POINTER)*end) > pivotvalue)
      end--;
  }
  *l = *end;
  *end = pivot;
  return end;
}
void srtg_AQuickSort( intptr_t *a, intptr_t *l, intptr_t *r, intptr_t (*AccessInt)(POINTER))
{
  intptr_t *j;
  if ( l < r )
    {
      j = srtg_APartition( a, l, r, AccessInt);
      srtg_AQuickSort( a, l, j-1, AccessInt);
      srtg_AQuickSort( a, j+1, r, AccessInt);
    }
}
void srtg_Merge(intptr_t *a, intptr_t *lstart, intptr_t *lend, intptr_t *rstart, intptr_t *rend, intptr_t *merge)
{
  intptr_t *mergepos,*lfinal;
  mergepos = merge;
  lfinal = lstart;
  while (lstart <= lend && rstart <= rend) {
    if (*lstart > *rstart) {
      *mergepos = *rstart;
      rstart++;
      mergepos++;
    }
    else {
      *mergepos = *lstart;
      lstart++;
      mergepos++;
    }
  }
  while (lstart <= lend) {
    *mergepos = *lstart;
    lstart++;
    mergepos++;
  }
  while (merge < mergepos) {
    *lfinal = *merge;
    lfinal++;
    merge++;
  }
}
void srtg_MergeSortIntern(intptr_t *a, intptr_t *l, intptr_t *r, intptr_t *merge)
{
  if (l+1<=r) {
    if (l+1 == r) {
        if (*l > *r) {
 intptr_t swap;
 swap = *l;
 *l = *r;
 *r = swap;
      }
    }
    else
      {
 intptr_t mid;
 mid = r-l;
 mid = mid/2;
 srtg_MergeSortIntern(a, l, l + mid, merge);
 srtg_MergeSortIntern(a, l + mid + 1, r, merge);
 srtg_Merge(a, l, l + mid, l + mid + 1, r, merge);
      }
  }
}
void srtg_MergeSort(MEMORY mem, intptr_t *a, intptr_t *l, intptr_t *r)
{
  if (l+1<=r) {
    if (l+1 == r) {
      if (*l > *r) {
 intptr_t swap;
 swap = *l;
 *l = *r;
 *r = swap;
      }
    }
    else
      {
 intptr_t length, *merge, mid;
 length = r-l+1;
 merge = (intptr_t *)memory_Malloc(mem, length * sizeof(intptr_t));
 mid = (length-1)/2;
 srtg_MergeSortIntern(a, l, l + mid, merge);
 srtg_MergeSortIntern(a, l + mid + 1, r, merge);
 srtg_Merge(a, l, l + mid, l + mid + 1, r, merge);
 memory_Free(mem, merge, length * sizeof(intptr_t));
      }
  }
}
void srtg_AMerge(intptr_t *a, intptr_t *lstart, intptr_t *lend, intptr_t *rstart, intptr_t *rend, intptr_t *merge, intptr_t (*AccessInt)(POINTER))
{
  intptr_t *mergepos,*lfinal;
  mergepos = merge;
  lfinal = lstart;
  while (lstart <= lend && rstart <= rend) {
    if (AccessInt((POINTER)*lstart) > AccessInt((POINTER)*rstart)) {
      *mergepos = *rstart;
      rstart++;
      mergepos++;
    }
    else {
      *mergepos = *lstart;
      lstart++;
      mergepos++;
    }
  }
  while (lstart <= lend) {
    *mergepos = *lstart;
    lstart++;
    mergepos++;
  }
  while (merge < mergepos) {
    *lfinal = *merge;
    lfinal++;
    merge++;
  }
}
void srtg_AMergeSortIntern(intptr_t *a, intptr_t *l, intptr_t *r, intptr_t *merge, intptr_t (*AccessInt)(POINTER))
{
  if (l+1<=r) {
    if (l+1 == r) {
      if (AccessInt((POINTER)*l) > AccessInt((POINTER)*r)) {
 intptr_t swap;
 swap = *l;
 *l = *r;
 *r = swap;
      }
    }
    else
      {
 intptr_t mid;
 mid = r-l;
 mid = mid/2;
 srtg_AMergeSortIntern(a, l, l + mid, merge, AccessInt);
 srtg_AMergeSortIntern(a, l + mid + 1, r, merge, AccessInt);
 srtg_AMerge(a, l, l + mid, l + mid + 1, r, merge, AccessInt);
      }
  }
}
void srtg_AMergeSort(MEMORY mem, intptr_t *a, intptr_t *l, intptr_t *r, intptr_t (*AccessInt)(POINTER))
{
  if (l==r)
    return;
  if (l+1<=r) {
    if (l+1 == r) {
      if (AccessInt((POINTER)*l) > AccessInt((POINTER)*r)) {
 intptr_t swap;
 swap = *l;
 *l = *r;
 *r = swap;
      }
    }
    else
      {
 intptr_t length, *merge, mid;
 length = r-l+1;
 merge = (intptr_t *)memory_Malloc(mem, length * sizeof(intptr_t));
 mid = (length-1)/2;
 srtg_AMergeSortIntern(a, l, l + mid, merge, AccessInt);
 srtg_AMergeSortIntern(a, l + mid + 1, r, merge, AccessInt);
 srtg_AMerge(a, l, l + mid, l + mid + 1, r, merge, AccessInt);
 memory_Free(mem, merge, length * sizeof(intptr_t));
      }
  }
}
void srtg_AUMerge(intptr_t *a, intptr_t *lstart, intptr_t *lend, intptr_t *rstart, intptr_t *rend, intptr_t *merge, unsigned (*AccessInt)(POINTER))
{
  intptr_t *mergepos,*lfinal;
  mergepos = merge;
  lfinal = lstart;
  while (lstart <= lend && rstart <= rend) {
    if (AccessInt((POINTER)*lstart) > AccessInt((POINTER)*rstart)) {
      *mergepos = *rstart;
      rstart++;
      mergepos++;
    }
    else {
      *mergepos = *lstart;
      lstart++;
      mergepos++;
    }
  }
  while (lstart <= lend) {
    *mergepos = *lstart;
    lstart++;
    mergepos++;
  }
  while (merge < mergepos) {
    *lfinal = *merge;
    lfinal++;
    merge++;
  }
}
void srtg_AUMergeSortIntern(intptr_t *a, intptr_t *l, intptr_t *r, intptr_t *merge, unsigned (*AccessInt)(POINTER))
{
  if (l+1<=r) {
    if (l+1 == r) {
      if (AccessInt((POINTER)*l) > AccessInt((POINTER)*r)) {
 intptr_t swap;
 swap = *l;
 *l = *r;
 *r = swap;
      }
    }
    else
      {
 intptr_t mid;
 mid = r-l;
 mid = mid/2;
 srtg_AUMergeSortIntern(a, l, l + mid, merge, AccessInt);
 srtg_AUMergeSortIntern(a, l + mid + 1, r, merge, AccessInt);
 srtg_AUMerge(a, l, l + mid, l + mid + 1, r, merge, AccessInt);
      }
  }
}
void srtg_AUMergeSort(MEMORY mem, intptr_t *a, intptr_t *l, intptr_t *r, unsigned (*AccessInt)(POINTER))
{
  if (l==r)
    return;
  if (l+1<=r) {
    if (l+1 == r) {
      if (AccessInt((POINTER)*l) > AccessInt((POINTER)*r)) {
 intptr_t swap;
 swap = *l;
 *l = *r;
 *r = swap;
      }
    }
    else
      {
 intptr_t length, *merge, mid;
 length = r-l+1;
 merge = (intptr_t *)memory_Malloc(mem, length * sizeof(intptr_t));
 mid = (length-1)/2;
 srtg_AUMergeSortIntern(a, l, l + mid, merge, AccessInt);
 srtg_AUMergeSortIntern(a, l + mid + 1, r, merge, AccessInt);
 srtg_AUMerge(a, l, l + mid, l + mid + 1, r, merge, AccessInt);
 memory_Free(mem, merge, length * sizeof(intptr_t));
      }
  }
}
void srtg_AMergeWithState(intptr_t *a, intptr_t *lstart, intptr_t *lend, intptr_t *rstart, intptr_t *rend,
                          intptr_t *merge, int (*MergeCompare)(POINTER, POINTER, POINTER), intptr_t* state)
{
  intptr_t *mergepos,*lfinal;
  mergepos = merge;
  lfinal = lstart;
  while (lstart <= lend && rstart <= rend) {
    if (MergeCompare((POINTER)lstart, (POINTER) rstart, state) > 0) {
      *mergepos = *rstart;
      rstart++;
      mergepos++;
    }
    else {
      *mergepos = *lstart;
      lstart++;
      mergepos++;
    }
  }
  while (lstart <= lend) {
    *mergepos = *lstart;
    lstart++;
    mergepos++;
  }
  while (merge < mergepos) {
    *lfinal = *merge;
    lfinal++;
    merge++;
  }
}
void srtg_AMergeSortWithStateIntern(intptr_t *a, intptr_t *l, intptr_t *r, intptr_t *merge, int (*MergeCompare)(POINTER, POINTER, POINTER), intptr_t *state)
{
  if (l+1<=r) {
    if (l+1 == r) {
      if (MergeCompare((POINTER)l, (POINTER)r, state) > 0) {
        intptr_t swap;
        swap = *l;
        *l = *r;
        *r = swap;
      }
    }
    else
    {
      intptr_t mid;
      mid = r-l;
      mid = mid/2;
      srtg_AMergeSortWithStateIntern(a, l, l + mid, merge, MergeCompare, state);
      srtg_AMergeSortWithStateIntern(a, l + mid + 1, r, merge, MergeCompare, state);
      srtg_AMergeWithState(a, l, l + mid, l + mid + 1, r, merge, MergeCompare, state);
    }
  }
}
void srtg_AMergeSortWithState(MEMORY mem, intptr_t *a, intptr_t *l, intptr_t *r, int (*MergeCompare)(POINTER, POINTER, POINTER), intptr_t *state)
{
  if (l>=r)
    return;
  if (l+1<=r) {
    if (l+1 == r) {
      if (MergeCompare((POINTER)l, (POINTER)r, state) > 0) {
        intptr_t swap;
        swap = *l;
        *l = *r;
        *r = swap;
      }
    }
    else
    {
      intptr_t length, *merge, mid;
      length = r-l+1;
      merge = (intptr_t *)memory_Malloc(mem, length * sizeof(intptr_t));
      mid = (length-1)/2;
      srtg_AMergeSortWithStateIntern(a, l, l + mid, merge, MergeCompare, state);
      srtg_AMergeSortWithStateIntern(a, l + mid + 1, r, merge, MergeCompare, state);
      srtg_AMergeWithState(a, l, l + mid, l + mid + 1, r, merge, MergeCompare, state);
      memory_Free(mem, merge, length * sizeof(intptr_t));
    }
  }
}
void srtg_AMergeCompare(intptr_t *a, intptr_t *lstart, intptr_t *lend, intptr_t *rstart, intptr_t *rend,
                          intptr_t *merge, BOOL (*MergeCompare)(POINTER, POINTER))
{
  intptr_t *mergepos,*lfinal;
  mergepos = merge;
  lfinal = lstart;
  while (lstart <= lend && rstart <= rend) {
    if (MergeCompare((POINTER)lstart, (POINTER) rstart) > 0) {
      *mergepos = *rstart;
      rstart++;
      mergepos++;
    }
    else {
      *mergepos = *lstart;
      lstart++;
      mergepos++;
    }
  }
  while (lstart <= lend) {
    *mergepos = *lstart;
    lstart++;
    mergepos++;
  }
  while (merge < mergepos) {
    *lfinal = *merge;
    lfinal++;
    merge++;
  }
}
void srtg_AMergeSortCompareIntern(intptr_t *a, intptr_t *l, intptr_t *r, intptr_t *merge, BOOL (*MergeCompare)(POINTER, POINTER))
{
  if (l+1<=r) {
    if (l+1 == r) {
      if (MergeCompare((POINTER)l, (POINTER)r) > 0) {
        intptr_t swap;
        swap = *l;
        *l = *r;
        *r = swap;
      }
    }
    else
    {
      intptr_t mid;
      mid = r-l;
      mid = mid/2;
      srtg_AMergeSortCompareIntern(a, l, l + mid, merge, MergeCompare);
      srtg_AMergeSortCompareIntern(a, l + mid + 1, r, merge, MergeCompare);
      srtg_AMergeCompare(a, l, l + mid, l + mid + 1, r, merge, MergeCompare);
    }
  }
}
void srtg_AMergeSortCompare(MEMORY mem, intptr_t *a, intptr_t *l, intptr_t *r, BOOL (*MergeCompare)(POINTER, POINTER))
{
  if (l>=r)
    return;
  if (l+1<=r) {
    if (l+1 == r) {
      if (MergeCompare((POINTER)l, (POINTER)r) > 0) {
        intptr_t swap;
        swap = *l;
        *l = *r;
        *r = swap;
      }
    }
    else
    {
      intptr_t length, *merge, mid;
      length = r-l+1;
      merge = (intptr_t *)memory_Malloc(mem, length * sizeof(intptr_t));
      mid = (length-1)/2;
      srtg_AMergeSortCompareIntern(a, l, l + mid, merge, MergeCompare);
      srtg_AMergeSortCompareIntern(a, l + mid + 1, r, merge, MergeCompare);
      srtg_AMergeCompare(a, l, l + mid, l + mid + 1, r, merge, MergeCompare);
      memory_Free(mem, merge, length * sizeof(intptr_t));
    }
  }
}
