• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
10  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11  * express or implied. See the License for the specific language governing permissions and
12  * limitations under 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 
22 import java.io.Serializable;
23 import java.math.BigInteger;
24 
25 import javax.annotation.CheckReturnValue;
26 import javax.annotation.Nullable;
27 
28 /**
29  * A wrapper class for unsigned {@code long} values, supporting arithmetic operations.
30  *
31  * <p>In some cases, when speed is more important than code readability, it may be faster simply to
32  * treat primitive {@code long} values as unsigned, using the methods from {@link UnsignedLongs}.
33  *
34  * <p>See the Guava User Guide article on <a href=
35  * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained#Unsigned_support">
36  * unsigned primitive utilities</a>.
37  *
38  * @author Louis Wasserman
39  * @author Colin Evans
40  * @since 11.0
41  */
42 @GwtCompatible(serializable = true)
43 public final class UnsignedLong extends Number implements Comparable<UnsignedLong>, Serializable {
44 
45   private static final long UNSIGNED_MASK = 0x7fffffffffffffffL;
46 
47   public static final UnsignedLong ZERO = new UnsignedLong(0);
48   public static final UnsignedLong ONE = new UnsignedLong(1);
49   public static final UnsignedLong MAX_VALUE = new UnsignedLong(-1L);
50 
51   private final long value;
52 
UnsignedLong(long value)53   private UnsignedLong(long value) {
54     this.value = value;
55   }
56 
57   /**
58    * Returns an {@code UnsignedLong} corresponding to a given bit representation.
59    * The argument is interpreted as an unsigned 64-bit value. Specifically, the sign bit
60    * of {@code bits} is interpreted as a normal bit, and all other bits are treated as usual.
61    *
62    * <p>If the argument is nonnegative, the returned result will be equal to {@code bits},
63    * otherwise, the result will be equal to {@code 2^64 + bits}.
64    *
65    * <p>To represent decimal constants less than {@code 2^63}, consider {@link #valueOf(long)}
66    * instead.
67    *
68    * @since 14.0
69    */
fromLongBits(long bits)70   public static UnsignedLong fromLongBits(long bits) {
71     // TODO(user): consider caching small values, like Long.valueOf
72     return new UnsignedLong(bits);
73   }
74 
75   /**
76    * Returns an {@code UnsignedLong} representing the same value as the specified {@code long}.
77    *
78    * @throws IllegalArgumentException if {@code value} is negative
79    * @since 14.0
80    */
valueOf(long value)81   public static UnsignedLong valueOf(long value) {
82     checkArgument(value >= 0,
83         "value (%s) is outside the range for an unsigned long value", value);
84     return fromLongBits(value);
85   }
86 
87   /**
88    * Returns a {@code UnsignedLong} representing the same value as the specified
89    * {@code BigInteger}. This is the inverse operation of {@link #bigIntegerValue()}.
90    *
91    * @throws IllegalArgumentException if {@code value} is negative or {@code value >= 2^64}
92    */
valueOf(BigInteger value)93   public static UnsignedLong valueOf(BigInteger value) {
94     checkNotNull(value);
95     checkArgument(value.signum() >= 0 && value.bitLength() <= Long.SIZE,
96         "value (%s) is outside the range for an unsigned long value", value);
97     return fromLongBits(value.longValue());
98   }
99 
100   /**
101    * Returns an {@code UnsignedLong} holding the value of the specified {@code String}, parsed as
102    * an unsigned {@code long} value.
103    *
104    * @throws NumberFormatException if the string does not contain a parsable unsigned {@code long}
105    *         value
106    */
valueOf(String string)107   public static UnsignedLong valueOf(String string) {
108     return valueOf(string, 10);
109   }
110 
111   /**
112    * Returns an {@code UnsignedLong} holding the value of the specified {@code String}, parsed as
113    * an unsigned {@code long} value in the specified radix.
114    *
115    * @throws NumberFormatException if the string does not contain a parsable unsigned {@code long}
116    *         value, or {@code radix} is not between {@link Character#MIN_RADIX} and
117    *         {@link Character#MAX_RADIX}
118    */
valueOf(String string, int radix)119   public static UnsignedLong valueOf(String string, int radix) {
120     return fromLongBits(UnsignedLongs.parseUnsignedLong(string, radix));
121   }
122 
123   /**
124    * Returns the result of adding this and {@code val}. If the result would have more than 64 bits,
125    * returns the low 64 bits of the result.
126    *
127    * @since 14.0
128    */
plus(UnsignedLong val)129   public UnsignedLong plus(UnsignedLong val) {
130     return fromLongBits(this.value + checkNotNull(val).value);
131   }
132 
133   /**
134    * Returns the result of subtracting this and {@code val}. If the result would have more than 64
135    * bits, returns the low 64 bits of the result.
136    *
137    * @since 14.0
138    */
minus(UnsignedLong val)139   public UnsignedLong minus(UnsignedLong val) {
140     return fromLongBits(this.value - checkNotNull(val).value);
141   }
142 
143   /**
144    * Returns the result of multiplying this and {@code val}. If the result would have more than 64
145    * bits, returns the low 64 bits of the result.
146    *
147    * @since 14.0
148    */
149   @CheckReturnValue
times(UnsignedLong val)150   public UnsignedLong times(UnsignedLong val) {
151     return fromLongBits(value * checkNotNull(val).value);
152   }
153 
154   /**
155    * Returns the result of dividing this by {@code val}.
156    *
157    * @since 14.0
158    */
159   @CheckReturnValue
dividedBy(UnsignedLong val)160   public UnsignedLong dividedBy(UnsignedLong val) {
161     return fromLongBits(UnsignedLongs.divide(value, checkNotNull(val).value));
162   }
163 
164   /**
165    * Returns this modulo {@code val}.
166    *
167    * @since 14.0
168    */
169   @CheckReturnValue
mod(UnsignedLong val)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
intValue()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
longValue()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
floatValue()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
doubleValue()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    */
bigIntegerValue()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
compareTo(UnsignedLong o)234   public int compareTo(UnsignedLong o) {
235     checkNotNull(o);
236     return UnsignedLongs.compare(value, o.value);
237   }
238 
239   @Override
hashCode()240   public int hashCode() {
241     return Longs.hashCode(value);
242   }
243 
244   @Override
equals(@ullable Object obj)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
toString()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    */
toString(int radix)266   public String toString(int radix) {
267     return UnsignedLongs.toString(value, radix);
268   }
269 }
270