Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

Pending breakages: changes agreed or arguable that cannot ship before a major version

Aperta
#1,019 72 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
5/5
Tempo stimato
Più di una settimana
Idoneità per principianti
25/100
Tipo di issue
Funzionalità
Chiarezza
Da chiarire
Stato di attività
Attiva
Stack tecnologico
csharp

Direzione di ricerca

Inizia da AGENTS.md e dalle issue collegate per capire quali decisioni sulla major version siano ancora aperte. Poi esamina ToString.Discrete.Classes.cs, Syntax.md e Sources/AngouriMath/Convenience/Experimental/ insieme ai test di round-trip indicati. Il lavoro è completato quando ogni breaking change proposta ha una decisione registrata, un ambito e un piano di validazione prima di dare un nome alla prossima major version.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Opinions wanted

"Maybe an issue on pending breakages would be appropriate. Remember to note to yourself to follow through on the next major version. Also, maybe noting down to promote experimentals and removing obsoletions would be appropriate."
— @Happypig375, #1009

This is that issue: the list of changes that are agreed or arguable but cannot ship in a minor, so that 3.0 has a docket rather than a memory. Nothing here is scheduled and nothing here is a defect report.

A change belongs on this list when it moves the value of existing user input, or removes a published member. A changed answer has gone in a minor here before, on the stated principle that correctness outranks compatibility — but every one of those was a wrong answer becoming right. Everything below is a deliberate convention change, which is a different thing and should not borrow that licence.


1. implies becomes right-associative

Raised on #1009. The grammar folds implies to the left; mathematics, Lean, Coq, Agda, Haskell and CSharpMath.Evaluation all read → to the right. Ours is the outlier, and CSharpMath reading it differently from us is a live inconsistency across a boundary we do not control.

It cannot go in a minor because it re-values existing text:

"false implies true implies false"     today  False        after  True

Nothing fails to compile; answers move silently. #1009 makes the printer state the grouping the grammar actually has, so the change is a one-line flip in ToString.Discrete.Classes.cs (from <=-on-the-right to <=-on-the-left) plus the grammar, and the round-trip tests written there keep it honest.

Also decide provided at the same time. It folds right today, which #1009 documents and tests. If implies moves to the right, the two agree and Syntax.md's rule becomes "^, implies and provided group to the right"; that is worth settling in one go rather than twice.

2. FreeVariables, VarsAndConsts, and a property that does not exist

Raised on #989.

"VarAndConsts is what it says: free variables and constants (pi and e). "Used variables" looks like another property." — @Happypig375

Measured on master at 6b93b401, against that definition. The documented example is Lambda(x, x * 2 + sin(y * pi)):

today by the definition above
Vars x, y —
VarsAndConsts x, y, pi y, pi — x is bound
FreeVariables y y

So VarsAndConsts returns bound names, and its XML example pins that. It is wrong for lambda, which is the one binder the library already honours elsewhere — and wrong for the other five (sum, product, integral, limit, derivative, set-builder) in the same way:

sum(k, k, 1, 3)      Vars = k    VarsAndConsts = k    FreeVariables = k

sum(k, k, 1, 3) is 6. Nothing about that value depends on k, and all three properties say it does.

The shape of the fix, which is three published properties moving at once:

  • FreeVariables — extend "bound" from lambda to every binder. Its own doc comment currently defines bound as "a parameter of some outer lambda", which was accurate when written and is not now that CalculusOperator and ConditionalSet both declare a Var (#986).
  • VarsAndConsts — free variables and constants, per the definition above.
  • A new property for "used variables" — every name that occurs, bound ones included. That is what Vars/VarsAndConsts do today, so the behaviour is not lost, it is renamed to something that describes it.

Part 1 of #989 — the %1 placeholder escaping — was a defect on any definition and is already fixed (#1000). This is part 2, which was always a design call.

3. Promote or retire the experimental features

MathS.ExperimentalFeatures (Sources/AngouriMath/Convenience/Experimental/) is 11 public members, documented as "features that might become stable in the future, but are not guaranteed to do anything useful or correctly at the current moment":

SolveDiophantineEquation · DecomposeRational ×2 · GetSineOfHalvedAngle · GetCosineOfHalvedAngle · ExpandSineArgumentMultiplied · ExpandCosineArgumentMultiplied · ExpandSineOfSum · ExpandCosineOfSum · SymbolicFormOfSine · SymbolicFormOfCosine

Each wants one of three verdicts, and the third is why this is on a breakage list:

  • promote — move to the stable surface under its proper name, and commit to the answer;
  • keep — it is still not guaranteed, and say what would settle it;
  • remove — it has not earned a place, and deleting a published member is a major-version act.

Worth doing as one pass rather than one member at a time, because "experimental" is a promise about the whole namespace and it decays if it is never spent.

Note also that Experimental is a folder inside the kernel package, not a separate package as #746 describes it — see #1008.

4. Removing obsoletions — a standing practice, not a backlog

There are currently zero [Obsolete] members in the tree: 2.0.0 removed the lot. So there is nothing to schedule, and the note to keep is the rule:

Anything marked [Obsolete] during 2.x is removed at 3.0. An obsoletion that survives a major stops meaning anything, and 1.x accumulated a set precisely by never spending them.

5. Already-known decisions that belong on the same docket

AGENTS.md names three under "Decisions only a major version may take", all still open:

  • #204 — roots versus fractional powers. SimplificationContract.md calls it "open and deliberately a major-version question".
  • #326 — the syntax for piecewise. #327's simplification half shipped; the syntax was never touched and no design is recorded.
  • #721 — unify Codomain with a provided … in RR condition. Named on #746 as a consumer of the retired expression-metadata item, and still open.

And one more that is breaking by construction:

  • #217 — complex infinity. It changes 1/0 from NaN, and every consumer branching on NaN is blast radius.

6. | stops meaning or

Raised on #1212, where the invitation was explicit:

"You may change the meaning of | on the next major version if that's more mathematically appropriate. Consider this for all the other parsed inputs as well." — @Happypig375

| is an alias for or today. It is the only spelling in the grammar that already means something else in mathematics — divides (a | b), "such that" ({x | P(x)}), "given" (P(A | B)), and the delimiter in |x| — so input written by a mathematician is read as a disjunction and answered as one. Measured on 281e0d0c:

written reads today as
2 | 6 2 or 6 — a disjunction of two numbers
{ x | x > 0 } { x or x > 0 } — a FiniteSet of one element, that element a disjunction

The second is what decided it: {x | x > 0} is ordinary set-builder notation, and we read it as a one-element set. Well-formed, silent, and nothing like what was written.

Nothing is lost by retiring the alias, since or is the primary spelling and is what everything prints as. & is deliberately not on this list: it is equally a programming convention, but no mathematical meaning competes for it, and the test applied throughout was "does this symbol already mean something else to a mathematician", not "would a mathematician have chosen it".

It cannot go in a minor because it re-values existing text, and the proposal is that it should not go in one major either:

"x > 0 | x < -1"     today  a disjunction        after  a divisibility statement

Nothing fails to compile; the answer moves silently. So two steps rather than one:

  1. First major: | becomes a parse error, with a message naming or. Loud rather than silent, and it costs a release of waiting to remove the entire class of quietly-wrong results.
  2. The major after: | means divides, and "given" inside an expectation or probability — the scoping @Happypig375 proposed on #1212, where E/P introduce the meaning and their closing bracket ends it. divides (#1220) then becomes the alias and | the canonical spelling.

If one step is preferred, the refusal step is the half I would keep regardless of how long it lasts.

7. Not-equal is a relation of its own, and != spells it

Raised on #1212's survey, filed as #1225; the node proposed there by @Happypig375, and the syntax below approved on #1225 (2026-10-02).

Measured on 94ba5ff6:

written parses as prints Solve("x")
x <> 3 not (x = 3) not x = 3 { x : not x = 3 }
a != b a! = b, an Equalsf a! = b
a ≠ b a parse error at ≠

The relation exists only as a negated equality, which the solver does not read, and != is silently a factorial equation.

What moves:

  • A node, NotEqualsf(a, b). It prints as one relation, is solved (x ≠ 3 is CC \ { 3 }, or RR \ { 3 } over the reals), and is matched by rules as a relation of its own. not (a = b) simplifies to it, so there is one canonical form.
  • Input ≠, <> and !=, with != one token, as Mathematica reads it beside the same postfix !: a != b and a!=b are the relation, and the factorial equation is written a! = b, with the space.
  • Printed <> in ASCII, ≠ in Unicode output, \neq in LaTeX.

Why a minor cannot carry it: a!=b and a != b change meaning, and not (a = b) prints and simplifies differently.

8. PeterO's types leave the public API

Raised on #1338, queued for v3 by @Happypig375 there (2026-09-16).

The library's numbers are PeterO's EInteger, ERational and EDecimal, and 48 published members expose them — Integer.EInteger, Rational.ERational, Real.EDecimal, Real.Create(EDecimal), Rational.Create(ERational), Complex.Create(EDecimal, EDecimal), the Deconstructs, the implicit conversions on Entity, Number, Real, Rational, Integer and Complex, MathS.Numbers.Create(...), ToNumber(...), DecimalConst.pi/e, Settings.DecimalPrecisionContext : Setting<EContext>, MaxAbsNumeratorOrDenominatorValue : Setting<EInteger>, PrecisionErrorCommon/PrecisionErrorZeroRange : Setting<EDecimal>, NewtonSetting.From/To, MathS.Utils.TryGetPolynomial(..., Dictionary<EInteger, Entity>), Number.GetAllRoots(Complex, EInteger), GetAllRootsOf1(EInteger), Number.IsZero(EDecimal), Entity.DefiniteIntegral(Variable, EDecimal, EDecimal, int), Rational.FindRational(EDecimal, int).

What moves and why a minor cannot carry it: measured on #1338, one multiply of two hundred-digit integers is 1,271 ns in EInteger and 109 ns in System.Numerics.BigInteger, and an EDecimal multiply or divide is 8–11× a decimal on a BigInteger mantissa; the fixed-point series already run on BigInteger (#1364, #1366) with the conversion at the boundary, and the remaining factor of two to mpmath is that boundary and the decimal layer above it. The plan posted there is in three steps, and only the last is breaking:

  1. done — the series on BigInteger behind an unchanged EDecimal surface;
  2. an internal AngouriMath.Numerics tower — BigInteger, a (BigInteger, BigInteger) rational and a (BigInteger mantissa, int exponent) decimal with a precision context — used by Number behind the current properties, which become conversions; measurable on the whole gate before any signature changes;
  3. v3: the 48 members above take and return the new types, PeterO.Numbers leaves the package's dependencies, and BREAKING-CHANGES.md carries the migration: every EDecimal a caller passes today becomes a decimal of ours (a parse from EDecimal.ToString() is lossless), every EInteger a BigInteger (EInteger.ToBytes/new BigInteger(bytes) both ways), and Setting<EContext> becomes a setting of a precision-and-rounding record of ours.

No answer moves: this changes the types a caller holds, not what any of them is worth.

9. An architectural review, every major version — and for v3, a global restructure

"Remember to do an architectural review every major version." — "refactor the API to reflect the best architecture as needed; major versions are for breaking changes." — and for this one in particular: "for v2->3 we still want to do a global architecture review and restructure pass because v1->2 didn't consider how a Math OS (according to everything in #746) should be structured - it followed mostly v1. Everything across file structure and API structure as well as projects and packages need to be restructured according to that vision. And because this is a global architecture pass, ensure that it's Claude Fable doing it instead of Opus." — @Happypig375, 1, 2, 3

Two things, then. As a standing rule, every major version gets an architectural review: the API read against what was added since the last one, and the parts that now share a better abstraction with the new work refactored to it there, since the major is where the breakage is allowed. For v3 specifically, a global pass: 2.0 followed 1.x's structure and never asked how a Math OS in #746's sense should be laid out, so the file structure, the API structure, the projects and the packages are to be restructured against that vision, not only patched where an abstraction has drifted — item 8's tower and the 48 members it retires are one piece of it, #746's package boundaries (its item 78) another. It is to be done by Claude Fable rather than Opus, per the maintainer, being a global pass; what it decides lands here or in the release, and it runs before v3 is named, not after.

The review also looks for duplicates and synthesises them — "whether hidden in implementation or types representing similar concepts" (4). Two kinds: the same computation written twice in different places (a rule and a solver each doing their own long division, a check re-implemented beside the helper that already answers it), and two types standing for one concept (a Setting<EContext> beside the precision the numeric tower will carry; an ERational beside a Rational; the several spellings of "a polynomial over x" that TryGetPolynomial, MultivariatePolynomial and the Hermite ansatz each keep). Each pair either becomes one thing or gets a written reason for being two, and a major is where the surviving one may take the other's name.

And every release, major or not, updates the website (AngouriMathSite): its What's new and its quickstart name the version they were last brought to, and as of 2026-09-16 that is 2.1.0 against a library at 2.5.0. It is a line on the release checklist in AGENTS.md from here on, not a thing to remember.

10. Numbers, evaluation and comparison: exact where exact, to a requested accuracy where not

Raised on #1376 and queued for v3 by @Happypig375 there (2026-09-16): "It just doesn't look right to have a logical boolean change its value just because we ask it at a different precision. An approximate comparison should be written properly as a chained inequality instead." — "we might want to separate the idea of a complex number that consists of two EDecimals and a real number that consists of an EDecimal from the node hierarchy as well. Any approximate operations with a floating point number would instead be interval arithmetic (or statistical distribution arithmetic if modelled that way)."

What is wrong today: 2 + 2^(-100) = 2 is True, because Equalsf subtracts the sides, evaluates, and asks Number.IsZero, which is |d| < PrecisionErrorZeroRange = 1e-16; Real == Real uses a third constant, PrecisionErrorCommon = 1e-6; and Evaled runs everything to DecimalPrecisionContext's hundred digits whether the question needs one or none. A boolean's value depends on the precision, and an exact rational is thrown away on the way to it.

What moves (the decisions are the review's, item 9):

  • Exact stays exact. Every parsable construction is exact — integers, rationals, radicals, pi, e. A comparison of exact quantities is decided exactly, symbolically where the numbers are algebraic, and enumerates no digits: 1 < 1 + 1^(-1000) < 2 is settled by arithmetic on rationals.
  • Evaluation to a requested accuracy, not to a global context: 3 < sqrt(2) + sqrt(3) < 4 needs one digit after the point and 0 < sqrt(2) + sqrt(3) - pi < 1 needs more, and each asks for what it needs ("Evaled as necessary"). The setting DecimalPrecisionContext : Setting<EContext> (item 8's PeterO type) becomes a request carried by the call, in significant digits or digits after the point, with a repeating expansion for a rational. Speed and memory of getting the correct digits with minimal computation is its own area, and worth it.
  • Approximate values are approximate on their face. A number that arrived as a double, or through an explicit Real constructor, is not exact, and arithmetic on it is interval arithmetic (or a distribution, if modelled so) rather than a decimal that pretends to a hundred digits. An approximate comparison is a chained inequality with the accuracy in it, never an equality with a hidden tolerance.
  • The numeric representation leaves the node hierarchy: a real as one EDecimal and a complex as two are representation, and the tower of item 8 is where that lives, with the nodes holding numbers rather than being them.

Why a minor cannot carry it: Equalsf, Number.IsZero, Real ==, the three PrecisionError* settings and Evaled itself all change what they answer, and every True that came from a tolerance may become False — recorded in BREAKING-CHANGES.md per input as the review finds them.

11. Newton's method is an entry point of its own

Raised on #1573 and queued for v3 by @Happypig375 there (2026-09-29): "Newton's solver is to be a separate entry point compared to the analytical solver since the guarantees of the answers are too different - Newton's solver guarantees "some" solutions on "more" equations while the analytical solver guarantees "all" solutions on "less" equations. Moreover, numerical approximation is to be their own types separate from the normal exact node hierarchy."

What is wrong today: where every analytical route declines, Solve falls back to Newton's method (MathS.Settings.AllowNewton, on by default) and answers the points it finds as a FiniteSet, which reads exactly like a complete, exact solution set. abs(x - 2) = abs(x - 3) was three points of the line Re x = 5/2. #1578 keeps the fallback away from equations real for every complex x, which is a guard and not the separation.

What moves: Solve answers what the analytical solvers establish, all the solutions or the equation left unsolved, and Newton's method becomes its own entry point, returning approximations typed as approximations (item 10) with no claim to be all of them.

Why a minor cannot carry it: every equation Solve answers today only through the fallback becomes unsolved there, a changed answer for each, and the types the new entry point returns are item 10's.


12. "Simplified" is a stated property, not a rating

Raised on #1409 by @Happypig375 (2026-09-29): "We also need a better definition of "simplified" for v3 (#1019). Counting the arbitrarily defined simplified rate isn't how mathematicians do it..."

What is wrong today: Simplify returns whichever candidate it generated has the lowest SimplifiedRate, a weighted count of nodes, and a tie goes to whichever was generated first. CanonicalForm.md §1 makes that the definition: "simplest is the best-rated member of an equivalence class under a cost metric." So an answer is simplified only relative to a number nobody states, and moving a weight moves answers nobody asked about.

What moves: simplified becomes a list of properties a result has, written per node class beside the canonical form, the way a textbook defines simplest radical form:

  • like terms combined;
  • a quotient in lowest terms, with no fraction nested in it;
  • no radical in a denominator, and no perfect power under a radical;
  • no negative exponents;
  • a function of an exact number evaluated where the value is exact.

Each is checkable on the answer, so Simplify is tested against the list the way canoncheck tests canonical form. A rate at most breaks ties among forms that already satisfy it. A shape that a question wants for its own purpose (factored, expanded, in partial fractions, over a common denominator) is asked for by name, as Factorize and Expand already are.

Why a minor cannot carry it: most answers Simplify gives today would be re-derived against the list, and every one that changes is a changed answer.


13. Exceptions are for unrecoverable errors; the lack of a value is null

Raised on this issue by @Happypig375 (2026-09-30): "Design principle for v3: exceptions are for unrecoverable errors; the lack of value is null."

What is wrong today: several public methods throw when they have no value to give, and a caller finds out only by catching.

  • EvalNumerical and EvalBoolean throw CannotEvalException where an expression has no value (#1570).
  • An operation the library does not support throws NotSufficientlySupportedException, from 12 sites (#1569).
  • Compile and SolveNt throw UncompilableNodeException where the compiler has no form for a node, from 17 sites. #1603 keeps Solve from reaching it; #1605 leaves SolveNt's exception in place for 2.x, because it is a public contract.
  • A limit toward a complex infinity throws LimitOperationNotSupportedException.

#1540 took exceptions out of the library's own control flow for 2.6.0. These are what remain, and all of them are on the public surface.

What moves: each of these returns null, typed as nullable, so that the compiler holds every caller to the check. Every other exception type is to be reviewed the same way, and presumably replaced (@Happypig375 on #1569, 2026-09-30: "all exception types require a review to see if null-returns or returning a union type (think how you'd do it in functional languages like F#) is cleaner for the API shape instead. Presumably all exceptions are to be replaced with proper return types."). Where there is more than one reason for the lack of a value, the reason is itself the return value, as a union. The candidates for staying an exception, which the review decides:

  • misuse, such as SolveRequiresStatementException and WrongNumberOfArgumentsException;
  • the library contradicting itself: AngouriBugException, 57 sites;
  • input that is not an expression at all: the parse exceptions. A TryParse-style entry that returns null, or a union with the parse error, can sit beside Parse.

One is kept already (@Happypig375 on #1569): the implicit conversion from a string, which declares an entity in one line and has no return value to put a failure in. No other case for throwing is known.

Two decisions went with it, and @Happypig375 settled both (2026-09-30): "treat Undefined and Indeterminate as proper values on their own like Mathematica does (We won't have NaN in v3 because it's inherently a value defined by an approximate floating point type)."

  • An operation on matrices of shapes it isn't defined for is Undefined, a value: neither misuse nor null (InvalidMatrixOperationException and InvalidNumberException, 24 sites between them).
  • There is no NaN in v3. 0/0 is Indeterminate, as one of the indeterminate forms, and 1/0 is complex infinity (#217). Null still says only that no value was produced.

Why a minor cannot carry it: every method named above changes its return type or its contract, and a caller that catches today either stops compiling or stops being reached.


14. Definedness comes from the arithmetic, and from a rule's stated condition

Raised on #1648 by @Happypig375 (2026-10-01): "Note the correct design for v3 (#1019) if you identify one".

What is wrong today: rewrites such as a / (b / c) → a * c / b give a value where the expression has none. 1/(1/x) simplifies to x, which is 0 at x = 0, where 1/(1/x) is NaN. O4 of SimplificationContract.md forbids that, and of the three 2.x fixes measured on #1648, none is clean.

What moves:

  • On v3's arithmetic, most of these rewrites are identities. There 1/0 is complex infinity (#217) and 0/0 is Indeterminate (item 13), so 1/(1/0) is 1/∞ = 0, the same as x. Measured with sympy's zoo and nan, letting each hole take 0, ∞, Indeterminate and five finite values. Holes need the infinite values because a hole matches a subexpression, and a subexpression can be infinite where the variables are not:

    rewrite assignments that agree
    a/(b/c) → a*c/b 512 of 512
    (a/b)/(c/d) → (a*d)/(b*c) 4096 of 4096
    (a/b)/c → a/(b*c) 512 of 512
    (a^n)^m → a^(n*m), m whole 200 of 200
    a/csc(b) → a*sin(b), and likewise sec/cos and cot/tan 88 of 88 each

    All eight examples of #1648 agree at their singular points. These rules carry no condition in v3, and any condition 2.x attaches to them in the meantime comes off.

  • The rest state their condition in the rule, as data. Some rewrites change definedness even on the sphere, and the same measurement finds them:

    • a/a → 1 at 0, ∞ and Indeterminate;
    • 0·a → 0 and a − a → 0 at ∞ and Indeterminate;
    • (a·b)/(a·c) → b/c, which is what pairwise grouping does when it cancels;
    • e^ln(a) → a at 0 and ∞. Whether this one belongs here depends on whether #217's infinity is directed: in Mathematica, Log[0] is -Infinity and e^-∞ is 0.

    Each such rule declares its condition beside its pattern, where when: sits today, and soundcheck checks each declaration at the points where the two sides differ.

  • The engine carries conditions beside the candidate, not inside it. It collects what the applied rules declare and drops whatever the input's own domain (DomainConditionIn) or the preamble already implies. What remains is stated once, on the answer. The alternative was measured on #1648: a provided inside the search hid the rewrite's shape from the rules that continue from it, and gave 34 failures, about 20 of them lost capability.

Why a minor cannot carry it: the arithmetic is #217's, and every answer that gains or loses a condition is a changed answer.


15. The number system says which infinities it has

Raised on #1648 by @Happypig375 (2026-10-02). over RR and over CC don't include infinities, and today's default includes them in a way that is neither the extended reals nor the Riemann sphere.

What is true today, measured on master bc6c190c:

  • oo and -oo are reals. Each part of a complex number can be infinite on its own, as in oo + i or -oo i. There is no complex infinity: 1/0 is NaN (#217). So the default is the complex plane with an infinity in each axis direction.
  • RR treats the two infinities differently: -oo in RR simplifies to True, while oo in RR is left undecided.
  • oo - oo and 0 * oo simplify to 0. These are item 14's a − a → 0 and 0·a → 0 at ∞.

What moves:

  • Five sets, each with a name, agreed on #1648: RR and CC without infinities; the extended reals, RRbar, which are RR with -∞ and +∞; and the two projective lines, RRhat and CChat, which are RR and CC each with one unsigned ∞ — the projectively extended reals and the Riemann sphere. The bar is a line with two ends, the hat two lines meeting at one point. Each algebra with an unambiguous notation has a short name, and its full name is a synonym (@Happypig375, 2026-10-02): Reals, Complexes, ExtendedReals, ProjectiveReals and ProjectiveComplexes. The default has no notation, so it has only its full name.
  • One projective infinity, printed ∞̃ and \tilde{\infty} in LaTeX as Mathematica (ComplexInfinity) and Calcium (UnsignedInfinity) print it, with SymPy's zoo proposed for its ASCII spelling: the point at infinity of RRhat is the same point as CChat's, since P¹(R) ⊂ P¹(C), and it is the default's undirected infinity, #217's 1/0.
  • The default is the complex singularity closure, Calcium's term (Johansson, arXiv 2011.01728, after Mathematica): CC, the directed infinities, ∞̃, and item 13's two exceptional values, Undefined and Indeterminate, where Calcium has one. Calcium's sets match these: ExtendedRealNumbers is RRbar, ProjectiveRealNumbers and ProjectiveComplexNumbers are RRhat and CChat. Written over ComplexSingularityClosure where it has to be named.
  • oo by algebra: +∞ in the default and in RRbar; under RRhat or CChat, oo and -oo both name the one point at infinity; under RR or CC, neither is a member.
  • Undefined and Indeterminate propagate in every algebra (@Happypig375 on #1648): an operation on either gives it, over RR as over the default. What an algebra decides is membership — Undefined in RR is false, Undefined in ComplexSingularityClosure true — and the value at its own special points: 1/0 is Undefined over RR, outside it, so division is partial there; and ∞̃ over the projective lines and the default, inside them, so division is total there.
  • Mixing overs: every named set sits inside the default, so nodes under different overs combine in the default and the result is the default's: (oo over RRbar) + (oo over RRhat) is +∞ + ∞̃, Indeterminate. No over means the default, and a prelude can set another for every node.
  • The projective lines share one arithmetic: x/0 = ∞ for x ≠ 0, x ± ∞ = ∞ and x/∞ = 0 for finite x, x·∞ = ∞ for x ≠ 0; ∞ + ∞, ∞ - ∞, 0·∞, ∞/∞ and 0/0 are Indeterminate; and there is no order, so ∞ > 0 has no value. Where they differ from RRbar is limits: 1/x at 0 tends to ∞ on the projective line and has no limit over the extended reals.
  • The default is stated. One model already has the default's shape, and it is Mathematica's: directed infinities ∞·e^(iθ), with +∞ and -∞ as the real directions, plus one undirected complex infinity, which is #217's 1/0. Together with Indeterminate (item 13), that set is closed under the arithmetic. Over the extended reals only the two real directions remain, and over the sphere every infinity is the one ∞. Its name is Calcium's, the complex singularity closure (below). It is documented as what evaluation works in, and over takes the named sets only.
  • over RR and over CC exclude every infinity. A limit of +∞ has no value over RR, and x in RR is false at ±∞. oo - oo and 0·oo are Indeterminate.
  • Rules ask for properties, not for algebras (@Happypig375 on #1648, 2026-10-02). Every algebra declares: division by every nonzero element (a field); no zero divisors; commutative multiplication; an order compatible with the arithmetic; its characteristic. A rule names what it needs -- a/a = 1 division, a^2 = 0 ⇒ a = 0 no zero divisors, a b = b a commutativity -- and applies only where the algebra has it. These are the assumptions #1252 says the 177 SoundUnderAssumptions rules declare and do not name.
  • ZZ/nZZ, the integers modulo the ideal nZZ, n a number or a symbol: a field for a prime n, with zero divisors otherwise (2 * 3 = 0 in ZZ/6ZZ). Today's a = b (mod n) is membership in one class of it. ZZ_3 is not used, being the 3-adic integers to many readers.
  • No further algebras in the default: hyperreals, infinitesimals, quaternions. @Happypig375 on #1648: the simplification rules would be damaged the further the default goes beyond the complex numbers with infinities, because more functions become multi-valued under inversion and more identities stop holding. Orders of vanishing and asymptotics, what infinitesimals would be used for here, limits and series already answer. Dual numbers (ε^2 = 0, for automatic differentiation) would be a separate algebra, outside the default.

Why a minor cannot carry it: oo - oo, 0·oo and the membership of every infinity change their answers, and #217 changes 1/0.


16. amcli's commands say what they do

Raised on #1654 by @Happypig375 (2026-10-02): "remember to revise the command names for clarity and correctness for v3".

#1654 kept the standalone CLI's names so that its scripts would keep working. A proposal:

today v3 why
eval evaluate the library's verb. It evaluates what it can, so amcli eval "x + 1" prints x + 1, and the usage line's "evaluates to a number" claims too much
simp simplify the library's verb
fsimp normalize it is the normalisation without the search, InnerSimplified, and fsimp names neither
diff differentiate diff reads as a difference
sub substitute sub reads as subtract
info describe the code already calls it describe, and the name says what it prints
solve, latex unchanged

Why a minor cannot carry it: removing a name breaks the scripts that call it. A minor can add the new names beside the old ones first, and v3 then removes the abbreviations.


17. Solve takes several unknowns, and EquationSystem goes

Raised on #1673 by @Happypig375 (2026-10-02): "this method is to be removed for v3 - let solve return for multiple variables."

A system is a conjunction, and Solve already reads and for one unknown. MathS.Equations(...).Solve(x, y) is a second entry point that takes each equation in = 0 form and returns a matrix of solution rows. Proposed:

  • "x + y = 3 and x - y = 1".Solve("x", "y") solves for both unknowns and returns the solutions jointly, { (2, 1) }, which wants a tuple that is not a vector.
  • MathS.Equations and EquationSystem are removed.

Before it, #1680 has to hold: a conjunction with a parameter keeps its second equation where its members leave it undecided, rather than dropping it.

Why a minor cannot carry it: removing MathS.Equations breaks every caller, and a minor can only add Solve(x, y) beside it.


What this issue is for

To be read before the next major version is named, in the same way #746 is read before any version is named. It is not a plan and it does not commit anyone.

Anything added here should say what moves, what the old and new values are, and why a minor cannot carry it.

Lingua principale
C#
Stelle
831
Fork
79
Merge medio
2h 22m
PR unite (30g)
507

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di ASC-Community/AngouriMath

Tutte le issue di ASC-Community/AngouriMath

Issue simili

Altre issue su C#

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.