001/* Split an input matrix into a sequence of input matrices.
002
003 Copyright (c) 2007-2014 The Regents of the University of California.
004 All rights reserved.
005 Permission is hereby granted, without written agreement and without
006 license or royalty fees, to use, copy, modify, and distribute this
007 software and its documentation for any purpose, provided that the above
008 copyright notice and the following two paragraphs appear in all copies
009 of this software.
010
011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
015 SUCH DAMAGE.
016
017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
022 ENHANCEMENTS, OR MODIFICATIONS.
023
024 PT_COPYRIGHT_VERSION_2
025 COPYRIGHTENDKEY
026
027 */
028package ptolemy.domains.sdf.lib;
029
030import ptolemy.data.ArrayToken;
031import ptolemy.data.IntToken;
032import ptolemy.data.MatrixToken;
033import ptolemy.data.expr.Parameter;
034import ptolemy.data.type.ArrayType;
035import ptolemy.data.type.BaseType;
036import ptolemy.kernel.CompositeEntity;
037import ptolemy.kernel.util.IllegalActionException;
038import ptolemy.kernel.util.NameDuplicationException;
039
040///////////////////////////////////////////////////////////////////
041//// MatrixSplit
042
043/**
044 This actor splits an input matrix into a sequence of matrices.
045 This actor reads 1 input matrix and produces N*M output matrices,
046 where N is the size of the <i>rowSplit</i> array, and M is
047 the size of the <i>columnSplit</i> parameter. The matrices
048 are produced from submatrices extracted left-to-right,
049 top-to-bottom, in a raster scan pattern.
050 For example, if <i>rowSplit</i> = {1, 2},
051 <i>columnSplit</i> = {2, 1}, and the input matrix is
052 as follows:
053 <pre>
054   1  2  3
055   4  5  6
056   7  8  9
057 </pre>
058 then the first matrix out is a column vector:
059  <pre>
060   1
061   4
062 </pre>
063 The second matrix out is
064  <pre>
065   2  3
066   5  6
067 </pre>
068 The third is
069  <pre>
070   7
071 </pre>
072 (a 1x1 matrix) and the fourth is
073  <pre>
074   8  9
075 </pre>
076 a row vector.
077 If the input does not have enough elements to fill the specified
078 output matrices, then zeros (of the same type as the input elements)
079 are used. If the input is larger than is required to fill the specified
080 output, then the additional values are discarded.
081 <p>
082
083 @author Edward Lee
084 @version $Id$
085 @since Ptolemy II 6.1
086 @Pt.ProposedRating Yellow (eal)
087 @Pt.AcceptedRating Red (neuendor)
088 */
089public class MatrixSplit extends SDFTransformer {
090    /** Construct an actor with the given container and name.
091     *  @param container The container.
092     *  @param name The name of this actor.
093     *  @exception IllegalActionException If the actor cannot be contained
094     *   by the proposed container.
095     *  @exception NameDuplicationException If the container already has an
096     *   actor with this name.
097     */
098    public MatrixSplit(CompositeEntity container, String name)
099            throws NameDuplicationException, IllegalActionException {
100        super(container, name);
101
102        // Set parameters.
103        rowSplit = new Parameter(this, "rowSplit");
104        rowSplit.setTypeEquals(new ArrayType(BaseType.INT));
105        rowSplit.setExpression("{1}");
106
107        columnSplit = new Parameter(this, "columnSplit");
108        columnSplit.setTypeEquals(new ArrayType(BaseType.INT));
109        columnSplit.setExpression("{1}");
110
111        output_tokenProductionRate
112                .setExpression("rowSplit.length() * columnSplit.length()");
113    }
114
115    ///////////////////////////////////////////////////////////////////
116    ////                         parameters                        ////
117
118    /** An array specifying the number of columns in the output matrices.
119     *  This is an array of integers, with default {1}.
120     */
121    public Parameter columnSplit;
122
123    /** An array specifying the number of rows in the output matrices.
124     *  This is an array of integers, with default {1}.
125     */
126    public Parameter rowSplit;
127
128    ///////////////////////////////////////////////////////////////////
129    ////                         public methods                    ////
130
131    /** Consume the input matrix and produce the output matrices.
132     *  @exception IllegalActionException If there is an error reading the inputs
133     *   or parameters.
134     */
135    @Override
136    public void fire() throws IllegalActionException {
137        super.fire();
138        if (!input.hasToken(0)) {
139            return;
140        }
141        ArrayToken columns = (ArrayToken) columnSplit.getToken();
142        ArrayToken rows = (ArrayToken) rowSplit.getToken();
143        int[] columnsValue = new int[columns.length()];
144        for (int i = 0; i < columnsValue.length; i++) {
145            columnsValue[i] = ((IntToken) columns.getElement(i)).intValue();
146        }
147        int[] rowsValue = new int[rows.length()];
148        for (int i = 0; i < rowsValue.length; i++) {
149            rowsValue[i] = ((IntToken) rows.getElement(i)).intValue();
150        }
151        MatrixToken inputValue = (MatrixToken) input.get(0);
152        MatrixToken[][] result = inputValue.split(rowsValue, columnsValue);
153        for (MatrixToken[] element : result) {
154            for (int j = 0; j < element.length; j++) {
155                output.send(0, element[j]);
156            }
157        }
158    }
159}