package st.gravel.support.jvm; import java.math.BigInteger; public class IntegerExtensions { public static class Factory { public static Number fromValue(BigInteger integer) { if (integer.compareTo(MAX_INT_VALUE) == 1) { return integer; } else if (integer.compareTo(MIN_INT_VALUE) == -1) { return (integer); } else { return (integer.intValue()); } } public static Number fromValue(long value) { if (value > Integer.MAX_VALUE || value < Integer.MIN_VALUE) { return BigInteger.valueOf(value); } return Integer.valueOf((int) value); } } public static final BigInteger MIN_INT_VALUE = BigInteger .valueOf(Integer.MIN_VALUE); public static final BigInteger MAX_INT_VALUE = BigInteger .valueOf(Integer.MAX_VALUE); public static final BigInteger MIN_LONG_VALUE = BigInteger .valueOf(Long.MIN_VALUE); public static final BigInteger MAX_LONG_VALUE = BigInteger .valueOf(Long.MAX_VALUE); public static double asDouble(int receiver) { return receiver; } public static float asFloat(int receiver) { return receiver; } public static int asInt(BigInteger integer) { if ((integer.compareTo(IntegerExtensions.MAX_INT_VALUE) == 1) || (integer.compareTo(IntegerExtensions.MIN_INT_VALUE) == -1)) { throw new RuntimeException("Integer out of range"); } else { return (integer.intValue()); } } public static long asLong(BigInteger integer) { if ((integer.compareTo(IntegerExtensions.MAX_LONG_VALUE) == 1) || (integer.compareTo(IntegerExtensions.MIN_LONG_VALUE) == -1)) throw new RuntimeException("Long out of range"); return integer.longValue(); } public static long asLong(Object argument) { if (argument instanceof Integer) return (int) argument; if (argument instanceof BigInteger) { return asLong((BigInteger) argument); } throw new IllegalArgumentException(); } public static BigInteger bigIntegerRaisedToInteger_(int ibase, int iexp) { // From: // http://stackoverflow.com/questions/101439/the-most-efficient-way-to-implement-an-integer-based-power-function-powint-int BigInteger result = BigInteger.valueOf(1); BigInteger base = BigInteger.valueOf(ibase); long exp = iexp; while (exp != 0) { if ((exp & 1) != 0) { result = result.multiply(base); } exp >>= 1; base = base.multiply(base); } return result; } public static int bitAnd_(int receiver, int other) { return receiver & other; } public static int bitInvert(int receiver) { return ~receiver; } public static int bitOr_(int receiver, int other) { return receiver | other; } public static Number bitShift_(int receiver, int operand) { return LargeIntegerExtensions.bitShift_(BigInteger.valueOf(receiver), operand); } public static int bitXor_(int receiver, int other) { return receiver ^ other; } public static Number differenceFromLargeInteger_(int receiver, BigInteger argument) { return objectFromBigInteger(argument.subtract(BigInteger .valueOf(receiver))); } public static Number differenceFromSmallInteger_(int receiver, int argument) { return objectFromLong(((long) (argument)) - receiver); } public static double doubleDivFromLargeInteger_(int receiver, BigInteger argument) { return (argument.doubleValue() / receiver); } public static double doubleDivFromSmallInteger_(int receiver, int argument) { return (double) argument / receiver; } public static boolean equals_(int receiver, int other) { return receiver == other; } public static boolean equals_(int receiver, Integer other) { return other != null && other.intValue() == receiver; } public static boolean equals_(Integer receiver, int other) { return receiver != null && receiver.intValue() == other; } public static boolean equals_(Integer receiver, Integer other) { throw new UnsupportedOperationException("Not Implemented Yet"); } public static float floatDivFromLargeInteger_(int receiver, BigInteger argument) { return (float) (argument.doubleValue() / receiver); } public static float floatDivFromSmallInteger_(int receiver, int argument) { return (float) argument / receiver; } private static int gcd(int a, int b) { // http://en.wikipedia.org/wiki/Euclidean_algorithm if (b == 0) return a; else return gcd(b, a % b); } public static Number gcdFromLargeInteger_(int receiver, BigInteger argument) { return LargeIntegerExtensions.gcdFromLargeInteger_( BigInteger.valueOf(receiver), argument); } public static int gcdFromSmallInteger_(int a, int b) { return gcd(Math.abs(b), Math.abs(a)); } public static int hashMultiply(int receiver) { int low14Bits = receiver & 0x3FFF; int a = receiver >> 14; int b = 0x0065 * low14Bits; int c = 0x260D * a + b; int d = c & 0x3FFF; int e = 0x260D * low14Bits; int f = 16384 * d; int g = f + e; return g & 0xFFFFFFF; } public static Number integerQuotientFromLargeInteger_(int receiver, BigInteger argument) { return LargeIntegerExtensions.integerQuotientFromLargeInteger_( BigInteger.valueOf(receiver), argument); } public static int integerQuotientFromSmallInteger_(int y, int x) { int q = x / y; if ((x % y != 0) && ((x < 0) != (y < 0))) --q; return q; } public static boolean lessFromLargeInteger_(Integer receiver, BigInteger argument) { return argument.compareTo(BigInteger.valueOf((int) receiver)) == -1; } public static boolean lessFromSmallInteger_(Integer receiver, Integer argument) { return argument < receiver; } public static Number moduloQuotientFromLargeInteger_(int receiver, BigInteger argument) { return LargeIntegerExtensions.moduloQuotientFromLargeInteger_( BigInteger.valueOf(receiver), argument); } public static int moduloQuotientFromSmallInteger_(int y, int x) { int r = x % y; if (((r < 0) && (y > 0)) || ((r > 0) && (y < 0))) r += y; return r; } static Number objectFromBigInteger(final BigInteger result) { if (result.compareTo(MAX_INT_VALUE) == 1) { return result; } else if (result.compareTo(MIN_INT_VALUE) == -1) { return (result); } else { return (result.intValue()); } } static Number objectFromLong(final long result) { if (result > Integer.MAX_VALUE) return BigInteger.valueOf(result); if (result < Integer.MIN_VALUE) return BigInteger.valueOf(result); return Integer.valueOf((int) result); } public static String printBase_(Integer receiver, int radix) { return Integer.toString(receiver, radix); } public static Number productFromLargeInteger_(int receiver, BigInteger argument) { if (receiver == 0) return 0; return argument.multiply(BigInteger.valueOf(receiver)); } public static Number productFromSmallInteger_(int receiver, int argument) { return objectFromLong(((long) (argument)) * receiver); } public static Number quoFromLargeInteger_(int receiver, BigInteger argument) { return objectFromBigInteger(argument.divide(BigInteger .valueOf(receiver))); } public static Number quoFromSmallInteger_(int receiver, int argument) { return objectFromLong(((long) (argument)) / receiver); } public static Object raisedToInteger_(final int ibase, final int iexp) { // From: // http://stackoverflow.com/questions/101439/the-most-efficient-way-to-implement-an-integer-based-power-function-powint-int long result = 1; long base = ibase; int exp = iexp; while (exp != 0) { if ((exp & 1) != 0) { result *= base; if (result > Integer.MAX_VALUE || result < Integer.MIN_VALUE) { return bigIntegerRaisedToInteger_(ibase, iexp); } } exp >>= 1; base *= base; if (base > Integer.MAX_VALUE || base < Integer.MIN_VALUE) { return bigIntegerRaisedToInteger_(ibase, iexp); } } return Integer.valueOf((int) result); } public static Number raisedFromLargeInteger_(int receiver, BigInteger argument) { return objectFromBigInteger(argument.pow(receiver)); } public static double raisedFromFloat_(int receiver, float argument) { return Math.pow(argument, receiver); } public static double raisedFromDouble_(int receiver, double argument) { return Math.pow(argument, receiver); } public static Number raisedFromSmallInteger_(int receiver, int argument) { return raisedFromLargeInteger_(receiver, BigInteger.valueOf(argument)); } public static Number remFromLargeInteger_(int receiver, BigInteger argument) { return objectFromBigInteger(argument.remainder(BigInteger .valueOf(receiver))); } public static int remFromSmallInteger_(int receiver, int argument) { return argument % receiver; } public static Number sumFromLargeInteger_(int receiver, BigInteger argument) { return objectFromBigInteger(argument.add(BigInteger.valueOf(receiver))); } public static Number sumFromSmallInteger_(int receiver, int argument) { return objectFromLong(((long) (argument)) + receiver); } }