using System;
namespace Legalsoft.Truffer
{
public class Sorter
{
public Sorter() { }
public static void sort(double[] arr)
{
sort(arr, -1);
}
public static void sort(double[] arr, int m = -1)
{
const int M = 7;
const int NSTACK = 64;
int jstack = -1;
int l = 0;
int n = arr.Length;
double a;
int[] istack = new int[NSTACK];
if (m > 0)
{
n = Math.Min(m, n);
}
int ir = n - 1;
for (; ; )
{
if (ir - l < M)
{
for (int j = l + 1; j <= ir; j++)
{
a = arr[j];
int i = j - 1;
for (; i >= l; i--)
{
//if (arr[i].CompareTo(a) <= 0)
if (arr[i] <= a)
{
break;
}
arr[i + 1] = arr[i];
}
arr[i + 1] = a;
}
if (jstack < 0)
{
break;
}
ir = istack[jstack--];
l = istack[jstack--];
}
else
{
int k = (l + ir) >> 1;
Globals.SWAP(ref arr[k], ref arr[l + 1]);
if (arr[l] > arr[ir])
{
Globals.SWAP(ref arr[l], ref arr[ir]);
}
if (arr[l + 1] > arr[ir])
{
Globals.SWAP(ref arr[l + 1], ref arr[ir]);
}
if (arr[l] > arr[l + 1])
{
Globals.SWAP(ref arr[l], ref arr[l + 1]);
}
int i = l + 1;
int j = ir;
a = arr[l + 1];
for (; ; )
{
do
{
i++;
} while (arr[i] < a);
do
{
j--;
} while (arr[j] > a);
if (j < i)
{
break;
}
Globals.SWAP(ref arr[i], ref arr[j]);
}
arr[l + 1] = arr[j];
arr[j] = a;
jstack += 2;
if (jstack >= NSTACK)
{
throw new Exception("NSTACK too small in sort.");
}
if (ir - i + 1 >= j - l)
{
istack[jstack] = ir;
istack[jstack - 1] = i;
ir = j - 1;
}
else
{
istack[jstack] = j - 1;
istack[jstack - 1] = l;
l = i;
}
}
}
}
public static void hpsort(double[] ra)
{
int n = ra.Length;
for (int i = n / 2 - 1; i >= 0; i--)
{
sift_down(ra, i, n - 1);
}
for (int i = n - 1; i > 0; i--)
{
Globals.SWAP(ref ra[0], ref ra[i]);
sift_down(ra, 0, i - 1);
}
}
public static void sift_down(double[] ra, int l, int r)
{
double a = ra[l];
int jold = l;
int j = 2 * l + 1;
while (j <= r)
{
if (j < r && ra[j] < ra[j + 1])
{
j++;
}
if (a >= ra[j])
{
break;
}
ra[jold] = ra[j];
jold = j;
j = 2 * j + 1;
}
ra[jold] = a;
}
public static void piksrt(double[] arr)
{
int n = arr.Length;
for (int j = 1; j < n; j++)
{
double a = arr[j];
int i = j;
while (i > 0 && arr[i - 1] > a)
{
arr[i] = arr[i - 1];
i--;
}
arr[i] = a;
}
}
public static void piksr2(double[] arr, double[] brr)
{
int n = arr.Length;
for (int j = 1; j < n; j++)
{
double a = arr[j];
double b = brr[j];
int i = j;
while (i > 0 && arr[i - 1] > a)
{
arr[i] = arr[i - 1];
brr[i] = brr[i - 1];
i--;
}
arr[i] = a;
brr[i] = b;
}
}
public static double select(int k, double[] arr)
{
int n = arr.Length;
double a;
int l = 0;
int ir = n - 1;
for (; ; )
{
if (ir <= l + 1)
{
if (ir == l + 1 && arr[ir] < arr[l])
{
Globals.SWAP(ref arr[l], ref arr[ir]);
}
return arr[k];
}
else
{
int mid = (l + ir) >> 1;
Globals.SWAP(ref arr[mid], ref arr[l + 1]);
if (arr[l] > arr[ir])
{
Globals.SWAP(ref arr[l], ref arr[ir]);
}
if (arr[l + 1] > arr[ir])
{
Globals.SWAP(ref arr[l + 1], ref arr[ir]);
}
if (arr[l] > arr[l + 1])
{
Globals.SWAP(ref arr[l], ref arr[l + 1]);
}
int i = l + 1;
int j = ir;
a = arr[l + 1];
for (; ; )
{
do
{
i++;
} while (arr[i] < a);
do
{
j--;
} while (arr[j] > a);
if (j < i)
{
break;
}
Globals.SWAP(ref arr[i], ref arr[j]);
}
arr[l + 1] = arr[j];
arr[j] = a;
if (j >= k)
{
ir = j - 1;
}
if (j <= k)
{
l = i;
}
}
}
}
public static void shell(double[] a, int m = -1)
{
int n = a.Length;
if (m > 0)
{
n = Math.Min(m, n);
}
int inc = 1;
do
{
inc *= 3;
inc++;
} while (inc <= n);
do
{
inc /= 3;
for (int i = inc; i < n; i++)
{
double v = a[i];
int j = i;
//if (a[j - inc].CompareTo(v) > 0)
while (a[j - inc] > v)
{
a[j] = a[j - inc];
j -= inc;
if (j < inc)
{
break;
}
}
a[j] = v;
}
} while (inc > 1);
}
public static void sort2(double[] arr, double[] brr)
{
const int M = 7;
const int NSTACK = 64;
int jstack = -1;
int l = 0;
int n = arr.Length;
int[] istack = new int[NSTACK];
int ir = n - 1;
for (; ; )
{
if (ir - l < M)
{
for (int j = l + 1; j <= ir; j++)
{
double a = arr[j];
double b = brr[j];
int i = j - 1;
for (; i >= l; i--)
{
if (arr[i] <= a)
{
break;
}
arr[i + 1] = arr[i];
brr[i + 1] = brr[i];
}
arr[i + 1] = a;
brr[i + 1] = b;
}
if (jstack < 0)
{
break;
}
ir = istack[jstack--];
l = istack[jstack--];
}
else
{
int k = (l + ir) >> 1;
Globals.SWAP(ref arr[k], ref arr[l + 1]);
Globals.SWAP(ref brr[k], ref brr[l + 1]);
if (arr[l] > arr[ir])
{
Globals.SWAP(ref arr[l], ref arr[ir]);
Globals.SWAP(ref brr[l], ref brr[ir]);
}
if (arr[l + 1] > arr[ir])
{
Globals.SWAP(ref arr[l + 1], ref arr[ir]);
Globals.SWAP(ref brr[l + 1], ref brr[ir]);
}
if (arr[l] > arr[l + 1])
{
Globals.SWAP(ref arr[l], ref arr[l + 1]);
Globals.SWAP(ref brr[l], ref brr[l + 1]);
}
int i = l + 1;
int j = ir;
double a = arr[l + 1];
double b = brr[l + 1];
for (; ; )
{
do
{
i++;
} while (arr[i] < a);
do
{
j--;
} while (arr[j] > a);
if (j < i)
{
break;
}
Globals.SWAP(ref arr[i], ref arr[j]);
Globals.SWAP(ref brr[i], ref brr[j]);
}
arr[l + 1] = arr[j];
arr[j] = a;
brr[l + 1] = brr[j];
brr[j] = b;
jstack += 2;
if (jstack >= NSTACK)
{
throw new Exception("NSTACK too small in sort2.");
}
if (ir - i + 1 >= j - l)
{
istack[jstack] = ir;
istack[jstack - 1] = i;
ir = j - 1;
}
else
{
istack[jstack] = j - 1;
istack[jstack - 1] = l;
l = i;
}
}
}
}
///
/// select Mth largest in place
///
///
///
///
///
public static double selip(int k, double[] arr)
{
const int M = 64;
const double BIG = 9.99e99;
int n = arr.Length;
int[] isel = new int[M + 2];
double[] sel = new double[M + 2];
if (k < 0 || k > n - 1)
{
throw new Exception("bad input to selip");
}
int kk = k;
double ahi = BIG;
double alo = -BIG;
for (; ; )
{
int mm = 0;
int nlo = 0;
double sum = 0.0;
int nxtmm = M + 1;
for (int i = 0; i < n; i++)
{
if (arr[i] >= alo && arr[i] <= ahi)
{
mm++;
//if (arr[i] == alo)
if (Math.Abs(arr[i] - alo) <= float.Epsilon)
{
nlo++;
}
if (mm <= M)
{
sel[mm - 1] = arr[i];
}
else if (mm == nxtmm)
{
nxtmm = mm + mm / M;
sel[(i + 2 + mm + kk) % M] = arr[i];
}
sum += arr[i];
}
}
if (kk < nlo)
{
return alo;
}
else if (mm < M + 1)
{
shell(sel, mm);
ahi = sel[kk];
return ahi;
}
sel[M] = sum / mm;
shell(sel, M + 1);
sel[M + 1] = ahi;
int j = 0;
for (; j < M + 2; j++)
{
isel[j] = 0;
}
for (int i = 0; i < n; i++)
{
if (arr[i] >= alo && arr[i] <= ahi)
{
int jl = 0;
int ju = M + 2;
while (ju - jl > 1)
{
int jm = (ju + jl) / 2;
if (arr[i] >= sel[jm - 1])
{
jl = jm;
}
else
{
ju = jm;
}
}
isel[ju - 1]++;
}
}
j = 0;
while (kk >= isel[j])
{
alo = sel[j];
kk -= isel[j++];
}
ahi = sel[j];
}
}
}
}