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 org.checkerframework.checker.nullness.qual.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 <a
35  * 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 
UnsignedInteger(int value)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    */
fromIntBits(int bits)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    */
valueOf(long value)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 {@link
84    * BigInteger}. This is the inverse operation of {@link #bigIntegerValue()}.
85    *
86    * @throws IllegalArgumentException if {@code value} is negative or {@code value >= 2^32}
87    */
valueOf(BigInteger value)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    */
valueOf(String string)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    */
valueOf(String string, int radix)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    */
plus(UnsignedInteger val)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    */
minus(UnsignedInteger val)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
times(UnsignedInteger val)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    */
dividedBy(UnsignedInteger val)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    */
mod(UnsignedInteger val)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
intValue()179   public int intValue() {
180     return value;
181   }
182 
183   /** Returns the value of this {@code UnsignedInteger} as a {@code long}. */
184   @Override
longValue()185   public long longValue() {
186     return toLong(value);
187   }
188 
189   /**
190    * Returns the value of this {@code UnsignedInteger} as a {@code float}, analogous to a widening
191    * primitive conversion from {@code int} to {@code float}, and correctly rounded.
192    */
193   @Override
floatValue()194   public float floatValue() {
195     return longValue();
196   }
197 
198   /**
199    * Returns the value of this {@code UnsignedInteger} as a {@code float}, analogous to a widening
200    * primitive conversion from {@code int} to {@code double}, and correctly rounded.
201    */
202   @Override
doubleValue()203   public double doubleValue() {
204     return longValue();
205   }
206 
207   /** Returns the value of this {@code UnsignedInteger} as a {@link BigInteger}. */
bigIntegerValue()208   public BigInteger bigIntegerValue() {
209     return BigInteger.valueOf(longValue());
210   }
211 
212   /**
213    * Compares this unsigned integer to another unsigned integer. Returns {@code 0} if they are
214    * equal, a negative number if {@code this < other}, and a positive number if {@code this >
215    * other}.
216    */
217   @Override
compareTo(UnsignedInteger other)218   public int compareTo(UnsignedInteger other) {
219     checkNotNull(other);
220     return compare(value, other.value);
221   }
222 
223   @Override
hashCode()224   public int hashCode() {
225     return value;
226   }
227 
228   @Override
equals(@ullable Object obj)229   public boolean equals(@Nullable Object obj) {
230     if (obj instanceof UnsignedInteger) {
231       UnsignedInteger other = (UnsignedInteger) obj;
232       return value == other.value;
233     }
234     return false;
235   }
236 
237   /** Returns a string representation of the {@code UnsignedInteger} value, in base 10. */
238   @Override
toString()239   public String toString() {
240     return toString(10);
241   }
242 
243   /**
244    * Returns a string representation of the {@code UnsignedInteger} value, in base {@code radix}. If
245    * {@code radix < Character.MIN_RADIX} or {@code radix > Character.MAX_RADIX}, the radix {@code
246    * 10} is used.
247    */
toString(int radix)248   public String toString(int radix) {
249     return UnsignedInts.toString(value, radix);
250   }
251 }
252