/* 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.Construction; import org.geogebra.common.kernel.algos.AlgoElement; import org.geogebra.common.kernel.algos.DrawInformationAlgo; import org.geogebra.common.kernel.arithmetic.MyDouble; import org.geogebra.common.kernel.arithmetic.NumberValue; import org.geogebra.common.kernel.commands.Commands; import org.geogebra.common.kernel.geos.GeoBoolean; 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; /** * Area between two functions (GeoFunction) f(x) and g(x) over an interval [a, * b]. The value equals Integral[f(x) - g(x), a, b] = Integral[f(x), a, b] - * Integral[g(x), a, b] * * @author Markus Hohenwarter */ public class AlgoIntegralFunctions extends AlgoElement implements DrawInformationAlgo, AlgoIntegralDefiniteInterface { private GeoFunction f, g; // input private NumberValue a, b; // input private GeoBoolean evaluate; // input private GeoElement ageo, bgeo; private GeoNumeric n; // output n = integral(f(x) - g(x), x, a, b) private GeoNumeric intF, intG; /** * @param cons * construction * @param label * output label * @param f * upper function * @param g * lower function * @param a * left bound * @param b * right bound */ public AlgoIntegralFunctions(Construction cons, String label, GeoFunction f, GeoFunction g, GeoNumberValue a, GeoNumberValue b) { this(cons, label, f, g, a, b, null); n.setLabel(label); } /** * @param cons * construction * @param label * output label * @param f * upper function * @param g * lower function * @param a * left bound * @param b * right bound * @param evaluate * true to evaluate, false = just shade */ public AlgoIntegralFunctions(Construction cons, String label, GeoFunction f, GeoFunction g, GeoNumberValue a, GeoNumberValue b, GeoBoolean evaluate) { super(cons); this.f = f; this.g = g; this.a = a; this.b = b; this.evaluate = evaluate; ageo = a.toGeoElement(); bgeo = b.toGeoElement(); // helper algorithms for integral f and g AlgoIntegralDefinite algoInt = new AlgoIntegralDefinite(cons, f, a, b, evaluate); cons.removeFromConstructionList(algoInt); intF = algoInt.getIntegral(); algoInt = new AlgoIntegralDefinite(cons, g, a, b, evaluate); cons.removeFromConstructionList(algoInt); intG = algoInt.getIntegral(); // output: intF - intG n = new GeoNumeric(cons); setInputOutput(); // for AlgoElement compute(); n.setDrawable(true); n.setLabel(label); } /** * @param f * lower function * @param g * upper function * @param a * left bound * @param b * right bound * @param evaluate * true to evaluate, false = just shade */ public AlgoIntegralFunctions(GeoFunction f, GeoFunction g, MyDouble a, MyDouble b, GeoBoolean evaluate) { super(f.getConstruction(), false); this.f = f; this.g = g; this.a = a; this.b = b; this.evaluate = evaluate; } @Override public Commands getClassName() { return Commands.IntegralBetween; } @Override public AlgoIntegralFunctions copy() { return new AlgoIntegralFunctions((GeoFunction) f.copy(), (GeoFunction) g.copy(), new MyDouble(kernel, a.getDouble()), new MyDouble(kernel, b.getDouble()), evaluate == null ? null : (GeoBoolean) evaluate.copy()); } // for AlgoElement @Override protected void setInputOutput() { if (evaluate == null) { input = new GeoElement[4]; input[0] = f; input[1] = g; input[2] = ageo; input[3] = bgeo; } else { input = new GeoElement[5]; input[0] = f; input[1] = g; input[2] = ageo; input[3] = bgeo; input[4] = evaluate; } setOutputLength(1); setOutput(0, n); setDependencies(); // done by AlgoElement } /** * @return integral result */ public GeoNumeric getIntegral() { return n; } /** * @return upper function */ public GeoFunction getF() { return f; } /** * @return lower function */ public GeoFunction getG() { return g; } /** * @return left bound */ public NumberValue getA() { return a; } /** * @return right bound */ public NumberValue getB() { return b; } @Override public final void compute() { if (!f.isDefined() || !g.isDefined() || !ageo.isDefined() || !bgeo.isDefined()) { n.setUndefined(); return; } // return if it should not be evaluated (i.e. is shade-only) if (evaluateOnly()) { n.setValue(Double.NaN); return; } // Integral[f(x) - g(x), a, b] = Integral[f(x), a, b] - Integral[g(x), // a, b] n.setValue(intF.getValue() - intG.getValue()); } @Override public boolean evaluateOnly() { return evaluate != null && !evaluate.getBoolean(); } @Override public void replaceChildrenByValues(GeoElement geo) { f.replaceChildrenByValues(geo); g.replaceChildrenByValues(geo); } }