package ru.ifmo.nds.jmh.internal;

import java.util.Random;
import java.util.concurrent.TimeUnit;

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;

import ru.ifmo.nds.util.ArrayHelper;

@State(Scope.Benchmark)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@Timeout(time = 10)
@Warmup(time = 1, iterations = 10)
@Measurement(time = 1, iterations = 3)
@Fork(value = 3)
public class SortIndicesByValuesBenchmark {
    @Param({"2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20",
            "21", "22", "23", "24", "25", "30", "35", "40", "50", "60", "70", "80", "90", "100", "1000", "10000", "100000"})
    private int size;

    @Param({"10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25"})
    private int threshold;

    private int[][] data;
    private int[] indices;

    @Setup
    public void initialize() {
        int nInstances = 10;
        Random random = new Random(size * 318325462111L);
        data = new int[nInstances][size];
        for (int i = 0; i < nInstances; ++i) {
            for (int j = 0; j < size; ++j) {
                data[i][j] = random.nextInt();
            }
        }
        indices = new int[size];
    }

    @Benchmark
    public void run(Blackhole bh) {
        for (int[] instance : data) {
            ArrayHelper.fillIdentity(indices, size);
            sortIndicesByValues(indices, instance, 0, size);
        }
    }

    private static int splitIndicesByRanks(int[] indices, int[] values, int from, int until) {
        int left = from, right = until - 1;
        int pivot = values[indices[(from + until) >>> 1]];
        int sl, sr;
        while (left <= right) {
            while (values[sl = indices[left]] < pivot) ++left;
            while (values[sr = indices[right]] > pivot) --right;
            if (left <= right) {
                indices[left] = sr;
                indices[right] = sl;
                ++left;
                --right;
            }
        }
        return left - 1 == right ? left : -left - 1;
    }

    private static void insertionSortIndicesByValues(int[] indices, int[] values, int from, int to) {
        for (int i = from, j = i; i < to; j = i) {
            int ii = indices[++i], ij;
            int ai = values[ii];
            while (ai < values[ij = indices[j]]) {
                indices[j + 1] = ij;
                if (--j < from) {
                    break;
                }
            }
            indices[j + 1] = ii;
        }
    }

    private void sortIndicesByValues(int[] indices, int[] values, int from, int until) {
        if (from + threshold > until) {
            insertionSortIndicesByValues(indices, values, from, until - 1);
        } else {
            int left = splitIndicesByRanks(indices, values, from, until);
            int right = left;
            if (left < 0) {
                left = -left - 1;
                right = left - 1;
            }
            if (from + 1 < right) {
                sortIndicesByValues(indices, values, from, right);
            }
            if (left + 1 < until) {
                sortIndicesByValues(indices, values, left, until);
            }
        }
    }
}

@@ -356,18 +356,17 @@
 tions = 
-10
+6
 )%0A@Measu
@@ -395,17 +395,17 @@
 tions = 
-3
+2
 )%0A@Fork(
@@ -412,17 +412,17 @@
 value = 
-3
+5
 )%0Apublic
@@ -476,234 +476,117 @@
 m(%7B%22
-2%22, %223%22, %224%22, %225%22, %226%22, %227%22, %228%22, %229%22, %2210%22, %2211%22, %221
+1%22, %22
 2%22, %22
-1
 3%22, %22
-1
 4%22, %22
-1
 5%22, %22
-16%22, %2217%22, %2218%22, %2219%22, %2220%22,%0A            %2221%22, %2222%22, %222
+7%22, %2210%22, %221
 3%22, %22
-24
+17
 %22, %222
-5%22, %2230
+3
 %22, %223
-5
+1
 %22, %224
-0
+2
 %22, %225
-0%22, %2260
+6
 %22, %227
-0
+4
 %22, %22
-80%22, %229
+10
 0%22, %221
-00
+33
 %22, %221
-000
+77
 %22, %22
-10000%22, %22100000
+237%22, %22316
 %22%7D)%0A
@@ -632,93 +632,93 @@
 , %221
-1
+2
 %22, %221
-2
+4
 %22, %221
-3
+6
 %22, %221
-4
+8
 %22, %22
-15
+20
 %22, %22
-16
+22
 %22, %22
-17
+24
 %22, %22
-18
+26
 %22, %22
-19
+28
 %22, %22
-2
+3
 0%22, %22
+3
 2
-1
 %22, %22
-22
+34
 %22, %22
-2
 3
+6
 %22, %22
-24
+38
 %22, %22
-25
+40
 %22%7D)%0A
@@ -868,16 +868,17 @@
 ces = 10
+0
 ;%0A      
@@ -1170,24 +1170,58 @@
 ze%5D;%0A    %7D%0A%0A
+    @OperationsPerInvocation(100)%0A
     @Benchma

Update the benchmark parameters to reflect the region of interest.