// Path: src/main/java/edu/berkeley/nlp/lm/collections/Iterators.java
// public class Iterators
// {
// 
// 	/**
// 	 * Wraps an Iterator as an Iterable
// 	 * 
// 	 * @param <T>
// 	 * @param it
// 	 * @return
// 	 */
// 	public static <T> Iterable<T> able(final Iterator<T> it) {
// 		return new Iterable<T>()
// 		{
// 			boolean used = false;
// 
// 			@Override
// 			public Iterator<T> iterator() {
// 				if (used) throw new RuntimeException("One use iterable");
// 				used = true;
// 				return it;
// 			}
// 		};
// 	}
// 
// 	public static <T> Iterable<T> flatten(final Iterator<Iterator<T>> iters) {
// 		return Iterators.able(new IteratorIterator<T>(iters));
// 	}
// 
// 	/**
// 	 * Wraps a two-level iteration scenario in an iterator. Each key of the keys
// 	 * iterator returns an iterator (via the factory) over T's.
// 	 * <p>
// 	 * The IteratorIterator loops through the iterator associated with each key
// 	 * until all the keys are used up.
// 	 */
// 	public static class IteratorIterator<T> implements Iterator<T>
// 	{
// 		Iterator<T> current = null;
// 
// 		private final Iterator<Iterator<T>> iters;
// 
// 		public IteratorIterator(final Iterator<Iterator<T>> iters) {
// 			this.iters = iters;
// 			current = getNextIterator();
// 		}
// 
// 		private Iterator<T> getNextIterator() {
// 			Iterator<T> next = null;
// 			while (next == null) {
// 				if (!iters.hasNext()) break;
// 				next = iters.next();
// 				if (!next.hasNext()) next = null;
// 			}
// 			return next;
// 		}
// 
// 		@Override
// 		public boolean hasNext() {
// 			return current != null;
// 		}
// 
// 		@Override
// 		public T next() {
// 			final T next = current.next();
// 			if (!current.hasNext()) current = getNextIterator();
// 			return next;
// 		}
// 
// 		@Override
// 		public void remove() {
// 			throw new UnsupportedOperationException();
// 		}
// 
// 	}
// 
// 	/**
// 	 * Wraps a base iterator with a transformation function.
// 	 */
// 	public static abstract class Transform<S, T> implements Iterator<T>
// 	{
// 
// 		private final Iterator<S> base;
// 
// 		public Transform(final Iterator<S> base) {
// 			this.base = base;
// 		}
// 
// 		@Override
// 		public boolean hasNext() {
// 			return base.hasNext();
// 		}
// 
// 		@Override
// 		public T next() {
// 			return transform(base.next());
// 		}
// 
// 		protected abstract T transform(S next);
// 
// 		@Override
// 		public void remove() {
// 			base.remove();
// 		}
// 
// 	}
// 
// 	public static <S, T> Iterator<Pair<S, T>> zip(final Iterator<S> s, final Iterator<T> t) {
// 		return new Iterator<Pair<S, T>>()
// 		{
// 			@Override
// 			public boolean hasNext() {
// 				return s.hasNext() && t.hasNext();
// 			}
// 
// 			@Override
// 			public Pair<S, T> next() {
// 				return Pair.newPair(s.next(), t.next());
// 			}
// 
// 			@Override
// 			public void remove() {
// 				throw new UnsupportedOperationException();
// 			}
// 		};
// 	}
// 
// }


import java.io.Serializable;
import java.util.Iterator;
import edu.berkeley.nlp.lm.collections.Iterators;
	 * @see edu.berkeley.nlp.lm.map.HashMap#put(long)
	 */
	@Override
	public long put(final long key) {
		return ngramMap.wordOf(key);
	}

	@Override
	public final long getOffset(final long key) {
		final long word = ngramMap.wordOf(key);
		return (word < 0 || word >= numWords) ? EMPTY_KEY : word;
	}

	@Override
	public long getKey(final long contextOffset) {
		return ngramMap.combineToKey((int) contextOffset, 0L);
	}

	@Override
	public boolean isEmptyKey(final long key) {
		return key == EMPTY_KEY;
	}

	@Override
	public long size() {
		return numWords;
	}

	@Override
	public Iterable<Long> keys() {
// Path: src/main/java/edu/berkeley/nlp/lm/collections/Iterators.java
// public class Iterators
// {
// 
// 	/**
// 	 * Wraps an Iterator as an Iterable
// 	 * 
// 	 * @param <T>
// 	 * @param it
// 	 * @return
// 	 */
// 	public static <T> Iterable<T> able(final Iterator<T> it) {
// 		return new Iterable<T>()
// 		{
// 			boolean used = false;
// 
// 			@Override
// 			public Iterator<T> iterator() {
// 				if (used) throw new RuntimeException("One use iterable");
// 				used = true;
// 				return it;
// 			}
// 		};
// 	}
// 
// 	public static <T> Iterable<T> flatten(final Iterator<Iterator<T>> iters) {
// 		return Iterators.able(new IteratorIterator<T>(iters));
// 	}
// 
// 	/**
// 	 * Wraps a two-level iteration scenario in an iterator. Each key of the keys
// 	 * iterator returns an iterator (via the factory) over T's.
// 	 * <p>
// 	 * The IteratorIterator loops through the iterator associated with each key
// 	 * until all the keys are used up.
// 	 */
// 	public static class IteratorIterator<T> implements Iterator<T>
// 	{
// 		Iterator<T> current = null;
// 
// 		private final Iterator<Iterator<T>> iters;
// 
// 		public IteratorIterator(final Iterator<Iterator<T>> iters) {
// 			this.iters = iters;
// 			current = getNextIterator();
// 		}
// 
// 		private Iterator<T> getNextIterator() {
// 			Iterator<T> next = null;
// 			while (next == null) {
// 				if (!iters.hasNext()) break;
// 				next = iters.next();
// 				if (!next.hasNext()) next = null;
// 			}
// 			return next;
// 		}
// 
// 		@Override
// 		public boolean hasNext() {
// 			return current != null;
// 		}
// 
// 		@Override
// 		public T next() {
// 			final T next = current.next();
// 			if (!current.hasNext()) current = getNextIterator();
// 			return next;
// 		}
// 
// 		@Override
// 		public void remove() {
// 			throw new UnsupportedOperationException();
// 		}
// 
// 	}
// 
// 	/**
// 	 * Wraps a base iterator with a transformation function.
// 	 */
// 	public static abstract class Transform<S, T> implements Iterator<T>
// 	{
// 
// 		private final Iterator<S> base;
// 
// 		public Transform(final Iterator<S> base) {
// 			this.base = base;
// 		}
// 
// 		@Override
// 		public boolean hasNext() {
// 			return base.hasNext();
// 		}
// 
// 		@Override
// 		public T next() {
// 			return transform(base.next());
// 		}
// 
// 		protected abstract T transform(S next);
// 
// 		@Override
// 		public void remove() {
// 			base.remove();
// 		}
// 
// 	}
// 
// 	public static <S, T> Iterator<Pair<S, T>> zip(final Iterator<S> s, final Iterator<T> t) {
// 		return new Iterator<Pair<S, T>>()
// 		{
// 			@Override
// 			public boolean hasNext() {
// 				return s.hasNext() && t.hasNext();
// 			}
// 
// 			@Override
// 			public Pair<S, T> next() {
// 				return Pair.newPair(s.next(), t.next());
// 			}
// 
// 			@Override
// 			public void remove() {
// 				throw new UnsupportedOperationException();
// 			}
// 		};
// 	}
// 
// }


// Path: src/main/java/edu/berkeley/nlp/lm/map/UnigramHashMap.java
import java.io.Serializable;
import java.util.Iterator;
import edu.berkeley.nlp.lm.collections.Iterators;

	 * @see edu.berkeley.nlp.lm.map.HashMap#put(long)
	 */
	@Override
	public long put(final long key) {
		return ngramMap.wordOf(key);
	}

	@Override
	public final long getOffset(final long key) {
		final long word = ngramMap.wordOf(key);
		return (word < 0 || word >= numWords) ? EMPTY_KEY : word;
	}

	@Override
	public long getKey(final long contextOffset) {
		return ngramMap.combineToKey((int) contextOffset, 0L);
	}

	@Override
	public boolean isEmptyKey(final long key) {
		return key == EMPTY_KEY;
	}

	@Override
	public long size() {
		return numWords;
	}

	@Override
	public Iterable<Long> keys() {
		return Iterators.able(new RangeIterator(numWords));