/*
 * Copyright (c) 2002 - 2006 IBM Corporation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 */
package com.ibm.wala.core.tests.basic;

import com.ibm.wala.core.tests.util.WalaTestCase;
import com.ibm.wala.util.collections.BimodalMap;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.collections.Iterator2Collection;
import com.ibm.wala.util.collections.Iterator2Iterable;
import com.ibm.wala.util.collections.SmallMap;
import com.ibm.wala.util.graph.Graph;
import com.ibm.wala.util.graph.NumberedGraph;
import com.ibm.wala.util.graph.dominators.Dominators;
import com.ibm.wala.util.graph.impl.SlowSparseNumberedGraph;
import com.ibm.wala.util.graph.traverse.BFSPathFinder;
import com.ibm.wala.util.graph.traverse.BoundedBFSIterator;
import com.ibm.wala.util.intset.BasicNaturalRelation;
import com.ibm.wala.util.intset.BimodalMutableIntSetFactory;
import com.ibm.wala.util.intset.BitVector;
import com.ibm.wala.util.intset.BitVectorBase;
import com.ibm.wala.util.intset.BitVectorIntSetFactory;
import com.ibm.wala.util.intset.IBinaryNaturalRelation;
import com.ibm.wala.util.intset.IntPair;
import com.ibm.wala.util.intset.IntSet;
import com.ibm.wala.util.intset.IntSetUtil;
import com.ibm.wala.util.intset.IntegerUnionFind;
import com.ibm.wala.util.intset.LongSet;
import com.ibm.wala.util.intset.LongSetUtil;
import com.ibm.wala.util.intset.MutableIntSet;
import com.ibm.wala.util.intset.MutableIntSetFactory;
import com.ibm.wala.util.intset.MutableLongSet;
import com.ibm.wala.util.intset.MutableLongSetFactory;
import com.ibm.wala.util.intset.MutableSharedBitVectorIntSetFactory;
import com.ibm.wala.util.intset.MutableSparseIntSetFactory;
import com.ibm.wala.util.intset.MutableSparseLongSetFactory;
import com.ibm.wala.util.intset.OffsetBitVector;
import com.ibm.wala.util.intset.SemiSparseMutableIntSet;
import com.ibm.wala.util.intset.SemiSparseMutableIntSetFactory;
import com.ibm.wala.util.intset.SparseIntSet;
import com.ibm.wala.util.intset.SparseLongSet;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import org.junit.Assert;
import org.junit.Test;

/** JUnit tests for some primitive operations. */
@SuppressWarnings("UnnecessaryBoxing")
public class PrimitivesTest extends WalaTestCase {

  /** Test the MutableSparseIntSet implementation */
  private static void doMutableIntSet(MutableIntSetFactory<?> factory) {
    MutableIntSet v = factory.parse("{9,17}");
    MutableIntSet w = factory.make(new int[] {});
    MutableIntSet x = factory.make(new int[] {7, 4, 2, 4, 2, 2});
    MutableIntSet y = factory.make(new int[] {7, 7, 7, 2, 7, 1});
    MutableIntSet z = factory.parse("{ 9 }");

    System.err.println(w); // { }
    System.err.println(x); // { 2 4 7 }
    System.err.println(y); // { 1 2 7 }
    System.err.println(z); // { 9 }

    MutableIntSet temp = factory.makeCopy(x);
    temp.intersectWith(y);
    System.err.println(temp); // { 2 7 }
    temp.copySet(x);
    temp.addAll(y);
    System.err.println(temp); // { 1 2 4 7 }
    temp.copySet(x);
    System.err.println(IntSetUtil.diff(x, y, factory)); // { 4 }
    System.err.println(IntSetUtil.diff(v, z, factory)); // { 17 }
    System.err.println(IntSetUtil.diff(z, v, factory)); // { }

    // Assert.assertTrue(x.union(z).intersection(y.union(z)).equals(x.intersection(y).union(z)));
    MutableIntSet temp1 = factory.makeCopy(x);
    MutableIntSet temp2 = factory.makeCopy(x);
    MutableIntSet tempY = factory.makeCopy(y);
    temp1.addAll(z);
    tempY.addAll(z);
    temp1.intersectWith(tempY);
    temp2.intersectWith(y);
    temp2.addAll(z);
    Assert.assertTrue(temp1.sameValue(temp2));

    // Assert.assertTrue(x.union(z).diff(z).equals(x));
    Assert.assertTrue(w.isEmpty());
    Assert.assertTrue(IntSetUtil.diff(x, x, factory).isEmpty());
    Assert.assertTrue(IntSetUtil.diff(z, v, factory).isEmpty());
    Assert.assertTrue(IntSetUtil.diff(v, z, factory).sameValue(SparseIntSet.singleton(17)));
    Assert.assertTrue(IntSetUtil.diff(z, v, factory).isEmpty());
    Assert.assertTrue(z.isSubset(v));
    temp = factory.make();
    temp.add(4);
    System.err.println(temp); // { 4 }
    temp.add(7);
    System.err.println(temp); // { 4 7 }
    temp.add(2);
    System.err.println(temp); // { 2 4 7 }
    System.err.println(x); // { 2 4 7 }
    Assert.assertTrue(temp.sameValue(x));

    MutableIntSet a =
        factory.parse(
            "{1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49,51,53,55,57,59}");
    System.err.println(a); // { 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33
    // 35
    // 37 39 41 43 45 47 49 51 53 55 57 59 }
    Assert.assertTrue(a.sameValue(a));
    IntSet i = a.intersection(temp);
    Assert.assertTrue(i.sameValue(SparseIntSet.singleton(7)));
    a.add(100);
    Assert.assertTrue(a.sameValue(a));

    MutableIntSet b =
        factory.parse(
            "{1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49,51,53,55,57,59,100}");
    Assert.assertTrue(a.sameValue(b));
    Assert.assertTrue(a.isSubset(b));

    IntSet f = IntSetUtil.diff(b, factory.parse("{7,8,9}"), factory);
    System.err.println(f);
    Assert.assertFalse(f.contains(7));
    Assert.assertFalse(f.contains(8));
    Assert.assertFalse(f.contains(9));
    Assert.assertFalse(f.sameValue(b));
    Assert.assertTrue(f.isSubset(b));

    IntSet tmp =
        factory.parse(
            "{2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,51,53,55,57,59,61,63}");
    f = IntSetUtil.diff(b, tmp, factory);
    System.err.println(f);
    Assert.assertFalse(f.sameValue(b));
    Assert.assertTrue(f.isSubset(b));
    Assert.assertFalse(f.contains(51));
    Assert.assertFalse(f.contains(53));
    Assert.assertFalse(f.contains(55));
    Assert.assertFalse(f.contains(57));
    Assert.assertFalse(f.contains(59));
    Assert.assertTrue(f.contains(100));

    tmp =
        factory.parse(
            "{2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,51,53,55,57,59,61,63,100}");
    f = IntSetUtil.diff(b, tmp, factory);
    System.err.println(f);
    Assert.assertFalse(f.sameValue(b));
    Assert.assertTrue(f.isSubset(b));
    Assert.assertFalse(f.contains(51));
    Assert.assertFalse(f.contains(53));
    Assert.assertFalse(f.contains(55));
    Assert.assertFalse(f.contains(57));
    Assert.assertFalse(f.contains(59));
    Assert.assertFalse(f.contains(100));

    b = factory.makeCopy(a);
    Assert.assertTrue(a.sameValue(b));
    b.remove(1);
    b.add(0);
    Assert.assertFalse(a.sameValue(b));

    a = factory.parse("{1}");
    Assert.assertFalse(a.isSubset(b));
    b.remove(0);
    Assert.assertFalse(a.isSubset(b));
    a.remove(1);
    Assert.assertTrue(a.isEmpty());
    IntSet ignored = a.intersection(temp);
    Assert.assertTrue(a.isEmpty());

    temp2 = factory.make();
    Assert.assertTrue(temp2.sameValue(a));

    a =
        factory.parse(
            "{2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,51,53,55,57,59,61,63}");
    b =
        factory.parse(
            "{2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62}");
    MutableIntSet c =
        factory.parse("{2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50}");
    MutableIntSet d =
        factory.parse("{2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50}");
    MutableIntSet e = factory.parse("{2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34}");

    Assert.assertTrue(e.isSubset(d));
    e.addAll(d);
    Assert.assertTrue(e.isSubset(d));
    e.remove(12);
    Assert.assertTrue(e.isSubset(d));
    e.add(105);
    Assert.assertFalse(e.isSubset(d));

    Assert.assertFalse(b.isSubset(a));

    b.add(53);
    Assert.assertFalse(b.isSubset(a));

    a.add(52);
    a.remove(52);
    Assert.assertFalse(b.isSubset(a));

    c.add(55);
    Assert.assertFalse(c.isSubset(b));

    d.add(53);
    Assert.assertTrue(d.isSubset(b));

    d = factory.make();
    d.copySet(c);
    Assert.assertFalse(d.isSubset(b));

    a = factory.parse("{2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50}");
    b = factory.parse("{2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48}");
    Assert.assertFalse(a.sameValue(b));
    b.add(50);
    Assert.assertTrue(a.sameValue(b));
    a.add(11);
    b.add(11);
    Assert.assertTrue(a.sameValue(b));

    a = factory.parse("{2,4,6,8,10,12,14,16,18,20,50}");
    b = factory.parse("{24,26,28,30,32,34,36,38,40,42,44,46,48}");
    c = factory.parse("{2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50}");
    a.addAll(b);
    a.add(22);
    Assert.assertTrue(a.sameValue(c));

    a = factory.parse("{2,4,6,8,10,12,14,16,18,20,50}");
    b = factory.parse("{24,26,28,30,32,34,36,38,40,42,44,46,48}");
    c = factory.parse("{2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50}");
    b.addAll(factory.parse("{22}"));
    a.addAll(b);
    Assert.assertTrue(a.sameValue(c));

    a = factory.parse("{2,4,6,8,10,12,14,16,18,20}");
    b = factory.parse("{22,24,26,28,30,32,34,36,38,40,42,44,46,48}");
    c = factory.parse("{2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50}");
    c.remove(22);
    a.addAll(b);
    Assert.assertFalse(a.sameValue(c));

    a =
        factory.parse(
            "{1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49,51,53,55,57,59}");
    System.err.println(a); // { 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33
    // 35
    // 37 39 41 43 45 47 49 51 53 55 57 59 }
    Assert.assertTrue(a.sameValue(a));
    i = a.intersection(temp);
    Assert.assertTrue(i.sameValue(SparseIntSet.singleton(7)));
    a.add(100);
    Assert.assertTrue(a.sameValue(a));

    b =
        factory.parse(
            "{1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49,51,53,55,57,59,100}");
    Assert.assertTrue(a.sameValue(b));
    Assert.assertTrue(a.isSubset(b));

    b = factory.makeCopy(a);
    Assert.assertTrue(a.sameValue(b));
    b.remove(1);
    b.add(0);
    Assert.assertFalse(a.sameValue(b));

    a.clear();
    Assert.assertTrue(a.isEmpty());

    a = factory.parse("{1}");
    Assert.assertFalse(a.isSubset(b));
    b.remove(0);
    Assert.assertFalse(a.isSubset(b));
    a.remove(1);
    Assert.assertTrue(a.isEmpty());
    ignored = a.intersection(temp);
    Assert.assertTrue(a.isEmpty());

    temp2 = factory.make();
    Assert.assertTrue(temp2.sameValue(a));

    for (int idx = 500; idx < 550; ) {
      for (int xx = 0; xx < 50; xx++, idx++) {
        temp2.add(idx);
      }
      System.err.println(temp2);
    }

    for (int idx = 3000; idx < 3200; ) {
      for (int xx = 0; xx < 50; xx++, idx++) {
        temp2.add(idx);
      }
      System.err.println(temp2);
    }

    temp2.clear();
    Assert.assertTrue(temp2.isEmpty());

    temp2 = factory.make();
    Assert.assertTrue(temp2.sameValue(a));

    for (int idx = 500; idx < 550; ) {
      for (int xx = 0; xx < 50; xx++, idx++) {
        temp2.add(idx);
      }
      System.err.println(temp2);
    }

    for (int idx = 0; idx < 25; idx++) {
      temp2.add(idx);
      System.err.println(temp2);
    }

    temp2.clear();
    Assert.assertTrue(temp2.isEmpty());
  }

  /** Test the MutableSharedBitVectorIntSet implementation */
  @Test
  public void testMutableSharedBitVectorIntSet() {
    doMutableIntSet(new MutableSharedBitVectorIntSetFactory());
  }

  /** Test the MutableSparseIntSet implementation */
  @Test
  public void testMutableSparseIntSet() {
    doMutableIntSet(new MutableSparseIntSetFactory());
  }

  /** Test the BimodalMutableSparseIntSet implementation */
  @Test
  public void testBimodalMutableSparseIntSet() {
    doMutableIntSet(new BimodalMutableIntSetFactory());
  }

  /** Test the BitVectorIntSet implementation */
  @Test
  public void testBitVectorIntSet() {
    doMutableIntSet(new BitVectorIntSetFactory());
  }

  /** Test the SemiSparseMutableIntSet implementation */
  @Test
  public void testSemiSparseMutableIntSet() {
    doMutableIntSet(new SemiSparseMutableIntSetFactory());
  }

  /** Test the MutableSparseIntSet implementation */
  private static void doMutableLongSet(MutableLongSetFactory factory) {
    MutableLongSet v = factory.parse("{9,17}");
    MutableLongSet w = factory.make(new long[] {});
    MutableLongSet x = factory.make(new long[] {7, 4, 2, 4, 2, 2});
    MutableLongSet y = factory.make(new long[] {7, 7, 7, 2, 7, 1});
    MutableLongSet z = factory.parse("{ 9 }");

    System.err.println(w); // { }
    System.err.println(x); // { 2 4 7 }
    System.err.println(y); // { 1 2 7 }
    System.err.println(z); // { 9 }

    MutableLongSet temp = factory.makeCopy(x);
    temp.intersectWith(y);
    System.err.println(temp); // { 2 7 }
    temp.copySet(x);
    temp.addAll(y);
    System.err.println(temp); // { 1 2 4 7 }
    temp.copySet(x);
    System.err.println(LongSetUtil.diff(x, y, factory)); // { 4 }
    System.err.println(LongSetUtil.diff(v, z, factory)); // { 17 }
    System.err.println(LongSetUtil.diff(z, v, factory)); // { }

    // Assert.assertTrue(x.union(z).intersection(y.union(z)).equals(x.intersection(y).union(z)));
    MutableLongSet temp1 = factory.makeCopy(x);
    MutableLongSet temp2 = factory.makeCopy(x);
    MutableLongSet tempY = factory.makeCopy(y);
    temp1.addAll(z);
    tempY.addAll(z);
    temp1.intersectWith(tempY);
    temp2.intersectWith(y);
    temp2.addAll(z);
    Assert.assertTrue(temp1.sameValue(temp2));

    // Assert.assertTrue(x.union(z).diff(z).equals(x));
    Assert.assertTrue(w.isEmpty());
    Assert.assertTrue(LongSetUtil.diff(x, x, factory).isEmpty());
    Assert.assertTrue(LongSetUtil.diff(z, v, factory).isEmpty());
    Assert.assertTrue(LongSetUtil.diff(v, z, factory).sameValue(SparseLongSet.singleton(17)));
    Assert.assertTrue(LongSetUtil.diff(z, v, factory).isEmpty());
    Assert.assertTrue(z.isSubset(v));
    temp = factory.make();
    temp.add(4);
    System.err.println(temp); // { 4 }
    temp.add(7);
    System.err.println(temp); // { 4 7 }
    temp.add(2);
    System.err.println(temp); // { 2 4 7 }
    System.err.println(x); // { 2 4 7 }
    Assert.assertTrue(temp.sameValue(x));

    MutableLongSet a =
        factory.parse(
            "{1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49,51,53,55,57,59}");
    System.err.println(a); // { 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33
    // 35
    // 37 39 41 43 45 47 49 51 53 55 57 59 }
    Assert.assertTrue(a.sameValue(a));
    LongSet i = a.intersection(temp);
    Assert.assertTrue(i.sameValue(SparseLongSet.singleton(7)));
    a.add(100);
    Assert.assertTrue(a.sameValue(a));

    MutableLongSet b =
        factory.parse(
            "{1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49,51,53,55,57,59,100}");
    Assert.assertTrue(a.sameValue(b));
    Assert.assertTrue(a.isSubset(b));

    LongSet f = LongSetUtil.diff(b, factory.parse("{7,8,9}"), factory);
    System.err.println(f);
    Assert.assertFalse(f.contains(7));
    Assert.assertFalse(f.contains(8));
    Assert.assertFalse(f.contains(9));
    Assert.assertFalse(f.sameValue(b));
    Assert.assertTrue(f.isSubset(b));

    LongSet tmp =
        factory.parse(
            "{2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,51,53,55,57,59,61,63}");
    f = LongSetUtil.diff(b, tmp, factory);
    System.err.println(f);
    Assert.assertFalse(f.sameValue(b));
    Assert.assertTrue(f.isSubset(b));
    Assert.assertFalse(f.contains(51));
    Assert.assertFalse(f.contains(53));
    Assert.assertFalse(f.contains(55));
    Assert.assertFalse(f.contains(57));
    Assert.assertFalse(f.contains(59));
    Assert.assertTrue(f.contains(100));

    tmp =
        factory.parse(
            "{2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,51,53,55,57,59,61,63,100}");
    f = LongSetUtil.diff(b, tmp, factory);
    System.err.println(f);
    Assert.assertFalse(f.sameValue(b));
    Assert.assertTrue(f.isSubset(b));
    Assert.assertFalse(f.contains(51));
    Assert.assertFalse(f.contains(53));
    Assert.assertFalse(f.contains(55));
    Assert.assertFalse(f.contains(57));
    Assert.assertFalse(f.contains(59));
    Assert.assertFalse(f.contains(100));

    b = factory.makeCopy(a);
    Assert.assertTrue(a.sameValue(b));
    b.remove(1);
    b.add(0);
    Assert.assertFalse(a.sameValue(b));

    a = factory.parse("{1}");
    Assert.assertFalse(a.isSubset(b));
    b.remove(0);
    Assert.assertFalse(a.isSubset(b));
    a.remove(1);
    Assert.assertTrue(a.isEmpty());
    LongSet ignored = a.intersection(temp);
    Assert.assertTrue(a.isEmpty());

    temp2 = factory.make();
    Assert.assertTrue(temp2.sameValue(a));

    a =
        factory.parse(
            "{2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,51,53,55,57,59,61,63}");
    b =
        factory.parse(
            "{2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62}");
    MutableLongSet c =
        factory.parse("{2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50}");
    MutableLongSet d =
        factory.parse("{2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50}");
    MutableLongSet e = factory.parse("{2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34}");

    Assert.assertTrue(e.isSubset(d));
    e.addAll(d);
    Assert.assertTrue(e.isSubset(d));
    e.remove(12);
    Assert.assertTrue(e.isSubset(d));
    e.add(105);
    Assert.assertFalse(e.isSubset(d));

    Assert.assertFalse(b.isSubset(a));

    b.add(53);
    Assert.assertFalse(b.isSubset(a));

    a.add(52);
    a.remove(52);
    Assert.assertFalse(b.isSubset(a));

    c.add(55);
    Assert.assertFalse(c.isSubset(b));

    d.add(53);
    Assert.assertTrue(d.isSubset(b));

    d = factory.make();
    d.copySet(c);
    Assert.assertFalse(d.isSubset(b));

    a = factory.parse("{2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50}");
    b = factory.parse("{2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48}");
    Assert.assertFalse(a.sameValue(b));
    b.add(50);
    Assert.assertTrue(a.sameValue(b));
    a.add(11);
    b.add(11);
    Assert.assertTrue(a.sameValue(b));

    a = factory.parse("{2,4,6,8,10,12,14,16,18,20,50}");
    b = factory.parse("{24,26,28,30,32,34,36,38,40,42,44,46,48}");
    c = factory.parse("{2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50}");
    a.addAll(b);
    a.add(22);
    Assert.assertTrue(a.sameValue(c));

    a = factory.parse("{2,4,6,8,10,12,14,16,18,20,50}");
    b = factory.parse("{24,26,28,30,32,34,36,38,40,42,44,46,48}");
    c = factory.parse("{2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50}");
    b.addAll(factory.parse("{22}"));
    a.addAll(b);
    Assert.assertTrue(a.sameValue(c));

    a = factory.parse("{2,4,6,8,10,12,14,16,18,20}");
    b = factory.parse("{22,24,26,28,30,32,34,36,38,40,42,44,46,48}");
    c = factory.parse("{2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50}");
    c.remove(22);
    a.addAll(b);
    Assert.assertFalse(a.sameValue(c));

    a =
        factory.parse(
            "{1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49,51,53,55,57,59}");
    System.err.println(a); // { 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33
    // 35
    // 37 39 41 43 45 47 49 51 53 55 57 59 }
    Assert.assertTrue(a.sameValue(a));
    i = a.intersection(temp);
    Assert.assertTrue(i.sameValue(SparseLongSet.singleton(7)));
    a.add(100);
    Assert.assertTrue(a.sameValue(a));

    b =
        factory.parse(
            "{1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49,51,53,55,57,59,100}");
    Assert.assertTrue(a.sameValue(b));
    Assert.assertTrue(a.isSubset(b));

    b = factory.makeCopy(a);
    Assert.assertTrue(a.sameValue(b));
    b.remove(1);
    b.add(0);
    Assert.assertFalse(a.sameValue(b));

    a = factory.parse("{1}");
    Assert.assertFalse(a.isSubset(b));
    b.remove(0);
    Assert.assertFalse(a.isSubset(b));
    a.remove(1);
    Assert.assertTrue(a.isEmpty());
    ignored = a.intersection(temp);
    Assert.assertTrue(a.isEmpty());

    temp2 = factory.make();
    Assert.assertTrue(temp2.sameValue(a));

    for (int idx = 500; idx < 550; ) {
      for (int xx = 0; xx < 50; xx++, idx++) {
        temp2.add(idx);
      }
      System.err.println(temp2);
    }

    for (int idx = 3000; idx < 3200; ) {
      for (int xx = 0; xx < 50; xx++, idx++) {
        temp2.add(idx);
      }
      System.err.println(temp2);
    }

    temp2 = factory.make();
    Assert.assertTrue(temp2.sameValue(a));

    for (int idx = 500; idx < 550; ) {
      for (int xx = 0; xx < 50; xx++, idx++) {
        temp2.add(idx);
      }
      System.err.println(temp2);
    }

    for (int idx = 0; idx < 25; idx++) {
      temp2.add(idx);
      System.err.println(temp2);
    }
  }

  /** Test the MutableSparseLongSet implementation */
  @Test
  public void testMutableSparseLongSet() {
    doMutableLongSet(new MutableSparseLongSetFactory());
  }

  @Test
  public void testSmallMap() {
    SmallMap<Integer, Integer> M = new SmallMap<>();
    Integer I1 = Integer.valueOf(1);
    Integer I2 = Integer.valueOf(2);
    Integer I3 = Integer.valueOf(3);
    M.put(I1, I1);
    M.put(I2, I2);
    M.put(I3, I3);

    Integer I = M.get(Integer.valueOf(2));
    Assert.assertNotNull(I);
    Assert.assertEquals(I, I2);

    I = M.get(Integer.valueOf(4));
    Assert.assertNull(I);

    I = M.put(Integer.valueOf(2), Integer.valueOf(3));
    Assert.assertEquals(I, I2);
    I = M.get(I2);
    Assert.assertEquals(I, I3);
  }

  @Test
  public void testBimodalMap() {
    Map<Integer, Integer> M = new BimodalMap<>(3);
    Integer I1 = Integer.valueOf(1);
    Integer I2 = Integer.valueOf(2);
    Integer I3 = Integer.valueOf(3);
    Integer I4 = Integer.valueOf(4);
    Integer I5 = Integer.valueOf(5);
    Integer I6 = Integer.valueOf(6);
    M.put(I1, I1);
    M.put(I2, I2);
    M.put(I3, I3);

    Integer I = M.get(Integer.valueOf(2));
    Assert.assertNotNull(I);
    Assert.assertEquals(I, I2);

    I = M.get(Integer.valueOf(4));
    Assert.assertNull(I);

    I = M.put(Integer.valueOf(2), Integer.valueOf(3));
    Assert.assertEquals(I, I2);
    I = M.get(I2);
    Assert.assertEquals(I, I3);

    M.put(I4, I4);
    M.put(I5, I5);
    M.put(I6, I6);
    I = M.get(Integer.valueOf(4));
    Assert.assertNotNull(I);
    Assert.assertEquals(I, I4);

    I = M.get(Integer.valueOf(7));
    Assert.assertNull(I);

    I = M.put(Integer.valueOf(2), Integer.valueOf(6));
    Assert.assertEquals(I, I3);
    I = M.get(I2);
    Assert.assertEquals(I, I6);
  }

  @Test
  public void testBFSPathFinder() {
    NumberedGraph<Integer> G = makeBFSTestGraph();

    // path from 0 to 8
    BFSPathFinder<Integer> pf = new BFSPathFinder<>(G, G.getNode(0), G.getNode(8));
    List<Integer> p = pf.find();

    // path should be 8, 6, 4, 2, 0
    System.err.println("Path is " + p);
    for (int i = 0; i < p.size(); i++) {
      Assert.assertEquals((int) p.get(i), new int[] {8, 6, 4, 2, 0}[i]);
    }
  }

  @Test
  public void testBoundedBFS() {
    NumberedGraph<Integer> G = makeBFSTestGraph();

    BoundedBFSIterator<Integer> bfs = new BoundedBFSIterator<>(G, G.getNode(0), 0);
    Collection<Integer> c = Iterator2Collection.toSet(bfs);
    Assert.assertEquals(1, c.size());

    bfs = new BoundedBFSIterator<>(G, G.getNode(0), 1);
    c = Iterator2Collection.toSet(bfs);
    Assert.assertEquals(3, c.size());

    bfs = new BoundedBFSIterator<>(G, G.getNode(0), 2);
    c = Iterator2Collection.toSet(bfs);
    Assert.assertEquals(5, c.size());

    bfs = new BoundedBFSIterator<>(G, G.getNode(0), 3);
    c = Iterator2Collection.toSet(bfs);
    Assert.assertEquals(7, c.size());

    bfs = new BoundedBFSIterator<>(G, G.getNode(0), 4);
    c = Iterator2Collection.toSet(bfs);
    Assert.assertEquals(9, c.size());

    bfs = new BoundedBFSIterator<>(G, G.getNode(0), 5);
    c = Iterator2Collection.toSet(bfs);
    Assert.assertEquals(10, c.size());

    bfs = new BoundedBFSIterator<>(G, G.getNode(0), 500);
    c = Iterator2Collection.toSet(bfs);
    Assert.assertEquals(10, c.size());
  }

  private static NumberedGraph<Integer> makeBFSTestGraph() {
    // test graph
    NumberedGraph<Integer> G = SlowSparseNumberedGraph.make();

    // add 10 nodes
    Integer[] nodes = new Integer[10];
    for (int i = 0; i < nodes.length; i++) G.addNode(nodes[i] = Integer.valueOf(i));

    // edges to i-1, i+1, i+2
    for (int i = 0; i < nodes.length; i++) {
      if (i > 0) {
        G.addEdge(nodes[i], nodes[i - 1]);
      }
      if (i < nodes.length - 1) {
        G.addEdge(nodes[i], nodes[i + 1]);
        if (i < nodes.length - 2) {
          G.addEdge(nodes[i], nodes[i + 2]);
        }
      }
    }
    return G;
  }

  @Test
  public void testDominatorsA() {
    // test graph
    Graph<Object> G = SlowSparseNumberedGraph.make();

    // add nodes
    Object[] nodes = new Object[11];
    for (int i = 0; i < nodes.length; i++) G.addNode(nodes[i] = Integer.valueOf(i));

    // add edges
    G.addEdge(nodes[10], nodes[0]);
    G.addEdge(nodes[10], nodes[1]);
    G.addEdge(nodes[0], nodes[2]);
    G.addEdge(nodes[1], nodes[3]);
    G.addEdge(nodes[2], nodes[5]);
    G.addEdge(nodes[3], nodes[5]);
    G.addEdge(nodes[4], nodes[2]);
    G.addEdge(nodes[5], nodes[8]);
    G.addEdge(nodes[6], nodes[3]);
    G.addEdge(nodes[7], nodes[4]);
    G.addEdge(nodes[8], nodes[7]);
    G.addEdge(nodes[8], nodes[9]);
    G.addEdge(nodes[9], nodes[6]);

    // compute dominators
    Dominators<Object> D = Dominators.make(G, nodes[10]);

    // Assert.assertions
    int i = 0;
    Object[] desired4 = new Object[] {nodes[4], nodes[7], nodes[8], nodes[5], nodes[10]};
    for (Object d4 : Iterator2Iterable.make(D.dominators(nodes[4])))
      Assert.assertSame(d4, desired4[i++]);

    int j = 0;
    Object[] desired5 = new Object[] {nodes[8]};
    for (Object o4 : Iterator2Iterable.make(D.dominatorTree().getSuccNodes(nodes[5]))) {
      Object d = desired5[j++];
      boolean ok = o4.equals(d);
      if (!ok) {
        System.err.println("O4: " + o4);
        System.err.println("desired " + d);
        Assert.assertEquals(o4, d);
      }
    }

    Assert.assertEquals(5, D.dominatorTree().getSuccNodeCount(nodes[10]));
  }

  @Test
  public void testBinaryIntegerRelation() {
    byte[] impl =
        new byte[] {
          BasicNaturalRelation.SIMPLE, BasicNaturalRelation.TWO_LEVEL, BasicNaturalRelation.SIMPLE
        };
    IBinaryNaturalRelation R = new BasicNaturalRelation(impl, BasicNaturalRelation.TWO_LEVEL);
    R.add(3, 5);
    R.add(3, 7);
    R.add(3, 9);
    R.add(3, 11);
    R.add(5, 1);
    int count = 0;
    for (IntPair intPair : R) {
      System.err.println(intPair);
      count++;
    }
    Assert.assertEquals(5, count);

    IntSet x = R.getRelated(3);
    Assert.assertEquals(4, x.size());

    x = R.getRelated(5);
    Assert.assertEquals(1, x.size());

    R.remove(5, 1);
    x = R.getRelated(5);
    Assert.assertNull(x);

    R.add(2, 1);
    R.add(2, 2);
    R.remove(2, 1);
    x = R.getRelated(2);
    Assert.assertEquals(1, x.size());

    R.removeAll(3);
    x = R.getRelated(3);
    Assert.assertNull(x);

    x = R.getRelated(0);
    Assert.assertNull(x);

    for (int i = 0; i < 100; i++) {
      R.add(1, i);
    }
    Assert.assertEquals(100, R.getRelated(1).size());
    R.remove(1, 1);
    Assert.assertEquals(99, R.getRelated(1).size());
  }

  @Test
  public void testUnionFind() {
    int SIZE = 10000;
    IntegerUnionFind uf = new IntegerUnionFind(SIZE);
    int count = countEquivalenceClasses(uf);
    Assert.assertEquals("Got count " + count, count, SIZE);

    uf.union(3, 7);
    Assert.assertEquals(uf.find(3), uf.find(7));
    Assert.assertTrue("Got uf.find(3)=" + uf.find(3), uf.find(3) == 3 || uf.find(3) == 7);

    uf.union(7, SIZE - 1);
    Assert.assertEquals(uf.find(3), uf.find(SIZE - 1));
    Assert.assertTrue(
        "Got uf.find(3)=" + uf.find(3),
        uf.find(3) == 3 || uf.find(3) == 7 || uf.find(3) == SIZE - 1);

    for (int i = 0; i < SIZE - 1; i++) {
      uf.union(i, i + 1);
    }
    count = countEquivalenceClasses(uf);
    Assert.assertEquals("Got count " + count, 1, count);

    uf = new IntegerUnionFind(SIZE);
    for (int i = 0; i < SIZE; i++) {
      if ((i % 2) == 0) {
        uf.union(i, 0);
      } else {
        uf.union(i, 1);
      }
    }
    count = countEquivalenceClasses(uf);
    Assert.assertEquals("Got count " + count, 2, count);
  }

  private static int countEquivalenceClasses(IntegerUnionFind uf) {
    HashSet<Integer> s = HashSetFactory.make();
    for (int i = 0; i < uf.size(); i++) {
      s.add(Integer.valueOf(uf.find(i)));
    }
    return s.size();
  }

  @Test
  public void testBitVector() {
    testSingleBitVector(new BitVector());
  }

  @Test
  public void testOffsetBitVector0_10() {
    testSingleBitVector(new OffsetBitVector(0, 10));
  }

  @Test
  public void testOffsetBitVector10_10() {
    testSingleBitVector(new OffsetBitVector(10, 10));
  }

  @Test
  public void testOffsetBitVector50_10() {
    testSingleBitVector(new OffsetBitVector(50, 10));
  }

  @Test
  public void testOffsetBitVector50_50() {
    testSingleBitVector(new OffsetBitVector(50, 50));
  }

  @Test
  public void testOffsetBitVector100_10() {
    testSingleBitVector(new OffsetBitVector(100, 10));
  }

  private static void testSingleBitVector(BitVectorBase<?> bv) {
    // does the following not automatically scale the bitvector to
    // a reasonable size?
    bv.set(55);

    Assert.assertEquals("bv.max() is " + bv.max(), 55, bv.max());
    Assert.assertTrue(bv.get(55));

    bv.set(59);
    Assert.assertEquals(59, bv.max());
    Assert.assertTrue(bv.get(55));
    Assert.assertTrue(bv.get(59));

    {
      boolean[] gets = new boolean[] {false, true, true};
      int[] bits = new int[] {0, 55, 59};
      for (int i = 0, j = 0; i != -1; i = bv.nextSetBit(i + 1), j++) {
        Assert.assertEquals(i, bits[j]);
        Assert.assertEquals(bv.get(i), gets[j]);
      }
    }

    bv.set(77);

    Assert.assertEquals("bv.max() is " + bv.max(), 77, bv.max());
    {
      boolean[] gets = new boolean[] {false, true, true, true};
      int[] bits = new int[] {0, 55, 59, 77};
      for (int i = 0, j = 0; i != -1; i = bv.nextSetBit(i + 1), j++) {
        Assert.assertEquals(i, bits[j]);
        Assert.assertEquals(bv.get(i), gets[j]);
      }
    }

    bv.set(3);
    Assert.assertEquals("bv.max() is " + bv.max(), 77, bv.max());
    {
      boolean[] gets = new boolean[] {false, true, true, true, true};
      int[] bits = new int[] {0, 3, 55, 59, 77};
      for (int i = 0, j = 0; i != -1; i = bv.nextSetBit(i + 1), j++) {
        Assert.assertEquals(i, bits[j]);
        Assert.assertEquals(bv.get(i), gets[j]);
      }
    }

    System.err.println(bv);
  }

  @Test
  public void testBitVectors() {
    testBitVectors(new BitVector(), new BitVector());
  }

  @Test
  public void testOffsetBitVectors150_10() {
    testBitVectors(new OffsetBitVector(150, 10), new OffsetBitVector(150, 10));
  }

  @Test
  public void testOffsetBitVectors100_200_10() {
    testBitVectors(new OffsetBitVector(100, 10), new OffsetBitVector(200, 10));
  }

  @Test
  public void testOffsetBitVectors100_25_10() {
    testBitVectors(new OffsetBitVector(100, 10), new OffsetBitVector(25, 10));
  }

  @Test
  public void testOffsetBitVectors35_25_20_10() {
    testBitVectors(new OffsetBitVector(35, 20), new OffsetBitVector(25, 10));
  }

  private static <T extends BitVectorBase<T>> void testBitVectors(T v1, T v2) {
    v1.set(100);
    v1.set(101);
    v1.set(102);
    Assert.assertEquals("v1.max() is " + v1.max(), 102, v1.max());

    v2.set(200);
    v2.set(201);
    v2.set(202);
    Assert.assertEquals("v2.max() is " + v2.max(), 202, v2.max());

    Assert.assertTrue(v1.intersectionEmpty(v2));
    Assert.assertTrue(v2.intersectionEmpty(v1));

    v1.or(v2);

    System.err.println("v1 = " + v1 + ", v2 = " + v2);
    Assert.assertFalse("v1 = " + v1 + ", v2 = " + v2, v1.intersectionEmpty(v2));
    Assert.assertFalse("v1 = " + v1 + ", v2 = " + v2, v2.intersectionEmpty(v1));
    Assert.assertEquals("v1.max() is " + v1.max(), 202, v1.max());

    {
      boolean[] gets = new boolean[] {false, true, true, true, true, true, true};
      int[] bits = new int[] {0, 100, 101, 102, 200, 201, 202};
      for (int i = 0, j = 0; i != -1; i = v1.nextSetBit(i + 1), j++) {
        Assert.assertEquals(i, bits[j]);
        Assert.assertEquals(v1.get(i), gets[j]);
      }
    }

    v1.clearAll();
    v2.clearAll();

    v1.set(100);
    v1.set(101);
    v1.set(102);
    v1.set(103);
    v1.set(104);
    v1.set(105);
    Assert.assertEquals("v1.max() is " + v1.max(), 105, v1.max());

    v2.set(103);
    v2.set(104);
    v2.set(200);
    v2.set(201);
    Assert.assertEquals("v2.max() is " + v2.max(), 201, v2.max());

    v1.and(v2);
    Assert.assertEquals("v1.max() is " + v1.max(), 104, v1.max());

    {
      boolean[] gets = new boolean[] {false, true, true};
      int[] bits = new int[] {0, 103, 104};
      for (int i = 0, j = 0; i != -1; i = v1.nextSetBit(i + 1), j++) {
        Assert.assertEquals(i, bits[j]);
        Assert.assertEquals(v1.get(i), gets[j]);
      }
    }

    v1.set(100);
    v1.set(101);
    v1.set(102);
    v1.set(105);
    Assert.assertEquals("v1.max() is " + v1.max(), 105, v1.max());

    {
      boolean[] gets = new boolean[] {false, true, true, true, true, true, true};
      int[] bits = new int[] {0, 100, 101, 102, 103, 104, 105};
      for (int i = 0, j = 0; i != -1; i = v1.nextSetBit(i + 1), j++) {
        Assert.assertEquals(i, bits[j]);
        Assert.assertEquals(v1.get(i), gets[j]);
      }
    }

    v2.clear(103);
    v2.clear(104);
    v1.andNot(v2);

    {
      boolean[] gets = new boolean[] {false, true, true, true, true, true, true};
      int[] bits = new int[] {0, 100, 101, 102, 103, 104, 105};
      for (int i = 0, j = 0; i != -1; i = v1.nextSetBit(i + 1), j++) {
        Assert.assertEquals(i, bits[j]);
        Assert.assertEquals(v1.get(i), gets[j]);
      }
    }

    v2.set(101);
    v2.set(102);

    System.err.println("v1 = " + v1 + ", v2 = " + v2);
    v1.andNot(v2);

    {
      boolean[] gets = new boolean[] {false, true, true, true, true};
      int[] bits = new int[] {0, 100, 103, 104, 105};
      for (int i = 0, j = 0; i != -1; i = v1.nextSetBit(i + 1), j++) {
        Assert.assertEquals(i, bits[j]);
        Assert.assertEquals(v1.get(i), gets[j]);
      }
    }

    v1.clearAll();
    v2.clearAll();

    v1.set(35);
    v1.set(101);
    v1.set(102);
    v1.set(103);
    v1.set(104);
    v1.set(105);

    v2.set(101);
    v2.set(102);
    v2.set(104);
    v2.set(206);

    System.err.println("v1 = " + v1 + ", v2 = " + v2);
    v1.xor(v2);

    {
      boolean[] gets = new boolean[] {false, true, true, true, true};
      int[] bits = new int[] {0, 35, 103, 105, 206};
      for (int i = 0, j = 0; i != -1; i = v1.nextSetBit(i + 1), j++) {
        Assert.assertEquals(i, bits[j]);
        Assert.assertEquals(v1.get(i), gets[j]);
      }
    }

    v2.set(35);
    v2.set(103);
    v2.set(105);

    System.err.println("v1 = " + v1 + ", v2 = " + v2);
    Assert.assertTrue(v1.isSubset(v2));

    v2.clearAll();
    v2.set(111);
    v2.or(v1);
    Assert.assertTrue(v1.isSubset(v2));

    v2.and(v1);

    Assert.assertTrue(v1.sameBits(v2));

    v1.clearAll();
  }

  private static OffsetBitVector makeBigTestOffsetVector() {
    OffsetBitVector v1 = new OffsetBitVector(50000096, 1024);
    v1.set(50000101);
    v1.set(50000103);
    v1.set(50000112);
    v1.set(50000114);
    v1.set(50000116);
    v1.set(50000126);
    v1.set(50000128);
    v1.set(50000129);
    v1.set(50000135);
    v1.set(50000137);
    v1.set(50000143);
    v1.set(50000148);
    v1.set(50000151);
    v1.set(50000158);
    v1.set(50000163);
    v1.set(50000167);
    v1.set(50000170);
    v1.set(50000173);
    v1.set(50000180);
    v1.set(50000182);
    v1.set(50000185);
    v1.set(50000187);
    v1.set(50000190);
    v1.set(50000194);
    v1.set(50000199);
    v1.set(50000201);
    v1.set(50000204);
    v1.set(50000206);
    v1.set(50000209);
    v1.set(50000210);
    v1.set(50000218);
    v1.set(50000221);
    v1.set(50000223);
    v1.set(50000227);
    v1.set(50000232);
    v1.set(50000234);
    v1.set(50000243);
    v1.set(50000246);
    v1.set(50000250);
    v1.set(50000257);
    v1.set(50000263);
    v1.set(50000268);
    v1.set(50000273);
    v1.set(50000275);
    v1.set(50000278);
    v1.set(50000282);
    v1.set(50000285);
    v1.set(50000290);
    v1.set(50000293);
    v1.set(50000298);
    v1.set(50000300);
    v1.set(50000303);
    v1.set(50000306);
    v1.set(50000308);
    v1.set(50000310);
    v1.set(50000315);
    v1.set(50000325);
    v1.set(50000327);
    v1.set(50000335);
    v1.set(50000337);
    v1.set(50000342);
    v1.set(50000345);
    v1.set(50000349);
    v1.set(50000360);
    v1.set(50000362);
    v1.set(50000369);
    v1.set(50000374);
    v1.set(50000375);
    v1.set(50000378);
    v1.set(50000380);
    v1.set(50000383);
    v1.set(50000384);
    v1.set(50000388);
    v1.set(50000391);
    v1.set(50000400);
    v1.set(50000405);
    v1.set(50000409);
    v1.set(50000414);
    v1.set(50000417);
    v1.set(50000421);
    v1.set(50000426);
    v1.set(50000431);
    v1.set(50000435);
    v1.set(50000437);
    v1.set(50000439);
    v1.set(50000442);
    v1.set(50000446);
    v1.set(50000450);
    v1.set(50000455);
    v1.set(50000459);
    v1.set(50000460);
    v1.set(50000463);
    v1.set(50000470);
    v1.set(50000471);
    v1.set(50000480);
    v1.set(50000497);
    v1.set(50000498);
    v1.set(50000500);
    v1.set(50000505);
    v1.set(50000508);
    v1.set(50000511);
    v1.set(50000513);
    v1.set(50000520);
    v1.set(50000526);
    v1.set(50000529);
    v1.set(50000536);
    v1.set(50000539);
    v1.set(50000551);
    v1.set(50000555);
    v1.set(50000559);
    v1.set(50000563);
    v1.set(50000564);
    v1.set(50000566);
    v1.set(50000568);
    v1.set(50000570);
    v1.set(50000576);
    v1.set(50000587);
    v1.set(50000590);
    v1.set(50000594);
    v1.set(50000601);
    v1.set(50000605);
    v1.set(50000608);
    v1.set(50000610);
    v1.set(50000619);
    v1.set(50000628);
    v1.set(50000630);
    v1.set(50000634);
    v1.set(50000644);
    v1.set(50000647);
    v1.set(50000654);
    v1.set(50000658);
    v1.set(50000661);
    v1.set(50000663);
    v1.set(50000669);
    v1.set(50000671);
    v1.set(50000673);
    v1.set(50000676);
    v1.set(50000677);
    v1.set(50000680);
    v1.set(50000689);
    v1.set(50000692);
    v1.set(50000695);
    v1.set(50000705);
    v1.set(50000707);
    v1.set(50000708);
    v1.set(50000714);
    v1.set(50000716);
    v1.set(50000721);
    v1.set(50000727);
    v1.set(50000732);
    v1.set(50000736);
    v1.set(50000739);
    v1.set(50000741);
    v1.set(50000750);
    v1.set(50000753);
    v1.set(50000755);
    v1.set(50000765);
    v1.set(50000769);
    v1.set(50000773);
    v1.set(50000779);
    v1.set(50000782);
    v1.set(50000784);
    v1.set(50000787);
    v1.set(50000791);
    v1.set(50000792);
    v1.set(50000793);
    v1.set(50000795);
    v1.set(50000801);
    v1.set(50000806);
    v1.set(50000809);
    return v1;
  }

  @Test
  public void testSpecificBugsInOffsetBitVectors() {
    OffsetBitVector v1 = makeBigTestOffsetVector();
    System.err.println(v1);

    OffsetBitVector v2 = new OffsetBitVector(50000128, 512);
    v2.set(50000137);
    v2.set(50000204);
    v2.set(50000278);
    v2.set(50000315);
    v2.set(50000362);
    v2.set(50000450);
    v2.set(50000455);
    v2.set(50000471);
    System.err.println(v2);

    v1.andNot(v2);
    System.err.println(v1);
    Assert.assertTrue(v1.intersectionEmpty(v2));

    v1 = makeBigTestOffsetVector();
    v1.and(v2);
    System.err.println(v1);
    Assert.assertTrue(v1.sameBits(v2));
    Assert.assertTrue(v1.isSubset(v2));
    Assert.assertTrue(v2.isSubset(v1));
  }

  @Test
  public void testSpecificBugsInSemiSparseMutableIntSets() {
    SemiSparseMutableIntSet v1 = new SemiSparseMutableIntSet();
    v1.add(54);
    v1.add(58);
    v1.add(59);
    v1.add(64);
    v1.add(67);
    v1.add(73);
    v1.add(83);
    v1.add(105);
    v1.add(110);
    v1.add(126);
    v1.add(136);
    v1.add(143);
    v1.add(150);
    v1.add(155);
    v1.add(156);
    v1.add(162);
    v1.add(168);
    v1.add(183);
    v1.add(191);
    v1.add(265);
    v1.add(294);
    v1.add(324);
    v1.add(344);
    v1.add(397);
  }
}
