Fix #344: remove division-style rules from the pow simplifier - #388
Merged
Conversation
petlenz
force-pushed
the
fix-340-hash-identity-sweep
branch
from
July 24, 2026 19:26
89658e1 to
349c423
Compare
petlenz
force-pushed
the
fix-344-pow-division-rules
branch
from
July 24, 2026 19:26
d3e4962 to
951d0e8
Compare
This was referenced Jul 24, 2026
petlenz
force-pushed
the
fix-340-hash-identity-sweep
branch
from
July 25, 2026 11:56
349c423 to
9590ea4
Compare
petlenz
force-pushed
the
fix-344-pow-division-rules
branch
from
July 25, 2026 12:06
951d0e8 to
8f5ef67
Compare
petlenz
force-pushed
the
fix-340-hash-identity-sweep
branch
from
July 25, 2026 13:25
9590ea4 to
f2a2102
Compare
petlenz
force-pushed
the
fix-344-pow-division-rules
branch
7 times, most recently
from
July 26, 2026 18:40
cb35152 to
444bca1
Compare
The negative-exponent branches treated pow(a, -b) as the division a/b:
pow(x, -x) -> 1, pow(x*y, -x) -> y, pow(x, -y)*y -> x, and pow(-e, p)
-> -pow(e, p) for every exponent (so pow(-x, 2) evaluated to -9 where
+9 is correct; same for pow(-trace(A), 2) -> -36 in the t2s domain,
which shares the generic dispatch). Real division composes as
mul x pow(rhs, -1) with a constant exponent, so these branches never
fired on legitimate divisions - only on wrong inputs.
- Deleted: the expr/expr->1 and erase-matching-factor branches in
pow_dispatch::get_default, the x*y*z/x branch in
mul_pow_dispatch::dispatch(negative_type) and its scalar copy, and
the pow(expr,-p)*p -> expr branch in scalar_pow_mul.
- pow(-e, p) sign pull-out is now gated on a provably integer
exponent: even folds to pow(e, p), odd to -pow(e, p), anything else
stays structural. x^(-1)*x -> 1 keeps working via exponent addition.
- POW_Simplification / TensorToScalar_PowSimplification pinned the
deleted rules ('division cancellation', 'mul factor cancel',
unconditional negative-base extraction); their expectations update
to the corrected contract per #344.
- New evaluation-verified lock-in tests in CoreBugFixTest.h.
Signed-off-by: petlenz <peterlenz89.pl@gmail.com>
…ric bases The even/odd fold built a raw pow node, so nested bases stopped canonicalizing: pow(-pow(x,2), 2) stayed pow(pow(x,2),2) and never cancelled against pow(x,4). Recursing through pow() restores the nested folds; numeric bases stay structural so pow(2,-1) keeps printing as a division instead of folding to the rational 1/2 (PRINT_DivisionFormat contract). Regression test included. Signed-off-by: petlenz <peterlenz89.pl@gmail.com>
The division-style fold in scalar_pow_mul::dispatch(scalar) was removed with the other unsound rules, leaving its 'power' alias unused (gcc -Wunused-variable). Signed-off-by: petlenz <peterlenz89.pl@gmail.com>
petlenz
force-pushed
the
fix-344-pow-division-rules
branch
from
July 26, 2026 19:03
444bca1 to
44b9918
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #344. Stacked on #387.
The negative-exponent branches of the shared pow simplifier treated
pow(a,−b)as the divisiona/b. Probe-confirmed wrong results fixed (scalar and t2s share the generic dispatch):pow(-x, 2)→-pow(x,2)(evaluated −9)pow(x,2)→ +9pow(-trace(A), 2)→ −36pow(x, -x)→1x^(−x)(6⁻⁶ ≈ 2.14e−5)pow(x*y, -x)→ypow(x, -y) * y→xy·x^(−y)pow(-x, y)→-pow(x,y)pow(-x,y)Design
mul × pow(rhs, −1)with a constant exponent, so they never fired on legitimate input.x^(−1)·x → 1keeps working via the exponent-addition rule (locked in).pow(-e, p)sign pull-out is gated on a provably integer exponent (pow_integer_exponenton the numeric value): even →pow(e,p), odd →-pow(e,p), otherwise structural. Symbolic-but-provable parity (assumption tags) is epic [epic] Complete the assumption algebra so simplification guards can be sound instead of inert #381's follow-up.mul_pow_dispatchis pow distributes/merges over products without integer-exponent guard: pow(x*y^2,1/2)→y*sqrt(x), sqrt(x)*sqrt(y)→sqrt(x*y) #345's scope (integer-exponent guard), not touched here.Tests
POW_Simplification/TensorToScalar_PowSimplificationexplicitly pinned the deleted rules ('division cancellation', 'mul factor cancel'); their expectations update to the corrected contract. Two new evaluation-verified lock-in tests. Full suite: 2426/2426 pass.