View Javadoc
1   /*
2    * Copyright (C) 2011 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5    * in compliance with the License. You may obtain a copy of the License at
6    *
7    * http://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software distributed under the License
10   * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11   * or implied. See the License for the specific language governing permissions and limitations under
12   * the License.
13   */
14  
15  package com.google.common.primitives;
16  
17  import static com.google.common.base.Preconditions.checkArgument;
18  import static com.google.common.base.Preconditions.checkNotNull;
19  
20  import com.google.common.annotations.GwtCompatible;
21  import com.google.errorprone.annotations.CanIgnoreReturnValue;
22  import java.io.Serializable;
23  import java.math.BigInteger;
24  import javax.annotation.Nullable;
25  
26  /**
27   * A wrapper class for unsigned {@code long} values, supporting arithmetic operations.
28   *
29   * <p>In some cases, when speed is more important than code readability, it may be faster simply to
30   * treat primitive {@code long} values as unsigned, using the methods from {@link UnsignedLongs}.
31   *
32   * <p>See the Guava User Guide article on
33   * <a href="https://github.com/google/guava/wiki/PrimitivesExplained#unsigned-support">unsigned
34   * primitive utilities</a>.
35   *
36   * @author Louis Wasserman
37   * @author Colin Evans
38   * @since 11.0
39   */
40  @GwtCompatible(serializable = true)
41  public final class UnsignedLong extends Number implements Comparable<UnsignedLong>, Serializable {
42  
43    private static final long UNSIGNED_MASK = 0x7fffffffffffffffL;
44  
45    public static final UnsignedLong ZERO = new UnsignedLong(0);
46    public static final UnsignedLong ONE = new UnsignedLong(1);
47    public static final UnsignedLong MAX_VALUE = new UnsignedLong(-1L);
48  
49    private final long value;
50  
51    private UnsignedLong(long value) {
52      this.value = value;
53    }
54  
55    /**
56     * Returns an {@code UnsignedLong} corresponding to a given bit representation. The argument is
57     * interpreted as an unsigned 64-bit value. Specifically, the sign bit of {@code bits} is
58     * interpreted as a normal bit, and all other bits are treated as usual.
59     *
60     * <p>If the argument is nonnegative, the returned result will be equal to {@code bits},
61     * otherwise, the result will be equal to {@code 2^64 + bits}.
62     *
63     * <p>To represent decimal constants less than {@code 2^63}, consider {@link #valueOf(long)}
64     * instead.
65     *
66     * @since 14.0
67     */
68    public static UnsignedLong fromLongBits(long bits) {
69      // TODO(lowasser): consider caching small values, like Long.valueOf
70      return new UnsignedLong(bits);
71    }
72  
73    /**
74     * Returns an {@code UnsignedLong} representing the same value as the specified {@code long}.
75     *
76     * @throws IllegalArgumentException if {@code value} is negative
77     * @since 14.0
78     */
79    @CanIgnoreReturnValue
80    public static UnsignedLong valueOf(long value) {
81      checkArgument(value >= 0, "value (%s) is outside the range for an unsigned long value", value);
82      return fromLongBits(value);
83    }
84  
85    /**
86     * Returns a {@code UnsignedLong} representing the same value as the specified {@code BigInteger}.
87     * This is the inverse operation of {@link #bigIntegerValue()}.
88     *
89     * @throws IllegalArgumentException if {@code value} is negative or {@code value >= 2^64}
90     */
91    @CanIgnoreReturnValue
92    public static UnsignedLong valueOf(BigInteger value) {
93      checkNotNull(value);
94      checkArgument(
95          value.signum() >= 0 && value.bitLength() <= Long.SIZE,
96          "value (%s) is outside the range for an unsigned long value",
97          value);
98      return fromLongBits(value.longValue());
99    }
100 
101   /**
102    * Returns an {@code UnsignedLong} holding the value of the specified {@code String}, parsed as an
103    * unsigned {@code long} value.
104    *
105    * @throws NumberFormatException if the string does not contain a parsable unsigned {@code long}
106    *     value
107    */
108   @CanIgnoreReturnValue
109   public static UnsignedLong valueOf(String string) {
110     return valueOf(string, 10);
111   }
112 
113   /**
114    * Returns an {@code UnsignedLong} holding the value of the specified {@code String}, parsed as an
115    * unsigned {@code long} value in the specified radix.
116    *
117    * @throws NumberFormatException if the string does not contain a parsable unsigned {@code long}
118    *     value, or {@code radix} is not between {@link Character#MIN_RADIX} and
119    *     {@link Character#MAX_RADIX}
120    */
121   @CanIgnoreReturnValue
122   public static UnsignedLong valueOf(String string, int radix) {
123     return fromLongBits(UnsignedLongs.parseUnsignedLong(string, radix));
124   }
125 
126   /**
127    * Returns the result of adding this and {@code val}. If the result would have more than 64 bits,
128    * returns the low 64 bits of the result.
129    *
130    * @since 14.0
131    */
132   public UnsignedLong plus(UnsignedLong val) {
133     return fromLongBits(this.value + checkNotNull(val).value);
134   }
135 
136   /**
137    * Returns the result of subtracting this and {@code val}. If the result would have more than 64
138    * bits, returns the low 64 bits of the result.
139    *
140    * @since 14.0
141    */
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   public UnsignedLong times(UnsignedLong val) {
153     return fromLongBits(value * checkNotNull(val).value);
154   }
155 
156   /**
157    * Returns the result of dividing this by {@code val}.
158    *
159    * @since 14.0
160    */
161   public UnsignedLong dividedBy(UnsignedLong val) {
162     return fromLongBits(UnsignedLongs.divide(value, checkNotNull(val).value));
163   }
164 
165   /**
166    * Returns this modulo {@code val}.
167    *
168    * @since 14.0
169    */
170   public UnsignedLong mod(UnsignedLong val) {
171     return fromLongBits(UnsignedLongs.remainder(value, checkNotNull(val).value));
172   }
173 
174   /**
175    * Returns the value of this {@code UnsignedLong} as an {@code int}.
176    */
177   @Override
178   public int intValue() {
179     return (int) value;
180   }
181 
182   /**
183    * Returns the value of this {@code UnsignedLong} as a {@code long}. This is an inverse operation
184    * to {@link #fromLongBits}.
185    *
186    * <p>Note that if this {@code UnsignedLong} holds a value {@code >= 2^63}, the returned value
187    * will be equal to {@code this - 2^64}.
188    */
189   @Override
190   public long longValue() {
191     return value;
192   }
193 
194   /**
195    * Returns the value of this {@code UnsignedLong} as a {@code float}, analogous to a widening
196    * primitive conversion from {@code long} to {@code float}, and correctly rounded.
197    */
198   @Override
199   public float floatValue() {
200     @SuppressWarnings("cast")
201     float fValue = (float) (value & UNSIGNED_MASK);
202     if (value < 0) {
203       fValue += 0x1.0p63f;
204     }
205     return fValue;
206   }
207 
208   /**
209    * Returns the value of this {@code UnsignedLong} as a {@code double}, analogous to a widening
210    * primitive conversion from {@code long} to {@code double}, and correctly rounded.
211    */
212   @Override
213   public double doubleValue() {
214     @SuppressWarnings("cast")
215     double dValue = (double) (value & UNSIGNED_MASK);
216     if (value < 0) {
217       dValue += 0x1.0p63;
218     }
219     return dValue;
220   }
221 
222   /**
223    * Returns the value of this {@code UnsignedLong} as a {@link BigInteger}.
224    */
225   public BigInteger bigIntegerValue() {
226     BigInteger bigInt = BigInteger.valueOf(value & UNSIGNED_MASK);
227     if (value < 0) {
228       bigInt = bigInt.setBit(Long.SIZE - 1);
229     }
230     return bigInt;
231   }
232 
233   @Override
234   public int compareTo(UnsignedLong o) {
235     checkNotNull(o);
236     return UnsignedLongs.compare(value, o.value);
237   }
238 
239   @Override
240   public int hashCode() {
241     return Longs.hashCode(value);
242   }
243 
244   @Override
245   public boolean equals(@Nullable Object obj) {
246     if (obj instanceof UnsignedLong) {
247       UnsignedLong other = (UnsignedLong) obj;
248       return value == other.value;
249     }
250     return false;
251   }
252 
253   /**
254    * Returns a string representation of the {@code UnsignedLong} value, in base 10.
255    */
256   @Override
257   public String toString() {
258     return UnsignedLongs.toString(value);
259   }
260 
261   /**
262    * Returns a string representation of the {@code UnsignedLong} value, in base {@code radix}. If
263    * {@code radix < Character.MIN_RADIX} or {@code radix > Character.MAX_RADIX}, the radix
264    * {@code 10} is used.
265    */
266   public String toString(int radix) {
267     return UnsignedLongs.toString(value, radix);
268   }
269 }