001/* Interface representing a dependency between ports.
002
003 Copyright (c) 2008-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.util;
029
030///////////////////////////////////////////////////////////////////
031//// SuperdenseDependency
032
033/**
034 This dependency represents causal relationships that have a real value
035 and a superdense time index. If the real value is infinite, this
036 represents the lack of a causal relationship.
037 A finite positive real value represents a causal dependency with (typically)
038 a time delay. A zero value represents no time delay, but whether there is
039 an immediate causal relationship depends on the index. If the index is 0,
040 then there is an immediate causal relationship. Otherwise, there is not.
041 See the paper "Causality Interfaces for Actor Networks" by Ye Zhou and
042 Edward A. Lee, ACM Transactions on Embedded Computing Systems (TECS),
043 April 2008, as available as <a href="http://www.eecs.berkeley.edu/Pubs/TechRpts/2006/EECS-2006-148.pdf">
044 Technical Report No. UCB/EECS-2006-148</a>,
045 November 16, 2006.
046
047 @author Edward A. Lee, Slobodan Matic, Jia Zou
048 @version $Id$
049 @since Ptolemy II 8.0
050 @Pt.ProposedRating Yellow (eal)
051 @Pt.AcceptedRating Red (eal)
052 */
053public class SuperdenseDependency extends BooleanDependency {
054
055    /** Construct a dependency with the specified value.
056     *  The constructor is private. Use valueOf() to construct
057     *  an instance.
058     *  @param time The real part of the dependency.
059     *  @param index The supersense index part of the dependency.
060     */
061    private SuperdenseDependency(double time, int index) {
062        super(time != Double.POSITIVE_INFINITY);
063        _time = time;
064        _index = index;
065    }
066
067    ///////////////////////////////////////////////////////////////////
068    ////                         public methods                    ////
069
070    /** Return Dependency.LESS_THAN, EQUALS, or GREATER_THAN depending
071     *  on whether the argument is less than, equal to, or greater than
072     *  this dependency. Real dependencies are totally ordered, so
073     *  this never returns Dependency.INCOMPARABLE. The order is the
074     *  usual numerical ordering of doubles, with Double.POSITIVE_INFINITY
075     *  on top.
076     *  <p>
077     *  In the case where both dependencies have _time value equal to
078     *  Double.POSITIVE_INFINITY, these two dependencies are equal, even
079     *  though its indices may differ. This conforms with valueOf() method.
080     *  @see #valueOf(double, int)
081     *  @param dependency The dependency to compare against.
082     *  @return The result of comparison.
083     *  @exception ClassCastException If the argument is not an instance
084     *   of SuperdenseDependency.
085     */
086    @Override
087    public int compareTo(Dependency dependency) {
088        if (equals(dependency)) {
089            return Dependency.EQUALS;
090        }
091        if (((SuperdenseDependency) dependency)._time == Double.POSITIVE_INFINITY
092                && _time == Double.POSITIVE_INFINITY) {
093            return Dependency.EQUALS;
094        }
095        if (_time < ((SuperdenseDependency) dependency)._time) {
096            return Dependency.LESS_THAN;
097        }
098        if (_time == ((SuperdenseDependency) dependency)._time
099                && _index < ((SuperdenseDependency) dependency)._index) {
100            return Dependency.LESS_THAN;
101        }
102        return Dependency.GREATER_THAN;
103    }
104
105    /** Return true if the value of this dependency equals that
106     *  of the specified one, and the specified one is an instance
107     *  of RealDependency.
108     *  <p>
109     *  In the case where both dependencies have _time value equal to
110     *  Double.POSITIVE_INFINITY, these two dependencies are equal, even
111     *  though its indices may differ. This conforms with valueOf() method.
112     *  @see #valueOf(double, int)
113     *  @param object The object to compare against.
114     *  @return true if this object is the same as the object argument.
115     */
116    @Override
117    public boolean equals(Object object) {
118        // See http://www.technofundo.com/tech/java/equalhash.html
119        if (object == this) {
120            return true;
121        }
122        if (object == null || object.getClass() != getClass()) {
123            return false;
124        } else {
125            if (((SuperdenseDependency) object)._time == Double.POSITIVE_INFINITY
126                    && _time == Double.POSITIVE_INFINITY) {
127                return true;
128            }
129            return _time == ((SuperdenseDependency) object)._time
130                    && _index == ((SuperdenseDependency) object)._index;
131        }
132    }
133
134    /** Return the same hashCode that that Java Double object would
135     *  return had it the same value as the real part of the value
136     *  of this dependency.
137     */
138    @Override
139    public int hashCode() {
140        long v = Double.doubleToLongBits(_time);
141        return (int) (v ^ v >>> 32);
142    }
143
144    /** Return the index value of this dependency.
145     *  @return The index part of the dependency.
146     */
147    public int indexValue() {
148        return _index;
149    }
150
151    /** Return a dependency that results from parallel composition of
152     *  this one and the specified one.
153     *  @param dependency The dependency to add.
154     *  @return A dependency whose value is the minimum of the two dependency
155     *   values.
156     *  @exception ClassCastException if dependency is not a SuperdenseDependency.
157     */
158    @Override
159    public Dependency oPlus(Dependency dependency) {
160        // NOTE: Findbugs reports this as an Unchecked/unconfirmed cast
161        if (((SuperdenseDependency) dependency)._time < _time
162                || ((SuperdenseDependency) dependency)._time == _time
163                        && ((SuperdenseDependency) dependency)._index < _index) {
164            return dependency;
165        }
166        return this;
167    }
168
169    /** Return the dependency that when added to any other
170     *  dependency using oPlus() yields the other dependency.
171     *  @return The additive identity.
172     */
173    @Override
174    public Dependency oPlusIdentity() {
175        return OPLUS_IDENTITY;
176    }
177
178    /** Return a dependency that results from serial composition of
179     *  this one and the specified one. The real part of the result
180     *  is the sum of the real parts of this and the specified dependency.
181     *  The index, however, will be nonzero only if the specified
182     *  dependency has a real part equal to 0.0. In that case,
183     *  the index of the result will be the sum of indices of
184     *  this and the specified dependency.
185     *  NOTE: This implementation of oTimes is not commutative.
186     *  Fortunately, the theory does not require it to be.
187     *  @param dependency The dependency to multiply.
188     *  @return A dependency whose value is the sum of the value of
189     *   this one and the specified one.
190     *  @exception ClassCastException if dependency is not a RealDependency.
191     */
192    @Override
193    public Dependency oTimes(Dependency dependency) {
194        int index = 0;
195        // NOTE: Findbugs reports this as an Unchecked/unconfirmed cast
196        if (((SuperdenseDependency) dependency)._time == 0.0) {
197            index = _index + ((SuperdenseDependency) dependency)._index;
198        }
199        return new SuperdenseDependency(
200                _time + ((SuperdenseDependency) dependency)._time, index);
201    }
202
203    /** Return the dependency that when multiplied by any other
204     *  dependency using oTimes() yields the other dependency.
205     *  @return The multiplicative identity.
206     */
207    @Override
208    public Dependency oTimesIdentity() {
209        return OTIMES_IDENTITY;
210    }
211
212    /** Return the time value of this dependency.
213     *  @return The real part of the dependency.
214     */
215    public double timeValue() {
216        return _time;
217    }
218
219    /** Return a string representation in the form
220     *  "SuperdenseDependency(_time, _index)".
221     *  @return A string representation.
222     */
223    @Override
224    public String toString() {
225        return "SuperdenseDependency(" + _time + ", " + _index + ")";
226    }
227
228    /** Return an instance of SuperdenseDependency with the specified
229     *  time and index value. This is preferable to use over the constructor
230     *  because it uses the same instances for the most common
231     *  values.
232     *  @param time The time value.
233     *  @param index The index value.
234     *  @return an instance of RealDependency, if value
235     *  is (0.0, 0) then {@link #OTIMES_IDENTITY} is returned, if
236     *  value is (Double.POSITIVE_INFINITY, n) for any n,
237     *  then {@link #OPLUS_IDENTITY}
238     *  is returned.  Otherwise the SuperdenseDependency constructor
239     *  is called.
240     */
241    public static SuperdenseDependency valueOf(double time, int index) {
242        if (time == 0.0 && index == 0) {
243            return OTIMES_IDENTITY;
244        } else if (time == Double.POSITIVE_INFINITY) {
245            return OPLUS_IDENTITY;
246        }
247        return new SuperdenseDependency(time, index);
248    }
249
250    ///////////////////////////////////////////////////////////////////
251    ////                         public variables                  ////
252
253    // NOTE: FindBugs suggests that both these fields be final
254    // "MS: Field isn't final but should be (MS_SHOULD_BE_FINAL)
255    // A mutable static field could be changed by malicious code or by
256    // accident from another package. The field could be made final to avoid
257    // this vulnerability."
258
259    /** The additive identity. */
260    public static final SuperdenseDependency OPLUS_IDENTITY = new SuperdenseDependency(
261            Double.POSITIVE_INFINITY, 0);
262
263    /** The multiplicative identity. */
264    public static final SuperdenseDependency OTIMES_IDENTITY = new SuperdenseDependency(
265            0.0, 0);
266
267    ///////////////////////////////////////////////////////////////////
268    ////                         private variables                 ////
269
270    /** The superdense time index. */
271    private int _index;
272
273    /** The real (time) value. */
274    private double _time;
275
276}