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