/*
GeoGebra - Dynamic Mathematics for Everyone
http://www.geogebra.org
This file is part of GeoGebra.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation.
*/
package org.geogebra.common.kernel.cas;
import org.geogebra.common.kernel.AsynchronousCommand;
import org.geogebra.common.kernel.Construction;
import org.geogebra.common.kernel.algos.AlgoElement;
import org.geogebra.common.kernel.arithmetic.MyArbitraryConstant;
import org.geogebra.common.kernel.arithmetic.NumberValue;
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;
import org.geogebra.common.kernel.geos.GeoNumeric;
import org.geogebra.common.main.error.ErrorHelper;
/**
* Find a limit
*
* @author Michael Borcherds
*/
public class AlgoLimit extends AlgoElement
implements AsynchronousCommand, UsesCAS {
/** function whose limit we are finding */
protected GeoFunction f;
/** input number */
protected GeoNumberValue num;
/** result */
protected GeoNumeric outNum;
private String limitString;
/**
* @param cons
* construction
* @param label
* label for output
* @param f
* function
* @param num
* number
*/
public AlgoLimit(Construction cons, String label, GeoFunction f,
GeoNumberValue num) {
super(cons);
cons.addCASAlgo(this);
this.f = f;
this.num = num;
init(label);
}
private void init(String label) {
outNum = new GeoNumeric(cons);
setInputOutput(); // for AlgoElement
compute();
outNum.setLabel(label);
}
@Override
public Commands getClassName() {
return Commands.Limit;
}
// for AlgoElement
@Override
protected void setInputOutput() {
input = new GeoElement[2];
input[0] = f;
input[1] = num.toGeoElement();
setOutputLength(1);
setOutput(0, outNum);
setDependencies(); // done by AlgoElement
}
/**
* @return limit result
*/
public GeoNumeric getResult() {
return outNum;
}
private MyArbitraryConstant arbconst = new MyArbitraryConstant(this);
@Override
public void compute() {
if (f == null || !f.isDefined() || !input[1].isDefined()) {
outNum.setUndefined();
return;
}
limitString = f.getLimit(num.getDouble(), getDirection());
try {
String numStr = kernel.evaluateCachedGeoGebraCAS(limitString,
arbconst);
// handles Infinity, ?
outNum.setValue(kernel.getAlgebraProcessor()
.evaluateToNumeric(numStr, ErrorHelper.silent())
.getDouble());
} catch (Throwable e) {
e.printStackTrace();
outNum.setUndefined();
return;
}
}
@Override
public String getCasInput() {
return limitString;
}
/**
*
* @return direction -- 0 default, -1 above, +1 below
*/
protected int getDirection() {
return 0;
}
@Override
public void handleCASoutput(String output, int requestID) {
NumberValue nv = kernel.getAlgebraProcessor().evaluateToNumeric(output,
ErrorHelper.silent());
outNum.setValue(nv.getDouble());
if (USE_ASYNCHRONOUS) {
outNum.updateCascade();
}
}
@Override
public void handleException(Throwable exception, int id) {
outNum.setUndefined();
}
@Override
public boolean useCacheing() {
return true;
}
}