IntArrayList uncontractedIndicesToCollect = TensorUtils.getContractedIndicesNames(split.term, split.factoredOut);
IntArrayList uncontractedIndicesCollected = TensorUtils.getContractedIndicesNames(term, factors.getElements().get(0));
IndexMappingBuffer concurentBuffer = null;
if (factors.size() > 30){//TODO refacor in future
concurentBuffer = IndexMappings.getFirst(toCollect, collectedTensor, allowDiffStates);}
else {
List<IndexMappingBuffer> buffers = IndexMappingUtils.createAllMappings(toCollect, collectedTensor, allowDiffStates);
//finding best mapping
//botleneck for very huge sums
int concurrence = 0, currentConcurrence;
boolean sign = false;
for (IndexMappingBuffer buffer : buffers) {
currentConcurrence = 0;
for (Map.Entry<Integer, IndexMappingBufferRecord> entry : buffer.getMap().entrySet()) {
int indexToCollect = entry.getKey();
int indexCollected = entry.getValue().getIndexName();
if (indexToCollect == indexCollected || (uncontractedIndicesToCollect.contains(indexToCollect) && uncontractedIndicesCollected.contains(indexCollected)))
currentConcurrence++;
if (entry.getValue().diffStatesInitialized())
currentConcurrence--;
}
if (concurentBuffer == null
|| currentConcurrence > concurrence
|| (sign && !buffer.getSignum()
&& (currentConcurrence >= concurrence))) {
concurentBuffer = buffer;
concurrence = currentConcurrence;
}
}
}
IndexMappingDirectAllowingUnmapped mappingToCollect = new IndexMappingDirectAllowingUnmapped();
IndexMappingDirectAllowingUnmapped mappingCollectedTensor = new IndexMappingDirectAllowingUnmapped();
//building index generator
IntArrayList usedIndices = new IntArrayList(TensorUtils.getAllIndicesNames(split.factoredOut));
usedIndices.addAll(factorsIndicesNames);
usedIndices.addAll(termIndicesNames);
IndexGenerator ig = new IndexGenerator(usedIndices.toArray());
List<Tensor> mkCollectedList = new ArrayList<>();
for (Map.Entry<Integer, IndexMappingBufferRecord> entry : concurentBuffer.getMap().entrySet()) {
int indexCollected, indexToCollect, rawState = ((entry.getValue().getStates() & 1) ^ 1) << 31;
boolean diffStatesInit = entry.getValue().diffStatesInitialized();
indexCollected = rawState | entry.getValue().getIndexName();
indexToCollect = (diffStatesInit ? 0x80000000 : 0) ^ (rawState | entry.getKey());
SimpleTensor mkCollected;
SimpleTensor mkToCollect;
if (indexToCollect == indexCollected)
continue;
else if (uncontractedIndicesToCollect.contains(getNameWithType(indexToCollect))
&& uncontractedIndicesCollected.contains(getNameWithType(indexCollected)))
mappingToCollect.add(inverseIndexState(indexToCollect),
inverseIndexState(indexCollected));
else if (uncontractedIndicesToCollect.contains(getNameWithType(indexToCollect))) {
mkCollected = CC.createMetricOrKronecker(inverseIndexState(indexToCollect), indexCollected);
factorsIndicesNames.add(getNameWithType(indexCollected));
factorsIndicesNames.add(getNameWithType(indexToCollect));
termIndicesNames.replaceFirst(getNameWithType(indexCollected), getNameWithType(indexToCollect));
mappingCollectedTensor.add(indexCollected, indexToCollect);
mkCollectedList.add(mkCollected);
} else if (uncontractedIndicesCollected.contains(getNameWithType(indexCollected))) {
mkToCollect = CC.createMetricOrKronecker(indexToCollect, inverseIndexState(indexCollected));
split.factoredOut.add(mkToCollect);
} else {
int newIndex = ig.generate(getType(indexToCollect));
factorsIndicesNames.add(getNameWithType(indexCollected));
factorsIndicesNames.add(newIndex);
termIndicesNames.replaceFirst(getNameWithType(indexCollected), newIndex);
newIndex = getRawStateInt(indexCollected) | newIndex;
mkCollected = CC.createKronecker(indexCollected, inverseIndexState(newIndex));
mkToCollect = CC.createMetricOrKronecker(indexToCollect, inverseIndexState(newIndex));
mappingCollectedTensor.add(indexCollected, newIndex);
mkCollectedList.add(mkCollected);
split.factoredOut.add(mkToCollect);
}
}
if (!mkCollectedList.isEmpty())
for (Tensor p : factors)
((Product) p).add(mkCollectedList);
if (concurentBuffer.getSignum())
split.factoredOut.addFirst(TensorNumber.createMINUSONE());
if (!mappingToCollect.isEmpty())
ApplyIndexMappingDirectTransformation.INSTANCE.perform(split.factoredOut, mappingToCollect);
factors.add(split.factoredOut);
factorsIndicesNames.addAll(TensorUtils.getAllIndicesNames(split.factoredOut));