001/* 002 * Copyright (C) 2011 The Guava Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 005 * in compliance with the License. You may obtain a copy of the License at 006 * 007 * http://www.apache.org/licenses/LICENSE-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, software distributed under the 010 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 011 * express or implied. See the License for the specific language governing permissions and 012 * limitations under the License. 013 */ 014 015package com.google.common.primitives; 016 017import static com.google.common.base.Preconditions.checkArgument; 018import static com.google.common.base.Preconditions.checkNotNull; 019 020import com.google.common.annotations.Beta; 021import com.google.common.annotations.GwtCompatible; 022 023import java.io.Serializable; 024import java.math.BigInteger; 025 026import javax.annotation.CheckReturnValue; 027import javax.annotation.Nullable; 028 029/** 030 * A wrapper class for unsigned {@code long} values, supporting arithmetic operations. 031 * 032 * <p>In some cases, when speed is more important than code readability, it may be faster simply to 033 * treat primitive {@code long} values as unsigned, using the methods from {@link UnsignedLongs}. 034 * 035 * <p>See the Guava User Guide article on <a href= 036 * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained#Unsigned_support"> 037 * unsigned primitive utilities</a>. 038 * 039 * @author Louis Wasserman 040 * @author Colin Evans 041 * @since 11.0 042 */ 043@GwtCompatible(serializable = true) 044public final class UnsignedLong extends Number implements Comparable<UnsignedLong>, Serializable { 045 046 private static final long UNSIGNED_MASK = 0x7fffffffffffffffL; 047 048 public static final UnsignedLong ZERO = new UnsignedLong(0); 049 public static final UnsignedLong ONE = new UnsignedLong(1); 050 public static final UnsignedLong MAX_VALUE = new UnsignedLong(-1L); 051 052 private final long value; 053 054 private UnsignedLong(long value) { 055 this.value = value; 056 } 057 058 /** 059 * Returns an {@code UnsignedLong} that, when treated as signed, is equal to {@code value}. The 060 * inverse operation is {@link #longValue()}. 061 * 062 * <p>Put another way, if {@code value} is negative, the returned result will be equal to 063 * {@code 2^64 + value}; otherwise, the returned result will be equal to {@code value}. 064 * 065 * @deprecated Use {@link #fromLongBits(long)}. This method is scheduled to be removed in Guava 066 * release 15.0. 067 */ 068 @Deprecated 069 @Beta 070 public static UnsignedLong asUnsigned(long value) { 071 return fromLongBits(value); 072 } 073 074 /** 075 * Returns an {@code UnsignedLong} corresponding to a given bit representation. 076 * The argument is interpreted as an unsigned 64-bit value. Specifically, the sign bit 077 * of {@code bits} is interpreted as a normal bit, and all other bits are treated as usual. 078 * 079 * <p>If the argument is nonnegative, the returned result will be equal to {@code bits}, 080 * otherwise, the result will be equal to {@code 2^64 + bits}. 081 * 082 * <p>To represent decimal constants less than {@code 2^63}, consider {@link #valueOf(long)} 083 * instead. 084 * 085 * @since 14.0 086 */ 087 public static UnsignedLong fromLongBits(long bits) { 088 // TODO(user): consider caching small values, like Long.valueOf 089 return new UnsignedLong(bits); 090 } 091 092 /** 093 * Returns an {@code UnsignedLong} representing the same value as the specified {@code long}. 094 * 095 * @throws IllegalArgumentException if {@code value} is negative 096 * @since 14.0 097 */ 098 public static UnsignedLong valueOf(long value) { 099 checkArgument(value >= 0, 100 "value (%s) is outside the range for an unsigned long value", value); 101 return fromLongBits(value); 102 } 103 104 /** 105 * Returns a {@code UnsignedLong} representing the same value as the specified 106 * {@code BigInteger}. This is the inverse operation of {@link #bigIntegerValue()}. 107 * 108 * @throws IllegalArgumentException if {@code value} is negative or {@code value >= 2^64} 109 */ 110 public static UnsignedLong valueOf(BigInteger value) { 111 checkNotNull(value); 112 checkArgument(value.signum() >= 0 && value.bitLength() <= Long.SIZE, 113 "value (%s) is outside the range for an unsigned long value", value); 114 return fromLongBits(value.longValue()); 115 } 116 117 /** 118 * Returns an {@code UnsignedLong} holding the value of the specified {@code String}, parsed as 119 * an unsigned {@code long} value. 120 * 121 * @throws NumberFormatException if the string does not contain a parsable unsigned {@code long} 122 * value 123 */ 124 public static UnsignedLong valueOf(String string) { 125 return valueOf(string, 10); 126 } 127 128 /** 129 * Returns an {@code UnsignedLong} holding the value of the specified {@code String}, parsed as 130 * an unsigned {@code long} value in the specified radix. 131 * 132 * @throws NumberFormatException if the string does not contain a parsable unsigned {@code long} 133 * value, or {@code radix} is not between {@link Character#MIN_RADIX} and 134 * {@link Character#MAX_RADIX} 135 */ 136 public static UnsignedLong valueOf(String string, int radix) { 137 return fromLongBits(UnsignedLongs.parseUnsignedLong(string, radix)); 138 } 139 140 /** 141 * Returns the result of adding this and {@code val}. If the result would have more than 64 bits, 142 * returns the low 64 bits of the result. 143 * 144 * @deprecated Use {@link #plus(UnsignedLong)}. This method is scheduled to be removed in Guava 145 * release 15.0. 146 */ 147 @Deprecated 148 @Beta 149 public UnsignedLong add(UnsignedLong val) { 150 return plus(val); 151 } 152 153 /** 154 * Returns the result of adding this and {@code val}. If the result would have more than 64 bits, 155 * returns the low 64 bits of the result. 156 * 157 * @since 14.0 158 */ 159 public UnsignedLong plus(UnsignedLong val) { 160 return fromLongBits(this.value + checkNotNull(val).value); 161 } 162 163 /** 164 * Returns the result of subtracting this and {@code val}. If the result would be negative, 165 * returns the low 64 bits of the result. 166 * 167 * @deprecated Use {@link #minus(UnsignedLong)}. This method is scheduled to be removed in Guava 168 * release 15.0. 169 */ 170 @Deprecated 171 @Beta 172 public UnsignedLong subtract(UnsignedLong val) { 173 return minus(val); 174 } 175 176 /** 177 * Returns the result of subtracting this and {@code val}. If the result would have more than 64 178 * bits, returns the low 64 bits of the result. 179 * 180 * @since 14.0 181 */ 182 public UnsignedLong minus(UnsignedLong val) { 183 return fromLongBits(this.value - checkNotNull(val).value); 184 } 185 186 /** 187 * Returns the result of multiplying this and {@code val}. If the result would have more than 64 188 * bits, returns the low 64 bits of the result. 189 * 190 * @deprecated Use {@link #times(UnsignedLong)}. This method is scheduled to be removed in Guava 191 * release 15.0. 192 */ 193 @Deprecated 194 @Beta 195 public UnsignedLong multiply(UnsignedLong val) { 196 return times(val); 197 } 198 199 /** 200 * Returns the result of multiplying this and {@code val}. If the result would have more than 64 201 * bits, returns the low 64 bits of the result. 202 * 203 * @since 14.0 204 */ 205 @CheckReturnValue 206 public UnsignedLong times(UnsignedLong val) { 207 return fromLongBits(value * checkNotNull(val).value); 208 } 209 210 /** 211 * Returns the result of dividing this by {@code val}. 212 * 213 * @deprecated Use {@link #dividedBy(UnsignedLong)}. This method is scheduled to be removed in 214 * Guava release 15.0. 215 */ 216 @Deprecated 217 @Beta 218 public UnsignedLong divide(UnsignedLong val) { 219 return dividedBy(val); 220 } 221 222 /** 223 * Returns the result of dividing this by {@code val}. 224 * 225 * @since 14.0 226 */ 227 @CheckReturnValue 228 public UnsignedLong dividedBy(UnsignedLong val) { 229 return fromLongBits(UnsignedLongs.divide(value, checkNotNull(val).value)); 230 } 231 232 /** 233 * Returns the remainder of dividing this by {@code val}. 234 * 235 * @deprecated Use {@link #mod(UnsignedLong)}. This method is scheduled to be removed in Guava 236 * release 15.0. 237 */ 238 @Deprecated 239 @Beta 240 public UnsignedLong remainder(UnsignedLong val) { 241 return mod(val); 242 } 243 244 /** 245 * Returns this modulo {@code val}. 246 * 247 * @since 14.0 248 */ 249 @CheckReturnValue 250 public UnsignedLong mod(UnsignedLong val) { 251 return fromLongBits(UnsignedLongs.remainder(value, checkNotNull(val).value)); 252 } 253 254 /** 255 * Returns the value of this {@code UnsignedLong} as an {@code int}. 256 */ 257 @Override 258 public int intValue() { 259 return (int) value; 260 } 261 262 /** 263 * Returns the value of this {@code UnsignedLong} as a {@code long}. This is an inverse operation 264 * to {@link #asUnsigned}. 265 * 266 * <p>Note that if this {@code UnsignedLong} holds a value {@code >= 2^63}, the returned value 267 * will be equal to {@code this - 2^64}. 268 */ 269 @Override 270 public long longValue() { 271 return value; 272 } 273 274 /** 275 * Returns the value of this {@code UnsignedLong} as a {@code float}, analogous to a widening 276 * primitive conversion from {@code long} to {@code float}, and correctly rounded. 277 */ 278 @Override 279 public float floatValue() { 280 @SuppressWarnings("cast") 281 float fValue = (float) (value & UNSIGNED_MASK); 282 if (value < 0) { 283 fValue += 0x1.0p63f; 284 } 285 return fValue; 286 } 287 288 /** 289 * Returns the value of this {@code UnsignedLong} as a {@code double}, analogous to a widening 290 * primitive conversion from {@code long} to {@code double}, and correctly rounded. 291 */ 292 @Override 293 public double doubleValue() { 294 @SuppressWarnings("cast") 295 double dValue = (double) (value & UNSIGNED_MASK); 296 if (value < 0) { 297 dValue += 0x1.0p63; 298 } 299 return dValue; 300 } 301 302 /** 303 * Returns the value of this {@code UnsignedLong} as a {@link BigInteger}. 304 */ 305 public BigInteger bigIntegerValue() { 306 BigInteger bigInt = BigInteger.valueOf(value & UNSIGNED_MASK); 307 if (value < 0) { 308 bigInt = bigInt.setBit(Long.SIZE - 1); 309 } 310 return bigInt; 311 } 312 313 @Override 314 public int compareTo(UnsignedLong o) { 315 checkNotNull(o); 316 return UnsignedLongs.compare(value, o.value); 317 } 318 319 @Override 320 public int hashCode() { 321 return Longs.hashCode(value); 322 } 323 324 @Override 325 public boolean equals(@Nullable Object obj) { 326 if (obj instanceof UnsignedLong) { 327 UnsignedLong other = (UnsignedLong) obj; 328 return value == other.value; 329 } 330 return false; 331 } 332 333 /** 334 * Returns a string representation of the {@code UnsignedLong} value, in base 10. 335 */ 336 @Override 337 public String toString() { 338 return UnsignedLongs.toString(value); 339 } 340 341 /** 342 * Returns a string representation of the {@code UnsignedLong} value, in base {@code radix}. If 343 * {@code radix < Character.MIN_RADIX} or {@code radix > Character.MAX_RADIX}, the radix 344 * {@code 10} is used. 345 */ 346 public String toString(int radix) { 347 return UnsignedLongs.toString(value, radix); 348 } 349}