diff --git a/Sources/AngouriMath/Functions/Simplification/Simplificator.cs b/Sources/AngouriMath/Functions/Simplification/Simplificator.cs
index a8898d766..36cf0b2b1 100644
--- a/Sources/AngouriMath/Functions/Simplification/Simplificator.cs
+++ b/Sources/AngouriMath/Functions/Simplification/Simplificator.cs
@@ -206,6 +206,26 @@ not solve this issue completely and yet too slow to be accepted.
{
AddHistory(res.Expand().Simplify(-level));
AddHistory(res.Factorize().Simplify(-level));
+
+ // A multiple angle written out is worth having only where the pieces then
+ // cancel, so it has to be simplified in full before the metric can be
+ // asked -- the same reason Expand and Factorize are re-simplified above,
+ // and for the same reason it is a candidate rather than a step. The pass
+ // inside the loop offers the opened form to the trigonometric rules only,
+ // which settles an expression that is already one term; it cannot settle
+ // one whose cancellation needs a common denominator, because the passes
+ // that build one ran earlier in the loop, while the angles were still shut.
+ // That is https://github.com/asc-community/AngouriMath/issues/557: the
+ // reporter's second expression is 0, and reaches 0 through
+ // 2 sin(t) cos(t) and not through sin(2t).
+ var openedAngles = res
+ .Replace(Patterns.ExpandMultipleAngleRules)
+ .Replace(Patterns.NormalTrigonometricForm)
+ .InnerSimplified;
+ if (openedAngles != res)
+ // Expanded, and for the same reason res is expanded above: the
+ // cancellation only shows up once the products are multiplied out.
+ AddHistory(openedAngles.Expand().Simplify(-level));
}
return history.Values.SelectMany(x => x);
diff --git a/Sources/Tests/UnitTests/PatternsTest/DoubleAngleOverSineTest.cs b/Sources/Tests/UnitTests/PatternsTest/DoubleAngleOverSineTest.cs
index 14823395e..a2e0079a0 100644
--- a/Sources/Tests/UnitTests/PatternsTest/DoubleAngleOverSineTest.cs
+++ b/Sources/Tests/UnitTests/PatternsTest/DoubleAngleOverSineTest.cs
@@ -37,6 +37,34 @@ private static Entity Bare(string expression)
public void TheDoubleAngleOverTheSingleOne(string expression, string expected) =>
Assert.Equal(expected.ToEntity().Simplify(), Bare(expression));
+ ///
+ /// The second expression the reporter gives, which is the first one with a
+ /// quotient of sixth and eighth powers of sin(t) added in front of it. Both are 0.
+ ///
+ /// This one needs the opened angle to survive as far as the fractions: the quotient
+ /// only cancels once its terms are over a common denominator, and the passes that
+ /// build one run before the angles are opened. So the opened form was offered to the
+ /// complexity metric in the one shape where its payoff had not happened yet, and was
+ /// rightly rejected as the longer of the two. It is now simplified in full first --
+ /// including expanded, since the cancellation only shows up once the products are
+ /// multiplied out -- which is what Expand and Factorize already get.
+ ///
+ [Fact]
+ public void TheReportersSecondExpressionIsAlsoZero() =>
+ Assert.Equal(Entity.Number.Integer.Create(0), Bare(
+ "(cos(2 * t) * sin(t) ^ 6 * (-1) + cos(t) * sin(t) ^ 5 * sin(2 * t)"
+ + " - sin(2 * t) ^ 2 * sin(t) ^ 4 / 4) / sin(t) ^ 8 - 1"
+ + " + (sin(2 * t) * cosec(t)) ^ 2 / 4 - cos(2 * t) - sin(t) ^ 2"));
+
+ // The pieces it is built from, each 0 or 1 on its own. Together they say the
+ // cancellation is the quotient's and not only the tail's.
+ [Theory]
+ [InlineData("(cos(2 * t) * sin(t) ^ 6 * (-1) + cos(t) * sin(t) ^ 5 * sin(2 * t)"
+ + " - sin(2 * t) ^ 2 * sin(t) ^ 4 / 4) / sin(t) ^ 8", "1")]
+ [InlineData("(sin(t) ^ 6 - sin(2 * t) ^ 2 * sin(t) ^ 4 / 4) / sin(t) ^ 8 - 1", "0")]
+ public void TheQuotientCancelsOnItsOwn(string expression, string expected) =>
+ Assert.Equal(expected.ToEntity(), Bare(expression));
+
///
/// 2cos(u) is a number where sin(u) is zero and sin(2u) csc(u) is not, so the
/// cosecant's own condition has to be carried rather than dropped. It is the same