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}