Skip to content

Commit 899e705

Browse files
committed
Vectors and matrices
1 parent 7982e72 commit 899e705

File tree

3 files changed

+82
-19
lines changed

3 files changed

+82
-19
lines changed

CSharpMath.Evaluation.Tests/EvaluationTests.cs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,17 @@ public void Parentheses(string latex, string converted, string result) {
359359
Test(latex.Replace("(", @"\left(").Replace(")", @"\right)"), converted, result);
360360
}
361361
[Theory]
362+
[InlineData(@"\begin{pmatrix}1\end{pmatrix}", @"\left( \begin{matrix}1\end{matrix}\right) ", @"\left( \begin{matrix}1\end{matrix}\right) ")]
363+
[InlineData(@"\begin{pmatrix}1\end{pmatrix}^2", @"\left( \begin{matrix}1\end{matrix}\right) ^2", @"\left( \begin{matrix}1\end{matrix}\right) ^2")]
364+
public void Vectors(string latex, string converted, string result) =>
365+
Test(latex, converted, result);
366+
[Theory]
367+
[InlineData(@"\begin{pmatrix}1&2\\3&4\end{pmatrix}", @"\left( \begin{matrix}1&2\\ 3&4\end{matrix}\right) ", @"\left( \begin{matrix}1&2\\ 3&4\end{matrix}\right) ")]
368+
[InlineData(@"\begin{pmatrix}1&2\\3&4\end{pmatrix}^2", @"\left( \begin{matrix}1&2\\ 3&4\end{matrix}\right) ^2", @"\left( \begin{matrix}1&2\\ 3&4\end{matrix}\right) ^2")]
369+
[InlineData(@"\begin{pmatrix}1&2\\3&4\end{pmatrix}+\begin{pmatrix}1&2\\3&5\end{pmatrix}", @"\left( \begin{matrix}1&2\\ 3&4\end{matrix}\right) +\left( \begin{matrix}1&2\\ 3&5\end{matrix}\right) ", @"\left( \begin{matrix}1&2\\ 3&4\end{matrix}\right) +\left( \begin{matrix}1&2\\ 3&5\end{matrix}\right) ")]
370+
public void Matrices(string latex, string converted, string result) =>
371+
Test(latex, converted, result);
372+
[Theory]
362373
[InlineData(@"1,2", @"1,2")]
363374
[InlineData(@"1,2,3", @"1,2,3")]
364375
[InlineData(@"a,b,c,d", @"a,b,c,d")]
@@ -382,6 +393,8 @@ public void Sets(string latex, string converted) {
382393
}
383394
[Theory]
384395
[InlineData(@"\emptyset\cup\{2\}", @"\left\{ 2\right\} ")]
396+
[InlineData(@"\{1\}\cup\{2\}", @"\left\{ 1,2\right\} ")]
397+
[InlineData(@"\{3,4\}\cap\emptyset", @"\emptyset ")]
385398
[InlineData(@"\{3,4\}\cap\{4,5\}", @"\left\{ 4\right\} ")]
386399
[InlineData(@"\{2,3,4\}\setminus\{4\}", @"\left\{ 2,3\right\} ")]
387400
//[InlineData(@"\{3\}^\complement", @"\left\{ 3\right\} ^\complement")] // wip
@@ -509,6 +522,14 @@ public void Intervals(string latex, string converted) {
509522
[InlineData(@"\sec\csc", "Missing argument for csc")]
510523
[InlineData(@"\arcsin_2x", "Subscripts are unsupported for Large Operator arcsin")]
511524
[InlineData(@"\operatorname{dab}", "Unsupported Large Operator dab")]
525+
[InlineData(@"\begin{matrix}\end{matrix}", "Missing matrix element")]
526+
[InlineData(@"\begin{matrix}2&3\end{matrix}_2", "Subscripts are unsupported for Ordinary")]
527+
[InlineData(@"\begin{matrix}2&3\end{matrix}^2", "Exponentiation is unsupported for Ordinary")]
528+
[InlineData(@"\begin{pmatrix}2&+\end{pmatrix}", "Missing right operand for +")]
529+
[InlineData(@"\begin{pmatrix}2&3\end{pmatrix}_2", "Subscripts are unsupported for Inner ")]
530+
[InlineData(@"\begin{Vmatrix}\end{Vmatrix}", "Missing matrix element")]
531+
[InlineData(@"\begin{Vmatrix}2&3\end{Vmatrix}", "Unrecognized bracket pair ‖ ‖")]
532+
[InlineData(@"\begin{eqnarray}&&\end{eqnarray}", "Unsupported table environment eqnarray")]
512533
[InlineData(@",", "Missing left operand for comma")]
513534
[InlineData(@"1,_22", "Subscripts are unsupported for Punctuation ,")]
514535
[InlineData(@"1,", "Missing right operand for comma")]
@@ -525,7 +546,7 @@ public void Intervals(string latex, string converted) {
525546
[InlineData(@"\frac{[7,8]}{9}", "Set cannot be numerator")]
526547
[InlineData(@"\sqrt[{[]}]{}", "Unrecognized bracket pair [ ]")]
527548
[InlineData(@"\sqrt[{[a,b]}]{}", "Set cannot be degree")]
528-
[InlineData(@"\{\{\}\}", "Set cannot be a set element")]
549+
[InlineData(@"\{\{\}\}", "Set cannot be set element")]
529550
[InlineData(@"\cap", "Unsupported Unary Operator ∩")]
530551
[InlineData(@"\cap1", "Unsupported Unary Operator ∩")]
531552
[InlineData(@"1\cap", "Entity cannot be left operand for ∩")]
@@ -535,9 +556,14 @@ public void Intervals(string latex, string converted) {
535556
[InlineData(@"\setminus", "Unsupported Unary Operator ∖")]
536557
[InlineData(@"\setminus1", "Unsupported Unary Operator ∖")]
537558
[InlineData(@"1\setminus", "Entity cannot be left operand for ∖")]
538-
[InlineData(@"^\complement", "There is nothing to evaluate")]
559+
[InlineData(@"^\complement", "Exponentiation is unsupported for Ordinary")]
560+
[InlineData(@"_\complement", "Subscripts are unsupported for Ordinary")]
539561
[InlineData(@"1^\complement", "Entity cannot be target of set inversion")]
562+
[InlineData(@"1_\complement", "Subscripts are unsupported for Number 1")]
540563
[InlineData(@"x^\complement", "Entity cannot be target of set inversion")]
564+
[InlineData(@"x_\complement", "Unsupported Ordinary ∁ in subscript")]
565+
[InlineData(@"\sin^\complement x", "Entity cannot be target of set inversion")]
566+
[InlineData(@"\sin_\complement x", "Subscripts are unsupported for Large Operator sin")]
541567
public void Error(string badLaTeX, string error) =>
542568
Evaluation.Evaluate(ParseLaTeX(badLaTeX))
543569
.Match(entity => throw new Xunit.Sdk.XunitException(entity.Latexise()), e => Assert.Equal(error, e));

CSharpMath.Evaluation/Evaluation.cs

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ private protected MathItem() { }
3232
public static explicit operator AngouriMath.Entity(MathItem item) => ((Entity)item).Content;
3333
public static implicit operator MathItem(SetNode content) => new Set(content);
3434
public static explicit operator SetNode(MathItem item) => ((Set)item).Content;
35-
/// <summary>An real number, complex number, variable or function call</summary>
35+
/// <summary>A real number, complex number, variable, function call, vector, matrix or higher-dimensional tensor</summary>
3636
public sealed class Entity : MathItem {
3737
public Entity(AngouriMath.Entity content) => Content = content;
3838
public AngouriMath.Entity Content { get; }
@@ -79,6 +79,18 @@ result is { } r
7979
int i = 0;
8080
return Transform(mathList, ref i, Precedence.DefaultContext);
8181
}
82+
static Result<Entity[]> ExpectEntities(this Result<MathItem?> result, string itemName) =>
83+
result.Bind(item => item switch {
84+
null => Array.Empty<Entity>(),
85+
MathItem.Entity { Content: var e } => new[] { e },
86+
MathItem.Comma c =>
87+
c.Aggregate((Result: Result.Ok(new Entity[c.Count()]), Index: 0), (acc, item) =>
88+
(acc.Result.Bind(s => item.AsEntity(itemName).Bind(i => { s[acc.Index] = i; return s; })), acc.Index + 1),
89+
acc => acc.Result),
90+
var notEntity => Result.Err(item.GetType().Name + " cannot be " + itemName)
91+
});
92+
static Result<Entity[]> AsEntities(this MathItem? item, string itemName) =>
93+
Result.Ok(item).ExpectEntities(itemName);
8294
static Result<Entity?> ExpectEntityOrNull(this Result<MathItem?> result, string itemName) =>
8395
result.Bind(item => item switch {
8496
null => Result.Ok((Entity?)null),
@@ -149,22 +161,15 @@ static Result<MathItem> TryMakeSet(MathItem.Comma c, bool leftClosed, bool right
149161
MathItem.Comma c => TryMakeSet(c, true, true),
150162
_ => "Unrecognized bracket pair [ ]"
151163
} },
152-
{ ("{", "}"), item => item switch {
153-
null => (MathItem)MathS.Sets.Empty(),
154-
MathItem.Entity { Content:var e } => (MathItem)MathS.Sets.Finite(e),
155-
MathItem.Comma c =>
156-
c.Aggregate(Result.Ok(MathS.Sets.Empty()), (set, item) =>
157-
set.Bind(s => item.AsEntity("set element").Bind(i => { s.Add(i); return s; })),
158-
set => set.Bind(s => (MathItem)s)),
159-
_ => item.GetType().Name + " cannot be a set element"
160-
} },
164+
{ ("{", "}"), item => item.AsEntities("set element").Bind(entities => (MathItem)MathS.Sets.Finite(entities)) }
161165
};
162166
static Result<MathItem?> Transform(MathList mathList, ref int i, Precedence prec) {
163167
MathItem? prev = null;
164168
MathItem? next;
165169
string? error;
166170
Precedence handlePrecendence;
167171
Func<Entity, Entity> handlePrefix, handlePostfix, handleFunction, handleFunctionInverse;
172+
Func<Entity[], Entity> handleFunctionN, handleFunctionInverseN;
168173
Func<Entity, Entity, Entity> handleBinary;
169174
Func<SetNode, SetNode> handlePrefixSet, handlePostfixSet, handleFunctionSet, handleFunctionInverseSet;
170175
Func<SetNode, SetNode, SetNode> handleBinarySet;
@@ -233,6 +238,9 @@ _ when LaTeXSettings.CommandForAtom(atom) is string s => MathS.Var(s + subscript
233238
};
234239
v.Subscript.Clear();
235240
goto handleThis;
241+
case Atoms.Ordinary { Nucleus: "∞" }:
242+
@this = new NumberEntity(MathS.Num(double.PositiveInfinity));
243+
goto handleThis;
236244
case Atoms.Ordinary { Nucleus: "∅" }:
237245
@this = MathS.Sets.Empty();
238246
goto handleThis;
@@ -399,6 +407,17 @@ _ when LaTeXSettings.CommandForAtom(atom) is string s => MathS.Var(s + subscript
399407
handlePrecendence = Precedence.PercentDegree;
400408
handlePostfix = x => x * MathS.pi / 180;
401409
goto handlePostfix;
410+
case Atoms.Table { Environment:"matrix", NRows:var rows, NColumns:var cols, Cells:var cells }:
411+
var matrixElements = new Entity[rows * cols];
412+
for (var row = 0; row < rows; row++)
413+
for (var col = 0; col < cols; col++) {
414+
if (cells[row].Count <= col)
415+
return $"There are empty slots in the {rows}×{cols} matrix";
416+
(matrixElements[row * cols + col], error) = Transform(cells[row][col]).ExpectEntity("matrix element");
417+
if (error != null) return error;
418+
}
419+
@this = MathS.Matrices.Matrix(rows, cols, matrixElements);
420+
goto handleThis;
402421
case Atoms.Punctuation { Nucleus: "," }:
403422
if (prec <= Precedence.Comma) {
404423
if (prev is null) return "Missing left operand for comma";
@@ -426,17 +445,32 @@ _ when LaTeXSettings.CommandForAtom(atom) is string s => MathS.Var(s + subscript
426445
handleBinarySet = (l, r) => l - r;
427446
goto handleBinarySet;
428447
case Atoms.Space _:
448+
case Atoms.Style _:
429449
case Atoms.Ordinary { Nucleus: var nucleus } when string.IsNullOrWhiteSpace(nucleus):
450+
if (atom.Superscript.Count > 0)
451+
return $"Exponentiation is unsupported for {atom.TypeName}";
452+
if (atom.Subscript.Count > 0)
453+
return $"Subscripts are unsupported for {atom.TypeName}";
430454
continue;
455+
case Atoms.Table table:
456+
return $"Unsupported table environment {table.Environment}";
431457
default:
432458
return $"Unsupported {atom.TypeName} {atom.Nucleus}";
433459

460+
#pragma warning disable CS0162 // Unreachable code detected
461+
#pragma warning disable CS0164 // This label has not been referenced
434462
handleFunction:
435463
handleFunctionInner = (itemName, item) =>
436464
item.AsEntity(itemName).Bind(e => (MathItem)handleFunction(e));
437465
handleFunctionInverseInner = (itemName, item) =>
438466
item.AsEntity(itemName).Bind(e => (MathItem)handleFunctionInverse(e));
439467
goto handleFunctionInner;
468+
handleFunctionN:
469+
handleFunctionInner = (itemName, item) =>
470+
item.AsEntities(itemName).Bind(e => (MathItem)handleFunctionN(e));
471+
handleFunctionInverseInner = (itemName, item) =>
472+
item.AsEntities(itemName).Bind(e => (MathItem)handleFunctionInverseN(e));
473+
goto handleFunctionInner;
440474
handleFunctionSet:
441475
handleFunctionInner = (itemName, item) =>
442476
item.AsSet(itemName).Bind(set => (MathItem)handleFunctionSet(set));
@@ -591,6 +625,8 @@ _ when LaTeXSettings.CommandForAtom(atom) is string s => MathS.Var(s + subscript
591625
i--;
592626
return prev;
593627
}
628+
#pragma warning restore CS0162 // Unreachable code detected
629+
#pragma warning restore CS0164 // This label has not been referenced
594630

595631
handleThis:
596632
if (atom.Subscript.Count > 0)

CSharpMath.sln

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
Microsoft Visual Studio Solution File, Format Version 12.00
32
# Visual Studio Version 16
43
VisualStudioVersion = 16.0.29201.188
@@ -38,7 +37,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpMath.Forms.Example.iO
3837
EndProject
3938
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpMath.Forms.Example.UWP", "CSharpMath.Forms.Example\CSharpMath.Forms.Example.UWP\CSharpMath.Forms.Example.UWP.csproj", "{B5C64A34-51EA-4948-80FC-505120BA943C}"
4039
EndProject
41-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpMath.Forms.Example", "CSharpMath.Forms.Example\CSharpMath.Forms.Example\CSharpMath.Forms.Example.csproj", "{B3FA77B8-C6E9-4A78-8BD4-9A167DA36637}"
40+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharpMath.Forms.Example", "CSharpMath.Forms.Example\CSharpMath.Forms.Example\CSharpMath.Forms.Example.csproj", "{B3FA77B8-C6E9-4A78-8BD4-9A167DA36637}"
4241
EndProject
4342
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharpMath.Rendering", "CSharpMath.Rendering\CSharpMath.Rendering.csproj", "{65016A61-2125-4E0C-90E8-A915230C7826}"
4443
EndProject
@@ -70,7 +69,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharpMath.Editor.Tests", "
7069
EndProject
7170
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharpMath.Editor.Tests.Visualizer", "CSharpMath.Editor.Tests.Visualizer\CSharpMath.Editor.Tests.Visualizer.csproj", "{C60126CE-A71D-4D11-A4A8-A45B67312E98}"
7271
EndProject
73-
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "CSharpMath.Editor.Tests.FSharp", "CSharpMath.Editor.Tests.FSharp\CSharpMath.Editor.Tests.FSharp.fsproj", "{65492AC6-8B98-42FF-AAA1-1DBDC050A25F}"
72+
Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "CSharpMath.Editor.Tests.FSharp", "CSharpMath.Editor.Tests.FSharp\CSharpMath.Editor.Tests.FSharp.fsproj", "{65492AC6-8B98-42FF-AAA1-1DBDC050A25F}"
7473
EndProject
7574
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "PixelFarm.Typography (Excerpt)", "PixelFarm.Typography (Excerpt)\PixelFarm.Typography (Excerpt).shproj", "{3ECA00B3-0925-4418-B6F2-AC49AA3520BB}"
7675
EndProject
@@ -84,7 +83,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharpMath.Rendering.Tests"
8483
EndProject
8584
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Run 'git submodule update --init' if below unloaded", "Run 'git submodule update --init' if below unloaded", "{15784E9C-7D6D-47C0-B993-A45A964C82F5}"
8685
EndProject
87-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpMath.Evaluation", "CSharpMath.Evaluation\CSharpMath.Evaluation.csproj", "{039990A9-FBF8-421E-A40A-CAE2A34B7240}"
86+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharpMath.Evaluation", "CSharpMath.Evaluation\CSharpMath.Evaluation.csproj", "{039990A9-FBF8-421E-A40A-CAE2A34B7240}"
8887
EndProject
8988
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharpMath.Xaml.Tests", "CSharpMath.Xaml.Tests\CSharpMath.Xaml.Tests.csproj", "{87C65DBF-14E4-4BFD-B8E3-BC7F8D2A857E}"
9089
EndProject
@@ -96,11 +95,13 @@ Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "CSharpMath.Wiki", "CSharpMa
9695
EndProject
9796
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharpMath.Xaml.Tests.NuGet", "CSharpMath.Xaml.Tests.NuGet\CSharpMath.Xaml.Tests.NuGet.csproj", "{2FD3FBBD-FD06-4E49-BA91-4FC5ADC33BA7}"
9897
EndProject
99-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AngouriMath", "AngouriMath\AngouriMath\AngouriMath.csproj", "{F3FE15B5-1995-4444-85FF-6CAC564A9113}"
98+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AngouriMath", "AngouriMath\AngouriMath\AngouriMath.csproj", "{F3FE15B5-1995-4444-85FF-6CAC564A9113}"
10099
EndProject
101-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpMath.Evaluation.Tests", "CSharpMath.Evaluation.Tests\CSharpMath.Evaluation.Tests.csproj", "{06241755-626A-4992-9CAE-C5A5745CB83C}"
100+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharpMath.Evaluation.Tests", "CSharpMath.Evaluation.Tests\CSharpMath.Evaluation.Tests.csproj", "{06241755-626A-4992-9CAE-C5A5745CB83C}"
102101
EndProject
103-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpMath.Forms.Example.Ooui", "CSharpMath.Forms.Example\CSharpMath.Forms.Example.Ooui\CSharpMath.Forms.Example.Ooui.csproj", "{338E9ACF-EB26-4D5B-9ADB-B0C4588D71E1}"
102+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharpMath.Forms.Example.Ooui", "CSharpMath.Forms.Example\CSharpMath.Forms.Example.Ooui\CSharpMath.Forms.Example.Ooui.csproj", "{338E9ACF-EB26-4D5B-9ADB-B0C4588D71E1}"
103+
EndProject
104+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Unity", "Unity", "{945A9D41-75F7-41DC-B61E-66B193CC2DA9}"
104105
EndProject
105106
Global
106107
GlobalSection(SharedMSBuildProjectFiles) = preSolution

0 commit comments

Comments
 (0)