Package cc.redberry.transformation.concurrent

Source Code of cc.redberry.transformation.concurrent.ExpandBracketsOutput$SumPortWrapper

/*
* 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.concurrent;

import java.util.ArrayList;
import java.util.List;
import cc.redberry.concurrent.OutputPortUnsafe;
import cc.redberry.core.tensor.Product;
import cc.redberry.core.tensor.Sum;
import cc.redberry.core.tensor.Tensor;
import cc.redberry.core.tensor.TensorIterator;
import cc.redberry.core.utils.Indicator;

/**
*
* @author Dmitry Bolotin
* @author Stanislav Poslavsky
*/
public class ExpandBracketsOutput implements OutputPortUnsafe<Tensor> {
    private final Indicator<Tensor> except;
    private final Product productBody;
    private final SumPort[] sumPorts;
    private final Tensor[] currentValues;
    private static final boolean USE_BUFFER = false;
    private static final int BUFFER_SIZE = 10;

    public ExpandBracketsOutput(Product productBody, Sum[] sums, Indicator<Tensor> except) {
        this.except = except;
        this.productBody = productBody;
        this.sumPorts = new SumPort[sums.length];
        this.currentValues = new Tensor[sums.length - 1];
        int i = 0;
        for (Sum sum : sums)
            if (USE_BUFFER)
                sumPorts[i++] = new SumPortWrapper(new SumPortImpl(this.except, sum));
            else
                sumPorts[i++] = new SumPortImpl(this.except, sum);
        for (i = 0; i < sums.length - 1; ++i)
            currentValues[i] = sumPorts[i].take();
    }

    @Override
    public Tensor take() {
        Product result = productBody.clone();
        int pointer = sumPorts.length - 1;
        boolean increment = false;
        Tensor element = sumPorts[pointer].take();
        if (element == null) {
            sumPorts[pointer].reset();
            element = sumPorts[pointer].take();
            increment = true;
        }
        result.add(element.clone());
        while (--pointer >= 0) {
            if (increment) {
                increment = false;
                element = sumPorts[pointer].take();
                if (element == null) {
                    sumPorts[pointer].reset();
                    element = sumPorts[pointer].take();
                    increment = true;
                }
                currentValues[pointer] = element;
            }
            result.add(currentValues[pointer].clone());
        }
        if (increment)
            return null;
        return result;
    }

    public static OutputPortUnsafe<Tensor> create(Tensor tensor) {
        return create(tensor, Indicator.FALSE_INDICATOR);
    }

    public static OutputPortUnsafe<Tensor> create(Tensor tensor, Indicator<Tensor> except) {
        if (tensor instanceof Product) {
            OutputPortUnsafe<Tensor> res = createOP(tensor, except);
            if (res != null)
                return res;
            else
                return new OutputPortUnsafe.Singleton<>(tensor);
        } else if (tensor instanceof Sum)
            return new SumPortImpl(except, (Sum) tensor);
        else
            return new OutputPortUnsafe.Singleton<>(tensor);
    }

    private static OutputPortUnsafe<Tensor> createOP(Tensor tensor, Indicator<Tensor> except) {
        if (!(tensor instanceof Product))
            return null;
        List<Sum> sums = new ArrayList<>();
        Product body = new Product();
        for (Tensor t : tensor)
            if ((t instanceof Sum) && !except.is(t))
                sums.add((Sum) t);
            else
                body.add(t);
        if (sums.isEmpty())
            return null;
        return new ExpandBracketsOutput(body, sums.toArray(new Sum[sums.size()]), except);
    }

    private static interface SumPort extends OutputPortUnsafe<Tensor> {
        void reset();
    }

    private static class SumPortImpl implements SumPort {
        private Sum sum;
        private Indicator<Tensor> except;
        private TensorIterator sumIterator;
        private OutputPortUnsafe<Tensor> currentPort = null;

        public SumPortImpl(Indicator<Tensor> except, Sum sum) {
            this.sum = sum;
            this.except = except;
            reset();
        }

        @Override
        public final void reset() {
            this.sumIterator = sum.iterator();
            currentPort = null;
        }

        @Override
        public Tensor take() {
            Tensor ret;
            if (currentPort != null && (ret = currentPort.take()) != null)
                return ret;
            if (!sumIterator.hasNext())
                return null;
            currentPort = null;
            Tensor summand = sumIterator.next();
            if (except.is(summand))
                return summand;
            currentPort = createOP(summand, except);
            if (currentPort != null)
                return currentPort.take();
            else
                return summand;
        }
    }

    private static class SumPortWrapper implements SumPort {
        private SumPort port;
        private Tensor[] buffer = new Tensor[BUFFER_SIZE];
        private int bufferPointer, firstBufferedElement = -1, sequenceSize, bufferSize;

        public SumPortWrapper(SumPort port) {
            this.port = port;
            bufferPointer = 0;
            sequenceSize = 0;
        }

        @Override
        public void reset() {
            if (firstBufferedElement == -1)
                firstBufferedElement = sequenceSize - bufferSize;
            if (firstBufferedElement > 0)
                port.reset();
            sequenceSize = 0;
            bufferPointer = 0;
        }

        @Override
        public Tensor take() {
            if (firstBufferedElement == sequenceSize)
                if (bufferPointer == bufferSize)
                    return null;
                else
                    return buffer[bufferPointer++];
            Tensor tensor = port.take();
            if (tensor == null)
                return null;
            sequenceSize++;
            assert sequenceSize > 0;
            if (firstBufferedElement == -1) {
                buffer[bufferPointer++] = tensor;
                if (bufferSize < BUFFER_SIZE)
                    bufferSize++;
                if (bufferPointer == BUFFER_SIZE)
                    bufferPointer = 0;
            }
            return tensor;
        }
    }
}
TOP

Related Classes of cc.redberry.transformation.concurrent.ExpandBracketsOutput$SumPortWrapper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.