Skip to content

Fix #357: limits report a sign only when it is provable - #437

Draft
petlenz wants to merge 2 commits into
mainfrom
fix-357-limit-signs
Draft

petlenz wants to merge 2 commits into
mainfrom
fix-357-limit-signs

Conversation

@petlenz

@petlenz petlenz commented Sep 15, 2026

Copy link
Copy Markdown
Member

Closes #357.

The limit visitors now report a direction only when it is provable; otherwise unknown.

Behavior changes (before → after)

Case Before After
finite⁺ + finite⁻ finite⁺ unknown
finite⁻ + finite⁻ finite⁺ finite⁻
log(c), c finite > 0 finite⁺ unknown
1/f, f^(-c), log(f) with f → 0 and side unknown +∞ / +∞ / −∞ unknown
same, f is the limit variable → 0⁺ or f inferred positive +∞ / +∞ / −∞ unchanged
c^g with g → 0 and c → 0 or ∞ finite⁺ indeterminate
symbol other than the limit variable finite⁺ sign from assumptions, else unknown
sin, tan, asin, atan of f → 0 finite⁺ / unknown 0
sin, cos, tan of finite nonzero finite⁺ unknown
asin of ±∞ finite⁺ unknown
atan, asin of finite⁻ finite⁺ finite⁻
acos of finite⁺ (acos(1) = 0) finite⁺ unknown
sign(x) at 0⁺ / 0⁻ finite⁺ finite⁺ / finite⁻
t2s invariants (trace, det, dot, norm, eigenvalue, …) independent of the variable finite⁺ sign from assumptions (e.g. det of a PD tensor), else unknown
t2s scalar wrapper finite⁺ sign of the scalar value

Signed zero: no new direction values. limit_algebra::apply_log/apply_pow/apply_reciprocal take a zero_from_above flag; the visitors set it when the argument is the limit variable approaching 0⁺ or is inferred positive.

Needs a decision: two existing tests changed (separate commit b6f32cd). Both asserted a positive sign that is not provable:

  • ScalarLimit.OtherVariableFinite: an unassumed symbol y as x → 0⁺ can be negative (y = −1), so finite_positiveunknown.
  • T2sLimit.TensorDepIndependentExpr: det(G) takes either sign (det(−I) = −1), so finite_positiveunknown.

Trade-off. There is no sign-neutral "finite" direction, so an unknown-sign constant now makes ∞ + y unknown where +∞ would be true. Adding such a direction would restore that precision; left for a follow-up.

Tests (LimitVisitorTest.h): LimitAlgebra.{AddSigns, MulSigns, ZeroNeedsApproachSide, LogAndPowOfFiniteValues}, ScalarLimit.{OddFunctionsAtZero, ReciprocalOfSinAtZeroIsNotFinite, ZeroFromBelowHasNoLogOrReciprocal, SignAtZeroFollowsApproachSide, AssumedSignOfOtherSymbols, InverseTrigSigns}, T2sLimit.{ConstantSignsComeFromValuesAndAssumptions, ExactMatchReciprocalNeedsApproachSide}. Negative control against main's limit sources: 9 of the new tests fail; MulSigns passes (locks in already-correct behavior); the two algebra probes using the new signature can't compile there and are covered end to end. Full suite 2358/2358 (gcc-14 Debug, -Werror minus pre-existing pedantic/deprecated).

Limit algebra:
- finite + finite is positive or negative only when both signs agree;
  mixed signs give unknown
- log(c) for finite positive c is unknown (negative below 1)
- 1/0, 0^(-c) and log(0) need the zero to be approached from above;
  callers pass that knowledge, otherwise the result is unknown
- c^0 with c -> 0 or c -> inf is indeterminate

Scalar limit visitor:
- a symbol other than the limit variable takes its sign from its
  assumptions, otherwise unknown
- sin, tan, asin, atan of an argument tending to 0 tend to 0; cos and
  acos tend to a positive value; other finite arguments of sin, cos,
  tan and a positive argument of acos give unknown
- asin of an infinite argument is unknown; atan and asin keep the
  argument's sign
- sign(x) at 0 follows the side of approach

Tensor-to-scalar limit visitor:
- invariants independent of the limit variable take their sign from
  their assumptions, otherwise unknown
- a scalar wrapper takes the sign of its scalar value
- pow and log of the exact limit variable use the side of approach

Signed-off-by: petlenz <peterlenz89.pl@gmail.com>
ScalarLimit.OtherVariableFinite: y has no assumptions, so as x -> 0+ it
is a constant of either sign; finite_positive is not provable (y = -1 is
a counterexample). Expected result is now unknown.

T2sLimit.TensorDepIndependentExpr: det(G) is independent of F but a
general 3x3 determinant takes either sign (det(-I) = -1). Expected result
is now unknown.

Signed-off-by: petlenz <peterlenz89.pl@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Limit machinery fabricates finite_positive: lim sin(x) at x→0 reported nonzero, neg+neg → positive in combine_add, sign-assumed symbols ignored

1 participant