package org.matheclipse.core.reflection.system;

import java.util.List;

import org.matheclipse.core.basic.Config;
import org.matheclipse.core.convert.ExprVariables;
import org.matheclipse.core.convert.JASIExpr;
import org.matheclipse.core.convert.JASModInteger;
import org.matheclipse.core.eval.exception.JASConversionException;
import org.matheclipse.core.eval.exception.Validate;
import org.matheclipse.core.eval.interfaces.AbstractFunctionEvaluator;
import org.matheclipse.core.eval.util.Options;
import org.matheclipse.core.expression.ExprRingFactory;
import org.matheclipse.core.expression.F;
import org.matheclipse.core.interfaces.IAST;
import org.matheclipse.core.interfaces.IExpr;
import org.matheclipse.core.interfaces.ISignedNumber;
import org.matheclipse.core.interfaces.IStringX;
import org.matheclipse.core.interfaces.ISymbol;

import edu.jas.arith.ModLong;
import edu.jas.arith.ModLongRing;
import edu.jas.poly.ExpVector;
import edu.jas.poly.GenPolynomial;
import edu.jas.poly.Monomial;
import edu.jas.poly.TermOrder;

/**
 * Get the list of monomials of a polynomial expression.
 * 
 * See Wikipedia - Monomial
 */
public class MonomialList extends AbstractFunctionEvaluator {

	public MonomialList() {
	}

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

		IExpr expr = F.evalExpandAll(ast.arg1());
		ExprVariables eVar;
		if (ast.size() == 2) {
			// extract all variables from the polynomial expression
			eVar = new ExprVariables(ast.arg1());
		} else {
			IAST symbolList = Validate.checkSymbolOrSymbolList(ast, 2);
			eVar = new ExprVariables(symbolList);
		}
		int termOrder = TermOrder.INVLEX;
		try {
			if (ast.size() > 3) {
				if (ast.arg3() instanceof IStringX) {
					String orderStr = ast.arg3().toString();
					if (orderStr.equals("DegreeLexicographic")) {
						termOrder = TermOrder.LEX;
					}
				}
				final Options options = new Options(ast.topHead(), ast, 2);
				IExpr option = options.getOption("Modulus");
				if (option != null && option.isSignedNumber()) {
					return monomialListModulus(expr, eVar.getArrayList(), termOrder, option);
				}
			}
			return monomialList(expr, eVar.getArrayList(), termOrder);
		} catch (JASConversionException jce) {
			// toInt() conversion failed
			if (Config.DEBUG) {
				jce.printStackTrace();
			}
		}
		return null;
	}

	/**
	 * Get the monomial list of a univariate polynomial.
	 * 
	 * @param polynomial
	 * @param variable
	 * @param termOrder
	 *            the JAS term ordering
	 * @return the list of monomials of the univariate polynomial.
	 */
	public static IAST monomialList(IExpr polynomial, final List variablesList, final int termOrder)
			throws JASConversionException {
		JASIExpr jas = new JASIExpr(variablesList, new ExprRingFactory(), new TermOrder(termOrder));
		GenPolynomial polyExpr = jas.expr2IExprJAS(polynomial);
		IAST list = F.List();
		for (Monomial monomial : polyExpr) {
			IExpr coeff = monomial.coefficient();
			ExpVector exp = monomial.exponent();
			IAST monomTimes = F.Times(coeff);
			long lExp;
			ISymbol variable;
			for (int i = 0; i < exp.length(); i++) {
				lExp = exp.getVal(i);
				if (lExp != 0) {
					variable = (ISymbol) variablesList.get(i);
					monomTimes.add(F.Power(variable, F.integer(lExp)));
				}
			}
			list.add(monomTimes);
		}
		return list;
	}

	/**
	 * Get the monomial list of a univariate polynomial with coefficients reduced by a modulo value.
	 * 
	 * @param polynomial
	 * @param variable
	 * @param termOrder
	 *            the JAS term ordering
	 * @param option
	 *            the "Modulus" option
	 * @return the list of monomials of the univariate polynomial.
	 */
	private static IAST monomialListModulus(IExpr polynomial, List variablesList, final int termOrder, IExpr option)
			throws JASConversionException {
		try {
			// found "Modulus" option => use ModIntegerRing
			ModLongRing modIntegerRing = JASModInteger.option2ModLongRing((ISignedNumber) option);
			JASModInteger jas = new JASModInteger(variablesList, modIntegerRing);
			GenPolynomial polyExpr = jas.expr2JAS(polynomial);
			IAST list = F.List();
			for (Monomial monomial : polyExpr) {
				ModLong coeff = monomial.coefficient();
				ExpVector exp = monomial.exponent();
				IAST monomTimes = F.Times(F.integer(coeff.getVal()));
				long lExp;
				ISymbol variable;
				for (int i = 0; i < exp.length(); i++) {
					lExp = exp.getVal(i);
					if (lExp != 0) {
						variable = (ISymbol) variablesList.get(i);
						monomTimes.add(F.Power(variable, F.integer(lExp)));
					}
				}
				list.add(monomTimes);
			}
			return list;
		} catch (ArithmeticException ae) {
			// toInt() conversion failed
			if (Config.DEBUG) {
				ae.printStackTrace();
			}
		}
		return null;
	}

}
 

Ads help maintain this website.