package org.matheclipse.core.reflection.system;

import static org.matheclipse.core.expression.F.$p;
import static org.matheclipse.core.expression.F.*;
import static org.matheclipse.core.expression.F.Sin;
import static org.matheclipse.core.expression.F.Times;
import static org.matheclipse.core.expression.F.x;

import org.matheclipse.core.eval.EvalEngine;
import org.matheclipse.core.eval.interfaces.AbstractArgMultiple;
import org.matheclipse.core.eval.interfaces.INumeric;
import org.matheclipse.core.expression.AST;
import org.matheclipse.core.expression.F;
import org.matheclipse.core.interfaces.IAST;
import org.matheclipse.core.interfaces.IComplex;
import org.matheclipse.core.interfaces.IComplexNum;
import org.matheclipse.core.interfaces.IExpr;
import org.matheclipse.core.interfaces.IFraction;
import org.matheclipse.core.interfaces.IInteger;
import org.matheclipse.core.interfaces.INum;
import org.matheclipse.core.interfaces.ISymbol;
import org.matheclipse.core.patternmatching.HashedOrderlessMatcher;

public class Plus extends AbstractArgMultiple implements INumeric {
	/**
	 * Constructor for the singleton
	 */
	public final static Plus CONST = new Plus();

	private static HashedOrderlessMatcher ORDERLESS_MATCHER = new HashedOrderlessMatcher(true);

	@Override
	public HashedOrderlessMatcher getHashRuleMap() {
		return ORDERLESS_MATCHER;
	}

	public Plus() {

	}

	@Override
	public IExpr e2ComArg(final IComplex c0, final IComplex c1) {
		return c0.add(c1);
	}

	@Override
	public IExpr e2DblArg(final INum d0, final INum d1) {
		return d0.add(d1);
	}

	@Override
	public IExpr e2DblComArg(final IComplexNum d0, final IComplexNum d1) {
		return d0.add(d1);
	}

	@Override
	public IExpr e2FraArg(final IFraction f0, final IFraction f1) {
		return f0.add(f1);
	}

	@Override
	public IExpr e2IntArg(final IInteger i0, final IInteger i1) {
		return i0.add(i1);
	}

	@Override
	public IExpr e2ObjArg(final IExpr o0, final IExpr o1) {
		if (o0.isZero()) {
			return o1;
		}

		if (o1.isZero()) {
			return o0;
		}

		if (o0.equals(F.Indeterminate) || o1.equals(F.Indeterminate)) {
			return F.Indeterminate;
		}

		IExpr temp = null;
		if (o0.isInfinity() || o0.isNegativeInfinity()) {
			temp = eInfinity(o0, o1);
		} else if (o1.isInfinity() || o1.isNegativeInfinity()) {
			temp = eInfinity(o1, o0);
		}
		if (temp != null) {
			return temp;
		}

		if (o0.equals(o1)) {
			return Times(F.C2, o0);
		}

		if (o0.isTimes()) {
			final AST f0 = (AST) o0;

			if (f0.arg1().isNumber()) {
				// Times(number, o1) + o1 => Times(Plus(1, number), o1)
				if ((f0.size() == 3) && f0.arg2().equals(o1)) {
					return Times(Plus(F.C1, f0.arg1()), o1);
				}

				if (o1.isTimes()) {
					final AST f1 = (AST) o1;

					if (f1.arg1().isNumber()) {
						if (f0.equalsFromPosition(1, f1, 1)) {
							final IAST result = F.ast(f0, F.Times, true, 2, f0.size());

							return Times(Plus(f0.arg1(), f1.arg1()), result);
						}
					} else {
						if (f0.equalsFromPosition(1, f1, 0)) {
							final IAST result = F.ast(f0, F.Times, true, 2, f0.size());

							return Times(Plus(F.C1, f0.arg1()), result);
						}
					}
				}
			} else {
				if (o1.isTimes()) {
					final AST f1 = (AST) o1;

					if (f1.arg1().isNumber()) {
						if (f0.equalsFromPosition(0, f1, 1)) {
							final IAST result = F.ast(f1, F.Times, true, 2, f1.size());

							return Times(Plus(F.C1, f1.arg1()), result);
						}
					}
				}
			}
		}

		if (o1.isTimes() && (((IAST) o1).arg1().isNumber())) {
			final IAST f1 = (IAST) o1;
			// o0 + Times(o0, number) => Times(Plus(1, number), o0)
			if ((f1.size() == 3) && f1.arg2().equals(o0)) {
				return Times(Plus(F.C1, f1.arg1()), o0);
			}
		}

		return null;
	}

	private IExpr eInfinity(IExpr inf, IExpr o1) {
		EvalEngine engine = EvalEngine.get();
		if (inf.isInfinity()) {
			if (o1.isInfinity()) {
				return F.CInfinity;
			} else if (o1.isNegativeInfinity()) {
				if (!engine.isQuietMode()) {
					engine.getOutPrintStream().println("Indeterminate expression Infinity-Infinity");
				}
				return F.Indeterminate;
			} else if (o1.isSignedNumber()) {
				return F.CInfinity;
			}
		} else if (inf.isNegativeInfinity()) {
			if (o1.isInfinity()) {
				if (!engine.isQuietMode()) {
					engine.getOutPrintStream().println("Indeterminate expression Infinity-Infinity");
				}
				return F.Indeterminate;
			} else if (o1.isNegativeInfinity()) {
				return F.CNInfinity;
			} else if (o1.isSignedNumber()) {
				return F.CNInfinity;
			}
		}
		return null;
	}

	@Override
	public IExpr eComIntArg(final IComplex c0, final IInteger i1) {
		return c0.add(F.complex(i1, F.C0));
	}

	@Override
	public void setUp(final ISymbol symbol) {
		symbol.setAttributes(ISymbol.ONEIDENTITY | ISymbol.ORDERLESS | ISymbol.FLAT | ISymbol.LISTABLE | ISymbol.NUMERICFUNCTION);

		// ORDERLESS_MATCHER.setUpHashRule("Sin[x_]^2", "Cos[x_]^2", "a");
		ORDERLESS_MATCHER.setUpHashRule(Power(Sin($p(x)), C2), Power(Cos($p(x)), C2), C1);
		// ORDERLESS_MATCHER.setUpHashRule("a_*Sin[x_]^2", "a_*Cos[x_]^2", "a");
		ORDERLESS_MATCHER.setUpHashRule(Times($p(a), Power(Sin($p(x)), C2)), Times($p(a), Power(Cos($p(x)), C2)), a);
		// ORDERLESS_MATCHER.setUpHashRule("ArcSin[x_]", "ArcCos[x_]", "Pi/2");
		ORDERLESS_MATCHER.setUpHashRule(ArcSin($p(x)), ArcCos($p(x)), Times(C1D2, Pi));
		// ORDERLESS_MATCHER.setUpHashRule("ArcTan[x_]", "ArcCot[x_]", "Pi/2");
		ORDERLESS_MATCHER.setUpHashRule(ArcTan($p(x)), ArcCot($p(x)), Times(C1D2, Pi));
		// ORDERLESS_MATCHER.setUpHashRule("ArcTan[x_]", "ArcTan[y_]", "Pi/2", "Positive[x]&&(y==1/x)");
		ORDERLESS_MATCHER.setUpHashRule(ArcTan($p(x)), ArcTan($p(y)), Times(C1D2, Pi), And(Positive(x), Equal(y, Power(x, CN1))));
		// ORDERLESS_MATCHER.setUpHashRule("-ArcTan[x_]", "-ArcTan[y_]", "-Pi/2", "Positive[x]&&(y==1/x)");
		ORDERLESS_MATCHER.setUpHashRule(Times(CN1, ArcTan($p(x))), Times(CN1, ArcTan($p(y))), Times(CN1D2, Pi),
				And(Positive(x), Equal(y, Power(x, CN1))));
		// ORDERLESS_MATCHER.setUpHashRule("Cosh[x_]^2", "-Sinh[x_]^2", "1");
		ORDERLESS_MATCHER.setUpHashRule(Power(Cosh($p(x)), C2), Times(CN1, Power(Sinh($p(x)), C2)), C1);
		super.setUp(symbol);
	}

	public double evalReal(final double[] stack, final int top, final int size) {
		double result = 0;
		for (int i = top - size + 1; i < top + 1; i++) {
			result += stack[i];
		}
		return result;
	}
}

 

Ads help maintain this website.