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  import static com.google.common.primitives.UnsignedInts.INT_MASK;
20  import static com.google.common.primitives.UnsignedInts.compare;
21  import static com.google.common.primitives.UnsignedInts.toLong;
22  
23  import com.google.common.annotations.GwtCompatible;
24  import com.google.common.annotations.GwtIncompatible;
25  import java.math.BigInteger;
26  import javax.annotation.Nullable;
27  
28  /**
29   * A wrapper class for unsigned {@code int} 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 int} values as unsigned, using the methods from {@link UnsignedInts}.
33   *
34   * <p>See the Guava User Guide article on
35   * <a href="https://github.com/google/guava/wiki/PrimitivesExplained#unsigned-support">unsigned
36   * primitive utilities</a>.
37   *
38   * @author Louis Wasserman
39   * @since 11.0
40   */
41  @GwtCompatible(emulated = true)
42  public final class UnsignedInteger extends Number implements Comparable<UnsignedInteger> {
43    public static final UnsignedInteger ZERO = fromIntBits(0);
44    public static final UnsignedInteger ONE = fromIntBits(1);
45    public static final UnsignedInteger MAX_VALUE = fromIntBits(-1);
46  
47    private final int value;
48  
49    private UnsignedInteger(int value) {
50      // GWT doesn't consistently overflow values to make them 32-bit, so we need to force it.
51      this.value = value & 0xffffffff;
52    }
53  
54    /**
55     * Returns an {@code UnsignedInteger} corresponding to a given bit representation. The argument is
56     * interpreted as an unsigned 32-bit value. Specifically, the sign bit of {@code bits} is
57     * interpreted as a normal bit, and all other bits are treated as usual.
58     *
59     * <p>If the argument is nonnegative, the returned result will be equal to {@code bits},
60     * otherwise, the result will be equal to {@code 2^32 + bits}.
61     *
62     * <p>To represent unsigned decimal constants, consider {@link #valueOf(long)} instead.
63     *
64     * @since 14.0
65     */
66    public static UnsignedInteger fromIntBits(int bits) {
67      return new UnsignedInteger(bits);
68    }
69  
70    /**
71     * Returns an {@code UnsignedInteger} that is equal to {@code value}, if possible. The inverse
72     * operation of {@link #longValue()}.
73     */
74    public static UnsignedInteger valueOf(long value) {
75      checkArgument(
76          (value & INT_MASK) == value,
77          "value (%s) is outside the range for an unsigned integer value",
78          value);
79      return fromIntBits((int) value);
80    }
81  
82    /**
83     * Returns a {@code UnsignedInteger} representing the same value as the specified
84     * {@link BigInteger}. This is the inverse operation of {@link #bigIntegerValue()}.
85     *
86     * @throws IllegalArgumentException if {@code value} is negative or {@code value >= 2^32}
87     */
88    public static UnsignedInteger valueOf(BigInteger value) {
89      checkNotNull(value);
90      checkArgument(
91          value.signum() >= 0 && value.bitLength() <= Integer.SIZE,
92          "value (%s) is outside the range for an unsigned integer value",
93          value);
94      return fromIntBits(value.intValue());
95    }
96  
97    /**
98     * Returns an {@code UnsignedInteger} holding the value of the specified {@code String}, parsed as
99     * an unsigned {@code int} value.
100    *
101    * @throws NumberFormatException if the string does not contain a parsable unsigned {@code int}
102    *     value
103    */
104   public static UnsignedInteger valueOf(String string) {
105     return valueOf(string, 10);
106   }
107 
108   /**
109    * Returns an {@code UnsignedInteger} holding the value of the specified {@code String}, parsed as
110    * an unsigned {@code int} value in the specified radix.
111    *
112    * @throws NumberFormatException if the string does not contain a parsable unsigned {@code int}
113    *     value
114    */
115   public static UnsignedInteger valueOf(String string, int radix) {
116     return fromIntBits(UnsignedInts.parseUnsignedInt(string, radix));
117   }
118 
119   /**
120    * Returns the result of adding this and {@code val}. If the result would have more than 32 bits,
121    * returns the low 32 bits of the result.
122    *
123    * @since 14.0
124    */
125   public UnsignedInteger plus(UnsignedInteger val) {
126     return fromIntBits(this.value + checkNotNull(val).value);
127   }
128 
129   /**
130    * Returns the result of subtracting this and {@code val}. If the result would be negative,
131    * returns the low 32 bits of the result.
132    *
133    * @since 14.0
134    */
135   public UnsignedInteger minus(UnsignedInteger val) {
136     return fromIntBits(value - checkNotNull(val).value);
137   }
138 
139   /**
140    * Returns the result of multiplying this and {@code val}. If the result would have more than 32
141    * bits, returns the low 32 bits of the result.
142    *
143    * @since 14.0
144    */
145   @GwtIncompatible // Does not truncate correctly
146   public UnsignedInteger times(UnsignedInteger val) {
147     // TODO(lowasser): make this GWT-compatible
148     return fromIntBits(value * checkNotNull(val).value);
149   }
150 
151   /**
152    * Returns the result of dividing this by {@code val}.
153    *
154    * @throws ArithmeticException if {@code val} is zero
155    * @since 14.0
156    */
157   public UnsignedInteger dividedBy(UnsignedInteger val) {
158     return fromIntBits(UnsignedInts.divide(value, checkNotNull(val).value));
159   }
160 
161   /**
162    * Returns this mod {@code val}.
163    *
164    * @throws ArithmeticException if {@code val} is zero
165    * @since 14.0
166    */
167   public UnsignedInteger mod(UnsignedInteger val) {
168     return fromIntBits(UnsignedInts.remainder(value, checkNotNull(val).value));
169   }
170 
171   /**
172    * Returns the value of this {@code UnsignedInteger} as an {@code int}. This is an inverse
173    * operation to {@link #fromIntBits}.
174    *
175    * <p>Note that if this {@code UnsignedInteger} holds a value {@code >= 2^31}, the returned value
176    * will be equal to {@code this - 2^32}.
177    */
178   @Override
179   public int intValue() {
180     return value;
181   }
182 
183   /**
184    * Returns the value of this {@code UnsignedInteger} as a {@code long}.
185    */
186   @Override
187   public long longValue() {
188     return toLong(value);
189   }
190 
191   /**
192    * Returns the value of this {@code UnsignedInteger} as a {@code float}, analogous to a widening
193    * primitive conversion from {@code int} to {@code float}, and correctly rounded.
194    */
195   @Override
196   public float floatValue() {
197     return longValue();
198   }
199 
200   /**
201    * Returns the value of this {@code UnsignedInteger} as a {@code float}, analogous to a widening
202    * primitive conversion from {@code int} to {@code double}, and correctly rounded.
203    */
204   @Override
205   public double doubleValue() {
206     return longValue();
207   }
208 
209   /**
210    * Returns the value of this {@code UnsignedInteger} as a {@link BigInteger}.
211    */
212   public BigInteger bigIntegerValue() {
213     return BigInteger.valueOf(longValue());
214   }
215 
216   /**
217    * Compares this unsigned integer to another unsigned integer. Returns {@code 0} if they are
218    * equal, a negative number if {@code this < other}, and a positive number if
219    * {@code this > other}.
220    */
221   @Override
222   public int compareTo(UnsignedInteger other) {
223     checkNotNull(other);
224     return compare(value, other.value);
225   }
226 
227   @Override
228   public int hashCode() {
229     return value;
230   }
231 
232   @Override
233   public boolean equals(@Nullable Object obj) {
234     if (obj instanceof UnsignedInteger) {
235       UnsignedInteger other = (UnsignedInteger) obj;
236       return value == other.value;
237     }
238     return false;
239   }
240 
241   /**
242    * Returns a string representation of the {@code UnsignedInteger} value, in base 10.
243    */
244   @Override
245   public String toString() {
246     return toString(10);
247   }
248 
249   /**
250    * Returns a string representation of the {@code UnsignedInteger} value, in base {@code radix}. If
251    * {@code radix < Character.MIN_RADIX} or {@code radix > Character.MAX_RADIX}, the radix
252    * {@code 10} is used.
253    */
254   public String toString(int radix) {
255     return UnsignedInts.toString(value, radix);
256   }
257 }