Does |e| → ∞ as x → +∞? true / false / undefined (unknown).
( e: Expression, x: string, ce: ComputeEngine )
| 616 | if (isDefiniteValue(l)) return l.neg().evaluate(); |
| 617 | return undefined; |
| 618 | } |
| 619 | |
| 620 | if (op === 'Add') { |
| 621 | // After the leading-order rewrite the surviving terms are co-dominant |
| 622 | // (e.g. 1/x + 1/x², both → 0); sum their individual limits. |
| 623 | let acc: Expression = ce.Zero; |
| 624 | let posInf = 0; |
| 625 | let negInf = 0; |
| 626 | for (const t of oo(e)) { |
| 627 | const l = limitAtPosInf(t, x, ce, depth + 1); |
| 628 | if (!l) return undefined; |
| 629 | if (l.isInfinity === true) { |
| 630 | if (l.isNegative === true) negInf++; |
| 631 | else posInf++; |
| 632 | } else if (isDefiniteValue(l)) acc = acc.add(l); |
| 633 | else return undefined; |
| 634 | } |
| 635 | if (posInf > 0 && negInf > 0) return undefined; // ∞ − ∞ (needs cancellation) |
| 636 | if (posInf > 0) return ce.PositiveInfinity; |
| 637 | if (negInf > 0) return ce.NegativeInfinity; |
| 638 | return acc.evaluate(); |
| 639 | } |
| 640 | |
| 641 | if (op === 'Divide') return limitRatioAtPosInf(o1(e), o2(e), x, ce, depth); |
| 642 | |
| 643 | if (op === 'Power') return limitPowerAtPosInf(o1(e), o2(e), x, ce, depth); |
| 644 | |
| 645 | // √u and ⁿ√u (canonical forms of u^{1/2}, u^{1/n}): monotone for a real |
| 646 | // radicand, so they carry the argument's limit. A radicand → −∞ heads to an |
| 647 | // imaginary infinity — deferred (undefined) rather than resolved. |
| 648 | if (op === 'Sqrt' || op === 'Root') { |
| 649 | const inner = limitAtPosInf(o1(e), x, ce, depth + 1); |
| 650 | if (!inner) return undefined; |
| 651 | if (inner.isInfinity === true) |
| 652 | return inner.isPositive === true ? ce.PositiveInfinity : undefined; |
| 653 | if (isDefiniteValue(inner)) { |
| 654 | const rest = op === 'Root' ? [inner, o2(e)] : [inner]; |
| 655 | return ce.function(op, rest).evaluate(); |
| 656 | } |
| 657 | return undefined; |
| 658 | } |
| 659 | |
| 660 | if (op === 'Exp') { |
| 661 | const inner = limitAtPosInf(o1(e), x, ce, depth + 1); |
| 662 | return expOfLimit(inner, ce); |
| 663 | } |
| 664 | |
| 665 | if (op === 'Ln' || op === 'Log') { |
| 666 | const inner = limitAtPosInf(o1(e), x, ce, depth + 1); |
| 667 | return lnOfLimit(inner, ce); |
| 668 | } |
| 669 | |
| 670 | if (op === 'Multiply') return limitProductAtPosInf(oo(e), x, ce, depth); |
| 671 | |
| 672 | if (op === 'Arctan') { |
| 673 | const inner = limitAtPosInf(o1(e), x, ce, depth + 1); |
| 674 | if (inner?.isInfinity === true) |
| 675 | return inner.isNegative === true ? ce.Pi.div(-2) : ce.Pi.div(2); |
no test coverage detected