UnsignedInteger.java revision 1d580d0f6ee4f21eb309ba7b509d2c6d671c4044
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
15package com.google.common.primitives;
16
17import static com.google.common.base.Preconditions.checkArgument;
18import static com.google.common.base.Preconditions.checkNotNull;
19import static com.google.common.primitives.UnsignedInts.INT_MASK;
20import static com.google.common.primitives.UnsignedInts.compare;
21import static com.google.common.primitives.UnsignedInts.toLong;
22
23import java.math.BigInteger;
24
25import javax.annotation.Nullable;
26
27import com.google.common.annotations.Beta;
28import com.google.common.annotations.GwtCompatible;
29import com.google.common.annotations.GwtIncompatible;
30
31/**
32 * A wrapper class for unsigned {@code int} values, supporting arithmetic operations.
33 *
34 * <p>In some cases, when speed is more important than code readability, it may be faster simply to
35 * treat primitive {@code int} values as unsigned, using the methods from {@link UnsignedInts}.
36 *
37 * @author Louis Wasserman
38 * @since 11.0
39 */
40@Beta
41@GwtCompatible(emulated = true)
42public final class UnsignedInteger extends Number implements Comparable<UnsignedInteger> {
43  public static final UnsignedInteger ZERO = asUnsigned(0);
44  public static final UnsignedInteger ONE = asUnsigned(1);
45  public static final UnsignedInteger MAX_VALUE = asUnsigned(-1);
46
47  private final int value;
48
49  private UnsignedInteger(int value) {
50    this.value = value & 0xffffffff;
51  }
52
53  /**
54   * Returns an {@code UnsignedInteger} that, when treated as signed, is
55   * equal to {@code value}.
56   */
57  public static UnsignedInteger asUnsigned(int value) {
58    return new UnsignedInteger(value);
59  }
60
61  /**
62   * Returns an {@code UnsignedInteger} that is equal to {@code value},
63   * if possible.  The inverse operation of {@link #longValue()}.
64   */
65  public static UnsignedInteger valueOf(long value) {
66    checkArgument((value & INT_MASK) == value,
67        "value (%s) is outside the range for an unsigned integer value", value);
68    return asUnsigned((int) value);
69  }
70
71  /**
72   * Returns a {@code UnsignedInteger} representing the same value as the specified
73   * {@link BigInteger}. This is the inverse operation of {@link #bigIntegerValue()}.
74   *
75   * @throws IllegalArgumentException if {@code value} is negative or {@code value >= 2^32}
76   */
77  public static UnsignedInteger valueOf(BigInteger value) {
78    checkNotNull(value);
79    checkArgument(value.signum() >= 0 && value.bitLength() <= Integer.SIZE,
80        "value (%s) is outside the range for an unsigned integer value", value);
81    return asUnsigned(value.intValue());
82  }
83
84  /**
85   * Returns an {@code UnsignedInteger} holding the value of the specified {@code String}, parsed
86   * as an unsigned {@code int} value.
87   *
88   * @throws NumberFormatException if the string does not contain a parsable unsigned {@code int}
89   *         value
90   */
91  public static UnsignedInteger valueOf(String string) {
92    return valueOf(string, 10);
93  }
94
95  /**
96   * Returns an {@code UnsignedInteger} holding the value of the specified {@code String}, parsed
97   * as an unsigned {@code int} value in the specified radix.
98   *
99   * @throws NumberFormatException if the string does not contain a parsable unsigned {@code int}
100   *         value
101   */
102  public static UnsignedInteger valueOf(String string, int radix) {
103    return asUnsigned(UnsignedInts.parseUnsignedInt(string, radix));
104  }
105
106  /**
107   * Returns the result of adding this and {@code val}. If the result would have more than 32 bits,
108   * returns the low 32 bits of the result.
109   */
110  public UnsignedInteger add(UnsignedInteger val) {
111    checkNotNull(val);
112    return asUnsigned(this.value + val.value);
113  }
114
115  /**
116   * Returns the result of subtracting this and {@code val}. If the result would be negative,
117   * returns the low 32 bits of the result.
118   */
119  public UnsignedInteger subtract(UnsignedInteger val) {
120    checkNotNull(val);
121    return asUnsigned(this.value - val.value);
122  }
123
124  /**
125   * Returns the result of multiplying this and {@code val}. If the result would have more than 32
126   * bits, returns the low 32 bits of the result.
127   */
128  @GwtIncompatible("Does not truncate correctly")
129  public UnsignedInteger multiply(UnsignedInteger val) {
130    checkNotNull(val);
131    return asUnsigned(value * val.value);
132  }
133
134  /**
135   * Returns the result of dividing this by {@code val}.
136   */
137  public UnsignedInteger divide(UnsignedInteger val) {
138    checkNotNull(val);
139    return asUnsigned(UnsignedInts.divide(value, val.value));
140  }
141
142  /**
143   * Returns the remainder of dividing this by {@code val}.
144   */
145  public UnsignedInteger remainder(UnsignedInteger val) {
146    checkNotNull(val);
147    return asUnsigned(UnsignedInts.remainder(value, val.value));
148  }
149
150  /**
151   * Returns the value of this {@code UnsignedInteger} as an {@code int}. This is an inverse
152   * operation to {@link #asUnsigned}.
153   *
154   * <p>Note that if this {@code UnsignedInteger} holds a value {@code >= 2^31}, the returned value
155   * will be equal to {@code this - 2^32}.
156   */
157  @Override
158  public int intValue() {
159    return value;
160  }
161
162  /**
163   * Returns the value of this {@code UnsignedInteger} as a {@code long}.
164   */
165  @Override
166  public long longValue() {
167    return toLong(value);
168  }
169
170  /**
171   * Returns the value of this {@code UnsignedInteger} as a {@code float}, analogous to a widening
172   * primitive conversion from {@code int} to {@code float}, and correctly rounded.
173   */
174  @Override
175  public float floatValue() {
176    return longValue();
177  }
178
179  /**
180   * Returns the value of this {@code UnsignedInteger} as a {@code float}, analogous to a widening
181   * primitive conversion from {@code int} to {@code double}, and correctly rounded.
182   */
183  @Override
184  public double doubleValue() {
185    return longValue();
186  }
187
188  /**
189   * Returns the value of this {@code UnsignedInteger} as a {@link BigInteger}.
190   */
191  public BigInteger bigIntegerValue() {
192    return BigInteger.valueOf(longValue());
193  }
194
195  /**
196   * Compares this unsigned integer to another unsigned integer.
197   * Returns {@code 0} if they are equal, a negative number if {@code this < other},
198   * and a positive number if {@code this > other}.
199   */
200  @Override
201  public int compareTo(UnsignedInteger other) {
202    checkNotNull(other);
203    return compare(value, other.value);
204  }
205
206  @Override
207  public int hashCode() {
208    return value;
209  }
210
211  @Override
212  public boolean equals(@Nullable Object obj) {
213    if (obj instanceof UnsignedInteger) {
214      UnsignedInteger other = (UnsignedInteger) obj;
215      return value == other.value;
216    }
217    return false;
218  }
219
220  /**
221   * Returns a string representation of the {@code UnsignedInteger} value, in base 10.
222   */
223  @Override
224  public String toString() {
225    return toString(10);
226  }
227
228  /**
229   * Returns a string representation of the {@code UnsignedInteger} value, in base {@code radix}.
230   * If {@code radix < Character.MIN_RADIX} or {@code radix > Character.MAX_RADIX}, the radix
231   * {@code 10} is used.
232   */
233  public String toString(int radix) {
234    return UnsignedInts.toString(value, radix);
235  }
236}
237