package gui; import java.math.BigDecimal; import java.math.BigInteger; /** * A Quadruple is similar to a Java Double, except that it uses * 16 bytes of data to internally represent a real (floating point) number. * * A Quadruple is a pair of 8-byte (64-bit) integers. * (255, -2) = 255 * 10^(-2) = 2.55 * (255, -4) = .0255 * (31415926535, -10) = 3.1415926535 * * Quadruples can also represent infinities. * When a quadruple is a non-infinity, the exponent's base is 10. * When a quadruple is an infinity, the exponent's base is aleph-null. * @author Oliver Chu */ public class Quadruple { public boolean isInfinity = false; public long value; /* Exponent represents a power of 10. * Or, in the case of infinities, the cardinal power of infinity. */ public long exponent; public static Quadruple NUMBER_OF_ALL_INTEGERS = null; public static Quadruple NEG_NUM_OF_ALL_INTS = null; public static Quadruple ZERO = null; public static BigInteger LONG_MAX = new BigInteger("" + Long.MAX_VALUE); public static BigInteger LONG_MIN = new BigInteger("" + Long.MIN_VALUE); public void growForever() { isInfinity = true; value = Math.abs(value); } public void shrinkForever() { isInfinity = true; value = -Math.abs(value); } public Quadruple(long v, long e) { if (NUMBER_OF_ALL_INTEGERS == null) { NUMBER_OF_ALL_INTEGERS = new Quadruple(1, 0); NUMBER_OF_ALL_INTEGERS.growForever(); } if (NEG_NUM_OF_ALL_INTS == null) { NEG_NUM_OF_ALL_INTS = new Quadruple(-1, 0); NEG_NUM_OF_ALL_INTS.shrinkForever(); } if (ZERO == null) { ZERO = new Quadruple(0, 0); } value = v; exponent = e; } public double toDouble() { BigDecimal bd = new BigDecimal("" + value); BigDecimal multiplier = BigDecimal.TEN; multiplier = multiplier.pow((int) exponent); bd = bd.multiply(multiplier); return bd.doubleValue(); } public String sqrt() { if (value == 0) { return "0"; } if (value < 0) { return "imaginary number"; } if (exponent != 0 && ((exponent & 1) == 0)) { return new Quadruple(value, exponent / 2).toString(); } return "" + Math.sqrt(toDouble()); } public Quadruple neg() { return new Quadruple(-value, exponent); } public Quadruple mul(Quadruple other) { long newValue = value * other.value; long newExp = exponent + other.exponent; return new Quadruple(newValue, newExp); } public Quadruple div(Quadruple other) { long newValue = (long) ((double) value / (double) other.value); long newExp = exponent - other.exponent; return new Quadruple(newValue, newExp); } public Quadruple add(Quadruple other) { long val = value; long exp = exponent; if (other.exponent == exp) { val += other.value; } else if (other.exponent > exp) { BigInteger self = new BigInteger("" + val); for (long i = 0; i < other.exponent - exp; i++) { self.multiply(BigInteger.TEN); val *= 10; if (self.compareTo(LONG_MAX) > 0) { return NUMBER_OF_ALL_INTEGERS; } else if (self.compareTo(LONG_MIN) < 0) { return NEG_NUM_OF_ALL_INTS; } } } else { // TODO } return new Quadruple(val, exp); } private String makeZeroes(byte num) { String answer = ""; while (num > 0) { answer += '0'; --num; } return answer; } @Override public String toString() { if (isInfinity) { if (value == 1) { return "infinity"; } else if (value == -1) { return "-infinity"; } else if (exponent == 0) { return "infinity of magnitude " + value; } else { return "infinity to the power of " + exponent + ", of magnitude " + value; } } if (exponent == 0) { return "" + value; } else if (exponent > 0 && exponent < 64) { return ("" + value) + makeZeroes((byte) exponent); } else if (exponent >= 64) { return "" + value + "e" + exponent; } else if (exponent < 0) { BigDecimal self = new BigDecimal("" + value); long saved = exponent; while (saved < 0) { self.divide(BigDecimal.TEN, 200, BigDecimal.ROUND_HALF_UP); ++saved; } return self.toString(); } else { return "undefined"; } } }