// Path: src/main/java/com/netflix/nfgraph/OrdinalIterator.java
// public interface OrdinalIterator {
//     
//     /**
//      * This value will be returned from <code>nextOrdinal()</code> after the iteration is completed.
//      */
//     public static final int NO_MORE_ORDINALS = Integer.MAX_VALUE;
//     
//     /**
//      * @return the next ordinal in this set.
//      */
//     public int nextOrdinal();
//     
//     /**
//      * Rewinds this <code>OrdinalIterator</code> to the beginning of the set.
//      */
//     public void reset();
//     
//     /**
//      * Obtain a copy of this <code>OrdinalIterator</code>.  The returned <code>OrdinalIterator</code> will be reset to the beginning of the set.
//      */
//     public OrdinalIterator copy();
//     
//     /**
//      * @return <code>true</code> if the ordinals returned from this set are guaranteed to be in ascending order.  Returns <code>false</code> otherwise.  
//      */
//     public boolean isOrdered();
//     
//     /**
//      * An iterator which always return <code>OrdinalIterator.NO_MORE_ORDINALS</code>
//      */
//     public static final OrdinalIterator EMPTY_ITERATOR = new OrdinalIterator() {
//         @Override public int nextOrdinal() { return NO_MORE_ORDINALS; }
// 
//         @Override public void reset() { }
// 
//         @Override public OrdinalIterator copy() { return this; }
//         
//         @Override public boolean isOrdered() { return true; }
//     };
// 
// }
// 
// Path: src/main/java/com/netflix/nfgraph/util/ByteArrayReader.java
// public class ByteArrayReader {
// 
//     private final ByteData data;
// 
//     private long pointer;
//     private long startByte;
//     private long endByte = Integer.MAX_VALUE;
// 
//     public ByteArrayReader(ByteData data, long pointer) {
//         this.data = data;
//         this.pointer = pointer;
//         this.startByte = pointer;
//         this.endByte = data.length();
//     }
// 
//     public ByteArrayReader(ByteData data, long startByte, long endByte) {
//         this.data = data;
//         this.startByte = startByte;
//         this.endByte = endByte;
//         this.pointer = startByte;
//     }
// 
//     /**
//      * @return the byte value at the given offset.
//      */
//     public byte getByte(long offset) {
//         return data.get(startByte + offset);
//     }
// 
//     /**
//      * Set the current offset of this reader.
//      */
//     public void setPointer(long pointer) {
//         this.pointer = pointer;
//     }
// 
//     /**
//      * Increment the current offset of this reader by numBytes.
//      */
//     public void skip(long numBytes) {
//         pointer += numBytes;
//     }
// 
//     /**
//      * @return a variable-byte integer at the current offset.  The offset is incremented by the size of the returned integer.
//      */
//     public int readVInt() {
//         if(pointer >= endByte)
//             return -1;
// 
//         byte b = readByte();
// 
//         if(b == (byte) 0x80)
//             return -1;
// 
//         int value = b & 0x7F;
//         while ((b & 0x80) != 0) {
//           b = readByte();
//           value <<= 7;
//           value |= (b & 0x7F);
//         }
// 
//         return value;
//     }
// 
//     /**
//      * @return the byte at the current offset.  The offset is incremented by one.
//      */
//     public byte readByte() {
//         return data.get(pointer++);
//     }
// 
//     /**
//      * Sets the start byte of this reader to the current offset, then sets the end byte to the current offset + <code>remainingBytes</code>
//      */
//     public void setRemainingBytes(int remainingBytes) {
//         this.startByte = pointer;
//         this.endByte = pointer + remainingBytes;
//     }
// 
//     /**
//      * Sets the current offset of this reader to the start byte.
//      */
//     public void reset() {
//         this.pointer = startByte;
//     }
// 
//     /**
//      * @return the length of this reader.
//      */
//     public long length() {
//         return endByte - startByte;
//     }
// 
//     /**
//      * @return a copy of this reader.  The copy will have the same underlying byte array, start byte, and end byte, but the current offset will be equal to the start byte.
//      */
//     public ByteArrayReader copy() {
//         return new ByteArrayReader(data, startByte, endByte);
//     }
// 
// 
// }


import com.netflix.nfgraph.OrdinalIterator;
import com.netflix.nfgraph.util.ByteArrayReader;
            value |= reader.getByte(offset) & 0x7F;
            nextOffset();
        }
        
        return value - 1;
    }

    @Override
    public void reset() { 
        offset = beginOffset;
        firstValue = true;
    }

    @Override
    public OrdinalIterator copy() {
        return new HashSetOrdinalIterator(reader);
    }

    @Override
    public boolean isOrdered() {
        return false;
    }
    
    private void nextOffset() {
        offset++;
        if(offset >= reader.length()) {
            offset = 0;
        }
    }
    
// Path: src/main/java/com/netflix/nfgraph/OrdinalIterator.java
// public interface OrdinalIterator {
//     
//     /**
//      * This value will be returned from <code>nextOrdinal()</code> after the iteration is completed.
//      */
//     public static final int NO_MORE_ORDINALS = Integer.MAX_VALUE;
//     
//     /**
//      * @return the next ordinal in this set.
//      */
//     public int nextOrdinal();
//     
//     /**
//      * Rewinds this <code>OrdinalIterator</code> to the beginning of the set.
//      */
//     public void reset();
//     
//     /**
//      * Obtain a copy of this <code>OrdinalIterator</code>.  The returned <code>OrdinalIterator</code> will be reset to the beginning of the set.
//      */
//     public OrdinalIterator copy();
//     
//     /**
//      * @return <code>true</code> if the ordinals returned from this set are guaranteed to be in ascending order.  Returns <code>false</code> otherwise.  
//      */
//     public boolean isOrdered();
//     
//     /**
//      * An iterator which always return <code>OrdinalIterator.NO_MORE_ORDINALS</code>
//      */
//     public static final OrdinalIterator EMPTY_ITERATOR = new OrdinalIterator() {
//         @Override public int nextOrdinal() { return NO_MORE_ORDINALS; }
// 
//         @Override public void reset() { }
// 
//         @Override public OrdinalIterator copy() { return this; }
//         
//         @Override public boolean isOrdered() { return true; }
//     };
// 
// }
// 
// Path: src/main/java/com/netflix/nfgraph/util/ByteArrayReader.java
// public class ByteArrayReader {
// 
//     private final ByteData data;
// 
//     private long pointer;
//     private long startByte;
//     private long endByte = Integer.MAX_VALUE;
// 
//     public ByteArrayReader(ByteData data, long pointer) {
//         this.data = data;
//         this.pointer = pointer;
//         this.startByte = pointer;
//         this.endByte = data.length();
//     }
// 
//     public ByteArrayReader(ByteData data, long startByte, long endByte) {
//         this.data = data;
//         this.startByte = startByte;
//         this.endByte = endByte;
//         this.pointer = startByte;
//     }
// 
//     /**
//      * @return the byte value at the given offset.
//      */
//     public byte getByte(long offset) {
//         return data.get(startByte + offset);
//     }
// 
//     /**
//      * Set the current offset of this reader.
//      */
//     public void setPointer(long pointer) {
//         this.pointer = pointer;
//     }
// 
//     /**
//      * Increment the current offset of this reader by numBytes.
//      */
//     public void skip(long numBytes) {
//         pointer += numBytes;
//     }
// 
//     /**
//      * @return a variable-byte integer at the current offset.  The offset is incremented by the size of the returned integer.
//      */
//     public int readVInt() {
//         if(pointer >= endByte)
//             return -1;
// 
//         byte b = readByte();
// 
//         if(b == (byte) 0x80)
//             return -1;
// 
//         int value = b & 0x7F;
//         while ((b & 0x80) != 0) {
//           b = readByte();
//           value <<= 7;
//           value |= (b & 0x7F);
//         }
// 
//         return value;
//     }
// 
//     /**
//      * @return the byte at the current offset.  The offset is incremented by one.
//      */
//     public byte readByte() {
//         return data.get(pointer++);
//     }
// 
//     /**
//      * Sets the start byte of this reader to the current offset, then sets the end byte to the current offset + <code>remainingBytes</code>
//      */
//     public void setRemainingBytes(int remainingBytes) {
//         this.startByte = pointer;
//         this.endByte = pointer + remainingBytes;
//     }
// 
//     /**
//      * Sets the current offset of this reader to the start byte.
//      */
//     public void reset() {
//         this.pointer = startByte;
//     }
// 
//     /**
//      * @return the length of this reader.
//      */
//     public long length() {
//         return endByte - startByte;
//     }
// 
//     /**
//      * @return a copy of this reader.  The copy will have the same underlying byte array, start byte, and end byte, but the current offset will be equal to the start byte.
//      */
//     public ByteArrayReader copy() {
//         return new ByteArrayReader(data, startByte, endByte);
//     }
// 
// 
// }


// Path: src/main/java/com/netflix/nfgraph/compressed/HashSetOrdinalIterator.java
import com.netflix.nfgraph.OrdinalIterator;
import com.netflix.nfgraph.util.ByteArrayReader;

            value |= reader.getByte(offset) & 0x7F;
            nextOffset();
        }
        
        return value - 1;
    }

    @Override
    public void reset() { 
        offset = beginOffset;
        firstValue = true;
    }

    @Override
    public OrdinalIterator copy() {
        return new HashSetOrdinalIterator(reader);
    }

    @Override
    public boolean isOrdered() {
        return false;
    }
    
    private void nextOffset() {
        offset++;
        if(offset >= reader.length()) {
            offset = 0;
        }
    }
    
    private void seekBeginByte() {