001/* An actor that performs a specified logic operation on the input.
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.logic;
029
030import java.util.Locale;
031
032import ptolemy.actor.lib.Transformer;
033import ptolemy.data.BooleanToken;
034import ptolemy.data.Token;
035import ptolemy.data.type.BaseType;
036import ptolemy.kernel.CompositeEntity;
037import ptolemy.kernel.util.Attribute;
038import ptolemy.kernel.util.IllegalActionException;
039import ptolemy.kernel.util.InternalErrorException;
040import ptolemy.kernel.util.NameDuplicationException;
041import ptolemy.kernel.util.StringAttribute;
042
043// NOTE: If you update the list of functions, then you will want
044// to update the list in actor/lib/logic/logic.xml.
045///////////////////////////////////////////////////////////////////
046//// LogicFunction
047
048/**
049 <p>Produce an output token on each firing with a value that is
050 equal to the specified logic operator of the input(s).
051 The functions are:</p>
052 <ul>
053 <li> <b>and</b>: The logical and operator.
054 This is the default function for this actor.</li>
055 <li> <b>or</b>: The logical or operator.</li>
056 <li> <b>xor</b>: The logical xor operator.</li>
057 <li> <b>nand</b>: The logical nand operator.
058 Equivalent to the negation of <i>and</i>.</li>
059 <li> <b>nor</b>: The logical nor operator.
060 Equivalent to the negation of <i>or</i>.</li>
061 <li> <b>xnor</b>: The logical xnor operator.
062 Equivalent to the negation of <i>xor</i>.</li>
063 </ul>
064 <p>
065 NOTE: All operators have
066 a single input port, which is a multiport, and a single output port, which
067 is not a multiport.  All ports have type boolean.</p>
068 <p>
069 This actor does not require that each input
070 channel have a token upon firing.  As long as one channel contains a
071 token, output will be produced.  If no input tokens are available at
072 all, then no output is produced.  At most one token is consumed
073 on each input channel.</p>
074
075 @author Paul Whitaker
076 @deprecated Use LogicGate instead.
077 @version $Id$
078 @since Ptolemy II 1.0
079 @Pt.ProposedRating Green (pwhitake)
080 @Pt.AcceptedRating Green (pwhitake)
081 */
082@Deprecated
083public class LogicFunction extends Transformer {
084    /** Construct an actor with the given container and name.  Set the
085     *  logic function to the default ("and").  Set the types of the ports
086     *  to boolean.
087     *  @param container The container.
088     *  @param name The name of this actor.
089     *  @exception IllegalActionException If the actor cannot be contained
090     *   by the proposed container.
091     *  @exception NameDuplicationException If the container already has an
092     *   actor with this name.
093     */
094    public LogicFunction(CompositeEntity container, String name)
095            throws NameDuplicationException, IllegalActionException {
096        super(container, name);
097
098        // Parameters
099        function = new StringAttribute(this, "function");
100        function.setExpression("and");
101        _function = _AND;
102        _negate = false;
103
104        // Ports
105        input.setMultiport(true);
106        output.setMultiport(false);
107        input.setTypeEquals(BaseType.BOOLEAN);
108        output.setTypeEquals(BaseType.BOOLEAN);
109
110        _attachText("_iconDescription",
111                "<svg>\n" + "<rect x=\"-30\" y=\"-15\" "
112                        + "width=\"60\" height=\"30\" "
113                        + "style=\"fill:white\"/>\n" + "</svg>\n");
114    }
115
116    ///////////////////////////////////////////////////////////////////
117    ////                     ports and parameters                  ////
118
119    /** The function to compute.  This is a string-valued attribute
120     *  that defaults to "and".
121     */
122    public StringAttribute function;
123
124    ///////////////////////////////////////////////////////////////////
125    ////                         public methods                    ////
126
127    /** Override the base class to determine which function is being
128     *  specified.  Read the value of the function attribute and set
129     *  the cached value appropriately.
130     *  @param attribute The attribute that changed.
131     *  @exception IllegalActionException If the function is not recognized.
132     */
133    @Override
134    public void attributeChanged(Attribute attribute)
135            throws IllegalActionException {
136        if (attribute == function) {
137            String functionName = function.getExpression().trim()
138                    .toLowerCase(Locale.getDefault());
139
140            if (functionName.equals("and")) {
141                _function = _AND;
142                _negate = false;
143            } else if (functionName.equals("or")) {
144                _function = _OR;
145                _negate = false;
146            } else if (functionName.equals("xor")) {
147                _function = _XOR;
148                _negate = false;
149            } else if (functionName.equals("nand")) {
150                _function = _AND;
151                _negate = true;
152            } else if (functionName.equals("nor")) {
153                _function = _OR;
154                _negate = true;
155            } else if (functionName.equals("xnor")) {
156                _function = _XOR;
157                _negate = true;
158            } else {
159                throw new IllegalActionException(this,
160                        "Unrecognized logic function: " + functionName
161                                + ".  Valid functions are 'and', 'or', 'xor', "
162                                + "'nand', 'nor', and 'xnor'.");
163            }
164        } else {
165            super.attributeChanged(attribute);
166        }
167    }
168
169    /** Consume at most one input token from each input channel,
170     *  and produce a token on the output port.  If there is no
171     *  input on any channel, then produce no output.
172     *  @exception IllegalActionException If there is no director.
173     */
174    @Override
175    public void fire() throws IllegalActionException {
176        super.fire();
177        BooleanToken value = null;
178        BooleanToken in = null;
179
180        for (int i = 0; i < input.getWidth(); i++) {
181            if (input.hasToken(i)) {
182                in = (BooleanToken) input.get(i);
183
184                if (in != null) {
185                    value = _updateFunction(in, value);
186                }
187            }
188        }
189
190        if (value != null) {
191            if (_negate) {
192                value = value.not();
193            }
194
195            output.send(0, value);
196        }
197    }
198
199    ///////////////////////////////////////////////////////////////////
200    ////                         protected methods                 ////
201
202    /** Calculate the function on the given arguments.
203     *  @param in The new input value.  Should never be null.
204     *  @param old The old result value, or null if there is none.
205     *  @return The result of applying the function.
206     *  @exception IllegalActionException If thrown by BooleanToken operations.
207     */
208    protected BooleanToken _updateFunction(BooleanToken in, BooleanToken old)
209            throws IllegalActionException {
210        Token result;
211
212        if (old == null) {
213            result = in;
214        } else {
215            switch (_function) {
216            case _AND:
217                result = old.and(in);
218                break;
219
220            case _OR:
221                result = old.or(in);
222                break;
223
224            case _XOR:
225                result = old.xor(in);
226                break;
227
228            default:
229                throw new InternalErrorException(
230                        "Invalid value for _function private variable. "
231                                + "LogicFunction actor (" + getFullName() + ")"
232                                + " on function type " + _function);
233            }
234        }
235
236        return (BooleanToken) result;
237    }
238
239    ///////////////////////////////////////////////////////////////////
240    ////                         protected variables               ////
241
242    /** An indicator for the function to compute.
243     *  Valid values are {@link #_AND}, {@link #_OR}, and {@link #_XOR}.
244     */
245    protected int _function;
246
247    /** True if the intermediate results should be negated. */
248    protected boolean _negate;
249
250    /** Perform a logical AND. */
251    protected static final int _AND = 0;
252
253    /** Perform a logical OR. */
254    protected static final int _OR = 1;
255
256    /** Perform a logical XOR. */
257    protected static final int _XOR = 2;
258}