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
12 changes: 12 additions & 0 deletions BREAKING-CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,18 @@ one inside another was answered with the empty set, a claim that it has no solut
| `"1/(2 + p^(-3)) = 1/3".Solve("p")` | `{ }` | `{ 1, -1/2 + i * 1/2 * sqrt(3), -1/2 + i * -1/2 * sqrt(3) }` |
| `"1/(1 + x^(-2)) = y".Solve("x")` | `{ }` | `{ ((-1) / (-y) - 1) ^ (-1/2), -((-1) / (-y) - 1) ^ (-1/2) }` |

### A quartic that is biquadratic once depressed is solved

**Silent: a quartic whose depressed form `y^4 + alpha y^2 + gamma`, for `y = x + b/(4a)`, has no cubic term is solved,
where it was answered `{ }`.** Its roots were shifted back by `-b a / 4` where the shift is `-b/(4a)`, so with a leading
coefficient other than `1` or `-1` every candidate was off and failed its check, and the empty set claimed there was no
root. An equation in a square root whose squared form is such a quartic was answered `{ }` with it.

| Input | Was (2.6.0) | Now |
|---|---|---|
| `"31x^4 - 62x^3 + 33x^2 - 2x - 1 = 0".ToEntity().Solve("x")` | `{ }` | `{ 1/2 + -sqrt((27/62 + -8/31 * sqrt(2)) / 2), … }`, four real roots |
| `"x^2 - x - 1 = 4x*sqrt(2x^2 - 4x + 2)".ToEntity().Solve("x")` | `{ }` | `{ 1/2 + -sqrt((27/62 + 8/31 * sqrt(2)) / 2) }` |

### A quotient of logarithms is differentiated only where both diverge

**Silent: a limit of a quotient of logarithms whose divisor tends to 0 is no longer answered by l'Hopital's rule, which
Expand Down
3 changes: 3 additions & 0 deletions Sources/.editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ file_header_template=\nCopyright (c) 2019-2026 Angouri.\nAngouriMath is licensed
[Tests/UnitTests/Algebra/ExponentialTwoBasesTest.cs]
file_header_template=\nCopyright (c) 2019-2026 Angouri.\nAngouriMath is licensed under MIT.\nDetails: https://github.com/asc-community/AngouriMath/blob/master/LICENSE.md.\nWebsite: https://am.angouri.org.\n

[Tests/UnitTests/Algebra/SolveTest/ADepressedBiquadraticQuarticTest.cs]
file_header_template=\nCopyright (c) 2019-2026 Angouri.\nAngouriMath is licensed under MIT.\nDetails: https://github.com/asc-community/AngouriMath/blob/master/LICENSE.md.\nWebsite: https://am.angouri.org.\n

[Tests/UnitTests/Algebra/OneByOneMatrixTest.cs]
file_header_template=\nCopyright (c) 2019-2026 Angouri.\nAngouriMath is licensed under MIT.\nDetails: https://github.com/asc-community/AngouriMath/blob/master/LICENSE.md.\nWebsite: https://am.angouri.org.\n

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,9 +268,14 @@ internal static IEnumerable<Entity> SolveQuartic(Entity a, Entity b, Entity c, E
var gamma = (-3 * MathS.Pow(b, 4) / (256 * MathS.Pow(a, 4)) + MathS.Sqr(b) * c / (16 * MathS.Pow(a, 3)) - (b * d) / (4 * MathS.Sqr(a)) + e / a)
.InnerSimplified;

// Biquadratic once depressed: y^4 + alpha y^2 + gamma = 0 for y = x + b/(4a), so x is
// the root of the quadratic in y^2 shifted back by b/(4a). The shift was written
// -b / 4 * a, which is -b a / 4, and for a leading coefficient other than 1 or -1 every
// candidate was off and failed its check: 31x^4 - 62x^3 + 33x^2 - 2x - 1 = 0, with four
// real roots, was answered { }.
if (beta.Evaled == 0)
return sqrtsOf1.SelectMany(_ => sqrtsOf1,
(s, t) => -b / 4 * a + s * MathS.Sqrt((-alpha + t * MathS.Sqrt(MathS.Sqr(alpha) - 4 * gamma)) / 2));
(s, t) => -b / (4 * a) + s * MathS.Sqrt((-alpha + t * MathS.Sqrt(MathS.Sqr(alpha) - 4 * gamma)) / 2));

var oneThird = Rational.Create(1, 3);
var P = (-MathS.Sqr(alpha) / 12 - gamma)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//
// Copyright (c) 2019-2026 Angouri.
// AngouriMath is licensed under MIT.
// Details: https://github.com/asc-community/AngouriMath/blob/master/LICENSE.md.
// Website: https://am.angouri.org.
//

using System.Linq;
using AngouriMath.Extensions;
using Xunit;
using static AngouriMath.Entity;
using static AngouriMath.Entity.Set;

namespace AngouriMath.Tests.Algebra
{
/// <summary>
/// A quartic whose depressed form <c>y^4 + alpha y^2 + gamma</c>, for <c>y = x + b/(4a)</c>, has
/// no cubic term is solved as a quadratic in <c>y^2</c> and shifted back by <c>b/(4a)</c>. The
/// shift was written <c>-b / 4 * a</c>, which is <c>-a b / 4</c>, so with a leading coefficient
/// other than 1 or -1 every candidate was off and failed its check, and the quartic was
/// answered <c>{ }</c>. Found by a cross-check of equations in square roots, whose squared
/// forms are such quartics; no issue was filed.
/// </summary>
[Trait("Area", "Algebra")]
public sealed class ADepressedBiquadraticQuarticTest
{
private static void AssertRoots(string equation, params string[] roots)
{
var answer = Assert.IsType<FiniteSet>(equation.ToEntity().Solve("x"));
Assert.Equal(roots.Length, answer.Count);
foreach (var root in roots)
Assert.Contains(answer, found => Number.IsZero((found - root.ToEntity()).EvalNumerical()));
}

/// <summary>Irreducible over the rationals, so that no factoring answers it first.</summary>
[Fact]
public void FourRealRoots()
=> AssertRoots("31x^4 - 62x^3 + 33x^2 - 2x - 1 = 0",
"1/2 + sqrt((27/62 + 8/31 * sqrt(2)) / 2)", "1/2 - sqrt((27/62 + 8/31 * sqrt(2)) / 2)",
"1/2 + sqrt((27/62 - 8/31 * sqrt(2)) / 2)", "1/2 - sqrt((27/62 - 8/31 * sqrt(2)) / 2)");

/// <summary><c>2(x - 1)^4 - 2(x - 1)^2 - 1</c>: two real roots and two that are not.</summary>
[Fact]
public void TwoRealRootsAndTwoComplex()
=> AssertRoots("2x^4 - 8x^3 + 10x^2 - 4x - 1 = 0",
"1 + sqrt((1 + sqrt(3)) / 2)", "1 - sqrt((1 + sqrt(3)) / 2)",
"1 + sqrt((1 - sqrt(3)) / 2)", "1 - sqrt((1 - sqrt(3)) / 2)");

/// <summary>
/// Equations in a square root whose squared form is such a quartic, each answered
/// <c>{ }</c>. The first has the one real root its squaring keeps; the second, four
/// complex ones.
/// </summary>
[Fact]
public void TheEquationsInARootWhoseSquareIsOne()
{
AssertRoots("x^2 - x - 1 = 4x * sqrt(2x^2 - 4x + 2)", "(1 - sqrt(1 + 4 / (1 + 4 * sqrt(2)))) / 2");
AssertRoots("(2x^2 + 4x - 2) / sqrt(-2x - x^2) = -2",
"-1 + sqrt((3 + sqrt(-3)) / 2)", "-1 - sqrt((3 + sqrt(-3)) / 2)",
"-1 + sqrt((3 - sqrt(-3)) / 2)", "-1 - sqrt((3 - sqrt(-3)) / 2)");
}
}
}
Loading