diff options
Diffstat (limited to 'guava/src/com/google/common/primitives/UnsignedLongs.java')
-rw-r--r-- | guava/src/com/google/common/primitives/UnsignedLongs.java | 113 |
1 files changed, 41 insertions, 72 deletions
diff --git a/guava/src/com/google/common/primitives/UnsignedLongs.java b/guava/src/com/google/common/primitives/UnsignedLongs.java index cb9923f..b723a1b 100644 --- a/guava/src/com/google/common/primitives/UnsignedLongs.java +++ b/guava/src/com/google/common/primitives/UnsignedLongs.java @@ -1,11 +1,11 @@ /* * Copyright (C) 2011 The Guava Authors - * + * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software distributed under the * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing permissions and @@ -17,31 +17,27 @@ package com.google.common.primitives; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; -import com.google.common.annotations.Beta; -import com.google.common.annotations.GwtCompatible; - import java.math.BigInteger; import java.util.Arrays; import java.util.Comparator; +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; + /** * Static utility methods pertaining to {@code long} primitives that interpret values as * <i>unsigned</i> (that is, any negative value {@code x} is treated as the positive value * {@code 2^64 + x}). The methods for which signedness is not an issue are in {@link Longs}, as * well as signed versions of methods for which signedness is an issue. - * + * * <p>In addition, this class provides several static methods for converting a {@code long} to a * {@code String} and a {@code String} to a {@code long} that treat the {@code long} as an unsigned * number. - * + * * <p>Users of these utilities must be <i>extremely careful</i> not to mix up signed and unsigned - * {@code long} values. When possible, it is recommended that the {@link UnsignedLong} wrapper + * {@code long} values. When possible, it is recommended that the {@link UnsignedLong} wrapper * class be used, at a small efficiency penalty, to enforce the distinction in the type system. - * - * <p>See the Guava User Guide article on <a href= - * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained#Unsigned_support"> - * unsigned primitive utilities</a>. - * + * * @author Louis Wasserman * @author Brian Milch * @author Colin Evans @@ -56,7 +52,7 @@ public final class UnsignedLongs { /** * A (self-inverse) bijection which converts the ordering on unsigned longs to the ordering on - * longs, that is, {@code a <= b} as unsigned longs if and only if {@code flip(a) <= flip(b)} + * longs, that is, {@code a <= b} as unsigned longs if and only if {@code rotate(a) <= rotate(b)} * as signed longs. */ private static long flip(long a) { @@ -66,7 +62,7 @@ public final class UnsignedLongs { /** * Compares the two specified {@code long} values, treating them as unsigned values between * {@code 0} and {@code 2^64 - 1} inclusive. - * + * * @param a the first unsigned {@code long} to compare * @param b the second unsigned {@code long} to compare * @return a negative value if {@code a} is less than {@code b}; a positive value if {@code a} is @@ -78,7 +74,7 @@ public final class UnsignedLongs { /** * Returns the least value present in {@code array}, treating values as unsigned. - * + * * @param array a <i>nonempty</i> array of unsigned {@code long} values * @return the value present in {@code array} that is less than or equal to every other value in * the array according to {@link #compare} @@ -98,7 +94,7 @@ public final class UnsignedLongs { /** * Returns the greatest value present in {@code array}, treating values as unsigned. - * + * * @param array a <i>nonempty</i> array of unsigned {@code long} values * @return the value present in {@code array} that is greater than or equal to every other value * in the array according to {@link #compare} @@ -119,7 +115,7 @@ public final class UnsignedLongs { /** * Returns a string containing the supplied unsigned {@code long} values separated by * {@code separator}. For example, {@code join("-", 1, 2, 3)} returns the string {@code "1-2-3"}. - * + * * @param separator the text that should appear between consecutive values in the resulting * string (but not at the start or end) * @param array an array of unsigned {@code long} values, possibly empty @@ -132,7 +128,7 @@ public final class UnsignedLongs { // For pre-sizing a builder, just get the right order of magnitude StringBuilder builder = new StringBuilder(array.length * 5); - builder.append(toString(array[0])); + builder.append(array[0]); for (int i = 1; i < array.length; i++) { builder.append(separator).append(toString(array[i])); } @@ -144,11 +140,11 @@ public final class UnsignedLongs { * lexicographically. That is, it compares, using {@link #compare(long, long)}), the first pair of * values that follow any common prefix, or when one array is a prefix of the other, treats the * shorter array as the lesser. For example, {@code [] < [1L] < [1L, 2L] < [2L] < [1L << 63]}. - * + * * <p>The returned comparator is inconsistent with {@link Object#equals(Object)} (since arrays * support only identity equality), but it is consistent with * {@link Arrays#equals(long[], long[])}. - * + * * @see <a href="http://en.wikipedia.org/wiki/Lexicographical_order">Lexicographical order * article at Wikipedia</a> */ @@ -174,7 +170,7 @@ public final class UnsignedLongs { /** * Returns dividend / divisor, where the dividend and divisor are treated as unsigned 64-bit * quantities. - * + * * @param dividend the dividend (numerator) * @param divisor the divisor (denominator) * @throws ArithmeticException if divisor is 0 @@ -207,7 +203,7 @@ public final class UnsignedLongs { /** * Returns dividend % divisor, where the dividend and divisor are treated as unsigned 64-bit * quantities. - * + * * @param dividend the dividend (numerator) * @param divisor the divisor (denominator) * @throws ArithmeticException if divisor is 0 @@ -240,55 +236,22 @@ public final class UnsignedLongs { /** * Returns the unsigned {@code long} value represented by the given decimal string. - * + * * @throws NumberFormatException if the string does not contain a valid unsigned {@code long} * value - * @throws NullPointerException if {@code s} is null - * (in contrast to {@link Long#parseLong(String)}) */ public static long parseUnsignedLong(String s) { return parseUnsignedLong(s, 10); } /** - * Returns the unsigned {@code long} value represented by the given string. - * - * Accepts a decimal, hexadecimal, or octal number given by specifying the following prefix: - * - * <ul> - * <li>{@code 0x}<i>HexDigits</i> - * <li>{@code 0X}<i>HexDigits</i> - * <li>{@code #}<i>HexDigits</i> - * <li>{@code 0}<i>OctalDigits</i> - * </ul> - * - * @throws NumberFormatException if the string does not contain a valid unsigned {@code long} - * value - * @since 13.0 - */ - public static long decode(String stringValue) { - ParseRequest request = ParseRequest.fromString(stringValue); - - try { - return parseUnsignedLong(request.rawValue, request.radix); - } catch (NumberFormatException e) { - NumberFormatException decodeException = - new NumberFormatException("Error parsing value: " + stringValue); - decodeException.initCause(e); - throw decodeException; - } - } - - /** * Returns the unsigned {@code long} value represented by a string with the given radix. - * + * * @param s the string containing the unsigned {@code long} representation to be parsed. * @param radix the radix to use while parsing {@code s} * @throws NumberFormatException if the string does not contain a valid unsigned {@code long} * with the given radix, or if {@code radix} is not between {@link Character#MIN_RADIX} * and {@link Character#MAX_RADIX}. - * @throws NullPointerException if {@code s} is null - * (in contrast to {@link Long#parseLong(String)}) */ public static long parseUnsignedLong(String s, int radix) { checkNotNull(s); @@ -296,7 +259,7 @@ public final class UnsignedLongs { throw new NumberFormatException("empty string"); } if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) { - throw new NumberFormatException("illegal radix: " + radix); + throw new NumberFormatException("illegal radix:" + radix); } int max_safe_pos = maxSafeDigits[radix] - 1; @@ -347,7 +310,7 @@ public final class UnsignedLongs { /** * Returns a string representation of {@code x} for the given radix, where {@code x} is treated * as unsigned. - * + * * @param x the value to convert to a string. * @param radix the radix to use while working with {@code x} * @throws IllegalArgumentException if {@code radix} is not between {@link Character#MIN_RADIX} @@ -363,17 +326,23 @@ public final class UnsignedLongs { char[] buf = new char[64]; int i = buf.length; if (x < 0) { - // Separate off the last digit using unsigned division. That will leave - // a number that is nonnegative as a signed integer. - long quotient = divide(x, radix); - long rem = x - quotient * radix; - buf[--i] = Character.forDigit((int) rem, radix); - x = quotient; - } - // Simple modulo/division approach - while (x > 0) { - buf[--i] = Character.forDigit((int) (x % radix), radix); - x /= radix; + // Split x into high-order and low-order halves. + // Individual digits are generated from the bottom half into which + // bits are moved continously from the top half. + long top = x >>> 32; + long bot = (x & 0xffffffffl) + ((top % radix) << 32); + top /= radix; + while ((bot > 0) || (top > 0)) { + buf[--i] = Character.forDigit((int) (bot % radix), radix); + bot = (bot / radix) + ((top % radix) << 32); + top /= radix; + } + } else { + // Simple modulo/division approach + while (x > 0) { + buf[--i] = Character.forDigit((int) (x % radix), radix); + x /= radix; + } } // Generate string return new String(buf, i, buf.length - i); |