import java.util.*;
import java.lang.*;
import java.io.*;
import java.util.function.*;
import java.awt.*;
}
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
; 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
) ? 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
) {
"%s не соответствует референсу (#%d = %06X <-> %06X, ориг. %06X).\n",
name, i, colors[i], ref[i], orig[i]);
return false;
}
}
return true;
}
static void benchmark() {
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]);
}
}
}
{
try {
benchmark();
}
}
}
aW1wb3J0IGphdmEudXRpbC4qOwppbXBvcnQgamF2YS5sYW5nLio7CmltcG9ydCBqYXZhLmlvLio7CmltcG9ydCBqYXZhLnV0aWwuZnVuY3Rpb24uKjsKaW1wb3J0IGphdmEuYXd0Lio7CgpjbGFzcyBVdGlsIHsKCXB1YmxpYyBzdGF0aWMgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uIGJhZEFyZ2YoU3RyaW5nIGZtdCwgT2JqZWN0Li4uIGFyZ3MpIHsKCQlyZXR1cm4gbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbihTdHJpbmcuZm9ybWF0KGZtdCwgYXJncykpOwoJfQoKCXB1YmxpYyBzdGF0aWMgU3RyaW5nIHRyYWNlKEV4Y2VwdGlvbiBlKSB7CgkJU3RyaW5nV3JpdGVyIHN3ID0gbmV3IFN0cmluZ1dyaXRlcigpOwoJCWUucHJpbnRTdGFja1RyYWNlKG5ldyBQcmludFdyaXRlcihzdykpOwoJCXJldHVybiBzdy50b1N0cmluZygpOwoJfQp9CgpjbGFzcyBCZW5jaG1hcmsKewoJcHVibGljIHN0YXRpYyBjbGFzcyBSZXN1bHQ8VD4gewoJCXB1YmxpYyBmaW5hbCBkb3VibGUgdGltZTsKCQlwdWJsaWMgZmluYWwgVCByZXN1bHQ7CgoJCVJlc3VsdChkb3VibGUgdGltZSwgVCByZXN1bHQpIHsKCQkJdGhpcy50aW1lID0gdGltZTsKCQkJdGhpcy5yZXN1bHQgPSByZXN1bHQ7CgkJfQoJfQoKCXB1YmxpYyBzdGF0aWMgPFQ+IFJlc3VsdDxUPiBydW4oU3RyaW5nIHRpdGxlLCBTdXBwbGllcjxUPiBwYXlsb2FkKSB7CgkJcmV0dXJuIHJ1bih0aXRsZSwgcGF5bG9hZCwgbnVsbCk7Cgl9CgoJcHVibGljIHN0YXRpYyA8VD4gUmVzdWx0PFQ+IHJ1bihTdHJpbmcgdGl0bGUsIFN1cHBsaWVyPFQ+IHBheWxvYWQsIFJlc3VsdCByZWZlcmVuY2UpIHsKCQlsb25nIHN0YXJ0ID0gU3lzdGVtLm5hbm9UaW1lKCk7CgkJdmFyIHJlc3VsdCA9IHBheWxvYWQuZ2V0KCk7CgkJZG91YmxlIHRpbWUgPSAoU3lzdGVtLm5hbm9UaW1lKCkgLSBzdGFydCkgKiAxZS05OwoJCVN5c3RlbS5vdXQucHJpbnRsbihTdHJpbmcuZm9ybWF0KCIlczogJS4yZiDRgSVzIiwKCQkJdGl0bGUsIHRpbWUsIHJlZmVyZW5jZSAhPSBudWxsID8gU3RyaW5nLmZvcm1hdCgiICglcykiLCBqdWRnZW1lbnQodGltZSwgcmVmZXJlbmNlLnRpbWUpKSA6ICIiKSk7CgkJcmV0dXJuIG5ldyBSZXN1bHQ8VD4odGltZSwgcmVzdWx0KTsKCX0KCglzdGF0aWMgU3RyaW5nIGp1ZGdlbWVudChkb3VibGUgdGltZSwgZG91YmxlIHJlZlRpbWUpIHsKCQlmaW5hbCBkb3VibGUgYWJzVGhyZXNob2xkID0gMC4wNywgcmVsVGhyZXNob2xkID0gLjE7CgoJCXJldHVybiB0aW1lIDw9IGFic1RocmVzaG9sZCB8fCByZWZUaW1lIDw9IGFic1RocmVzaG9sZCA/CgkJCVN0cmluZy5mb3JtYXQoItC80LjQvS4g0LLRgNC10LzRjyAlLjJmINGBIiwgYWJzVGhyZXNob2xkKSA6CgkJCU1hdGgubWF4KHRpbWUsIHJlZlRpbWUpID4gKDEgKyByZWxUaHJlc2hvbGQpICogTWF0aC5taW4odGltZSwgcmVmVGltZSkgPwoJCQlTdHJpbmcuZm9ybWF0KCIlcyDQvdCwICUuMGYlJSIsCgkJCQl0aW1lIDwgcmVmVGltZSA/ICLQsdGL0YHRgtGA0LXQtSIgOiAi0LzQtdC00LvQtdC90L3QtdC1IiwKCQkJCU1hdGguYWJzKCh0aW1lIDwgcmVmVGltZSA/IHJlZlRpbWUgLyB0aW1lIDogdGltZSAvIHJlZlRpbWUpIC0gMSkgKiAxMDApIDoKCQkJU3RyaW5nLmZvcm1hdCgiPCUuMGYlJSDRgNCw0LfQvdC40YbRiyIsIHJlbFRocmVzaG9sZCAqIDEwMCk7Cgl9Cn0KCmNsYXNzIE1haW4KewoJc3RhdGljIGJvb2xlYW4gdmVyaWZ5Q29sb3JzKGludFtdIGNvbG9ycywgaW50W10gcmVmLCBTdHJpbmcgbmFtZSwgaW50W10gb3JpZykgewoJCWZpbmFsIGludCBNQVhfRVJST1IgPSAwOwoJCWZvciAoaW50IGkgPSAwOyBpIDwgY29sb3JzLmxlbmd0aDsgaSsrKSB7CgkJCWlmICgoY29sb3JzW2ldID4+IDI0KSAhPSAocmVmW2ldID4+IDI0KSB8fAoJCQkJTWF0aC5hYnMoKGNvbG9yc1tpXSA+PiAxNiAmIDB4RkYpIC0gKHJlZltpXSA+PiAxNiAmIDB4RkYpKSA+IE1BWF9FUlJPUiB8fAoJCQkJTWF0aC5hYnMoKGNvbG9yc1tpXSA+PiA4ICYgMHhGRikgLSAocmVmW2ldID4+IDggJiAweEZGKSkgPiBNQVhfRVJST1IgfHwKCQkJCU1hdGguYWJzKChjb2xvcnNbaV0gJiAweEZGKSAtIChyZWZbaV0gJiAweEZGKSkgPiBNQVhfRVJST1IpIHsKCgkJCQlTeXN0ZW0ub3V0LnByaW50ZigKCQkJCQkiJXMg0L3QtSDRgdC+0L7RgtCy0LXRgtGB0YLQstGD0LXRgiDRgNC10YTQtdGA0LXQvdGB0YMgKCMlZCA9ICUwNlggPC0+ICUwNlgsINC+0YDQuNCzLiAlMDZYKS5cbiIsCgkJCQkJbmFtZSwgaSwgY29sb3JzW2ldLCByZWZbaV0sIG9yaWdbaV0pOwoJCQkJcmV0dXJuIGZhbHNlOwoJCQl9CgkJfQoJCXJldHVybiB0cnVlOwoJfQoKCXN0YXRpYyB2b2lkIGJlbmNobWFyaygpIHsKCQl2YXIgcmFuZCA9IG5ldyBSYW5kb20oMSk7CgkJaW50W10gY29sb3JzID0gbmV3IGludFsxMF8wMDBfMDAwXTsKCQlmb3IgKGludCBpID0gMDsgaSA8IGNvbG9ycy5sZW5ndGg7IGkrKykgewoJCQljb2xvcnNbaV0gPSByYW5kLm5leHRJbnQoMHgxXzAwXzAwXzAwKTsKCQl9CgkJZmluYWwgZmxvYXQgYWxwaGEgPSBNYXRoLnJvdW5kKDAuMjM0ZiAqIDI1NSkgLyAyNTVmOwoKCQlpbnRbXSByZXN1bHRDb2xvcnMwID0gbmV3IGludFtjb2xvcnMubGVuZ3RoXSwKCQkJcmVzdWx0Q29sb3JzMSA9IG5ldyBpbnRbY29sb3JzLmxlbmd0aF0sCgkJCXJlc3VsdENvbG9yczIgPSBuZXcgaW50W2NvbG9ycy5sZW5ndGhdOwoKCQlmaW5hbCBpbnQgVFJJQUxTID0gMywgQU1QTElGWSA9IDk7CgkJZm9yIChpbnQgaVRyaWFsID0gMDsgaVRyaWFsIDwgVFJJQUxTOyBpVHJpYWwrKykgewoJCQlTeXN0ZW0ub3V0LnByaW50ZigiJXMtLS0g0J/QntCf0KvQotCa0JAgJWQvJWQgLS0tXG4iLCBpVHJpYWwgPiAwID8gIlxuIiA6ICIiLCAxICsgaVRyaWFsLCBUUklBTFMpOwoKCQkJdmFyIHJlZiA9IEJlbmNobWFyay5ydW4oIlJHQnRvSFNCICsgSFNCdG9SR0IiLAoJCQkJKCkgLT4gewoJCQkJCWZpbmFsIGZsb2F0IGFscGhhTG9jYWwgPSBhbHBoYTsKCQkJCQlmbG9hdFtdIGhzYiA9IG5ldyBmbG9hdFszXTsKCQkJCQlmb3IgKGludCBpQW1wID0gMDsgaUFtcCA8IEFNUExJRlk7IGlBbXArKykgewoJCQkJCQlmb3IgKGludCBpID0gMDsgaSA8IGNvbG9ycy5sZW5ndGg7IGkrKykgewoJCQkJCQkJaW50IGlyZ2IgPSBjb2xvcnNbaV07CgkJCQkJCQlDb2xvci5SR0J0b0hTQihpcmdiID4+IDE2ICYgMHhGRiwgaXJnYiA+PiA4ICYgMHhGRiwgaXJnYiAmIDB4RkYsIGhzYik7CgkJCQkJCQlyZXN1bHRDb2xvcnMwW2ldID0gQ29sb3IuSFNCdG9SR0IoaHNiWzBdLCBoc2JbMV0sIGhzYlsyXSAqIGFscGhhTG9jYWwpOwoJCQkJCQl9CgkJCQkJfQoJCQkJCXJldHVybiByZXN1bHRDb2xvcnMwOwoJCQkJfSk7CgoJCQlTdHJpbmcgbmFtZTEgPSAiKGludCkgKGNvbXBvbmVudCAqIGFscGhhICsgLjVmKSI7CgkJCUJlbmNobWFyay5ydW4obmFtZTEsCgkJCQkoKSAtPiB7CgkJCQkJZmluYWwgZmxvYXQgYWxwaGFMb2NhbCA9IGFscGhhOwoJCQkJCWZvciAoaW50IGlBbXAgPSAwOyBpQW1wIDwgQU1QTElGWTsgaUFtcCsrKSB7CgkJCQkJCWZvciAoaW50IGkgPSAwOyBpIDwgY29sb3JzLmxlbmd0aDsgaSsrKSB7CgkJCQkJCQlpbnQgaXJnYiA9IGNvbG9yc1tpXTsKCQkJCQkJCXJlc3VsdENvbG9yczFbaV0gPQoJCQkJCQkJCShpbnQpICgoaXJnYiA+PiAxNiAmIDB4RkYpICogYWxwaGFMb2NhbCArIC41ZikgPDwgMTYgfAoJCQkJCQkJCShpbnQpICgoaXJnYiA+PiA4ICYgMHhGRikgKiBhbHBoYUxvY2FsICsgLjVmKSA8PCA4IHwKCQkJCQkJCQkoaW50KSAoKGlyZ2IgJiAweEZGKSAqIGFscGhhTG9jYWwgKyAuNWYpIHwKCQkJCQkJCQkweEZGMDAwMDAwOwoJCQkJCQl9CgkJCQkJfQoJCQkJCXJldHVybiByZXN1bHRDb2xvcnMxOwoJCQkJfSwgcmVmKTsKCgkJCVN0cmluZyBuYW1lMiA9ICIoKGNvbXBvbmVudCAqIGFscGhhMTAgKyA1MTIpID4+IDEwKSI7CgkJCUJlbmNobWFyay5ydW4obmFtZTIsCgkJCQkoKSAtPiB7CgkJCQkJZmluYWwgaW50IGFscGhhMTAgPSAoaW50KSAoYWxwaGEgKiAxMDI0ICsgLjVmKTsKCgkJCQkJZm9yIChpbnQgaUFtcCA9IDA7IGlBbXAgPCBBTVBMSUZZOyBpQW1wKyspIHsKCQkJCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBjb2xvcnMubGVuZ3RoOyBpKyspIHsKCQkJCQkJCWludCBpcmdiID0gY29sb3JzW2ldOwoJCQkJCQkJcmVzdWx0Q29sb3JzMltpXSA9CgkJCQkJCQkJKCgoaXJnYiA+PiAxNiAmIDB4RkYpICogYWxwaGExMCArIDUxMikgPj4gMTApIDw8IDE2IHwKCQkJCQkJCQkoKChpcmdiID4+IDggJiAweEZGKSAqIGFscGhhMTAgKyA1MTIpID4+IDEwKSA8PCA4IHwKCQkJCQkJCQkoKChpcmdiICYgMHhGRikgKiBhbHBoYTEwICsgNTEyKSA+PiAxMCkgfAoJCQkJCQkJCTB4RkYwMDAwMDA7CgkJCQkJCX0KCQkJCQl9CgkJCQkJcmV0dXJuIHJlc3VsdENvbG9yczI7CgkJCQl9LCByZWYpOwoKCQkJaWYgKGlUcmlhbCA9PSAwKSB7CgkJCQlpZiAoIXZlcmlmeUNvbG9ycyhyZXN1bHRDb2xvcnMxLCByZXN1bHRDb2xvcnMwLCBuYW1lMSwgY29sb3JzKSB8CgkJCQkJIXZlcmlmeUNvbG9ycyhyZXN1bHRDb2xvcnMyLCByZXN1bHRDb2xvcnMwLCBuYW1lMiwgY29sb3JzKSkKCQkJCQlyZXR1cm47CgoJCQkJU3lzdGVtLm91dC5wcmludGYoItCg0LXQt9GD0LvRjNGC0LDRgiDQutC+0YDRgNC10LrRgtC10L0gKCUwNlgsICUwNlgsICUwNlgsIC4uLikuXG4iLAoJCQkJCXJlc3VsdENvbG9yczBbMF0sIHJlc3VsdENvbG9yczBbMV0sIHJlc3VsdENvbG9yczBbMl0pOwoJCQl9CgkJfQoJfQoKCXB1YmxpYyBzdGF0aWMgdm9pZCBtYWluIChTdHJpbmdbXSBhcmdzKSB0aHJvd3MgamF2YS5sYW5nLkV4Y2VwdGlvbgoJewoJCXRyeSB7CgkJCWJlbmNobWFyaygpOwoJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCVN5c3RlbS5vdXQucHJpbnRsbihVdGlsLnRyYWNlKGUpKTsKCQl9Cgl9Cn0=