Repository navigation
A monomial body is multiplied in closed form (#717) - #1153
Merged
Merged
Conversation
The same for `product` as #1152 did for `sum`, over the narrower class a product's shape allows: a sum of two terms is the sum of their sums, and a product of two terms is not the product of their products in any way that helps. What separates is the body that is one term. product(k, k, 1, n) was carried is piecewise(n! provided n >= 1, 1) product(2, k, 1, 500) was carried is the 151-digit integer `product(k^2, k, 1, n)` is `(n!)^2`, `product(2 * k, k, 1, n)` is `n! * 2^n`, and a constant body needs no factorial at all -- `product(c, k, m, n)` is `c^(n - m + 1)`, symbolic lower bound included. This closes the last of the three `sum`/`product` rows in #717's survey. The condition is `to >= from` where the sum's is `to >= from - 1`, and the one point between them is the reason. At the empty range itself the closed form is `c^0`, which is 1 for every `c` but zero and undefined there, while the empty product is 1 for every `c` including zero. Giving that point to the identity branch keeps a value from becoming an undefinedness. It cost nothing: both branches say 1 there. Found by comparing the closed form against the expansion at bounds either side of the boundary, which is why the check is written that way rather than against a printed form. A lower bound that is not a concrete integer of at least one is declined where the index is in the body, rather than conditioned. `b!/(a-1)!` holds only for `a >= 1`; below that the range runs through zero so the product is 0 while `(a-1)!` is undefined -- and `a < 1` does not make the range empty, so it cannot share a branch with the empty-range case. A piecewise reading "identity otherwise" would be wrong there. Three tests asserted the product is carried, two of them added by #1152 with the reason it could not yet be answered. They now assert what is still carried -- a body that is not one term. Syntax.md, MathS.Product's summary and the #1152 entry in BREAKING-CHANGES.md are corrected the same way. Comparison.md's cell is again left as measured, its note now naming two moved rows rather than one. Full suite 9487 passed, 0 failed. Part of #717. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura
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.
The same for
productas #1152 did forsum, over the narrower class a product's shape allows.product(k ^ 2, k, 1, n)(n!)^2product(k ^ 3, k, 1, n)(n!)^3product(2 * k, k, 1, n)n! * 2^nproduct(c, k, m, n)c^(n - m + 1)— symbolic lower bound, no factorial neededThis closes the last of the three
sum/productrows in #717's survey.Narrower than the sum, and not by omission
A sum of two terms is the sum of their sums; a product of two terms is not the product of their
products in any way that helps. There is no linearity to take a general polynomial apart with, so
what separates is the body that is one term —
c * k^p, over which the product becomes apower of the constant times a power of the factorial.
product(k + 1, k, 1, n)is therefore still carried, and there is a test saying so.The condition moved by one, and that is the interesting part
The sum's condition is
to >= from - 1. The product's isto >= from, and the single pointbetween them is the reason.
At the empty range itself the closed form is
c^0— which is1for everycexcept zero,where it is undefined, while the empty product is
1for everycincluding zero. Handingthat one point to the identity branch keeps a value from becoming an undefinedness, which is what
the contract's O4 asks. It costs nothing: both branches say
1there.I found this by comparing the closed form against the expansion at bounds either side of the
boundary — it is not visible from the formula, and it is why the tests are written as agreement
with the expansion rather than against a printed form.
A lower bound that cannot be a condition
product(k, k, a, b)isb!/(a-1)!only wherea >= 1. Below that the range runs through zero,so the product is
0, while(a-1)!is undefined at the negative integers.That cannot go into the piecewise condition, because
a < 1does not mean the range is empty— a branch reading "identity otherwise" would answer
1where the product is0. So it isdecided before anything is built: a lower bound that is not a concrete integer of at least one is
declined outright where the index is in the body.
product(k, k, 0, n)andproduct(k, k, m, n)stay as written, with tests carrying that reason.
A constant body has no such restriction, there being no factorial in its answer — hence
product(c, k, m, n)working withmsymbolic.Records that changed their verdict
Three tests asserted the product is carried, two of them added by #1152 an hour earlier, with
the reason it could not yet be answered. They now assert what is still carried — a body that is
not one term.
Corrected the same way:
Syntax.md,MathS.Product's<returns>, and #1152's ownBREAKING-CHANGES.mdentry, which said answering the product "is not done here".Comparison.md'sdeclinescell is again left as it was measured. That table records onesympyparityrun at one commit, and a hand-corrected cell would be a measurement nobody took; itsnote now names two moved rows rather than one, and says the row between them — infinite series —
has not moved, an infinite bound being refused outright by both closed forms.
Verification
Full suite 9487 passed, 0 failed, 14 skipped. 27 new tests.
Every closed form is checked by agreeing with the expansion at bounds on both sides of the
empty-range boundary. The exception is the
c = 0test, which is about the boundary itself andwould pass vacuously if it only compared the two routes.
Part of #717.