package org.matheclipse.core.reflection.system;

import static org.matheclipse.core.expression.F.*;

import org.matheclipse.core.eval.exception.Validate;
import org.matheclipse.core.expression.F;
import org.matheclipse.core.generic.Functors;
import org.matheclipse.core.interfaces.IAST;
import org.matheclipse.core.interfaces.IExpr;
import org.matheclipse.core.interfaces.IInteger;
import org.matheclipse.core.interfaces.ISymbol;

/**
 * Product of expressions.
 * 
 * See  Wikipedia Multiplication
 */
public class Product extends Table {

	// {
	// Product[x_,{x_,0,n_]:=0,
	// Product[x_,{x_,0,n_, s_]:=0,
	// Product[x_,{x_,1,n_]:=n!
	// }

	final static IAST RULES = List(SetDelayed(Product($p(x), List($p(x), C0, $p(n))), C0),
			SetDelayed(Product($p(x), List($p(x), C0, $p(n), $p(s))), C0),
			SetDelayed(Product($p(x), List($p(x), C1, $p(n))), Factorial(n)));

	public Product() {
	}

	@Override
	public IAST getRuleAST() {
		return RULES;
	}

	@Override
	public IExpr evaluate(final IAST ast) {
		Validate.checkRange(ast, 3);

		if (ast.arg1().isTimes()) {
			IAST prod = ast.clone();
			prod.set(1, F.Null);
			return ((IAST) ast.arg1()).map(Functors.replace1st(prod));
		}
		if (ast.arg1().isPower()) {
			IExpr powArg1 = ast.arg1().getAt(1);
			IExpr powArg2 = ast.arg1().getAt(2);
			boolean flag = true;
			// Prod( i^a, {i,from,to},... )
			for (int i = 2; i < ast.size(); i++) {
				if (ast.get(i).isList() && (((IAST) ast.get(i)).size() == 4 || ((IAST) ast.get(i)).size() == 5)) {
					IAST list = (IAST) ast.get(i);
					if (powArg2.isFree(list.arg1(), true)) {
						continue;
					}
				}
				flag = false;
				break;
			}
			if (flag) {
				IAST prod = ast.clone();
				prod.set(1, powArg1);
				return F.Power(prod, powArg2);
			}
		}
		if (ast.size() == 3 && ast.arg2().isList() && ((IAST) ast.arg2()).size() == 4) {
			IAST list = (IAST) ast.arg2();
			if (list.arg1().isSymbol() && list.arg2().isInteger() && list.arg3().isSymbol()) {
				final ISymbol var = (ISymbol) list.arg1();
				final IInteger from = (IInteger) list.arg2();
				final ISymbol to = (ISymbol) list.arg3();
				if (ast.arg1().isFree(var, true) && ast.arg1().isFree(to, true)) {
					if (from.equals(F.C1)) {
						return F.Power(ast.arg1(), to);
					}
					if (from.equals(F.C0)) {
						return F.Power(ast.arg1(), Plus(to, C1));
					}
				}
			}
		}
		IAST resultList = Times();
		IExpr temp = evaluateTable(ast, resultList, C0);
		if (temp == null || temp.equals(resultList)) {
			return null;
		}
		return temp;
	}

}

 

Ads help maintain this website.