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
15 changes: 15 additions & 0 deletions BREAKING-CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2319,6 +2319,21 @@ one reads a numeric slope, and writes an offset out by the addition formula, whi
| `"csc(1+x)*csc(2+2*x)^2".ToEntity().Integrate("x")` | `integral(...)` | an antiderivative in `cos(1 + x)` |
| `"sin(a+b*x)^3/sin(2*a+2*b*x)^(3/2)".ToEntity().Integrate("x")` | `integral(...)` | an antiderivative in `tan(a + b x)` |

### Multiples of one linear argument are written in it with `x` beside them in a linear

`csc(a + b x) sin(3a + 3b x)/(c + d x)` was left unevaluated, and so was each power of `c + d x`
below the bar. Writing the arguments in `u = a + b x` declined wherever `x` stood outside them as
well. Where it stands there only in sums, products and powers, it is written in `u` too, as
`(u - a)/b`, and the linears in the answer are put back in lowest terms. Rubi's 4.7.3
([#718](https://github.com/asc-community/AngouriMath/issues/718), PR
[#1863](https://github.com/asc-community/AngouriMath/pull/1863)).

| Input | Was (2.5.0) | Now |
|---|---|---|
| `"csc(a+b*x)*sin(3*a+3*b*x)/(c+d*x)".ToEntity().Integrate("x")` | `integral(...)` | 190 characters, in `ln`, `Si` and `Ci` of a multiple of `c + d x` |
| `"csc(a+b*x)*sin(3*a+3*b*x)/(c+d*x)^4".ToEntity().Integrate("x")` | `integral(...)` | 736 characters |
| `"csc(2+3*x)*sin(6+9*x)/(c+d*x)".ToEntity().Integrate("x")` | `integral(...)` | 194 characters |

### A function of one linear under a power inside a sum is written in that linear

`x^3/(a + b (c + d x)^3)` was left unevaluated, and `(c + d x)^4/(a + b (c + d x)^3)` ran for more
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13297,8 +13297,10 @@ Entity Named(Entity value)
/// <c>csc(1 + x) csc(2 + 2x)^2</c> became a rational function of the sine and cosine with
/// <c>sin(2)</c> and <c>cos(2)</c> in its coefficients, and ran twenty seconds; with the slope
/// a symbol it declined at once. Only where some argument has an offset or a symbolic
/// slope, the rest being that rule's already, and where x stands nowhere else. At the
/// question asked or one below it, since it lands on the chain in u. Rubi's 4.7.1.
/// slope, the rest being that rule's already, and where x stands elsewhere only
/// algebraically: <c>csc(a + b x) sin(3a + 3b x)/(c + d x)</c> is
/// <c>csc(u) sin(3u)/(b c + d (u - a))</c> over <c>b</c>, Rubi's 4.7.3. At the question
/// asked or one below it, since it lands on the chain in u. Rubi's 4.7.1.
/// https://github.com/asc-community/AngouriMath/issues/718
/// </remarks>
internal static Entity? SolveByWritingMultiplesOfOneLinearArgument(Entity expr, Entity.Variable x, bool integrateByParts)
Expand Down Expand Up @@ -13348,12 +13350,26 @@ Entity Named(Entity value)
Cosecantf(var a) when Of(a) is { } v => new Cosecantf(v),
_ => node,
});
if (inU.ContainsNode(x))
return null;
// x beside the functions as well, algebraically -- `csc(a + b x) sin(3a + 3b x)/(c + d x)`
// -- is written in u too, x = (u - p)/q.
var beside = inU.ContainsNode(x);
if (beside)
{
if (inU.Nodes.Any(node => node.ContainsNode(x) && node is not (Variable or Sumf or Minusf or Mulf or Divf)
&& !(node is Powf(_, var exponent) && !exponent.ContainsNode(x))))
return null;
inU = inU.Substitute(x, (u - firstOffset) / firstSlope).InnerSimplified;
}
// dx = du/q.
if (Integration.ComputeAsAQuestionOfItsOwn((inU / firstSlope).InnerSimplified, u, integrateByParts) is not { } answer)
return null;
var back = answer.Substitute(u, first);
// And each linear the substitution wrote, `b c + d (a + b x - a)`, back in lowest terms.
if (beside)
back = back.Replace(node => node is Sumf or Minusf && node.ContainsNode(x)
&& TreeAnalyzer.TryGetPolyLinear(node, x, out var slope, out var offset) && !slope.ContainsNode(x) && !offset.ContainsNode(x)
? LowestOverTheSymbols(slope) * x + LowestOverTheSymbols(offset)
: node).InnerSimplified;
return back.Nodes.Any(node => node == MathS.NaN) ? null : back;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,22 +77,29 @@ private static void DifferentiatesBack(string integrand, string variable = "x")
/// Multiples of one linear with an offset or a symbolic slope, written in that linear:
/// <c>csc(1 + x) csc(2 + 2x)^2</c> ran twenty seconds with the offsets written out by the
/// addition formula, and <c>csc(a + b x) csc(2a + 2b x)^2</c> was declined for its slope.
/// Rubi's 4.7.1.
/// Rubi's 4.7.1; and with x beside them in a linear, <c>csc(a + b x) sin(3a + 3b x)/(c + d x)</c>,
/// which was declined whatever the slope, Rubi's 4.7.3.
/// </summary>
[Theory]
[InlineData("csc(1 + x)*csc(2 + 2*x)^2")]
[InlineData("sin(3 + 3*x)/sin(1 + x)")]
[InlineData("csc(2 + 3*x)*sin(6 + 9*x)/(1 + x)")]
[InlineData("csc(2 + 3*x)*sin(6 + 9*x)/(1 + x)^2")]
public void MultiplesOfOneLinearArgument(string integrand) => DifferentiatesBack(integrand);

[Theory]
[InlineData("csc(a + b*x)*csc(2*a + 2*b*x)^2")]
[InlineData("cos(a + b*x)^2/sin(2*a + 2*b*x)^5")]
[InlineData("csc(a + b*x)*sin(3*a + 3*b*x)/(c + d*x)")]
[InlineData("csc(a + b*x)*sin(3*a + 3*b*x)/(c + d*x)^2")]
[InlineData("csc(a + b*x)*sin(3*a + 3*b*x)/(c + d*x)^4")]
public void MultiplesOfOneLinearArgumentWithASymbolicSlope(string integrand)
{
var integral = integrand.ToEntity().Integrate("x");
Assert.DoesNotContain("integral(", integral.Stringize());
var derivative = integral.Substitute("C", 0).Differentiate("x").Substitute("a", 0.3).Substitute("b", 1.2);
var original = integrand.ToEntity().Substitute("a", 0.3).Substitute("b", 1.2);
var derivative = integral.Substitute("C", 0).Differentiate("x")
.Substitute("a", 0.3).Substitute("b", 1.2).Substitute("c", 0.7).Substitute("d", 1.3);
var original = integrand.ToEntity().Substitute("a", 0.3).Substitute("b", 1.2).Substitute("c", 0.7).Substitute("d", 1.3);
var compared = 0;
foreach (var at in new[] { 0.3, 0.5, 0.9, 1.1 })
{
Expand Down
Loading