package com.arm.benchmarks;

import java.util.concurrent.TimeUnit;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;


@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@State(Scope.Benchmark)
public class IdealNegate {

    private static final int SIZE = 65536;
    private static long[] inputL = new long[SIZE];
    private static long[] outputL = new long[SIZE];
    private static long[] inputI = new long[SIZE];
    private static long[] outputI = new long[SIZE];

    @Setup
    public static void setup() {
        for (int i = 0; i < SIZE; i++) {
            inputL[i] = i;
            inputI[i] = i;
        }
    }

    @Benchmark
    public static void testNegateLong() {
        for (int i = 0; i < SIZE; i++) {
            outputL[i] = 0 - (inputL[i] >> 63);
        }
    }

    @Benchmark
    public static void testL2C2L() {
        for (int i = 0; i < SIZE; i++) {
            outputI[i] = 0 - (inputI[i] >> 31);
        }
    }

    @Benchmark
    public static void testSignExtractInt() {
        for (int i = 0; i < SIZE; i++) {
            outputI[i] = (inputI[i] >> 31) >>> 31;
        }
    }

    @Benchmark
    public static void testSignExtractLong() {
        for (int i = 0; i < SIZE; i++) {
            outputL[i] = (inputL[i] >> 63) >>> 63;
        }
    }
}
