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}