    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
    015    package com.google.common.primitives;
    016
    017    import static com.google.common.base.Preconditions.checkArgument;
    018    import static com.google.common.base.Preconditions.checkNotNull;
    019    import static com.google.common.primitives.UnsignedInts.INT_MASK;
    020    import static com.google.common.primitives.UnsignedInts.compare;
    021    import static com.google.common.primitives.UnsignedInts.toLong;
    022
    023    import com.google.common.annotations.Beta;
    024    import com.google.common.annotations.GwtCompatible;
    025    import com.google.common.annotations.GwtIncompatible;
    026
    027    import java.math.BigInteger;
    028
    029    import javax.annotation.Nullable;
    030
    031    /**
    032     * A wrapper class for unsigned {@code int} values, supporting arithmetic operations.
    033     *
    034     * <p>In some cases, when speed is more important than code readability, it may be faster simply to
    035     * treat primitive {@code int} values as unsigned, using the methods from {@link UnsignedInts}.
    036     *
    037     * <p>See the Guava User Guide article on <a href=
    038     * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained#Unsigned_support">
    039     * unsigned primitive utilities</a>.
    040     *
    041     * @author Louis Wasserman
    042     * @since 11.0
    043     */
    044    @Beta
    045    @GwtCompatible(emulated = true)
    046    public final class UnsignedInteger extends Number implements Comparable<UnsignedInteger> {
    047      public static final UnsignedInteger ZERO = asUnsigned(0);
    048      public static final UnsignedInteger ONE = asUnsigned(1);
    049      public static final UnsignedInteger MAX_VALUE = asUnsigned(-1);
    050
    051      private final int value;
    052
    053      private UnsignedInteger(int value) {
    054        this.value = value & 0xffffffff;
    055      }
    056
    057      /**
    058       * Returns an {@code UnsignedInteger} that, when treated as signed, is
    059       * equal to {@code value}.
    060       */
    061      public static UnsignedInteger asUnsigned(int value) {
    062        return new UnsignedInteger(value);
    063      }
    064
    065      /**
    066       * Returns an {@code UnsignedInteger} that is equal to {@code value},
    067       * if possible.  The inverse operation of {@link #longValue()}.
    068       */
    069      public static UnsignedInteger valueOf(long value) {
    070        checkArgument((value & INT_MASK) == value,
    071            "value (%s) is outside the range for an unsigned integer value", value);
    072        return asUnsigned((int) value);
    073      }
    074
    075      /**
    076       * Returns a {@code UnsignedInteger} representing the same value as the specified
    077       * {@link BigInteger}. This is the inverse operation of {@link #bigIntegerValue()}.
    078       *
    079       * @throws IllegalArgumentException if {@code value} is negative or {@code value >= 2^32}
    080       */
    081      public static UnsignedInteger valueOf(BigInteger value) {
    082        checkNotNull(value);
    083        checkArgument(value.signum() >= 0 && value.bitLength() <= Integer.SIZE,
    084            "value (%s) is outside the range for an unsigned integer value", value);
    085        return asUnsigned(value.intValue());
    086      }
    087
    088      /**
    089       * Returns an {@code UnsignedInteger} holding the value of the specified {@code String}, parsed
    090       * as an unsigned {@code int} value.
    091       *
    092       * @throws NumberFormatException if the string does not contain a parsable unsigned {@code int}
    093       *         value
    094       */
    095      public static UnsignedInteger valueOf(String string) {
    096        return valueOf(string, 10);
    097      }
    098
    099      /**
    100       * Returns an {@code UnsignedInteger} holding the value of the specified {@code String}, parsed
    101       * as an unsigned {@code int} value in the specified radix.
    102       *
    103       * @throws NumberFormatException if the string does not contain a parsable unsigned {@code int}
    104       *         value
    105       */
    106      public static UnsignedInteger valueOf(String string, int radix) {
    107        return asUnsigned(UnsignedInts.parseUnsignedInt(string, radix));
    108      }
    109
    110      /**
    111       * Returns the result of adding this and {@code val}. If the result would have more than 32 bits,
    112       * returns the low 32 bits of the result.
    113       */
    114      public UnsignedInteger add(UnsignedInteger val) {
    115        checkNotNull(val);
    116        return asUnsigned(this.value + val.value);
    117      }
    118
    119      /**
    120       * Returns the result of subtracting this and {@code val}. If the result would be negative,
    121       * returns the low 32 bits of the result.
    122       */
    123      public UnsignedInteger subtract(UnsignedInteger val) {
    124        checkNotNull(val);
    125        return asUnsigned(this.value - val.value);
    126      }
    127
    128      /**
    129       * Returns the result of multiplying this and {@code val}. If the result would have more than 32
    130       * bits, returns the low 32 bits of the result.
    131       */
    132      @GwtIncompatible("Does not truncate correctly")
    133      public UnsignedInteger multiply(UnsignedInteger val) {
    134        checkNotNull(val);
    135        return asUnsigned(value * val.value);
    136      }
    137
    138      /**
    139       * Returns the result of dividing this by {@code val}.
    140       */
    141      public UnsignedInteger divide(UnsignedInteger val) {
    142        checkNotNull(val);
    143        return asUnsigned(UnsignedInts.divide(value, val.value));
    144      }
    145
    146      /**
    147       * Returns the remainder of dividing this by {@code val}.
    148       */
    149      public UnsignedInteger remainder(UnsignedInteger val) {
    150        checkNotNull(val);
    151        return asUnsigned(UnsignedInts.remainder(value, val.value));
    152      }
    153
    154      /**
    155       * Returns the value of this {@code UnsignedInteger} as an {@code int}. This is an inverse
    156       * operation to {@link #asUnsigned}.
    157       *
    158       * <p>Note that if this {@code UnsignedInteger} holds a value {@code >= 2^31}, the returned value
    159       * will be equal to {@code this - 2^32}.
    160       */
    161      @Override
    162      public int intValue() {
    163        return value;
    164      }
    165
    166      /**
    167       * Returns the value of this {@code UnsignedInteger} as a {@code long}.
    168       */
    169      @Override
    170      public long longValue() {
    171        return toLong(value);
    172      }
    173
    174      /**
    175       * Returns the value of this {@code UnsignedInteger} as a {@code float}, analogous to a widening
    176       * primitive conversion from {@code int} to {@code float}, and correctly rounded.
    177       */
    178      @Override
    179      public float floatValue() {
    180        return longValue();
    181      }
    182
    183      /**
    184       * Returns the value of this {@code UnsignedInteger} as a {@code float}, analogous to a widening
    185       * primitive conversion from {@code int} to {@code double}, and correctly rounded.
    186       */
    187      @Override
    188      public double doubleValue() {
    189        return longValue();
    190      }
    191
    192      /**
    193       * Returns the value of this {@code UnsignedInteger} as a {@link BigInteger}.
    194       */
    195      public BigInteger bigIntegerValue() {
    196        return BigInteger.valueOf(longValue());
    197      }
    198
    199      /**
    200       * Compares this unsigned integer to another unsigned integer.
    201       * Returns {@code 0} if they are equal, a negative number if {@code this < other},
    202       * and a positive number if {@code this > other}.
    203       */
    204      @Override
    205      public int compareTo(UnsignedInteger other) {
    206        checkNotNull(other);
    207        return compare(value, other.value);
    208      }
    209
    210      @Override
    211      public int hashCode() {
    212        return value;
    213      }
    214
    215      @Override
    216      public boolean equals(@Nullable Object obj) {
    217        if (obj instanceof UnsignedInteger) {
    218          UnsignedInteger other = (UnsignedInteger) obj;
    219          return value == other.value;
    220        }
    221        return false;
    222      }
    223
    224      /**
    225       * Returns a string representation of the {@code UnsignedInteger} value, in base 10.
    226       */
    227      @Override
    228      public String toString() {
    229        return toString(10);
    230      }
    231
    232      /**
    233       * Returns a string representation of the {@code UnsignedInteger} value, in base {@code radix}.
    234       * If {@code radix < Character.MIN_RADIX} or {@code radix > Character.MAX_RADIX}, the radix
    235       * {@code 10} is used.
    236       */
    237      public String toString(int radix) {
    238        return UnsignedInts.toString(value, radix);
    239      }
    240    }