mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
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.
192 lines
6.0 KiB
C++
192 lines
6.0 KiB
C++
#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");
|
||
}
|