/*
* Redberry: symbolic tensor computations.
*
* Copyright (c) 2010-2012:
* Stanislav Poslavsky <stvlpos@mail.ru>
* Bolotin Dmitriy <bolotin.dmitriy@gmail.com>
*
* This file is part of Redberry.
*
* Redberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Redberry is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Redberry. If not, see <http://www.gnu.org/licenses/>.
*/
package cc.redberry.transformation.substitutions.n;
import cc.redberry.core.tensor.Derivative;
import cc.redberry.core.tensor.Product;
import cc.redberry.core.tensor.Tensor;
import cc.redberry.core.tensor.TensorField;
import cc.redberry.core.tensor.iterators.TraverseState;
import cc.redberry.core.tensor.iterators.TraverseTreeIterator;
import cc.redberry.core.utils.TensorUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
/**
*
* @author Dmitry Bolotin
* @author Stanislav Poslavsky
*/
class TreeIteratorSubs extends TraverseTreeIterator {
private TensorReference<Tensor> currentUpperProduct = new TensorReference<>(null);
TensorReference<Derivative> derivativeStack = new TensorReference<>(null);
TreeIteratorSubs(Tensor tensor) {
super(tensor);
}
@Override
public TraverseState next() {
TraverseState oldState = state();
Tensor oldTensor = tensor();
TraverseState newState = super.next();
Tensor newTensor = tensor();
if (oldState == TraverseState.Entering && oldTensor instanceof TensorField)
currentUpperProduct = new TensorReference(currentUpperProduct);
if (oldState == TraverseState.Entering && oldTensor instanceof Derivative) {
derivativeStack = new TensorReference<>(derivativeStack);
derivativeStack.tensor = (Derivative) oldTensor;
}
if (newState == TraverseState.Leaving && newTensor instanceof TensorField)
currentUpperProduct = currentUpperProduct.previous;
if (newState == TraverseState.Leaving && newTensor instanceof Derivative)
derivativeStack = derivativeStack.previous;
if (currentUpperProduct.tensor == null) {
if (newState == TraverseState.Entering
&& (newTensor instanceof Product || newTensor instanceof Derivative))
currentUpperProduct.tensor = tensor();
} else if (newState == TraverseState.Leaving
&& currentUpperProduct.tensor == newTensor)
currentUpperProduct.tensor = null;
if (isUnderIterator(Derivative.onVarsIndicator, 1) && newState == TraverseState.Entering)
return next();
return newState;
}
Tensor getUpperProduct() {
return currentUpperProduct.tensor;
}
int[] usedIndices() {
if (currentUpperProduct.tensor == null)
return new int[0];
return TensorUtils.getAllIndicesNames(currentUpperProduct.tensor);
}
static class TensorReference<T extends Tensor> implements Iterable<T> {
private final TensorReference<T> previous;
T tensor;
TensorReference(TensorReference<T> previous) {
this.previous = previous;
}
@Override
public Iterator<T> iterator() {
return new TIterator(this);
}
private class TIterator implements Iterator<T> {
TensorReference<T> current;
public TIterator(TensorReference<T> current) {
this.current = current;
}
@Override
public boolean hasNext() {
return current != null && current.previous != null;
}
@Override
public T next() {
T next = current.tensor;
current = current.previous;
return next;
}
@Override
public void remove() {
throw new UnsupportedOperationException("Not supported yet.");
}
}
@Override
public String toString() {
List<T> l = new ArrayList<>();
for (T t : this)
l.add(t);
return Arrays.toString(l.toArray(new Tensor[l.size()]));
}
}
}