Skip to content

Commit 5f4269e

Browse files
Put a leftover reciprocal under the line, not on top of it (#712)
The rewrite that turns a vanishing factor against a diverging one into a quotient multiplied every remaining factor into the numerator. The children of a product arrive flattened through any division in it -- tan(x) * ln(x) comes apart into sin(x), cos(x)^(-1) and ln(x) -- so a leftover could itself be a reciprocal, and putting that on top rebuilt the very product the rewrite exists to take apart. The quotient simplified straight back to its own input and the rule worked at it until something else stopped it. Split into a numerator and a denominator instead. lim x->0+ (x * ln(x) / cos(x)) went from not terminating inside thirty seconds to 0. Suite 4675 passed, 0 failed; corpus unchanged at 111/117 with 0 wrong, 0 error and 0 timeout.
1 parent b00ed78 commit 5f4269e

2 files changed

Lines changed: 63 additions & 3 deletions

File tree

‎Sources/AngouriMath/Functions/Continuous/Limits/Transformations.cs‎

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -391,9 +391,17 @@ private static bool IsIndeterminateQuotient(Entity numerator, Entity denominator
391391
else
392392
rest *= factor;
393393
}
394-
return vanishing is { } zero && diverging is { } infinity
395-
? rest * infinity / (1 / zero).InnerSimplified
396-
: null;
394+
if (vanishing is not { } zero || diverging is not { } infinity)
395+
return null;
396+
// The leftover factors are split rather than multiplied on top, because the children
397+
// of a product arrive flattened through any division in it: tan(x) * ln(x) comes
398+
// apart into sin(x), cos(x)^(-1) and ln(x), and putting that cos(x)^(-1) into the
399+
// numerator would rebuild the very product this is meant to take apart -- the
400+
// quotient would simplify straight back to it and the rule would be handed its own
401+
// input. Into the denominator it gives ln(x) / (cos(x) / sin(x)), which is oo/oo
402+
// and which the rule settles at 0.
403+
var (restNumerator, restDenominator) = SplitProduct(rest);
404+
return restNumerator * infinity / (restDenominator * (1 / zero)).InnerSimplified;
397405
}
398406

399407
/// <remarks>
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//
2+
// Copyright (c) 2019-2022 Angouri.
3+
// AngouriMath is licensed under MIT.
4+
// Details: https://github.com/asc-community/AngouriMath/blob/master/LICENSE.md.
5+
// Website: https://am.angouri.org.
6+
//
7+
8+
using AngouriMath;
9+
using AngouriMath.Core;
10+
using AngouriMath.Extensions;
11+
using System;
12+
using System.Threading.Tasks;
13+
using Xunit;
14+
15+
namespace AngouriMath.Tests.Calculus
16+
{
17+
/// <summary>
18+
/// A product of something vanishing with something diverging, where the product also carries
19+
/// a factor that is neither. The children of a product arrive flattened through any division
20+
/// in it, so those leftovers can include a reciprocal, and multiplying one of those back on
21+
/// top rebuilt the very product the rewrite exists to take apart -- the quotient simplified
22+
/// straight back and the rule was handed its own input. Split into the denominator instead,
23+
/// x * ln(x) / cos(x) is answered rather than run at until it times out.
24+
/// </summary>
25+
public sealed class VanishingTimesDivergingTest
26+
{
27+
private static void AssertLimit(string expression, string expected)
28+
{
29+
var task = Task.Run(() =>
30+
expression.ToEntity().Limit("x", 0, ApproachFrom.Right).Simplify());
31+
Assert.True(task.Wait(TimeSpan.FromSeconds(30)), "the limit did not terminate");
32+
Assert.Equal(expected.ToEntity().Evaled, task.Result.Evaled);
33+
}
34+
35+
[Theory]
36+
[InlineData("x * ln(x) / cos(x)", "0")]
37+
[InlineData("x * ln(x) / (1 + x)", "0")]
38+
[InlineData("sqrt(x) * ln(x) / (2 + x)", "0")]
39+
public void ALeftoverReciprocalGoesUnderTheLine(string expression, string expected) =>
40+
AssertLimit(expression, expected);
41+
42+
/// <summary>The plain forms, which have no leftover at all, are unaffected.</summary>
43+
[Theory]
44+
[InlineData("x * ln(x)", "0")]
45+
[InlineData("sin(x) * ln(x)", "0")]
46+
[InlineData("sqrt(x) * ln(x)", "0")]
47+
[InlineData("x * cotan(x)", "1")]
48+
[InlineData("(1 - cos(x)) * cotan(x)", "0")]
49+
public void ThePlainFormsAreUnaffected(string expression, string expected) =>
50+
AssertLimit(expression, expected);
51+
}
52+
}

0 commit comments

Comments
 (0)