001: // Copyright (c) 2005 Per M.A. Bothner.
002: // This is free software; for terms and warranty disclaimer see ./COPYING.
003:
004: package gnu.kawa.functions;
005:
006: import gnu.math.*;
007: import java.math.*;
008: import gnu.expr.*;
009: import gnu.mapping.*;
010:
011: /**
012: * Implement the Scheme standard function "*".
013: * @author Per Bothner
014: */
015:
016: public class MultiplyOp extends ProcedureN implements CanInline {
017: public static final MultiplyOp $St = new MultiplyOp("*");
018:
019: public MultiplyOp(String name) {
020: super (name);
021: }
022:
023: public static Object apply(Object arg1, Object arg2) {
024: return ((Numeric) arg1).mul(arg2);
025: }
026:
027: public Object applyN(Object[] args) {
028: int len = args.length;
029: if (len == 0)
030: return IntNum.one();
031: Number result = (Number) args[0];
032: int code = Arithmetic.classifyValue(result);
033: for (int i = 1; i < len; i++) {
034: Object arg2 = args[i];
035: int code2 = Arithmetic.classifyValue(arg2);
036: code = code < code2 ? code2 : code;
037:
038: switch (code) {
039: case Arithmetic.INT_CODE:
040: int i1 = Arithmetic.asInt(result);
041: int i2 = Arithmetic.asInt(arg2);
042: result = new Integer(i1 * i2);
043: break;
044: case Arithmetic.LONG_CODE:
045: long l1 = Arithmetic.asLong(result);
046: long l2 = Arithmetic.asLong(arg2);
047: result = new Long(l1 * l2);
048: break;
049: case Arithmetic.BIGINTEGER_CODE:
050: BigInteger bi1 = Arithmetic.asBigInteger(result);
051: BigInteger bi2 = Arithmetic.asBigInteger(arg2);
052: result = bi1.multiply(bi2);
053: break;
054: case Arithmetic.INTNUM_CODE:
055: result = IntNum.times(Arithmetic.asIntNum(result),
056: Arithmetic.asIntNum(arg2));
057: break;
058: case Arithmetic.BIGDECIMAL_CODE:
059: BigDecimal bd1 = Arithmetic.asBigDecimal(result);
060: BigDecimal bd2 = Arithmetic.asBigDecimal(arg2);
061: result = bd1.multiply(bd2);
062: break;
063: case Arithmetic.RATNUM_CODE:
064: result = RatNum.times(Arithmetic.asRatNum(result),
065: Arithmetic.asRatNum(arg2));
066: break;
067: case Arithmetic.FLOAT_CODE:
068: float f1 = Arithmetic.asFloat(result);
069: float f2 = Arithmetic.asFloat(arg2);
070: result = new Float(f1 * f2);
071: break;
072: case Arithmetic.DOUBLE_CODE:
073: double d1 = Arithmetic.asDouble(result);
074: double d2 = Arithmetic.asDouble(arg2);
075: result = new Double(d1 * d2);
076: break;
077: case Arithmetic.FLONUM_CODE:
078: d1 = Arithmetic.asDouble(result);
079: d2 = Arithmetic.asDouble(arg2);
080: result = new DFloNum(d1 * d2);
081: break;
082: default:
083: result = Arithmetic.asNumeric(result).mul(
084: Arithmetic.asNumeric(arg2));
085: }
086: }
087: return result;
088: }
089:
090: public Expression inline(ApplyExp exp, ExpWalker walker) {
091: if (!walker.getCompilation().mustCompile)
092: return exp;
093: Expression folded = exp.inlineIfConstant(this , walker);
094: if (folded != exp)
095: return folded;
096: Expression[] args = exp.getArgs();
097: if (args.length > 2)
098: return AddOp
099: .pairwise(this , exp.getFunction(), args, walker);
100: if (args.length == 2)
101: return AddOp.primInline(104, exp);
102:
103: return exp;
104: }
105: }
|