001/* A token that contains an integer number.
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
028 */
029package ptolemy.data;
030
031import ptolemy.data.type.BaseType;
032import ptolemy.data.type.Type;
033import ptolemy.data.type.TypeLattice;
034import ptolemy.data.unit.UnitUtilities;
035import ptolemy.graph.CPO;
036import ptolemy.kernel.util.IllegalActionException;
037import ptolemy.math.Complex;
038import ptolemy.math.FixPoint;
039
040///////////////////////////////////////////////////////////////////
041//// IntToken
042
043/**
044 A token that contains a signed 32-bit integer number.  Generally, this
045 class handles overflow the same way that overflow Java native types
046 are handled. In other words, overflow just past java.lang.Integer.MAX_VALUE
047 results in negative values close to java.lang.Integer.MIN_VALUE.
048
049 @author Neil Smyth, Yuhong Xiong, Steve Neuendorffer, contributor: Christopher Brooks
050 @version $Id$
051 @since Ptolemy II 0.2
052 @Pt.ProposedRating Yellow (cxh) nil token, ONE, ZERO
053 @Pt.AcceptedRating Red (cxh)
054 */
055public class IntToken extends ScalarToken {
056    /** Construct a token with integer 0.
057     */
058    public IntToken() {
059        _value = 0;
060    }
061
062    /** Construct a token with the specified value.
063     *  @param value The specified value.
064     */
065    public IntToken(final int value) {
066        _value = value;
067    }
068
069    /** Construct an IntToken from the specified string.
070     *  @param init The specified string.
071     *  @exception IllegalActionException If the token could not
072     *  be created with the given String.
073     */
074    public IntToken(String init) throws IllegalActionException {
075        if (init == null || init.equals("nil")) {
076            throw new IllegalActionException(
077                    notSupportedNullNilStringMessage("IntToken", init));
078        }
079        try {
080            _value = Integer.parseInt(init);
081        } catch (NumberFormatException e) {
082            throw new IllegalActionException(null, e,
083                    "Failed to parse \"" + init + "\" as a number.");
084        }
085    }
086
087    ///////////////////////////////////////////////////////////////////
088    ////                         public methods                    ////
089
090    /** Return the value of this token as a Complex. The real part
091     *  of the Complex is the value of this token, the imaginary part
092     *  is set to 0.
093     *  @return A Complex.
094     */
095    @Override
096    public Complex complexValue() {
097        return new Complex(_value);
098    }
099
100    /** Convert the specified token into an instance of IntToken.
101     *  This method does lossless conversion.  The units of the
102     *  returned token will be the same as the units of the given
103     *  token.  If the argument is already an instance of IntToken, it
104     *  is returned without any change.  If the argument is a
105     *  nil token, then {@link #NIL} is returned.
106     *  Otherwise, if the argument is below IntToken in the type
107     *  hierarchy, it is converted to an instance of IntToken or one
108     *  of the subclasses of IntToken and returned. If none of the
109     *  above condition is met, an exception is thrown.
110     *
111     *  @param token The token to be converted to a IntToken.
112     *  @return A IntToken.
113     *  @exception IllegalActionException If the conversion
114     *   cannot be carried out.
115     */
116    public static IntToken convert(Token token) throws IllegalActionException {
117        if (token instanceof IntToken) {
118            return (IntToken) token;
119        }
120        if (token.isNil()) {
121            return IntToken.NIL;
122        }
123
124        int compare = TypeLattice.compare(BaseType.INT, token);
125
126        if (compare == CPO.LOWER || compare == CPO.INCOMPARABLE) {
127            throw new IllegalActionException(
128                    notSupportedIncomparableConversionMessage(token, "int"));
129        }
130
131        compare = TypeLattice.compare(BaseType.SHORT, token);
132
133        if (compare == CPO.SAME || compare == CPO.HIGHER) {
134            ShortToken shortToken = ShortToken.convert(token);
135            IntToken result = new IntToken(shortToken.intValue());
136            if (shortToken._unitCategoryExponents != null && !UnitUtilities
137                    .isUnitless(shortToken._unitCategoryExponents)) {
138                result._unitCategoryExponents = shortToken
139                        ._copyOfCategoryExponents();
140            }
141            return result;
142        }
143
144        // The argument is below ShortToken in the type hierarchy,
145        // but I don't recognize it.
146        throw new IllegalActionException(
147                notSupportedConversionMessage(token, "int"));
148    }
149
150    /** Return the value in the token as a double.
151     *  @return The value contained in this token as a double.
152     */
153    @Override
154    public double doubleValue() {
155        return _value;
156    }
157
158    /** Return true if the argument's class is IntToken and it has the
159     *  same values as this token.
160     *  @param object An instance of Object.
161     *  @return True if the argument is an IntToken with the same
162     *  value. If either this object or the argument is a nil Token, return
163     *  false.
164     */
165    @Override
166    public boolean equals(Object object) {
167        if (object == null) {
168            return false;
169        }
170        // This test rules out subclasses.
171        if (object.getClass() != getClass()) {
172            return false;
173        }
174
175        if (this.isNil() || ((IntToken) object).isNil()) {
176            return false;
177        }
178
179        if (((IntToken) object).intValue() == _value) {
180            return true;
181        }
182
183        return false;
184    }
185
186    /** Return the value in the token as a fixpoint.
187     *  @return The value contained in this token as a fixpoint.
188     */
189    @Override
190    public FixPoint fixValue() {
191        return new FixPoint(_value);
192    }
193
194    /** Return the type of this token.
195     *  @return BaseType.INT
196     */
197    @Override
198    public Type getType() {
199        return BaseType.INT;
200    }
201
202    /** Return a hash code value for this token. This method just returns the
203     *  contained integer.
204     *  @return A hash code value for this token.
205     */
206    @Override
207    public int hashCode() {
208        return _value;
209    }
210
211    /** Return the value in the token as an int.
212     *  @return The int value contained in this token.
213     */
214    @Override
215    public int intValue() {
216        return _value;
217    }
218
219    /** Return true if the token is nil, (aka null or missing).
220     *  Nil or missing tokens occur when a data source is sparsely populated.
221     *  @return True if the token is the {@link #NIL} token.
222     */
223    @Override
224    public boolean isNil() {
225        // We use a method here so that we can easily change how
226        // we determine if a token is nil without modify lots of classes.
227        // Can't use equals() here, or we'll go into an infinite loop.
228        return this == IntToken.NIL;
229    }
230
231    /** Returns a token representing the result of shifting the bits
232     *  of this token towards the most significant bit, filling the
233     *  least significant bits with zeros.
234     *  @param bits The number of bits to shift.
235     *  @return The left shift.
236     *  If this token is nil, then {@link #NIL} is returned.
237     */
238    @Override
239    public ScalarToken leftShift(int bits) {
240        if (isNil()) {
241            return IntToken.NIL;
242        }
243        return new IntToken(_value << bits);
244    }
245
246    /** Returns a token representing the result of shifting the bits
247     *  of this token towards the least significant bit, filling the
248     *  most significant bits with zeros.  This treats the value as an
249     *  unsigned number, which may have the effect of destroying the
250     *  sign of the value.
251     *  @param bits The number of bits to shift.
252     *  @return The logical right shift.
253     *  If this token is nil, then {@link #NIL} is returned.
254     */
255    @Override
256    public ScalarToken logicalRightShift(int bits) {
257        if (isNil()) {
258            return IntToken.NIL;
259        }
260        return new IntToken(_value >>> bits);
261    }
262
263    /** Return the value in the token as a long.
264     *  @return The int value contained in this token as a long.
265     */
266    @Override
267    public long longValue() {
268        return _value;
269    }
270
271    /** Returns an IntToken with value 1.
272     *  @return An IntToken with value 1.
273     */
274    @Override
275    public Token one() {
276        return ONE;
277    }
278
279    /** Returns a token representing the result of shifting the bits
280     *  of this token towards the least significant bit, filling the
281     *  most significant bits with the sign of the value.  This preserves
282     *  the sign of the result.
283     *  @param bits The number of bits to shift.
284     *  @return The right shift.
285     *  If this token is nil, then {@link #NIL} is returned.
286     */
287    @Override
288    public ScalarToken rightShift(int bits) {
289        if (isNil()) {
290            return IntToken.NIL;
291        }
292        return new IntToken(_value >> bits);
293    }
294
295    /** Return the value of this token as a string that can be parsed
296     *  by the expression language to recover a token with the same value.
297     *  If this token has a unit, the return string also includes a unit
298     *  string produced by the unitsString() method in the super class.
299     *  @return A String representing the int value and the units (if
300     *   any) of this token.
301     *  @see ptolemy.data.ScalarToken#unitsString
302     */
303    @Override
304    public String toString() {
305        String unitString = "";
306
307        if (!_isUnitless()) {
308            unitString = " * " + unitsString();
309        }
310
311        if (isNil()) {
312            // FIXME: what about units?
313            return super.toString();
314        }
315        return Integer.toString(_value) + unitString;
316    }
317
318    /** Returns an IntToken with value 0.
319     *  @return An IntToken with value 0.
320     */
321    @Override
322    public Token zero() {
323        return ZERO;
324    }
325
326    ///////////////////////////////////////////////////////////////////
327    ////                         public variables                  ////
328
329    /** A token that represents a missing value.
330     *  Null or missing tokens are common in analytical systems
331     *  like R and SAS where they are used to handle sparsely populated data
332     *  sources.  In database parlance, missing tokens are sometimes called
333     *  null tokens.  Since null is a Java keyword, we use the term "nil".
334     *  The toString() method on a nil token returns the string "nil".
335     */
336    public static final IntToken NIL = new IntToken(Integer.MAX_VALUE);
337
338    /** A IntToken with the value 1.0. */
339    public static final IntToken ONE = new IntToken(1);
340
341    /** A IntToken with the value 0.0. */
342    public static final IntToken ZERO = new IntToken(0);
343
344    ///////////////////////////////////////////////////////////////////
345    ////                         protected methods                 ////
346
347    /** Return a ScalarToken containing the absolute value of the
348     *  value of this token. If this token contains a non-negative
349     *  number, it is returned directly; otherwise, a new token is
350     *  returned.  Note that it is explicitly allowable to return this
351     *  token, since the units are the same.
352     *  @return An IntToken.
353     */
354    @Override
355    protected ScalarToken _absolute() {
356        IntToken result;
357
358        if (_value >= 0) {
359            result = this;
360        } else {
361            result = new IntToken(-_value);
362        }
363
364        return result;
365    }
366
367    /** Return a new token whose value is the value of the
368     *  argument Token added to the value of this Token.  It is assumed
369     *  that the type of the argument is an IntToken.
370     *  @param rightArgument The token to add to this token.
371     *  @return A new IntToken containing the result.
372     */
373    @Override
374    protected ScalarToken _add(ScalarToken rightArgument) {
375        int sum = _value + ((IntToken) rightArgument).intValue();
376        return new IntToken(sum);
377    }
378
379    /** Returns a token representing the bitwise AND of this token and
380     *  the given token.  It is assumed that the type of the argument
381     *  is an IntToken.
382     *  @param rightArgument The IntToken to bitwise AND with this one.
383     *  @return The bitwise AND.
384     */
385    @Override
386    protected ScalarToken _bitwiseAnd(ScalarToken rightArgument) {
387        int sum = _value & ((IntToken) rightArgument).intValue();
388        return new IntToken(sum);
389    }
390
391    /** Returns a token representing the bitwise NOT of this token.
392     *  @return The bitwise NOT of this token.
393     */
394    @Override
395    protected ScalarToken _bitwiseNot() {
396        IntToken result = new IntToken(~_value);
397        return result;
398    }
399
400    /** Returns a token representing the bitwise OR of this token and
401     *  the given token.  It is assumed that
402     *  the type of the argument is an IntToken.
403     *  @param rightArgument The IntToken to bitwise OR with this one.
404     *  @return The bitwise OR.
405     */
406    @Override
407    protected ScalarToken _bitwiseOr(ScalarToken rightArgument) {
408        int sum = _value | ((IntToken) rightArgument).intValue();
409        return new IntToken(sum);
410    }
411
412    /** Returns a token representing the bitwise XOR of this token and
413     *  the given token.  It is assumed that
414     *  the type of the argument is an IntToken.
415     *  @param rightArgument The IntToken to bitwise XOR with this one.
416     *  @return The bitwise XOR.
417     */
418    @Override
419    protected ScalarToken _bitwiseXor(ScalarToken rightArgument) {
420        int sum = _value ^ ((IntToken) rightArgument).intValue();
421        return new IntToken(sum);
422    }
423
424    /** Return a new token whose value is the value of this token
425     *  divided by the value of the argument token. It is assumed that
426     *  the type of the argument is an IntToken.
427     *  @param rightArgument The token to divide this token by.
428     *  @return A new IntToken containing the result.
429     */
430    @Override
431    protected ScalarToken _divide(ScalarToken rightArgument) {
432        int quotient = _value / ((IntToken) rightArgument).intValue();
433        return new IntToken(quotient);
434    }
435
436    /** Test whether the value of this token is close to the first
437     *  argument, where "close" means that the distance between their
438     *  values is less than or equal to the second argument. It is
439     *  assumed that the type of the first argument is IntToken.
440     *  @param rightArgument The token to compare to this token.
441     *  @param epsilon The distance.
442     *  @return A token containing true if the value of the first
443     *   argument is close to the value of this token.
444     */
445    @Override
446    protected BooleanToken _isCloseTo(ScalarToken rightArgument,
447            double epsilon) {
448        // NOTE: This code is duplicated in
449        // ptolemy.math.IntegerMatrixMath.within(); if this
450        // implementation changes, also change the corresponding
451        // implementation there.
452        double right = ((IntToken) rightArgument).doubleValue();
453        double left = doubleValue();
454
455        if (right > left + epsilon || right < left - epsilon) {
456            return BooleanToken.FALSE;
457        } else {
458            return BooleanToken.TRUE;
459        }
460    }
461
462    /** Test for ordering of the values of this Token and the argument
463     *  Token.  It is assumed that the type of the argument is IntToken.
464     *  @param rightArgument The token to add to this token.
465     *  @exception IllegalActionException If this method is not
466     *  supported by the derived class.
467     *  @return A new Token containing the result.
468     */
469    @Override
470    protected BooleanToken _isLessThan(ScalarToken rightArgument)
471            throws IllegalActionException {
472        IntToken convertedArgument = (IntToken) rightArgument;
473        return BooleanToken.getInstance(_value < convertedArgument.intValue());
474    }
475
476    /** Return a new token whose value is the value of this token
477     *  modulo the value of the argument token.  It is assumed that
478     *  the type of the argument is an IntToken.
479     *  @param rightArgument The token to modulo this token by.
480     *  @return A new IntToken containing the result.
481     */
482    @Override
483    protected ScalarToken _modulo(ScalarToken rightArgument) {
484        int remainder = _value % ((IntToken) rightArgument).intValue();
485        return new IntToken(remainder);
486    }
487
488    /** Return a new token whose value is the value of this token
489     *  multiplied by the value of the argument token.  It is assumed that
490     *  the type of the argument is an IntToken.
491     *  @param rightArgument The token to multiply this token by.
492     *  @return A new IntToken containing the result.
493     */
494    @Override
495    protected ScalarToken _multiply(ScalarToken rightArgument) {
496        int product = _value * ((IntToken) rightArgument).intValue();
497        return new IntToken(product);
498    }
499
500    /** Return a new token whose value is the value of the argument token
501     *  subtracted from the value of this token.  It is assumed that
502     *  the type of the argument is an IntToken.
503     *  @param rightArgument The token to subtract from this token.
504     *  @return A new IntToken containing the result.
505     */
506    @Override
507    protected ScalarToken _subtract(ScalarToken rightArgument) {
508        int difference = _value - ((IntToken) rightArgument).intValue();
509        return new IntToken(difference);
510    }
511
512    ///////////////////////////////////////////////////////////////////
513    ////                         private variables                 ////
514    private final int _value;
515}