001/* An actor that outputs the sum of the elements of an input array.
002
003 Copyright (c) 2007-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 */
027package ptolemy.actor.lib;
028
029import ptolemy.data.ArrayToken;
030import ptolemy.data.Token;
031import ptolemy.data.type.ArrayType;
032import ptolemy.kernel.CompositeEntity;
033import ptolemy.kernel.util.IllegalActionException;
034import ptolemy.kernel.util.InternalErrorException;
035import ptolemy.kernel.util.NameDuplicationException;
036import ptolemy.kernel.util.Workspace;
037
038///////////////////////////////////////////////////////////////////
039//// ArraySum
040
041/**
042 Compute the sum of the elements in an array.  This actor reads an
043 array from the <i>input</i> port and sends the sum of its elements
044 to the <i>output</i> port. The output data type is at least the
045 type of the elements of the input array.  The elements of the input
046 array have to support addition, or an
047 exception will be thrown in the fire() method.
048 This actor is similar to ArrayAverage, except that it supports
049 data types that do not support division by an integer.
050
051 @author Edward A. Lee, Christine Avanessians
052 @version $Id$
053 @since Ptolemy II 6.1
054 @see ArrayAverage
055 @Pt.ProposedRating Red (cxh)
056 @Pt.AcceptedRating Red (cxh)
057 */
058public class ArraySum extends Transformer {
059    /** Construct an actor with the given container and name.
060     *  @param container The container.
061     *  @param name The name of this actor.
062     *  @exception IllegalActionException If the actor cannot be contained
063     *   by the proposed container.
064     *  @exception NameDuplicationException If the container already has an
065     *   actor with this name.
066     */
067    public ArraySum(CompositeEntity container, String name)
068            throws NameDuplicationException, IllegalActionException {
069        super(container, name);
070
071        // set type constraints.
072        output.setTypeAtLeast(ArrayType.elementType(input));
073    }
074
075    ///////////////////////////////////////////////////////////////////
076    ////                         public methods                    ////
077
078    /** Override the base class to set type constraints.
079     *  @param workspace The workspace for the new object.
080     *  @return A new instance of ArraySum.
081     *  @exception CloneNotSupportedException If a derived class contains
082     *   an attribute that cannot be cloned.
083     */
084    @Override
085    public Object clone(Workspace workspace) throws CloneNotSupportedException {
086        ArraySum newObject = (ArraySum) super.clone(workspace);
087        try {
088            newObject.output
089                    .setTypeAtLeast(ArrayType.elementType(newObject.input));
090        } catch (IllegalActionException e) {
091            // Should have been caught before.
092            throw new InternalErrorException(e);
093        }
094        return newObject;
095    }
096
097    /** Consume at most one array from the input port and produce
098     *  the average of its elements on the <i>output</i> port.
099     *  If there is no token on the input, or if the input array
100     *  is empty, then no output is produced.
101     *  @exception IllegalActionException If there is no director.
102     */
103    @Override
104    public void fire() throws IllegalActionException {
105        super.fire();
106        if (input.hasToken(0)) {
107            ArrayToken token = (ArrayToken) input.get(0);
108
109            if (token.length() == 0) {
110                return;
111            }
112
113            Token sum = token.getElement(0);
114
115            for (int i = 1; i < token.length(); i++) {
116                sum = sum.add(token.getElement(i));
117            }
118
119            output.send(0, sum);
120        }
121    }
122}