| // Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| package com.android.tools.r8.ir.desugar.backports; |
| |
| public final class LongMethods { |
| |
| public static int hashCode(long l) { |
| return (int) (l ^ (l >>> 32)); |
| } |
| |
| public static long parseLongSubsequenceWithRadix( |
| CharSequence s, int beginIndex, int endIndex, int radix) { |
| return Long.parseLong(s.subSequence(beginIndex, endIndex).toString(), radix); |
| } |
| |
| public static long parseLongSubsequenceWithRadixDalvik( |
| CharSequence s, int beginIndex, int endIndex, int radix) { |
| // Dalvik (API level 19 and below) does not support a '+' prefix. |
| if (endIndex - beginIndex >= 2 |
| && s.charAt(beginIndex) == '+' |
| && Character.digit(s.charAt(beginIndex + 1), radix) >= 0) { |
| beginIndex++; |
| } |
| return Long.parseLong(s.subSequence(beginIndex, endIndex).toString(), radix); |
| } |
| |
| public static long divideUnsigned(long dividend, long divisor) { |
| // This implementation is adapted from Guava's UnsignedLongs.java and Longs.java. |
| |
| if (divisor < 0) { // i.e., divisor >= 2^63: |
| // Reference implementation calls UnsignedLongs.compare(dividend, divisor) whose |
| // implementation is Longs.compare(UnsignedLong.flip(a), UnsignedLong.flip(b)). The |
| // implementations of flip() and compare() are inlined here instead. |
| long dividendFlipped = dividend ^ Long.MIN_VALUE; |
| long divisorFlipped = divisor ^ Long.MIN_VALUE; |
| if (dividendFlipped < divisorFlipped) { |
| return 0; // dividend < divisor |
| } else { |
| return 1; // dividend >= divisor |
| } |
| } |
| |
| // Optimization - use signed division if dividend < 2^63 |
| if (dividend >= 0) { |
| return dividend / divisor; |
| } |
| |
| // Otherwise, approximate the quotient, check, and correct if necessary. Our approximation is |
| // guaranteed to be either exact or one less than the correct value. This follows from the |
| // fact that floor(floor(x)/i) == floor(x/i) for any real x and integer i != 0. The proof is |
| // not quite trivial. |
| long quotient = ((dividend >>> 1) / divisor) << 1; |
| long rem = dividend - quotient * divisor; |
| |
| // Reference implementation calls UnsignedLongs.compare(rem, divisor) whose |
| // implementation is Longs.compare(UnsignedLong.flip(a), UnsignedLong.flip(b)). The |
| // implementations of flip() and compare() are inlined here instead. |
| long remFlipped = rem ^ Long.MIN_VALUE; |
| long divisorFlipped = divisor ^ Long.MIN_VALUE; |
| return quotient + (remFlipped >= divisorFlipped ? 1 : 0); |
| } |
| |
| public static long remainderUnsigned(long dividend, long divisor) { |
| // This implementation is adapted from Guava's UnsignedLongs.java and Longs.java. |
| |
| if (divisor < 0) { // i.e., divisor >= 2^63: |
| // Reference implementation calls UnsignedLongs.compare(dividend, divisor) whose |
| // implementation is Longs.compare(UnsignedLong.flip(a), UnsignedLong.flip(b)). The |
| // implementations of flip() and compare() are inlined here instead. |
| long dividendFlipped = dividend ^ Long.MIN_VALUE; |
| long divisorFlipped = divisor ^ Long.MIN_VALUE; |
| if (dividendFlipped < divisorFlipped) { |
| return dividend; // dividend < divisor |
| } else { |
| return dividend - divisor; // dividend >= divisor |
| } |
| } |
| |
| // Optimization - use signed modulus if dividend < 2^63 |
| if (dividend >= 0) { |
| return dividend % divisor; |
| } |
| |
| // Otherwise, approximate the quotient, check, and correct if necessary. Our approximation is |
| // guaranteed to be either exact or one less than the correct value. This follows from the |
| // fact that floor(floor(x)/i) == floor(x/i) for any real x and integer i != 0. The proof is |
| // not quite trivial. |
| long quotient = ((dividend >>> 1) / divisor) << 1; |
| long rem = dividend - quotient * divisor; |
| |
| // Reference implementation calls UnsignedLongs.compare(rem, divisor) whose |
| // implementation is Longs.compare(UnsignedLong.flip(a), UnsignedLong.flip(b)). The |
| // implementations of flip() and compare() are inlined here instead. |
| long remFlipped = rem ^ Long.MIN_VALUE; |
| long divisorFlipped = divisor ^ Long.MIN_VALUE; |
| return rem - (remFlipped >= divisorFlipped ? divisor : 0); |
| } |
| |
| public static int compareUnsigned(long a, long b) { |
| long aFlipped = a ^ Long.MIN_VALUE; |
| long bFlipped = b ^ Long.MIN_VALUE; |
| return Long.compare(aFlipped, bFlipped); |
| } |
| |
| public static long parseUnsignedLong(String s) { |
| return Long.parseUnsignedLong(s, 10); |
| } |
| |
| private static long javaLangLongParseUnsignedLongStub( |
| CharSequence s, int beginIndex, int endIndex, int radix) { |
| throw new RuntimeException("Stub invoked"); |
| } |
| |
| public static long parseUnsignedLongWithRadix(String s, int radix) { |
| return javaLangLongParseUnsignedLongStub(s, 0, s.length(), radix); |
| } |
| |
| public static long parseUnsignedLongSubsequenceWithRadix( |
| CharSequence s, int beginIndex, int endIndex, int radix) { |
| // This implementation is adapted from Guava's UnsignedLongs.java |
| |
| int length = endIndex - beginIndex; |
| if (length == 0) { |
| throw new NumberFormatException("empty string"); |
| } |
| if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) { |
| // Explicit String.concat to work around https://issuetracker.google.com/issues/136596951. |
| throw new NumberFormatException("illegal radix: ".concat(String.valueOf(radix))); |
| } |
| long maxValueBeforeRadixMultiply = Long.divideUnsigned(-1L, radix); |
| |
| // If the string starts with '+' and contains at least two characters, skip the plus. |
| int start = s.charAt(beginIndex) == '+' && length > 1 ? beginIndex + 1 : beginIndex; |
| |
| long value = 0; |
| for (int pos = start; pos < endIndex; pos++) { |
| int digit = Character.digit(s.charAt(pos), radix); |
| if (digit == -1) { |
| throw new NumberFormatException(s.toString()); |
| } |
| if ( // high bit is already set |
| value < 0 |
| // or radix multiply will overflow |
| || value > maxValueBeforeRadixMultiply |
| // or digit add will overflow after radix multiply |
| || (value == maxValueBeforeRadixMultiply |
| && digit > (int) Long.remainderUnsigned(-1L, radix))) { |
| // Explicit String.concat to work around https://issuetracker.google.com/issues/136596951. |
| throw new NumberFormatException("Too large for unsigned long: ".concat(s.toString())); |
| } |
| value = (value * radix) + digit; |
| } |
| |
| return value; |
| } |
| |
| public static String toUnsignedString(long l) { |
| return Long.toUnsignedString(l, 10); |
| } |
| |
| public static String toUnsignedStringWithRadix(long l, int radix) { |
| // This implementation is adapted from Guava's UnsignedLongs.java |
| |
| if (l == 0) { |
| // Simply return "0" |
| return "0"; |
| } else if (l > 0) { |
| return Long.toString(l, radix); |
| } else { |
| if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) { |
| radix = 10; |
| } |
| char[] buf = new char[64]; |
| int i = buf.length; |
| if ((radix & (radix - 1)) == 0) { |
| // Radix is a power of two so we can avoid division. |
| int shift = Integer.numberOfTrailingZeros(radix); |
| int mask = radix - 1; |
| do { |
| buf[--i] = Character.forDigit(((int) l) & mask, radix); |
| l >>>= shift; |
| } while (l != 0); |
| } else { |
| // Separate off the last digit using unsigned division. That will leave |
| // a number that is nonnegative as a signed integer. |
| long quotient; |
| if ((radix & 1) == 0) { |
| // Fast path for the usual case where the radix is even. |
| quotient = (l >>> 1) / (radix >>> 1); |
| } else { |
| quotient = Long.divideUnsigned(l, radix); |
| } |
| long rem = l - quotient * radix; |
| buf[--i] = Character.forDigit((int) rem, radix); |
| l = quotient; |
| // Simple modulo/division approach |
| while (l > 0) { |
| buf[--i] = Character.forDigit((int) (l % radix), radix); |
| l /= radix; |
| } |
| } |
| // Generate string |
| return new String(buf, i, buf.length - i); |
| } |
| } |
| } |