001/*
002 * Copyright (C) 2011 The Guava Authors
003 * 
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005 * in compliance with the License. You may obtain a copy of the License at
006 * 
007 * http://www.apache.org/licenses/LICENSE-2.0
008 * 
009 * Unless required by applicable law or agreed to in writing, software distributed under the
010 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
011 * express or implied. See the License for the specific language governing permissions and
012 * limitations under the License.
013 */
014
015package com.google.common.primitives;
016
017import static com.google.common.base.Preconditions.checkArgument;
018import static com.google.common.base.Preconditions.checkNotNull;
019
020import com.google.common.annotations.Beta;
021import com.google.common.annotations.GwtCompatible;
022
023import java.io.Serializable;
024import java.math.BigInteger;
025
026import javax.annotation.Nullable;
027
028/**
029 * A wrapper class for unsigned {@code long} values, supporting arithmetic operations.
030 * 
031 * <p>In some cases, when speed is more important than code readability, it may be faster simply to
032 * treat primitive {@code long} values as unsigned, using the methods from {@link UnsignedLongs}.
033 * 
034 * <p>See the Guava User Guide article on <a href=
035 * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained#Unsigned_support">
036 * unsigned primitive utilities</a>.
037 * 
038 * @author Louis Wasserman
039 * @author Colin Evans
040 * @since 11.0
041 */
042@Beta
043@GwtCompatible(serializable = true)
044public final class UnsignedLong extends Number implements Comparable<UnsignedLong>, Serializable {
045
046  private static final long UNSIGNED_MASK = 0x7fffffffffffffffL;
047
048  public static final UnsignedLong ZERO = new UnsignedLong(0);
049  public static final UnsignedLong ONE = new UnsignedLong(1);
050  public static final UnsignedLong MAX_VALUE = new UnsignedLong(-1L);
051
052  private final long value;
053
054  private UnsignedLong(long value) {
055    this.value = value;
056  }
057
058  /**
059   * Returns an {@code UnsignedLong} that, when treated as signed, is equal to {@code value}. The
060   * inverse operation is {@link #longValue()}.
061   * 
062   * <p>Put another way, if {@code value} is negative, the returned result will be equal to
063   * {@code 2^64 + value}; otherwise, the returned result will be equal to {@code value}.
064   */
065  public static UnsignedLong asUnsigned(long value) {
066    return new UnsignedLong(value);
067  }
068
069  /**
070   * Returns a {@code UnsignedLong} representing the same value as the specified {@code BigInteger}
071   * . This is the inverse operation of {@link #bigIntegerValue()}.
072   * 
073   * @throws IllegalArgumentException if {@code value} is negative or {@code value >= 2^64}
074   */
075  public static UnsignedLong valueOf(BigInteger value) {
076    checkNotNull(value);
077    checkArgument(value.signum() >= 0 && value.bitLength() <= Long.SIZE,
078        "value (%s) is outside the range for an unsigned long value", value);
079    return asUnsigned(value.longValue());
080  }
081
082  /**
083   * Returns an {@code UnsignedLong} holding the value of the specified {@code String}, parsed as
084   * an unsigned {@code long} value.
085   * 
086   * @throws NumberFormatException if the string does not contain a parsable unsigned {@code long}
087   *         value
088   */
089  public static UnsignedLong valueOf(String string) {
090    return valueOf(string, 10);
091  }
092
093  /**
094   * Returns an {@code UnsignedLong} holding the value of the specified {@code String}, parsed as
095   * an unsigned {@code long} value in the specified radix.
096   * 
097   * @throws NumberFormatException if the string does not contain a parsable unsigned {@code long}
098   *         value, or {@code radix} is not between {@link Character#MIN_RADIX} and
099   *         {@link Character#MAX_RADIX}
100   */
101  public static UnsignedLong valueOf(String string, int radix) {
102    return asUnsigned(UnsignedLongs.parseUnsignedLong(string, radix));
103  }
104
105  /**
106   * Returns the result of adding this and {@code val}. If the result would have more than 64 bits,
107   * returns the low 64 bits of the result.
108   */
109  public UnsignedLong add(UnsignedLong val) {
110    checkNotNull(val);
111    return asUnsigned(this.value + val.value);
112  }
113
114  /**
115   * Returns the result of subtracting this and {@code val}. If the result would be negative,
116   * returns the low 64 bits of the result.
117   */
118  public UnsignedLong subtract(UnsignedLong val) {
119    checkNotNull(val);
120    return asUnsigned(this.value - val.value);
121  }
122
123  /**
124   * Returns the result of multiplying this and {@code val}. If the result would have more than 64
125   * bits, returns the low 64 bits of the result.
126   */
127  public UnsignedLong multiply(UnsignedLong val) {
128    checkNotNull(val);
129    return asUnsigned(value * val.value);
130  }
131
132  /**
133   * Returns the result of dividing this by {@code val}.
134   */
135  public UnsignedLong divide(UnsignedLong val) {
136    checkNotNull(val);
137    return asUnsigned(UnsignedLongs.divide(value, val.value));
138  }
139
140  /**
141   * Returns the remainder of dividing this by {@code val}.
142   */
143  public UnsignedLong remainder(UnsignedLong val) {
144    checkNotNull(val);
145    return asUnsigned(UnsignedLongs.remainder(value, val.value));
146  }
147
148  /**
149   * Returns the value of this {@code UnsignedLong} as an {@code int}.
150   */
151  @Override
152  public int intValue() {
153    return (int) value;
154  }
155
156  /**
157   * Returns the value of this {@code UnsignedLong} as a {@code long}. This is an inverse operation
158   * to {@link #asUnsigned}.
159   * 
160   * <p>Note that if this {@code UnsignedLong} holds a value {@code >= 2^63}, the returned value
161   * will be equal to {@code this - 2^64}.
162   */
163  @Override
164  public long longValue() {
165    return value;
166  }
167
168  /**
169   * Returns the value of this {@code UnsignedLong} as a {@code float}, analogous to a widening
170   * primitive conversion from {@code long} to {@code float}, and correctly rounded.
171   */
172  @Override
173  public float floatValue() {
174    @SuppressWarnings("cast")
175    float fValue = (float) (value & UNSIGNED_MASK);
176    if (value < 0) {
177      fValue += 0x1.0p63f;
178    }
179    return fValue;
180  }
181
182  /**
183   * Returns the value of this {@code UnsignedLong} as a {@code double}, analogous to a widening
184   * primitive conversion from {@code long} to {@code double}, and correctly rounded.
185   */
186  @Override
187  public double doubleValue() {
188    @SuppressWarnings("cast")
189    double dValue = (double) (value & UNSIGNED_MASK);
190    if (value < 0) {
191      dValue += 0x1.0p63;
192    }
193    return dValue;
194  }
195
196  /**
197   * Returns the value of this {@code UnsignedLong} as a {@link BigInteger}.
198   */
199  public BigInteger bigIntegerValue() {
200    BigInteger bigInt = BigInteger.valueOf(value & UNSIGNED_MASK);
201    if (value < 0) {
202      bigInt = bigInt.setBit(Long.SIZE - 1);
203    }
204    return bigInt;
205  }
206
207  @Override
208  public int compareTo(UnsignedLong o) {
209    checkNotNull(o);
210    return UnsignedLongs.compare(value, o.value);
211  }
212
213  @Override
214  public int hashCode() {
215    return Longs.hashCode(value);
216  }
217
218  @Override
219  public boolean equals(@Nullable Object obj) {
220    if (obj instanceof UnsignedLong) {
221      UnsignedLong other = (UnsignedLong) obj;
222      return value == other.value;
223    }
224    return false;
225  }
226
227  /**
228   * Returns a string representation of the {@code UnsignedLong} value, in base 10.
229   */
230  @Override
231  public String toString() {
232    return UnsignedLongs.toString(value);
233  }
234
235  /**
236   * Returns a string representation of the {@code UnsignedLong} value, in base {@code radix}. If
237   * {@code radix < Character.MIN_RADIX} or {@code radix > Character.MAX_RADIX}, the radix
238   * {@code 10} is used.
239   */
240  public String toString(int radix) {
241    return UnsignedLongs.toString(value, radix);
242  }
243}