// Path: src/main/java/edu/berkeley/nlp/lm/ContextEncodedNgramLanguageModel.java
// public static class LmContextInfo
// {
// 
// 	/**
// 	 * Offset of context (prefix) of an n-gram
// 	 */
// 	public long offset = -1L;
// 
// 	/**
// 	 * The (0-based) length of <code>context</code> (i.e.
// 	 * <code>order == 0</code> iff <code>context</code> refers to a
// 	 * unigram).
// 	 * 
// 	 * Use -1 for an empty context.
// 	 */
// 	public int order = -1;
// 
// }


import java.util.Arrays;
import java.util.concurrent.atomic.AtomicIntegerArray;
import edu.berkeley.nlp.lm.ContextEncodedNgramLanguageModel.LmContextInfo;
import edu.berkeley.nlp.lm.util.Annotations.OutputParameter;
	/**
	 * @return
	 */
	private long[] allocCache() {
		final long[] array = new long[STRUCT_LENGTH * cacheSize];
		Arrays.fill(array, -1);
		return array;
	}

	@Override
	public float getCached(final long contextOffset, final int contextOrder, final int word, final int hash, @OutputParameter final LmContextInfo outputPrefix) {
		final long[] array = !threadSafe ? threadUnsafeArray : threadSafeArray.get();
		final int cachedWordHere = getWord(hash, array);

		if (word >= 0 && word == cachedWordHere && getLong(hash, CONTEXT_OFFSET, array) == combine(contextOrder, contextOffset)) {
			final float f = getVal(hash, array);
			if (outputPrefix == null) return f;
			final long outputOrderAndOffset = getLong(hash, OUTPUT_CONTEXT_OFFSET, array);
			if (outputOrderAndOffset >= 0) {
				outputPrefix.order = orderOf(outputOrderAndOffset);
				outputPrefix.offset = offsetOf(outputOrderAndOffset);
				return f;
			}

		}
		return Float.NaN;
	}

	@Override
	public void putCached(final long contextOffset, final int contextOrder, final int word, final float score, final int hash,
// Path: src/main/java/edu/berkeley/nlp/lm/ContextEncodedNgramLanguageModel.java
// public static class LmContextInfo
// {
// 
// 	/**
// 	 * Offset of context (prefix) of an n-gram
// 	 */
// 	public long offset = -1L;
// 
// 	/**
// 	 * The (0-based) length of <code>context</code> (i.e.
// 	 * <code>order == 0</code> iff <code>context</code> refers to a
// 	 * unigram).
// 	 * 
// 	 * Use -1 for an empty context.
// 	 */
// 	public int order = -1;
// 
// }


// Path: src/main/java/edu/berkeley/nlp/lm/cache/ContextEncodedDirectMappedLmCache.java
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicIntegerArray;
import edu.berkeley.nlp.lm.ContextEncodedNgramLanguageModel.LmContextInfo;
import edu.berkeley.nlp.lm.util.Annotations.OutputParameter;

	/**
	 * @return
	 */
	private long[] allocCache() {
		final long[] array = new long[STRUCT_LENGTH * cacheSize];
		Arrays.fill(array, -1);
		return array;
	}

	@Override
	public float getCached(final long contextOffset, final int contextOrder, final int word, final int hash, @OutputParameter final LmContextInfo outputPrefix) {
		final long[] array = !threadSafe ? threadUnsafeArray : threadSafeArray.get();
		final int cachedWordHere = getWord(hash, array);

		if (word >= 0 && word == cachedWordHere && getLong(hash, CONTEXT_OFFSET, array) == combine(contextOrder, contextOffset)) {
			final float f = getVal(hash, array);
			if (outputPrefix == null) return f;
			final long outputOrderAndOffset = getLong(hash, OUTPUT_CONTEXT_OFFSET, array);
			if (outputOrderAndOffset >= 0) {
				outputPrefix.order = orderOf(outputOrderAndOffset);
				outputPrefix.offset = offsetOf(outputOrderAndOffset);
				return f;
			}

		}
		return Float.NaN;
	}

	@Override
	public void putCached(final long contextOffset, final int contextOrder, final int word, final float score, final int hash,
		@OutputParameter final LmContextInfo outputPrefix) {