001/* An actor that computes a specified math function of the input.
002
003 Copyright (c) 2004-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.DoubleToken;
031import ptolemy.data.expr.StringParameter;
032import ptolemy.data.type.BaseType;
033import ptolemy.kernel.CompositeEntity;
034import ptolemy.kernel.util.Attribute;
035import ptolemy.kernel.util.IllegalActionException;
036import ptolemy.kernel.util.InternalErrorException;
037import ptolemy.kernel.util.NameDuplicationException;
038
039// NOTE: If you update the list of functions, then you will want
040// to update the list in actor/lib/math.xml.
041///////////////////////////////////////////////////////////////////
042//// UnaryMathFunction
043
044/**
045 Produce an output token on each firing with a value that is
046 equal to the specified math function of the input.
047 The input and output types are DoubleToken.  The functions
048 are a subset of those in the java.lang.Math class.  They are:
049 <ul>
050 <li> <b>exp</b>: The exponential function.
051 This is the default function for this actor
052 If the argument is NaN, then the result is NaN.
053 <li> <b>log</b>: The natural logarithm function.
054 If the argument is NaN, then the result is NaN.
055 <li> <b>sign</b>: If the argument is greater than 0, return 1.0, if
056 it is less than 0, return -1.0, otherwise return 0.0.
057 <li> <b>square</b>: The square function
058 If the argument is NaN, then the result is NaN.
059 <li> <b>sqrt</b>: The square root function.
060 If the argument is NaN, then the result is NaN.
061 </ul>
062 <p>
063
064 @author C. Fong, Steve Neuendorffer
065 @version $Id$
066 @since Ptolemy II 4.1
067 @Pt.ProposedRating Yellow (neuendor)
068 @Pt.AcceptedRating Red (neuendor)
069 @see AbsoluteValue
070 @see Remainder
071 @see Scale
072 @see TrigFunction
073 */
074public class UnaryMathFunction extends Transformer {
075    /** Construct an actor with the given container and name.
076     *  @param container The container.
077     *  @param name The name of this actor.
078     *  @exception IllegalActionException If the actor cannot be contained
079     *   by the proposed container.
080     *  @exception NameDuplicationException If the container already has an
081     *   actor with this name.
082     */
083    public UnaryMathFunction(CompositeEntity container, String name)
084            throws NameDuplicationException, IllegalActionException {
085        super(container, name);
086
087        // Parameters
088        function = new StringParameter(this, "function");
089        function.setExpression("exp");
090        function.addChoice("exp");
091        function.addChoice("log");
092        function.addChoice("sign");
093        function.addChoice("square");
094        function.addChoice("sqrt");
095        _function = _EXP;
096
097        // Ports
098        input.setTypeEquals(BaseType.DOUBLE);
099        output.setTypeEquals(BaseType.DOUBLE);
100
101        // Create a simple rectangle icon.
102        _attachText("_iconDescription",
103                "<svg>\n" + "<rect x=\"-30\" y=\"-15\" "
104                        + "width=\"60\" height=\"30\" "
105                        + "style=\"fill:white\"/>\n" + "</svg>\n");
106    }
107
108    ///////////////////////////////////////////////////////////////////
109    ////                     ports and parameters                  ////
110
111    /** The function to compute.  This is a string-valued attribute
112     *  that defaults to "exp".
113     */
114    public StringParameter function;
115
116    ///////////////////////////////////////////////////////////////////
117    ////                         public methods                    ////
118
119    /** Override the base class to determine which function is being
120     *  specified.
121     *  @param attribute The attribute that changed.
122     *  @exception IllegalActionException If the function is not recognized.
123     */
124    @Override
125    public void attributeChanged(Attribute attribute)
126            throws IllegalActionException {
127        if (attribute == function) {
128            String functionName = function.stringValue();
129
130            if (functionName.equals("exp")) {
131                _function = _EXP;
132            } else if (functionName.equals("log")) {
133                _function = _LOG;
134            } else if (functionName.equals("sign")) {
135                _function = _SIGN;
136            } else if (functionName.equals("square")) {
137                _function = _SQUARE;
138            } else if (functionName.equals("sqrt")) {
139                _function = _SQRT;
140            } else {
141                throw new IllegalActionException(this,
142                        "Unrecognized math function: " + functionName);
143            }
144        } else {
145            super.attributeChanged(attribute);
146        }
147    }
148
149    /** Consume at most one input token from each input channel, and
150     *  compute the specified math function of the input.
151     *  If there is no input, then produce no output.
152     *  @exception IllegalActionException If there is no director.
153     */
154    @Override
155    public void fire() throws IllegalActionException {
156        super.fire();
157        if (input.hasToken(0)) {
158            double inputValue = ((DoubleToken) input.get(0)).doubleValue();
159            output.send(0, new DoubleToken(_doFunction(inputValue)));
160        }
161    }
162
163    ///////////////////////////////////////////////////////////////////
164    ////                         private methods                   ////
165
166    /** Calculate the function on the given argument.
167     *  @param input The input value.
168     *  @return The result of applying the function.
169     */
170    private double _doFunction(double input) {
171        double result;
172
173        switch (_function) {
174        case _EXP:
175            result = Math.exp(input);
176            break;
177
178        case _LOG:
179            result = Math.log(input);
180            break;
181
182        case _SIGN:
183
184            if (input > 0) {
185                result = 1.0;
186            } else if (input < 0) {
187                result = -1.0;
188            } else {
189                result = 0.0;
190            }
191
192            break;
193
194        case _SQUARE:
195            result = input * input;
196            break;
197
198        case _SQRT:
199            result = Math.sqrt(input);
200            break;
201
202        default:
203            throw new InternalErrorException(
204                    "Invalid value for _function private variable. "
205                            + "MathFunction actor (" + getFullName() + ")"
206                            + " on function type " + _function);
207        }
208
209        return result;
210    }
211
212    ///////////////////////////////////////////////////////////////////
213    ////                         private variables                 ////
214    // An indicator for the function to compute.
215    private int _function;
216
217    // Constants used for more efficient execution.
218    private static final int _EXP = 0;
219
220    private static final int _LOG = 1;
221
222    private static final int _SIGN = 2;
223
224    private static final int _SQUARE = 3;
225
226    private static final int _SQRT = 4;
227}