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
30 changes: 22 additions & 8 deletions Sources/AngouriMath/Convenience/AngouriMathExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ public static FastExpression Compile(this string str, params Variable[] variable
/// Finds the symbolical derivative of the given expression
/// </summary>
/// <param name="str">
/// The expresion to be parsed and differentiated
/// The expression to be parsed and differentiated
/// </param>
/// <param name="x">
/// Over which variable to find the derivative
Expand All @@ -315,7 +315,7 @@ public static Entity Derive(this string str, Variable x)
/// Finds the symbolical derivative of the given expression
/// </summary>
/// <param name="str">
/// The expresion to be parsed and differentiated
/// The expression to be parsed and differentiated
/// </param>
/// <param name="x">
/// Over which variable to find the derivative
Expand All @@ -328,21 +328,35 @@ public static Entity Differentiate(this string str, Variable x)
=> str.ToEntity().Differentiate(x);

/// <summary>
/// Integrates the given expression over the `x` variable, if can.
/// Integrates indefinitely the given expression over the `x` variable, if can.
/// May return an unresolved <see cref="Integralf"/> node.
/// </summary>
/// <param name="str">
/// The expression to be parsed and integrated over <paramref name="x"/>
/// The expression to be parsed and integrated
/// </param>
/// <param name="x">Over which to integrate</param>
/// <param name="x">Over which variable to integrate</param>
/// <returns>
/// An integrated expression. It might remain the same,
/// it might have no integrals, and it might be transformed so that
/// only a few nodes have unresolved integrals.
/// An integrated expression. It might remain the same or be transformed into nodes with no integrals.
/// </returns>
public static Entity Integrate(this string str, Variable x)
=> str.ToEntity().Integrate(x);

/// <summary>
/// Integrates definitely the given expression over the `x` variable, if can.
/// May return an unresolved <see cref="Integralf"/> node.
/// </summary>
/// <param name="str">
/// The expression to be parsed and integrated
/// </param>
/// <param name="x">Over which variable to integrate</param>
/// <param name="from">The lower bound for integrating</param>
/// <param name="to">The upper bound for integrating</param>
/// <returns>
/// An integrated expression. It might remain the same or be transformed into nodes with no integrals.
/// </returns>
public static Entity Integrate(this string str, Variable x, Entity from, Entity to)
=> str.ToEntity().Integrate(x, from, to);

/// <summary>
/// Finds the limit of the given expression over the given variable
/// </summary>
Expand Down
25 changes: 19 additions & 6 deletions Sources/AngouriMath/Convenience/MathS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6338,7 +6338,7 @@ public static Entity Integral(Entity expr, Variable x)
/// <param name="to">The complex upper bound for integrating</param>
[Obsolete("Now these functions are available as non-static methods at Entity")]
public static Complex DefiniteIntegral(Entity expr, Variable x, (EDecimal Re, EDecimal Im) from, (EDecimal Re, EDecimal Im) to) =>
Integration.Integrate(expr, x, from, to, 100);
DefiniteIntegral(expr, x, from, to, 100);

/// <summary>
/// Returns a value of a definite integral of a function. Only works for one-variable functions
Expand All @@ -6349,7 +6349,7 @@ public static Complex DefiniteIntegral(Entity expr, Variable x, (EDecimal Re, ED
/// <param name="to">The real upper bound for integrating</param>
[Obsolete("Now these functions are available as non-static methods at Entity")]
public static Complex DefiniteIntegral(Entity expr, Variable x, EDecimal from, EDecimal to) =>
Integration.Integrate(expr, x, (from, 0), (to, 0), 100);
DefiniteIntegral(expr, x, (from, 0), (to, 0), 100);

/// <summary>
/// Returns a value of a definite integral of a function. Only works for one-variable functions
Expand All @@ -6361,7 +6361,7 @@ public static Complex DefiniteIntegral(Entity expr, Variable x, EDecimal from, E
/// <param name="stepCount">Accuracy (initially, amount of iterations)</param>
[Obsolete("Now these functions are available as non-static methods at Entity")]
public static Complex DefiniteIntegral(Entity expr, Variable x, (EDecimal Re, EDecimal Im) from, (EDecimal Re, EDecimal Im) to, int stepCount) =>
Integration.Integrate(expr, x, from, to, stepCount);
Integration.IntegrateNumerically(expr, x, Complex.Create(from.Re, from.Im), Complex.Create(to.Re, to.Im), stepCount);


/// <summary>
Expand Down Expand Up @@ -6626,15 +6626,16 @@ public static Complex DefiniteIntegral(Entity expr, Variable x, (EDecimal Re, ED
/// a
/// </code>
/// </example>
public static Entity Integral(Entity expr, Entity var) => new Integralf(expr, var, 1);
public static Entity Integral(Entity expr, Entity var) => new Integralf(expr, var, null);

/// <summary>
/// Hangs your entity to an integral node
/// (to evaluate instead use <see cref="Compute.Integral(Entity, Variable)"/>)
/// </summary>
/// <param name="expr">Expression to be hung</param>
/// <param name="var">Variable over which integral is taken</param>
/// <param name="power">Number of times integral is taken. Only integers will be simplified or evaluated.</param>
/// <param name="from">The lower bound for integrating</param>
/// <param name="to">The upper bound for integrating</param>
/// <example>
/// <code>
/// using System;
Expand Down Expand Up @@ -6680,7 +6681,7 @@ public static Complex DefiniteIntegral(Entity expr, Variable x, (EDecimal Re, ED
/// a
/// </code>
/// </example>
public static Entity Integral(Entity expr, Entity var, int power) => new Integralf(expr, var, power);
public static Entity Integral(Entity expr, Entity var, Entity from, Entity to) => new Integralf(expr, var, (from, to));

/// <summary>
/// Hangs your entity to a limit node
Expand Down Expand Up @@ -6820,6 +6821,18 @@ public static class Boolean
/// </summary>
public static Entity.Boolean Create(bool b)
=> Entity.Boolean.Create(b);

/// <summary>
/// One of the Boolean's states, which also behaves as Entity
/// That is, hangable
/// </summary>
[ConstantField] public static readonly Entity.Boolean True = Entity.Boolean.True;

/// <summary>
/// One of the Boolean's states, which also behaves as Entity
/// That is, hangable
/// </summary>
[ConstantField] public static readonly Entity.Boolean False = Entity.Boolean.False;
}

/// <summary>
Expand Down
16 changes: 8 additions & 8 deletions Sources/AngouriMath/Core/Antlr/AngouriMath.g
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/*

Remember to run the "antlr_rerun.bat" file at the project root every time you modify this file so that other
source files under the Antlr folder can update and be reflected in other parts of AngouriMath!
It only consists of commands that are consistent across CMD and Bash so you should be able to run that file
regardless of whether you are on Windows, Linux or Mac. You need to have an installed Java Runtime, however.
Remember to run the "antlr_rerun.bat" file located at "Sources/Utils/antlr_rerun.bat" (relative to the repository root)
every time you modify this file so that the generated source files under the Antlr folder are updated and changes are
reflected in other parts of AngouriMath. The script only consists of commands that are consistent across CMD and Bash,
so you should be able to run it on Windows, Linux, or Mac. You need to have an installed Java Runtime, however.

*/

Expand Down Expand Up @@ -362,12 +362,12 @@ atom returns[Entity value]
}
| 'integral(' args = function_arguments ')'
{
if (Assert("integral", (3, 2), $args.list.Count))
if (Assert("integral", (4, 2), $args.list.Count))
{
if ($args.list[2] is Integer { EInteger: var asEInt })
$value = MathS.Integral($args.list[0], $args.list[1], asEInt.ToInt32Checked());
if ($args.list.Count == 4)
$value = MathS.Integral($args.list[0], $args.list[1], $args.list[2], $args.list[3]);
else
throw new InvalidArgumentParseException("Expected number for the third argument of integral");
$value = MathS.Integral($args.list[0], $args.list[1]);
}
else
$value = MathS.Integral($args.list[0], $args.list[1]);
Expand Down
8 changes: 4 additions & 4 deletions Sources/AngouriMath/Core/Antlr/AngouriMathParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2968,12 +2968,12 @@ public AtomContext atom() {
State = 734;
Match(T__39);

if (Assert("integral", (3, 2), _localctx.args.list.Count))
if (Assert("integral", (4, 2), _localctx.args.list.Count))
{
if (_localctx.args.list[2] is Integer { EInteger: var asEInt })
_localctx.value = MathS.Integral(_localctx.args.list[0], _localctx.args.list[1], asEInt.ToInt32Checked());
if (_localctx.args.list.Count == 4)
_localctx.value = MathS.Integral(_localctx.args.list[0], _localctx.args.list[1], _localctx.args.list[2], _localctx.args.list[3]);
else
throw new InvalidArgumentParseException("Expected number for the third argument of integral");
_localctx.value = MathS.Integral(_localctx.args.list[0], _localctx.args.list[1]);
Comment on lines +2973 to +2976
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both branches of this 'if' statement write to the same variable - consider using '?' to express intent better.

Copilot uses AI. Check for mistakes.
}
else
_localctx.value = MathS.Integral(_localctx.args.list[0], _localctx.args.list[1]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ namespace AngouriMath
partial record Entity
{
#pragma warning disable CS1591 // only while records' parameters cannot be documented
// Iterations should be refactored? to be int instead of Entity
/// <summary>
/// A node of derivative
/// </summary>
/// <remarks>
/// Negative iterations convert to integrals.
/// </remarks>
public sealed partial record Derivativef(Entity Expression, Entity Var, int Iterations) : CalculusOperator(Expression, Var)
{
/// <summary>Reuse the cache by returning the same object if possible</summary>
Expand All @@ -32,17 +34,19 @@ public override Entity Replace(Func<Entity, Entity> func) =>
/// <summary>
/// A node of integral
/// </summary>
public sealed partial record Integralf(Entity Expression, Entity Var, int Iterations) : CalculusOperator(Expression, Var)
public sealed partial record Integralf(Entity Expression, Entity Var, (Entity from, Entity to)? Range) : CalculusOperator(Expression, Var)
{
/// <summary>Reuse the cache by returning the same object if possible</summary>
private Integralf New(Entity expression, Entity var) =>
private Integralf New(Entity expression, Entity var, (Entity from, Entity to)? range) =>
ReferenceEquals(Expression, expression) && ReferenceEquals(Var, var)
? this : new(expression, var, Iterations);
&& (range is null && Range is null || range is var (newFrom, newTo) && Range is var (oldFrom, oldTo)
&& ReferenceEquals(newFrom, oldFrom) && ReferenceEquals(newTo, oldTo))
? this : new(expression, var, range);
/// <inheritdoc/>
public override Entity Replace(Func<Entity, Entity> func) =>
func(New(Expression.Replace(func), Var.Replace(func)));
func(New(Expression.Replace(func), Var, Range is var (from, to) ? (from.Replace(func), to.Replace(func)) : null));
/// <inheritdoc/>
protected override Entity[] InitDirectChildren() => new[] { Expression, Var, Iterations };
protected override Entity[] InitDirectChildren() => Range is var (from, to) ? [Expression, Var, from, to] : [Expression, Var];
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ partial record Entity
public sealed partial record Boolean(bool Value) : Statement
{
/// <summary>
/// One of the Boolean's state, which also behaves as Entity
/// One of the Boolean's states, which also behaves as Entity
/// That is, hangable
/// </summary>
[ConstantField] public static readonly Boolean True = new Boolean(true);

/// <summary>
/// One of the Boolean's state, which also behaves as Entity
/// One of the Boolean's states, which also behaves as Entity
/// That is, hangable
/// </summary>
[ConstantField] public static readonly Boolean False = new Boolean(false);
Expand Down
19 changes: 13 additions & 6 deletions Sources/AngouriMath/Functions/Continuous/Differentiation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,15 @@ partial record Matrix
}

/// <summary>Derives over <paramref name="x"/> <paramref name="power"/> times</summary>
public Entity Differentiate(Variable x, EInteger power)
public Entity Differentiate(Variable x, int power)
{
var ent = this;
for (var _ = 0; _ < power; _++)
ent = ent.InnerDifferentiate(x);
if (power < 0)
for (var _ = 0; _ < -power; _++)
ent = ent.Integrate(x);
else
for (var _ = 0; _ < power; _++)
ent = ent.InnerDifferentiate(x);
return ent;
}

Expand Down Expand Up @@ -276,7 +280,11 @@ partial record Integralf
/// <inheritdoc/>
protected override Entity InnerDifferentiate(Variable variable) =>
Var == variable
? this with { Iterations = Iterations - 1 }
? Range is var (from, to)
// https://math.stackexchange.com/a/139191/627798
? to.InnerDifferentiate(variable) * Expression.Substitute(variable, to) -
from.InnerDifferentiate(variable) * Expression.Substitute(variable, from)
: Expression
: MathS.Derivative(this, variable, 1);
}
#pragma warning restore IDE0054 // Use compound assignment
Expand All @@ -303,10 +311,9 @@ protected override Entity InnerDifferentiate(Variable variable)

partial record Absf
{
// TODO: derivative of the absolute function?
/// <inheritdoc/>
protected override Entity InnerDifferentiate(Variable variable)
=> MathS.Signum(Argument) * Argument.InnerDifferentiate(variable);
=> MathS.Signum(Argument).Provided(!Argument.Equalizes(Integer.Zero)) * Argument.InnerDifferentiate(variable);
}

partial record Providedf
Expand Down
Loading
Loading