/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.lucene.util;


import java.util.Arrays;

A LSB Radix sorter for unsigned int values.
@lucene.internal
/** * A LSB Radix sorter for unsigned int values. * @lucene.internal */
public final class LSBRadixSorter { private static final int INSERTION_SORT_THRESHOLD = 30; private static final int HISTOGRAM_SIZE = 256; private final int[] histogram = new int[HISTOGRAM_SIZE]; private int[] buffer = new int[0]; private static void buildHistogram(int[] array, int len, int[] histogram, int shift) { for (int i = 0; i < len; ++i) { final int b = (array[i] >>> shift) & 0xFF; histogram[b] += 1; } } private static void sumHistogram(int[] histogram) { int accum = 0; for (int i = 0; i < HISTOGRAM_SIZE; ++i) { final int count = histogram[i]; histogram[i] = accum; accum += count; } } private static void reorder(int[] array, int len, int[] histogram, int shift, int[] dest) { for (int i = 0; i < len; ++i) { final int v = array[i]; final int b = (v >>> shift) & 0xFF; dest[histogram[b]++] = v; } } private static boolean sort(int[] array, int len, int[] histogram, int shift, int[] dest) { Arrays.fill(histogram, 0); buildHistogram(array, len, histogram, shift); if (histogram[0] == len) { return false; } sumHistogram(histogram); reorder(array, len, histogram, shift, dest); return true; } private static void insertionSort(int[] array, int off, int len) { for (int i = off + 1, end = off + len; i < end; ++i) { for (int j = i; j > off; --j) { if (array[j - 1] > array[j]) { int tmp = array[j - 1]; array[j - 1] = array[j]; array[j] = tmp; } else { break; } } } }
Sort array[0:len] in place.
Params:
  • numBits – how many bits are required to store any of the values in array[0:len]. Pass 32 if unknown.
/** Sort {@code array[0:len]} in place. * @param numBits how many bits are required to store any of the values in * {@code array[0:len]}. Pass {@code 32} if unknown. */
public void sort(int numBits, final int[] array, int len) { if (len < INSERTION_SORT_THRESHOLD) { insertionSort(array, 0, len); return; } buffer = ArrayUtil.grow(buffer, len); int[] arr = array; int[] buf = buffer; for (int shift = 0; shift < numBits; shift += 8) { if (sort(arr, len, histogram, shift, buf)) { // swap arrays int[] tmp = arr; arr = buf; buf = tmp; } } if (array == buf) { System.arraycopy(arr, 0, array, 0, len); } } }