/* * Copyright (c) 2003-onwards Shaven Puppy Ltd * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of 'Shaven Puppy' nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.shavenpuppy.jglib.algorithms; import com.shavenpuppy.jglib.MultiBuffer; /** * Radix Sort algorithm. * * Creation date: (12/21/00 4:14:46 PM) * @author: cas */ public final class BufferRadixSort { /** * The RadixSort can sort things which are Sortable. * They simply have to return an int which is their sort order. */ public interface Sortable { public int sortOrder(); } private final int[] mHistogram = new int[1024]; // Counters for each byte private final int[] mOffset = new int[256]; // Offsets (nearly a cumulative distribution function) private int mCurrentSize = -1; // Current size of the indices list private int[] mIndices; // Two lists, swapped each pass private int[] mIndices2; /** * RadixSort constructor comment. */ public BufferRadixSort() { super(); } /** * Returns the sorted indexes. * Creation date: (22/12/2000 01:05:01) */ public int[] getIndices() { return mIndices; } /** * Resets the indices. Returns a self-reference. * Creation date: (12/21/00 4:26:11 PM) */ public BufferRadixSort resetIndices() { for (int i = 0; i < mCurrentSize; i++) { mIndices[i] = i; } return this; } /** * Main sort routine * Input : input a list of integer values to sort. Size is limit of ints field. * Output : mIndices, a list of indices in sorted order, i.e. in the order you may process your data * Return : Self-Reference * Exception: - * Remark : this one is for integer values * Creation date: (12/21/00 4:29:01 PM) */ public BufferRadixSort sort(MultiBuffer input) { if (input == null) { throw new IllegalArgumentException("Null array input to radix sort"); } final int length = input.ints.limit(); if (length == 0) { return this; } // Resize lists if needed if(length > mCurrentSize) { mIndices = new int[length]; mIndices2 = new int[length]; mCurrentSize = length; // Initialize indices so that the input buffer is read in sequential order resetIndices(); } // Clear counters java.util.Arrays.fill(mHistogram, 0); // Create histograms (counters). Counters for all passes are created in one run. // Pros: read input buffer once instead of four times // Cons: mHistogram is 4Kb instead of 1Kb // We must take care of signed/unsigned values for temporal coherence.... // Temporal coherence boolean AlreadySorted = true; // Optimism... int iC = 0; // Prepare to count. // We must get the incoming integer array as a sequence of bytes int pC = 0; int pLen = length << 2; int h0= 0; // Histogram for first pass (LSB) int h1= 256; // Histogram for second pass int h2= 512; // Histogram for third pass int h3= 768; // Histogram for last pass (MSB) // Temporal coherence int PrevVal = input.ints.get(mIndices[0]); while(pC!=pLen) { // Temporal coherence int Val = input.ints.get(mIndices[iC++]); // Read input buffer in previous sorted order if(Val