[poincare] Function expression

This commit is contained in:
Léa Saviot
2018-09-25 11:45:05 +02:00
committed by Émilie Feral
parent 3bbb8b39d1
commit 522f5e781e
9 changed files with 123 additions and 9 deletions

View File

@@ -2,11 +2,10 @@
#include "../app.h"
using namespace Shared;
using namespace Poincare;
namespace Graph {
GraphController::GraphController(Responder * parentResponder, CartesianFunctionStore * functionStore, Shared::InteractiveCurveViewRange * curveViewRange, CurveViewCursor * cursor, int * indexFunctionSelectedByCursor, uint32_t * modelVersion, uint32_t * rangeVersion, Preferences::AngleUnit * angleUnitVersion, ButtonRowController * header) :
GraphController::GraphController(Responder * parentResponder, CartesianFunctionStore * functionStore, Shared::InteractiveCurveViewRange * curveViewRange, CurveViewCursor * cursor, int * indexFunctionSelectedByCursor, uint32_t * modelVersion, uint32_t * rangeVersion, Poincare::Preferences::AngleUnit * angleUnitVersion, ButtonRowController * header) :
FunctionGraphController(parentResponder, header, curveViewRange, &m_view, cursor, indexFunctionSelectedByCursor, modelVersion, rangeVersion, angleUnitVersion),
m_bannerView(),
m_view(functionStore, curveViewRange, m_cursor, &m_bannerView, &m_cursorView),
@@ -44,7 +43,7 @@ float GraphController::interestingXRange() {
TextFieldDelegateApp * myApp = (TextFieldDelegateApp *)app();
for (int i = 0; i < functionStore()->numberOfActiveFunctions(); i++) {
Function * f = functionStore()->activeFunctionAtIndex(i);
float fRange = f->expression(myApp->localContext()).characteristicXRange(*(myApp->localContext()), Preferences::sharedPreferences()->angleUnit());
float fRange = f->expression(myApp->localContext()).characteristicXRange(*(myApp->localContext()), Poincare::Preferences::sharedPreferences()->angleUnit());
if (!std::isnan(fRange)) {
characteristicRange = fRange > characteristicRange ? fRange : characteristicRange;
}

View File

@@ -3,7 +3,6 @@
#include "../../shared/poincare_helpers.h"
using namespace Shared;
using namespace Poincare;
namespace Graph {
@@ -21,7 +20,7 @@ const char * IntersectionGraphController::title() {
void IntersectionGraphController::reloadBannerView() {
m_bannerView->setNumberOfSubviews(2);
reloadBannerViewForCursorOnFunction(m_cursor, m_function, 'x');
size_t bufferSize = FunctionBannerDelegate::k_maxNumberOfCharacters+PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits);
size_t bufferSize = FunctionBannerDelegate::k_maxNumberOfCharacters+Poincare::PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits);
char buffer[bufferSize];
const char * space = " ";
int spaceLength = strlen(space);
@@ -31,18 +30,18 @@ void IntersectionGraphController::reloadBannerView() {
numberOfChar += strlcpy(buffer, legend, bufferSize);
buffer[0] = m_function->name()[0];
buffer[5] = m_intersectedFunction->name()[0];
numberOfChar += PoincareHelpers::ConvertFloatToText<double>(m_cursor->y(), buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits), Constant::MediumNumberOfSignificantDigits);
numberOfChar += PoincareHelpers::ConvertFloatToText<double>(m_cursor->y(), buffer+numberOfChar, Poincare::PrintFloat::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits), Constant::MediumNumberOfSignificantDigits);
strlcpy(buffer+numberOfChar, space, bufferSize - numberOfChar);
buffer[FunctionBannerDelegate::k_maxDigitLegendLength+legendLength] = 0;
bannerView()->setLegendAtIndex(buffer, 1);
}
Expression::Coordinate2D IntersectionGraphController::computeNewPointOfInterest(double start, double step, double max, Context * context) {
Expression::Coordinate2D result = {.abscissa = NAN, .value = NAN};
Poincare::Expression::Coordinate2D IntersectionGraphController::computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) {
Poincare::Expression::Coordinate2D result = {.abscissa = NAN, .value = NAN};
for (int i = 0; i < m_functionStore->numberOfActiveFunctions(); i++) {
Function * f = m_functionStore->activeFunctionAtIndex(i);
if (f != m_function) {
Expression::Coordinate2D intersection = m_function->nextIntersectionFrom(start, step, max, context, f);
Poincare::Expression::Coordinate2D intersection = m_function->nextIntersectionFrom(start, step, max, context, f);
if ((std::isnan(result.abscissa) || std::fabs(intersection.abscissa-start) < std::fabs(result.abscissa-start)) && !std::isnan(intersection.abscissa)) {
m_intersectedFunction = f;
result = (std::isnan(result.abscissa) || std::fabs(intersection.abscissa-start) < std::fabs(result.abscissa-start)) ? intersection : result;

View File

@@ -70,6 +70,7 @@ objs += $(addprefix poincare/src/,\
float.o\
floor.o\
frac_part.o\
function.o\
global_context.o\
great_common_divisor.o\
hyperbolic_arc_cosine.o\

View File

@@ -37,6 +37,7 @@ class Expression : public TreeHandle {
friend class Factorial;
friend class Floor;
friend class FracPart;
friend class Function;
friend class GlobalContext;
friend class GreatCommonDivisor;
friend class HyperbolicTrigonometricFunction;
@@ -74,6 +75,7 @@ class Expression : public TreeHandle {
template<typename T>
friend class ExceptionExpressionNode;
friend class ExpressionNode;
friend class FunctionNode;
friend class IntegralNode;
template<int T>
friend class LogarithmNode;

View File

@@ -51,6 +51,7 @@ public:
Factor,
Floor,
FracPart,
Function,
GreatCommonDivisor,
HyperbolicArcCosine,
HyperbolicArcSine,

View File

@@ -0,0 +1,50 @@
#ifndef POINCARE_FUNCTION_H
#define POINCARE_FUNCTION_H
#include <poincare/symbol.h>
namespace Poincare {
class FunctionNode : public SymbolNode {
public:
// TreeNode
size_t size() const override { return sizeof(FunctionNode); }
int numberOfChildren() const override { return 1; } //TODO allow any number of children?
#if POINCARE_TREE_LOG
virtual void logNodeName(std::ostream & stream) const override {
stream << "Function";
}
#endif
// Properties
Type type() const override { return Type::Function; }
int polynomialDegree(Context & context, char symbolName) const override;
int getPolynomialCoefficients(Context & context, char symbolName, Expression coefficients[]) const override;
int getVariables(Context & context, isVariableTest isVariable, char * variables) const override;
float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const override;
private:
// Layout
Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
// Simplification
Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit) override;
// Evaluation
Evaluation<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override;
Evaluation<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override;
};
class Function : public Symbol {
public:
Function();
Function(const FunctionNode * n) : Symbol(n) {}
explicit Function(Expression operand) : Function() {
replaceChildAtIndexInPlace(0, operand);
}
Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit);
};
}
#endif

View File

@@ -29,6 +29,7 @@
#include <poincare/float.h>
#include <poincare/floor.h>
#include <poincare/frac_part.h>
#include <poincare/function.h>
#include <poincare/global_context.h>
#include <poincare/great_common_divisor.h>
#include <poincare/hyperbolic_arc_cosine.h>

60
poincare/src/function.cpp Normal file
View File

@@ -0,0 +1,60 @@
#include <poincare/function.h>
#include <poincare/layout_helper.h>
#include <poincare/serialization_helper.h>
#include <poincare/simplification_helper.h>
#include <poincare/rational.h>
#include <cmath>
namespace Poincare {
int FunctionNode::polynomialDegree(Context & context, char symbolName) const {
Expression e = context.expressionForSymbol(Function(this));
return e.polynomialDegree(context, symbolName);
}
int FunctionNode::getPolynomialCoefficients(Context & context, char symbolName, Expression coefficients[]) const {
Expression e = context.expressionForSymbol(Function(this));
return e.getPolynomialCoefficients(context, symbolName, coefficients);
}
int FunctionNode::getVariables(Context & context, isVariableTest isVariable, char * variables) const {
Expression e = context.expressionForSymbol(Function(this));
return e.getVariables(context, isVariable, variables);
}
float FunctionNode::characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const {
Expression e = context.expressionForSymbol(Function(this));
return e.characteristicXRange(context, angleUnit);
}
Layout FunctionNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const {
char nameString[2] = {name(), 0}; //TODO Fix this when longer name
return LayoutHelper::Prefix(Function(this), floatDisplayMode, numberOfSignificantDigits, nameString);
}
int FunctionNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const {
char nameString[2] = {name(), 0}; //TODO Fix this when longer name
return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, nameString);
}
Expression FunctionNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) {
return Function(this).shallowReduce(context, angleUnit);
}
Evaluation<float> FunctionNode::approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const {
Expression e = context.expressionForSymbol(Function(this));
return e.approximateToEvaluation<float>(context, angleUnit);
}
Evaluation<double> FunctionNode::approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const {
Expression e = context.expressionForSymbol(Function(this));
return e.approximateToEvaluation<double>(context, angleUnit);
}
Function::Function() : Function(TreePool::sharedPool()->createTreeNode<FunctionNode>()) {}
Expression Function::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) {
return Expression::defaultShallowReduce(context, angleUnit);
}
}

View File

@@ -231,6 +231,7 @@ template DivisionNode * Poincare::TreePool::createTreeNode<DivisionNode>(size_t
template DivisionQuotientNode * Poincare::TreePool::createTreeNode<DivisionQuotientNode>(size_t size);
template DivisionRemainderNode * Poincare::TreePool::createTreeNode<DivisionRemainderNode>(size_t size);
template EmptyExpressionNode * Poincare::TreePool::createTreeNode<EmptyExpressionNode>(size_t size);
template FunctionNode * Poincare::TreePool::createTreeNode<FunctionNode>(size_t size);
template HyperbolicArcCosineNode * Poincare::TreePool::createTreeNode<HyperbolicArcCosineNode>(size_t size);
template HyperbolicArcSineNode * Poincare::TreePool::createTreeNode<HyperbolicArcSineNode>(size_t size);
template HyperbolicArcTangentNode * Poincare::TreePool::createTreeNode<HyperbolicArcTangentNode>(size_t size);