package org.matheclipse.core.convert;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

import org.matheclipse.core.eval.exception.JASConversionException;
import org.matheclipse.core.eval.exception.Validate;
import org.matheclipse.core.eval.exception.WrongArgumentType;
import org.matheclipse.core.expression.F;
import org.matheclipse.core.interfaces.IAST;
import org.matheclipse.core.interfaces.IExpr;
import org.matheclipse.core.interfaces.IFraction;
import org.matheclipse.core.interfaces.IInteger;
import org.matheclipse.core.interfaces.ISignedNumber;
import org.matheclipse.core.interfaces.ISymbol;

import com.google.common.base.Predicates;

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

/**
 * Convert JAS objects from and to MathEclipse objects
 * 
 * 
 * @param 
 */
public class JASModInteger {
	private final ModLongRing fRingFactory;
	private final TermOrder fTermOrder;
	private final GenPolynomialRing fPolyFactory;

	private final GenPolynomialRing fBigIntegerPolyFactory;

	private final List fVariables;

	public JASModInteger(IExpr variable, ModLongRing ringFactory) {
		List varList = new ArrayList();
		varList.add(variable);
		this.fRingFactory = ringFactory;
		this.fVariables = varList;
		String[] vars = new String[fVariables.size()];
		for (int i = 0; i < fVariables.size(); i++) {
			vars[i] = fVariables.get(i).toString();
		}
		this.fTermOrder = new TermOrder(TermOrder.INVLEX);
		this.fPolyFactory = new GenPolynomialRing(fRingFactory, fVariables.size(), fTermOrder, vars);
		this.fBigIntegerPolyFactory = new GenPolynomialRing(edu.jas.arith.BigInteger.ZERO,
				fVariables.size(), fTermOrder, vars);
	}

	public JASModInteger(final List variablesList, ModLongRing ringFactory) {
		this(variablesList, ringFactory, new TermOrder(TermOrder.INVLEX));
	}

	public JASModInteger(final List variablesList, ModLongRing ringFactory, TermOrder termOrder) {
		this.fRingFactory = ringFactory;
		this.fVariables = variablesList;
		String[] vars = new String[fVariables.size()];
		for (int i = 0; i < fVariables.size(); i++) {
			vars[i] = fVariables.get(i).toString();
		}
		this.fTermOrder = termOrder;
		this.fPolyFactory = new GenPolynomialRing(fRingFactory, fVariables.size(), fTermOrder, vars);
		this.fBigIntegerPolyFactory = new GenPolynomialRing(edu.jas.arith.BigInteger.ZERO,
				fVariables.size(), fTermOrder, vars);
	}

	public GenPolynomial expr2JAS(final IExpr exprPoly) throws JASConversionException {
		try {
			return expr2Poly(exprPoly, false);
		} catch (Exception ae) {
			// ae.printStackTrace();
			throw new JASConversionException();
		}
	}

	/**
	 * Convert the given expression into a JAS polynomial. INum
	 * double values are internally converted to IFractions and converte into the pokynomial structure.
	 * 
	 * @param exprPoly
	 * @return
	 * @throws JASConversionException
	 */
	public GenPolynomial numericExpr2JAS(final IExpr exprPoly) throws JASConversionException {
		try {
			return numericExpr2Poly(exprPoly);
		} catch (Exception ae) {
			// ae.printStackTrace();
			throw new JASConversionException();
		}
	}

	/**
	 * Convert the given expression into a JAS polynomial. Only symbolic numbers
	 * are converted (i.e. no INum or IComplexNum values are converted into the polynomial structure)
	 * 
	 * @param exprPoly
	 * @return
	 * @throws JASConversionException
	 */
	public GenPolynomial expr2IExprJAS(final IExpr exprPoly) throws JASConversionException {
		try {
			return expr2IExprPoly(exprPoly);
		} catch (Exception ae) {
			// ae.printStackTrace();
			throw new JASConversionException();
		}
	}

	/**
	 * Convert the given expression into a JAS polynomial. INum
	 * values are internally converted to IFractions and expr2Poly was called for the expression
	 * 
	 * @param exprPoly
	 * @return
	 * @throws ArithmeticException
	 * @throws ClassCastException
	 */
	private GenPolynomial numericExpr2Poly(final IExpr exprPoly) throws ArithmeticException, ClassCastException {
		return expr2Poly(exprPoly, true);
	}

	/**
	 * Convert the given expression into a JAS polynomial
	 * 
	 * @param exprPoly
	 * @param numeric2Rational
	 *            if true, INum double values are converted to BigRational internally
	 * 
	 * @return
	 * @throws ArithmeticException
	 * @throws ClassCastException
	 */
	private GenPolynomial expr2Poly(final IExpr exprPoly, boolean numeric2Rational) throws ArithmeticException,
			ClassCastException {
		if (exprPoly instanceof IAST) {
			final IAST ast = (IAST) exprPoly;
			GenPolynomial result = fPolyFactory.getZERO();
			GenPolynomial p = fPolyFactory.getZERO();
			if (ast.isPlus()) {
				IExpr expr = ast.get(1);
				result = expr2Poly(expr, numeric2Rational);
				for (int i = 2; i < ast.size(); i++) {
					expr = ast.get(i);
					p = expr2Poly(expr, numeric2Rational);
					result = result.sum(p);
				}
				return result;
			} else if (ast.isTimes()) {
				IExpr expr = ast.get(1);
				result = expr2Poly(expr, numeric2Rational);
				for (int i = 2; i < ast.size(); i++) {
					expr = ast.get(i);
					p = expr2Poly(expr, numeric2Rational);
					result = result.multiply(p);
				}
				return result;
			} else if (ast.isPower()) {
				final IExpr expr = ast.get(1);
				for (int i = 0; i < fVariables.size(); i++) {
					if (fVariables.get(i).equals(expr)) {
						int exponent = -1;
						try {
							exponent = Validate.checkPowerExponent(ast);
						} catch (WrongArgumentType e) {
						}
						if (exponent < 0) {
							throw new ArithmeticException("JASConvert:expr2Poly - invalid exponent: " + ast.get(2).toString());
						}
						ExpVector e = ExpVector.create(fVariables.size(), i, exponent);
						return fPolyFactory.valueOf(e);
						// return fPolyFactory.getONE().multiply(e);
					}
				}
			}
		} else if (exprPoly instanceof ISymbol) {
			for (int i = 0; i < fVariables.size(); i++) {
				if (fVariables.get(i).equals(exprPoly)) {
					ExpVector e = ExpVector.create(fVariables.size(), i, 1L);
					return fPolyFactory.getONE().multiply(e);
				}
			}
			// class cast exception
		} else if (exprPoly instanceof IInteger) {
			return fPolyFactory.fromInteger((java.math.BigInteger) ((IInteger) exprPoly).asType(java.math.BigInteger.class));
			// } else if (exprPoly instanceof IFraction) {
			// return fraction2Poly((IFraction) exprPoly);
			// } else if (exprPoly instanceof INum && numeric2Rational) {
			// IFraction frac = F.fraction(((INum) exprPoly).getRealPart());
			// return fraction2Poly(frac);
			// } else if (exprPoly instanceof IComplexNum && numeric2Rational) {
			// if (F.isZero(((IComplexNum) exprPoly).getImaginaryPart())) {
			// // the imaginary part is zero
			// IFraction frac = F.fraction(((INum) exprPoly).getRealPart());
			// return fraction2Poly(frac);
			// }
		}
		throw new ClassCastException(exprPoly.toString());
	}

	private GenPolynomial fraction2Poly(final IFraction exprPoly) {
		BigInteger n = exprPoly.getBigNumerator();// .toJavaBigInteger();
		BigInteger d = exprPoly.getBigDenominator();// .toJavaBigInteger();
		BigRational nr = new BigRational(n);
		BigRational dr = new BigRational(d);
		BigRational r = nr.divide(dr);
		// if (fRingFactory instanceof ComplexRing) {
		// ComplexRing ring = (ComplexRing) fRingFactory;
		// Complex c = new Complex(ring, r);
		// return new GenPolynomial(fPolyFactory, c);
		// } else {
		return new GenPolynomial(fPolyFactory, r);
		// }
	}

	private GenPolynomial expr2IExprPoly(final IExpr exprPoly) throws ArithmeticException, ClassCastException {
		if (exprPoly instanceof IAST) {
			final IAST ast = (IAST) exprPoly;
			GenPolynomial result = fPolyFactory.getZERO();
			GenPolynomial p = fPolyFactory.getZERO();
			if (ast.isPlus()) {
				IExpr expr = ast.get(1);
				result = expr2IExprPoly(expr);
				for (int i = 2; i < ast.size(); i++) {
					expr = ast.get(i);
					p = expr2IExprPoly(expr);
					result = result.sum(p);
				}
				return result;
			} else if (ast.isTimes()) {
				IExpr expr = ast.get(1);
				result = expr2IExprPoly(expr);
				for (int i = 2; i < ast.size(); i++) {
					expr = ast.get(i);
					p = expr2IExprPoly(expr);
					result = result.multiply(p);
				}
				return result;
			} else if (ast.isPower()) {
				final IExpr expr = ast.get(1);
				for (int i = 0; i < fVariables.size(); i++) {
					if (fVariables.get(i).equals(expr)) {
						int exponent = -1;
						try {
							exponent = Validate.checkPowerExponent(ast);
						} catch (WrongArgumentType e) {
							//
						}
						if (exponent < 0) {
							throw new ArithmeticException("JASConvert:expr2Poly - invalid exponent: " + ast.get(2).toString());
						}
						ExpVector e = ExpVector.create(fVariables.size(), i, exponent);
						return fPolyFactory.getONE().multiply(e);
					}
				}
			}
		} else if (exprPoly instanceof ISymbol) {
			for (int i = 0; i < fVariables.size(); i++) {
				if (fVariables.get(i).equals(exprPoly)) {
					ExpVector e = ExpVector.create(fVariables.size(), i, 1L);
					return fPolyFactory.getONE().multiply(e);
				}
			}
			return new GenPolynomial(fPolyFactory, exprPoly);
		} else if (exprPoly instanceof IInteger) {
			return fPolyFactory.fromInteger((java.math.BigInteger) ((IInteger) exprPoly).asType(java.math.BigInteger.class));
		} else if (exprPoly instanceof IFraction) {
			return fraction2Poly((IFraction) exprPoly);
		}
		if (exprPoly.isFree(Predicates.in(fVariables), true)) {
			return new GenPolynomial(fPolyFactory, exprPoly);
		} else {
			for (int i = 0; i < fVariables.size(); i++) {
				if (fVariables.get(i).equals(exprPoly)) {
					ExpVector e = ExpVector.create(fVariables.size(), i, 1L);
					return fPolyFactory.getONE().multiply(e);
				}
			}
		}
		throw new ClassCastException(exprPoly.toString());
	}

	/**
	 * @return the fPolyFactory
	 */
	public GenPolynomialRing getPolynomialRingFactory() {
		return fPolyFactory;
	} 

	public IAST modLongPoly2Expr(final GenPolynomial poly) throws ArithmeticException, ClassCastException {
		if (poly.length() == 0) {
			return F.Plus(F.C0);
		}
		IAST result = F.Plus();
		for (Monomial monomial : poly) {
			ModLong coeff = monomial.coefficient();
			ExpVector exp = monomial.exponent();
			IInteger coeffValue = F.integer(coeff.getVal());
			IAST monomTimes = F.Times(coeffValue);
			long lExp;
			for (int i = 0; i < exp.length(); i++) {
				lExp = exp.getVal(i);
				if (lExp != 0) {
					monomTimes.add(F.Power(fVariables.get(i), F.integer(lExp)));
				}
			}
			result.add(monomTimes);
		}
		return result;
	}

	public static ModLongRing option2ModLongRing(ISignedNumber option) {
		// TODO convert to long value
		long longValue = option.toLong();
		final BigInteger value = BigInteger.valueOf(longValue);
		return new ModLongRing(longValue, value.isProbablePrime(32));
	}

}

 

Ads help maintain this website.