result[result.length - 1] = factor;
return Tensors.multiply(result);
}
SubsResult atomicSubstitute(PContent content, ForbiddenContainer forbidden, SubstitutionIterator iterator) {
Mapping mapping = null;
int[] indexlessBijection, dataBijection;
IndexlessBijectionsPort indexlessPort
= new IndexlessBijectionsPort(fromIndexless, content.indexless);
while ((indexlessBijection = indexlessPort.take()) != null) {
mapping = createBijectiveProductPort(fromIndexless, extract(content.indexless, indexlessBijection)).take();
if (mapping != null)
break;
}
if (mapping == null)
return null;
boolean sign = mapping.getSign();
mapping = null;
Tensor[] currentData;
if (content.data instanceof Product) {
ProductContent currentContent = ((Product) content.data).getContent();
currentData = currentContent.getDataCopy();
ProductsBijectionsPort dataPort = new ProductsBijectionsPort(fromContent, currentContent);
while ((dataBijection = dataPort.take()) != null) {
mapping = createBijectiveProductPort(fromData, extract(currentData, dataBijection)).take();
if (mapping != null)
break;
}
} else {
if (TensorUtils.isOne(content.data)) {
if (fromContent.size() != 0)
return null;
dataBijection = new int[0];
currentData = new Tensor[0];
mapping = Mapping.IDENTITY;
} else {
if (fromContent.size() != 1)
return null;
dataBijection = new int[1];
currentData = new Tensor[]{content.data};
mapping = getFirst(fromContent.get(0), content.data);
}
}
if (mapping == null)
return null;
mapping = mapping.addSign(sign);
Arrays.sort(indexlessBijection);
Arrays.sort(dataBijection);
Tensor[] indexlessRemainder = new Tensor[content.indexless.length - fromIndexless.length];
ProductBuilder dataRemainder = new ProductBuilder(0,
(content.data instanceof Product)
? content.data.size()
: 1 - fromContent.size());
int pivot = 0;
int i, j = 0;
for (i = 0; i < content.indexless.length; ++i) {
if (pivot < indexlessBijection.length && i == indexlessBijection[pivot])
++pivot;
else
indexlessRemainder[j++] = content.indexless[i];
}
pivot = 0;
for (i = 0; i < currentData.length; ++i) {
if (pivot < dataBijection.length && i == dataBijection[pivot])
++pivot;
else
dataRemainder.put(currentData[i]);
}
Tensor dataRemainderT = dataRemainder.build();
PContent remainder = new PContent(indexlessRemainder, dataRemainderT);
Tensor newTo;
if (toIsSymbolic)
newTo = mapping.getSign() ? Tensors.negate(to) : to;
else {
if (possiblyAddsDummies) {
if (forbidden.forbidden == null)
forbidden.forbidden = new TIntHashSet(iterator.getForbidden());
TIntHashSet remainderIndices = new TIntHashSet(forbidden.forbidden);
remainderIndices.addAll(getAllIndicesNamesT(indexlessRemainder));
remainderIndices.addAll(getAllIndicesNamesT(dataRemainderT));
newTo = applyIndexMapping(to, mapping, remainderIndices.toArray());
forbidden.forbidden.addAll(getAllIndicesNamesT(newTo));
} else {
TIntHashSet allowed = new TIntHashSet();
for (int index : indexlessBijection)
allowed.addAll(TensorUtils.getAllDummyIndicesT(content.indexless[index]));
IndicesBuilder ib = new IndicesBuilder();
for (int index : dataBijection) {
allowed.addAll(TensorUtils.getAllDummyIndicesT(currentData[index]));
ib.append(currentData[index]);
}
allowed.addAll(ib.getIndices().getNamesOfDummies());
allowed.removeAll(IndicesUtils.getIndicesNames(mapping.getToData()));
newTo = applyIndexMappingAndRenameAllDummies(to, mapping, allowed.toArray());
}
}
return new SubsResult(newTo, remainder);
}