<commit_before>package jocltest;

import static java.lang.Math.max;
import static java.lang.Math.min;
import static jocltest.JOCLConvolution2D.Denormalize.denormalizeTo;
import static net.sourceforge.aprog.tools.Tools.ignore;

import imj.cl.CLContext;
import imj.cl.CLKernel;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import javax.imageio.ImageIO;

import org.jocl.CL;
import org.jocl.Sizeof;

import net.sourceforge.aprog.tools.CommandLineArgumentsParser;
import net.sourceforge.aprog.tools.IllegalInstantiationException;
import net.sourceforge.aprog.tools.Tools;
import net.sourceforge.aprog.tools.MathTools.Statistics;

/**
 * @author codistmonk (creation 2014-12-07)
 */
public final class JOCLConvolution2D {
	
	private JOCLConvolution2D() {
		throw new IllegalInstantiationException();
	}
	
    public static final String PROGRAM_SOURCE =
            "__kernel void "
            + "convolution2D(__global const float * input,"
            + "             __global const int * inputDimensions,"
            + "             __global const int * step,"
            + "             __global const float * convolutions,"
            + "             __global const int * convolutionsDimensions,"
            + "             __global float * output)"
            + "{\n"
            + "	const int gid = get_global_id(0);\n"
            + "	const int inputChannels = inputDimensions[0];\n"
            + "	const int inputWidth = inputDimensions[1];\n"
            + "	const int inputHeight = inputDimensions[2];\n"
            + "	const int s = *step;\n"
            + "	const int convolutionCount = convolutionsDimensions[0];\n"
            + "	const int convolutionWidth = convolutionsDimensions[1];\n"
            + "	const int convolutionHeight = convolutionsDimensions[2];\n"
            + "	const int convolutionSize = convolutionWidth * convolutionHeight * inputChannels;\n"
            + "	const int x = s * (gid % (inputWidth / s));\n"
            + "	const int y = s * (gid / (inputWidth / s));\n"
            + "	const int virtualLeft = x + 1 - (convolutionWidth / 2);\n"
            + "	const int virtualRight = virtualLeft + convolutionWidth;\n"
            + "	const int virtualTop = y + 1 - (convolutionHeight / 2);\n"
            + "	const int virtualBottom = virtualTop + convolutionHeight;\n"
            + "	const int left = max(0, virtualLeft);\n"
            + "	const int right = min(virtualRight, inputWidth) - 1;\n"
            + "	const int top = max(0, virtualTop);\n"
            + "	const int bottom = min(virtualBottom, inputHeight) - 1;\n"
            + "	const int cleft = left - virtualLeft;\n"
            + "	const int cright = (virtualRight - 1) - right;\n"
            + "	const int ctop = top - virtualTop;\n"
            + "	const int cbottom = (virtualBottom - 1) - bottom;\n"
            + "	const int outputPlaneSize = (inputWidth / s) * (inputHeight / s);\n"
            + "	for (int o = 0; o < convolutionCount; ++o)\n"
            + "	{\n"
            + "		output[outputPlaneSize * o + gid] = 0;\n"
            + "	}\n"
            + "	for (int yy = top, cy = ctop; yy <= bottom; ++yy, ++cy)\n"
            + "	{\n"
            + "		for (int xx = left, cx = cleft; xx <= right; ++xx, ++cx)\n"
            + "		{\n"
            + "			const int inputOffset = (yy * inputWidth + xx) * inputChannels;\n"
            + "			const int convolutionOffset = (cy * convolutionWidth + cx) * inputChannels;\n"
            + "			for (int c = 0; c < inputChannels; ++c)\n"
            + "			{\n"
            + "				const float inputValue = input[inputOffset + c];\n"
            + "				for (int o = 0; o < convolutionCount; ++o)\n"
            + "				{\n"
            + "					output[outputPlaneSize * o + gid] += inputValue * convolutions[o * convolutionSize + convolutionOffset + c];\n"
            + "				}\n"
            + "			}\n"
            + "		}\n"
            + "	}\n"
            + "}";
	
	/**
	 * @param commandLineArguments
	 * <br>must not be null
	 * @throws IOException 
	 */
	public static final void main(final String[] commandLineArguments) throws IOException {
		final CommandLineArgumentsParser arguments = new CommandLineArgumentsParser(commandLineArguments);
		final File file = new File(arguments.get("file", ""));
		final File outputFile = new File(arguments.get("output", ""));
		
		Tools.debugPrint(file);
		
		final BufferedImage image = ImageIO.read(file);
		final int imageWidth = image.getWidth();
		final int imageHeight = image.getHeight();
		final int pixelCount = imageWidth * imageHeight;
		final int channelCount = 3;
		final float[] input = new float[pixelCount * channelCount];
		final int step = 2;
		final float[] convolutions = {
				1F, 0F, 0F, 1F, 0F, 0F,
				1F, 0F, 0F, 1F, 0F, 0F,
				
				0F, 1F, 0F, 0F, 1F, 0F,
				0F, 1F, 0F, 0F, 1F, 0F,
				
				0F, 0F, 1F, 0F, 0F, 1F,
				0F, 0F, 1F, 0F, 0F, 1F
		};
		final int convolutionSize = 2;
		final int convolutionCount = convolutions.length / (convolutionSize * convolutionSize * channelCount);
		Tools.debugPrint(pixelCount, convolutionSize, convolutionCount);
		
		for (int pixel = 0; pixel < pixelCount; ++pixel) {
			final int rgb = image.getRGB(pixel % imageWidth, pixel / imageWidth);
			input[pixel * 3 + 0] = (rgb >> 16) & 0xFF;
			input[pixel * 3 + 1] = (rgb >> 8) & 0xFF;
			input[pixel * 3 + 2] = (rgb >> 0) & 0xFF;
		}
		
		CL.setExceptionsEnabled(true);
		
		final CLContext context = new CLContext(CL.CL_DEVICE_TYPE_GPU, 0);
		final CLKernel kernel = context.createAndBuildProgram(PROGRAM_SOURCE)
				.createKernel("convolution2D");
		final int outputWidth = imageWidth / step;
		final int outputHeight = imageHeight / step;
		final int outputPixelCount = outputWidth * outputHeight;
		final float[] output = new float[outputPixelCount * convolutionCount];
		
		kernel.setArg(0, context.createInputBuffer(input));
		kernel.setArg(1, context.createInputBuffer(channelCount, imageWidth, imageHeight));
		kernel.setArg(2, context.createInputBuffer(step));
		kernel.setArg(3, context.createInputBuffer(convolutions));
		kernel.setArg(4, context.createInputBuffer(convolutionCount, convolutionSize, convolutionSize));
		kernel.setArg(5, context.createOutputBuffer(Sizeof.cl_float, output.length));
		
		Tools.debugPrint();
		
		kernel.enqueueNDRange(output.length / convolutionCount);
		kernel.enqueueReadArg(5, output);
		
		context.release();
		Tools.debugPrint();
		
		final BufferedImage outputImage = new BufferedImage(outputWidth, outputHeight, BufferedImage.TYPE_INT_ARGB);
		final ToInt<?> toRed = denormalizeTo(0, 255).using(output, outputPixelCount * 0, outputPixelCount * 1);<commit_msg>[JOCLTest] Refactoring.<commit_after>package jocltest;

import static java.lang.Math.max;
import static java.lang.Math.min;
import static jocltest.JOCLConvolution2D.Denormalize.denormalizeTo;
import static net.sourceforge.aprog.tools.Tools.ignore;

import imj.cl.CLContext;
import imj.cl.CLKernel;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import javax.imageio.ImageIO;

import org.jocl.CL;
import org.jocl.Sizeof;

import net.sourceforge.aprog.tools.CommandLineArgumentsParser;
import net.sourceforge.aprog.tools.IllegalInstantiationException;
import net.sourceforge.aprog.tools.Tools;
import net.sourceforge.aprog.tools.MathTools.Statistics;

/**
 * @author codistmonk (creation 2014-12-07)
 */
public final class JOCLConvolution2D {
	
	private JOCLConvolution2D() {
		throw new IllegalInstantiationException();
	}
	
    public static final String PROGRAM_SOURCE =
            "__kernel void "
            + "convolution2D(__global const float * input,"
            + "             __global const int * inputDimensions,"
            + "             __global const int * step,"
            + "             __global const float * convolutions,"
            + "             __global const int * convolutionsDimensions,"
            + "             __global float * output)"
            + "{\n"
            + "	const int gid = get_global_id(0);\n"
            + "	const int inputChannels = inputDimensions[0];\n"
            + "	const int inputWidth = inputDimensions[1];\n"
            + "	const int inputHeight = inputDimensions[2];\n"
            + "	const int inputPlaneSize = inputWidth * inputHeight;\n"
            + "	const int s = *step;\n"
            + "	const int convolutionCount = convolutionsDimensions[0];\n"
            + "	const int convolutionWidth = convolutionsDimensions[1];\n"
            + "	const int convolutionHeight = convolutionsDimensions[2];\n"
            + "	const int convolutionSize = convolutionWidth * convolutionHeight * inputChannels;\n"
            + "	const int x = s * (gid % (inputWidth / s));\n"
            + "	const int y = s * (gid / (inputWidth / s));\n"
            + "	const int virtualLeft = x + 1 - (convolutionWidth / 2);\n"
            + "	const int virtualRight = virtualLeft + convolutionWidth;\n"
            + "	const int virtualTop = y + 1 - (convolutionHeight / 2);\n"
            + "	const int virtualBottom = virtualTop + convolutionHeight;\n"
            + "	const int left = max(0, virtualLeft);\n"
            + "	const int right = min(virtualRight, inputWidth) - 1;\n"
            + "	const int top = max(0, virtualTop);\n"
            + "	const int bottom = min(virtualBottom, inputHeight) - 1;\n"
            + "	const int cleft = left - virtualLeft;\n"
            + "	const int cright = (virtualRight - 1) - right;\n"
            + "	const int ctop = top - virtualTop;\n"
            + "	const int cbottom = (virtualBottom - 1) - bottom;\n"
            + "	const int outputPlaneSize = (inputWidth / s) * (inputHeight / s);\n"
            + "	for (int o = 0; o < convolutionCount; ++o)\n"
            + "	{\n"
            + "		output[outputPlaneSize * o + gid] = 0;\n"
            + "	}\n"
            + "	for (int yy = top, cy = ctop; yy <= bottom; ++yy, ++cy)\n"
            + "	{\n"
            + "		for (int xx = left, cx = cleft; xx <= right; ++xx, ++cx)\n"
            + "		{\n"
            + "			const int inputOffset = (yy * inputWidth + xx);\n"
            + "			const int convolutionOffset = (cy * convolutionWidth + cx) * inputChannels;\n"
            + "			for (int c = 0; c < inputChannels; ++c)\n"
            + "			{\n"
            + "				const float inputValue = input[inputPlaneSize * c + inputOffset];\n"
            + "				for (int o = 0; o < convolutionCount; ++o)\n"
            + "				{\n"
            + "					output[outputPlaneSize * o + gid] += inputValue * convolutions[o * convolutionSize + convolutionOffset + c];\n"
            + "				}\n"
            + "			}\n"
            + "		}\n"
            + "	}\n"
            + "}";
	
	/**
	 * @param commandLineArguments
	 * <br>must not be null
	 * @throws IOException 
	 */
	public static final void main(final String[] commandLineArguments) throws IOException {
		final CommandLineArgumentsParser arguments = new CommandLineArgumentsParser(commandLineArguments);
		final File file = new File(arguments.get("file", ""));
		final File outputFile = new File(arguments.get("output", ""));
		
		Tools.debugPrint(file);
		
		final BufferedImage image = ImageIO.read(file);
		final int imageWidth = image.getWidth();
		final int imageHeight = image.getHeight();
		final int pixelCount = imageWidth * imageHeight;
		final int channelCount = 3;
		final float[] input = new float[pixelCount * channelCount];
		final int step = 2;
		final float[] convolutions = {
				1F, 0F, 0F, 1F, 0F, 0F,
				1F, 0F, 0F, 1F, 0F, 0F,
				
				0F, 1F, 0F, 0F, 1F, 0F,
				0F, 1F, 0F, 0F, 1F, 0F,
				
				0F, 0F, 1F, 0F, 0F, 1F,
				0F, 0F, 1F, 0F, 0F, 1F
		};
		final int convolutionSize = 2;
		final int convolutionCount = convolutions.length / (convolutionSize * convolutionSize * channelCount);
		Tools.debugPrint(pixelCount, convolutionSize, convolutionCount);
		
		for (int pixel = 0; pixel < pixelCount; ++pixel) {
			final int rgb = image.getRGB(pixel % imageWidth, pixel / imageWidth);
			input[pixelCount * 0 + pixel] = (rgb >> 16) & 0xFF;
			input[pixelCount * 1 + pixel] = (rgb >> 8) & 0xFF;
			input[pixelCount * 2 + pixel] = (rgb >> 0) & 0xFF;
		}
		
		CL.setExceptionsEnabled(true);
		
		final CLContext context = new CLContext(CL.CL_DEVICE_TYPE_GPU, 0);
		final CLKernel kernel = context.createAndBuildProgram(PROGRAM_SOURCE)
				.createKernel("convolution2D");
		final int outputWidth = imageWidth / step;
		final int outputHeight = imageHeight / step;
		final int outputPixelCount = outputWidth * outputHeight;
		final float[] output = new float[outputPixelCount * convolutionCount];
		
		kernel.setArg(0, context.createInputBuffer(input));
		kernel.setArg(1, context.createInputBuffer(channelCount, imageWidth, imageHeight));
		kernel.setArg(2, context.createInputBuffer(step));
		kernel.setArg(3, context.createInputBuffer(convolutions));
		kernel.setArg(4, context.createInputBuffer(convolutionCount, convolutionSize, convolutionSize));
		kernel.setArg(5, context.createOutputBuffer(Sizeof.cl_float, output.length));
		
		Tools.debugPrint();
		
		kernel.enqueueNDRange(output.length / convolutionCount);
		kernel.enqueueReadArg(5, output);
		
		context.release();
		Tools.debugPrint();
		
		final BufferedImage outputImage = new BufferedImage(outputWidth, outputHeight, BufferedImage.TYPE_INT_ARGB);
		final ToInt<?> toRed = denormalizeTo(0, 255).using(output, outputPixelCount * 0, outputPixelCount * 1);
{'fraction_non_alphanumeric': 0.12707100591715975, 'fraction_numerical': 0.014718934911242603, 'mean_word_length': 2.627850818352562, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '123216', 'n_tokens_mistral': 4667, 'n_tokens_neox': 4171, 'n_words': 1035}