package mcmas.core.examples;

import java.util.Arrays;

import org.jocl.Pointer;

import mcmas.core.MCM;
import mcmas.core.MCMCommandQueue;
import mcmas.core.MCMContext;
import mcmas.core.MCMEvent;
import mcmas.core.MCMKernel;
import mcmas.core.MCMMem;
import mcmas.core.MCMProgram;
import mcmas.core.MCMProgramOptions;

public class MCMReduce {
	
	public static final int NB_BLOCKS = 5;
	public static final int BLOCK_SIZE = 64;
	
	public static void test_reduce1() {
		int [] data = new int[64];
		int [] results = new int[NB_BLOCKS];
		Arrays.fill(data, 1);
		
		MCMContext context = new MCMContext();
		MCMCommandQueue queue = context.createCommandQueue();
		
		MCMProgram program = context.createProgramFromFile("kernels/reduce.cl");
		MCMKernel reducer = program.createKernel("reduce7");
		
		MCMMem dataMem = context.newBuffer().Using(data).b();
		MCMMem resultMem = context.newBuffer().Size(NB_BLOCKS, MCM.INT).b();
		MCMMem sharedMem = context.newBuffer().Size(BLOCK_SIZE).Local().b();
		
		reducer.setArguments(dataMem, resultMem, sharedMem, data.length);
		MCMEvent finished = queue.enqueue1DKernel(reducer, NB_BLOCKS * BLOCK_SIZE, BLOCK_SIZE);
		queue.blockingReadBuffer(resultMem, Pointer.to(results), 0, resultMem.getSize(), finished);
		
		System.out.println(Arrays.toString(data));
		System.out.println(Arrays.toString(results));
	}
	
	public static void test_reduce2() {
		int [] data = new int[50];
		int [] results = new int[NB_BLOCKS];
		
		for (int i = 0; i < data.length; i++) {
			data[i] = i;
		}
		
		//Arrays.fill(data, 1);
		
		MCMContext context = new MCMContext();
		MCMCommandQueue queue = context.createCommandQueue();
		
		MCMProgramOptions options = new MCMProgramOptions();
		options.define("NEUTRAL", 0);
		options.define("OP", "SUM");
		
		System.out.println(options);
		
		MCMProgram program = context.createProgramFromFile("kernels/greduce.cl", options);
		MCMKernel reducer = program.createKernel("greduce");
		
		MCMMem dataMem = context.newBuffer().Using(data).b();
		MCMMem resultMem = context.newBuffer().Size(NB_BLOCKS, MCM.INT).b();
		MCMMem sharedMem = context.newBuffer().Size(BLOCK_SIZE).Local().b();
		
		reducer.setArguments(dataMem, resultMem, sharedMem, data.length);
		MCMEvent finished = queue.enqueue1DKernel(reducer, NB_BLOCKS * BLOCK_SIZE, BLOCK_SIZE);
		queue.blockingReadBuffer(resultMem, Pointer.to(results), 0, resultMem.getSize(), finished);
		
		System.out.println(Arrays.toString(data));
		System.out.println(Arrays.toString(results));
	}
	
	
	public static void main(String[] args) {
		test_reduce2();
	}

}
