From 19405ef9e40fdc98aac2b7cf987326694f454610 Mon Sep 17 00:00:00 2001 From: asmhatre Date: Sun, 26 Jul 2026 11:46:16 +0000 Subject: [PATCH] Add image brightness + clamp kernel --- .../java/com/ankurm/vectorapi/Brightness.java | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 timings/src/main/java/com/ankurm/vectorapi/Brightness.java diff --git a/timings/src/main/java/com/ankurm/vectorapi/Brightness.java b/timings/src/main/java/com/ankurm/vectorapi/Brightness.java new file mode 100644 index 0000000..09cc70a --- /dev/null +++ b/timings/src/main/java/com/ankurm/vectorapi/Brightness.java @@ -0,0 +1,51 @@ +package com.ankurm.vectorapi; + +import jdk.incubator.vector.*; + +/** Image brightness: scale, bias, clamp to [0, 255]. The clamp is two branches. */ +public final class Brightness { + + static final VectorSpecies SP = FloatVector.SPECIES_PREFERRED; + + // Scalar: the clamp is two data-dependent branches + static void brightScalar(float[] in, float[] out, float gain, float bias) { + for (int i = 0; i < in.length; i++) { + float v = in[i] * gain + bias; + if (v < 0f) v = 0f; else if (v > 255f) v = 255f; + out[i] = v; + } + } + + static void brightVector(float[] in, float[] out, float gain, float bias) { + var vg = FloatVector.broadcast(SP, gain); + var vb = FloatVector.broadcast(SP, bias); + var lo = FloatVector.zero(SP); + var hi = FloatVector.broadcast(SP, 255f); + int i = 0, bound = SP.loopBound(in.length); + for (; i < bound; i += SP.length()) { + FloatVector.fromArray(SP, in, i).fma(vg, vb).max(lo).min(hi).intoArray(out, i); + } + for (; i < in.length; i++) { // scalar tail + float v = in[i] * gain + bias; + if (v < 0f) v = 0f; else if (v > 255f) v = 255f; + out[i] = v; + } + } + + static void run(int n) { + float[] in = Data.randomFloats(n, 4); + for (int i = 0; i < n; i++) in[i] = in[i] * 300f - 20f; // some pixels clamp at both ends + float[] o1 = new float[n], o2 = new float[n]; + brightScalar(in, o1, 1.4f, 12f); + brightVector(in, o2, 1.4f, 12f); + Data.assertSame("brightness", o1, o2); + + System.out.println("--- kernel 3: image brightness + clamp, " + n + " pixels ---"); + double s = Bench.measure("scalar (branchy clamp)", () -> brightScalar(in, o1, 1.4f, 12f)); + double v = Bench.measure("Vector API (max/min)", () -> brightVector(in, o2, 1.4f, 12f)); + Bench.speedup("vector advantage", s, v); + System.out.println(); + } + + private Brightness() {} +}