// Path: src/main/java/org/shaman/jmecl/OpenCLSettings.java
// public class OpenCLSettings {
// 	
// 	private final Context clContext;
// 	private final CommandQueue clCommandQueue;
// 	private final ProgramCache programCache;
// 	private final AssetManager assetManager;
// 
// 	public OpenCLSettings(Context clContext, CommandQueue clCommandQueue, 
// 			ProgramCache programCache, AssetManager assetManager) {
// 		this.clContext = clContext;
// 		this.clCommandQueue = clCommandQueue;
// 		this.programCache = programCache!=null ? programCache : new ProgramCache();
// 		this.assetManager = assetManager;
// 	}
// 
// 	public Context getClContext() {
// 		return clContext;
// 	}
// 
// 	public CommandQueue getClCommandQueue() {
// 		return clCommandQueue;
// 	}
// 
// 	public ProgramCache getProgramCache() {
// 		return programCache;
// 	}
// 
// 	public AssetManager getAssetManager() {
// 		return assetManager;
// 	}
// 
// 	@Override
// 	public int hashCode() {
// 		int hash = 3;
// 		hash = 43 * hash + Objects.hashCode(this.clContext);
// 		hash = 43 * hash + Objects.hashCode(this.clCommandQueue);
// 		return hash;
// 	}
// 
// 	@Override
// 	public boolean equals(Object obj) {
// 		if (obj == null) {
// 			return false;
// 		}
// 		if (getClass() != obj.getClass()) {
// 			return false;
// 		}
// 		final OpenCLSettings other = (OpenCLSettings) obj;
// 		if (!Objects.equals(this.clContext, other.clContext)) {
// 			return false;
// 		}
// 		if (!Objects.equals(this.clCommandQueue, other.clCommandQueue)) {
// 			return false;
// 		}
// 		return true;
// 	}
// 
// }


import com.jme3.asset.AssetManager;
import com.jme3.opencl.*;
import java.nio.ByteBuffer;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.shaman.jmecl.OpenCLSettings;
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package org.shaman.jmecl.sorting;


/**
 * Radix sort implementation.
 * Only integer keys and values are supported.
 * This is a stable, in-place, non-comparison-based algorithm.
 * You have to specify the range of bits to be sorted by {@link #setEndBit(int) }
 * (the start bit is assumed to be zero).
 * 
 * <p>
 * A. G. DUANE MERRILL, "High performance and scalable radix sorting:
A case study of implementing dynamic parallelism for gpu computing,"
Parallel processing letters, vol. 2011 (21), no. 2, pp. 245 - 272.
* 
* Geist Software Labs, \libcl: Parallel algorithm library."
* http://www.libcl.org
 * @author shaman
 */
public class RadixSort implements Sorter {
	private static final Logger LOG = Logger.getLogger(BitonicSort.class.getName());
	private static final String PROGRAM_FILE = "org/shaman/jmecl/sorting/RadixSort.cl";

	private final Context clContext;
	private final Device clDevice;
	private final CommandQueue clQueue;
	private final Sorter.ComparisonSettings settings;
	
	private final int RS_CBITS = 4;
	private final int RS_BLOCK_SIZE = 256;
	private final int RS_BLOCK_SIZE_CUBE = RS_BLOCK_SIZE*RS_BLOCK_SIZE*RS_BLOCK_SIZE;
	private final long cMaxArraySize = RS_BLOCK_SIZE_CUBE * 4 / (1 << RS_CBITS);
	
	private Program program;
	private final Kernel clBlockSort;
	private final Kernel clBlockScan;
	private final Kernel clBlockPrefix;
	private final Kernel clReorder;
	private Buffer bfTempKey;
	private Buffer bfTempVal;
	private Buffer bfBlockScan;
	private Buffer bfBlockSum;
	private Buffer bfBlockOffset;
	private int endBit = 32;
	
	/**
	 * Creates a new instance of the radix sort using ascending sorting on
	 * integer keys and values.
	 *
	 * @param settings the opencl settings
	 */
// Path: src/main/java/org/shaman/jmecl/OpenCLSettings.java
// public class OpenCLSettings {
// 	
// 	private final Context clContext;
// 	private final CommandQueue clCommandQueue;
// 	private final ProgramCache programCache;
// 	private final AssetManager assetManager;
// 
// 	public OpenCLSettings(Context clContext, CommandQueue clCommandQueue, 
// 			ProgramCache programCache, AssetManager assetManager) {
// 		this.clContext = clContext;
// 		this.clCommandQueue = clCommandQueue;
// 		this.programCache = programCache!=null ? programCache : new ProgramCache();
// 		this.assetManager = assetManager;
// 	}
// 
// 	public Context getClContext() {
// 		return clContext;
// 	}
// 
// 	public CommandQueue getClCommandQueue() {
// 		return clCommandQueue;
// 	}
// 
// 	public ProgramCache getProgramCache() {
// 		return programCache;
// 	}
// 
// 	public AssetManager getAssetManager() {
// 		return assetManager;
// 	}
// 
// 	@Override
// 	public int hashCode() {
// 		int hash = 3;
// 		hash = 43 * hash + Objects.hashCode(this.clContext);
// 		hash = 43 * hash + Objects.hashCode(this.clCommandQueue);
// 		return hash;
// 	}
// 
// 	@Override
// 	public boolean equals(Object obj) {
// 		if (obj == null) {
// 			return false;
// 		}
// 		if (getClass() != obj.getClass()) {
// 			return false;
// 		}
// 		final OpenCLSettings other = (OpenCLSettings) obj;
// 		if (!Objects.equals(this.clContext, other.clContext)) {
// 			return false;
// 		}
// 		if (!Objects.equals(this.clCommandQueue, other.clCommandQueue)) {
// 			return false;
// 		}
// 		return true;
// 	}
// 
// }


// Path: src/main/java/org/shaman/jmecl/sorting/RadixSort.java
import com.jme3.asset.AssetManager;
import com.jme3.opencl.*;
import java.nio.ByteBuffer;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.shaman.jmecl.OpenCLSettings;

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package org.shaman.jmecl.sorting;


/**
 * Radix sort implementation.
 * Only integer keys and values are supported.
 * This is a stable, in-place, non-comparison-based algorithm.
 * You have to specify the range of bits to be sorted by {@link #setEndBit(int) }
 * (the start bit is assumed to be zero).
 * 
 * <p>
 * A. G. DUANE MERRILL, "High performance and scalable radix sorting:
A case study of implementing dynamic parallelism for gpu computing,"
Parallel processing letters, vol. 2011 (21), no. 2, pp. 245 - 272.
* 
* Geist Software Labs, \libcl: Parallel algorithm library."
* http://www.libcl.org
 * @author shaman
 */
public class RadixSort implements Sorter {
	private static final Logger LOG = Logger.getLogger(BitonicSort.class.getName());
	private static final String PROGRAM_FILE = "org/shaman/jmecl/sorting/RadixSort.cl";

	private final Context clContext;
	private final Device clDevice;
	private final CommandQueue clQueue;
	private final Sorter.ComparisonSettings settings;
	
	private final int RS_CBITS = 4;
	private final int RS_BLOCK_SIZE = 256;
	private final int RS_BLOCK_SIZE_CUBE = RS_BLOCK_SIZE*RS_BLOCK_SIZE*RS_BLOCK_SIZE;
	private final long cMaxArraySize = RS_BLOCK_SIZE_CUBE * 4 / (1 << RS_CBITS);
	
	private Program program;
	private final Kernel clBlockSort;
	private final Kernel clBlockScan;
	private final Kernel clBlockPrefix;
	private final Kernel clReorder;
	private Buffer bfTempKey;
	private Buffer bfTempVal;
	private Buffer bfBlockScan;
	private Buffer bfBlockSum;
	private Buffer bfBlockOffset;
	private int endBit = 32;
	
	/**
	 * Creates a new instance of the radix sort using ascending sorting on
	 * integer keys and values.
	 *
	 * @param settings the opencl settings
	 */
	public RadixSort(OpenCLSettings settings) {