mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
[poincare] Get rid of AngleUnit::Default
This commit is contained in:
@@ -61,9 +61,9 @@ void Calculation::setContent(const char * c, Context * context, Expression * ans
|
||||
/* We do not store directly the text enter by the user because we do not want
|
||||
* to keep Ans symbol in the calculation store. */
|
||||
PoincareHelpers::WriteTextInBuffer(m_input, m_inputText, sizeof(m_inputText));
|
||||
m_exactOutput = Expression::ParseAndSimplify(m_inputText, *context);
|
||||
m_exactOutput = PoincareHelpers::ParseAndSimplify(m_inputText, *context);
|
||||
PoincareHelpers::WriteTextInBuffer(m_exactOutput, m_exactOutputText, sizeof(m_exactOutputText));
|
||||
m_approximateOutput = m_exactOutput->approximate<double>(*context);
|
||||
m_approximateOutput = PoincareHelpers::Approximate<double>(m_exactOutput, *context);
|
||||
PoincareHelpers::WriteTextInBuffer(m_approximateOutput, m_approximateOutputText, sizeof(m_approximateOutputText));
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ Expression * Calculation::approximateOutput(Context * context) {
|
||||
* call 'evaluate'. */
|
||||
Expression * exp = Expression::parse(m_approximateOutputText);
|
||||
if (exp != nullptr) {
|
||||
m_approximateOutput = exp->approximate<double>(*context);
|
||||
m_approximateOutput = PoincareHelpers::Approximate<double>(exp, *context);
|
||||
delete exp;
|
||||
} else {
|
||||
m_approximateOutput = new Undefined();
|
||||
@@ -202,7 +202,7 @@ Calculation::EqualSign Calculation::exactAndApproximateDisplayedOutputsAreEqual(
|
||||
if (m_equalSign != EqualSign::Unknown) {
|
||||
return m_equalSign;
|
||||
}
|
||||
m_equalSign = exactOutput(context)->isEqualToItsApproximationLayout(approximateOutput(context), k_printedExpressionSize, Preferences::sharedPreferences()->displayMode(), Preferences::sharedPreferences()->numberOfSignificantDigits(), *context) ? EqualSign::Equal : EqualSign::Approximation;
|
||||
m_equalSign = exactOutput(context)->isEqualToItsApproximationLayout(approximateOutput(context), k_printedExpressionSize, Preferences::sharedPreferences()->angleUnit(), Preferences::sharedPreferences()->displayMode(), Preferences::sharedPreferences()->numberOfSignificantDigits(), *context) ? EqualSign::Equal : EqualSign::Approximation;
|
||||
return m_equalSign;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
#include "cartesian_function.h"
|
||||
#include "../shared/poincare_helpers.h"
|
||||
#include <float.h>
|
||||
#include <cmath>
|
||||
|
||||
using namespace Poincare;
|
||||
using namespace Shared;
|
||||
|
||||
namespace Graph {
|
||||
|
||||
@@ -27,7 +29,7 @@ double CartesianFunction::approximateDerivative(double x, Poincare::Context * co
|
||||
/* TODO: when we will simplify derivative, we might want to simplify the
|
||||
* derivative here. However, we might want to do it once for all x (to avoid
|
||||
* lagging in the derivative table. */
|
||||
return derivative.approximateToScalar<double>(*context);
|
||||
return PoincareHelpers::ApproximateToScalar<double>(&derivative, *context);
|
||||
}
|
||||
|
||||
double CartesianFunction::sumBetweenBounds(double start, double end, Poincare::Context * context) const {
|
||||
@@ -38,23 +40,23 @@ double CartesianFunction::sumBetweenBounds(double start, double end, Poincare::C
|
||||
/* TODO: when we will simplify integral, we might want to simplify the
|
||||
* integral here. However, we might want to do it once for all x (to avoid
|
||||
* lagging in the derivative table. */
|
||||
return integral.approximateToScalar<double>(*context);
|
||||
return PoincareHelpers::ApproximateToScalar<double>(&integral, *context);
|
||||
}
|
||||
|
||||
Expression::Coordinate2D CartesianFunction::nextMinimumFrom(double start, double step, double max, Context * context) const {
|
||||
return expression(context)->nextMinimum(symbol(), start, step, max, *context);
|
||||
return expression(context)->nextMinimum(symbol(), start, step, max, *context, Preferences::sharedPreferences()->angleUnit());
|
||||
}
|
||||
|
||||
Expression::Coordinate2D CartesianFunction::nextMaximumFrom(double start, double step, double max, Context * context) const {
|
||||
return expression(context)->nextMaximum(symbol(), start, step, max, *context);
|
||||
return expression(context)->nextMaximum(symbol(), start, step, max, *context, Preferences::sharedPreferences()->angleUnit());
|
||||
}
|
||||
|
||||
double CartesianFunction::nextRootFrom(double start, double step, double max, Context * context) const {
|
||||
return expression(context)->nextRoot(symbol(), start, step, max, *context);
|
||||
return expression(context)->nextRoot(symbol(), start, step, max, *context, Preferences::sharedPreferences()->angleUnit());
|
||||
}
|
||||
|
||||
Expression::Coordinate2D CartesianFunction::nextIntersectionFrom(double start, double step, double max, Poincare::Context * context, const Shared::Function * function) const {
|
||||
return expression(context)->nextIntersection(symbol(), start, step, max, *context, function->expression(context));
|
||||
return expression(context)->nextIntersection(symbol(), start, step, max, *context, Preferences::sharedPreferences()->angleUnit(), function->expression(context));
|
||||
}
|
||||
|
||||
char CartesianFunction::symbol() const {
|
||||
|
||||
@@ -44,7 +44,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()));
|
||||
float fRange = f->expression(myApp->localContext())->characteristicXRange(*(myApp->localContext()), Preferences::sharedPreferences()->angleUnit());
|
||||
if (!std::isnan(fRange)) {
|
||||
characteristicRange = fRange > characteristicRange ? fRange : characteristicRange;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "calculation_controller.h"
|
||||
#include "../constant.h"
|
||||
#include "../apps_container.h"
|
||||
#include "../shared/poincare_helpers.h"
|
||||
#include "app.h"
|
||||
#include "calculation/discrete_calculation.h"
|
||||
#include "calculation/left_integral_calculation.h"
|
||||
@@ -208,7 +209,7 @@ bool CalculationController::textFieldShouldFinishEditing(TextField * textField,
|
||||
bool CalculationController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) {
|
||||
App * probaApp = (App *)app();
|
||||
Context * globalContext = probaApp->container()->globalContext();
|
||||
double floatBody = Expression::approximateToScalar<double>(text, *globalContext);
|
||||
double floatBody = PoincareHelpers::ApproximateToScalar<double>(text, *globalContext);
|
||||
if (std::isnan(floatBody) || std::isinf(floatBody)) {
|
||||
app()->displayWarning(I18n::Message::UndefinedValue);
|
||||
return false;
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#include "cubic_model.h"
|
||||
#include "../../shared/poincare_helpers.h"
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
#include "../../poincare/include/poincare_layouts.h"
|
||||
|
||||
using namespace Poincare;
|
||||
using namespace Shared;
|
||||
|
||||
namespace Regression {
|
||||
|
||||
@@ -64,7 +66,7 @@ Expression * CubicModel::simplifiedExpression(double * modelCoefficients, Poinca
|
||||
Expression * dExpression = new Decimal(d);
|
||||
Expression * const operands[] = {ax3Expression, bx2Expression, cxExpression, dExpression};
|
||||
Expression * result = new Addition(operands, 4, false);
|
||||
Expression::Simplify(&result, *context);
|
||||
PoincareHelpers::Simplify(&result, *context);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "model.h"
|
||||
#include "../store.h"
|
||||
#include "../../shared/poincare_helpers.h"
|
||||
#include <poincare/decimal.h>
|
||||
#include <poincare/matrix.h>
|
||||
#include <poincare/multiplication.h>
|
||||
@@ -12,9 +13,9 @@ namespace Regression {
|
||||
|
||||
double Model::levelSet(double * modelCoefficients, double xMin, double step, double xMax, double y, Poincare::Context * context) {
|
||||
Expression * yExpression = static_cast<Expression *>(new Decimal(y));
|
||||
Expression::Simplify(&yExpression, *context);
|
||||
PoincareHelpers::Simplify(&yExpression, *context);
|
||||
Expression * modelExpression = simplifiedExpression(modelCoefficients, context);
|
||||
double result = modelExpression->nextIntersection('x', xMin, step, xMax, *context, yExpression).abscissa;
|
||||
double result = modelExpression->nextIntersection('x', xMin, step, xMax, *context, Preferences::sharedPreferences()->angleUnit(), yExpression).abscissa;
|
||||
delete modelExpression;
|
||||
delete yExpression;
|
||||
return result;
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#include "quadratic_model.h"
|
||||
#include "../../shared/poincare_helpers.h"
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
#include "../../poincare/include/poincare_layouts.h"
|
||||
|
||||
using namespace Poincare;
|
||||
using namespace Shared;
|
||||
|
||||
namespace Regression {
|
||||
|
||||
@@ -48,7 +50,7 @@ Expression * QuadraticModel::simplifiedExpression(double * modelCoefficients, Po
|
||||
Expression * cExpression = new Decimal(c);
|
||||
Expression * const operands[] = {ax2Expression, bxExpression, cExpression};
|
||||
Expression * result = new Addition(operands, 3, false);
|
||||
Expression::Simplify(&result, *context);
|
||||
PoincareHelpers::Simplify(&result, *context);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#include "quartic_model.h"
|
||||
#include "../../shared/poincare_helpers.h"
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
#include "../../poincare/include/poincare_layouts.h"
|
||||
|
||||
using namespace Poincare;
|
||||
using namespace Shared;
|
||||
|
||||
namespace Regression {
|
||||
|
||||
@@ -80,7 +82,7 @@ Expression * QuarticModel::simplifiedExpression(double * modelCoefficients, Poin
|
||||
Expression * eExpression = new Decimal(e);
|
||||
Expression * const operands[] = {ax4Expression, bx3Expression, cx2Expression, dxExpression, eExpression};
|
||||
Expression * result = new Addition(operands, 5, false);
|
||||
Expression::Simplify(&result, *context);
|
||||
PoincareHelpers::Simplify(&result, *context);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#include "trigonometric_model.h"
|
||||
#include "../../shared/poincare_helpers.h"
|
||||
#include "../../poincare/include/poincare_layouts.h"
|
||||
#include <math.h>
|
||||
#include <poincare/preferences.h>
|
||||
#include <assert.h>
|
||||
|
||||
using namespace Poincare;
|
||||
using namespace Shared;
|
||||
|
||||
namespace Regression {
|
||||
|
||||
@@ -50,7 +52,7 @@ Expression * TrigonometricModel::simplifiedExpression(double * modelCoefficients
|
||||
Expression * asinExpression = new Multiplication(aExpression, sinExpression, false);
|
||||
Expression * dExpression = new Decimal(d);
|
||||
Expression * result = new Addition(asinExpression, dExpression, false);
|
||||
Expression::Simplify(&result, *context);
|
||||
PoincareHelpers::Simplify(&result, *context);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ Store::Store() :
|
||||
InteractiveCurveViewRange(nullptr),
|
||||
DoublePairStore(),
|
||||
m_seriesChecksum{0, 0, 0},
|
||||
m_angleUnit(Poincare::Expression::AngleUnit::Default)
|
||||
m_angleUnit(Poincare::Expression::AngleUnit::Degree)
|
||||
{
|
||||
for (int i = 0; i < k_numberOfSeries; i++) {
|
||||
m_regressionTypes[i] = Model::Type::Linear;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "list_controller.h"
|
||||
#include "../app.h"
|
||||
#include "../../apps_container.h"
|
||||
#include "../../shared/poincare_helpers.h"
|
||||
|
||||
using namespace Poincare;
|
||||
using namespace Shared;
|
||||
@@ -126,7 +127,7 @@ bool ListParameterController::textFieldDidFinishEditing(TextField * textField, c
|
||||
* SecondIndex = FirstIndex + 1 */
|
||||
AppsContainer * appsContainer = ((TextFieldDelegateApp *)app())->container();
|
||||
Context * globalContext = appsContainer->globalContext();
|
||||
float floatBody = Expression::approximateToScalar<float>(text, *globalContext);
|
||||
float floatBody = PoincareHelpers::ApproximateToScalar<float>(text, *globalContext);
|
||||
int index = std::round(floatBody);
|
||||
if (std::isnan(floatBody) || std::isinf(floatBody)) {
|
||||
app()->displayWarning(I18n::Message::UndefinedValue);
|
||||
|
||||
@@ -152,14 +152,14 @@ void Sequence::setInitialRank(int rank) {
|
||||
|
||||
Poincare::Expression * Sequence::firstInitialConditionExpression(Context * context) const {
|
||||
if (m_firstInitialConditionExpression == nullptr) {
|
||||
m_firstInitialConditionExpression = Poincare::Expression::ParseAndSimplify(m_firstInitialConditionText, *context);
|
||||
m_firstInitialConditionExpression = PoincareHelpers::ParseAndSimplify(m_firstInitialConditionText, *context);
|
||||
}
|
||||
return m_firstInitialConditionExpression;
|
||||
}
|
||||
|
||||
Poincare::Expression * Sequence::secondInitialConditionExpression(Context * context) const {
|
||||
if (m_secondInitialConditionExpression == nullptr) {
|
||||
m_secondInitialConditionExpression = Poincare::Expression::ParseAndSimplify(m_secondInitialConditionText, *context);
|
||||
m_secondInitialConditionExpression = PoincareHelpers::ParseAndSimplify(m_secondInitialConditionText, *context);
|
||||
}
|
||||
return m_secondInitialConditionExpression;
|
||||
}
|
||||
@@ -336,32 +336,32 @@ T Sequence::approximateToNextRank(int n, SequenceContext * sqctx) const {
|
||||
{
|
||||
ctx.setValueForSymbol(un, &unSymbol);
|
||||
ctx.setValueForSymbol(vn, &vnSymbol);
|
||||
return expression(sqctx)->approximateWithValueForSymbol(symbol(), (T)n, ctx);
|
||||
return expression(sqctx)->approximateWithValueForSymbol(symbol(), (T)n, ctx, Poincare::Preferences::sharedPreferences()->angleUnit());
|
||||
}
|
||||
case Type::SingleRecurrence:
|
||||
{
|
||||
if (n == m_initialRank) {
|
||||
return firstInitialConditionExpression(sqctx)->template approximateToScalar<T>(*sqctx);
|
||||
return PoincareHelpers::ApproximateToScalar<T>(firstInitialConditionExpression(sqctx), *sqctx);
|
||||
}
|
||||
ctx.setValueForSymbol(un, &un1Symbol);
|
||||
ctx.setValueForSymbol(unm1, &unSymbol);
|
||||
ctx.setValueForSymbol(vn, &vn1Symbol);
|
||||
ctx.setValueForSymbol(vnm1, &vnSymbol);
|
||||
return expression(sqctx)->approximateWithValueForSymbol(symbol(), (T)(n-1), ctx);
|
||||
return expression(sqctx)->approximateWithValueForSymbol(symbol(), (T)(n-1), ctx, Poincare::Preferences::sharedPreferences()->angleUnit());
|
||||
}
|
||||
default:
|
||||
{
|
||||
if (n == m_initialRank) {
|
||||
return firstInitialConditionExpression(sqctx)->template approximateToScalar<T>(*sqctx);
|
||||
return PoincareHelpers::ApproximateToScalar<T>(firstInitialConditionExpression(sqctx), *sqctx);
|
||||
}
|
||||
if (n == m_initialRank+1) {
|
||||
return secondInitialConditionExpression(sqctx)->template approximateToScalar<T>(*sqctx);
|
||||
return PoincareHelpers::ApproximateToScalar<T>(secondInitialConditionExpression(sqctx), *sqctx);
|
||||
}
|
||||
ctx.setValueForSymbol(unm1, &un1Symbol);
|
||||
ctx.setValueForSymbol(unm2, &unSymbol);
|
||||
ctx.setValueForSymbol(vnm1, &vn1Symbol);
|
||||
ctx.setValueForSymbol(vnm2, &vnSymbol);
|
||||
return expression(sqctx)->approximateWithValueForSymbol(symbol(), (T)(n-2), ctx);
|
||||
return expression(sqctx)->approximateWithValueForSymbol(symbol(), (T)(n-2), ctx, Poincare::Preferences::sharedPreferences()->angleUnit());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
#include "helpers.h"
|
||||
#include "../global_preferences.h"
|
||||
#include "../apps_container.h"
|
||||
#include "../shared/poincare_helpers.h"
|
||||
#include <assert.h>
|
||||
#include <cmath>
|
||||
|
||||
using namespace Poincare;
|
||||
using namespace Shared;
|
||||
|
||||
namespace Settings {
|
||||
|
||||
@@ -217,7 +219,7 @@ bool SubController::textFieldShouldFinishEditing(TextField * textField, Ion::Eve
|
||||
|
||||
bool SubController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) {
|
||||
Context * globalContext = textFieldDelegateApp()->localContext();
|
||||
float floatBody = Expression::approximateToScalar<float>(text, *globalContext);
|
||||
float floatBody = PoincareHelpers::ApproximateToScalar<float>(text, *globalContext);
|
||||
if (std::isnan(floatBody) || std::isinf(floatBody)) {
|
||||
floatBody = PrintFloat::k_numberOfPrintedSignificantDigits;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "editable_cell_table_view_controller.h"
|
||||
#include "../apps_container.h"
|
||||
#include "../shared/poincare_helpers.h"
|
||||
#include "../constant.h"
|
||||
#include "text_field_delegate_app.h"
|
||||
#include <assert.h>
|
||||
@@ -25,7 +26,7 @@ bool EditableCellTableViewController::textFieldShouldFinishEditing(TextField * t
|
||||
bool EditableCellTableViewController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) {
|
||||
AppsContainer * appsContainer = ((TextFieldDelegateApp *)app())->container();
|
||||
Context * globalContext = appsContainer->globalContext();
|
||||
double floatBody = Expression::approximateToScalar<double>(text, *globalContext);
|
||||
double floatBody = PoincareHelpers::ApproximateToScalar<double>(text, *globalContext);
|
||||
if (std::isnan(floatBody) || std::isinf(floatBody)) {
|
||||
app()->displayWarning(I18n::Message::UndefinedValue);
|
||||
return false;
|
||||
|
||||
@@ -40,7 +40,7 @@ const char * ExpressionModel::text() const {
|
||||
|
||||
Poincare::Expression * ExpressionModel::expression(Poincare::Context * context) const {
|
||||
if (m_expression == nullptr) {
|
||||
m_expression = Expression::ParseAndSimplify(m_text, *context);
|
||||
m_expression = PoincareHelpers::ParseAndSimplify(m_text, *context);
|
||||
}
|
||||
return m_expression;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "float_parameter_controller.h"
|
||||
#include "../constant.h"
|
||||
#include "../apps_container.h"
|
||||
#include "../shared/poincare_helpers.h"
|
||||
#include "text_field_delegate_app.h"
|
||||
#include <assert.h>
|
||||
#include <cmath>
|
||||
@@ -119,7 +120,7 @@ bool FloatParameterController::textFieldShouldFinishEditing(TextField * textFiel
|
||||
bool FloatParameterController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) {
|
||||
AppsContainer * appsContainer = ((TextFieldDelegateApp *)app())->container();
|
||||
Context * globalContext = appsContainer->globalContext();
|
||||
double floatBody = Expression::approximateToScalar<double>(text, *globalContext);
|
||||
double floatBody = PoincareHelpers::ApproximateToScalar<double>(text, *globalContext);
|
||||
if (std::isnan(floatBody) || std::isinf(floatBody)) {
|
||||
app()->displayWarning(I18n::Message::UndefinedValue);
|
||||
return false;
|
||||
|
||||
@@ -41,7 +41,7 @@ void Function::setActive(bool active) {
|
||||
|
||||
template<typename T>
|
||||
T Function::templatedApproximateAtAbscissa(T x, Poincare::Context * context) const {
|
||||
return expression(context)->approximateWithValueForSymbol(symbol(), x, *context);
|
||||
return expression(context)->approximateWithValueForSymbol(symbol(), x, *context, Preferences::sharedPreferences()->angleUnit());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,6 +20,29 @@ inline int WriteTextInBuffer(const Poincare::Expression * e, char * buffer, int
|
||||
return e->writeTextInBuffer(buffer, bufferSize, Poincare::Preferences::sharedPreferences()->displayMode(), numberOfSignificantDigits);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline Poincare::Expression * Approximate(const Poincare::Expression * e, Poincare::Context & context) {
|
||||
return e->approximate<T>(context, Poincare::Preferences::sharedPreferences()->angleUnit(), Poincare::Preferences::sharedPreferences()->complexFormat());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T ApproximateToScalar(const Poincare::Expression * e, Poincare::Context & context) {
|
||||
return e->approximateToScalar<T>(context, Poincare::Preferences::sharedPreferences()->angleUnit());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T ApproximateToScalar(const char * text, Poincare::Context & context) {
|
||||
return Poincare::Expression::approximateToScalar<T>(text, context, Poincare::Preferences::sharedPreferences()->angleUnit());
|
||||
}
|
||||
|
||||
inline Poincare::Expression * ParseAndSimplify(const char * text, Poincare::Context & context) {
|
||||
return Poincare::Expression::ParseAndSimplify(text, context, Poincare::Preferences::sharedPreferences()->angleUnit());
|
||||
}
|
||||
|
||||
inline void Simplify(Poincare::Expression ** expressionAddress, Poincare::Context & context) {
|
||||
return Poincare::Expression::Simplify(expressionAddress, context, Poincare::Preferences::sharedPreferences()->angleUnit());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "store_controller.h"
|
||||
#include "../apps_container.h"
|
||||
#include "../shared/poincare_helpers.h"
|
||||
#include "../constant.h"
|
||||
#include <escher/metric.h>
|
||||
#include <assert.h>
|
||||
@@ -85,7 +86,7 @@ bool StoreController::textFieldDidFinishEditing(TextField * textField, const cha
|
||||
}
|
||||
AppsContainer * appsContainer = ((TextFieldDelegateApp *)app())->container();
|
||||
Context * globalContext = appsContainer->globalContext();
|
||||
double floatBody = Expression::approximateToScalar<double>(text, *globalContext);
|
||||
double floatBody = PoincareHelpers::ApproximateToScalar<double>(text, *globalContext);
|
||||
if (std::isnan(floatBody) || std::isinf(floatBody)) {
|
||||
app()->displayWarning(I18n::Message::UndefinedValue);
|
||||
return false;
|
||||
@@ -299,7 +300,7 @@ bool StoreController::privateFillColumnWithFormula(Expression * formula, Express
|
||||
// Set the context
|
||||
store->setSeriesPairIndex(j);
|
||||
// Compute the new value using the formula
|
||||
double evaluation = formula->approximateToScalar<double>(*store);
|
||||
double evaluation = PoincareHelpers::ApproximateToScalar<double>(formula, *store);
|
||||
if (std::isnan(evaluation) || std::isinf(evaluation)) {
|
||||
app()->displayWarning(I18n::Message::DataNotSuitable);
|
||||
return false;
|
||||
@@ -309,7 +310,7 @@ bool StoreController::privateFillColumnWithFormula(Expression * formula, Express
|
||||
// Fill in the table with the formula values
|
||||
for (int j = 0; j < numberOfValuesToCompute; j++) {
|
||||
store->setSeriesPairIndex(j);
|
||||
double evaluation = formula->approximateToScalar<double>(*store);
|
||||
double evaluation = PoincareHelpers::ApproximateToScalar<double>(formula, *store);
|
||||
setDataAtLocation(evaluation, currentColumn, j + 1);
|
||||
}
|
||||
selectableTableView()->reloadData();
|
||||
|
||||
@@ -127,7 +127,7 @@ void SumGraphController::setFunction(Function * function) {
|
||||
bool SumGraphController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) {
|
||||
AppsContainer * appsContainer = ((TextFieldDelegateApp *)app())->container();
|
||||
Context * globalContext = appsContainer->globalContext();
|
||||
double floatBody = Expression::approximateToScalar<double>(text, *globalContext);
|
||||
double floatBody = PoincareHelpers::ApproximateToScalar<double>(text, *globalContext);
|
||||
if (std::isnan(floatBody) || std::isinf(floatBody)) {
|
||||
app()->displayWarning(I18n::Message::UndefinedValue);
|
||||
return false;
|
||||
|
||||
@@ -37,7 +37,7 @@ Expression * Equation::standardForm(Context * context) const {
|
||||
if (m_standardForm == nullptr) {
|
||||
Expression * e = expression(context);
|
||||
if (e->type() == Expression::Type::Equal) {
|
||||
m_standardForm = static_cast<const Equal *>(e)->standardEquation(*context);
|
||||
m_standardForm = static_cast<const Equal *>(e)->standardEquation(*context, Preferences::sharedPreferences()->angleUnit());
|
||||
} else if (e->type() == Expression::Type::Rational && static_cast<Rational *>(e)->isOne()) {
|
||||
// The equality was reduced which means the equality was always true.
|
||||
m_standardForm = new Rational(0);
|
||||
|
||||
@@ -69,7 +69,7 @@ bool EquationStore::haveMoreApproximationSolutions(Context * context) {
|
||||
return false;
|
||||
}
|
||||
double step = (m_intervalApproximateSolutions[1]-m_intervalApproximateSolutions[0])*k_precision;
|
||||
return !std::isnan(definedModelAtIndex(0)->standardForm(context)->nextRoot(m_variables[0], m_approximateSolutions[m_numberOfSolutions-1], step, m_intervalApproximateSolutions[1], *context));
|
||||
return !std::isnan(definedModelAtIndex(0)->standardForm(context)->nextRoot(m_variables[0], m_approximateSolutions[m_numberOfSolutions-1], step, m_intervalApproximateSolutions[1], *context, Preferences::sharedPreferences()->angleUnit()));
|
||||
}
|
||||
|
||||
void EquationStore::approximateSolve(Poincare::Context * context) {
|
||||
@@ -79,7 +79,7 @@ void EquationStore::approximateSolve(Poincare::Context * context) {
|
||||
double start = m_intervalApproximateSolutions[0];
|
||||
double step = (m_intervalApproximateSolutions[1]-m_intervalApproximateSolutions[0])*k_precision;
|
||||
for (int i = 0; i < k_maxNumberOfApproximateSolutions; i++) {
|
||||
m_approximateSolutions[i] = definedModelAtIndex(0)->standardForm(context)->nextRoot(m_variables[0], start, step, m_intervalApproximateSolutions[1], *context);
|
||||
m_approximateSolutions[i] = definedModelAtIndex(0)->standardForm(context)->nextRoot(m_variables[0], start, step, m_intervalApproximateSolutions[1], *context, Preferences::sharedPreferences()->angleUnit());
|
||||
if (std::isnan(m_approximateSolutions[i])) {
|
||||
break;
|
||||
} else {
|
||||
@@ -112,7 +112,7 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) {
|
||||
Expression * constants[k_maxNumberOfEquations];
|
||||
bool isLinear = true; // Invalid the linear system if one equation is non-linear
|
||||
for (int i = 0; i < numberOfDefinedModels(); i++) {
|
||||
isLinear = isLinear && definedModelAtIndex(i)->standardForm(context)->getLinearCoefficients(m_variables, coefficients[i], &constants[i], *context);
|
||||
isLinear = isLinear && definedModelAtIndex(i)->standardForm(context)->getLinearCoefficients(m_variables, coefficients[i], &constants[i], *context, Preferences::sharedPreferences()->angleUnit());
|
||||
// Clean allocated memory if the system is not linear
|
||||
if (!isLinear) {
|
||||
for (int j = 0; j < i; j++) {
|
||||
@@ -144,7 +144,7 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) {
|
||||
assert(numberOfVariables == 1 && numberOfDefinedModels() == 1);
|
||||
char x = m_variables[0];
|
||||
Expression * polynomialCoefficients[Expression::k_maxNumberOfPolynomialCoefficients];
|
||||
int degree = definedModelAtIndex(0)->standardForm(context)->getPolynomialCoefficients(x, polynomialCoefficients, *context);
|
||||
int degree = definedModelAtIndex(0)->standardForm(context)->getPolynomialCoefficients(x, polynomialCoefficients, *context, Preferences::sharedPreferences()->angleUnit());
|
||||
if (degree == 2) {
|
||||
/* Polynomial degree <= 2*/
|
||||
m_type = Type::PolynomialMonovariable;
|
||||
@@ -161,7 +161,7 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) {
|
||||
for (int i = 0; i < k_maxNumberOfExactSolutions; i++) {
|
||||
if (exactSolutions[i]) {
|
||||
m_exactSolutionExactLayouts[i] = PoincareHelpers::CreateLayout(exactSolutions[i]);
|
||||
Expression * approximate = exactSolutions[i]->approximate<double>(*context);
|
||||
Expression * approximate = PoincareHelpers::Approximate<double>(exactSolutions[i], *context);
|
||||
m_exactSolutionApproximateLayouts[i] = PoincareHelpers::CreateLayout(approximate);
|
||||
/* Check for identity between exact and approximate layouts */
|
||||
char exactBuffer[Shared::ExpressionModel::k_expressionBufferSize];
|
||||
@@ -171,7 +171,7 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) {
|
||||
m_exactSolutionIdentity[i] = strcmp(exactBuffer, approximateBuffer) == 0;
|
||||
/* Check for equality between exact and approximate layouts */
|
||||
if (!m_exactSolutionIdentity[i]) {
|
||||
m_exactSolutionEquality[i] = exactSolutions[i]->isEqualToItsApproximationLayout(approximate, Shared::ExpressionModel::k_expressionBufferSize, Preferences::sharedPreferences()->displayMode(), Preferences::sharedPreferences()->numberOfSignificantDigits(), *context);
|
||||
m_exactSolutionEquality[i] = exactSolutions[i]->isEqualToItsApproximationLayout(approximate, Shared::ExpressionModel::k_expressionBufferSize, Preferences::sharedPreferences()->angleUnit(), Preferences::sharedPreferences()->displayMode(), Preferences::sharedPreferences()->numberOfSignificantDigits(), *context);
|
||||
}
|
||||
delete approximate;
|
||||
delete exactSolutions[i];
|
||||
@@ -222,7 +222,7 @@ EquationStore::Error EquationStore::resolveLinearSystem(Expression * exactSoluti
|
||||
Expression * sol = Ab->matrixOperand(i,n);
|
||||
exactSolutions[i] = sol;
|
||||
Ab->detachOperand(sol);
|
||||
Expression::Simplify(&exactSolutions[i], *context);
|
||||
PoincareHelpers::Simplify(&exactSolutions[i], *context);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -237,7 +237,7 @@ EquationStore::Error EquationStore::oneDimensialPolynomialSolve(Expression * exa
|
||||
Expression * deltaSubOperand[3] = {new Rational(4), coefficients[0]->clone(), coefficients[2]->clone()};
|
||||
// Compute delta = b*b-4ac
|
||||
Expression * delta = new Subtraction(new Power(coefficients[1]->clone(), new Rational(2), false), new Multiplication(deltaSubOperand, 3, false), false);
|
||||
Expression::Simplify(&delta, *context);
|
||||
PoincareHelpers::Simplify(&delta, *context);
|
||||
if (delta->isRationalZero()) {
|
||||
// if delta = 0, x0=x1= -b/(2a)
|
||||
exactSolutions[0] = new Division(new Opposite(coefficients[1], false), new Multiplication(new Rational(2), coefficients[2], false), false);
|
||||
@@ -252,7 +252,7 @@ EquationStore::Error EquationStore::oneDimensialPolynomialSolve(Expression * exa
|
||||
exactSolutions[m_numberOfSolutions] = delta;
|
||||
delete coefficients[0];
|
||||
for (int i = 0; i < m_numberOfSolutions; i++) {
|
||||
Expression::Simplify(&exactSolutions[i], *context);
|
||||
PoincareHelpers::Simplify(&exactSolutions[i], *context);
|
||||
}
|
||||
return Error::NoError;
|
||||
#if 0
|
||||
@@ -269,7 +269,7 @@ EquationStore::Error EquationStore::oneDimensialPolynomialSolve(Expression * exa
|
||||
Expression * mult4Operands[3] = {new Rational(-4), d->clone(), new Power(b->clone(), new Rational(3), false)};
|
||||
Expression * add0Operands[5] = {new Multiplication(mult0Operands, 2, false), new Multiplication(mult1Operands, 5, false), new Multiplication(mult2Operands, 3, false), new Multiplication(mult3Operands, 3, false), new Multiplication(mult4Operands, 3, false)};
|
||||
Expression * delta = new Addition(add0Operands, 5, false);
|
||||
Simplify(&delta, *context);
|
||||
PoincareHelpers::Simplify(&delta, *context);
|
||||
// Delta0 = b^2-3ac
|
||||
Expression * mult5Operands[3] = {new Rational(3), a->clone(), c->clone()};
|
||||
Expression * delta0 = new Subtraction(new Power(b->clone(), new Rational(2), false), new Multiplication(mult5Operands, 3, false), false);
|
||||
|
||||
@@ -15,7 +15,7 @@ class Cosine : public StaticHierarchy<1>::StaticHierarchy {
|
||||
public:
|
||||
Type type() const override;
|
||||
Expression * clone() const override;
|
||||
float characteristicXRange(Context & context, AngleUnit angleUnit = AngleUnit::Default) const override;
|
||||
float characteristicXRange(Context & context, AngleUnit angleUnit) const override;
|
||||
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, AngleUnit angleUnit = AngleUnit::Radian) {
|
||||
return Trigonometry::computeOnComplex(c, angleUnit, std::cos);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ public:
|
||||
Expression * clone() const override;
|
||||
int polynomialDegree(char symbolName) const override;
|
||||
// For the equation A = B, create the reduced expression A-B
|
||||
Expression * standardEquation(Context & context, AngleUnit angleUnit = AngleUnit::Default) const;
|
||||
Expression * standardEquation(Context & context, AngleUnit angleUnit) const;
|
||||
private:
|
||||
/* Simplification */
|
||||
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
|
||||
|
||||
@@ -151,12 +151,10 @@ public:
|
||||
enum class ComplexFormat {
|
||||
Cartesian = 0,
|
||||
Polar = 1,
|
||||
Default = 2
|
||||
};
|
||||
enum class AngleUnit {
|
||||
Degree = 0,
|
||||
Radian = 1,
|
||||
Default = 2
|
||||
};
|
||||
|
||||
/* Constructor & Destructor */
|
||||
@@ -208,7 +206,7 @@ public:
|
||||
* the return value is NAN.
|
||||
* NB: so far, we consider that the only way of building a periodic function
|
||||
* is to use sin/tan/cos(f(x)) with f a linear function. */
|
||||
virtual float characteristicXRange(Context & context, AngleUnit angleUnit = AngleUnit::Default) const;
|
||||
virtual float characteristicXRange(Context & context, AngleUnit angleUnit) const;
|
||||
static bool IsMatrix(const Expression * e, Context & context);
|
||||
|
||||
/* polynomialDegree returns:
|
||||
@@ -227,14 +225,14 @@ public:
|
||||
* the variables hold in 'variables'. Otherwise, it fills 'coefficients' with
|
||||
* the coefficients of the variables hold in 'variables' (following the same
|
||||
* order) and 'constant' with the constant of the expression. */
|
||||
bool getLinearCoefficients(char * variables, Expression * coefficients[], Expression * constant[], Context & context) const;
|
||||
bool getLinearCoefficients(char * variables, Expression * coefficients[], Expression * constant[], Context & context, AngleUnit angleUnit) const;
|
||||
/* getPolynomialCoefficients fills the table coefficients with the expressions
|
||||
* of the first 3 polynomial coefficients and return polynomialDegree.
|
||||
* coefficients has up to 3 entries. It supposed to be called on Reduced
|
||||
* expression. */
|
||||
static constexpr int k_maxPolynomialDegree = 2;
|
||||
static constexpr int k_maxNumberOfPolynomialCoefficients = k_maxPolynomialDegree+1;
|
||||
int getPolynomialCoefficients(char symbolName, Expression * coefficients[], Context & context) const;
|
||||
int getPolynomialCoefficients(char symbolName, Expression * coefficients[], Context & context, AngleUnit angleUnit) const;
|
||||
|
||||
/* Comparison */
|
||||
/* isIdenticalTo is the "easy" equality, it returns true if both trees have
|
||||
@@ -245,34 +243,34 @@ public:
|
||||
* order on expresssions. */
|
||||
return SimplificationOrder(this, e, true) == 0;
|
||||
}
|
||||
bool isEqualToItsApproximationLayout(Expression * approximation, int bufferSize, PrintFloat::Mode floatDisplayMode, int numberOfSignificantDigits, Context & context);
|
||||
bool isEqualToItsApproximationLayout(Expression * approximation, int bufferSize, AngleUnit angleUnit, PrintFloat::Mode floatDisplayMode, int numberOfSignificantDigits, Context & context);
|
||||
|
||||
/* Layout Engine */
|
||||
virtual ExpressionLayout * createLayout(PrintFloat::Mode floatDisplayMode, int numberOfSignificantDigits) const = 0; // Returned object must be deleted
|
||||
virtual int writeTextInBuffer(char * buffer, int bufferSize, PrintFloat::Mode floatDisplayMode, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const = 0;
|
||||
|
||||
/* Simplification */
|
||||
static Expression * ParseAndSimplify(const char * text, Context & context, AngleUnit angleUnit = AngleUnit::Default);
|
||||
static void Simplify(Expression ** expressionAddress, Context & context, AngleUnit angleUnit = AngleUnit::Default);
|
||||
static void Reduce(Expression ** expressionAddress, Context & context, AngleUnit angleUnit = AngleUnit::Default, bool recursively = true);
|
||||
static Expression * ParseAndSimplify(const char * text, Context & context, AngleUnit angleUnit);
|
||||
static void Simplify(Expression ** expressionAddress, Context & context, AngleUnit angleUnit);
|
||||
static void Reduce(Expression ** expressionAddress, Context & context, AngleUnit angleUnit, bool recursively = true);
|
||||
|
||||
/* Evaluation Engine */
|
||||
/* The function approximate creates a new expression and thus mallocs memory.
|
||||
* Do not forget to delete the new expression to avoid leaking. */
|
||||
template<typename T> Expression * approximate(Context& context, AngleUnit angleUnit = AngleUnit::Default, ComplexFormat complexFormat = ComplexFormat::Default) const;
|
||||
template<typename T> T approximateToScalar(Context& context, AngleUnit angleUnit = AngleUnit::Default, ComplexFormat complexFormat = ComplexFormat::Default) const;
|
||||
template<typename T> static T approximateToScalar(const char * text, Context& context, AngleUnit angleUnit = AngleUnit::Default, ComplexFormat complexFormat = ComplexFormat::Default);
|
||||
template<typename T> T approximateWithValueForSymbol(char symbol, T x, Context & context) const;
|
||||
template<typename T> Expression * approximate(Context& context, AngleUnit angleUnit, ComplexFormat complexFormat) const;
|
||||
template<typename T> T approximateToScalar(Context& context, AngleUnit angleUnit) const;
|
||||
template<typename T> static T approximateToScalar(const char * text, Context& context, AngleUnit angleUnit);
|
||||
template<typename T> T approximateWithValueForSymbol(char symbol, T x, Context & context, AngleUnit angleUnit) const;
|
||||
|
||||
/* Expression roots/extrema solver*/
|
||||
struct Coordinate2D {
|
||||
double abscissa;
|
||||
double value;
|
||||
};
|
||||
Coordinate2D nextMinimum(char symbol, double start, double step, double max, Context & context) const;
|
||||
Coordinate2D nextMaximum(char symbol, double start, double step, double max, Context & context) const;
|
||||
double nextRoot(char symbol, double start, double step, double max, Context & context) const;
|
||||
Coordinate2D nextIntersection(char symbol, double start, double step, double max, Context & context, const Expression * expression) const;
|
||||
Coordinate2D nextMinimum(char symbol, double start, double step, double max, Context & context, AngleUnit angleUnit) const;
|
||||
Coordinate2D nextMaximum(char symbol, double start, double step, double max, Context & context, AngleUnit angleUnit) const;
|
||||
double nextRoot(char symbol, double start, double step, double max, Context & context, AngleUnit angleUnit) const;
|
||||
Coordinate2D nextIntersection(char symbol, double start, double step, double max, Context & context, AngleUnit angleUnit, const Expression * expression) const;
|
||||
|
||||
/* Evaluation engine */
|
||||
template<typename T> static T epsilon();
|
||||
@@ -337,13 +335,13 @@ private:
|
||||
constexpr static double k_sqrtEps = 1.4901161193847656E-8; // sqrt(DBL_EPSILON)
|
||||
constexpr static double k_goldenRatio = 0.381966011250105151795413165634361882279690820194237137864; // (3-sqrt(5))/2
|
||||
constexpr static double k_maxFloat = 1e100;
|
||||
typedef double (*EvaluationAtAbscissa)(char symbol, double abscissa, Context & context, const Expression * expression0, const Expression * expression1);
|
||||
Coordinate2D nextMinimumOfExpression(char symbol, double start, double step, double max, EvaluationAtAbscissa evaluation, Context & context, const Expression * expression = nullptr, bool lookForRootMinimum = false) const;
|
||||
void bracketMinimum(char symbol, double start, double step, double max, double result[3], EvaluationAtAbscissa evaluation, Context & context, const Expression * expression = nullptr) const;
|
||||
Coordinate2D brentMinimum(char symbol, double ax, double bx, EvaluationAtAbscissa evaluation, Context & context, const Expression * expression = nullptr) const;
|
||||
double nextIntersectionWithExpression(char symbol, double start, double step, double max, EvaluationAtAbscissa evaluation, Context & context, const Expression * expression) const;
|
||||
void bracketRoot(char symbol, double start, double step, double max, double result[2], EvaluationAtAbscissa evaluation, Context & context, const Expression * expression) const;
|
||||
double brentRoot(char symbol, double ax, double bx, double precision, EvaluationAtAbscissa evaluation, Context & context, const Expression * expression) const;
|
||||
typedef double (*EvaluationAtAbscissa)(char symbol, double abscissa, Context & context, AngleUnit angleUnit, const Expression * expression0, const Expression * expression1);
|
||||
Coordinate2D nextMinimumOfExpression(char symbol, double start, double step, double max, EvaluationAtAbscissa evaluation, Context & context, AngleUnit angleUnit, const Expression * expression = nullptr, bool lookForRootMinimum = false) const;
|
||||
void bracketMinimum(char symbol, double start, double step, double max, double result[3], EvaluationAtAbscissa evaluation, Context & context, AngleUnit angleUnit, const Expression * expression = nullptr) const;
|
||||
Coordinate2D brentMinimum(char symbol, double ax, double bx, EvaluationAtAbscissa evaluation, Context & context, AngleUnit angleUnit, const Expression * expression = nullptr) const;
|
||||
double nextIntersectionWithExpression(char symbol, double start, double step, double max, EvaluationAtAbscissa evaluation, Context & context, AngleUnit angleUnit, const Expression * expression) const;
|
||||
void bracketRoot(char symbol, double start, double step, double max, double result[2], EvaluationAtAbscissa evaluation, Context & context, AngleUnit angleUnit, const Expression * expression) const;
|
||||
double brentRoot(char symbol, double ax, double bx, double precision, EvaluationAtAbscissa evaluation, Context & context, AngleUnit angleUnit, const Expression * expression) const;
|
||||
|
||||
Expression * m_parent;
|
||||
};
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Poincare {
|
||||
class Sine : public StaticHierarchy<1> {
|
||||
using StaticHierarchy<1>::StaticHierarchy;
|
||||
friend class Tangent;
|
||||
float characteristicXRange(Context & context, AngleUnit angleUnit = AngleUnit::Default) const override;
|
||||
float characteristicXRange(Context & context, AngleUnit angleUnit) const override;
|
||||
public:
|
||||
Type type() const override;
|
||||
Expression * clone() const override;
|
||||
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
static bool isSeriesSymbol(char c);
|
||||
static bool isRegressionSymbol(char c);
|
||||
bool isApproximate(Context & context) const;
|
||||
float characteristicXRange(Context & context, AngleUnit angleUnit = AngleUnit::Default) const override;
|
||||
float characteristicXRange(Context & context, AngleUnit angleUnit) const override;
|
||||
bool hasAnExactRepresentation(Context & context) const;
|
||||
static const char * textForSpecialSymbols(char name);
|
||||
int getVariables(isVariableTest isVariable, char * variables) const override;
|
||||
|
||||
@@ -13,7 +13,7 @@ class Tangent : public StaticHierarchy<1> {
|
||||
public:
|
||||
Type type() const override;
|
||||
Expression * clone() const override;
|
||||
float characteristicXRange(Context & context, AngleUnit angleUnit = AngleUnit::Default) const override;
|
||||
float characteristicXRange(Context & context, AngleUnit angleUnit) const override;
|
||||
private:
|
||||
/* Layout */
|
||||
ExpressionLayout * createLayout(PrintFloat::Mode floatDisplayMode, int numberOfSignificantDigits) const override {
|
||||
|
||||
@@ -32,7 +32,6 @@ Expression * ArcCosine::shallowReduce(Context& context, AngleUnit angleUnit) {
|
||||
|
||||
template<typename T>
|
||||
std::complex<T> ArcCosine::computeOnComplex(const std::complex<T> c, AngleUnit angleUnit) {
|
||||
assert(angleUnit != AngleUnit::Default);
|
||||
std::complex<T> result = std::acos(c);
|
||||
if (angleUnit == AngleUnit::Degree && result.imag() == 0.0) {
|
||||
result *= 180/M_PI;
|
||||
|
||||
@@ -32,7 +32,6 @@ Expression * ArcSine::shallowReduce(Context& context, AngleUnit angleUnit) {
|
||||
|
||||
template<typename T>
|
||||
std::complex<T> ArcSine::computeOnComplex(const std::complex<T> c, AngleUnit angleUnit) {
|
||||
assert(angleUnit != AngleUnit::Default);
|
||||
std::complex<T> result = std::asin(c);
|
||||
if (angleUnit == AngleUnit::Degree && result.imag() == 0.0) {
|
||||
result *= 180/M_PI;
|
||||
|
||||
@@ -32,7 +32,6 @@ Expression * ArcTangent::shallowReduce(Context& context, AngleUnit angleUnit) {
|
||||
|
||||
template<typename T>
|
||||
std::complex<T> ArcTangent::computeOnComplex(const std::complex<T> c, AngleUnit angleUnit) {
|
||||
assert(angleUnit != AngleUnit::Default);
|
||||
std::complex<T> result = std::atan(c);
|
||||
if (angleUnit == AngleUnit::Degree && result.imag() == 0.0) {
|
||||
result *= 180/M_PI;
|
||||
|
||||
@@ -50,7 +50,7 @@ Complex<T> * Derivative::templatedApproximate(Context& context, AngleUnit angleU
|
||||
Evaluation<T> * xInput = operand(1)->privateApproximate(T(), context, angleUnit);
|
||||
T x = xInput->toScalar();
|
||||
delete xInput;
|
||||
T functionValue = operand(0)->approximateWithValueForSymbol('x', x, context);
|
||||
T functionValue = operand(0)->approximateWithValueForSymbol('x', x, context, angleUnit);
|
||||
// No complex/matrix version of Derivative
|
||||
if (std::isnan(x) || std::isnan(functionValue)) {
|
||||
return new Complex<T>(Complex<T>::Undefined());
|
||||
@@ -76,8 +76,8 @@ Complex<T> * Derivative::templatedApproximate(Context& context, AngleUnit angleU
|
||||
|
||||
template<typename T>
|
||||
T Derivative::growthRateAroundAbscissa(T x, T h, Context & context, AngleUnit angleUnit) const {
|
||||
T expressionPlus = operand(0)->approximateWithValueForSymbol('x', x+h, context);
|
||||
T expressionMinus = operand(0)->approximateWithValueForSymbol('x', x-h, context);
|
||||
T expressionPlus = operand(0)->approximateWithValueForSymbol('x', x+h, context, angleUnit);
|
||||
T expressionMinus = operand(0)->approximateWithValueForSymbol('x', x-h, context, angleUnit);
|
||||
return (expressionPlus - expressionMinus)/(2*h);
|
||||
}
|
||||
|
||||
|
||||
@@ -190,9 +190,6 @@ bool Expression::isApproximate(Context & context) const {
|
||||
}
|
||||
|
||||
float Expression::characteristicXRange(Context & context, AngleUnit angleUnit) const {
|
||||
if (angleUnit == AngleUnit::Default) {
|
||||
angleUnit = Preferences::sharedPreferences()->angleUnit();
|
||||
}
|
||||
/* A expression has a characteristic range if at least one of its operand has
|
||||
* one and the other are x-independant. We keep the biggest interesting range
|
||||
* among the operand interesting ranges. */
|
||||
@@ -237,7 +234,7 @@ bool dependsOnVariables(const Expression * e, Context & context) {
|
||||
return e->type() == Expression::Type::Symbol && Symbol::isVariableSymbol(static_cast<const Symbol *>(e)->name());
|
||||
}
|
||||
|
||||
bool Expression::getLinearCoefficients(char * variables, Expression * coefficients[], Expression ** constant, Context & context) const {
|
||||
bool Expression::getLinearCoefficients(char * variables, Expression * coefficients[], Expression ** constant, Context & context, AngleUnit angleUnit) const {
|
||||
char * x = variables;
|
||||
while (*x != 0) {
|
||||
int degree = polynomialDegree(*x);
|
||||
@@ -251,7 +248,7 @@ bool Expression::getLinearCoefficients(char * variables, Expression * coefficien
|
||||
int index = 0;
|
||||
Expression * polynomialCoefficients[k_maxNumberOfPolynomialCoefficients];
|
||||
while (*x != 0) {
|
||||
int degree = equation->getPolynomialCoefficients(*x, polynomialCoefficients, context);
|
||||
int degree = equation->getPolynomialCoefficients(*x, polynomialCoefficients, context, angleUnit);
|
||||
if (degree == 1) {
|
||||
coefficients[index] = polynomialCoefficients[1];
|
||||
} else {
|
||||
@@ -264,7 +261,7 @@ bool Expression::getLinearCoefficients(char * variables, Expression * coefficien
|
||||
index++;
|
||||
}
|
||||
*constant = new Opposite(equation, false);
|
||||
Reduce(constant, context);
|
||||
Reduce(constant, context, angleUnit);
|
||||
/* The expression can be linear on all coefficients taken one by one but
|
||||
* non-linear (ex: xy = 2). We delete the results and return false if one of
|
||||
* the coefficients contains a variable. */
|
||||
@@ -287,10 +284,10 @@ bool Expression::getLinearCoefficients(char * variables, Expression * coefficien
|
||||
return true;
|
||||
}
|
||||
|
||||
int Expression::getPolynomialCoefficients(char symbolName, Expression * coefficients[], Context & context) const {
|
||||
int Expression::getPolynomialCoefficients(char symbolName, Expression * coefficients[], Context & context, AngleUnit angleUnit) const {
|
||||
int degree = privateGetPolynomialCoefficients(symbolName, coefficients);
|
||||
for (int i = 0; i <= degree; i++) {
|
||||
Reduce(&coefficients[i], context);
|
||||
Reduce(&coefficients[i], context, angleUnit);
|
||||
}
|
||||
return degree;
|
||||
}
|
||||
@@ -335,7 +332,7 @@ int Expression::SimplificationOrder(const Expression * e1, const Expression * e2
|
||||
}
|
||||
}
|
||||
|
||||
bool Expression::isEqualToItsApproximationLayout(Expression * approximation, int bufferSize, PrintFloat::Mode floatDisplayMode, int numberOfSignificantDigits, Context & context) {
|
||||
bool Expression::isEqualToItsApproximationLayout(Expression * approximation, int bufferSize, AngleUnit angleUnit, PrintFloat::Mode floatDisplayMode, int numberOfSignificantDigits, Context & context) {
|
||||
char buffer[bufferSize];
|
||||
approximation->writeTextInBuffer(buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits);
|
||||
/* Warning: we cannot use directly the the approximate expression but we have
|
||||
@@ -344,7 +341,7 @@ bool Expression::isEqualToItsApproximationLayout(Expression * approximation, int
|
||||
* identical. (For example, 0.000025 might be displayed "0.00003" and stored
|
||||
* as Decimal(0.000025) and isEqualToItsApproximationLayout should return
|
||||
* false) */
|
||||
Expression * approximateOutput = Expression::ParseAndSimplify(buffer, context);
|
||||
Expression * approximateOutput = Expression::ParseAndSimplify(buffer, context, angleUnit);
|
||||
bool equal = isIdenticalTo(approximateOutput);
|
||||
delete approximateOutput;
|
||||
return equal;
|
||||
@@ -366,9 +363,6 @@ Expression * Expression::ParseAndSimplify(const char * text, Context & context,
|
||||
|
||||
void Expression::Simplify(Expression ** expressionAddress, Context & context, AngleUnit angleUnit) {
|
||||
sSimplificationHasBeenInterrupted = false;
|
||||
if (angleUnit == AngleUnit::Default) {
|
||||
angleUnit = Preferences::sharedPreferences()->angleUnit();
|
||||
}
|
||||
#if MATRIX_EXACT_REDUCING
|
||||
#else
|
||||
if ((*expressionAddress)->recursivelyMatches(IsMatrix, context)) {
|
||||
@@ -426,12 +420,6 @@ Expression * Expression::deepBeautify(Context & context, AngleUnit angleUnit) {
|
||||
/* Evaluation */
|
||||
|
||||
template<typename T> Expression * Expression::approximate(Context& context, AngleUnit angleUnit, ComplexFormat complexFormat) const {
|
||||
if (angleUnit == AngleUnit::Default) {
|
||||
angleUnit = Preferences::sharedPreferences()->angleUnit();
|
||||
}
|
||||
if (complexFormat == ComplexFormat::Default) {
|
||||
complexFormat = Preferences::sharedPreferences()->complexFormat();
|
||||
}
|
||||
Expression * result = nullptr;
|
||||
Evaluation<T> * e = privateApproximate(T(), context, angleUnit);
|
||||
if (e->type() == Evaluation<T>::Type::Complex) {
|
||||
@@ -449,13 +437,7 @@ template<typename T> Expression * Expression::approximate(Context& context, Angl
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T> T Expression::approximateToScalar(Context& context, AngleUnit angleUnit, ComplexFormat complexFormat) const {
|
||||
if (angleUnit == AngleUnit::Default) {
|
||||
angleUnit = Preferences::sharedPreferences()->angleUnit();
|
||||
}
|
||||
if (complexFormat == ComplexFormat::Default) {
|
||||
complexFormat = Preferences::sharedPreferences()->complexFormat();
|
||||
}
|
||||
template<typename T> T Expression::approximateToScalar(Context& context, AngleUnit angleUnit) const {
|
||||
Evaluation<T> * evaluation = privateApproximate(T(), context, angleUnit);
|
||||
T result = evaluation->toScalar();
|
||||
/*if (evaluation->type() == Type::Matrix) {
|
||||
@@ -467,9 +449,9 @@ template<typename T> T Expression::approximateToScalar(Context& context, AngleUn
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T> T Expression::approximateToScalar(const char * text, Context& context, AngleUnit angleUnit, ComplexFormat complexFormat) {
|
||||
template<typename T> T Expression::approximateToScalar(const char * text, Context& context, AngleUnit angleUnit) {
|
||||
Expression * exp = ParseAndSimplify(text, context, angleUnit);
|
||||
T result = exp->approximateToScalar<T>(context, angleUnit, complexFormat);
|
||||
T result = exp->approximateToScalar<T>(context, angleUnit);
|
||||
delete exp;
|
||||
return result;
|
||||
}
|
||||
@@ -481,37 +463,37 @@ template<typename T> T Expression::epsilon() {
|
||||
|
||||
/* Expression roots/extrema solver*/
|
||||
|
||||
Expression::Coordinate2D Expression::nextMinimum(char symbol, double start, double step, double max, Context & context) const {
|
||||
return nextMinimumOfExpression(symbol, start, step, max, [](char symbol, double x, Context & context, const Expression * expression0, const Expression * expression1 = nullptr) {
|
||||
return expression0->approximateWithValueForSymbol(symbol, x, context);
|
||||
}, context);
|
||||
Expression::Coordinate2D Expression::nextMinimum(char symbol, double start, double step, double max, Context & context, AngleUnit angleUnit) const {
|
||||
return nextMinimumOfExpression(symbol, start, step, max, [](char symbol, double x, Context & context, AngleUnit angleUnit, const Expression * expression0, const Expression * expression1 = nullptr) {
|
||||
return expression0->approximateWithValueForSymbol(symbol, x, context, angleUnit);
|
||||
}, context, angleUnit);
|
||||
}
|
||||
|
||||
Expression::Coordinate2D Expression::nextMaximum(char symbol, double start, double step, double max, Context & context) const {
|
||||
Coordinate2D minimumOfOpposite = nextMinimumOfExpression(symbol, start, step, max, [](char symbol, double x, Context & context, const Expression * expression0, const Expression * expression1 = nullptr) {
|
||||
return -expression0->approximateWithValueForSymbol(symbol, x, context);
|
||||
}, context);
|
||||
Expression::Coordinate2D Expression::nextMaximum(char symbol, double start, double step, double max, Context & context, AngleUnit angleUnit) const {
|
||||
Coordinate2D minimumOfOpposite = nextMinimumOfExpression(symbol, start, step, max, [](char symbol, double x, Context & context, AngleUnit angleUnit, const Expression * expression0, const Expression * expression1 = nullptr) {
|
||||
return -expression0->approximateWithValueForSymbol(symbol, x, context, angleUnit);
|
||||
}, context, angleUnit);
|
||||
return {.abscissa = minimumOfOpposite.abscissa, .value = -minimumOfOpposite.value};
|
||||
}
|
||||
|
||||
double Expression::nextRoot(char symbol, double start, double step, double max, Context & context) const {
|
||||
return nextIntersectionWithExpression(symbol, start, step, max, [](char symbol, double x, Context & context, const Expression * expression0, const Expression * expression1 = nullptr) {
|
||||
return expression0->approximateWithValueForSymbol(symbol, x, context);
|
||||
}, context, nullptr);
|
||||
double Expression::nextRoot(char symbol, double start, double step, double max, Context & context, AngleUnit angleUnit) const {
|
||||
return nextIntersectionWithExpression(symbol, start, step, max, [](char symbol, double x, Context & context, AngleUnit angleUnit, const Expression * expression0, const Expression * expression1 = nullptr) {
|
||||
return expression0->approximateWithValueForSymbol(symbol, x, context, angleUnit);
|
||||
}, context, angleUnit, nullptr);
|
||||
}
|
||||
|
||||
Expression::Coordinate2D Expression::nextIntersection(char symbol, double start, double step, double max, Poincare::Context & context, const Expression * expression) const {
|
||||
double resultAbscissa = nextIntersectionWithExpression(symbol, start, step, max, [](char symbol, double x, Context & context, const Expression * expression0, const Expression * expression1) {
|
||||
return expression0->approximateWithValueForSymbol(symbol, x, context)-expression1->approximateWithValueForSymbol(symbol, x, context);
|
||||
}, context, expression);
|
||||
Expression::Coordinate2D result = {.abscissa = resultAbscissa, .value = approximateWithValueForSymbol(symbol, resultAbscissa, context)};
|
||||
Expression::Coordinate2D Expression::nextIntersection(char symbol, double start, double step, double max, Poincare::Context & context, AngleUnit angleUnit, const Expression * expression) const {
|
||||
double resultAbscissa = nextIntersectionWithExpression(symbol, start, step, max, [](char symbol, double x, Context & context, AngleUnit angleUnit, const Expression * expression0, const Expression * expression1) {
|
||||
return expression0->approximateWithValueForSymbol(symbol, x, context, angleUnit)-expression1->approximateWithValueForSymbol(symbol, x, context, angleUnit);
|
||||
}, context, angleUnit, expression);
|
||||
Expression::Coordinate2D result = {.abscissa = resultAbscissa, .value = approximateWithValueForSymbol(symbol, resultAbscissa, context, angleUnit)};
|
||||
if (std::fabs(result.value) < step*k_solverPrecision) {
|
||||
result.value = 0.0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Expression::Coordinate2D Expression::nextMinimumOfExpression(char symbol, double start, double step, double max, EvaluationAtAbscissa evaluate, Context & context, const Expression * expression, bool lookForRootMinimum) const {
|
||||
Expression::Coordinate2D Expression::nextMinimumOfExpression(char symbol, double start, double step, double max, EvaluationAtAbscissa evaluate, Context & context, AngleUnit angleUnit, const Expression * expression, bool lookForRootMinimum) const {
|
||||
Coordinate2D result = {.abscissa = NAN, .value = NAN};
|
||||
if (start == max || step == 0.0) {
|
||||
return result;
|
||||
@@ -520,13 +502,13 @@ Expression::Coordinate2D Expression::nextMinimumOfExpression(char symbol, double
|
||||
double x = start;
|
||||
bool endCondition = false;
|
||||
do {
|
||||
bracketMinimum(symbol, x, step, max, bracket, evaluate, context, expression);
|
||||
result = brentMinimum(symbol, bracket[0], bracket[2], evaluate, context, expression);
|
||||
bracketMinimum(symbol, x, step, max, bracket, evaluate, context, angleUnit, expression);
|
||||
result = brentMinimum(symbol, bracket[0], bracket[2], evaluate, context, angleUnit, expression);
|
||||
x = bracket[1];
|
||||
// Because of float approximation, exact zero is never reached
|
||||
if (std::fabs(result.abscissa) < std::fabs(step)*k_solverPrecision) {
|
||||
result.abscissa = 0;
|
||||
result.value = evaluate(symbol, 0, context, this, expression);
|
||||
result.value = evaluate(symbol, 0, context, angleUnit, this, expression);
|
||||
}
|
||||
/* Ignore extremum whose value is undefined or too big because they are
|
||||
* really unlikely to be local extremum. */
|
||||
@@ -548,13 +530,13 @@ Expression::Coordinate2D Expression::nextMinimumOfExpression(char symbol, double
|
||||
return result;
|
||||
}
|
||||
|
||||
void Expression::bracketMinimum(char symbol, double start, double step, double max, double result[3], EvaluationAtAbscissa evaluate, Context & context, const Expression * expression) const {
|
||||
void Expression::bracketMinimum(char symbol, double start, double step, double max, double result[3], EvaluationAtAbscissa evaluate, Context & context, AngleUnit angleUnit, const Expression * expression) const {
|
||||
Coordinate2D p[3];
|
||||
p[0] = {.abscissa = start, .value = evaluate(symbol, start, context, this, expression)};
|
||||
p[1] = {.abscissa = start+step, .value = evaluate(symbol, start+step, context, this, expression)};
|
||||
p[0] = {.abscissa = start, .value = evaluate(symbol, start, context, angleUnit, this, expression)};
|
||||
p[1] = {.abscissa = start+step, .value = evaluate(symbol, start+step, context, angleUnit, this, expression)};
|
||||
double x = start+2.0*step;
|
||||
while (step > 0.0 ? x <= max : x >= max) {
|
||||
p[2] = {.abscissa = x, .value = evaluate(symbol, x, context, this, expression)};
|
||||
p[2] = {.abscissa = x, .value = evaluate(symbol, x, context, angleUnit, this, expression)};
|
||||
if ((p[0].value > p[1].value || std::isnan(p[0].value)) && (p[2].value > p[1].value || std::isnan(p[2].value)) && (!std::isnan(p[0].value) || !std::isnan(p[2].value))) {
|
||||
result[0] = p[0].abscissa;
|
||||
result[1] = p[1].abscissa;
|
||||
@@ -573,11 +555,11 @@ void Expression::bracketMinimum(char symbol, double start, double step, double m
|
||||
result[2] = NAN;
|
||||
}
|
||||
|
||||
Expression::Coordinate2D Expression::brentMinimum(char symbol, double ax, double bx, EvaluationAtAbscissa evaluate, Context & context, const Expression * expression) const {
|
||||
Expression::Coordinate2D Expression::brentMinimum(char symbol, double ax, double bx, EvaluationAtAbscissa evaluate, Context & context, AngleUnit angleUnit, const Expression * expression) const {
|
||||
/* Bibliography: R. P. Brent, Algorithms for finding zeros and extrema of
|
||||
* functions without calculating derivatives */
|
||||
if (ax > bx) {
|
||||
return brentMinimum(symbol, bx, ax, evaluate, context, expression);
|
||||
return brentMinimum(symbol, bx, ax, evaluate, context, angleUnit, expression);
|
||||
}
|
||||
double e = 0.0;
|
||||
double a = ax;
|
||||
@@ -585,7 +567,7 @@ Expression::Coordinate2D Expression::brentMinimum(char symbol, double ax, double
|
||||
double x = a+k_goldenRatio*(b-a);
|
||||
double v = x;
|
||||
double w = x;
|
||||
double fx = evaluate(symbol, x, context, this, expression);
|
||||
double fx = evaluate(symbol, x, context, angleUnit, this, expression);
|
||||
double fw = fx;
|
||||
double fv = fw;
|
||||
|
||||
@@ -597,10 +579,10 @@ Expression::Coordinate2D Expression::brentMinimum(char symbol, double ax, double
|
||||
double tol1 = k_sqrtEps*std::fabs(x)+1E-10;
|
||||
double tol2 = 2.0*tol1;
|
||||
if (std::fabs(x-m) <= tol2-0.5*(b-a)) {
|
||||
double middleFax = evaluate(symbol, (x+a)/2.0, context, this, expression);
|
||||
double middleFbx = evaluate(symbol, (x+b)/2.0, context, this, expression);
|
||||
double fa = evaluate(symbol, a, context, this, expression);
|
||||
double fb = evaluate(symbol, b, context, this, expression);
|
||||
double middleFax = evaluate(symbol, (x+a)/2.0, context, angleUnit, this, expression);
|
||||
double middleFbx = evaluate(symbol, (x+b)/2.0, context, angleUnit, this, expression);
|
||||
double fa = evaluate(symbol, a, context, angleUnit, this, expression);
|
||||
double fb = evaluate(symbol, b, context, angleUnit, this, expression);
|
||||
if (middleFax-fa <= k_sqrtEps && fx-middleFax <= k_sqrtEps && fx-middleFbx <= k_sqrtEps && middleFbx-fb <= k_sqrtEps) {
|
||||
Coordinate2D result = {.abscissa = x, .value = fx};
|
||||
return result;
|
||||
@@ -633,7 +615,7 @@ Expression::Coordinate2D Expression::brentMinimum(char symbol, double ax, double
|
||||
d = k_goldenRatio*e;
|
||||
}
|
||||
u = x + (std::fabs(d) >= tol1 ? d : (d>0 ? tol1 : -tol1));
|
||||
fu = evaluate(symbol, u, context, this, expression);
|
||||
fu = evaluate(symbol, u, context, angleUnit, this, expression);
|
||||
if (fu <= fx) {
|
||||
if (u<x) {
|
||||
b = x;
|
||||
@@ -667,7 +649,7 @@ Expression::Coordinate2D Expression::brentMinimum(char symbol, double ax, double
|
||||
return result;
|
||||
}
|
||||
|
||||
double Expression::nextIntersectionWithExpression(char symbol, double start, double step, double max, EvaluationAtAbscissa evaluation, Context & context, const Expression * expression) const {
|
||||
double Expression::nextIntersectionWithExpression(char symbol, double start, double step, double max, EvaluationAtAbscissa evaluation, Context & context, AngleUnit angleUnit, const Expression * expression) const {
|
||||
if (start == max || step == 0.0) {
|
||||
return NAN;
|
||||
}
|
||||
@@ -676,27 +658,27 @@ double Expression::nextIntersectionWithExpression(char symbol, double start, dou
|
||||
static double precisionByGradUnit = 1E6;
|
||||
double x = start+step;
|
||||
do {
|
||||
bracketRoot(symbol, x, step, max, bracket, evaluation, context, expression);
|
||||
result = brentRoot(symbol, bracket[0], bracket[1], std::fabs(step/precisionByGradUnit), evaluation, context, expression);
|
||||
bracketRoot(symbol, x, step, max, bracket, evaluation, context, angleUnit, expression);
|
||||
result = brentRoot(symbol, bracket[0], bracket[1], std::fabs(step/precisionByGradUnit), evaluation, context, angleUnit, expression);
|
||||
x = bracket[1];
|
||||
} while (std::isnan(result) && (step > 0.0 ? x <= max : x >= max));
|
||||
|
||||
double extremumMax = std::isnan(result) ? max : result;
|
||||
Coordinate2D resultExtremum[2] = {
|
||||
nextMinimumOfExpression(symbol, start, step, extremumMax, [](char symbol, double x, Context & context, const Expression * expression0, const Expression * expression1) {
|
||||
nextMinimumOfExpression(symbol, start, step, extremumMax, [](char symbol, double x, Context & context, AngleUnit angleUnit, const Expression * expression0, const Expression * expression1) {
|
||||
if (expression1) {
|
||||
return expression0->approximateWithValueForSymbol(symbol, x, context)-expression1->approximateWithValueForSymbol(symbol, x, context);
|
||||
return expression0->approximateWithValueForSymbol(symbol, x, context, angleUnit)-expression1->approximateWithValueForSymbol(symbol, x, context, angleUnit);
|
||||
} else {
|
||||
return expression0->approximateWithValueForSymbol(symbol, x, context);
|
||||
return expression0->approximateWithValueForSymbol(symbol, x, context, angleUnit);
|
||||
}
|
||||
}, context, expression, true),
|
||||
nextMinimumOfExpression(symbol, start, step, extremumMax, [](char symbol, double x, Context & context, const Expression * expression0, const Expression * expression1) {
|
||||
}, context, angleUnit, expression, true),
|
||||
nextMinimumOfExpression(symbol, start, step, extremumMax, [](char symbol, double x, Context & context, AngleUnit angleUnit, const Expression * expression0, const Expression * expression1) {
|
||||
if (expression1) {
|
||||
return expression1->approximateWithValueForSymbol(symbol, x, context)-expression0->approximateWithValueForSymbol(symbol, x, context);
|
||||
return expression1->approximateWithValueForSymbol(symbol, x, context, angleUnit)-expression0->approximateWithValueForSymbol(symbol, x, context, angleUnit);
|
||||
} else {
|
||||
return -expression0->approximateWithValueForSymbol(symbol, x, context);
|
||||
return -expression0->approximateWithValueForSymbol(symbol, x, context, angleUnit);
|
||||
}
|
||||
}, context, expression, true)};
|
||||
}, context, angleUnit, expression, true)};
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (!std::isnan(resultExtremum[i].abscissa) && (std::isnan(result) || std::fabs(result - start) > std::fabs(resultExtremum[i].abscissa - start))) {
|
||||
result = resultExtremum[i].abscissa;
|
||||
@@ -708,12 +690,12 @@ double Expression::nextIntersectionWithExpression(char symbol, double start, dou
|
||||
return result;
|
||||
}
|
||||
|
||||
void Expression::bracketRoot(char symbol, double start, double step, double max, double result[2], EvaluationAtAbscissa evaluation, Context & context, const Expression * expression) const {
|
||||
void Expression::bracketRoot(char symbol, double start, double step, double max, double result[2], EvaluationAtAbscissa evaluation, Context & context, AngleUnit angleUnit, const Expression * expression) const {
|
||||
double a = start;
|
||||
double b = start+step;
|
||||
while (step > 0.0 ? b <= max : b >= max) {
|
||||
double fa = evaluation(symbol, a, context, this, expression);
|
||||
double fb = evaluation(symbol, b, context, this, expression);
|
||||
double fa = evaluation(symbol, a, context, angleUnit, this, expression);
|
||||
double fb = evaluation(symbol, b, context, angleUnit, this, expression);
|
||||
if (fa*fb <= 0) {
|
||||
result[0] = a;
|
||||
result[1] = b;
|
||||
@@ -727,17 +709,17 @@ void Expression::bracketRoot(char symbol, double start, double step, double max,
|
||||
}
|
||||
|
||||
|
||||
double Expression::brentRoot(char symbol, double ax, double bx, double precision, EvaluationAtAbscissa evaluation, Context & context, const Expression * expression) const {
|
||||
double Expression::brentRoot(char symbol, double ax, double bx, double precision, EvaluationAtAbscissa evaluation, Context & context, AngleUnit angleUnit, const Expression * expression) const {
|
||||
if (ax > bx) {
|
||||
return brentRoot(symbol, bx, ax, precision, evaluation, context, expression);
|
||||
return brentRoot(symbol, bx, ax, precision, evaluation, context, angleUnit, expression);
|
||||
}
|
||||
double a = ax;
|
||||
double b = bx;
|
||||
double c = bx;
|
||||
double d = b-a;
|
||||
double e = b-a;
|
||||
double fa = evaluation(symbol, a, context, this, expression);
|
||||
double fb = evaluation(symbol, b, context, this, expression);
|
||||
double fa = evaluation(symbol, a, context, angleUnit, this, expression);
|
||||
double fb = evaluation(symbol, b, context, angleUnit, this, expression);
|
||||
double fc = fb;
|
||||
for (int i = 0; i < 100; i++) {
|
||||
if ((fb > 0.0 && fc > 0.0) || (fb < 0.0 && fc < 0.0)) {
|
||||
@@ -757,7 +739,7 @@ double Expression::brentRoot(char symbol, double ax, double bx, double precision
|
||||
double tol1 = 2.0*DBL_EPSILON*std::fabs(b)+0.5*precision;
|
||||
double xm = 0.5*(c-b);
|
||||
if (std::fabs(xm) <= tol1 || fb == 0.0) {
|
||||
double fbcMiddle = evaluation(symbol, 0.5*(b+c), context, this, expression);
|
||||
double fbcMiddle = evaluation(symbol, 0.5*(b+c), context, angleUnit, this, expression);
|
||||
double isContinuous = (fb <= fbcMiddle && fbcMiddle <= fc) || (fc <= fbcMiddle && fbcMiddle <= fb);
|
||||
if (isContinuous) {
|
||||
return b;
|
||||
@@ -795,16 +777,16 @@ double Expression::brentRoot(char symbol, double ax, double bx, double precision
|
||||
} else {
|
||||
b += xm > 0.0 ? tol1 : tol1;
|
||||
}
|
||||
fb = evaluation(symbol, b, context, this, expression);
|
||||
fb = evaluation(symbol, b, context, angleUnit, this, expression);
|
||||
}
|
||||
return NAN;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T Expression::approximateWithValueForSymbol(char symbol, T x, Context & context) const {
|
||||
T Expression::approximateWithValueForSymbol(char symbol, T x, Context & context, AngleUnit angleUnit) const {
|
||||
VariableContext<T> variableContext = VariableContext<T>(symbol, &context);
|
||||
variableContext.setApproximationForVariable(x);
|
||||
T value = approximateToScalar<T>(variableContext);
|
||||
T value = approximateToScalar<T>(variableContext, angleUnit);
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -817,9 +799,6 @@ Expression * Expression::CreateDecimal(T f) {
|
||||
}
|
||||
|
||||
template<typename T> Expression * Expression::complexToExpression(std::complex<T> c, ComplexFormat complexFormat) {
|
||||
if (complexFormat == ComplexFormat::Default) {
|
||||
complexFormat = Preferences::sharedPreferences()->complexFormat();
|
||||
}
|
||||
if (std::isnan(c.real()) || std::isnan(c.imag()) || std::isinf(c.real()) || std::isinf(c.imag())) {
|
||||
return new Undefined();
|
||||
}
|
||||
@@ -890,11 +869,11 @@ template<typename T> Expression * Expression::complexToExpression(std::complex<T
|
||||
|
||||
template Poincare::Expression * Poincare::Expression::approximate<double>(Context& context, AngleUnit angleUnit, ComplexFormat complexFormat) const;
|
||||
template Poincare::Expression * Poincare::Expression::approximate<float>(Context& context, AngleUnit angleUnit, ComplexFormat complexFormat) const;
|
||||
template double Poincare::Expression::approximateToScalar<double>(char const*, Poincare::Context&, Poincare::Expression::AngleUnit, ComplexFormat complexFormat);
|
||||
template float Poincare::Expression::approximateToScalar<float>(char const*, Poincare::Context&, Poincare::Expression::AngleUnit, ComplexFormat complexFormat);
|
||||
template double Poincare::Expression::approximateToScalar<double>(Poincare::Context&, Poincare::Expression::AngleUnit, ComplexFormat complexFormat) const;
|
||||
template float Poincare::Expression::approximateToScalar<float>(Poincare::Context&, Poincare::Expression::AngleUnit, ComplexFormat complexFormat) const;
|
||||
template double Poincare::Expression::approximateToScalar<double>(char const*, Poincare::Context&, Poincare::Expression::AngleUnit);
|
||||
template float Poincare::Expression::approximateToScalar<float>(char const*, Poincare::Context&, Poincare::Expression::AngleUnit);
|
||||
template double Poincare::Expression::approximateToScalar<double>(Poincare::Context&, Poincare::Expression::AngleUnit) const;
|
||||
template float Poincare::Expression::approximateToScalar<float>(Poincare::Context&, Poincare::Expression::AngleUnit) const;
|
||||
template double Poincare::Expression::epsilon<double>();
|
||||
template float Poincare::Expression::epsilon<float>();
|
||||
template double Poincare::Expression::approximateWithValueForSymbol(char, double, Poincare::Context&) const;
|
||||
template float Poincare::Expression::approximateWithValueForSymbol(char, float, Poincare::Context&) const;
|
||||
template double Poincare::Expression::approximateWithValueForSymbol(char, double, Poincare::Context&, AngleUnit) const;
|
||||
template float Poincare::Expression::approximateWithValueForSymbol(char, float, Poincare::Context&, AngleUnit) const;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <poincare/global_context.h>
|
||||
#include <poincare/matrix.h>
|
||||
#include <poincare/undefined.h>
|
||||
#include <poincare/preferences.h>
|
||||
#include <assert.h>
|
||||
#include <cmath>
|
||||
#include <ion.h>
|
||||
@@ -94,7 +95,7 @@ void GlobalContext::setExpressionForSymbolName(const Expression * expression, co
|
||||
if (symbol->isMatrixSymbol()) {
|
||||
int indexMatrix = symbol->name() - (char)Symbol::SpecialSymbols::M0;
|
||||
assert(indexMatrix >= 0 && indexMatrix < k_maxNumberOfMatrixExpressions);
|
||||
Expression * evaluation = expression ? expression->approximate<double>(context) : nullptr; // evaluate before deleting anything (to be able to evaluate M1+2->M1)
|
||||
Expression * evaluation = expression ? expression->approximate<double>(context, Preferences::sharedPreferences()->angleUnit(), Preferences::sharedPreferences()->complexFormat()) : nullptr; // evaluate before deleting anything (to be able to evaluate M1+2->M1)
|
||||
if (m_matrixExpressions[indexMatrix] != nullptr) {
|
||||
delete m_matrixExpressions[indexMatrix];
|
||||
m_matrixExpressions[indexMatrix] = nullptr;
|
||||
@@ -115,7 +116,7 @@ void GlobalContext::setExpressionForSymbolName(const Expression * expression, co
|
||||
if (index < 0 || index >= k_maxNumberOfScalarExpressions) {
|
||||
return;
|
||||
}
|
||||
Expression * evaluation = expression ? expression->approximate<double>(context) : nullptr; // evaluate before deleting anything (to be able to evaluate A+2->A)
|
||||
Expression * evaluation = expression ? expression->approximate<double>(context, Preferences::sharedPreferences()->angleUnit(), Preferences::sharedPreferences()->complexFormat()) : nullptr; // evaluate before deleting anything (to be able to evaluate A+2->A)
|
||||
if (m_expressions[index] != nullptr) {
|
||||
delete m_expressions[index];
|
||||
m_expressions[index] = nullptr;
|
||||
|
||||
@@ -76,7 +76,7 @@ ExpressionLayout * Integral::createLayout(PrintFloat::Mode floatDisplayMode, int
|
||||
|
||||
template<typename T>
|
||||
T Integral::functionValueAtAbscissa(T x, Context & context, AngleUnit angleUnit) const {
|
||||
return operand(0)->approximateWithValueForSymbol('x', x, context);
|
||||
return operand(0)->approximateWithValueForSymbol('x', x, context, angleUnit);
|
||||
}
|
||||
|
||||
#ifdef LAGRANGE_METHOD
|
||||
|
||||
@@ -139,7 +139,7 @@ template<typename T> MatrixComplex<T> Power::computeOnMatrixAndComplex(const Mat
|
||||
if (inverse == nullptr) {
|
||||
return MatrixComplex<T>::Undefined();
|
||||
}
|
||||
Complex<T> minusC = Complex<T>(Opposite::compute(d, AngleUnit::Default));
|
||||
Complex<T> minusC = Complex<T>(-d);
|
||||
MatrixComplex<T> result = Power::computeOnMatrixAndComplex(*inverse, minusC);
|
||||
delete inverse;
|
||||
return result;
|
||||
|
||||
@@ -19,9 +19,6 @@ namespace Poincare {
|
||||
|
||||
float Trigonometry::characteristicXRange(const Expression * e, Context & context, Expression::AngleUnit angleUnit) {
|
||||
assert(e->numberOfOperands() == 1);
|
||||
if (angleUnit == Expression::AngleUnit::Default) {
|
||||
angleUnit = Preferences::sharedPreferences()->angleUnit();
|
||||
}
|
||||
const Expression * op = e->operand(0);
|
||||
int d = op->polynomialDegree('x');
|
||||
// op is not linear so we cannot not easily find an interesting range
|
||||
@@ -39,7 +36,7 @@ float Trigonometry::characteristicXRange(const Expression * e, Context & context
|
||||
Poincare::Approximation<float> x(1.0f);
|
||||
const Poincare::Expression * args[2] = {op, &x};
|
||||
Poincare::Derivative derivative(args, true);
|
||||
float a = derivative.approximateToScalar<float>(context);
|
||||
float a = derivative.approximateToScalar<float>(context, angleUnit);
|
||||
float pi = angleUnit == Expression::AngleUnit::Radian ? M_PI : 180.0f;
|
||||
return 2.0f*pi/std::fabs(a);
|
||||
}
|
||||
@@ -243,7 +240,6 @@ Expression * Trigonometry::table(const Expression * e, Expression::Type type, Co
|
||||
|
||||
template <typename T>
|
||||
std::complex<T> Trigonometry::computeOnComplex(const std::complex<T> c, Expression::AngleUnit angleUnit, Approximation<T> approximate) {
|
||||
assert(angleUnit != Expression::AngleUnit::Default);
|
||||
std::complex<T> input(c);
|
||||
if (angleUnit == Expression::AngleUnit::Degree && input.imag() == 0.0) {
|
||||
input = input*std::complex<T>(M_PI/180.0);
|
||||
|
||||
@@ -21,11 +21,10 @@ void VariableContext<T>::setApproximationForVariable(T value) {
|
||||
template<typename T>
|
||||
void VariableContext<T>::setExpressionForSymbolName(const Expression * expression, const Symbol * symbol, Context & context) {
|
||||
if (symbol->name() == m_name) {
|
||||
assert(false);
|
||||
if (expression == nullptr) {
|
||||
return;
|
||||
}
|
||||
m_value = Approximation<T>(expression->approximateToScalar<T>(context));
|
||||
m_value = Approximation<T>(expression->approximateToScalar<T>(context, Preferences::sharedPreferences()->angleUnit()));
|
||||
} else {
|
||||
m_parentContext->setExpressionForSymbolName(expression, symbol, context);
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ void assert_parsed_expression_has_polynomial_coefficient(const char * expression
|
||||
Expression * e = parse_expression(expression);
|
||||
Expression::Reduce(&e, globalContext, angleUnit);
|
||||
Expression * coefficientBuffer[Poincare::Expression::k_maxNumberOfPolynomialCoefficients];
|
||||
int d = e->getPolynomialCoefficients(symbolName, coefficientBuffer, globalContext);
|
||||
int d = e->getPolynomialCoefficients(symbolName, coefficientBuffer, globalContext, Radian);
|
||||
for (int i = 0; i <= d; i++) {
|
||||
Expression * f = parse_expression(coefficients[i]);
|
||||
Expression::Reduce(&coefficientBuffer[i], globalContext, angleUnit);
|
||||
|
||||
Reference in New Issue
Block a user