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}