diff --git a/java/expression/exceptions/CheckedAdd.java b/java/expression/exceptions/CheckedAdd.java new file mode 100644 index 0000000..88d38fe --- /dev/null +++ b/java/expression/exceptions/CheckedAdd.java @@ -0,0 +1,29 @@ +package expression.exceptions; + +import java.math.BigDecimal; +import java.math.BigInteger; + +import expression.*; + +/** + * @author Doschennikov Nikita (me@fymio.us) + */ +public class CheckedAdd extends AbstractBinaryOperation { + public CheckedAdd(AbstractExpression l, AbstractExpression r) { super(l, r); } + + @Override protected String getOperator() { return "+"; } + @Override protected int getPriority() { return 1; } + @Override protected boolean isRightAssoc() { return false; } + + @Override + protected int applyInt(int a, int b) { + int result = a + b; + if (((a ^ result) & (b ^ result)) < 0) { + throw new OverflowException("addition"); + } + return result; + } + + @Override protected BigInteger applyBi(BigInteger a, BigInteger b) { return a.add(b); } + @Override protected BigDecimal applyBd(BigDecimal a, BigDecimal b) { return a.add(b); } +} \ No newline at end of file diff --git a/java/expression/exceptions/CheckedDivide.java b/java/expression/exceptions/CheckedDivide.java new file mode 100644 index 0000000..0713133 --- /dev/null +++ b/java/expression/exceptions/CheckedDivide.java @@ -0,0 +1,37 @@ +package expression.exceptions; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.math.MathContext; + +import expression.*; + +/** + * @author Doschennikov Nikita (me@fymio.us) + */ +public class CheckedDivide extends AbstractBinaryOperation { + public CheckedDivide(AbstractExpression l, AbstractExpression r) { super(l, r); } + + @Override protected String getOperator() { return "/"; } + @Override protected int getPriority() { return 2; } + @Override protected boolean isRightAssoc() { return true; } + + @Override + protected int applyInt(int a, int b) { + if (b == 0) throw new DivisionByZeroException(); + if (a == Integer.MIN_VALUE && b == -1) throw new OverflowException("division"); + return a / b; + } + + @Override + protected BigInteger applyBi(BigInteger a, BigInteger b) { + if (b.signum() == 0) throw new DivisionByZeroException(); + return a.divide(b); + } + + @Override + protected BigDecimal applyBd(BigDecimal a, BigDecimal b) { + if (b.signum() == 0) throw new DivisionByZeroException(); + return a.divide(b, MathContext.DECIMAL128); + } +} \ No newline at end of file diff --git a/java/expression/exceptions/CheckedMultiply.java b/java/expression/exceptions/CheckedMultiply.java new file mode 100644 index 0000000..91a1398 --- /dev/null +++ b/java/expression/exceptions/CheckedMultiply.java @@ -0,0 +1,32 @@ +package expression.exceptions; + +import java.math.BigDecimal; +import java.math.BigInteger; + +import expression.*; + +/** + * @author Doschennikov Nikita (me@fymio.us) + */ +public class CheckedMultiply extends AbstractBinaryOperation { + public CheckedMultiply(AbstractExpression l, AbstractExpression r) { super(l, r); } + + @Override protected String getOperator() { return "*"; } + @Override protected int getPriority() { return 2; } + @Override protected boolean isRightAssoc() { return false; } + + @Override + protected int applyInt(int a, int b) { + if (a == 0 || b == 0) return 0; + if (a == Integer.MIN_VALUE && b == -1) throw new OverflowException("multiplication"); + if (b == Integer.MIN_VALUE && a == -1) throw new OverflowException("multiplication"); + int result = a * b; + if (result / a != b) { + throw new OverflowException("multiplication"); + } + return result; + } + + @Override protected BigInteger applyBi(BigInteger a, BigInteger b) { return a.multiply(b); } + @Override protected BigDecimal applyBd(BigDecimal a, BigDecimal b) { return a.multiply(b); } +} \ No newline at end of file diff --git a/java/expression/exceptions/CheckedNegate.java b/java/expression/exceptions/CheckedNegate.java new file mode 100644 index 0000000..fbcb96f --- /dev/null +++ b/java/expression/exceptions/CheckedNegate.java @@ -0,0 +1,44 @@ +package expression.exceptions; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.List; + +import expression.*; + +/** + * @author Doschennikov Nikita (me@fymio.us) + */ +public class CheckedNegate extends AbstractExpression { + private final AbstractExpression operand; + + public CheckedNegate(AbstractExpression operand) { + this.operand = operand; + } + + private static int checkedNegate(int n) { + if (n == Integer.MIN_VALUE) throw new OverflowException("negation"); + return -n; + } + + @Override public int evaluate(int x) { return checkedNegate(operand.evaluate(x)); } + @Override public int evaluate(int x, int y, int z) { return checkedNegate(operand.evaluate(x,y,z)); } + @Override public int evaluate(List vars) { return checkedNegate(operand.evaluate(vars)); } + @Override public BigInteger evaluateBi(List vars) { return operand.evaluateBi(vars).negate(); } + @Override public BigDecimal evaluateBd(List vars) { return operand.evaluateBd(vars).negate(); } + + @Override public String toString() { return "-(" + operand + ")"; } + @Override public String toMiniString() { + if (operand instanceof AbstractBinaryOperation) return "-(" + operand.toMiniString() + ")"; + return "- " + operand.toMiniString(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof CheckedNegate)) return false; + return operand.equals(((CheckedNegate) obj).operand); + } + + @Override public int hashCode() { return -operand.hashCode(); } +} \ No newline at end of file diff --git a/java/expression/exceptions/CheckedSubtract.java b/java/expression/exceptions/CheckedSubtract.java new file mode 100644 index 0000000..85a40d4 --- /dev/null +++ b/java/expression/exceptions/CheckedSubtract.java @@ -0,0 +1,31 @@ +package expression.exceptions; + +import expression.AbstractBinaryOperation; +import expression.AbstractExpression; +import expression.OverflowException; + +import java.math.BigDecimal; +import java.math.BigInteger; + +/** + * @author Doschennikov Nikita (me@fymio.us) + */ +public class CheckedSubtract extends AbstractBinaryOperation { + public CheckedSubtract(AbstractExpression l, AbstractExpression r) { super(l, r); } + + @Override protected String getOperator() { return "-"; } + @Override protected int getPriority() { return 1; } + @Override protected boolean isRightAssoc() { return true; } + + @Override + protected int applyInt(int a, int b) { + int result = a - b; + if (((a ^ b) & (a ^ result)) < 0) { + throw new OverflowException("subtraction"); + } + return result; + } + + @Override protected BigInteger applyBi(BigInteger a, BigInteger b) { return a.subtract(b); } + @Override protected BigDecimal applyBd(BigDecimal a, BigDecimal b) { return a.subtract(b); } +} \ No newline at end of file