001/* An actor that disassemble an ArrayToken to a multiport output. 002 003 Copyright (c) 2003-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.actor.lib; 029 030import ptolemy.data.ArrayToken; 031import ptolemy.data.BooleanMatrixToken; 032import ptolemy.data.BooleanToken; 033import ptolemy.data.ComplexMatrixToken; 034import ptolemy.data.ComplexToken; 035import ptolemy.data.DoubleMatrixToken; 036import ptolemy.data.DoubleToken; 037import ptolemy.data.FixMatrixToken; 038import ptolemy.data.FixToken; 039import ptolemy.data.IntMatrixToken; 040import ptolemy.data.IntToken; 041import ptolemy.data.LongMatrixToken; 042import ptolemy.data.LongToken; 043import ptolemy.data.MatrixToken; 044import ptolemy.data.expr.Parameter; 045import ptolemy.data.type.ArrayType; 046import ptolemy.data.type.BaseType; 047import ptolemy.data.type.FixType; 048import ptolemy.data.type.Type; 049import ptolemy.kernel.CompositeEntity; 050import ptolemy.kernel.util.IllegalActionException; 051import ptolemy.kernel.util.NameDuplicationException; 052import ptolemy.kernel.util.Workspace; 053import ptolemy.math.Complex; 054import ptolemy.math.FixPoint; 055 056/////////////////////////////////////////////////////////////////// 057//// ArrayToMatrix 058 059/** 060 Convert an array to a row or column vector encoded as a matrix token. 061 The input array has to have a type that is convertible to a matrix. 062 063 @author Edward A. Lee 064 @version $Id$ 065 @since Ptolemy II 10.0 066 @Pt.ProposedRating Red (zhouye) 067 @Pt.AcceptedRating Red (cxh) 068 */ 069public class ArrayToMatrix extends Transformer { 070 /** Construct an actor with the given container and name. 071 * @param container The container. 072 * @param name The name of this actor. 073 * @exception IllegalActionException If the actor cannot be 074 * contained by the proposed container. 075 * @exception NameDuplicationException If the container 076 * already has an actor with this name. 077 */ 078 public ArrayToMatrix(CompositeEntity container, String name) 079 throws NameDuplicationException, IllegalActionException { 080 super(container, name); 081 082 // Set type constraints. 083 input.setTypeAtLeast(ArrayType.ARRAY_BOTTOM); 084 output.setTypeAtMost(BaseType.MATRIX); 085 086 rowVector = new Parameter(this, "rowVector"); 087 rowVector.setTypeEquals(BaseType.BOOLEAN); 088 rowVector.setExpression("true"); 089 090 // Set the icon. 091 _attachText("_iconDescription", 092 "<svg>\n" + "<polygon points=\"-15,-15 15,15 15,-15 -15,15\" " 093 + "style=\"fill:white\"/>\n" + "</svg>\n"); 094 } 095 096 /////////////////////////////////////////////////////////////////// 097 //// parameters //// 098 099 /** If true, then convert the array to a matrix with one row 100 * and multiple columns (a row vector), and otherwise, convert 101 * the input to a matrix with one column and multiple rows 102 * (a column vector). This is a boolean that defaults to true. 103 */ 104 public Parameter rowVector; 105 106 /////////////////////////////////////////////////////////////////// 107 //// public methods //// 108 109 /** Clone the actor into the specified workspace. This calls the 110 * base class and then creates new ports and parameters. 111 * @param workspace The workspace for the new object. 112 * @return A new actor. 113 * @exception CloneNotSupportedException If a derived class 114 * contains an attribute that cannot be cloned. 115 */ 116 @Override 117 public Object clone(Workspace workspace) throws CloneNotSupportedException { 118 ArrayToMatrix newObject = (ArrayToMatrix) super.clone(workspace); 119 newObject.input.setTypeAtLeast(ArrayType.ARRAY_BOTTOM); 120 newObject.output.setTypeAtMost(BaseType.MATRIX); 121 return newObject; 122 } 123 124 /** If there is a token at the input, read the array 125 * from the input port, and construct and send to the 126 * output a matrix containing the values from the array. 127 * @exception IllegalActionException If a runtime 128 * type conflict occurs. 129 */ 130 @Override 131 public void fire() throws IllegalActionException { 132 super.fire(); 133 if (input.hasToken(0)) { 134 ArrayToken token = (ArrayToken) input.get(0); 135 int size = token.length(); 136 int rows = 1; 137 int columns = size; 138 if (!((BooleanToken) rowVector.getToken()).booleanValue()) { 139 rows = size; 140 columns = 1; 141 } 142 Type arrayElementType = token.getElementType(); 143 // Have to look for matching types. 144 if (arrayElementType.equals(BaseType.INT)) { 145 int[] contents = new int[size]; 146 for (int i = 0; i < token.length(); i++) { 147 contents[i] = ((IntToken) token.getElement(i)).intValue(); 148 } 149 MatrixToken result = new IntMatrixToken(contents, rows, columns, 150 MatrixToken.DO_NOT_COPY); 151 output.broadcast(result); 152 } else if (arrayElementType.equals(BaseType.DOUBLE)) { 153 double[] contents = new double[size]; 154 for (int i = 0; i < token.length(); i++) { 155 contents[i] = ((DoubleToken) token.getElement(i)) 156 .doubleValue(); 157 } 158 MatrixToken result = new DoubleMatrixToken(contents, rows, 159 columns, MatrixToken.DO_NOT_COPY); 160 output.broadcast(result); 161 } else if (arrayElementType.equals(BaseType.BOOLEAN)) { 162 boolean[][] contents = new boolean[rows][columns]; 163 for (int i = 0; i < rows; i++) { 164 for (int j = 0; j < columns; j++) { 165 contents[i][j] = ((BooleanToken) token 166 .getElement(j + i * columns)).booleanValue(); 167 } 168 } 169 MatrixToken result = new BooleanMatrixToken(contents); 170 output.broadcast(result); 171 } else if (arrayElementType.equals(BaseType.COMPLEX)) { 172 Complex[][] contents = new Complex[rows][columns]; 173 for (int i = 0; i < rows; i++) { 174 for (int j = 0; j < columns; j++) { 175 contents[i][j] = ((ComplexToken) token 176 .getElement(j + i * columns)).complexValue(); 177 } 178 } 179 MatrixToken result = new ComplexMatrixToken(contents, 180 MatrixToken.DO_NOT_COPY); 181 output.broadcast(result); 182 } else if (arrayElementType instanceof FixType) { 183 FixPoint[][] contents = new FixPoint[rows][columns]; 184 for (int i = 0; i < rows; i++) { 185 for (int j = 0; j < columns; j++) { 186 contents[i][j] = ((FixToken) token 187 .getElement(j + i * columns)).fixValue(); 188 } 189 } 190 MatrixToken result = new FixMatrixToken(contents); 191 output.broadcast(result); 192 } else if (arrayElementType.equals(BaseType.LONG)) { 193 long[] contents = new long[size]; 194 for (int i = 0; i < token.length(); i++) { 195 contents[i] = ((LongToken) token.getElement(i)).longValue(); 196 } 197 MatrixToken result = new LongMatrixToken(contents, rows, 198 columns, MatrixToken.DO_NOT_COPY); 199 output.broadcast(result); 200 } else { 201 // Not a supported type. 202 throw new IllegalActionException(this, 203 "Received an input array with elements of type " 204 + arrayElementType 205 + " for which there is no corresponding matrix type."); 206 } 207 } 208 } 209}