Files
Upsilon/apps/solver/test/equation_store.cpp

186 lines
5.8 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
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");
// 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, {});
}
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) {
// TODO: Does it make sense to test polar vs cartesian?
// It doesn't seem to work when converting expressions anyway...
#if 0
set_complex_format(Polar);
assert_solves_to("x+𝐢=0", "x=^(-(π/2)𝐢)");
assert_solves_to("x+√(-1)=0", "x=^(-(π/2)𝐢)");
assert_quadratic_solves_to("x^2+x+1=0", {"x=^(-(2π/3)𝐢)", "x=^((2π/3)𝐢)"});
assert_quadratic_solves_to("x^2-√(-1)=0", {"x=^(-(3×π/4)𝐢)", "x=^((π/4)𝐢)"});
assert_solves_to("root(-8,3)*x+3=0", "x=3/2^((2π/3)𝐢)");
reset_complex_format();
#endif
}
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"});
unset("a");
unset("b");
unset("c");
unset("d");
unset("e");
unset("f");
unset("g");
unset("h");
}