@Override
	protected List<FunctionPair> pairFunctions(LSHVectorFactory vectorFactory,
		List<DescriptionManager> vec2func, List<VectorResult> vectors, int hitcount,
		int pairThreshold) {

		// Separate cluster into functions that are in singleExe
		// and functions that are NOT in singleExe  (but are still in our filter set)
		List<FunctionDescription> singleFuncs = new ArrayList<FunctionDescription>(hitcount);
		List<VectorResult> singleVec = new ArrayList<VectorResult>(hitcount);
		List<FunctionDescription> otherFuncs = new ArrayList<FunctionDescription>(hitcount);
		List<VectorResult> otherVec = new ArrayList<VectorResult>(hitcount);
		for (int i = 0; i < vec2func.size(); ++i) {
			DescriptionManager manage = vec2func.get(i);
			VectorResult curVec = vectors.get(i);
			Iterator<FunctionDescription> iter = manage.listAllFunctions();
			while (iter.hasNext()) {
				FunctionDescription func = iter.next();
				int xrefIndex = func.getExecutableRecord().getXrefIndex();
				if (xrefIndex == 0) {
					continue;						// Not in our filter set
				}
				else if (xrefIndex == singleExeXref) {
					singleFuncs.add(func);				// Save off function in singleExe for later enumeration
					singleVec.add(curVec);				// Save off its associated vector
				}
				else {
					otherFuncs.add(func);
					otherVec.add(curVec);
				}
			}
		}

		int pairCount = singleFuncs.size() * otherFuncs.size() +
			(singleFuncs.size() * (singleFuncs.size() + 1)) / 2;
		if (pairCount > pairThreshold) {
			return null;
		}
		// For each function (funcA) in singleExe
		//    a) enumerate pairs with funcA and other functions in singleExe
		//    b) enumerate pairs with funcA and other functions NOT in singleExe
		List<FunctionPair> pairs = new ArrayList<FunctionPair>(pairCount);
		VectorCompare vectorCompare = new VectorCompare();
		for (int i = 0; i < singleFuncs.size(); ++i) {
			FunctionDescription funcA = singleFuncs.get(i);
			LSHVector vectorA = singleVec.get(i).vec;
			LSHVector lastVec = vectorA;
			double similarity = 1.0;
			double significance = vectorFactory.getSelfSignificance(lastVec);

			// Create pairs from functions within singleExe
			for (int j = i; j < singleFuncs.size(); ++j) {
				LSHVector nextVec = singleVec.get(j).vec;
				if (lastVec != nextVec) {
					similarity = vectorA.compare(nextVec, vectorCompare);
					significance = vectorFactory.calculateSignificance(vectorCompare);
					lastVec = nextVec;
				}
				if (similarity < simThreshold || significance < sigThreshold) {
					continue;
				}
				pairs.add(new FunctionPair(funcA, singleFuncs.get(j), similarity, significance));
			}

			// Create pairs with one function in singleExe and one function not in singleExe
			for (int j = 0; j < otherFuncs.size(); ++j) {
				LSHVector nextVec = otherVec.get(j).vec;
				if (lastVec != nextVec) {
					similarity = vectorA.compare(nextVec, vectorCompare);
					significance = vectorFactory.calculateSignificance(vectorCompare);
					lastVec = nextVec;
				}
				if (similarity < simThreshold || significance < sigThreshold) {
					continue;
				}
				FunctionDescription funcB = otherFuncs.get(j);
				pairs.add(new FunctionPair(funcA, funcB, similarity, significance));
			}
		}

		return pairs;
	}
Construct the scorer.  If normalized scores are required, a self-score cacher
must be provided.
@param cache is the self-score cacher or null
@throws LSHException for problems initializing the cache
Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/client/ExecutableScorerSingle.java