diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md
index ff7259513..77fa74a33 100644
--- a/BREAKING-CHANGES.md
+++ b/BREAKING-CHANGES.md
@@ -574,6 +574,31 @@ filed; a check of limits against values near the destination found it.
The same spelled `(-ln(2)/ln(x))^(exp(x) - 1)` was `1` in 2.6.0 and did not return after it; it is `1` again.
+### The error functions and the exponential and trigonometric integrals have limits
+
+**`erf(x)` at +oo is `1`, where it was left unevaluated.** None of erf, erfc, erfi, Si, Ci, Shi, Chi, Ei or li had a
+limit at all, not even at a point where it is continuous: `erf(x)` at 1 was unevaluated too. Their limits at the
+infinities are now their values there:
+- erf: 1 and -1
+- erfc: 0 and 2
+- erfi and Shi: +oo and -oo
+- Si: pi/2 and -pi/2
+- Ci: 0
+- Chi and li: +oo
+- Ei: +oo and 0
+
+A finite limit of the argument is put in where the function is continuous. For the entire ones that is anywhere.
+For Ci, Chi, Ei and li it is only a positive real point, since they are singular at 0 and cut below it, and li is
+singular at 1 too.
+
+| Input | Was (2.6.0) | Now |
+|---|---|---|
+| `"erf(x)".ToEntity().Limit("x", "+oo")` | `limit(erf(x), x, +oo)` | `1` |
+| `"erf(x)".ToEntity().Limit("x", 1)` | `limit(erf(x), x, 1)` | `erf(1)` |
+| `"Si(x)".ToEntity().Limit("x", "+oo")` | `limit(Si(x), x, +oo)` | `pi / 2` |
+| `"Ei(x)".ToEntity().Limit("x", "-oo")` | `limit(Ei(x), x, -oo)` | `0` |
+| `"erf(x)/x + 1".ToEntity().Limit("x", 0)` | `limit(erf(x) / x + 1, x, 0)` | `2 / sqrt(pi) + 1` |
+
### A limit of a logarithm that is not decided is left unevaluated
**Not silent: what overflowed the stack now returns.** A limit of a logarithm whose argument has no limit, as
diff --git a/Sources/AngouriMath/Functions/Continuous/Limits/Solvers/Limit.Classes.cs b/Sources/AngouriMath/Functions/Continuous/Limits/Solvers/Limit.Classes.cs
index d375d50ee..89551f459 100644
--- a/Sources/AngouriMath/Functions/Continuous/Limits/Solvers/Limit.Classes.cs
+++ b/Sources/AngouriMath/Functions/Continuous/Limits/Solvers/Limit.Classes.cs
@@ -402,6 +402,115 @@ partial record Arccosf
}
}
+ ///
+ /// The limit of an error function or an exponential or trigonometric integral, given its
+ /// argument's limit: the value it tends to at an infinity, and the function of a finite limit
+ /// where it is continuous there.
+ ///
+ ///
+ /// None of these had a limit at all, so erf(x) at +oo, which is 1, was left unevaluated, and
+ /// so was erf(x) at 1. A logarithm of something holding one came to a stop that took more than
+ /// forty seconds: log(x + pi + erf(x), x^2 + tanh(1)) at +oo, which is 2. At an infinity:
+ /// erf to 1 and -1, erfc to 0 and 2, erfi, Shi to +oo and -oo, Si to pi/2 and -pi/2, Ci to 0,
+ /// Chi and li to +oo, and Ei to +oo and 0. Erf, erfc, erfi, Si and Shi are entire, so a finite
+ /// limit is put in as it is. Ci, Chi, Ei and li have a logarithm's singularity at 0 and its cut
+ /// below it, and li another at 1, so only a positive real limit other than li's 1 is put in;
+ /// elsewhere nothing is claimed. Each value at an infinity was checked against mpmath at 10^6 and
+ /// -10^6, and at 50 and -50 for erfi, Shi and Chi.
+ ///
+ private static Entity? OfAnErrorOrIntegralFunction(Entity node, Entity argument, Variable x, Entity dist, ApproachFrom side)
+ {
+ if (argument.ComputeLimitDivideEtImpera(x, dist, side) is not { } limit)
+ return null;
+ if (limit.Evaled is Real { IsFinite: false, IsNaN: false } infinity)
+ {
+ var upwards = !infinity.IsNegative;
+ return node switch
+ {
+ Erff => upwards ? Integer.One : Integer.MinusOne,
+ Erfcf => upwards ? Integer.Zero : Integer.Create(2),
+ Erfif or Shif => upwards ? Real.PositiveInfinity : Real.NegativeInfinity,
+ Sif => upwards ? MathS.pi / 2 : -MathS.pi / 2,
+ Cif => upwards ? Integer.Zero : null,
+ Chif or Lif => upwards ? Real.PositiveInfinity : null,
+ Eif => upwards ? Real.PositiveInfinity : Integer.Zero,
+ _ => null
+ };
+ }
+ if (limit.Evaled is not Number { IsFinite: true, IsNaN: false } value)
+ return null;
+ var entire = node is Erff or Erfcf or Erfif or Sif or Shif;
+ if (!entire && !(value is Real { IsPositive: true } && !(node is Lif && value == Integer.One)))
+ return null;
+ return node switch
+ {
+ Erff => new Erff(limit),
+ Erfcf => new Erfcf(limit),
+ Erfif => new Erfif(limit),
+ Sif => new Sif(limit),
+ Cif => new Cif(limit),
+ Shif => new Shif(limit),
+ Chif => new Chif(limit),
+ Eif => new Eif(limit),
+ Lif => new Lif(limit),
+ _ => null
+ };
+ }
+
+ partial record Erff
+ {
+ internal override Entity? ComputeLimitDivideEtImpera(Variable x, Entity dist, ApproachFrom side)
+ => OfAnErrorOrIntegralFunction(this, Argument, x, dist, side);
+ }
+
+ partial record Erfcf
+ {
+ internal override Entity? ComputeLimitDivideEtImpera(Variable x, Entity dist, ApproachFrom side)
+ => OfAnErrorOrIntegralFunction(this, Argument, x, dist, side);
+ }
+
+ partial record Erfif
+ {
+ internal override Entity? ComputeLimitDivideEtImpera(Variable x, Entity dist, ApproachFrom side)
+ => OfAnErrorOrIntegralFunction(this, Argument, x, dist, side);
+ }
+
+ partial record Sif
+ {
+ internal override Entity? ComputeLimitDivideEtImpera(Variable x, Entity dist, ApproachFrom side)
+ => OfAnErrorOrIntegralFunction(this, Argument, x, dist, side);
+ }
+
+ partial record Cif
+ {
+ internal override Entity? ComputeLimitDivideEtImpera(Variable x, Entity dist, ApproachFrom side)
+ => OfAnErrorOrIntegralFunction(this, Argument, x, dist, side);
+ }
+
+ partial record Shif
+ {
+ internal override Entity? ComputeLimitDivideEtImpera(Variable x, Entity dist, ApproachFrom side)
+ => OfAnErrorOrIntegralFunction(this, Argument, x, dist, side);
+ }
+
+ partial record Chif
+ {
+ internal override Entity? ComputeLimitDivideEtImpera(Variable x, Entity dist, ApproachFrom side)
+ => OfAnErrorOrIntegralFunction(this, Argument, x, dist, side);
+ }
+
+ partial record Eif
+ {
+ internal override Entity? ComputeLimitDivideEtImpera(Variable x, Entity dist, ApproachFrom side)
+ => OfAnErrorOrIntegralFunction(this, Argument, x, dist, side);
+ }
+
+ partial record Lif
+ {
+ internal override Entity? ComputeLimitDivideEtImpera(Variable x, Entity dist, ApproachFrom side)
+ => OfAnErrorOrIntegralFunction(this, Argument, x, dist, side);
+ }
+
partial record Arctanf
{
internal override Entity? ComputeLimitDivideEtImpera(Variable x, Entity dist, ApproachFrom side)
diff --git a/Sources/Tests/UnitTests/Calculus/ErrorAndIntegralFunctionLimitsTest.cs b/Sources/Tests/UnitTests/Calculus/ErrorAndIntegralFunctionLimitsTest.cs
new file mode 100644
index 000000000..125d76b0e
--- /dev/null
+++ b/Sources/Tests/UnitTests/Calculus/ErrorAndIntegralFunctionLimitsTest.cs
@@ -0,0 +1,59 @@
+//
+// 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 AngouriMath.Core;
+using Xunit;
+
+namespace AngouriMath.Tests.Calculus
+{
+ ///
+ /// The error functions and the exponential and trigonometric integrals had no limit at all: erf(x) at +oo,
+ /// which is 1, was left unevaluated, and so was erf(x) at 1. Their limits at the infinities are now their
+ /// values there, and a finite limit of the argument is put in where the function is continuous: anywhere for the
+ /// entire ones, only at a positive real point for Ci, Chi, Ei and li, which are singular at 0 and cut below it, and
+ /// li singular at 1 too. The same on 2.6.0. Found by limitcheck at DEPTH=3, SEED=53; no issue was
+ /// filed.
+ ///
+ [Trait("Area", "Calculus")]
+ public sealed class ErrorAndIntegralFunctionLimitsTest
+ {
+ [Theory]
+ [InlineData("erf(x)", "+oo", "1")]
+ [InlineData("erf(x)", "-oo", "-1")]
+ [InlineData("erfc(x)", "+oo", "0")]
+ [InlineData("erfc(x)", "-oo", "2")]
+ [InlineData("erfi(x)", "+oo", "+oo")]
+ [InlineData("Si(x)", "+oo", "pi/2")]
+ [InlineData("Si(x)", "-oo", "-pi/2")]
+ [InlineData("Ci(x)", "+oo", "0")]
+ [InlineData("Shi(x)", "-oo", "-oo")]
+ [InlineData("Chi(x)", "+oo", "+oo")]
+ [InlineData("Ei(x)", "+oo", "+oo")]
+ [InlineData("Ei(x)", "-oo", "0")]
+ [InlineData("li(x)", "+oo", "+oo")]
+ [InlineData("erf(x)", "1", "erf(1)")]
+ [InlineData("Ci(x)", "2", "Ci(2)")]
+ [InlineData("erf(x)/x + 1", "0", "2/sqrt(pi) + 1")]
+ public void HasItsLimit(string input, string destination, string expected)
+ => Assert.Equal(MathS.FromString(expected).Simplify(), MathS.FromString(input).Limit("x", destination).Simplify());
+
+ [Fact]
+ public void IsOneSidedWhereItsArgumentDiverges()
+ {
+ Assert.Equal(MathS.FromString("1"), MathS.FromString("erf(1/x)").Limit("x", 0, ApproachFrom.Right));
+ Assert.Equal(MathS.FromString("-pi/2").Simplify(), MathS.FromString("Si(1/x)").Limit("x", 0, ApproachFrom.Left).Simplify());
+ Assert.Equal(MathS.NaN, MathS.FromString("erf(1/x)").Limit("x", 0));
+ }
+
+ // Nothing is claimed on Ci's cut or at li's pole.
+ [Theory]
+ [InlineData("Ci(x)", "-2")]
+ [InlineData("Ci(x)", "-oo")]
+ public void IsNotAnsweredOnACut(string input, string destination)
+ => Assert.IsType(MathS.FromString(input).Limit("x", destination));
+ }
+}