001/* A polymorphic multiplier/divider. 002 003 Copyright (c) 1997-2015 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.TypedAtomicActor; 031import ptolemy.actor.TypedIOPort; 032import ptolemy.data.Token; 033import ptolemy.kernel.CompositeEntity; 034import ptolemy.kernel.util.IllegalActionException; 035import ptolemy.kernel.util.NameDuplicationException; 036 037/////////////////////////////////////////////////////////////////// 038//// MultiplyDivide 039 040/** 041 042 <p>A polymorphic multiplier and/or divider. This adder has two input 043 ports, both of which are multiports, and one output port, which is 044 not. The types on the ports are undeclared and will be resolved by 045 the type resolution mechanism. Data that arrives on the input port 046 named <i>multiply</i> will be multiplied, and data that arrives on 047 the input port named <i>divide</i> will be divided. Any token type 048 supporting multiplication and division can be used. In most 049 domains, either input port can be left unconnected. Thus, to get a 050 simple multiplier (with no division), just leave the <i>divide</i> 051 input unconnected. 052 </p> 053 <p> 054 Currently, the type system is quite liberal about the resolved 055 types it will permit at the inputs. In particular, it may permit 056 the <i>multiply</i> and <i>divide</i> inputs to resolve to types 057 that cannot in fact be multiplied or divided. In these cases, a 058 run-time error will occur. In the future, we hope that the type 059 system will intercept such errors before run time. 060 </p> 061 <p> 062 This actor does not require that each input channel have a token 063 upon firing. It will multiply or divide available tokens at the 064 inputs and ignore the channels that do not have tokens. It 065 consumes at most one input token from each port. If no input 066 tokens are available on the <i>multiply</i> inputs, then a 067 numerator of one is assumed for the division operations. The "one" 068 is obtained by calling the one() method of the first token seen at 069 the <i>divide</i> input. If no input tokens are available at all, 070 then no output is produced. 071 </p> 072 073 @author Edward A. Lee 074 @version $Id$ 075 @since Ptolemy II 0.3 076 @Pt.ProposedRating Green (eal) 077 @Pt.AcceptedRating Green (bilung) 078 */ 079public class MultiplyDivide extends TypedAtomicActor { 080 /** Construct an actor in the specified container with the specified 081 * name. 082 * @param container The container. 083 * @param name The name of this actor within the container. 084 * @exception IllegalActionException If the actor cannot be contained 085 * by the proposed container. 086 * @exception NameDuplicationException If the name coincides with 087 * an actor already in the container. 088 */ 089 public MultiplyDivide(CompositeEntity container, String name) 090 throws IllegalActionException, NameDuplicationException { 091 super(container, name); 092 multiply = new TypedIOPort(this, "multiply", true, false); 093 multiply.setMultiport(true); 094 divide = new TypedIOPort(this, "divide", true, false); 095 divide.setMultiport(true); 096 output = new TypedIOPort(this, "output", false, true); 097 _attachText("_iconDescription", "<svg>\n" + "<rect x=\"-20\" y=\"-20\" " 098 + "width=\"40\" height=\"40\" " + "style=\"fill:white\"/>\n" 099 + "<line x1=\"-15\" y1=\"-15\" x2=\"-5\" y2=\"-5\"/>" 100 + "<line x1=\"-15\" y1=\"-5\" x2=\"-5\" y2=\"-15\"/>" 101 + "<line x1=\"-15\" y1=\"10\" x2=\"-5\" y2=\"10\"/>" 102 + "<circle cx=\"-10\" cy=\"6\" r=\"1\"" 103 + "style=\"fill:black\"/>\n" 104 + "<circle cx=\"-10\" cy=\"14\" r=\"1\"" 105 + "style=\"fill:black\"/>\n" + "</svg>\n"); 106 } 107 108 /////////////////////////////////////////////////////////////////// 109 //// ports and parameters //// 110 111 /** Input for tokens to be divided. This is a multiport, and its 112 * type is inferred from the connections. 113 */ 114 public TypedIOPort divide; 115 116 /** Output port. The type is inferred from the connections. 117 */ 118 public TypedIOPort output; 119 120 /** Input for tokens to be multiplied. This is a multiport, and its 121 * type is inferred from the connections. 122 */ 123 public TypedIOPort multiply; 124 125 /////////////////////////////////////////////////////////////////// 126 //// public methods //// 127 128 /** If there is at least one token on the input ports, multiply 129 * tokens from the <i>multiply</i> port, divide by tokens from 130 * the <i>divide</i> port, and send the result to the output 131 * port. At most one token is read from each channel, so if more 132 * than one token is pending, the rest are left for future 133 * firings. If none of the input channels has a token, do 134 * nothing. If none of the multiply channels have tokens, then 135 * the tokens on the divide channels are divided into a one token 136 * of the same type as the denominator. 137 * 138 * @exception IllegalActionException If there is no director, 139 * or if multiplication and division are not supported by the 140 * available tokens. 141 */ 142 @Override 143 public void fire() throws IllegalActionException { 144 super.fire(); 145 Token numerator = null; 146 try { 147 for (int i = 0; i < multiply.getWidth(); i++) { 148 if (multiply.hasToken(i)) { 149 if (numerator == null) { 150 numerator = multiply.get(i); 151 } else { 152 numerator = numerator.multiply(multiply.get(i)); 153 } 154 } 155 } 156 157 Token denominator = null; 158 159 for (int i = 0; i < divide.getWidth(); i++) { 160 if (divide.hasToken(i)) { 161 if (denominator == null) { 162 denominator = divide.get(i); 163 } else { 164 denominator = denominator.multiply(divide.get(i)); 165 } 166 } 167 } 168 169 if (numerator == null) { 170 if (denominator == null) { 171 return; 172 } 173 174 // For the benefit of copernicus, this means that 175 // numerator always has the same type. 176 numerator = multiply.getType().convert(denominator.one()); 177 } 178 179 if (denominator != null) { 180 numerator = numerator.divide(denominator); 181 } 182 } catch (Exception e) { 183 throw new IllegalActionException(this, e.getCause(), 184 e.getMessage()); 185 } 186 187 output.send(0, numerator); 188 } 189}