Package kodkod.util.ints

Source Code of kodkod.util.ints.Ints$UnmodifiableSparseSequence

/*
* Kodkod -- Copyright (c) 2005-2007, Emina Torlak
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package kodkod.util.ints;

import java.util.Iterator;
import java.util.NoSuchElementException;

import kodkod.util.ints.IntRange.OnePointRange;
import kodkod.util.ints.IntRange.TwoPointRange;


/**
* Contains various utility methods for working with
* integers, {@link kodkod.util.ints.IntRange IntRanges}
* {@link kodkod.util.ints.IntSet IntSets}, and {@link kodkod.util.ints.SparseSequence SparseSequences}.
*
* <p>The methods in this class all throw a NullPointerException if
* given a null reference unless otherwise specified.</p>
*
* @author Emina Torlak
*/
public final class Ints {
  /** An immutable empty int set. The clone method returns the empty set itself. */
  public static final IntSet EMPTY_SET =
    new AbstractIntSet() {
      public boolean contains(int i) { return false; }
      public int min() { throw new NoSuchElementException(); }
      public int max() { throw new NoSuchElementException(); }
      public IntIterator iterator(int from, int to) { 
        return new IntIterator() {
          public boolean hasNext() { return false; }
          public int next() { throw new NoSuchElementException(); }
          public void remove() { throw new UnsupportedOperationException(); }
        };
      }
      public int size() {  return 0; }
      public int floor(int i) { throw new NoSuchElementException(); }
      public int ceil(int i) { throw new NoSuchElementException(); }
      public IntSet clone() { return EMPTY_SET;}
  };
 
  private Ints() {}

  /*-----------SETS AND RANGES-----------*/
 
  /**
   * Returns an integer range from min, inclusive, to max, inclusive.
   * @return { r: IntRange | r.min = min && r.max = max }
   * @throws IllegalArgumentException - min > max
   */
  public static IntRange range(int min, int max) {
    if (min < max) return new TwoPointRange(min,max);
    else if (min==max) return new OnePointRange(min);
    else throw new IllegalArgumentException("min > max");
  }
 
  /**
   * Returns the smallest IntRange r that contains
   * both r1 and r2.
   * @return { r: IntRange | r.contains(r1) && r.contains(r2) &&
   *           no r' : IntRange - r | r'.contains(r1) && r'.contains(r2) && r'.size() < r.size() }
   * @throws NullPointerException - range = null
   */
  public static IntRange merge(IntRange r1, IntRange r2) {
    if (r1.contains(r2)) return r1;
    else if (r2.contains(r1)) return r2;
    else return range(StrictMath.min(r1.min(),r2.min()), StrictMath.max(r1.max(), r2.max()));
  }
 
  /**
   * Returns an unmodifiable view of the specified set. This method
   * allows modules to provide users with "read-only" access to internal int sets.
   * Query operations on the returned set "read through" to the specified set, and
   * attempts to modify the returned set, whether direct or via its iterator, result
   * in an UnsupportedOperationException.  The clone() method of the returned set
   * returns the result of calling s.clone().
   * @return an unmodifiable view of s
   * @throws NullPointerException - s = null
   */
  public static IntSet unmodifiableIntSet(final IntSet s) {
    if (s==null)
      throw new NullPointerException("s = null");
    else if (s instanceof UnmodifiableIntSet || s instanceof SingletonIntSet || s instanceof RangeIntSet)
      return s;
    else
      return new UnmodifiableIntSet(s);
  }
 
  /**
   * Returns an unmodifiable IntSet whose sole
   * element is the given integer.  The clone method
   * of the returned set returns the set itself.
   * @return {s: IntSet | s.ints = i}
   */
  public static IntSet singleton(final int i) {
    return new SingletonIntSet(i);
  }
 
  /**
   * Returns an unmodifiable IntSet that contains
   * all the elements in the given range.  The clone
   * method of the returned set returns the set itself.
   * @return {s: IntSet | s.ints = [range.min()..range.max()] }
   */
  public static IntSet rangeSet(IntRange range) {
    if (range==null)
      throw new NullPointerException();
    return new RangeIntSet(range);
  }
 
  /**
   * Returns an implementation of the int set interface
   * that offers the best time/space trade-off for a
   * set that can store all elements in the half open
   * range [0..max).  The returned instance may or may
   * not admit elements out of the range [0..max).
   * @return an int set that can store at least the
   * elements in [0..max).
   */
  public static IntSet bestSet(int max) {
    // cut-off for using a bit map is 512
    return max > 512 ? new IntTreeSet() : new IntBitSet(max);
  }

  /**
   * Returns an implementation of the int set interface
   * that offers the best time/space trade-off for a
   * set that can store all elements in the closed range [min..max]. 
   * The returned instance may or may not admit elements
   * out of the specified range.
   * @return an int set that can store at least the
   * elements in the given range.
   * @throws IllegalArgumentException - min > max
   */
  public static IntSet bestSet(int min, int max) {
    if (min > max) throw new IllegalArgumentException("min > max");
    return min < 0 ? new IntTreeSet() : bestSet(max+1);
  }
 
  /**
   * Returns an IntSet that is backed by the given array of integers.
   * The array must contain no duplicates, its elements must be sorted
   * in the ascending order, and its contents
   * must not be changed while it is in use by the returned set.
   * @requires all i, j: [0..ints.length) | i < j => array[i] <= Sarray[j]
   * @return an unmodifiable IntSet view of the given array
   */
  public static IntSet asSet(int[] ints) {
    return ints.length==0 ? EMPTY_SET : new ArrayIntSet(ints);
  }
 
  /**
   * Returns an unmodifiable IntArray backed by the given array of integers.
   * @return an unmodifiable IntArray backed by the given array of integers.
   */
  public static IntVector asIntVector(final int[] ints) {
    return new AbstractIntVector() {
      public int get(int index) { return ints[index]; }
      public int size() { return ints.length; }
      public int[] toArray(int[] array) {
        if (array.length < ints.length) {
          array = new int[ints.length];
        }
        System.arraycopy(ints, 0, array, 0, ints.length);
        return array;
      }
    };
  }
 
  /**
   * Returns an unmodifiable IntArray of length n which contains the given
   * element at each position.
   * @return an unmodifiable IntArray of length n which contains the given
   * element at each position
   */
  public static IntVector nCopies(final int n, final int elt) {
    return new AbstractIntVector() {
      public int get(int index) {
        if (index < 0 || index >= n) throw new IndexOutOfBoundsException();
        return elt;
      }
      public int size() { return n; }
      public int[] toArray(int[] array) {
        if (array.length < n) {
          array = new int[n];
        }
        for(int i = 0; i < n; i++) { array[i] = elt; }
        return array;
      }
    };
  }
 
  /*-----------SEQUENCES-----------*/
  /**
   * Returns an unmodifiable view of the specified sparse sequence. This method
   * allows modules to provide users with "read-only" access to internal sparse sequences.
   * Query operations on the returned sequence "read through" to the specified sequence, and
   * attempts to modify the returned sequence, whether direct or via its iterator, result
   * in an UnsupportedOperationException.  The clone() method of the returned sequence
   * returns the result of calling s.clone().
   * @return an unmodifiable view of s
   * @throws NullPointerException - s = null
   */
  public static <V> SparseSequence<V> unmodifiableSequence(SparseSequence<V> s) {
    if (s==null)
      throw new NullPointerException();
    if (s instanceof UnmodifiableSparseSequence)
      return s;
    else return new UnmodifiableSparseSequence<V>(s);
  }
 
  /*-----------INTEGER MANIPULATION-----------*/
 
  /**
   * Returns an integer whose value is the 16 low order bits of the given key.
   * @return key & 0x0000ffff
   */
  private static int low16(int key) {
    return key & 0x0000ffff;
  }
 
  /**
   * Returns an integer whose value is the 16 high order bits of the given key.
   * @return (key >>> 16) & 0x0000ffff
   */
  private static int high16(int key) {
    return low16(key>>>16);
  }
 
  /**
   * Performs the bit avalanching step of Paul Hsieh's
   * hashing function (http://www.azillionmonkeys.com/qed/hash.html)
   * @return the bit avalanched version of the given hash value
   */
  public static int superFastHashAvalanche(int hash) {
    hash ^= hash << 3;
    hash += hash >> 5;
    hash ^= hash << 4;
    hash += hash >> 17;
    hash ^= hash << 25;
    hash += hash >> 6;
    return hash;
  }
 
  /**
   * Performs the hashing step of Paul Hsieh's hashing function,
   * described at http://www.azillionmonkeys.com/qed/hash.html.
   * The method returns a 32 bit hash of the given integer, starting
   * with the given initial hash.  <b>This method does not perform
   * bit avalanching.</b>  To get the full hash, call {@linkplain #superFastHashAvalanche(int)}
   * on the value returned by this method.
   * @return a 32 bit hash of the given integer, based on the given hash
   */
  public static int superFastHashIncremental(int key, int hash) {

    hash += low16(key);
    final int tmp = (high16(key) << 11) ^ hash;
    hash = (hash << 16) ^ tmp;
    hash += hash >> 11;
   
    // no end cases since the key has exactly 4 bytes
    return hash;
  }
 
  /**
   * An implementation of Paul Hsieh's hashing function,
   * described at http://www.azillionmonkeys.com/qed/hash.html.
   * The method returns a 32 bit hash of the given integer.
   * This function is very fast and collision resistent; e.g.
   * it hashes the four million integers in the range
   * [-2000000,...-1, 1,..., 2000000] to distinct values.
   * The initial hash is taken to be 11.
   * @return a 32 bit hash of the given integer
   */
  public static int superFastHash(int key) {
    return superFastHashAvalanche(superFastHashIncremental(key, 11));
  }
 
  /**
   * An implementation of Paul Hsieh's hashing function,
   * described at http://www.azillionmonkeys.com/qed/hash.html.
   * The method returns a 32 bit hash of the given integers,
   * or 0 if the array is empty. The initial hash is taken to be
   * the number of keys.
   * @return a 32 bit hash of the given integers
   */
  public static int superFastHash(int... key) {
    if (key.length==0) return 0;
    int hash = key.length;

    for(int word : key) {
      hash = superFastHashIncremental(word, hash);
    }
    // no end cases since key parts are ints
    return superFastHashAvalanche(hash);
  }
 
  /**
   * An implementation of Paul Hsieh's hashing function,
   * described at http://www.azillionmonkeys.com/qed/hash.html.
   * The method returns a 32 bit hash of the given objects' hash codes,
   * or zero if the array is empty.  Any null references in the array
   * are taken to have 0 as their hash code value.
   * @return a 32 bit hash of the given objects' hashCodes
   */
  public static int superFastHash(Object... key) {
    if (key.length==0) return 0;
    int hash = key.length;

    for(Object o : key) {
      hash = superFastHashIncremental(o == null ? 0 : o.hashCode(), hash);
    }
    //  no end cases since the hashcodes of key parts are ints
    return superFastHashAvalanche(hash);
  }
 
  /**
   * An implementation of an IntSet wrapper for an IntRange.
   */
  private static final class RangeIntSet extends AbstractIntSet {
    private final IntRange range;
    /**
     * Constructs an unmodifiable IntSet wrapper for a range.
     */
    RangeIntSet(IntRange range) {
      this.range = range;
    }
    public boolean contains(int i) { return range.contains(i); }
    public int min() { return range.min(); }
    public int max() { return range.max(); }
    public IntIterator iterator(final int from, final int to) {
      return new IntIterator() {
        final boolean ascending = (from <= to);
        long cursor = ascending ? StrictMath.max(range.min(), from) : StrictMath.min(range.max(), from);
        final int end = ascending ? StrictMath.min(range.max(), to) : StrictMath.max(range.min(), to);
        public boolean hasNext() {
          return ascending && cursor<=end || !ascending && cursor >= end;
        }
        public int next() {
          if (!hasNext()) throw new NoSuchElementException();
          return ascending ? (int)cursor++ : (int)cursor--;
        }
        public void remove() { throw new UnsupportedOperationException(); }
       
      };
    }
    public int size() {  return range.size(); }
    public IntSet copy() { return this; }
    public int floor(int i) {
      if (i<range.min())
        throw new NoSuchElementException();
      return StrictMath.min(i, range.max());
    }
    public int ceil(int i) {
      if (i>range.max())
        throw new NoSuchElementException();
      return StrictMath.max(i, range.min());
    }
    public IntSet clone() { return this; }
  }
 
  /**
   * An implementation of an IntSet wrapper for a single integer.
   */
  private static final class SingletonIntSet extends AbstractIntSet {
    private final int i;
    /**
     * Constructs an unmodifiable intset wrapper for the given integer.
     */
    SingletonIntSet(int i) {
      this.i = i;
    }
    public boolean contains(int j) { return i==j; }
    public int min() { return i; }
    public int max() { return i; }
    public IntIterator iterator(final int from, final int to) { 
      return new IntIterator() {
        boolean cursor = (from<=i && i<=to) || (to<=i && i<=from);
        public boolean hasNext() { return cursor; }
        public int next() {
          if (!hasNext()) throw new NoSuchElementException();
          cursor = false;
          return i;
        }
        public void remove() { throw new UnsupportedOperationException(); }
      };
    }
    public int size() {  return 1; }
    public IntSet copy() { return this; }
    public boolean equals(Object o) {
      if (this==o) return true;
      else if (o instanceof IntSet) {
        final IntSet s = (IntSet) o;
        return s.size()==1 && s.min()==i;
      } else
        return super.equals(o);
    }
    public int hashCode() { return i; }
    public int floor(int j) {
      if (i<=j) return i;
      else throw new NoSuchElementException();
    }
    public int ceil(int j) {
      if (i>=j) return i;
      else throw new NoSuchElementException();
    }
    public IntSet clone() { return this; }
  }
 
  /**
   * An implementation of an unmodifiable IntSet view.
   * @author Emina Torlak
   */
  private static final class UnmodifiableIntSet extends AbstractIntSet {
    private final IntSet s;
   
    /**
     * Constructs an unmodifiable wrapper for the given intset.
     * @requires set != null
     */
    UnmodifiableIntSet(IntSet set) {
      this.s = set;
    }
    public int size() { return s.size(); }
    public boolean contains(int i) { return s.contains(i); }
    public int min() { return s.min()}
    public int max() { return s.max()}
    public boolean containsAll(IntSet other) { return s.containsAll(other );
    public IntIterator iterator(final int from, final int to) {  
      return new IntIterator() {
        IntIterator iter = s.iterator(from,to);
        public boolean hasNext() { return iter.hasNext(); }
        public int next() { return iter.next(); }
        public void remove() {
          throw new UnsupportedOperationException();
       
      };
    }
    public int floor(int i) { return s.floor(i); }
    public int ceil(int i) { return s.ceil(i); }
    public IntSet clone() throws CloneNotSupportedException { return s.clone(); }
  }
 
  /**
   * An implementation of an unmodifiable SparseSequence view.
   * @author Emina Torlak
   */
  private static final class UnmodifiableSparseSequence<V> extends AbstractSparseSequence<V> {
    private final SparseSequence<V> s;
   
    UnmodifiableSparseSequence(SparseSequence<V> s) {
      this.s = s;
    }
   
    public Iterator<IndexedEntry<V>> iterator(final int from, final int to) {
      return new Iterator<IndexedEntry<V>>() {
        Iterator<IndexedEntry<V>> iter = s.iterator(from, to);
        public boolean hasNext() {
          return iter.hasNext();
        }

        public IndexedEntry<V> next() {
          return iter.next();
        }

        public void remove() {
          throw new UnsupportedOperationException();
        }
       
      };
    }

    public int size() {          return s.size(); }
    public void clear() {        throw new UnsupportedOperationException(); }
    public V put(int index, V value) {  throw new UnsupportedOperationException(); }
    public V get(int index) {       return s.get(index); }
    public V remove(int index) {    throw new UnsupportedOperationException(); }
    public IndexedEntry<V> first() {  return s.first(); }
    public IndexedEntry<V> last() {    return s.last(); }
   
    public IndexedEntry<V> ceil(int index) {  return s.ceil(index); }
    public IndexedEntry<V> floor(int index) {  return s.floor(index); }
    public boolean containsIndex(int index) {  return s.containsIndex(index); }
    public boolean contains(Object value) {    return s.contains(value); }
   
    public SparseSequence<V> clone() throws CloneNotSupportedException {
      return s.clone();
    }
   
  }
}
TOP

Related Classes of kodkod.util.ints.Ints$UnmodifiableSparseSequence

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.