mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-21 14:50:44 +01:00
[poincare] Function expression
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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\
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -51,6 +51,7 @@ public:
|
||||
Factor,
|
||||
Floor,
|
||||
FracPart,
|
||||
Function,
|
||||
GreatCommonDivisor,
|
||||
HyperbolicArcCosine,
|
||||
HyperbolicArcSine,
|
||||
|
||||
50
poincare/include/poincare/function.h
Normal file
50
poincare/include/poincare/function.h
Normal 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
|
||||
@@ -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
60
poincare/src/function.cpp
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user