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.GwtCompatible;
021
022import java.io.Serializable;
023import java.math.BigInteger;
024
025import javax.annotation.CheckReturnValue;
026import javax.annotation.Nullable;
027
028/**
029 * A wrapper class for unsigned {@code long} values, supporting arithmetic operations.
030 *
031 * <p>In some cases, when speed is more important than code readability, it may be faster simply to
032 * treat primitive {@code long} values as unsigned, using the methods from {@link UnsignedLongs}.
033 *
034 * <p>See the Guava User Guide article on <a href=
035 * "https://github.com/google/guava/wiki/PrimitivesExplained#unsigned-support">
036 * unsigned primitive utilities</a>.
037 *
038 * @author Louis Wasserman
039 * @author Colin Evans
040 * @since 11.0
041 */
042@GwtCompatible(serializable = true)
043public final class UnsignedLong extends Number implements Comparable<UnsignedLong>, Serializable {
044
045  private static final long UNSIGNED_MASK = 0x7fffffffffffffffL;
046
047  public static final UnsignedLong ZERO = new UnsignedLong(0);
048  public static final UnsignedLong ONE = new UnsignedLong(1);
049  public static final UnsignedLong MAX_VALUE = new UnsignedLong(-1L);
050
051  private final long value;
052
053  private UnsignedLong(long value) {
054    this.value = value;
055  }
056
057  /**
058   * Returns an {@code UnsignedLong} corresponding to a given bit representation.
059   * The argument is interpreted as an unsigned 64-bit value. Specifically, the sign bit
060   * of {@code bits} is interpreted as a normal bit, and all other bits are treated as usual.
061   *
062   * <p>If the argument is nonnegative, the returned result will be equal to {@code bits},
063   * otherwise, the result will be equal to {@code 2^64 + bits}.
064   *
065   * <p>To represent decimal constants less than {@code 2^63}, consider {@link #valueOf(long)}
066   * instead.
067   *
068   * @since 14.0
069   */
070  public static UnsignedLong fromLongBits(long bits) {
071    // TODO(lowasser): consider caching small values, like Long.valueOf
072    return new UnsignedLong(bits);
073  }
074
075  /**
076   * Returns an {@code UnsignedLong} representing the same value as the specified {@code long}.
077   *
078   * @throws IllegalArgumentException if {@code value} is negative
079   * @since 14.0
080   */
081  public static UnsignedLong valueOf(long value) {
082    checkArgument(value >= 0, "value (%s) is outside the range for an unsigned long value", value);
083    return fromLongBits(value);
084  }
085
086  /**
087   * Returns a {@code UnsignedLong} representing the same value as the specified
088   * {@code BigInteger}. This is the inverse operation of {@link #bigIntegerValue()}.
089   *
090   * @throws IllegalArgumentException if {@code value} is negative or {@code value >= 2^64}
091   */
092  public static UnsignedLong valueOf(BigInteger value) {
093    checkNotNull(value);
094    checkArgument(
095        value.signum() >= 0 && value.bitLength() <= Long.SIZE,
096        "value (%s) is outside the range for an unsigned long value",
097        value);
098    return fromLongBits(value.longValue());
099  }
100
101  /**
102   * Returns an {@code UnsignedLong} holding the value of the specified {@code String}, parsed as
103   * an unsigned {@code long} value.
104   *
105   * @throws NumberFormatException if the string does not contain a parsable unsigned {@code long}
106   *     value
107   */
108  public static UnsignedLong valueOf(String string) {
109    return valueOf(string, 10);
110  }
111
112  /**
113   * Returns an {@code UnsignedLong} holding the value of the specified {@code String}, parsed as
114   * an unsigned {@code long} value in the specified radix.
115   *
116   * @throws NumberFormatException if the string does not contain a parsable unsigned {@code long}
117   *     value, or {@code radix} is not between {@link Character#MIN_RADIX} and
118   *     {@link Character#MAX_RADIX}
119   */
120  public static UnsignedLong valueOf(String string, int radix) {
121    return fromLongBits(UnsignedLongs.parseUnsignedLong(string, radix));
122  }
123
124  /**
125   * Returns the result of adding this and {@code val}. If the result would have more than 64 bits,
126   * returns the low 64 bits of the result.
127   *
128   * @since 14.0
129   */
130  @CheckReturnValue
131  public UnsignedLong plus(UnsignedLong val) {
132    return fromLongBits(this.value + checkNotNull(val).value);
133  }
134
135  /**
136   * Returns the result of subtracting this and {@code val}. If the result would have more than 64
137   * bits, returns the low 64 bits of the result.
138   *
139   * @since 14.0
140   */
141  @CheckReturnValue
142  public UnsignedLong minus(UnsignedLong val) {
143    return fromLongBits(this.value - checkNotNull(val).value);
144  }
145
146  /**
147   * Returns the result of multiplying this and {@code val}. If the result would have more than 64
148   * bits, returns the low 64 bits of the result.
149   *
150   * @since 14.0
151   */
152  @CheckReturnValue
153  public UnsignedLong times(UnsignedLong val) {
154    return fromLongBits(value * checkNotNull(val).value);
155  }
156
157  /**
158   * Returns the result of dividing this by {@code val}.
159   *
160   * @since 14.0
161   */
162  @CheckReturnValue
163  public UnsignedLong dividedBy(UnsignedLong val) {
164    return fromLongBits(UnsignedLongs.divide(value, checkNotNull(val).value));
165  }
166
167  /**
168   * Returns this modulo {@code val}.
169   *
170   * @since 14.0
171   */
172  @CheckReturnValue
173  public UnsignedLong mod(UnsignedLong val) {
174    return fromLongBits(UnsignedLongs.remainder(value, checkNotNull(val).value));
175  }
176
177  /**
178   * Returns the value of this {@code UnsignedLong} as an {@code int}.
179   */
180  @Override
181  public int intValue() {
182    return (int) value;
183  }
184
185  /**
186   * Returns the value of this {@code UnsignedLong} as a {@code long}. This is an inverse operation
187   * to {@link #fromLongBits}.
188   *
189   * <p>Note that if this {@code UnsignedLong} holds a value {@code >= 2^63}, the returned value
190   * will be equal to {@code this - 2^64}.
191   */
192  @Override
193  public long longValue() {
194    return value;
195  }
196
197  /**
198   * Returns the value of this {@code UnsignedLong} as a {@code float}, analogous to a widening
199   * primitive conversion from {@code long} to {@code float}, and correctly rounded.
200   */
201  @Override
202  public float floatValue() {
203    @SuppressWarnings("cast")
204    float fValue = (float) (value & UNSIGNED_MASK);
205    if (value < 0) {
206      fValue += 0x1.0p63f;
207    }
208    return fValue;
209  }
210
211  /**
212   * Returns the value of this {@code UnsignedLong} as a {@code double}, analogous to a widening
213   * primitive conversion from {@code long} to {@code double}, and correctly rounded.
214   */
215  @Override
216  public double doubleValue() {
217    @SuppressWarnings("cast")
218    double dValue = (double) (value & UNSIGNED_MASK);
219    if (value < 0) {
220      dValue += 0x1.0p63;
221    }
222    return dValue;
223  }
224
225  /**
226   * Returns the value of this {@code UnsignedLong} as a {@link BigInteger}.
227   */
228  public BigInteger bigIntegerValue() {
229    BigInteger bigInt = BigInteger.valueOf(value & UNSIGNED_MASK);
230    if (value < 0) {
231      bigInt = bigInt.setBit(Long.SIZE - 1);
232    }
233    return bigInt;
234  }
235
236  @Override
237  public int compareTo(UnsignedLong o) {
238    checkNotNull(o);
239    return UnsignedLongs.compare(value, o.value);
240  }
241
242  @Override
243  public int hashCode() {
244    return Longs.hashCode(value);
245  }
246
247  @Override
248  public boolean equals(@Nullable Object obj) {
249    if (obj instanceof UnsignedLong) {
250      UnsignedLong other = (UnsignedLong) obj;
251      return value == other.value;
252    }
253    return false;
254  }
255
256  /**
257   * Returns a string representation of the {@code UnsignedLong} value, in base 10.
258   */
259  @Override
260  public String toString() {
261    return UnsignedLongs.toString(value);
262  }
263
264  /**
265   * Returns a string representation of the {@code UnsignedLong} value, in base {@code radix}. If
266   * {@code radix < Character.MIN_RADIX} or {@code radix > Character.MAX_RADIX}, the radix
267   * {@code 10} is used.
268   */
269  public String toString(int radix) {
270    return UnsignedLongs.toString(value, radix);
271  }
272}