Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions Sources/AngouriMath/Functions/Continuous/Limits/Transformations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -391,9 +391,17 @@ private static bool IsIndeterminateQuotient(Entity numerator, Entity denominator
else
rest *= factor;
}
return vanishing is { } zero && diverging is { } infinity
? rest * infinity / (1 / zero).InnerSimplified
: null;
if (vanishing is not { } zero || diverging is not { } infinity)
return null;
// The leftover factors are split rather than multiplied on top, because 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), and putting that cos(x)^(-1) into the
// numerator would rebuild the very product this is meant to take apart -- the
// quotient would simplify straight back to it and the rule would be handed its own
// input. Into the denominator it gives ln(x) / (cos(x) / sin(x)), which is oo/oo
// and which the rule settles at 0.
var (restNumerator, restDenominator) = SplitProduct(rest);
return restNumerator * infinity / (restDenominator * (1 / zero)).InnerSimplified;
}

/// <remarks>
Expand Down
52 changes: 52 additions & 0 deletions Sources/Tests/UnitTests/Calculus/VanishingTimesDivergingTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//
// Copyright (c) 2019-2022 Angouri.
// AngouriMath is licensed under MIT.
// Details: https://github.com/asc-community/AngouriMath/blob/master/LICENSE.md.
// Website: https://am.angouri.org.
//

using AngouriMath;
using AngouriMath.Core;
using AngouriMath.Extensions;
using System;
using System.Threading.Tasks;
using Xunit;

namespace AngouriMath.Tests.Calculus
{
/// <summary>
/// A product of something vanishing with something diverging, where the product also carries
/// a factor that is neither. The children of a product arrive flattened through any division
/// in it, so those leftovers can include a reciprocal, and multiplying one of those back on
/// top rebuilt the very product the rewrite exists to take apart -- the quotient simplified
/// straight back and the rule was handed its own input. Split into the denominator instead,
/// x * ln(x) / cos(x) is answered rather than run at until it times out.
/// </summary>
public sealed class VanishingTimesDivergingTest
{
private static void AssertLimit(string expression, string expected)
{
var task = Task.Run(() =>
expression.ToEntity().Limit("x", 0, ApproachFrom.Right).Simplify());
Assert.True(task.Wait(TimeSpan.FromSeconds(30)), "the limit did not terminate");
Assert.Equal(expected.ToEntity().Evaled, task.Result.Evaled);
}

[Theory]
[InlineData("x * ln(x) / cos(x)", "0")]
[InlineData("x * ln(x) / (1 + x)", "0")]
[InlineData("sqrt(x) * ln(x) / (2 + x)", "0")]
public void ALeftoverReciprocalGoesUnderTheLine(string expression, string expected) =>
AssertLimit(expression, expected);

/// <summary>The plain forms, which have no leftover at all, are unaffected.</summary>
[Theory]
[InlineData("x * ln(x)", "0")]
[InlineData("sin(x) * ln(x)", "0")]
[InlineData("sqrt(x) * ln(x)", "0")]
[InlineData("x * cotan(x)", "1")]
[InlineData("(1 - cos(x)) * cotan(x)", "0")]
public void ThePlainFormsAreUnaffected(string expression, string expected) =>
AssertLimit(expression, expected);
}
}
Loading