Package net.hydromatic.optiq.util

Source Code of net.hydromatic.optiq.util.BitSets$Closure

/*
// 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 net.hydromatic.optiq.util;

import org.eigenbase.util.ImmutableIntList;
import org.eigenbase.util.IntList;

import java.util.*;

/**
* Utility functions for {@link BitSet}.
*/
public final class BitSets {
  private BitSets() {
    throw new AssertionError("no instances!");
  }

  /**
   * Returns true if all bits set in the second parameter are also set in the
   * first. In other words, whether x is a super-set of y.
   *
   * @param set0 Containing bitmap
   * @param set1 Bitmap to be checked
   *
   * @return Whether all bits in set1 are set in set0
   */
  public static boolean contains(BitSet set0, BitSet set1) {
    for (int i = set1.nextSetBit(0); i >= 0; i = set1.nextSetBit(i + 1)) {
      if (!set0.get(i)) {
        return false;
      }
    }
    return true;
  }

  /**
   * Returns an iterable over the bits in a bitmap that are set to '1'.
   *
   * <p>This allows you to iterate over a bit set using a 'foreach' construct.
   * For instance:
   *
   * <blockquote><code>
   * BitSet bitSet;<br>
   * for (int i : Util.toIter(bitSet)) {<br>
   * &nbsp;&nbsp;print(i);<br>
   * }</code></blockquote>
   *
   * @param bitSet Bit set
   * @return Iterable
   */
  public static Iterable<Integer> toIter(final BitSet bitSet) {
    return new Iterable<Integer>() {
      public Iterator<Integer> iterator() {
        return new Iterator<Integer>() {
          int i = bitSet.nextSetBit(0);

          public boolean hasNext() {
            return i >= 0;
          }

          public Integer next() {
            int prev = i;
            i = bitSet.nextSetBit(i + 1);
            return prev;
          }

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

  /**
   * Converts a bitset to a list.
   *
   * <p>The list is mutable, and future changes to the list do not affect the
   * contents of the bit set.
   *
   * @param bitSet Bit set
   * @return List of set bits
   */
  public static IntList toList(final BitSet bitSet) {
    final IntList list = new IntList();
    for (int i = bitSet.nextSetBit(0); i >= 0; i = bitSet.nextSetBit(i + 1)) {
      list.add(i);
    }
    return list;
  }

  /**
   * Converts a BitSet to an array.
   *
   * @param bitSet Bit set
   * @return Array of set bits
   */
  public static int[] toArray(final BitSet bitSet) {
    final int[] integers = new int[bitSet.cardinality()];
    int j = 0;
    for (int i = bitSet.nextSetBit(0); i >= 0; i = bitSet.nextSetBit(i + 1)) {
      integers[j++] = i;
    }
    return integers;
  }

  /**
   * Creates a bitset with given bits set.
   *
   * <p>For example, {@code of(0, 3)} returns a bit set with bits {0, 3}
   * set.
   *
   * @param bits Array of bits to set
   * @return Bit set
   */
  public static BitSet of(int... bits) {
    final BitSet bitSet = new BitSet();
    for (int bit : bits) {
      bitSet.set(bit);
    }
    return bitSet;
  }

  /**
   * Creates a BitSet with given bits set.
   *
   * <p>For example, {@code of(new Integer[] {0, 3})} returns a bit set
   * with bits {0, 3} set.
   *
   * @param bits Array of bits to set
   * @return Bit set
   */
  public static BitSet of(Integer[] bits) {
    final BitSet bitSet = new BitSet();
    for (int bit : bits) {
      bitSet.set(bit);
    }
    return bitSet;
  }

  /**
   * Creates a BitSet with given bits set.
   *
   * <p>For example, {@code of(Arrays.asList(0, 3)) } returns a bit set
   * with bits {0, 3} set.
   *
   * @param bits Collection of bits to set
   * @return Bit set
   */
  public static BitSet of(Iterable<? extends Number> bits) {
    final BitSet bitSet = new BitSet();
    for (Number bit : bits) {
      bitSet.set(bit.intValue());
    }
    return bitSet;
  }

  /**
   * Creates a BitSet with given bits set.
   *
   * <p>For example, {@code of(ImmutableIntList.of(0, 3))} returns a bit set
   * with bits {0, 3} set.
   *
   * @param bits Collection of bits to set
   * @return Bit set
   */
  public static BitSet of(ImmutableIntList bits) {
    final BitSet bitSet = new BitSet();
    for (int i = 0, n = bits.size(); i < n; i++) {
      bitSet.set(bits.getInt(i));
    }
    return bitSet;
  }

  /**
   * Creates a bitset with bits from {@code fromIndex} (inclusive) to
   * specified {@code toIndex} (exclusive) set to {@code true}.
   *
   * <p>For example, {@code range(0, 3)} returns a bit set with bits
   * {0, 1, 2} set.
   *
   * @param fromIndex Index of the first bit to be set.
   * @param toIndex   Index after the last bit to be set.
   * @return Bit set
   */
  public static BitSet range(int fromIndex, int toIndex) {
    final BitSet bitSet = new BitSet();
    if (toIndex > fromIndex) {
      // Avoid http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6222207
      // "BitSet internal invariants may be violated"
      bitSet.set(fromIndex, toIndex);
    }
    return bitSet;
  }

  /** Creates a BitSet with bits between 0 and {@code toIndex} set. */
  public static BitSet range(int toIndex) {
    return range(0, toIndex);
  }

  /** Sets all bits in a given BitSet corresponding to integers from a list. */
  public static void setAll(BitSet bitSet, Iterable<? extends Number> list) {
    for (Number number : list) {
      bitSet.set(number.intValue());
    }
  }

  /** Returns a BitSet that is the union of the given BitSets. Does not modify
   * any of the inputs. */
  public static BitSet union(BitSet set0, BitSet... sets) {
    final BitSet s = (BitSet) set0.clone();
    for (BitSet set : sets) {
      s.or(set);
    }
    return s;
  }

  /** Returns the previous clear bit.
   *
   * <p>Has same behavior as {@link BitSet#previousClearBit}, but that method
   * does not exist before 1.7. */
  public static int previousClearBit(BitSet bitSet, int fromIndex) {
    if (fromIndex < -1) {
      throw new IndexOutOfBoundsException();
    }
    while (fromIndex >= 0) {
      if (!bitSet.get(fromIndex)) {
        return fromIndex;
      }
      --fromIndex;
    }
    return -1;
  }

  /** Computes the closure of a map from integers to bits.
   *
   * <p>The input must have an entry for each position.
   *
   * <p>Does not modify the input map or its bit sets. */
  public static SortedMap<Integer, BitSet> closure(
      SortedMap<Integer, BitSet> equivalence) {
    final Closure closure = new Closure(equivalence);
    return closure.closure;
  }

  /** Populates a {@link BitSet} from an iterable, such as a list of integer. */
  public static void populate(BitSet bitSet, Iterable<? extends Number> list) {
    for (Number number : list) {
      bitSet.set(number.intValue());
    }
  }

  /** Populates a {@link BitSet} from an
   *  {@link org.eigenbase.util.ImmutableIntList}. */
  public static void populate(BitSet bitSet, ImmutableIntList list) {
    for (int i = 0; i < list.size(); i++) {
      bitSet.set(list.getInt(i));
    }
  }

  /**
   * Setup equivalence Sets for each position. If i & j are equivalent then
   * they will have the same equivalence Set. The algorithm computes the
   * closure relation at each position for the position wrt to positions
   * greater than it. Once a closure is computed for a position, the closure
   * Set is set on all its descendants. So the closure computation bubbles up
   * from lower positions and the final equivalence Set is propagated down
   * from the lowest element in the Set.
   */
  private static class Closure {
    private SortedMap<Integer, BitSet> equivalence;
    private final SortedMap<Integer, BitSet> closure =
        new TreeMap<Integer, BitSet>();

    public Closure(SortedMap<Integer, BitSet> equivalence) {
      this.equivalence = equivalence;
      final ImmutableIntList keys =
          ImmutableIntList.copyOf(equivalence.keySet());
      for (int pos : keys) {
        computeClosure(pos);
      }
    }

    private BitSet computeClosure(int pos) {
      BitSet o = closure.get(pos);
      if (o != null) {
        return o;
      }
      BitSet b = equivalence.get(pos);
      o = (BitSet) b.clone();
      int i = b.nextSetBit(pos + 1);
      for (; i >= 0; i = b.nextSetBit(i + 1)) {
        o.or(computeClosure(i));
      }
      closure.put(pos, o);
      i = o.nextSetBit(pos + 1);
      for (; i >= 0; i = b.nextSetBit(i + 1)) {
        closure.put(i, o);
      }
      return o;
    }
  }
}

// End BitSets.java
TOP

Related Classes of net.hydromatic.optiq.util.BitSets$Closure

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.