001/* Extract a subarray from an array. 002 003 Copyright (c) 1998-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.actor.parameters.PortParameter; 031import ptolemy.data.ArrayToken; 032import ptolemy.data.IntToken; 033import ptolemy.data.Token; 034import ptolemy.data.expr.Parameter; 035import ptolemy.data.type.ArrayType; 036import ptolemy.data.type.Type; 037import ptolemy.kernel.CompositeEntity; 038import ptolemy.kernel.util.IllegalActionException; 039import ptolemy.kernel.util.NameDuplicationException; 040import ptolemy.kernel.util.StringAttribute; 041import ptolemy.kernel.util.Workspace; 042 043/////////////////////////////////////////////////////////////////// 044//// ArrayExtract 045 046/** 047 Extract a subarray from an array. This actor reads an array from the 048 <i>input</i> port and sends a subarray to the <i>output</i> 049 port, possibly padded with zeros. The segment of the input array 050 starting at <i>sourcePosition</i> with length <i>extractLength</i> is 051 copied to the output array, starting at <i>destinationPosition</i>. 052 The total length of the output array is <i>outputArrayLength</i>. 053 Any of its entries that are not supplied by the input have value 054 zero (of the same type as the entries in the input array). 055 With the default values of the parameters, only the first element 056 of the input array is copied to the output array, which has length one. 057 The output type is the same as the input type. 058 059 @author Edward A. Lee, Elaine Cheong 060 @version $Id$ 061 @since Ptolemy II 1.0 062 @Pt.ProposedRating Green (celaine) 063 @Pt.AcceptedRating Green (cxh) 064 */ 065public class ArrayExtract extends Transformer { 066 /** Construct an actor with the given container and name. 067 * @param container The container. 068 * @param name The name of this actor. 069 * @exception IllegalActionException If the actor cannot be contained 070 * by the proposed container. 071 * @exception NameDuplicationException If the container already has an 072 * actor with this name. 073 */ 074 public ArrayExtract(CompositeEntity container, String name) 075 throws NameDuplicationException, IllegalActionException { 076 super(container, name); 077 078 // Set type constraints. 079 input.setTypeAtLeast(ArrayType.ARRAY_BOTTOM); 080 output.setTypeAtLeast(input); 081 // FIXME: correct type constraint for length 082 output.setTypeAtLeast(ArrayType.ARRAY_UNSIZED_BOTTOM); 083 084 // Set parameters. 085 sourcePosition = new PortParameter(this, "sourcePosition"); 086 sourcePosition.setExpression("0"); 087 new StringAttribute(sourcePosition.getPort(), "_cardinal") 088 .setExpression("SOUTH"); 089 new Parameter(sourcePosition.getPort(), "_showName") 090 .setExpression("true"); 091 extractLength = new PortParameter(this, "extractLength"); 092 extractLength.setExpression("1"); 093 new StringAttribute(extractLength.getPort(), "_cardinal") 094 .setExpression("SOUTH"); 095 new Parameter(extractLength.getPort(), "_showName") 096 .setExpression("true"); 097 destinationPosition = new PortParameter(this, "destinationPosition"); 098 destinationPosition.setExpression("0"); 099 new StringAttribute(destinationPosition.getPort(), "_cardinal") 100 .setExpression("SOUTH"); 101 new Parameter(destinationPosition.getPort(), "_showName") 102 .setExpression("true"); 103 outputArrayLength = new PortParameter(this, "outputArrayLength"); 104 outputArrayLength.setExpression("1"); 105 new StringAttribute(outputArrayLength.getPort(), "_cardinal") 106 .setExpression("SOUTH"); 107 new Parameter(outputArrayLength.getPort(), "_showName") 108 .setExpression("true"); 109 } 110 111 /////////////////////////////////////////////////////////////////// 112 //// parameters //// 113 114 /** The index into the input array at which to start copying. 115 * This is a non-negative integer that defaults to 0, and is 116 * required to be less than the length of the input array. 117 */ 118 public PortParameter sourcePosition; 119 120 /** The length of the segment of the input array that is copied 121 * to the output. This is a non-negative integer that defaults 122 * to 1. The sum of it and the <i>sourcePosition</i> is 123 * required to be less than or equal to the length of the input array. 124 */ 125 public PortParameter extractLength; 126 127 /** The index into the output array at which to start copying. 128 * This is a non-negative integer that defaults to 0, and is 129 * required to be less than the length of the output array. 130 */ 131 public PortParameter destinationPosition; 132 133 /** The total length of the output array. 134 * This is a non-negative integer that defaults to 1. It is 135 * required to be at least <i>destinationPosition</i> plus 136 * <i>extractLength</i>. 137 */ 138 public PortParameter outputArrayLength; 139 140 /////////////////////////////////////////////////////////////////// 141 //// public methods //// 142 143 /** Clone the actor into the specified workspace. This calls the 144 * base class and then sets up the type constraints. 145 * @param workspace The workspace for the new object. 146 * @return A new actor. 147 * @exception CloneNotSupportedException If a derived class contains 148 * an attribute that cannot be cloned. 149 */ 150 @Override 151 public Object clone(Workspace workspace) throws CloneNotSupportedException { 152 ArrayExtract newObject = (ArrayExtract) super.clone(workspace); 153 154 // Set the type constraints. 155 newObject.input.setTypeAtLeast(ArrayType.ARRAY_BOTTOM); 156 newObject.output.setTypeAtLeast(newObject.input); 157 newObject.output.setTypeAtLeast(ArrayType.ARRAY_UNSIZED_BOTTOM); 158 159 return newObject; 160 } 161 162 /** Consume one array from the input port and send a subarray to 163 * the output port, padding the subarray with zeros if necessary. 164 * @exception IllegalActionException If any parameter value 165 * is out of range. 166 */ 167 @Override 168 public void fire() throws IllegalActionException { 169 super.fire(); 170 sourcePosition.update(); 171 extractLength.update(); 172 destinationPosition.update(); 173 outputArrayLength.update(); 174 175 if (input.hasToken(0)) { 176 ArrayToken inputValue = (ArrayToken) input.get(0); 177 Type inputElementType = inputValue.getElementType(); 178 Token[] inputArray = inputValue.arrayValue(); 179 int sourcePositionValue = ((IntToken) sourcePosition.getToken()) 180 .intValue(); 181 int extractLengthValue = ((IntToken) extractLength.getToken()) 182 .intValue(); 183 int destinationPositionValue = ((IntToken) destinationPosition 184 .getToken()).intValue(); 185 int outputArrayLengthValue = ((IntToken) outputArrayLength 186 .getToken()).intValue(); 187 188 try { 189 Token[] outputArray = new Token[outputArrayLengthValue]; 190 191 Token zero = inputArray[0].zero(); 192 193 for (int i = 0; i < destinationPositionValue; i++) { 194 outputArray[i] = zero; 195 } 196 int j = sourcePositionValue; 197 for (int i = destinationPositionValue; i < destinationPositionValue 198 + extractLengthValue; i++) { 199 outputArray[i] = inputValue.getElement(j++); 200 } 201 for (int i = destinationPositionValue 202 + extractLengthValue; i < outputArrayLengthValue; i++) { 203 outputArray[i] = zero; 204 } 205 206 output.send(0, new ArrayToken(inputElementType, outputArray)); 207 } catch (IndexOutOfBoundsException ex) { 208 throw new IllegalActionException(this, 209 "Parameter values out of range for the array supplied." 210 + "inputArray has length " + inputArray.length); 211 } 212 } 213 } 214}