001/* An actor that outputs the average of the inputs so far. 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.TypedIOPort; 031import ptolemy.data.BooleanToken; 032import ptolemy.data.IntToken; 033import ptolemy.data.Token; 034import ptolemy.data.expr.SingletonParameter; 035import ptolemy.data.type.BaseType; 036import ptolemy.kernel.CompositeEntity; 037import ptolemy.kernel.util.IllegalActionException; 038import ptolemy.kernel.util.NameDuplicationException; 039import ptolemy.kernel.util.StringAttribute; 040 041/////////////////////////////////////////////////////////////////// 042//// Average 043 044/** 045 <p>Output the average of the inputs after the last time a true token is 046 received at the reset port. 047 One output is produced each time the actor is fired. 048 The inputs and outputs can be any token type that 049 supports addition and division by an integer. The output type is 050 constrained to be the same as the input type. 051 Note that if the input is an integer, then the output is an 052 integer, which may not be what you want. You may need to set 053 the input and output ports to double to force the result to be 054 a double.</p> 055 <p> 056 Note that the type system will fail to catch some errors. Static type 057 checking may result in a resolved type that does not support addition 058 and division. In this case, a run-time error will occur. 059 </p> 060 061 @author Edward A. Lee, Jie Liu 062 @version $Id$ 063 @since Ptolemy II 0.3 064 @Pt.ProposedRating Green (eal) 065 @Pt.AcceptedRating Green (bilung) 066 */ 067public class Average extends Transformer { 068 /** Construct an actor with the given container and name. 069 * @param container The container. 070 * @param name The name of this actor. 071 * @exception IllegalActionException If the actor cannot be contained 072 * by the proposed container. 073 * @exception NameDuplicationException If the container already has an 074 * actor with this name. 075 */ 076 public Average(CompositeEntity container, String name) 077 throws NameDuplicationException, IllegalActionException { 078 super(container, name); 079 reset = new TypedIOPort(this, "reset", true, false); 080 reset.setTypeEquals(BaseType.BOOLEAN); 081 new StringAttribute(reset, "_cardinal").setExpression("SOUTH"); 082 new SingletonParameter(reset, "_showName").setToken(BooleanToken.TRUE); 083 } 084 085 /////////////////////////////////////////////////////////////////// 086 //// ports and parameters //// 087 088 /** The reset port of type BooleanToken. If this input port 089 * receives a True token, then the averaging process will be 090 * reset. 091 */ 092 public TypedIOPort reset; 093 094 /////////////////////////////////////////////////////////////////// 095 //// public methods //// 096 097 /** Consume at most one token from the <i>input</i> 098 * and compute the average of the input tokens so far. Send the 099 * result to the output. If there is no input token available, 100 * no output will be produced. If there is a true-valued token 101 * on the <i>reset</i> input, then the average is reset, and 102 * the output will be equal to the <i>input</i> token (if there 103 * is one). If the fire method 104 * is invoked multiple times in one iteration, then only the 105 * input read on the last invocation in the iteration will affect 106 * future averages. Inputs that are read earlier in the iteration 107 * are forgotten. 108 * @exception IllegalActionException If addition or division by an 109 * integer are not supported by the supplied tokens. 110 */ 111 @Override 112 public void fire() throws IllegalActionException { 113 super.fire(); 114 _latestSum = _sum; 115 _latestCount = _count; 116 117 // Check whether to reset. 118 for (int i = 0; i < reset.getWidth(); i++) { 119 if (reset.hasToken(i)) { 120 BooleanToken r = (BooleanToken) reset.get(i); 121 122 if (r.booleanValue()) { 123 // Being reset at this firing. 124 _latestSum = null; 125 _latestCount = 0; 126 } 127 } 128 } 129 130 if (input.hasToken(0)) { 131 Token in = input.get(0); 132 _latestCount++; 133 134 if (_latestSum == null) { 135 _latestSum = in; 136 } else { 137 _latestSum = _latestSum.add(in); 138 } 139 140 Token out = _latestSum.divide(new IntToken(_latestCount)); 141 output.broadcast(out); 142 } 143 } 144 145 /** Reset the count of inputs. 146 * @exception IllegalActionException If the parent class throws it. 147 */ 148 @Override 149 public void initialize() throws IllegalActionException { 150 super.initialize(); 151 _count = 0; 152 _sum = null; 153 } 154 155 /** Record the most recent input as part of the running average. 156 * Do nothing if there is no input. 157 * @exception IllegalActionException If the base class throws it. 158 */ 159 @Override 160 public boolean postfire() throws IllegalActionException { 161 _sum = _latestSum; 162 _count = _latestCount; 163 return super.postfire(); 164 } 165 166 /////////////////////////////////////////////////////////////////// 167 //// private members //// 168 private Token _sum; 169 170 private Token _latestSum; 171 172 private int _count = 0; 173 174 private int _latestCount; 175}