import java.util.*;
import java.lang.*;
import java.io.*;
import java.util.function.*;
import java.awt.*;

class Util {
	public static IllegalArgumentException badArgf(String fmt, Object... args) {
		return new IllegalArgumentException(String.format(fmt, args));
	}

	public static String trace(Exception e) {
		StringWriter sw = new StringWriter();
		e.printStackTrace(new PrintWriter(sw));
		return sw.toString();
	}
}

class Benchmark
{
	public static class Result<T> {
		public final double time;
		public final T result;

		Result(double time, T result) {
			this.time = time;
			this.result = result;
		}
	}

	public static <T> Result<T> run(String title, Supplier<T> payload) {
		return run(title, payload, null);
	}

	public static <T> Result<T> run(String title, Supplier<T> payload, Result reference) {
		long start = System.nanoTime();
		var result = payload.get();
		double time = (System.nanoTime() - start) * 1e-9;
		System.out.println(String.format("%s: %.2f с%s",
			title, time, reference != null ? String.format(" (%s)", judgement(time, reference.time)) : ""));
		return new Result<T>(time, result);
	}

	static String judgement(double time, double refTime) {
		final double absThreshold = 0.07, relThreshold = .1;

		return time <= absThreshold || refTime <= absThreshold ?
			String.format("мин. время %.2f с", absThreshold) :
			Math.max(time, refTime) > (1 + relThreshold) * Math.min(time, refTime) ?
			String.format("%s на %.0f%%",
				time < refTime ? "быстрее" : "медленнее",
				Math.abs((time < refTime ? refTime / time : time / refTime) - 1) * 100) :
			String.format("<%.0f%% разницы", relThreshold * 100);
	}
}

class Main
{
	static boolean verifyColors(int[] colors, int[] ref, String name, int[] orig) {
		final int MAX_ERROR = 0;
		for (int i = 0; i < colors.length; i++) {
			if ((colors[i] >> 24) != (ref[i] >> 24) ||
				Math.abs((colors[i] >> 16 & 0xFF) - (ref[i] >> 16 & 0xFF)) > MAX_ERROR ||
				Math.abs((colors[i] >> 8 & 0xFF) - (ref[i] >> 8 & 0xFF)) > MAX_ERROR ||
				Math.abs((colors[i] & 0xFF) - (ref[i] & 0xFF)) > MAX_ERROR) {

				System.out.printf(
					"%s не соответствует референсу (#%d = %06X <-> %06X, ориг. %06X).\n",
					name, i, colors[i], ref[i], orig[i]);
				return false;
			}
		}
		return true;
	}

	static void benchmark() {
		var rand = new Random(1);
		int[] colors = new int[10_000_000];
		for (int i = 0; i < colors.length; i++) {
			colors[i] = rand.nextInt(0x1_00_00_00);
		}
		final float alpha = Math.round(0.234f * 255) / 255f;

		int[] resultColors0 = new int[colors.length],
			resultColors1 = new int[colors.length],
			resultColors2 = new int[colors.length];

		final int TRIALS = 3, AMPLIFY = 9;
		for (int iTrial = 0; iTrial < TRIALS; iTrial++) {
			System.out.printf("%s--- ПОПЫТКА %d/%d ---\n", iTrial > 0 ? "\n" : "", 1 + iTrial, TRIALS);

			var ref = Benchmark.run("RGBtoHSB + HSBtoRGB",
				() -> {
					final float alphaLocal = alpha;
					float[] hsb = new float[3];
					for (int iAmp = 0; iAmp < AMPLIFY; iAmp++) {
						for (int i = 0; i < colors.length; i++) {
							int irgb = colors[i];
							Color.RGBtoHSB(irgb >> 16 & 0xFF, irgb >> 8 & 0xFF, irgb & 0xFF, hsb);
							resultColors0[i] = Color.HSBtoRGB(hsb[0], hsb[1], hsb[2] * alphaLocal);
						}
					}
					return resultColors0;
				});

			String name1 = "(int) (component * alpha + .5f)";
			Benchmark.run(name1,
				() -> {
					final float alphaLocal = alpha;
					for (int iAmp = 0; iAmp < AMPLIFY; iAmp++) {
						for (int i = 0; i < colors.length; i++) {
							int irgb = colors[i];
							resultColors1[i] =
								(int) ((irgb >> 16 & 0xFF) * alphaLocal + .5f) << 16 |
								(int) ((irgb >> 8 & 0xFF) * alphaLocal + .5f) << 8 |
								(int) ((irgb & 0xFF) * alphaLocal + .5f) |
								0xFF000000;
						}
					}
					return resultColors1;
				}, ref);

			String name2 = "((component * alpha10 + 512) >> 10)";
			Benchmark.run(name2,
				() -> {
					final int alpha10 = (int) (alpha * 1024 + .5f);

					for (int iAmp = 0; iAmp < AMPLIFY; iAmp++) {
						for (int i = 0; i < colors.length; i++) {
							int irgb = colors[i];
							resultColors2[i] =
								(((irgb >> 16 & 0xFF) * alpha10 + 512) >> 10) << 16 |
								(((irgb >> 8 & 0xFF) * alpha10 + 512) >> 10) << 8 |
								(((irgb & 0xFF) * alpha10 + 512) >> 10) |
								0xFF000000;
						}
					}
					return resultColors2;
				}, ref);

			if (iTrial == 0) {
				if (!verifyColors(resultColors1, resultColors0, name1, colors) |
					!verifyColors(resultColors2, resultColors0, name2, colors))
					return;

				System.out.printf("Результат корректен (%06X, %06X, %06X, ...).\n",
					resultColors0[0], resultColors0[1], resultColors0[2]);
			}
		}
	}

	public static void main (String[] args) throws java.lang.Exception
	{
		try {
			benchmark();
		} catch (Exception e) {
			System.out.println(Util.trace(e));
		}
	}
}