diff --git a/Sources/AngouriMath/Core/Entity/Continuous/Entity.Continuous.Calculus.Classes.cs b/Sources/AngouriMath/Core/Entity/Continuous/Entity.Continuous.Calculus.Classes.cs
index 826c98cd5..ffb5e2740 100644
--- a/Sources/AngouriMath/Core/Entity/Continuous/Entity.Continuous.Calculus.Classes.cs
+++ b/Sources/AngouriMath/Core/Entity/Continuous/Entity.Continuous.Calculus.Classes.cs
@@ -16,7 +16,7 @@ partial record Entity
///
/// A node of derivative
///
- public sealed partial record Derivativef(Entity Expression, Entity Var, int Iterations) : Function
+ public sealed partial record Derivativef(Entity Expression, Entity Var, int Iterations) : CalculusOperator(Expression, Var)
{
/// Reuse the cache by returning the same object if possible
private Derivativef New(Entity expression, Entity var) =>
@@ -32,7 +32,7 @@ public override Entity Replace(Func func) =>
///
/// A node of integral
///
- public sealed partial record Integralf(Entity Expression, Entity Var, int Iterations) : Function
+ public sealed partial record Integralf(Entity Expression, Entity Var, int Iterations) : CalculusOperator(Expression, Var)
{
/// Reuse the cache by returning the same object if possible
private Integralf New(Entity expression, Entity var) =>
@@ -48,7 +48,7 @@ public override Entity Replace(Func func) =>
///
/// A node of limit
///
- public sealed partial record Limitf(Entity Expression, Entity Var, Entity Destination, ApproachFrom ApproachFrom) : Function
+ public sealed partial record Limitf(Entity Expression, Entity Var, Entity Destination, ApproachFrom ApproachFrom) : CalculusOperator(Expression, Var)
{
/// Reuse the cache by returning the same object if possible
private Limitf New(Entity expression, Entity var, Entity destination, ApproachFrom approachFrom) =>
diff --git a/Sources/AngouriMath/Core/Entity/Continuous/Entity.Continuous.Definition.cs b/Sources/AngouriMath/Core/Entity/Continuous/Entity.Continuous.Definition.cs
index de10e4871..76b8e37da 100644
--- a/Sources/AngouriMath/Core/Entity/Continuous/Entity.Continuous.Definition.cs
+++ b/Sources/AngouriMath/Core/Entity/Continuous/Entity.Continuous.Definition.cs
@@ -17,12 +17,27 @@ public abstract partial record ContinuousNode : Entity
}
+ ///
+ /// Describes any node that is a function (e. g. sin, cos, etc.) or calculus operator (e. g. derivative, integral, limit)
+ /// but not an arithmetic operator or leaf
+ ///
+ public abstract record Function : ContinuousNode
+ {
+ internal override Priority Priority => Priority.Func;
+ }
+
///
/// Describes any function that is related to trigonometry
///
public abstract record TrigonometricFunction : Function
{
+ }
+ ///
+ /// Describes any calculus operator
+ ///
+ public abstract partial record CalculusOperator(Entity Expression, Entity Var) : Function
+ {
}
///
@@ -100,14 +115,5 @@ public abstract record TrigonometricFunction : Function
public Entity Signum() => new Signumf(this);
///
public Entity Abs() => new Absf(this);
-
- ///
- /// Describes any node that is a function (e. g. sin, cos, etc.)
- /// but not an operator or leaf
- ///
- public abstract record Function : ContinuousNode
- {
- internal override Priority Priority => Priority.Func;
- }
}
}
diff --git a/Sources/AngouriMath/Core/Entity/Entity.Definition.cs b/Sources/AngouriMath/Core/Entity/Entity.Definition.cs
index 5400575a2..a2fafd958 100644
--- a/Sources/AngouriMath/Core/Entity/Entity.Definition.cs
+++ b/Sources/AngouriMath/Core/Entity/Entity.Definition.cs
@@ -47,13 +47,14 @@ internal enum Priority
Sum = 20 | NumericalOperation,
Minus = 20 | NumericalOperation,
+ /// For text formats, is used instead.
+ LatexCalculusOperation = 30 | NumericalOperation,
Mul = 40 | NumericalOperation,
Div = 40 | NumericalOperation,
Pow = 60 | NumericalOperation,
Factorial = 70 | NumericalOperation,
Func = 80 | NumericalOperation,
-
Leaf = 100 | NumericalOperation,
}
#pragma warning restore CA1069 // Enums values should not be duplicated
diff --git a/Sources/AngouriMath/Functions/Output/Latex.Definition.cs b/Sources/AngouriMath/Functions/Output/Latex.Definition.cs
index af3c86388..5eaaa03c8 100644
--- a/Sources/AngouriMath/Functions/Output/Latex.Definition.cs
+++ b/Sources/AngouriMath/Functions/Output/Latex.Definition.cs
@@ -45,6 +45,11 @@ partial record Entity : ILatexiseable
///
///
public abstract string Latexise();
+ ///
+ /// Calculus operators, unlike other functions, have a between addition/subtraction
+ /// and multiplication/division which is different from .
+ ///
+ internal virtual Priority LatexPriority => Priority;
/// Returns the expression in LaTeX (for example, a / b -> \frac{a}{b})
/// Whether to wrap it with parentheses
diff --git a/Sources/AngouriMath/Functions/Output/Latex/Latex.Arithmetics.Classes.cs b/Sources/AngouriMath/Functions/Output/Latex/Latex.Arithmetics.Classes.cs
index 82396cc91..94bc3f361 100644
--- a/Sources/AngouriMath/Functions/Output/Latex/Latex.Arithmetics.Classes.cs
+++ b/Sources/AngouriMath/Functions/Output/Latex/Latex.Arithmetics.Classes.cs
@@ -15,8 +15,8 @@ public partial record Sumf
{
///
public override string Latexise() =>
- Augend.Latexise(Augend.Priority < Priority)
- + (Addend.Latexise(Addend.Priority < Priority) is var addend && addend.StartsWith("-")
+ Augend.Latexise(Augend.LatexPriority < LatexPriority)
+ + (Addend.Latexise(Addend.LatexPriority < LatexPriority) is var addend && addend.StartsWith("-")
? addend : "+" + addend);
}
@@ -24,8 +24,8 @@ public partial record Minusf
{
///
public override string Latexise() =>
- Subtrahend.Latexise(Subtrahend.Priority < Priority)
- + "-" + Minuend.Latexise(Minuend.Priority <= Priority);
+ Subtrahend.Latexise(Subtrahend.LatexPriority < LatexPriority)
+ + "-" + Minuend.Latexise(Minuend.LatexPriority <= LatexPriority);
}
public partial record Mulf
@@ -43,16 +43,16 @@ public override string Latexise()
return currIn switch
{
// -1, -2, 2i, i, -i, -2i etc. in the front and not (1+i) etc.
- Number { Priority: Priority.Sum } and not Complex { RealPart.IsZero: false, ImaginaryPart.IsZero: false } =>
+ Number { LatexPriority: Priority.Sum } and not Complex { RealPart.IsZero: false, ImaginaryPart.IsZero: false } =>
currIn.Latexise(false),
- _ => currIn.Latexise(currIn.Priority < Priority)
+ _ => currIn.Latexise(currIn.LatexPriority < LatexPriority)
};
case 1:
if (longArray[index - 1] is Integer(-1))
- return $"-{currIn.Latexise(currIn.Priority < Priority)}"; // display "-1 * x * y" as "-x \cdot y", only for the first -1
+ return $"-{currIn.Latexise(currIn.LatexPriority < LatexPriority)}"; // display "-1 * x * y" as "-x \cdot y", only for the first -1
break;
}
- var currOut = currIn.Latexise(currIn.Priority < Priority);
+ var currOut = currIn.Latexise(currIn.LatexPriority < LatexPriority);
return (longArray[index - 1], currIn) switch // whether we use juxtaposition and omit \cdot
{
@@ -61,20 +61,20 @@ public override string Latexise()
// Don't juxtapose upright variables with numbers like displaying "var2" for "var*2" since "var2" may be interpreted as one variable.
// Also, don't produce upright "ei" (one variable with two chars) for e*i, or "ei^2" for e*i^2.
- // but "e (2+i)" and "e (2+i)^2" are fine with the parentheses - so we have the priority check.
+ // but "e (2+i)" and "e (2+i)^2" are fine with the parentheses - so we have the LatexPriority check.
(Variable { IsLatexUprightFormatted: true }
- or Complex { ImaginaryPart.IsZero: false, Priority: >= Priority.Mul } /* don't combine upright "i" with an upright variable*/,
- Variable { IsLatexUprightFormatted: true } or Number { Priority: >= Priority.Mul }
- or Factorialf(Number { Priority: Priority.Leaf } or Variable { IsLatexUprightFormatted: true })
- or Powf(Number { Priority: Priority.Leaf } or Variable { IsLatexUprightFormatted: true }
- or Factorialf(Number { Priority: Priority.Leaf } or Variable { IsLatexUprightFormatted: true }), _)) => false,
+ or Complex { ImaginaryPart.IsZero: false, LatexPriority: >= Priority.Mul } /* don't combine upright "i" with an upright variable*/,
+ Variable { IsLatexUprightFormatted: true } or Number { LatexPriority: >= Priority.Mul }
+ or Factorialf(Number { LatexPriority: Priority.Leaf } or Variable { IsLatexUprightFormatted: true })
+ or Powf(Number { LatexPriority: Priority.Leaf } or Variable { IsLatexUprightFormatted: true }
+ or Factorialf(Number { LatexPriority: Priority.Leaf } or Variable { IsLatexUprightFormatted: true }), _)) => false,
// 2 * (3/4) instead of 2 (3/4) which is a mixed number (= 2 + 3/4)
- (Number { Priority: Priority.Leaf }, { Priority: Priority.Div }) => false,
- // 2 * 3 instead of 2 3 (= 23), 2 * 3^4 instead of 2 3^4 (= 23^4), but "(2+i) 2", "2 (2+i)" and "2 (2+i)^2" are fine with the parentheses - so we have the priority check.
- (_, Number { Priority: >= Priority.Mul } or Factorialf(Number { Priority: Priority.Leaf })
- or Powf(Number { Priority: Priority.Leaf } or Factorialf(Number { Priority: Priority.Leaf }), _)) => false, // Keep the \cdot in "f(x) \cdot -2" "f(x) \cdot 2i" "f(x) \cdot -2i"
- (var left, var right) => left.Priority >= right.Priority &&
- !(left.Priority == Priority.Div && right.Priority == Priority.Div) // Without \cdot, the fraction lines may appear too closely together.
+ (Number { LatexPriority: Priority.Leaf }, { LatexPriority: Priority.Div }) => false,
+ // 2 * 3 instead of 2 3 (= 23), 2 * 3^4 instead of 2 3^4 (= 23^4), but "(2+i) 2", "2 (2+i)" and "2 (2+i)^2" are fine with the parentheses - so we have the LatexPriority check.
+ (_, Number { LatexPriority: >= Priority.Mul } or Factorialf(Number { LatexPriority: Priority.Leaf })
+ or Powf(Number { LatexPriority: Priority.Leaf } or Factorialf(Number { LatexPriority: Priority.Leaf }), _)) => false, // Keep the \cdot in "f(x) \cdot -2" "f(x) \cdot 2i" "f(x) \cdot -2i"
+ (var left, var right) => left.LatexPriority >= right.LatexPriority &&
+ !(left.LatexPriority == Priority.Div && right.LatexPriority == Priority.Div) // Without \cdot, the fraction lines may appear too closely together.
} ? $@"{prevOut} {currOut}" : $@"{prevOut} \cdot {currOut}";
});
@@ -125,7 +125,7 @@ public override string Latexise()
}
else
{
- return "{" + Base.Latexise(Base.Priority <= Priority) + "}^{" + Exponent.Latexise() + "}";
+ return "{" + Base.Latexise(Base.LatexPriority <= LatexPriority) + "}^{" + Exponent.Latexise() + "}";
}
}
}
@@ -134,7 +134,7 @@ public partial record Factorialf
{
///
public override string Latexise() =>
- Argument.Latexise(Argument.Priority <= Priority) + "!";
+ Argument.Latexise(Argument.LatexPriority <= LatexPriority) + "!";
}
partial record Signumf
diff --git a/Sources/AngouriMath/Functions/Output/Latex/Latex.Calculus.Classes.cs b/Sources/AngouriMath/Functions/Output/Latex/Latex.Calculus.Classes.cs
index 0c860fb36..788bd18fa 100644
--- a/Sources/AngouriMath/Functions/Output/Latex/Latex.Calculus.Classes.cs
+++ b/Sources/AngouriMath/Functions/Output/Latex/Latex.Calculus.Classes.cs
@@ -11,16 +11,20 @@ namespace AngouriMath
{
partial record Entity
{
+ partial record CalculusOperator
+ {
+ ///
+ internal override Priority LatexPriority => Priority.LatexCalculusOperation;
+ }
public partial record Derivativef
{
internal static string LatexiseDerivative(Entity expression, Entity var, int iterations)
{
var powerIfNeeded = iterations == 1 ? "" : "^{" + iterations + "}";
- var varOverDeriv = var is Variable { IsLatexUprightFormatted: false } ? var.Latexise() : @"\left(" + var.Latexise() + @"\right)";
- string ParenIfNeeded(string paren) => expression.Priority < Priority.Pow ? paren : "";
// NOTE: \mathrm{d} is used for upright 'd' following ISO 80000-2 standard.
// The differential operator should be upright (roman) to distinguish it from variables, similar to sin, cos, log, etc.
- return $$"""\frac{\mathrm{d}{{powerIfNeeded}}}{\mathrm{d}{{varOverDeriv}}{{powerIfNeeded}}}{{ParenIfNeeded(@"\left[")}}{{expression.Latexise()}}{{ParenIfNeeded(@"\right]")}}""";
+ return $$"""\frac{\mathrm{d}{{powerIfNeeded}}}{\mathrm{d}{{var.Latexise(var is not Variable { IsLatexUprightFormatted: false })
+ }}{{powerIfNeeded}}}{{expression.Latexise(expression.LatexPriority < Priority.LatexCalculusOperation)}}""";
}
///
public override string Latexise() => LatexiseDerivative(Expression, Var, Iterations);
@@ -40,9 +44,7 @@ public override string Latexise()
var sb = new StringBuilder();
for (int i = 0; i < Iterations; i++)
sb.Append(@"\int");
- sb.Append(@" \left[");
- sb.Append(Expression.Latexise(false));
- sb.Append(@"\right]");
+ sb.Append(' ').Append(Expression.Latexise(Expression.LatexPriority < Priority.LatexCalculusOperation));
// NOTE: \mathrm{d} is used for upright 'd' following ISO 80000-2 standard.
// The differential operator should be upright (roman) to distinguish it from variables.
@@ -54,14 +56,7 @@ public override string Latexise()
{
sb.Append(@"\,");// Leading space before first differential and between differentials
sb.Append(@"\mathrm{d}");
- if (Var is Variable { IsLatexUprightFormatted: false })
- sb.Append(Var.Latexise());
- else
- {
- sb.Append(@"\left(");
- sb.Append(Var.Latexise());
- sb.Append(@"\right)");
- }
+ sb.Append(Var.Latexise(Var is not Variable { IsLatexUprightFormatted: false }));
}
return sb.ToString();
}
@@ -79,10 +74,10 @@ public override string Latexise()
switch (ApproachFrom)
{
case ApproachFrom.Left:
- sb.Append(Destination.Latexise(Destination.Priority <= Priority.Pow)).Append("^-");
+ sb.Append(Destination.Latexise(Destination.LatexPriority <= Priority.Pow)).Append("^-");
break;
case ApproachFrom.Right:
- sb.Append(Destination.Latexise(Destination.Priority <= Priority.Pow)).Append("^+");
+ sb.Append(Destination.Latexise(Destination.LatexPriority <= Priority.Pow)).Append("^+");
break;
case ApproachFrom.BothSides:
sb.Append(Destination.Latexise());
@@ -90,12 +85,7 @@ public override string Latexise()
}
sb.Append("} ");
- if (Expression.Priority < Priority.Pow)
- sb.Append(@"\left[");
- sb.Append(Expression.Latexise());
- if (Expression.Priority < Priority.Pow)
- sb.Append(@"\right]");
-
+ sb.Append(Expression.Latexise(Expression.LatexPriority < Priority.LatexCalculusOperation));
return sb.ToString();
}
}
diff --git a/Sources/AngouriMath/Functions/Output/Latex/Latex.Discrete.Classes.cs b/Sources/AngouriMath/Functions/Output/Latex/Latex.Discrete.Classes.cs
index 131794d1b..0ee10e0ff 100644
--- a/Sources/AngouriMath/Functions/Output/Latex/Latex.Discrete.Classes.cs
+++ b/Sources/AngouriMath/Functions/Output/Latex/Latex.Discrete.Classes.cs
@@ -21,8 +21,8 @@ partial record Notf
///
public override string Latexise()
=> Argument is Equalsf(var left, var right)
- ? $@"{left.Latexise(left.Priority <= Priority.Equal)} \neq {right.Latexise(right.Priority <= Priority.Equal)}"
- : $@"\neg{{{Argument.Latexise(Argument.Priority < Priority)}}}";
+ ? $@"{left.Latexise(left.LatexPriority <= Priority.Equal)} \neq {right.Latexise(right.LatexPriority <= Priority.Equal)}"
+ : $@"\neg{{{Argument.Latexise(Argument.LatexPriority < LatexPriority)}}}";
}
partial record Andf
@@ -42,7 +42,7 @@ public override string Latexise()
var renew = left != child.DirectChildren[0];
if (!first && renew) result.Append(@" \land ");
first = false;
- if (first || renew) result.Append(child.DirectChildren[0].Latexise(child.DirectChildren[0].Priority <= child.Priority));
+ if (first || renew) result.Append(child.DirectChildren[0].Latexise(child.DirectChildren[0].LatexPriority <= child.LatexPriority));
renew = false;
result.Append(child switch {
Equalsf => " = ",
@@ -51,23 +51,23 @@ public override string Latexise()
Lessf => " < ",
LessOrEqualf => @" \leq ",
_ => throw new Core.Exceptions.AngouriBugException("Unexpected comparison sign in Andf.Latexise")
- }).Append(child.DirectChildren[1].Latexise(child.DirectChildren[1].Priority <= child.Priority));
+ }).Append(child.DirectChildren[1].Latexise(child.DirectChildren[1].LatexPriority <= child.LatexPriority));
left = child.DirectChildren[1];
break;
case Notf (Equalsf eq):
renew = left != eq.Left;
if (!first && renew) result.Append(@" \land ");
first = false;
- if (first || renew) result.Append(eq.Left.Latexise(eq.Left.Priority <= eq.Priority));
+ if (first || renew) result.Append(eq.Left.Latexise(eq.Left.LatexPriority <= eq.LatexPriority));
renew = false;
- result.Append(@" \neq ").Append(eq.Right.Latexise(eq.Right.Priority <= eq.Priority));
+ result.Append(@" \neq ").Append(eq.Right.Latexise(eq.Right.LatexPriority <= eq.LatexPriority));
left = eq.Right;
break;
default:
if (!first) result.Append(" \\land ");
left = null;
first = false;
- result.Append(child.Latexise(child.Priority < Priority));
+ result.Append(child.Latexise(child.LatexPriority < LatexPriority));
break;
}
}
@@ -79,7 +79,7 @@ partial record Orf
{
///
public override string Latexise()
- => $@"{Left.Latexise(Left.Priority < Priority)} \lor {Right.Latexise(Right.Priority < Priority)}";
+ => $@"{Left.Latexise(Left.LatexPriority < LatexPriority)} \lor {Right.Latexise(Right.LatexPriority < LatexPriority)}";
}
partial record Xorf
@@ -87,7 +87,7 @@ partial record Xorf
///
// NOTE: \veebar (⊻) can disambiguate better than \oplus (⊕) which can mean the direct sum in algebra.
public override string Latexise()
- => $@"{Left.Latexise(Left.Priority < Priority)} \veebar {Right.Latexise(Right.Priority < Priority)}";
+ => $@"{Left.Latexise(Left.LatexPriority < LatexPriority)} \veebar {Right.Latexise(Right.LatexPriority < LatexPriority)}";
}
partial record Impliesf
@@ -99,21 +99,21 @@ partial record Impliesf
// ISO 80000-2 puts ⇒ first for implies, but → is also accepted and is more common in logic contexts.
// ⇒ can be used in steps for proofs if we were to add it later.
public override string Latexise()
- => $@"{Assumption.Latexise(Assumption.Priority <= Priority)} \to {Conclusion.Latexise(Conclusion.Priority < Priority)}";
+ => $@"{Assumption.Latexise(Assumption.LatexPriority <= LatexPriority)} \to {Conclusion.Latexise(Conclusion.LatexPriority < LatexPriority)}";
}
partial record Equalsf
{
///
public override string Latexise()
- => $@"{Left.Latexise(Left.Priority <= Priority)} = {Right.Latexise(Right.Priority <= Priority)}";
+ => $@"{Left.Latexise(Left.LatexPriority <= LatexPriority)} = {Right.Latexise(Right.LatexPriority <= LatexPriority)}";
}
partial record Greaterf
{
///
public override string Latexise()
- => $@"{Left.Latexise(Left.Priority <= Priority)} > {Right.Latexise(Right.Priority <= Priority)}";
+ => $@"{Left.Latexise(Left.LatexPriority <= LatexPriority)} > {Right.Latexise(Right.LatexPriority <= LatexPriority)}";
}
partial record GreaterOrEqualf
@@ -122,14 +122,14 @@ partial record GreaterOrEqualf
// NOTE: While \geqslant (⩾) is more used in e.g. Russian texts, \geq (≥) is more universally used in English texts.
// Since the output language of LaTeX is English (referencing Piecewise and Providedf), \geq is more appropriate.
public override string Latexise()
- => $@"{Left.Latexise(Left.Priority <= Priority)} \geq {Right.Latexise(Right.Priority <= Priority)}";
+ => $@"{Left.Latexise(Left.LatexPriority <= LatexPriority)} \geq {Right.Latexise(Right.LatexPriority <= LatexPriority)}";
}
partial record Lessf
{
///
public override string Latexise()
- => $@"{Left.Latexise(Left.Priority <= Priority)} < {Right.Latexise(Right.Priority <= Priority)}";
+ => $@"{Left.Latexise(Left.LatexPriority <= LatexPriority)} < {Right.Latexise(Right.LatexPriority <= LatexPriority)}";
}
partial record LessOrEqualf
@@ -138,7 +138,7 @@ partial record LessOrEqualf
// NOTE: While \leqslant (⩽) is more used in e.g. Russian texts, \leq (≤) is more universally used in English texts.
// Since the output language of LaTeX is English (referencing Piecewise and Providedf), \leq is more appropriate.
public override string Latexise()
- => $@"{Left.Latexise(Left.Priority <= Priority)} \leq {Right.Latexise(Right.Priority <= Priority)}";
+ => $@"{Left.Latexise(Left.LatexPriority <= LatexPriority)} \leq {Right.Latexise(Right.LatexPriority <= LatexPriority)}";
}
}
}
diff --git a/Sources/AngouriMath/Functions/Output/Latex/Latex.Omni.Classes.cs b/Sources/AngouriMath/Functions/Output/Latex/Latex.Omni.Classes.cs
index 051b86f57..455ac77b4 100644
--- a/Sources/AngouriMath/Functions/Output/Latex/Latex.Omni.Classes.cs
+++ b/Sources/AngouriMath/Functions/Output/Latex/Latex.Omni.Classes.cs
@@ -51,35 +51,35 @@ partial record Unionf
{
///
public override string Latexise()
- => $@"{Left.Latexise(Left.Priority < Priority)} \cup {Right.Latexise(Right.Priority < Priority)}";
+ => $@"{Left.Latexise(Left.LatexPriority < LatexPriority)} \cup {Right.Latexise(Right.LatexPriority < LatexPriority)}";
}
partial record Intersectionf
{
///
public override string Latexise()
- => $@"{Left.Latexise(Left.Priority < Priority)} \cap {Right.Latexise(Right.Priority < Priority)}";
+ => $@"{Left.Latexise(Left.LatexPriority < LatexPriority)} \cap {Right.Latexise(Right.LatexPriority < LatexPriority)}";
}
partial record SetMinusf
{
///
public override string Latexise()
- => $@"{Left.Latexise(Left.Priority < Priority)} \setminus {Right.Latexise(Right.Priority < Priority)}";
+ => $@"{Left.Latexise(Left.LatexPriority < LatexPriority)} \setminus {Right.Latexise(Right.LatexPriority < LatexPriority)}";
}
partial record Inf
{
///
public override string Latexise()
- => $@"{Element.Latexise(Element.Priority < Priority)} \in {SupSet.Latexise(SupSet.Priority < Priority)}";
+ => $@"{Element.Latexise(Element.LatexPriority < LatexPriority)} \in {SupSet.Latexise(SupSet.LatexPriority < LatexPriority)}";
}
}
partial record Providedf
{
///
- public override string Latexise() => $@"{Expression.Latexise(Expression.Priority < Priority)} \quad \text{{for}} \quad {Predicate.Latexise(Predicate.Priority <= Priority)}";
+ public override string Latexise() => $@"{Expression.Latexise(Expression.LatexPriority < LatexPriority)} \quad \text{{for}} \quad {Predicate.Latexise(Predicate.LatexPriority <= LatexPriority)}";
}
partial record Piecewise
@@ -90,8 +90,8 @@ public override string Latexise() => $@"\begin{{cases}}" +
Cases.Select(c =>
{
if (c.Predicate == Boolean.True)
- return $@"{c.Expression.Latexise(c.Expression.Priority < Priority.Provided)} & \text{{otherwise}}";
- return $@"{c.Expression.Latexise(c.Expression.Priority < Priority.Provided)} & \text{{for }} {c.Predicate.Latexise(c.Predicate.Priority <= Priority.Provided)}"; // "for" used in https://mathworld.wolfram.com/Derivative.html
+ return $@"{c.Expression.Latexise(c.Expression.LatexPriority < Priority.Provided)} & \text{{otherwise}}";
+ return $@"{c.Expression.Latexise(c.Expression.LatexPriority < Priority.Provided)} & \text{{for }} {c.Predicate.Latexise(c.Predicate.LatexPriority <= Priority.Provided)}"; // "for" used in https://mathworld.wolfram.com/Derivative.html
}
))
+
@@ -139,7 +139,7 @@ partial record Application
// are rendered as separate applications: f(x)(y) rather than f(x, y)
public override string Latexise()
{
- var result = new StringBuilder(Expression.Latexise(Expression.Priority < Priority));
+ var result = new StringBuilder(Expression.Latexise(Expression.LatexPriority < LatexPriority));
foreach (var arg in Arguments)
{
result.Append(@"\left(").Append(arg.Latexise()).Append(@"\right)");
@@ -154,7 +154,7 @@ partial record Lambda
// NOTE: \mapsto (↦) links the function variable with its output while
// \rightarrow (→) links the function domain with its codomain. See https://math.stackexchange.com/a/651240, https://math.stackexchange.com/a/936591
public override string Latexise()
- => Parameter.Latexise() + @" \mapsto " + Body.Latexise(Body.Priority < Priority);
+ => Parameter.Latexise() + @" \mapsto " + Body.Latexise(Body.LatexPriority < LatexPriority);
}
}
}
diff --git a/Sources/Tests/UnitTests/Convenience/LatexTest.cs b/Sources/Tests/UnitTests/Convenience/LatexTest.cs
index f1d796ec7..f4463c8e4 100644
--- a/Sources/Tests/UnitTests/Convenience/LatexTest.cs
+++ b/Sources/Tests/UnitTests/Convenience/LatexTest.cs
@@ -225,45 +225,53 @@ [Fact] public void VectorSingle() =>
[Fact] public void Derivative7() => Test(@"\frac{\mathrm{d}^{2}}{\mathrm{d}\left({x}^{2}\right)^{2}}{x}^{2}", MathS.Derivative(x.Pow(2), x.Pow(2), 2));
[Fact] public void Derivative8() => Test(@"\frac{\mathrm{d}}{\mathrm{d}\left(\mathrm{xy}\right)}\mathrm{xy}", MathS.Derivative("xy", "xy"));
[Fact] public void Derivative9() => Test(@"\frac{\mathrm{d}^{2}}{\mathrm{d}\left(\mathrm{xy}\right)^{2}}\mathrm{xy}", MathS.Derivative("xy", "xy", 2));
- [Fact] public void Derivative10() => Test(@"\frac{\mathrm{d}}{\mathrm{d}x}\left[\frac{x}{2}\right]", MathS.Derivative("x / 2", x));
- [Fact] public void Derivative11() => Test(@"\frac{\mathrm{d}}{\mathrm{d}\left(\mathrm{quack}\right)}\left[x+y\right]", MathS.Derivative("x + y", "quack"));
- [Fact] public void Derivative12() => Test(@"\frac{\mathrm{d}^{3}}{\mathrm{d}x_{f}^{3}}\left[x+1\right]", MathS.Derivative("x + 1", "x_f", 3));
- [Fact] public void Derivative13() => Test(@"\frac{\mathrm{d}}{\mathrm{d}x_{f}}\left[\frac{1}{x}\right]", MathS.Derivative("1/x", "x_f"));
- [Fact] public void Derivative14() => Test(@"\frac{\mathrm{d}}{\mathrm{d}\alpha}\left[{x}^{23}-x_{\mathrm{16}}\right]", MathS.Derivative("x^23-x_16", "alpha"));
+ [Fact] public void Derivative10() => Test(@"\frac{\mathrm{d}}{\mathrm{d}x}\frac{x}{2}", MathS.Derivative("x / 2", x));
+ [Fact] public void Derivative11() => Test(@"\frac{\mathrm{d}}{\mathrm{d}\left(\mathrm{quack}\right)}\left(x+y\right)", MathS.Derivative("x + y", "quack"));
+ [Fact] public void Derivative12() => Test(@"\frac{\mathrm{d}^{3}}{\mathrm{d}x_{f}^{3}}\left(x+1\right)", MathS.Derivative("x + 1", "x_f", 3));
+ [Fact] public void Derivative13() => Test(@"\frac{\mathrm{d}}{\mathrm{d}x_{f}}\frac{1}{x}", MathS.Derivative("1/x", "x_f"));
+ [Fact] public void Derivative14() => Test(@"\frac{\mathrm{d}}{\mathrm{d}\alpha}\left({x}^{23}-x_{\mathrm{16}}\right)", MathS.Derivative("x^23-x_16", "alpha"));
[Fact] public void Derivative15() => Test(@"\frac{\mathrm{d}}{\mathrm{d}\alpha_{\beta}}\alpha", MathS.Derivative("alpha", "alpha_beta"));
[Fact] public void Derivative16() => Test(@"\frac{\mathrm{d}}{\mathrm{d}\left(\mathrm{alphaa}_{\beta}\right)}\alpha", MathS.Derivative("alpha", "alphaa_beta"));
- [Fact] public void Integral1() => Test(@"\int \left[x\right]\,\mathrm{d}x", MathS.Integral(x, x));
+ [Fact] public void Integral1() => Test(@"\int x\,\mathrm{d}x", MathS.Integral(x, x));
[Fact] public void Integral2() =>
- Test(@"\int \left[x+1\right]\,\mathrm{d}\left(x+1\right)", MathS.Integral("x + 1", "x+1"));
+ Test(@"\int \left(x+1\right)\,\mathrm{d}\left(x+1\right)", MathS.Integral("x + 1", "x+1"));
[Fact] public void Integral3() =>
- Test(@"\int\int \left[x+1\right]\,\mathrm{d}x\,\mathrm{d}x", MathS.Integral("x + 1", x, 2));
+ Test(@"\int\int \left(x+1\right)\,\mathrm{d}x\,\mathrm{d}x", MathS.Integral("x + 1", x, 2));
[Fact] public void Integral4() =>
- Test(@"\int\int \left[x+1\right]\,\mathrm{d}\left(\mathrm{xf}\right)\,\mathrm{d}\left(\mathrm{xf}\right)", MathS.Integral("x + 1", "xf", 2));
+ Test(@"\int\int \left(x+1\right)\,\mathrm{d}\left(\mathrm{xf}\right)\,\mathrm{d}\left(\mathrm{xf}\right)", MathS.Integral("x + 1", "xf", 2));
[Fact] public void Integral5() =>
- Test(@"\int \left[\frac{1}{x}\right]\,\mathrm{d}x_{f}", MathS.Integral("1/x", "x_f"));
+ Test(@"\int \frac{1}{x}\,\mathrm{d}x_{f}", MathS.Integral("1/x", "x_f"));
[Fact] public void Integral6() =>
- Test(@"\int\int\int \left[{x}^{23}-x_{\mathrm{16}}\right]\,\mathrm{d}\left({x_{f}}^{2}\right)\,\mathrm{d}\left({x_{f}}^{2}\right)\,\mathrm{d}\left({x_{f}}^{2}\right)", MathS.Integral("x^23-x_16", "x_f^2", 3));
- [Fact] public void IntegralSpecialCase1() => Test(@"\frac{\mathrm{d}^{0}}{\mathrm{d}x^{0}}\left[x+1\right]+1", MathS.Integral("x+1", "x", 0) + 1);
- [Fact] public void IntegralSpecialCase2() => Test(@"\frac{\mathrm{d}}{\mathrm{d}x}\left[x+1\right] \cdot 2", MathS.Integral("x+1", "x", -1) * 2);
+ Test(@"\int\int\int \left({x}^{23}-x_{\mathrm{16}}\right)\,\mathrm{d}\left({x_{f}}^{2}\right)\,\mathrm{d}\left({x_{f}}^{2}\right)\,\mathrm{d}\left({x_{f}}^{2}\right)", MathS.Integral("x^23-x_16", "x_f^2", 3));
+ [Fact] public void IntegralSpecialCase1() => Test(@"\frac{\mathrm{d}^{0}}{\mathrm{d}x^{0}}\left(x+1\right)+1", MathS.Integral("x+1", "x", 0) + 1);
+ [Fact] public void IntegralSpecialCase2() => Test(@"\left(\frac{\mathrm{d}}{\mathrm{d}x}\left(x+1\right)\right) \cdot 2", MathS.Integral("x+1", "x", -1) * 2);
[Theory, CombinatorialData] public void IntegralSpecialCase3([CombinatorialRange(0, 3)] int power, [CombinatorialValues("x", "x_f", "ab", "ab_cd", "e", "alpha", "alpha_beta", "alpha_e")] string v) =>
Test(MathS.Derivative(Integer.One + v, v, power).Latexise(), MathS.Integral(Integer.One + v, v, -power));
[Fact] public void Limit1() =>
- Test(@"\lim_{x\to 0^-} \left[x+y\right]", (Entity)"limitleft(x + y, x, 0)");
+ Test(@"\lim_{x\to 0^-} \left(x+y\right)", (Entity)"limitleft(x + y, x, 0)");
[Fact] public void Limit2() =>
Test(@"\lim_{x\to 0^+} {a}^{5}", (Entity)"limitright(a^5, x, 0)");
[Fact] public void Limit3() =>
- Test(@"\lim_{x\to \infty } \left[x+y\right]", MathS.Limit("x + y", x, Real.PositiveInfinity));
+ Test(@"\lim_{x\to \infty } \left(x+y\right)", MathS.Limit("x + y", x, Real.PositiveInfinity));
[Fact] public void Limit4() =>
- Test(@"\lim_{\mathrm{xf}\to 1+x} \left[\frac{1}{x}\right]", MathS.Limit("1/x", "xf", "1+x"));
+ Test(@"\lim_{\mathrm{xf}\to 1+x} \frac{1}{x}", MathS.Limit("1/x", "xf", "1+x"));
[Fact] public void Limit5() =>
- Test(@"\lim_{\mathrm{xf}\to {x_{2}}^{3}} \left[{x}^{23}-x_{\mathrm{16}}\right]", MathS.Limit("x^23-x_16", "xf", "x_2^3"));
+ Test(@"\lim_{\mathrm{xf}\to {x_{2}}^{3}} \left({x}^{23}-x_{\mathrm{16}}\right)", MathS.Limit("x^23-x_16", "xf", "x_2^3"));
[Theory, InlineData("+"), InlineData("-")] public void LimitOneSided1(string sign) =>
- Test($$"""\lim_{x\to \left(a+2\right)^{{sign}}} \left[x+y\right]""", (Entity)$"limit{(sign == "-" ? "left" : "right")}(x + y, x, a+2)");
+ Test($$"""\lim_{x\to \left(a+2\right)^{{sign}}} \left(x+y\right)""", (Entity)$"limit{(sign == "-" ? "left" : "right")}(x + y, x, a+2)");
[Theory, InlineData("+"), InlineData("-")] public void LimitOneSided2(string sign) =>
- Test($$"""\lim_{x\to \left({a}^{2}\right)^{{sign}}} \left[x+y\right]""", (Entity)$"limit{(sign == "-" ? "left" : "right")}(x + y, x, a^2)");
+ Test($$"""\lim_{x\to \left({a}^{2}\right)^{{sign}}} \left(x+y\right)""", (Entity)$"limit{(sign == "-" ? "left" : "right")}(x + y, x, a^2)");
[Theory, InlineData("+"), InlineData("-")]
public void LimitOneSided3(string sign) =>
- Test($$"""\lim_{x\to \left({a}^{2}\right)!^{{sign}}} \left[x+y\right]""", (Entity)$"limit{(sign == "-" ? "left" : "right")}(x + y, x, (a^2)!)");
+ Test($$"""\lim_{x\to \left({a}^{2}\right)!^{{sign}}} \left(x+y\right)""", (Entity)$"limit{(sign == "-" ? "left" : "right")}(x + y, x, (a^2)!)");
+ [Fact] public void LimitOfExponential() =>
+ Test(@"\lim_{x\to \infty } {\sin\left(x\right)}^{x} = \infty ", MathS.Limit(MathS.Pow(MathS.Sin(x), x), x, Real.PositiveInfinity).Equalizes(Real.PositiveInfinity));
+ [Fact] public void NestedLimitDerivative() =>
+ Test(@"\left(\lim_{x\to 0} \frac{\mathrm{d}^{2}}{\mathrm{d}x^{2}}\lim_{y\to \infty } \frac{x}{y}\right) \cdot x", MathS.Limit(MathS.Derivative(MathS.Limit("x / y", "y", Real.PositiveInfinity), x, 2), x, 0) * x);
+ [Fact] public void NestedDerivativeIntegral1() =>
+ Test(@"\frac{\mathrm{d}}{\mathrm{d}x}\int \frac{\mathrm{d}}{\mathrm{d}y}\int {x}^{2} \cdot y\,\mathrm{d}y\,\mathrm{d}\left(x+1\right)+1", MathS.Derivative(MathS.Integral(MathS.Derivative(MathS.Integral(MathS.Pow(x, 2) * "y", "y"), "y"), x + 1), x) + 1);
+ [Fact] public void NestedDerivativeIntegral2() =>
+ Test(@"\int \frac{\mathrm{d}}{\mathrm{d}x}\int \frac{\mathrm{d}}{\mathrm{d}y}\left(1-{x}^{2} \cdot y\right)\,\mathrm{d}y\,\mathrm{d}x+1", MathS.Integral(MathS.Derivative(MathS.Integral(MathS.Derivative(1 - MathS.Pow(x, 2) * "y", "y"), "y"), x), x) + 1);
[Fact] public void Interval1() =>
Test(@"\left[3, 4\right]", MathS.Sets.Interval(3, true, 4, true));
[Fact] public void Interval2() =>