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
Original file line number Diff line number Diff line change
Expand Up @@ -3494,6 +3494,28 @@ node is Cotanf(var cotangentArgument)
if (!expr.ContainsNode(tangent))
return null;

// An even power of the secant, cosine, sine or cosecant of x is a rational function
// of the tangent, exactly and wherever it is defined: `sec^2 = 1 + tan^2`,
// `cos^2 = 1/(1 + tan^2)`, `sin^2 = tan^2/(1 + tan^2)`. Timofeev's
// `(sec^2 - 3 tan sqrt(4 sec^2 + 5 tan^2))/(sin^2 (4 sec^2 + 5 tan^2)^(3/2))` is
// `((1 + u^2) - 3u sqrt(4 + 9u^2))/(u^2 (4 + 9u^2)^(3/2))` under the tangent, and was
// declined for the secant and the sine that survived the rewriting. An odd power is
// not a function of the tangent -- its sign is not -- and is left, to survive and
// decline as before.
var secantSquared = 1 + MathS.Sqr(tangent);
expr = expr.Replace(node => node switch
{
Powf(Secantf(var a), Number.Integer even) when a == x && even.EInteger.IsEven && even.EInteger.Sign > 0
=> MathS.Pow(secantSquared, even.EInteger.ToInt32Checked() / 2),
Powf(Cosf(var a), Number.Integer even) when a == x && even.EInteger.IsEven && even.EInteger.Sign > 0
=> MathS.Pow(secantSquared, -(even.EInteger.ToInt32Checked() / 2)),
Powf(Sinf(var a), Number.Integer even) when a == x && even.EInteger.IsEven && even.EInteger.Sign > 0
=> MathS.Pow(MathS.Sqr(tangent) / secantSquared, even.EInteger.ToInt32Checked() / 2),
Powf(Cosecantf(var a), Number.Integer even) when a == x && even.EInteger.IsEven && even.EInteger.Sign > 0
=> MathS.Pow(secantSquared / MathS.Sqr(tangent), even.EInteger.ToInt32Checked() / 2),
_ => node,
});

var uSub = Variable.CreateUnique(expr, "u_tan");
var inU = expr.Substitute(tangent, uSub);
if (inU.ContainsNode(x))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,16 @@ public void TheOtherFunctionsAreWrittenAsSineAndCosine(string integrand)
/// simplification the substitution runs takes <c>sqrt(.../cos(x)^2)</c> as
/// <c>.../cos(x)</c>, its value where the cosine is positive and its negative
/// elsewhere, and Timofeev's was answered wrongly on half the line that way. Declined
/// or right on both sides, never wrong.
/// or right on both sides, never wrong -- and answered now, by the tangent
/// substitution, which writes its even powers of the secant and the sine as the
/// rational functions of the tangent they are, exactly.
/// </summary>
[Theory]
[InlineData("(sec(x)^2 - 3*sqrt(4*sec(x)^2 + 5*tan(x)^2)*tan(x))/(sin(x)^2*(4*sec(x)^2 + 5*tan(x)^2)^(3/2))")]
public void AnOddComplementUnderARootIsNotWrittenSo(string integrand)
{
var integral = integrand.ToEntity().Integrate("x");
if (integral.Stringize().Contains("integral("))
return; // declined is a legitimate verdict; a wrong answer is not
Assert.DoesNotContain("integral(", integral.Stringize());
DifferentiatesBack(integrand, new[] { -2.6, -2.0, -0.4, 0.4, 2.0, 2.6 });
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,21 @@ private static void DifferentiatesBack(string integrand)
[InlineData("tan(x)/(1 + tan(x)^2)")]
public void AFunctionOfTheTangentAlone(string integrand) => DifferentiatesBack(integrand);

/// <summary>
/// An even power of the secant, cosine, sine or cosecant is a rational function of the
/// tangent, exactly and wherever it is defined, and is written as one before the test:
/// <c>sec^2 = 1 + tan^2</c>, <c>cos^2 = 1/(1 + tan^2)</c>, <c>sin^2 = tan^2/(1 + tan^2)</c>.
/// Timofeev's is <c>((1 + u^2) - 3u sqrt(4 + 9u^2))/(u^2 (4 + 9u^2)^(3/2))</c> under the
/// tangent, and was declined for the secant and the sine that survived. An odd power
/// is not a function of the tangent, and is left to decline as before.
/// </summary>
[Theory]
[InlineData("sec(x)^2*sqrt(tan(x))")]
[InlineData("sin(x)^2/(1 + tan(x))")]
[InlineData("csc(x)^4*tan(x)^(3/2)")]
[InlineData("(sec(x)^2 - 3*sqrt(4*sec(x)^2 + 5*tan(x)^2)*tan(x))/(sin(x)^2*(4*sec(x)^2 + 5*tan(x)^2)^(3/2))")]
public void AnEvenPowerOfTheOthersIsWrittenInTheTangent(string integrand) => DifferentiatesBack(integrand);

/// <summary>
/// A power of the tangent, which the rewrite turns into an <b>improper</b> rational
/// function — <c>u^2/(1 + u^2)</c> and <c>u^3/(1 + u^2)</c>. These were declined while
Expand Down
Loading