Files
Upsilon/apps/solver/test/equation_store.cpp
Gabriel Ozouf c7b758f536 [poincare/expression] Fix solutions to e^x=0
Because of the limitations of the floating-point representation, e^x is
null for x <= 710, causing the nextRoot functions to find roots for it.
To prevent this, we looking for places where a function changes sign, we
actually require the function to take two non-null values of different
signs.
2020-12-14 10:20:09 +01:00

192 lines
6.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include <quiz.h>
#include "helpers.h"
QUIZ_CASE(equation_solve) {
assert_solves_to_error("x+y+z+a+b+c+d=0", TooManyVariables);
assert_solves_to_error("x^2+y=0", NonLinearSystem);
assert_solves_to_error("cos(x)=0", RequireApproximateSolution);
assert_solves_to_no_solution("2=0");
assert_solves_to_no_solution("x-x+2=0");
assert_solves_to_infinite_solutions("0=0");
assert_solves_to_infinite_solutions("x-x=0");
assert_solves_to("2x+3=4", "x=1/2");
assert_solves_to("3×x^2-4x+4=2", {"x=2/3-(√(2)/3)𝐢", "x=2/3+(√(2)/3)𝐢", "delta=-8"});
assert_solves_to("2×x^2-4×x+4=3", {"x=(-√(2)+2)/2", "x=(√(2)+2)/2", "delta=8"});
assert_solves_to("2×x^2-4×x+2=0", {"x=1", "delta=0"});
assert_solves_to(
"x^2+x+1=3×x^2+π×x-√(5)",
{
"x=(√(π^2-2π+8√(5)+9)-π+1)/4",
"x=(-√(π^2-2π+8×√(5)+9)-π+1)/4",
"delta=π^2-2π+8√(5)+9"
}
);
assert_solves_to("(x-3)^2=0", {"x=3", "delta=0"});
/* TODO: Cubic
* x^3-4x^2+6x-24=0
* x^3+x^2+1=0
* x^3-3x-2=0 */
// Linear System
assert_solves_to_infinite_solutions("x+y=0");
assert_solves_to({"x+y=0", "3x+y=-5"}, {"x=-5/2", "y=5/2"});
assert_solves_to(
{
"x+y=0",
"3x+y+z=-5",
"4z-π=0"
},
{
"x=(-π-20)/8",
"y=(π+20)/8",
"z=π/4"
}
);
assert_solves_to(
{
"x+y=0",
"3x+y+z=-5",
"4z-π=0",
"a+b+c=0",
"a=3",
"c=a+2"
},
{
"x=(-π-20)/8",
"y=(π+20)/8",
"z=π/4",
"a=3",
"b=-8",
"c=5"
}
);
/* This test case needs the user defined variable. Indeed, in the equation
* store, m_variables is just before m_userVariables, so bad fetching in
* m_variables might fetch into m_userVariables and create problems. */
set("x", "0");
assert_solves_to_infinite_solutions({
"b=0",
"D=0",
"e=0",
"x+y+z+t=0"
});
unset("x");
// Monovariable non-polynomial equation
Poincare::Preferences::sharedPreferences()->setAngleUnit(Degree);
assert_solves_numerically_to("cos(x)=0", -100, 100, {-90.0, 90.0});
assert_solves_numerically_to("cos(x)=0", -900, 1000, {-810.0, -630.0, -450.0, -270.0, -90.0, 90.0, 270.0, 450.0, 630.0, 810.0});
assert_solves_numerically_to("√(y)=0", -900, 1000, {0}, "y");
assert_solves_numerically_to("^x=0", -1000, 1000, {});
assert_solves_numerically_to("^x/1000=0", -1000, 1000, {});
// Long variable names
assert_solves_to("2abcde+3=4", "abcde=1/2");
assert_solves_to({"Big1+Big2=0", "3Big1+Big2=-5"}, {"Big1=-5/2", "Big2=5/2"});
// conj(x)*x+1 = 0
assert_solves_to_error("conj(x)*x+1=0", RequireApproximateSolution);
assert_solves_numerically_to("conj(x)*x+1=0", -100, 100, {});
assert_solves_to_error("(x-10)^7=0", RequireApproximateSolution);
assert_solves_numerically_to("(x-10)^7=0", -100, 100, {10});
}
QUIZ_CASE(equation_solve_complex_real) {
set_complex_format(Real);
assert_solves_to("x+𝐢=0", "x=-𝐢"); // We still want complex solutions if the input has some complex value
assert_solves_to_error("x+√(-1)=0", EquationUnreal);
assert_solves_to("x^2+x+1=0", {"delta=-3"});
assert_solves_to_error("x^2-√(-1)=0", EquationUnreal);
assert_solves_to_error("x+√(-1)×√(-1)=0", EquationUnreal);
assert_solves_to("root(-8,3)*x+3=0", "x=3/2");
reset_complex_format();
}
QUIZ_CASE(equation_solve_complex_cartesian) {
set_complex_format(Cartesian);
assert_solves_to("x+𝐢=0", "x=-𝐢");
assert_solves_to("x+√(-1)=0", "x=-𝐢");
assert_solves_to({"x^2+x+1=0"}, {"x=-1/2-((√(3))/2)𝐢", "x=-1/2+((√(3))/2)𝐢", "delta=-3"});
assert_solves_to("x^2-√(-1)=0", {"x=-√(2)/2-(√(2)/2)𝐢", "x=√(2)/2+(√(2)/2)𝐢", "delta=4𝐢"});
assert_solves_to("x+√(-1)×√(-1)=0", "x=1");
assert_solves_to("root(-8,3)*x+3=0", "x=-3/4+(3√(3)/4)*𝐢");
reset_complex_format();
}
QUIZ_CASE(equation_solve_complex_polar) {
set_complex_format(Polar);
assert_solves_to("x+𝐢=0", "x=^(-(π/2)𝐢)");
assert_solves_to("x+√(-1)=0", "x=^(-(π/2)𝐢)");
assert_solves_to("x^2+x+1=0", {"x=^(-(2π/3)𝐢)", "x=^((2π/3)𝐢)", "delta=3^(π𝐢)"});
assert_solves_to("x^2-√(-1)=0", {"x=^(-(3π/4)𝐢)", "x=^((π/4)𝐢)", "delta=4^((π/2)𝐢)"});
assert_solves_to("root(-8,3)*x+3=0", "x=3/2×^((2π/3)𝐢)");
reset_complex_format();
}
QUIZ_CASE(equation_and_symbolic_computation) {
assert_solves_to_infinite_solutions("x+a=0");
set("a", "-3");
assert_solves_to("x+a=0", "x=3");
assert_solves_to("a=0", "a=0");
/* The equation has no solution since the user defined a = -3. So a is not
* replaced with its context value, and the solution is a = 0. */
set("b", "-4");
assert_solves_to_infinite_solutions("a+b=0");
/* The equation has no solution since the user defined a = -3 and b = -4.
* So neither a nor b are replaced with their context values. Therefore the
* solution is an infinity of solutions. */
assert_solves_to("a+b+c=0", "c=7");
assert_solves_to({"a+c=0", "a=3"}, {"a=3", "c=-3"});
/* The system has no solution since the user defined a = -3. So a is not
* replaced with its context value, and the solution is a = 3 and c = -3. */
set("f(x)", "x+1");
assert_solves_to("f(x)=0", "x=-1");
assert_solves_to("f(a)=0", "a=-1");
/* The equation has no solution since the user defined a = -3. So a is not
* replaced with its context value, and the solution is a = -1. */
set("g(x)", "a+x+2");
assert_solves_to("g(x)=0", "x=1");
assert_solves_to("g(a)=0", "a=-1");
/* The equation has no solution since the user defined a = -3. So a is not
* replaced with its context value, and the equation becomes a + a + 2 = 0.
* The solution is therefore a = -1. */
set("d", "5");
set("c", "d");
set("h(x)", "c+d+3");
assert_solves_to({"h(x)=0", "c=-3"}, {"c=-3", "d=0"});
// c and d context values should not be used
assert_solves_to({"c+d=5", "c-d=1"}, {"c=3", "d=2"});
set("e", "8_g");
assert_solves_to({"e+1=0"}, {"e=-1"});
unset("a");
unset("b");
unset("c");
unset("d");
unset("e");
unset("f");
unset("g");
unset("h");
}