@@ -1361,15 +1361,15 @@ Entity Coefficient(Dictionary<EInteger, Entity> polynomial, int power)
13611361 }
13621362
13631363 // R = (N - P B)/x^k, whose coefficient of x^(m - k) is that of x^m in N - P B.
1364- Entity remainder = Number.Integer.Zero ;
1364+ var remainder = new Dictionary<int, Entity>() ;
13651365 for (var m = k; m <= System.Math.Max(degreeAbove, degreeBelow + k - 1); m++)
13661366 {
13671367 var coefficient = Coefficient(above, m);
13681368 for (var j = System.Math.Max(0, m - degreeBelow); j <= System.Math.Min(k - 1, m); j++)
13691369 coefficient -= series[j] * Coefficient(below, m - j);
13701370 coefficient = Functions.PartialFractions.InLowestTermsOverTheSymbols(coefficient);
13711371 if (!VanishesIdentically(coefficient))
1372- remainder += m == k ? coefficient : coefficient * MathS.Pow(x, m - k) ;
1372+ remainder[m - k] = coefficient;
13731373 }
13741374
13751375 // The part over x^k term by term, and the rest over the block as it is written.
@@ -1379,7 +1379,7 @@ Entity Coefficient(Dictionary<EInteger, Entity> polynomial, int power)
13791379 overX += j == k - 1
13801380 ? series[j] * IntegralPatterns.AntiderivativeLog(x)
13811381 : series[j] * MathS.Pow(x, j - k + 1) / (j - k + 1);
1382- if (remainder == Number.Integer.Zero )
1382+ if (remainder.Count == 0 )
13831383 return overX;
13841384 return OverTheRestOfTheBlock(remainder, block, x, integrateByParts) is { } overTheBlock
13851385 ? overX + overTheBlock
@@ -1398,10 +1398,69 @@ Entity Coefficient(Dictionary<EInteger, Entity> polynomial, int power)
13981398 /// https://github.com/asc-community/AngouriMath/issues/718
13991399 /// </remarks>
14001400 private static Entity? OverTheRestOfTheBlock(Entity remainder, Entity block, Entity.Variable x, bool integrateByParts)
1401+ => AtAnotherLinearOfTheBlock(remainder, block, x, integrateByParts)
1402+ ?? Integration.ComputeIndefiniteIntegral(remainder / block, x, integrateByParts);
1403+
1404+ /// <summary>
1405+ /// <see cref="OverTheRestOfTheBlock(Entity, Entity, Entity.Variable, bool)"/> for a rest
1406+ /// given by its coefficients, integrated a level down in named coefficients.
1407+ /// </summary>
1408+ private static Entity? OverTheRestOfTheBlock(Dictionary<int, Entity> rest, Entity block, Entity.Variable x, bool integrateByParts)
1409+ {
1410+ Entity remainder = Number.Integer.Zero;
1411+ foreach (var pair in rest.OrderBy(pair => pair.Key))
1412+ remainder += pair.Key == 0 ? pair.Value : pair.Value * (pair.Key == 1 ? x : MathS.Pow(x, pair.Key));
1413+ return AtAnotherLinearOfTheBlock(remainder, block, x, integrateByParts)
1414+ ?? IntegratedInNamedCoefficients(rest, block, x, integrateByParts);
1415+ }
1416+
1417+ /// <summary>
1418+ /// <c>R/B</c> split at a linear the block still holds, where that answer differentiates back.
1419+ /// </summary>
1420+ private static Entity? AtAnotherLinearOfTheBlock(Entity remainder, Entity block, Entity.Variable x, bool integrateByParts)
14011421 => IntegrateOverAPowerOfALinearBesideABlock(remainder, block, x, integrateByParts) is { } atAnotherRoot
14021422 && Functions.PartialFractions.DerivativeHoldsAtSampledPoints(atAnotherRoot, remainder / block, x)
14031423 ? atAnotherRoot
1404- : Integration.ComputeIndefiniteIntegral(remainder / block, x, integrateByParts);
1424+ : null;
1425+
1426+ /// <summary>
1427+ /// The integral of <c>R/B</c>, for a polynomial <c>R</c> in x given by its coefficients, with each coefficient of
1428+ /// <c>R</c> that is more than a symbol or a number a fresh symbol while it is integrated,
1429+ /// and put back in the answer.
1430+ /// </summary>
1431+ /// <remarks>
1432+ /// What a reduction leaves over its block has coefficients the reduction computed, such as
1433+ /// <c>(a^2 g - 3 a b d + 6 b^2 c)/a^2</c>, and the substitution search simplifies each
1434+ /// quotient it tries in them. Over <c>(a/b + x^3)^3</c> that took 40 s to decline where three
1435+ /// symbols take it 45 ms, and over <c>(a + b x^2 + c x^4)</c> past a minute.
1436+ /// https://github.com/asc-community/AngouriMath/issues/718
1437+ /// </remarks>
1438+ private static Entity? IntegratedInNamedCoefficients(Dictionary<int, Entity> rest, Entity block, Entity.Variable x, bool integrateByParts)
1439+ {
1440+ var named = new List<(Variable Name, Entity Value)>();
1441+ Entity everything = block;
1442+ foreach (var value in rest.Values)
1443+ everything += value;
1444+ Entity inNames = Number.Integer.Zero;
1445+ foreach (var pair in rest.OrderBy(pair => pair.Key))
1446+ {
1447+ var power = pair.Key;
1448+ var coefficient = pair.Value;
1449+ if (coefficient is not (Variable or Number))
1450+ {
1451+ var name = Variable.CreateUnique(everything, "k_r");
1452+ everything += name;
1453+ named.Add((name, coefficient));
1454+ coefficient = name;
1455+ }
1456+ inNames += power == 0 ? coefficient : coefficient * (power == 1 ? x : MathS.Pow(x, power));
1457+ }
1458+ if (Integration.ComputeIndefiniteIntegral(inNames / block, x, integrateByParts) is not { } answer)
1459+ return null;
1460+ foreach (var (name, value) in named)
1461+ answer = answer.Substitute(name, value);
1462+ return answer;
1463+ }
14051464
14061465 /// <summary>
14071466 /// <c>N/(L^k B)</c> for a linear <c>L = g + h x</c> other than x, beside a block <c>B</c>
@@ -1897,13 +1956,13 @@ Entity InU(Dictionary<EInteger, Entity> polynomial)
18971956 Entity answer = Number.Integer.Zero;
18981957 foreach (var pair in overPowers.OrderByDescending(pair => pair.Key))
18991958 answer = answer + pair.Value / (pair.Key == 1 ? trinomial : MathS.Pow(trinomial, pair.Key));
1900- Entity rest = Number.Integer.Zero ;
1901- foreach (var pair in atThisPower.OrderBy(pair => pair.Key) )
1959+ var rest = new Dictionary<int, Entity>() ;
1960+ foreach (var pair in atThisPower)
19021961 if (!VanishesIdentically(pair.Value))
1903- rest = rest + pair.Value * (pair. Key == 0 ? Number.Integer.One : pair.Key == 1 ? x : MathS.Pow(x, pair.Key)) ;
1904- if (rest != Number.Integer.Zero )
1962+ rest[ pair.Key] = pair.Value ;
1963+ if (rest.Count > 0 )
19051964 {
1906- if (Integration.ComputeIndefiniteIntegral (rest / trinomial, x, integrateByParts) is not { } overTheTrinomial)
1965+ if (IntegratedInNamedCoefficients (rest, trinomial, x, integrateByParts) is not { } overTheTrinomial)
19071966 return null;
19081967 answer = answer + overTheTrinomial;
19091968 }
0 commit comments