[solver] Take into account the complexFormat Real

This commit is contained in:
Émilie Feral
2018-12-21 10:24:02 +01:00
committed by Léa Saviot
parent 6fd3a155df
commit aa80710f4d
5 changed files with 97 additions and 8 deletions

View File

@@ -43,6 +43,10 @@ Expression Equation::standardForm(Context * context) const {
return m_standardForm;
}
bool Equation::containsIComplex() const {
return strchr(text(), Ion::Charset::IComplex) != nullptr;
}
void Equation::tidyStandardForm() {
// Free the pool of the m_standardForm
m_standardForm = Expression();

View File

@@ -14,6 +14,7 @@ public:
return false;
}
Poincare::Expression standardForm(Poincare::Context * context) const;
bool containsIComplex() const;
private:
void tidyStandardForm();
mutable Poincare::Expression m_standardForm;

View File

@@ -2,6 +2,7 @@
#include "../shared/poincare_helpers.h"
#include <limits.h>
#include <poincare/constant.h>
#include <poincare/symbol.h>
#include <poincare/matrix.h>
#include <poincare/rational.h>
@@ -170,21 +171,39 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) {
}
}
/* Turn the results in layouts */
for (int i = 0; i < k_maxNumberOfExactSolutions; i++) {
int solutionIndex = 0;
int initialNumberOfSolutions = m_numberOfSolutions;
// We iterate through the solutions and the potential delta
for (int i = 0; i < initialNumberOfSolutions+1; i++) {
if (!exactSolutions[i].isUninitialized()) {
m_exactSolutionExactLayouts[i] = PoincareHelpers::CreateLayout(exactSolutions[i]);
m_exactSolutionApproximateLayouts[i] = PoincareHelpers::CreateLayout(exactSolutionsApproximations[i]);
/* Discard complex solutions if ComplexFormat is Real and the equation
* system was not explicitly complex. */
if (Preferences::sharedPreferences()->complexFormat() == Preferences::ComplexFormat::Real && !isExplictlyComplex() && exactSolutionsApproximations[i].recursivelyMatches([](const Expression e, Context & context, bool replaceSymbols) { return e.type() == ExpressionNode::Type::Constant && static_cast<const Poincare::Constant &>(e).isIComplex(); }, *context, false)) {
if (i < initialNumberOfSolutions) {
// Discard the solution
m_numberOfSolutions--;
continue;
} else {
assert( i == initialNumberOfSolutions);
// Delta is not real
exactSolutions[i] = Undefined();
exactSolutionsApproximations[i] = Undefined();
}
}
m_exactSolutionExactLayouts[solutionIndex] = PoincareHelpers::CreateLayout(exactSolutions[i]);
m_exactSolutionApproximateLayouts[solutionIndex] = PoincareHelpers::CreateLayout(exactSolutionsApproximations[i]);
/* Check for identity between exact and approximate layouts */
char exactBuffer[Shared::ExpressionModel::k_expressionBufferSize];
char approximateBuffer[Shared::ExpressionModel::k_expressionBufferSize];
m_exactSolutionExactLayouts[i].serializeForParsing(exactBuffer, Shared::ExpressionModel::k_expressionBufferSize);
m_exactSolutionApproximateLayouts[i].serializeForParsing(approximateBuffer, Shared::ExpressionModel::k_expressionBufferSize);
m_exactSolutionIdentity[i] = strcmp(exactBuffer, approximateBuffer) == 0;
m_exactSolutionExactLayouts[solutionIndex].serializeForParsing(exactBuffer, Shared::ExpressionModel::k_expressionBufferSize);
m_exactSolutionApproximateLayouts[solutionIndex].serializeForParsing(approximateBuffer, Shared::ExpressionModel::k_expressionBufferSize);
m_exactSolutionIdentity[solutionIndex] = strcmp(exactBuffer, approximateBuffer) == 0;
/* Check for equality between exact and approximate layouts */
if (!m_exactSolutionIdentity[i]) {
if (!m_exactSolutionIdentity[solutionIndex]) {
char buffer[Shared::ExpressionModel::k_expressionBufferSize];
m_exactSolutionEquality[i] = exactSolutions[i].isEqualToItsApproximationLayout(exactSolutionsApproximations[i], buffer, Shared::ExpressionModel::k_expressionBufferSize, preferences->angleUnit(), preferences->displayMode(), preferences->numberOfSignificantDigits(), *context);
m_exactSolutionEquality[solutionIndex] = exactSolutions[i].isEqualToItsApproximationLayout(exactSolutionsApproximations[i], buffer, Shared::ExpressionModel::k_expressionBufferSize, preferences->angleUnit(), preferences->displayMode(), preferences->numberOfSignificantDigits(), *context);
}
solutionIndex++;
}
}
return error;
@@ -337,4 +356,13 @@ void EquationStore::tidySolution() {
}
}
bool EquationStore::isExplictlyComplex() {
for (int i = 0; i < numberOfDefinedModels(); i++) {
if (definedModelAtIndex(i)->containsIComplex()) {
return true;
}
}
return false;
}
}

View File

@@ -82,6 +82,7 @@ private:
Error resolveLinearSystem(Poincare::Expression solutions[k_maxNumberOfExactSolutions], Poincare::Expression solutionApproximations[k_maxNumberOfExactSolutions], Poincare::Expression coefficients[k_maxNumberOfEquations][Poincare::Expression::k_maxNumberOfVariables], Poincare::Expression constants[k_maxNumberOfEquations], Poincare::Context * context);
Error oneDimensialPolynomialSolve(Poincare::Expression solutions[k_maxNumberOfExactSolutions], Poincare::Expression solutionApproximations[k_maxNumberOfExactSolutions], Poincare::Expression polynomialCoefficients[Poincare::Expression::k_maxNumberOfPolynomialCoefficients], int degree, Poincare::Context * context);
void tidySolution();
bool isExplictlyComplex();
Equation m_equations[k_maxNumberOfEquations];
Type m_type;

View File

@@ -169,4 +169,59 @@ QUIZ_CASE(equation_solve) {
assert_equation_system_exact_solve_to(equations19, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesBig1Big2, solutions19, 2);
}
QUIZ_CASE(equation_solve_complex_format) {
Poincare::Preferences::sharedPreferences()->setComplexFormat(Poincare::Preferences::ComplexFormat::Real);
const char * variablesx[] = {"x", ""};
// x+I = 0 --> x = -I
const char * equations0[] = {"x+I=0", 0};
const char * solutions0[] = {"-I"};
assert_equation_system_exact_solve_to(equations0, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesx, solutions0, 1);
// x+R(-1) = 0 --> pas de solution dans R
const char * equations1[] = {"x+R(-1)=0", 0};
assert_equation_system_exact_solve_to(equations1, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesx, nullptr, 0);
// x^2+x+1=0 --> pas de solution dans R
const char * equations2[] = {"x^2+x+1=0", 0};
const char * delta2[] = {"-3"};
assert_equation_system_exact_solve_to(equations2, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, delta2, 0);
// x^2-R(-1)=0 --> pas de solution dans R
const char * equations3[] = {"x^2-R(-1)=0", 0};
const char * delta3[] = {"undef"};
assert_equation_system_exact_solve_to(equations3, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, delta3, 0);
Poincare::Preferences::sharedPreferences()->setComplexFormat(Poincare::Preferences::ComplexFormat::Cartesian);
// x+I = 0 --> x = -I
assert_equation_system_exact_solve_to(equations0, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesx, solutions0, 1);
// x+R(-1) = 0 --> x = -I
assert_equation_system_exact_solve_to(equations1, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesx, solutions0, 1);
// x^2+x+1=0
const char * solutions2[] = {"-(1)/(2)-(R(3))/(2)*I","-(1)/(2)+(R(3))/(2)*I", "-3"};
assert_equation_system_exact_solve_to(equations2, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions2, 2);
// x^2-R(-1)=0
const char * solutions3[] = {"-(R(2))/(2)-(R(2))/(2)*I", "(R(2))/(2)+(R(2))/(2)*I","4*I"};
assert_equation_system_exact_solve_to(equations3, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions3, 2);
Poincare::Preferences::sharedPreferences()->setComplexFormat(Poincare::Preferences::ComplexFormat::Polar);
// x+I = 0 --> x = e^(-pi/2*i)
const char * solutions0Polar[] = {"X$-(P)/(2)*I#"};
assert_equation_system_exact_solve_to(equations0, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesx, solutions0Polar, 1);
// x+R(-1) = 0 --> x = e^(-pi/2*i)
assert_equation_system_exact_solve_to(equations1, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesx, solutions0Polar, 1);
// x^2+x+1=0
const char * solutions2Polar[] = {"X$-(2*P)/(3)*I#","X$(2*P)/(3)*I#", "3*X$P*I#"};
assert_equation_system_exact_solve_to(equations2, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions2Polar, 2);
// x^2-R(-1)=0
const char * solutions3Polar[] = {"X$-(3*P)/(4)*I#", "X$(P)/(4)*I#", "4*X$(P)/(2)*I#"};
assert_equation_system_exact_solve_to(equations3, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions3Polar, 2);
}
}