// Copyright 2001, FreeHEP. package org.freehep.postscript; /** * Arithmetic Operators for PostScript Processor * * @author Mark Donszelmann * @version $Id: ArithmeticOperator.java 8958 2006-09-12 23:37:43Z duns $ */ public class ArithmeticOperator extends PSOperator { protected PSRandom random = new PSRandom(); public static Class[] operators = { Add.class, Div.class, IDiv.class, Mod.class, Mul.class, Sub.class, Abs.class, Neg.class, Ceiling.class, Floor.class, Round.class, Truncate.class, Sqrt.class, Atan.class, Cos.class, Sin.class, Exp.class, Ln.class, Log.class }; public boolean execute(OperandStack os) { throw new RuntimeException("Cannot execute class: "+getClass()); } } class Add extends ArithmeticOperator { { operandTypes = new Class[] {PSNumber.class, PSNumber.class }; } public boolean execute(OperandStack os) { if (os.checkType(PSInteger.class, PSInteger.class)) { PSInteger n2 = os.popInteger(); PSInteger n1 = os.popInteger(); long s = (long)n1.getValue() + (long)n2.getValue(); if ((Integer.MIN_VALUE <= s) && (s <= Integer.MAX_VALUE)) { os.push((int)s); } else { os.push((double)s); } } else { PSNumber n2 = os.popNumber(); PSNumber n1 = os.popNumber(); double s = n1.getDouble() + n2.getDouble(); os.push(s); } return true; } } class Div extends ArithmeticOperator { { operandTypes = new Class[] {PSNumber.class, PSNumber.class }; } public boolean execute(OperandStack os) { PSNumber n2 = os.popNumber(); PSNumber n1 = os.popNumber(); if (n2.getDouble() == 0.0) { error(os, new UndefinedResult()); } else { double q = n1.getDouble() / n2.getDouble(); os.push(q); } return true; } } class IDiv extends ArithmeticOperator { { operandTypes = new Class[] {PSInteger.class, PSInteger.class }; } public boolean execute(OperandStack os) { PSInteger i2 = os.popInteger(); PSInteger i1 = os.popInteger(); if (i2.getValue() == 0) { error(os, new UndefinedResult()); } else { int q = i1.getValue() / i2.getValue(); os.push(q); } return true; } } class Mod extends ArithmeticOperator { { operandTypes = new Class[] {PSInteger.class, PSInteger.class }; } public boolean execute(OperandStack os) { PSInteger i2 = os.popInteger(); PSInteger i1 = os.popInteger(); if (i2.getValue() == 0) { error(os, new UndefinedResult()); } else { int r = i1.getValue() % i2.getValue(); os.push(r); } return true; } } class Mul extends ArithmeticOperator { { operandTypes = new Class[] {PSNumber.class, PSNumber.class }; } public boolean execute(OperandStack os) { if (os.checkType(PSInteger.class, PSInteger.class)) { PSInteger n2 = os.popInteger(); PSInteger n1 = os.popInteger(); long p = (long)n1.getValue() * (long)n2.getValue(); if ((Integer.MIN_VALUE <= p) && (p <= Integer.MAX_VALUE)) { os.push((int)p); } else { os.push((double)p); } } else { PSNumber n2 = os.popNumber(); PSNumber n1 = os.popNumber(); double p = n1.getDouble() * n2.getDouble(); os.push(p); } return true; } } class Sub extends ArithmeticOperator { { operandTypes = new Class[] {PSNumber.class, PSNumber.class }; } public boolean execute(OperandStack os) { if (os.checkType(PSInteger.class, PSInteger.class)) { PSInteger n2 = os.popInteger(); PSInteger n1 = os.popInteger(); long d = (long)n1.getValue() - (long)n2.getValue(); if ((Integer.MIN_VALUE <= d) && (d <= Integer.MAX_VALUE)) { os.push((int)d); } else { os.push((double)d); } } else { PSNumber n2 = os.popNumber(); PSNumber n1 = os.popNumber(); double d = n1.getDouble() - n2.getDouble(); os.push(d); } return true; } } class Abs extends ArithmeticOperator { { operandTypes = new Class[] {PSNumber.class}; } public boolean execute(OperandStack os) { if (os.checkType(PSInteger.class)) { PSInteger n1 = os.popInteger(); int n2 = Math.abs(n1.getValue()); os.push(n2); } else { PSReal n1 = os.popReal(); double n2 = Math.abs(n1.getValue()); os.push(n2); } return true; } } class Neg extends ArithmeticOperator { { operandTypes = new Class[] {PSNumber.class}; } public boolean execute(OperandStack os) { if (os.checkType(PSInteger.class)) { PSInteger n1 = os.popInteger(); int n2 = -n1.getValue(); os.push(n2); } else { PSReal n1 = os.popReal(); double n2 = -n1.getValue(); os.push(n2); } return true; } } class Ceiling extends ArithmeticOperator { { operandTypes = new Class[] {PSNumber.class}; } public boolean execute(OperandStack os) { PSNumber n1 = os.popNumber(); double n2 = Math.ceil(n1.getDouble()); if (os.checkType(PSInteger.class)) { os.push((int)n2); } else { os.push(n2); } return true; } } class Floor extends ArithmeticOperator { { operandTypes = new Class[] {PSNumber.class}; } public boolean execute(OperandStack os) { PSNumber n1 = os.popNumber(); double n2 = Math.floor(n1.getDouble()); if (os.checkType(PSInteger.class)) { os.push((int)n2); } else { os.push(n2); } return true; } } class Round extends ArithmeticOperator { { operandTypes = new Class[] {PSNumber.class}; } public boolean execute(OperandStack os) { PSNumber n1 = os.popNumber(); long n2 = Math.round(n1.getDouble()); if (os.checkType(PSInteger.class)) { os.push((int)n2); } else { os.push((double)n2); } return true; } } class Truncate extends ArithmeticOperator { { operandTypes = new Class[] {PSNumber.class}; } public boolean execute(OperandStack os) { PSNumber n1 = os.popNumber(); double n2 = Math.rint(n1.getDouble()); if (os.checkType(PSInteger.class)) { os.push((int)n2); } else { os.push(n2); } return true; } } class Sqrt extends ArithmeticOperator { { operandTypes = new Class[] {PSNumber.class}; } public boolean execute(OperandStack os) { PSNumber n1 = os.popNumber(); if (n1.getDouble() < 0.0) { error(os, new RangeCheck()); } else { double n2 = Math.sqrt(n1.getDouble()); os.push(n2); } return true; } } class Atan extends ArithmeticOperator { { operandTypes = new Class[] {PSNumber.class, PSNumber.class}; } public boolean execute(OperandStack os) { PSNumber den = os.popNumber(); PSNumber num = os.popNumber(); if ((den.getDouble() == 0.0) && (num.getDouble() == 0.0)) { error(os, new UndefinedResult()); } else { double angle = Math.toDegrees(Math.atan2(num.getDouble(), den.getDouble())); os.push(angle); } return true; } } class Cos extends ArithmeticOperator { { operandTypes = new Class[] {PSNumber.class}; } public boolean execute(OperandStack os) { PSNumber angle = os.popNumber(); double r = Math.cos(Math.toRadians(angle.getDouble())); os.push(r); return true; } } class Sin extends ArithmeticOperator { { operandTypes = new Class[] {PSNumber.class}; } public boolean execute(OperandStack os) { PSNumber angle = os.popNumber(); double r = Math.sin(Math.toRadians(angle.getDouble())); os.push(r); return true; } } class Exp extends ArithmeticOperator { { operandTypes = new Class[] {PSNumber.class, PSNumber.class}; } public boolean execute(OperandStack os) { PSNumber exponent = os.popNumber(); PSNumber base = os.popNumber(); if (((exponent.getDouble() % 1) != 0.0) && (base.getDouble() < 0.0)) { error(os, new UndefinedResult()); } else { double r = Math.pow(base.getDouble(), exponent.getDouble()); os.push(r); } return true; } } class Ln extends ArithmeticOperator { { operandTypes = new Class[] {PSNumber.class}; } public boolean execute(OperandStack os) { PSNumber num = os.popNumber(); if (num.getDouble() <= 0.0) { error(os, new RangeCheck()); } else { double r = Math.log(num.getDouble()); os.push(r); } return true; } } class Log extends ArithmeticOperator { { operandTypes = new Class[] {PSNumber.class}; } public boolean execute(OperandStack os) { PSNumber num = os.popNumber(); if (num.getDouble() <= 0.0) { error(os, new RangeCheck()); } else { double r = Math.log(num.getDouble()) / Math.log(10.0); os.push(r); } return true; } } class Rand extends ArithmeticOperator { public boolean execute(OperandStack os) { os.push(random.nextInt()); return true; } } class SRand extends ArithmeticOperator { { operandTypes = new Class[] {PSNumber.class}; } public boolean execute(OperandStack os) { PSInteger seed = os.popInteger(); random.setSeed(seed.getValue()); return true; } } class RRand extends ArithmeticOperator { public boolean execute(OperandStack os) { int seed = random.getSeed(); os.push(seed); return true; } }