Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions src/expression.cc
Original file line number Diff line number Diff line change
Expand Up @@ -902,8 +902,18 @@ static size_t check_match(size_t eq, size_t eqsz,
bool want_var = must_be_non_constant(cat);
if (want_cst || want_int || want_var)
{
// At this point, if we have a numerical value, it was
// wrapped in an equation by grab_arguments.
// Wildcard naming convention: the first letter of the name
// determines the category. Letters a-c (or A-C) match numeric
// constants; letters i-k (or I-K) match integers. For constant
// patterns (a-c), reject symbolic expressions like √(2) without
// evaluating them — otherwise program::run would compute √(2) to
// 1.41421... and let it match as a constant, incorrectly folding
// '48·√2' into a decimal. Integer patterns (i-k) still allow
// evaluation, because expressions like K-1 need to be reduced to
// verify they produce an integer result (e.g. in 'X^K → X*X^(K-1)').
if (want_cst && object::is_symbolic(ftop->type()))
return 0;

size_t depth = rt.depth();
if (program::run(+ftop) != object::OK)
return 0;
Expand Down
21 changes: 17 additions & 4 deletions src/tests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9194,7 +9194,7 @@ void tests::symbolic_differentiation()
.expect("'X↑(A+2)·(A+2)÷X'");
step("Derivative of power of a numerical constant")
.test(CLEAR, "'2^X' 'X'", ID_Derivative)
.expect("'0.69314 71805 6·2↑X'");
.expect("'2↑X·ln 2'");
step("Derivative of power of a non-numerical constant")
.test(CLEAR, "'A^X' 'X'", ID_Derivative)
.expect("'A↑X·ln A'")
Expand Down Expand Up @@ -9307,7 +9307,7 @@ void tests::symbolic_integration()
.expect("'X↑(A+3)÷(A+3)'");
step("Primitive of power of a numerical constant")
.test(CLEAR, "'2^X' 'X'", ID_Primitive)
.expect("'2↑X÷0.69314 71805 6'");
.expect("'2↑X÷ln 2'");
step("Primitive of power of a non-numerical constant")
.test(CLEAR, "'A^X' 'X'", ID_Primitive)
.expect("'A↑X÷ln A'")
Expand Down Expand Up @@ -9343,11 +9343,11 @@ void tests::symbolic_integration()
step("Primitive of log2 and exp2")
.test(CLEAR, "'log2(A*X+B)+exp2(X*C-D)' 'X'",
LENGTHY(20000), ID_Primitive)
.expect("'((A·X+B)·log2(A·X+B)-(A·X+B)÷ln 2)÷A+exp2(X·C-D)÷(0.69314 71805 6·C)'");
.expect("'((A·X+B)·log2(A·X+B)-(A·X+B)÷ln 2)÷A+exp2(X·C-D)÷(C·ln 2)'");
step("Primitive of log10 and exp10")
.test(CLEAR, "'log10(A*X+B)+exp10(X*C-D)' 'X'",
LENGTHY(20000), ID_Primitive)
.expect("'((A·X+B)·log10(A·X+B)-(A·X+B)÷ln 10)÷A+exp10(X·C-D)÷(2.30258 50929 9·C)'");
.expect("'((A·X+B)·log10(A·X+B)-(A·X+B)÷ln 10)÷A+exp10(X·C-D)÷(C·ln 10)'");

step("Primitive of lnp1 and expm1")
.test(CLEAR, "'ln1p(A*X+B)+expm1(X*C-D)' 'X'",
Expand Down Expand Up @@ -13854,6 +13854,19 @@ void tests::regression_checks()
step("Bug 279: 0/0 should error out");
test(CLEAR, "0 0 /", ENTER).error("Divide by zero");

step("Bug 1620: AutoSimplify must not evaluate √(2) as a numeric constant in rewrites");
test(CLEAR,
"118", ENTER,
"48", ENTER,
F, // Open algebraic editor ('()' key)
C, // √x in editor → √(
KEY2, // type 2 → √(2
ENTER, // confirm → '√(2)' on stack
MUL, // 48 × '√(2)'
SUB, // 118 − 48×√(2)
C) // √(118 − 48×√(2))
.expect("'√(118-48·√ 2)'");

step("Bug 695: Putting program separators in names");
test(CLEAR,
LSHIFT,
Expand Down