Skip to content

Move to AngouriMath 2.0, which renamed Latexise to Latexize - #262

Merged
Happypig375 merged 2 commits into
verybadcat:masterfrom
Rafael-SOWNet:angourimath-2.0-latexize
Aug 17, 2026
Merged

Move to AngouriMath 2.0, which renamed Latexise to Latexize#262
Happypig375 merged 2 commits into
verybadcat:masterfrom
Rafael-SOWNet:angourimath-2.0-latexize

Conversation

@Rafael-SOWNet

Copy link
Copy Markdown
Contributor

Hello — I maintain AngouriMath, which CSharpMath.Evaluation builds on. AngouriMath 2.0 renames ILatexiseable.Latexise to ILatexizeable.Latexize, so this is advance notice with the work already done rather than a bug report after the fact.

Entirely your call whether to take it now or when 2.0 is final — the only thing that would need changing then is the version string.

CSharpMath's own public API does not change

This is the part I wanted to get right. MathItem implements the renamed interface explicitly, so MathItem.Latexise() stays exactly the name your callers know:

public abstract record MathItem : ILatexizeable {
  public abstract string Latexise();
  string ILatexizeable.Latexize() => Latexise();
}

PublicAPI.Unshipped.txt is untouched, and the public-API analyzer agrees — the build produces no RS warnings. Your consumers see nothing.

If you would rather follow the rename through to your own member for consistency, that is a two-line change and yours to make; I did not presume it.

What actually moves

Only what is on AngouriMath's side of the boundary. I let the compiler establish the list rather than grepping for the name — several sites that look affected are your own MathItem and are not:

file change
Evaluation.cs:45 MathItem : ILatexiseableILatexizeable
Evaluation.cs explicit ILatexizeable.Latexize() added
Evaluation.cs:54 Content.Latexise()Content.Latexize() (receiver is AngouriMath.Entity)
Interpret.cs:6,7 parameter type and call
CSharpMath.Evaluation.csproj AngouriMath 1.4.02.0.0-preview.2

Evaluation.cs:64, Evaluation.cs:76 and EvaluationTests.cs:809 call MathItem.Latexise() — your method — and are untouched.

One test expectation changes, and it is a real rendering change

InterpretTests: 1+\sqrt{2x} now expands to 1+\sqrt{2}\sqrt{x} rather than staying 1+\sqrt{2 x}. AngouriMath 2.0 splits a radical over a positive factor.

The identity √(2x) = √2·√x holds for all complex x when the factored-out constant is positive, so the output is sound — but it is a change in what your users will see rendered, so I have flagged it rather than quietly updated it. Only the Expanded line differs; Input, Simplified and Factorized are unchanged.

A bug of ours that your test suite found

Running your suite against 2.0.0-preview.1 failed two tests. The second was ours: \mathbb R+1 rendered as \mathrm{undefined}, because Expand turned RR + 1 into NaN — a 2.0 regression where collecting like terms wrote a factor back as base^1, which is an identity only where the power is defined at all.

Fixed in asc-community/AngouriMath#852 and released in 2.0.0-preview.2, which is what this PR references. Thank you — your tests caught something ours did not.

Measured

Against 2.0.0-preview.2:

CSharpMath.Evaluation.Tests  Total: 955, Errors: 0, Failed: 0, Skipped: 0

For reference, before this change: 955 green on AngouriMath 1.4.0, two red on 2.0.0-preview.1.

Happy to adjust anything here, or to close it and simply leave the heads-up if you would rather do the upgrade yourselves.

AngouriMath 2.0 renames ILatexiseable.Latexise to ILatexizeable.Latexize.

MathItem implements the new interface explicitly, so CSharpMath's own public
surface does not change: MathItem.Latexise stays the name callers know, and
PublicAPI.Unshipped.txt is untouched. The public-API analyzer confirms it --
no RS warnings.

Only two call sites are on AngouriMath's side of the boundary and move:
Content.Latexize() on an AngouriMath.Entity, and the ILatexizeable parameter
in Interpret.

One test expectation changes. 2.0 splits a radical over a positive factor, so
1+\sqrt{2x} expands to 1+\sqrt{2}\sqrt{x}. sqrt(2x) = sqrt(2)sqrt(x) holds for
all complex x when the factored constant is positive, so the new output is
sound; it is a rendering change rather than a correctness one.

955 of 955 tests pass.
@Happypig375

Copy link
Copy Markdown
Collaborator

@Rafael-SOWNet Can you also add the implementation and tests for the new forms of LaTeX that AngouriMath started to produce?

Evaluation.Visualize throws InvalidCodePathException on any LaTeX it cannot
read, and says why in its own source -- "CSharpMath must handle all LaTeX
coming from AngouriMath or a bug is present!" -- but nothing checked it.
AngouriMathLatexSweepTests now does: every concrete Entity type AngouriMath
can print, Latexized and fed back through LaTeXParser. On 2.2.0 that is 76
nodes, of which two forms had no reading here.

\bmod, AngouriMath's modulo node. Added as a BinaryOperator whose nucleus is
the word "mod": binary spacing, and upright because only Variable and Number
go through the italicising font changer. It binds like multiplication and
division, matching AngouriMath's Priority.Mul, so x+y \bmod z is x+(y mod z)
on both sides.

\operatorname{\varphi}, Euler's totient. The name was read with ReadString,
which takes ASCII letters only, so both the command and -- since the name is
written back out as the letter -- this method's own output \operatorname{φ}
were rejected. It now reads char.IsLetter and resolves commands that stand
for a letter, refusing the rest; \operatorname{a|} stays the error it was.

Both directions are covered: parsing, serialising back, evaluating to an
Entity, and laying out. Layout is measured rather than compared against a
baseline image, since the new shapes there are a word-length BinaryOperator
and a non-ASCII operator name, and glyph coverage is already asserted by
TestCommandDisplay.

Four recorded answers changed with the version and are updated, each because
AngouriMath became more careful rather than less:

  sgn(|x|)         was 1; it is 1 away from zero but 0 at zero
  arccos(cos x)    was x; that holds only on [0, pi]
  x <= x           was T; now T for x in RR, the domain <= needs
  cos(-x)          now folds to cos(x), by evenness

Core 1515, Evaluation 962, Rendering 1226, Rendering.Text 237 all pass.
@Rafael-SOWNet

Copy link
Copy Markdown
Contributor Author

Done — and the version is now 2.2.0 rather than 2.0.0-preview.2, since 2.2 is what is on NuGet.

To find the new forms rather than guess at them, I added a sweep: every concrete Entity type AngouriMath can print, Latexized and fed back through LaTeXParser.MathListFromLaTeX. That is the claim Evaluation.Visualize already makes in its own source —

// CSharpMath must handle all LaTeX coming from AngouriMath or a bug is present!
.Match(list => list, e => throw new InvalidCodePathException(e));

— and nothing was checking it. On 2.2.0 it covers 76 nodes, and exactly two forms failed.

\bmod, AngouriMath's modulo node. Added as a BinaryOperator whose nucleus is the word mod: that gives binary spacing, and it stays upright because only Variable and Number go through the italicising font changer. It binds like multiplication and division, which matches AngouriMath's Priority.Mul, so x+y\bmod z is x+(y mod z) on both sides — the grouping cases are in the tests rather than assumed.

\operatorname{\varphi}, Euler's totient. The name was read with ReadString, which takes ASCII letters only. That rejected the command, and — because MathListToLaTeX writes the name back out as the letter — it also rejected this method's own output \operatorname{φ}. It now reads char.IsLetter and resolves commands that stand for a letter, refusing anything else; \operatorname{a|} is still the error it was, and \operatorname{\pm} is a new one.

Both forms are covered in both directions: parsed, serialised back, evaluated to an Entity (MathS.Mod and MathS.NumberTheory.Phi, the latter with no inverse, as abs and sgn already do), and laid out. Layout is measured rather than compared against a baseline image — the genuinely new shapes are a word-length BinaryOperator and a non-ASCII operator name, and TestCommandDisplay already asserts glyph coverage for everything in CommandSymbols.

Four recorded answers in EvaluationTests changed with the AngouriMath version. I checked each rather than just re-recording it, and in every case the library became more careful:

was now
sgn(|x|) 1 unsimplified — it is 1 away from zero but 0 at zero
arccos(cos x) x unsimplified — that holds only on [0, π]
x ≤ x ⊤ for x ∈ ℝ — the domain needs
cos(-x) cos(-x) cos(x) — by evenness

Core 1515, Evaluation 962, Rendering 1226, Rendering.Text 237, all passing. CSharpMath.Xaml.Tests I could not build locally (missing maui-tizen workload), so CI is the check there.

One note for the other side of this: AngouriMath's Docs/Usage/Syntax.md now says its LaTeX round trip "is checked in someone else's repository", meaning this one, and links back here. So the sweep is the thing that will catch the next new node — but only when this repo bumps the version, which is worth knowing.

@Happypig375
Happypig375 merged commit ae6d1b5 into verybadcat:master Aug 17, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants