package org.geogebra.common.kernel.statistics;
import org.geogebra.common.kernel.Construction;
import org.geogebra.common.kernel.algos.AlgoElement;
import org.geogebra.common.kernel.algos.AlgoPolynomialFromCoordinates;
import org.geogebra.common.kernel.arithmetic.Function;
import org.geogebra.common.kernel.commands.Commands;
import org.geogebra.common.kernel.geos.GeoElement;
import org.geogebra.common.kernel.geos.GeoFunction;
import org.geogebra.common.kernel.geos.GeoNumberValue;
/**
* Algorithm for random polynomials with given degree and coefficient range
*
* @author Zbynek Konecny
*
*/
public class AlgoRandomPolynomial extends AlgoElement {
private GeoNumberValue degree, min, max;
private GeoFunction polynomial;
private Function f;
/**
*
* @param cons
* construction
* @param label
* label for output
* @param degree
* maximal degree
* @param min
* minimal coefficient value
* @param max
* maximal coefficient value
*/
public AlgoRandomPolynomial(Construction cons, String label,
GeoNumberValue degree, GeoNumberValue min, GeoNumberValue max) {
super(cons);
this.degree = degree;
this.min = min;
this.max = max;
polynomial = new GeoFunction(cons);
setInputOutput();
compute();
polynomial.setLabel(label);
}
@Override
protected void setInputOutput() {
setOnlyOutput(polynomial);
input = new GeoElement[] { degree.toGeoElement(), min.toGeoElement(),
max.toGeoElement() };
setDependencies();
}
@Override
public void compute() {
// cover undefined cases
if (!degree.isDefined() || !min.isDefined() || !max.isDefined()
|| degree.getDouble() < 0) {
polynomial.setUndefined();
return;
}
int lower = (int) Math.ceil(min.getDouble());
int upper = (int) Math.floor(max.getDouble());
if (lower > upper || (lower == 0 && upper == 0)) {
polynomial.setUndefined();
return;
}
// input is sane, we can do the computation
int deg = (int) Math.floor(degree.getDouble());
double[] coeffs = new double[deg + 1];
for (int i = 0; i <= deg; i++) {
coeffs[i] = randomCoef(i != deg);
// Log.error("coeff " + i + " is " + coeffs[i]);
}
f = AlgoPolynomialFromCoordinates
.buildPolyFunctionExpression(kernel, coeffs);
polynomial.setFunction(f);
}
private double randomCoef(boolean acceptZero) {
double minD = min.getDouble();
double maxD = max.getDouble();
if (acceptZero
// either both positive, both negative
// or both zero (which shouldn't happen)
// eg RandomPolynomial[3,0,0] returns undefined
|| Math.signum(maxD) == Math.signum(minD)) {
return kernel.getApplication().getRandomIntegerBetween(minD, maxD);
}
// logic doen't work unless minD < 0 < maxD
int rnd = kernel.getApplication().getRandomIntegerBetween(minD,
maxD - 1);
return rnd >= 0 ? rnd + 1 : rnd;
}
@Override
public Commands getClassName() {
return Commands.RandomPolynomial;
}
/**
* @return resulting polynomial
*/
public GeoFunction getResult() {
return polynomial;
}
}