protected void calcHashes(int minLength,int maxLength,boolean wholeBlock,boolean matchOnly,HashCalculator hashCalc) throws MemoryAccessException {
		if (wholeBlock && (instList.length < minLength)) {
			// If allowed and if block is too small for even smallest n-gram
			minLength = instList.length;		// Set-up for exactly 1 whole-block n-gram
			maxLength = instList.length;
		}
		else if (matchOnly && matchHash == 0 && instList.length > 8) {
			// If matchOnly, this block has not been matched, and this block is big, then don't generate n-grams for it
			for(int i=0;i<instList.length;++i) {
				if (!instList[i].isMatched)
					instList[i].clearNGrams(0);		// No possibility of matching with tiny pieces
			}
			return;
		}
		for(int i=0;i<instList.length;++i) {		// Calculate hashes starting with instruction i
			if (instList[i].isMatched) continue;	// If already match, no hashes with this instruction
			int maxind;
			if (i + minLength > instList.length) {	// If we cannot fit in minimum hash size
				instList[i].clearNGrams(0);			// No hashes
				continue;
			}
			maxind = i + maxLength;				// Maximum possible index
			if (maxind > instList.length) {		// Make sure it fits
				maxind = instList.length;
			}
			int num = maxind - i - minLength + 1;	// Number of hashes we generate for this instruction
			instList[i].clearNGrams(num);
			// If an n-gram contains the block's starting instruction (and the block is big) this is encoded
			// in the hash by changing the initial hash accumulator value.
			int accum = (i==0 && instList.length > 8) ? Hash.SEED: Hash.ALTERNATE_SEED;	// For big blocks, encode starting instruction
			
			// Perform the intermediate hashes,  0 to minLength-1
			for(int j=0;j<minLength-1;++j) {
				if (accum != 0) {
					if (instList[i+j].isMatched) {		// Could be matched/unmatched instructions in window
						accum = 0;
						break;
					}
					accum = hashCalc.calcHash(accum, instList[i + j].instruction);
				}
			}
			
			// Extend to final hashes, saving the resulting nGram each time
			for(int j=0;j<num;++j) {
				// Hash in one more value
				if (accum != 0) {
					if (instList[i+j+minLength-1].isMatched)
						accum = 0;
					else
						accum = hashCalc.calcHash(accum, instList[i + j + minLength-1].instruction);
				}
				// Create a hash record
				if (accum != 0) {										
					instList[i].nGrams[j] = new Hash(accum ^ matchHash,minLength+j);	// XOR in non-zero value if block has already been matched
				}
				else
					instList[i].nGrams[j] = null;
			}
		}
	}
Calculate n-gram hashes used for matching (for Instructions in this basic-block).  The exact hashes generated
can be changed to get different looks at the data over multiple matching passes.
@param minLength is the minimum length of an n-gram to calculate
@param maxLength is the maximum length of an n-gram
@param wholeBlock, true indicates a hash of the whole block should be calculated even if its size is below minLength
@param matchOnly, true indicates hashes should only be calculated for previously matched, or small, blocks
@param hashCalc is the hash function for this matching pass
@throws MemoryAccessException
Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/correlate/Block.java