All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.it.unimi.dsi.fastutil.objects.ObjectBigArrays Maven / Gradle / Ivy

The newest version!
/* Generic definitions */
/* Assertions (useful to generate conditional code) */
/* Current type and class (and size, if applicable) */
/* Value methods */
/* Interfaces (keys) */
/* Interfaces (values) */
/* Abstract implementations (keys) */
/* Abstract implementations (values) */
/* Static containers (keys) */
/* Static containers (values) */
/* Implementations */
/* Synchronized wrappers */
/* Unmodifiable wrappers */
/* Other wrappers */
/* Methods (keys) */
/* Methods (values) */
/* Methods (keys/values) */
/* Methods that have special names depending on keys (but the special names depend on values) */
/* Equality */
/* Object/Reference-only definitions (keys) */
/* Object/Reference-only definitions (values) */
/*		 
 * Copyright (C) 2009-2015 Sebastiano Vigna
 *
 * Licensed 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. 
 *
 *
 *
 * Copyright (C) 1999 CERN - European Organization for Nuclear Research.
 *
 *   Permission to use, copy, modify, distribute and sell this software and
 *   its documentation for any purpose is hereby granted without fee,
 *   provided that the above copyright notice appear in all copies and that
 *   both that copyright notice and this permission notice appear in
 *   supporting documentation. CERN makes no representations about the
 *   suitability of this software for any purpose. It is provided "as is"
 *   without expressed or implied warranty. 
 */
package it.unimi.dsi.fastutil.objects;

import java.util.Arrays;
import java.util.Random;
import it.unimi.dsi.fastutil.BigArrays;
import it.unimi.dsi.fastutil.Hash;
import static it.unimi.dsi.fastutil.BigArrays.start;
import static it.unimi.dsi.fastutil.BigArrays.segment;
import static it.unimi.dsi.fastutil.BigArrays.displacement;
import static it.unimi.dsi.fastutil.BigArrays.SEGMENT_MASK;
import static it.unimi.dsi.fastutil.BigArrays.SEGMENT_SIZE;
import java.util.Comparator;

/** A class providing static methods and objects that do useful things with {@linkplain BigArrays big arrays}.
 *
 * 

In particular, the ensureCapacity(), grow(), trim() and setLength() methods allow to handle arrays much like array lists. * *

Note that {@link it.unimi.dsi.fastutil.io.BinIO} and {@link it.unimi.dsi.fastutil.io.TextIO} contain several methods make it possible to load and save big arrays of primitive types as sequences * of elements in {@link java.io.DataInput} format (i.e., not as objects) or as sequences of lines of text. * *

Warning: creating arrays using {@linkplain java.lang.reflect.Array#newInstance(Class,int) reflection}, as it happens in {@link #ensureCapacity(Object[][],long,long)} and * {@link #grow(Object[][],long,long)}, is significantly slower than using new. This phenomenon is particularly evident in the first growth phases of an array reallocated with * doubling (or similar) logic. * * @see BigArrays */ public class ObjectBigArrays { private ObjectBigArrays() {} /** A static, final, empty big array. */ public final static Object[][] EMPTY_BIG_ARRAY = {}; /** Returns the element of the given big array of specified index. * * @param array a big array. * @param index a position in the big array. * @return the element of the big array at the specified position. */ public static K get( final K[][] array, final long index ) { return array[ segment( index ) ][ displacement( index ) ]; } /** Sets the element of the given big array of specified index. * * @param array a big array. * @param index a position in the big array. * @param value the new value for the array element at the specified position. */ public static void set( final K[][] array, final long index, K value ) { array[ segment( index ) ][ displacement( index ) ] = value; } /** Swaps the element of the given big array of specified indices. * * @param array a big array. * @param first a position in the big array. * @param second a position in the big array. */ public static void swap( final K[][] array, final long first, final long second ) { final K t = array[ segment( first ) ][ displacement( first ) ]; array[ segment( first ) ][ displacement( first ) ] = array[ segment( second ) ][ displacement( second ) ]; array[ segment( second ) ][ displacement( second ) ] = t; } /** Returns the length of the given big array. * * @param array a big array. * @return the length of the given big array. */ public static long length( final K[][] array ) { final int length = array.length; return length == 0 ? 0 : start( length - 1 ) + array[ length - 1 ].length; } /** Copies a big array from the specified source big array, beginning at the specified position, to the specified position of the destination big array. Handles correctly overlapping regions of the * same big array. * * @param srcArray the source big array. * @param srcPos the starting position in the source big array. * @param destArray the destination big array. * @param destPos the starting position in the destination data. * @param length the number of elements to be copied. */ public static void copy( final K[][] srcArray, final long srcPos, final K[][] destArray, final long destPos, long length ) { if ( destPos <= srcPos ) { int srcSegment = segment( srcPos ); int destSegment = segment( destPos ); int srcDispl = displacement( srcPos ); int destDispl = displacement( destPos ); int l; while ( length > 0 ) { l = (int)Math.min( length, Math.min( srcArray[ srcSegment ].length - srcDispl, destArray[ destSegment ].length - destDispl ) ); System.arraycopy( srcArray[ srcSegment ], srcDispl, destArray[ destSegment ], destDispl, l ); if ( ( srcDispl += l ) == SEGMENT_SIZE ) { srcDispl = 0; srcSegment++; } if ( ( destDispl += l ) == SEGMENT_SIZE ) { destDispl = 0; destSegment++; } length -= l; } } else { int srcSegment = segment( srcPos + length ); int destSegment = segment( destPos + length ); int srcDispl = displacement( srcPos + length ); int destDispl = displacement( destPos + length ); int l; while ( length > 0 ) { if ( srcDispl == 0 ) { srcDispl = SEGMENT_SIZE; srcSegment--; } if ( destDispl == 0 ) { destDispl = SEGMENT_SIZE; destSegment--; } l = (int)Math.min( length, Math.min( srcDispl, destDispl ) ); System.arraycopy( srcArray[ srcSegment ], srcDispl - l, destArray[ destSegment ], destDispl - l, l ); srcDispl -= l; destDispl -= l; length -= l; } } } /** Copies a big array from the specified source big array, beginning at the specified position, to the specified position of the destination array. * * @param srcArray the source big array. * @param srcPos the starting position in the source big array. * @param destArray the destination array. * @param destPos the starting position in the destination data. * @param length the number of elements to be copied. */ public static void copyFromBig( final K[][] srcArray, final long srcPos, final K[] destArray, int destPos, int length ) { int srcSegment = segment( srcPos ); int srcDispl = displacement( srcPos ); int l; while ( length > 0 ) { l = Math.min( srcArray[ srcSegment ].length - srcDispl, length ); System.arraycopy( srcArray[ srcSegment ], srcDispl, destArray, destPos, l ); if ( ( srcDispl += l ) == SEGMENT_SIZE ) { srcDispl = 0; srcSegment++; } destPos += l; length -= l; } } /** Copies an array from the specified source array, beginning at the specified position, to the specified position of the destination big array. * * @param srcArray the source array. * @param srcPos the starting position in the source array. * @param destArray the destination big array. * @param destPos the starting position in the destination data. * @param length the number of elements to be copied. */ public static void copyToBig( final K[] srcArray, int srcPos, final K[][] destArray, final long destPos, long length ) { int destSegment = segment( destPos ); int destDispl = displacement( destPos ); int l; while ( length > 0 ) { l = (int)Math.min( destArray[ destSegment ].length - destDispl, length ); System.arraycopy( srcArray, srcPos, destArray[ destSegment ], destDispl, l ); if ( ( destDispl += l ) == SEGMENT_SIZE ) { destDispl = 0; destSegment++; } srcPos += l; length -= l; } } /** Creates a new big array using the given one as prototype. * *

This method returns a new big array of the given length whose element are of the same class as of those of prototype. In case of an empty big array, it tries to return * {@link #EMPTY_BIG_ARRAY}, if possible. * * @param prototype a big array that will be used to type the new one. * @param length the length of the new big array. * @return a new big array of given type and length. */ @SuppressWarnings("unchecked") public static K[][] newBigArray( final K[][] prototype, final long length ) { return (K[][])newBigArray( prototype.getClass().getComponentType(), length ); } /** Creates a new big array using a the given one as component type. * *

This method returns a new big array whose segments are of class componentType. In case of an empty big array, it tries to return {@link #EMPTY_BIG_ARRAY}, if possible. * * @param componentType a class representing the type of segments of the array to be created. * @param length the length of the new big array. * @return a new big array of given type and length. */ private static Object[][] newBigArray( Class componentType, final long length ) { if ( length == 0 && componentType == Object[].class ) return EMPTY_BIG_ARRAY; final int baseLength = (int)( ( length + SEGMENT_MASK ) / SEGMENT_SIZE ); Object[][] base = (Object[][])java.lang.reflect.Array.newInstance( componentType, baseLength ); final int residual = (int)( length & SEGMENT_MASK ); if ( residual != 0 ) { for ( int i = 0; i < baseLength - 1; i++ ) base[ i ] = (Object[])java.lang.reflect.Array.newInstance( componentType.getComponentType(), SEGMENT_SIZE ); base[ baseLength - 1 ] = (Object[])java.lang.reflect.Array.newInstance( componentType.getComponentType(), residual ); } else for ( int i = 0; i < baseLength; i++ ) base[ i ] = (Object[])java.lang.reflect.Array.newInstance( componentType.getComponentType(), SEGMENT_SIZE ); return base; } /** Creates a new big array. * * @param length the length of the new big array. * @return a new big array of given length. */ public static Object[][] newBigArray( final long length ) { if ( length == 0 ) return EMPTY_BIG_ARRAY; final int baseLength = (int)( ( length + SEGMENT_MASK ) / SEGMENT_SIZE ); Object[][] base = new Object[ baseLength ][]; final int residual = (int)( length & SEGMENT_MASK ); if ( residual != 0 ) { for ( int i = 0; i < baseLength - 1; i++ ) base[ i ] = new Object[ SEGMENT_SIZE ]; base[ baseLength - 1 ] = new Object[ residual ]; } else for ( int i = 0; i < baseLength; i++ ) base[ i ] = new Object[ SEGMENT_SIZE ]; return base; } /** Turns a standard array into a big array. * *

Note that the returned big array might contain as a segment the original array. * * @param array an array. * @return a new big array with the same length and content of array. */ @SuppressWarnings("unchecked") public static K[][] wrap( final K[] array ) { if ( array.length == 0 && array.getClass() == Object[].class ) return (K[][])EMPTY_BIG_ARRAY; if ( array.length <= SEGMENT_SIZE ) { final K[][] bigArray = (K[][])java.lang.reflect.Array.newInstance( array.getClass(), 1 ); bigArray[ 0 ] = array; return bigArray; } final K[][] bigArray = (K[][])newBigArray( array.getClass(), array.length ); for ( int i = 0; i < bigArray.length; i++ ) System.arraycopy( array, (int)start( i ), bigArray[ i ], 0, bigArray[ i ].length ); return bigArray; } /** Ensures that a big array can contain the given number of entries. * *

If you cannot foresee whether this big array will need again to be enlarged, you should probably use grow() instead. * *

Warning: the returned array might use part of the segments of the original array, which must be considered read-only after calling this method. * * @param array a big array. * @param length the new minimum length for this big array. * @return array, if it contains length entries or more; otherwise, a big array with length entries whose first length(array) entries are the * same as those of array. */ public static K[][] ensureCapacity( final K[][] array, final long length ) { return ensureCapacity( array, length, length( array ) ); } /** Ensures that a big array can contain the given number of entries, preserving just a part of the big array. * *

This method returns a new big array of the given length whose element are of the same class as of those of array. * *

Warning: the returned array might use part of the segments of the original array, which must be considered read-only after calling this method. * * @param array a big array. * @param length the new minimum length for this big array. * @param preserve the number of elements of the big array that must be preserved in case a new allocation is necessary. * @return array, if it can contain length entries or more; otherwise, a big array with length entries whose first preserve entries are the same * as those of array. */ @SuppressWarnings("unchecked") public static K[][] ensureCapacity( final K[][] array, final long length, final long preserve ) { final long oldLength = length( array ); if ( length > oldLength ) { final int valid = array.length - ( array.length == 0 || array.length > 0 && array[ array.length - 1 ].length == SEGMENT_SIZE ? 0 : 1 ); final int baseLength = (int)( ( length + SEGMENT_MASK ) / SEGMENT_SIZE ); final K[][] base = Arrays.copyOf( array, baseLength ); final Class componentType = array.getClass().getComponentType(); final int residual = (int)( length & SEGMENT_MASK ); if ( residual != 0 ) { for ( int i = valid; i < baseLength - 1; i++ ) base[ i ] = (K[])java.lang.reflect.Array.newInstance( componentType.getComponentType(), SEGMENT_SIZE ); base[ baseLength - 1 ] = (K[])java.lang.reflect.Array.newInstance( componentType.getComponentType(), residual ); } else for ( int i = valid; i < baseLength; i++ ) base[ i ] = (K[])java.lang.reflect.Array.newInstance( componentType.getComponentType(), SEGMENT_SIZE ); if ( preserve - ( valid * (long)SEGMENT_SIZE ) > 0 ) copy( array, valid * (long)SEGMENT_SIZE, base, valid * (long)SEGMENT_SIZE, preserve - ( valid * (long)SEGMENT_SIZE ) ); return base; } return array; } /** Grows the given big array to the maximum between the given length and the current length multiplied by two, provided that the given length is larger than the current length. * *

If you want complete control on the big array growth, you should probably use ensureCapacity() instead. * *

Warning: the returned array might use part of the segments of the original array, which must be considered read-only after calling this method. * * @param array a big array. * @param length the new minimum length for this big array. * @return array, if it can contain length entries; otherwise, a big array with max(length,length(array)/φ) entries whose first * length(array) entries are the same as those of array. */ public static K[][] grow( final K[][] array, final long length ) { final long oldLength = length( array ); return length > oldLength ? grow( array, length, oldLength ) : array; } /** Grows the given big array to the maximum between the given length and the current length multiplied by two, provided that the given length is larger than the current length, preserving just a * part of the big array. * *

If you want complete control on the big array growth, you should probably use ensureCapacity() instead. * *

Warning: the returned array might use part of the segments of the original array, which must be considered read-only after calling this method. * * @param array a big array. * @param length the new minimum length for this big array. * @param preserve the number of elements of the big array that must be preserved in case a new allocation is necessary. * @return array, if it can contain length entries; otherwise, a big array with max(length,length(array)/φ) entries whose first * preserve entries are the same as those of array. */ public static K[][] grow( final K[][] array, final long length, final long preserve ) { final long oldLength = length( array ); return length > oldLength ? ensureCapacity( array, Math.max( 2 * oldLength, length ), preserve ) : array; } /** Trims the given big array to the given length. * *

Warning: the returned array might use part of the segments of the original array, which must be considered read-only after calling this method. * * @param array a big array. * @param length the new maximum length for the big array. * @return array, if it contains length entries or less; otherwise, a big array with length entries whose entries are the same as the first * length entries of array. */ public static K[][] trim( final K[][] array, final long length ) { final long oldLength = length( array ); if ( length >= oldLength ) return array; final int baseLength = (int)( ( length + SEGMENT_MASK ) / SEGMENT_SIZE ); final K[][] base = Arrays.copyOf( array, baseLength ); final int residual = (int)( length & SEGMENT_MASK ); if ( residual != 0 ) base[ baseLength - 1 ] = ObjectArrays.trim( base[ baseLength - 1 ], residual ); return base; } /** Sets the length of the given big array. * *

Warning: the returned array might use part of the segments of the original array, which must be considered read-only after calling this method. * * @param array a big array. * @param length the new length for the big array. * @return array, if it contains exactly length entries; otherwise, if it contains more than length entries, a big array with length * entries whose entries are the same as the first length entries of array; otherwise, a big array with length entries whose first length(array) * entries are the same as those of array. */ public static K[][] setLength( final K[][] array, final long length ) { final long oldLength = length( array ); if ( length == oldLength ) return array; if ( length < oldLength ) return trim( array, length ); return ensureCapacity( array, length ); } /** Returns a copy of a portion of a big array. * * @param array a big array. * @param offset the first element to copy. * @param length the number of elements to copy. * @return a new big array containing length elements of array starting at offset. */ public static K[][] copy( final K[][] array, final long offset, final long length ) { ensureOffsetLength( array, offset, length ); final K[][] a = newBigArray( array, length ); copy( array, offset, a, 0, length ); return a; } /** Returns a copy of a big array. * * @param array a big array. * @return a copy of array. */ public static K[][] copy( final K[][] array ) { final K[][] base = array.clone(); for ( int i = base.length; i-- != 0; ) base[ i ] = array[ i ].clone(); return base; } /** Fills the given big array with the given value. * *

This method uses a backward loop. It is significantly faster than the corresponding method in {@link java.util.Arrays}. * * @param array a big array. * @param value the new value for all elements of the big array. */ public static void fill( final K[][] array, final K value ) { for ( int i = array.length; i-- != 0; ) Arrays.fill( array[ i ], value ); } /** Fills a portion of the given big array with the given value. * *

If possible (i.e., from is 0) this method uses a backward loop. In this case, it is significantly faster than the corresponding method in {@link java.util.Arrays}. * * @param array a big array. * @param from the starting index of the portion to fill. * @param to the end index of the portion to fill. * @param value the new value for all elements of the specified portion of the big array. */ public static void fill( final K[][] array, final long from, long to, final K value ) { final long length = length( array ); BigArrays.ensureFromTo( length, from, to ); int fromSegment = segment( from ); int toSegment = segment( to ); int fromDispl = displacement( from ); int toDispl = displacement( to ); if ( fromSegment == toSegment ) { Arrays.fill( array[ fromSegment ], fromDispl, toDispl, value ); return; } if ( toDispl != 0 ) Arrays.fill( array[ toSegment ], 0, toDispl, value ); while ( --toSegment > fromSegment ) Arrays.fill( array[ toSegment ], value ); Arrays.fill( array[ fromSegment ], fromDispl, SEGMENT_SIZE, value ); } /** Returns true if the two big arrays are elementwise equal. * *

This method uses a backward loop. It is significantly faster than the corresponding method in {@link java.util.Arrays}. * * @param a1 a big array. * @param a2 another big array. * @return true if the two big arrays are of the same length, and their elements are equal. */ public static boolean equals( final K[][] a1, final K a2[][] ) { if ( length( a1 ) != length( a2 ) ) return false; int i = a1.length, j; K[] t, u; while ( i-- != 0 ) { t = a1[ i ]; u = a2[ i ]; j = t.length; while ( j-- != 0 ) if ( !( ( t[ j ] ) == null ? ( u[ j ] ) == null : ( t[ j ] ).equals( u[ j ] ) ) ) return false; } return true; } /* Returns a string representation of the contents of the specified big array. * * The string representation consists of a list of the big array's elements, enclosed in square brackets ("[]"). Adjacent elements are separated by the characters ", " (a comma followed by a * space). Returns "null" if a is null. * * @param a the big array whose string representation to return. * * @return the string representation of a. */ public static String toString( final K[][] a ) { if ( a == null ) return "null"; final long last = length( a ) - 1; if ( last == -1 ) return "[]"; final StringBuilder b = new StringBuilder(); b.append( '[' ); for ( long i = 0;; i++ ) { b.append( String.valueOf( get( a, i ) ) ); if ( i == last ) return b.append( ']' ).toString(); b.append( ", " ); } } /** Ensures that a range given by its first (inclusive) and last (exclusive) elements fits a big array. * *

This method may be used whenever a big array range check is needed. * * @param a a big array. * @param from a start index (inclusive). * @param to an end index (inclusive). * @throws IllegalArgumentException if from is greater than to. * @throws ArrayIndexOutOfBoundsException if from or to are greater than the big array length or negative. */ public static void ensureFromTo( final K[][] a, final long from, final long to ) { BigArrays.ensureFromTo( length( a ), from, to ); } /** Ensures that a range given by an offset and a length fits a big array. * *

This method may be used whenever a big array range check is needed. * * @param a a big array. * @param offset a start index. * @param length a length (the number of elements in the range). * @throws IllegalArgumentException if length is negative. * @throws ArrayIndexOutOfBoundsException if offset is negative or offset+length is greater than the big array length. */ public static void ensureOffsetLength( final K[][] a, final long offset, final long length ) { BigArrays.ensureOffsetLength( length( a ), offset, length ); } /** A type-specific content-based hash strategy for big arrays. */ private static final class BigArrayHashStrategy implements Hash.Strategy, java.io.Serializable { private static final long serialVersionUID = -7046029254386353129L; public int hashCode( final K[][] o ) { return java.util.Arrays.deepHashCode( o ); } public boolean equals( final K[][] a, final K[][] b ) { return ObjectBigArrays.equals( a, b ); } } /** A type-specific content-based hash strategy for big arrays. * *

This hash strategy may be used in custom hash collections whenever keys are big arrays, and they must be considered equal by content. This strategy will handle null correctly, * and it is serializable. */ @SuppressWarnings({ "rawtypes" }) public final static Hash.Strategy HASH_STRATEGY = new BigArrayHashStrategy(); private static final int SMALL = 7; private static final int MEDIUM = 40; private static void vecSwap( final K[][] x, long a, long b, final long n ) { for ( int i = 0; i < n; i++, a++, b++ ) swap( x, a, b ); } private static long med3( final K x[][], final long a, final long b, final long c, Comparator comp ) { int ab = comp.compare( get( x, a ), get( x, b ) ); int ac = comp.compare( get( x, a ), get( x, c ) ); int bc = comp.compare( get( x, b ), get( x, c ) ); return ( ab < 0 ? ( bc < 0 ? b : ac < 0 ? c : a ) : ( bc > 0 ? b : ac > 0 ? c : a ) ); } private static void selectionSort( final K[][] a, final long from, final long to, final Comparator comp ) { for ( long i = from; i < to - 1; i++ ) { long m = i; for ( long j = i + 1; j < to; j++ ) if ( comp.compare( ObjectBigArrays.get( a, j ), ObjectBigArrays.get( a, m ) ) < 0 ) m = j; if ( m != i ) swap( a, i, m ); } } /** Sorts the specified range of elements according to the order induced by the specified comparator using quicksort. * *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), * pages 1249−1265, 1993. * * @param x the big array to be sorted. * @param from the index of the first element (inclusive) to be sorted. * @param to the index of the last element (exclusive) to be sorted. * @param comp the comparator to determine the sorting order. */ public static void quickSort( final K[][] x, final long from, final long to, final Comparator comp ) { final long len = to - from; // Selection sort on smallest arrays if ( len < SMALL ) { selectionSort( x, from, to, comp ); return; } // Choose a partition element, v long m = from + len / 2; // Small arrays, middle element if ( len > SMALL ) { long l = from; long n = to - 1; if ( len > MEDIUM ) { // Big arrays, pseudomedian of 9 long s = len / 8; l = med3( x, l, l + s, l + 2 * s, comp ); m = med3( x, m - s, m, m + s, comp ); n = med3( x, n - 2 * s, n - s, n, comp ); } m = med3( x, l, m, n, comp ); // Mid-size, med of 3 } final K v = get( x, m ); // Establish Invariant: v* (v)* v* long a = from, b = a, c = to - 1, d = c; while ( true ) { int comparison; while ( b <= c && ( comparison = comp.compare( get( x, b ), v ) ) <= 0 ) { if ( comparison == 0 ) swap( x, a++, b ); b++; } while ( c >= b && ( comparison = comp.compare( get( x, c ), v ) ) >= 0 ) { if ( comparison == 0 ) swap( x, c, d-- ); c--; } if ( b > c ) break; swap( x, b++, c-- ); } // Swap partition elements back to middle long s, n = to; s = Math.min( a - from, b - a ); vecSwap( x, from, b - s, s ); s = Math.min( d - c, n - d - 1 ); vecSwap( x, b, n - s, s ); // Recursively sort non-partition-elements if ( ( s = b - a ) > 1 ) quickSort( x, from, from + s, comp ); if ( ( s = d - c ) > 1 ) quickSort( x, n - s, n, comp ); } @SuppressWarnings("unchecked") private static long med3( final K x[][], final long a, final long b, final long c ) { int ab = ( ( (Comparable)( get( x, a ) ) ).compareTo( get( x, b ) ) ); int ac = ( ( (Comparable)( get( x, a ) ) ).compareTo( get( x, c ) ) ); int bc = ( ( (Comparable)( get( x, b ) ) ).compareTo( get( x, c ) ) ); return ( ab < 0 ? ( bc < 0 ? b : ac < 0 ? c : a ) : ( bc > 0 ? b : ac > 0 ? c : a ) ); } @SuppressWarnings("unchecked") private static void selectionSort( final K[][] a, final long from, final long to ) { for ( long i = from; i < to - 1; i++ ) { long m = i; for ( long j = i + 1; j < to; j++ ) if ( ( ( (Comparable)( ObjectBigArrays.get( a, j ) ) ).compareTo( ObjectBigArrays.get( a, m ) ) < 0 ) ) m = j; if ( m != i ) swap( a, i, m ); } } /** Sorts the specified big array according to the order induced by the specified comparator using quicksort. * *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), * pages 1249−1265, 1993. * * @param x the big array to be sorted. * @param comp the comparator to determine the sorting order. */ public static void quickSort( final K[][] x, final Comparator comp ) { quickSort( x, 0, ObjectBigArrays.length( x ), comp ); } /** Sorts the specified range of elements according to the natural ascending order using quicksort. * *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), * pages 1249−1265, 1993. * * @param x the big array to be sorted. * @param from the index of the first element (inclusive) to be sorted. * @param to the index of the last element (exclusive) to be sorted. */ @SuppressWarnings("unchecked") public static void quickSort( final K[][] x, final long from, final long to ) { final long len = to - from; // Selection sort on smallest arrays if ( len < SMALL ) { selectionSort( x, from, to ); return; } // Choose a partition element, v long m = from + len / 2; // Small arrays, middle element if ( len > SMALL ) { long l = from; long n = to - 1; if ( len > MEDIUM ) { // Big arrays, pseudomedian of 9 long s = len / 8; l = med3( x, l, l + s, l + 2 * s ); m = med3( x, m - s, m, m + s ); n = med3( x, n - 2 * s, n - s, n ); } m = med3( x, l, m, n ); // Mid-size, med of 3 } final K v = get( x, m ); // Establish Invariant: v* (v)* v* long a = from, b = a, c = to - 1, d = c; while ( true ) { int comparison; while ( b <= c && ( comparison = ( ( (Comparable)( get( x, b ) ) ).compareTo( v ) ) ) <= 0 ) { if ( comparison == 0 ) swap( x, a++, b ); b++; } while ( c >= b && ( comparison = ( ( (Comparable)( get( x, c ) ) ).compareTo( v ) ) ) >= 0 ) { if ( comparison == 0 ) swap( x, c, d-- ); c--; } if ( b > c ) break; swap( x, b++, c-- ); } // Swap partition elements back to middle long s, n = to; s = Math.min( a - from, b - a ); vecSwap( x, from, b - s, s ); s = Math.min( d - c, n - d - 1 ); vecSwap( x, b, n - s, s ); // Recursively sort non-partition-elements if ( ( s = b - a ) > 1 ) quickSort( x, from, from + s ); if ( ( s = d - c ) > 1 ) quickSort( x, n - s, n ); } /** Sorts the specified big array according to the natural ascending order using quicksort. * *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), * pages 1249−1265, 1993. * * @param x the big array to be sorted. */ public static void quickSort( final K[][] x ) { quickSort( x, 0, ObjectBigArrays.length( x ) ); } /** Searches a range of the specified big array for the specified value using the binary search algorithm. The range must be sorted prior to making this call. If it is not sorted, the results are * undefined. If the range contains multiple elements with the specified value, there is no guarantee which one will be found. * * @param a the big array to be searched. * @param from the index of the first element (inclusive) to be searched. * @param to the index of the last element (exclusive) to be searched. * @param key the value to be searched for. * @return index of the search key, if it is contained in the big array; otherwise, (-(insertion point) - 1). The insertion point is defined as the the point at which the * value would be inserted into the big array: the index of the first element greater than the key, or the length of the big array, if all elements in the big array are less than the specified * key. Note that this guarantees that the return value will be >= 0 if and only if the key is found. * @see java.util.Arrays */ @SuppressWarnings("unchecked") public static long binarySearch( final K[][] a, long from, long to, final K key ) { K midVal; to--; while ( from <= to ) { final long mid = ( from + to ) >>> 1; midVal = get( a, mid ); final int cmp = ( (Comparable)midVal ).compareTo( key ); if ( cmp < 0 ) from = mid + 1; else if ( cmp > 0 ) to = mid - 1; else return mid; } return -( from + 1 ); } /** Searches a big array for the specified value using the binary search algorithm. The range must be sorted prior to making this call. If it is not sorted, the results are undefined. If the range * contains multiple elements with the specified value, there is no guarantee which one will be found. * * @param a the big array to be searched. * @param key the value to be searched for. * @return index of the search key, if it is contained in the big array; otherwise, (-(insertion point) - 1). The insertion point is defined as the the point at which the * value would be inserted into the big array: the index of the first element greater than the key, or the length of the big array, if all elements in the big array are less than the specified * key. Note that this guarantees that the return value will be >= 0 if and only if the key is found. * @see java.util.Arrays */ public static long binarySearch( final K[][] a, final Object key ) { return binarySearch( a, 0, ObjectBigArrays.length( a ), key ); } /** Searches a range of the specified big array for the specified value using the binary search algorithm and a specified comparator. The range must be sorted following the comparator prior to * making this call. If it is not sorted, the results are undefined. If the range contains multiple elements with the specified value, there is no guarantee which one will be found. * * @param a the big array to be searched. * @param from the index of the first element (inclusive) to be searched. * @param to the index of the last element (exclusive) to be searched. * @param key the value to be searched for. * @param c a comparator. * @return index of the search key, if it is contained in the big array; otherwise, (-(insertion point) - 1). The insertion point is defined as the the point at which the * value would be inserted into the big array: the index of the first element greater than the key, or the length of the big array, if all elements in the big array are less than the specified * key. Note that this guarantees that the return value will be >= 0 if and only if the key is found. * @see java.util.Arrays */ public static long binarySearch( final K[][] a, long from, long to, final K key, final Comparator c ) { K midVal; to--; while ( from <= to ) { final long mid = ( from + to ) >>> 1; midVal = get( a, mid ); final int cmp = c.compare( midVal, key ); if ( cmp < 0 ) from = mid + 1; else if ( cmp > 0 ) to = mid - 1; else return mid; // key found } return -( from + 1 ); } /** Searches a big array for the specified value using the binary search algorithm and a specified comparator. The range must be sorted following the comparator prior to making this call. If it is * not sorted, the results are undefined. If the range contains multiple elements with the specified value, there is no guarantee which one will be found. * * @param a the big array to be searched. * @param key the value to be searched for. * @param c a comparator. * @return index of the search key, if it is contained in the big array; otherwise, (-(insertion point) - 1). The insertion point is defined as the the point at which the * value would be inserted into the big array: the index of the first element greater than the key, or the length of the big array, if all elements in the big array are less than the specified * key. Note that this guarantees that the return value will be >= 0 if and only if the key is found. * @see java.util.Arrays */ public static long binarySearch( final K[][] a, final K key, final Comparator c ) { return binarySearch( a, 0, ObjectBigArrays.length( a ), key, c ); } /** Shuffles the specified big array fragment using the specified pseudorandom number generator. * * @param a the big array to be shuffled. * @param from the index of the first element (inclusive) to be shuffled. * @param to the index of the last element (exclusive) to be shuffled. * @param random a pseudorandom number generator (please use a XorShift* generator). * @return a. */ public static K[][] shuffle( final K[][] a, final long from, final long to, final Random random ) { for ( long i = to - from; i-- != 0; ) { final long p = ( random.nextLong() & 0x7FFFFFFFFFFFFFFFL ) % ( i + 1 ); final K t = get( a, from + i ); set( a, from + i, get( a, from + p ) ); set( a, from + p, t ); } return a; } /** Shuffles the specified big array using the specified pseudorandom number generator. * * @param a the big array to be shuffled. * @param random a pseudorandom number generator (please use a XorShift* generator). * @return a. */ public static K[][] shuffle( final K[][] a, final Random random ) { for ( long i = length( a ); i-- != 0; ) { final long p = ( random.nextLong() & 0x7FFFFFFFFFFFFFFFL ) % ( i + 1 ); final K t = get( a, i ); set( a, i, get( a, p ) ); set( a, p, t ); } return a; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy