package org.geogebra.common.kernel.advanced;
import java.util.Iterator;
import java.util.LinkedList;
import org.geogebra.common.kernel.Construction;
import org.geogebra.common.kernel.algos.AlgoRootsPolynomial;
import org.geogebra.common.kernel.arithmetic.Function;
import org.geogebra.common.kernel.arithmetic.PolyFunction;
import org.geogebra.common.kernel.commands.Commands;
import org.geogebra.common.kernel.geos.GeoFunction;
public class AlgoComplexRootsPolynomial extends AlgoRootsPolynomial {
double[] curComplexRoots;
public AlgoComplexRootsPolynomial(Construction cons, String[] labels,
GeoFunction f) {
super(cons, labels, f);
}
@Override
public void compute() {
computeComplexRoots();
setRootPoints(solution.curRoots, curComplexRoots,
solution.curRealRoots);
}
@Override
public Commands getClassName() {
return Commands.ComplexRoot;
}
// roots of f
private void computeComplexRoots() {
if (f.isDefined()) {
Function fun = f.getFunction();
// get polynomial factors anc calc roots
calcComplexRoots(fun);
} else {
solution.resetRoots();
}
}
final void calcComplexRoots(Function fun) {
LinkedList<PolyFunction> factorList;
// get polynomial factors for this function
factorList = fun.getPolynomialFactors(true, false);
double[] real, complex;
int noOfRoots;
solution.resetRoots(); // reset solution.curRoots index
// we got a list of polynomial factors
if (factorList != null) {
// compute the roots of every single factor
Iterator<PolyFunction> it = factorList.iterator();
while (it.hasNext()) {
PolyFunction polyFun = it.next();
// update the current coefficients of polyFun
// (this is needed for SymbolicPolyFunction objects)
if (!polyFun.updateCoeffValues()) {
// current coefficients are not defined
solution.curRealRoots = 0;
return;
}
// now let's compute the roots of this factor
// compute all roots of polynomial polyFun
if (polyFun.hasZeroRoot()) {
addToCurrentRoots(new double[] { 0 }, new double[] { 0 },
1);
}
real = polyFun.getCoeffsCopyNoTrailingZeros();
complex = new double[real.length];
noOfRoots = eqnSolver.polynomialComplexRoots(real, complex);
addToCurrentRoots(real, complex, noOfRoots);
}
} else {
return;
}
/*
* if (solution.curRealRoots > 1) { // sort roots and eliminate
* duplicate ones Arrays.sort(solution.curRoots, 0,
* solution.curRealRoots);
*
* // eliminate duplicate roots double maxRoot = solution.curRoots[0];
* int maxIndex = 0; for (int i = 1; i < solution.curRealRoots; i++) {
* if ((solution.curRoots[i] - maxRoot) > AbstractKernel.MIN_PRECISION)
* { maxRoot = solution.curRoots[i]; maxIndex++;
* solution.curRoots[maxIndex] = maxRoot; } } solution.curRealRoots =
* maxIndex + 1; }
*/
}
// add first number of doubles in roots to current roots
private void addToCurrentRoots(double[] real, double[] complex,
int number) {
int length = solution.curRealRoots + number;
if (length >= solution.curRoots.length) { // ensure space
double[] temp = new double[2 * length];
double[] temp2 = new double[2 * length];
for (int i = 0; i < solution.curRealRoots; i++) {
temp[i] = solution.curRoots[i];
temp2[i] = curComplexRoots[i];
}
solution.curRoots = temp;
curComplexRoots = temp2;
}
if (curComplexRoots == null) {
curComplexRoots = new double[solution.curRoots.length];
}
// insert new roots
for (int i = 0; i < number; i++) {
solution.curRoots[solution.curRealRoots + i] = real[i];
curComplexRoots[solution.curRealRoots + i] = complex[i];
}
solution.curRealRoots += number;
}
// roots array and number of roots
final private void setRootPoints(double[] real, double[] complex,
int number) {
initRootPoints(number);
// now set the new values of the roots
for (int i = 0; i < number; i++) {
rootPoints[i].setCoords(real[i], complex[i], 1.0); // root point
rootPoints[i].setComplex();
}
// all other roots are undefined
for (int i = number; i < rootPoints.length; i++) {
rootPoints[i].setUndefined();
}
if (setLabels) {
updateLabels(number);
}
}
}