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 License
010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
011 * or implied. See the License for the specific language governing permissions and limitations under
012 * 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.GwtCompatible;
021import com.google.errorprone.annotations.CanIgnoreReturnValue;
022import java.math.BigInteger;
023import org.jspecify.annotations.Nullable;
024
025/**
026 * A wrapper class for unsigned {@code long} values, supporting arithmetic operations.
027 *
028 * <p>In some cases, when speed is more important than code readability, it may be faster simply to
029 * treat primitive {@code long} values as unsigned, using the methods from {@link UnsignedLongs}.
030 *
031 * <p>See the Guava User Guide article on <a
032 * href="https://github.com/google/guava/wiki/PrimitivesExplained#unsigned-support">unsigned
033 * primitive utilities</a>.
034 *
035 * @author Louis Wasserman
036 * @author Colin Evans
037 * @since 11.0
038 */
039@GwtCompatible
040public final class UnsignedLong extends Number implements Comparable<UnsignedLong> {
041
042  private static final long UNSIGNED_MASK = 0x7fffffffffffffffL;
043
044  /** An {@code UnsignedLong} constant holding the value 0. */
045  public static final UnsignedLong ZERO = new UnsignedLong(0);
046
047  /** An {@code UnsignedLong} constant holding the value 1. */
048  public static final UnsignedLong ONE = new UnsignedLong(1);
049
050  /** An {@code UnsignedLong} constant holding the maximum value, 2^64 - 1. */
051  public static final UnsignedLong MAX_VALUE = new UnsignedLong(-1L);
052
053  private final long value;
054
055  private UnsignedLong(long value) {
056    this.value = value;
057  }
058
059  /**
060   * Returns an {@code UnsignedLong} corresponding to a given bit representation. The argument is
061   * interpreted as an unsigned 64-bit value. Specifically, the sign bit of {@code bits} is
062   * interpreted as a normal bit, and all other bits are treated as usual.
063   *
064   * <p>If the argument is nonnegative, the returned result will be equal to {@code bits},
065   * otherwise, the result will be equal to {@code 2^64 + bits}.
066   *
067   * <p>To represent decimal constants less than {@code 2^63}, consider {@link #valueOf(long)}
068   * instead.
069   *
070   * @since 14.0
071   */
072  public static UnsignedLong fromLongBits(long bits) {
073    // TODO(lowasser): consider caching small values, like Long.valueOf
074    return new UnsignedLong(bits);
075  }
076
077  /**
078   * Returns an {@code UnsignedLong} representing the same value as the specified {@code long}.
079   *
080   * @throws IllegalArgumentException if {@code value} is negative
081   * @since 14.0
082   */
083  @CanIgnoreReturnValue
084  public static UnsignedLong valueOf(long value) {
085    checkArgument(value >= 0, "value (%s) is outside the range for an unsigned long value", value);
086    return fromLongBits(value);
087  }
088
089  /**
090   * Returns a {@code UnsignedLong} representing the same value as the specified {@code BigInteger}.
091   * This is the inverse operation of {@link #bigIntegerValue()}.
092   *
093   * @throws IllegalArgumentException if {@code value} is negative or {@code value >= 2^64}
094   */
095  @CanIgnoreReturnValue
096  public static UnsignedLong valueOf(BigInteger value) {
097    checkNotNull(value);
098    checkArgument(
099        value.signum() >= 0 && value.bitLength() <= Long.SIZE,
100        "value (%s) is outside the range for an unsigned long value",
101        value);
102    return fromLongBits(value.longValue());
103  }
104
105  /**
106   * Returns an {@code UnsignedLong} holding the value of the specified {@code String}, parsed as an
107   * unsigned {@code long} value.
108   *
109   * @throws NumberFormatException if the string does not contain a parsable unsigned {@code long}
110   *     value
111   */
112  @CanIgnoreReturnValue
113  public static UnsignedLong valueOf(String string) {
114    return valueOf(string, 10);
115  }
116
117  /**
118   * Returns an {@code UnsignedLong} holding the value of the specified {@code String}, parsed as an
119   * unsigned {@code long} value in the specified radix.
120   *
121   * @throws NumberFormatException if the string does not contain a parsable unsigned {@code long}
122   *     value, or {@code radix} is not between {@link Character#MIN_RADIX} and {@link
123   *     Character#MAX_RADIX}
124   */
125  @CanIgnoreReturnValue
126  public static UnsignedLong valueOf(String string, int radix) {
127    return fromLongBits(UnsignedLongs.parseUnsignedLong(string, radix));
128  }
129
130  /**
131   * Returns the result of adding this and {@code val}. If the result would have more than 64 bits,
132   * returns the low 64 bits of the result.
133   *
134   * @since 14.0
135   */
136  public UnsignedLong plus(UnsignedLong val) {
137    return fromLongBits(this.value + checkNotNull(val).value);
138  }
139
140  /**
141   * Returns the result of subtracting this and {@code val}. If the result would have more than 64
142   * bits, returns the low 64 bits of the result.
143   *
144   * @since 14.0
145   */
146  public UnsignedLong minus(UnsignedLong val) {
147    return fromLongBits(this.value - checkNotNull(val).value);
148  }
149
150  /**
151   * Returns the result of multiplying this and {@code val}. If the result would have more than 64
152   * bits, returns the low 64 bits of the result.
153   *
154   * @since 14.0
155   */
156  public UnsignedLong times(UnsignedLong val) {
157    return fromLongBits(value * checkNotNull(val).value);
158  }
159
160  /**
161   * Returns the result of dividing this by {@code val}.
162   *
163   * @since 14.0
164   */
165  public UnsignedLong dividedBy(UnsignedLong val) {
166    return fromLongBits(UnsignedLongs.divide(value, checkNotNull(val).value));
167  }
168
169  /**
170   * Returns this modulo {@code val}.
171   *
172   * @since 14.0
173   */
174  public UnsignedLong mod(UnsignedLong val) {
175    return fromLongBits(UnsignedLongs.remainder(value, checkNotNull(val).value));
176  }
177
178  /** Returns the value of this {@code UnsignedLong} as an {@code int}. */
179  @Override
180  public int intValue() {
181    return (int) value;
182  }
183
184  /**
185   * Returns the value of this {@code UnsignedLong} as a {@code long}. This is an inverse operation
186   * to {@link #fromLongBits}.
187   *
188   * <p>Note that if this {@code UnsignedLong} holds a value {@code >= 2^63}, the returned value
189   * will be equal to {@code this - 2^64}.
190   */
191  @Override
192  public long longValue() {
193    return value;
194  }
195
196  /**
197   * Returns the value of this {@code UnsignedLong} as a {@code float}, analogous to a widening
198   * primitive conversion from {@code long} to {@code float}, and correctly rounded.
199   */
200  @Override
201  public float floatValue() {
202    if (value >= 0) {
203      return (float) value;
204    }
205    // The top bit is set, which means that the float value is going to come from the top 24 bits.
206    // So we can ignore the bottom 8, except for rounding. See doubleValue() for more.
207    return (float) ((value >>> 1) | (value & 1)) * 2f;
208  }
209
210  /**
211   * Returns the value of this {@code UnsignedLong} as a {@code double}, analogous to a widening
212   * primitive conversion from {@code long} to {@code double}, and correctly rounded.
213   */
214  @Override
215  public double doubleValue() {
216    if (value >= 0) {
217      return (double) value;
218    }
219    // The top bit is set, which means that the double value is going to come from the top 53 bits.
220    // So we can ignore the bottom 11, except for rounding. We can unsigned-shift right 1, aka
221    // unsigned-divide by 2, and convert that. Then we'll get exactly half of the desired double
222    // value. But in the specific case where the bottom two bits of the original number are 01, we
223    // want to replace that with 1 in the shifted value for correct rounding.
224    return (double) ((value >>> 1) | (value & 1)) * 2.0;
225  }
226
227  /** Returns the value of this {@code UnsignedLong} as a {@link BigInteger}. */
228  public BigInteger bigIntegerValue() {
229    BigInteger bigInt = BigInteger.valueOf(value & UNSIGNED_MASK);
230    if (value < 0) {
231      bigInt = bigInt.setBit(Long.SIZE - 1);
232    }
233    return bigInt;
234  }
235
236  @Override
237  public int compareTo(UnsignedLong o) {
238    checkNotNull(o);
239    return UnsignedLongs.compare(value, o.value);
240  }
241
242  @Override
243  public int hashCode() {
244    return Long.hashCode(value);
245  }
246
247  @Override
248  public boolean equals(@Nullable Object obj) {
249    if (obj instanceof UnsignedLong) {
250      UnsignedLong other = (UnsignedLong) obj;
251      return value == other.value;
252    }
253    return false;
254  }
255
256  /** Returns a string representation of the {@code UnsignedLong} value, in base 10. */
257  @Override
258  public String toString() {
259    return UnsignedLongs.toString(value);
260  }
261
262  /**
263   * Returns a string representation of the {@code UnsignedLong} value, in base {@code radix}. If
264   * {@code radix < Character.MIN_RADIX} or {@code radix > Character.MAX_RADIX}, the radix {@code
265   * 10} is used.
266   */
267  public String toString(int radix) {
268    return UnsignedLongs.toString(value, radix);
269  }
270}