package org.matheclipse.core.polynomials;
import java.util.Iterator;
import java.util.Comparator;
import java.util.TreeMap;
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.ISymbol;
/**
* Generate the horner scheme for univariate polynomials
*/
public class HornerScheme {
private TreeMap map;
public HornerScheme() {
Comparator comp = new Comparator() {
public int compare(ISignedNumber arg0, ISignedNumber arg1) {
if (arg0.isGreaterThan(arg1)) {
return 1;
}
if (arg0.isLessThan(arg1)) {
return -1;
}
return 0;
}
};
map = new TreeMap(comp);
}
public IAST generate(boolean numericMode, IAST poly, ISymbol sym) {
if (numericMode) {
for (int i = 1; i < poly.size(); i++) {
collectTermN(sym, poly.get(i));
}
IAST result = F.Plus();
IAST startResult = result;
IAST temp;
ISignedNumber start = F.CD0;
for (Iterator iter = map.keySet().iterator(); iter.hasNext();) {
ISignedNumber exponent = iter.next();
IExpr coefficient = getCoefficient(exponent);
if (exponent.isLessThan(F.CD1)) {
if (exponent.compareTo(F.CD0) == 0) {
result.add(coefficient);
} else {
result.add(F.Times(coefficient, F.Power(sym, exponent)));
}
} else {
temp = F.Times();
ISignedNumber currentExponent = exponent.subtractFrom(start);
if (currentExponent.equals(F.CD1)) {
temp.add(sym);
} else {
temp.add(F.Power(sym, currentExponent));
}
result.add(temp);
result = F.Plus();
temp.add(result);
result.add(coefficient);
start = exponent;
}
}
return startResult;
} else {
for (int i = 1; i < poly.size(); i++) {
collectTerm(sym, poly.get(i));
}
IAST result = F.Plus();
IAST startResult = result;
IAST temp;
ISignedNumber start = F.C0;
for (Iterator iter = map.keySet().iterator(); iter.hasNext();) {
ISignedNumber exponent = iter.next();
IExpr coefficient = getCoefficient(exponent);
if (exponent.isLessThan(F.C1)) {
if (exponent.compareTo(F.C0) == 0) {
result.add(coefficient);
} else {
result.add(F.Times(coefficient, F.Power(sym, exponent)));
}
} else {
temp = F.Times();
ISignedNumber currentExponent = exponent.subtractFrom(start);
if (currentExponent.equals(F.C1)) {
temp.add(sym);
} else {
temp.add(F.Power(sym, currentExponent));
}
result.add(temp);
result = F.Plus();
temp.add(result);
result.add(coefficient);
start = exponent;
}
}
return startResult;
}
}
private IExpr getCoefficient(ISignedNumber key) {
IAST value = map.get(key);
IExpr coefficient;
if (value.isAST(F.Plus, 2)) {
coefficient = value.get(1);
if (coefficient.isAST(F.Times, 2)) {
coefficient = ((IAST) coefficient).get(1);
}
} else {
coefficient = value;
}
return coefficient;
}
private void collectTerm(ISymbol sym, IExpr expr) {
if (expr instanceof IAST) {
IAST term = (IAST) expr;
if (term.isASTSizeGE(F.Times, 2)) {
for (int i = 1; i < term.size(); i++) {
if (sym.equals(term.get(i))) {
IAST temp = F.ast(term, F.Times, false, i, i + 1);
addToMap(F.C1, temp);
return;
} else if (term.get(i).isAST(F.Power, 3)) {
IAST pow = (IAST) term.get(i);
if (pow.get(1).equals(sym) && pow.get(2) instanceof ISignedNumber) {
IAST temp = F.ast(term, F.Times, false, i, i + 1);
addToMap((ISignedNumber) pow.get(2), temp);
return;
}
}
}
} else if (term.isAST(F.Power, 3)) {
if (term.get(1).equals(sym) && term.get(2) instanceof ISignedNumber) {
addToMap((ISignedNumber) term.get(2), F.C1);
return;
}
}
} else if (expr instanceof ISymbol && expr.equals(sym)) {
addToMap(F.C1, F.C1);
return;
}
addToMap(F.C0, expr);
}
private void collectTermN(ISymbol sym, IExpr expr) {
if (expr instanceof IAST) {
IAST term = (IAST) expr;
if (term.isASTSizeGE(F.Times, 2)) {
for (int i = 1; i < term.size(); i++) {
if (sym.equals(term.get(i))) {
IAST temp = F.ast(term, F.Times, false, i, i + 1);
addToMap(F.CD1, temp);
return;
} else if (term.get(i).isAST(F.Power, 3)) {
IAST pow = (IAST) term.get(i);
if (pow.get(1).equals(sym) && pow.get(2).isSignedNumber()) {
IAST temp = F.ast(term, F.Times, false, i, i + 1);
addToMap((ISignedNumber) pow.get(2), temp);
return;
}
}
}
} else if (term.isAST(F.Power, 3)) {
if (term.get(1).equals(sym) && term.get(2).isSignedNumber()) {
addToMap((ISignedNumber) term.get(2), F.CD1);
return;
}
}
} else if (expr instanceof ISymbol && expr.equals(sym)) {
addToMap(F.CD1, F.CD1);
return;
}
addToMap(F.CD0, expr);
}
public IAST addToMap(final ISignedNumber key, final IExpr value) {
IAST temp = map.get(key);
if (temp == null) {
temp = F.Plus();
temp.add(value);
map.put(key, temp);
} else {
temp.add(value);
}
return temp;
}
}
Ads help maintain this website.