Releases: asc-community/AngouriMath
Release list
2.4.0
Tier 1 of the Math OS roadmap is
finished, and the thing that finished it kept finding wrong answers. Writing a rewrite rule out as
data — a pattern and a replacement, rather than an arm of a switch — makes the
correspondence between the two something you have to state. Four times this cycle, a rule did not
survive stating it.
Every changed answer is in BREAKING-CHANGES.md
under 2.4.0 — since 2.3.0, with the old value, the new one and why, each measured on a build
of both sides. Read that first if you have code depending on an answer. Twenty-seven entries, and
more than half are marked Silent — the call still succeeds and quietly returns something else.
AssemblyVersion stays 2.0.0.0. The recorded public surface shows 68 additions and 130
removals, and none of the removals is one a caller can hit: Stringize() and Latexize()
stopped being abstract on Entity and each node's override became a private helper, so the
member is still public on Entity and inherited by every node. Source- and binary-compatible.
Wrong answers fixed
- A factorisation that was not equal to what it factored.
Factor("4x² − 4y²", "x")returned
(x + y)(x − y)— the4simply gone, the difference from the input−3x² + 3y². Every
candidate in the polynomial layer is checked by exact division, but that check is on the
individual factors; nothing compared the assembled product against the input, so a constant
lost during assembly was lost silently. (#1092) (y < x) or (x = y)simplified tox <= y— its own negation off the diagonal. Four of the
eightor-with-equality rules carried their neighbour's comparison. Only reachable with both
operands symbolic: with a number on one side,2 < xis rewritten tox > 2earlier in the same
pass and one of the four correct rules matches. A test written with a numeric operand would
have passed on the defect. (#1077)x! = 0was answeredFalseeverywhere, including at the negative integers where the
factorial has a pole and the statement isNaN. The rule read a property pattern on the
factorial's argument rather than on the factorial. It tookx! / x!→1with it, and three
recorded test verdicts had been recording that. (#1081)ln(1/b) = −ln(b)was applied unconditionally, which is false on the negative reals — at
b = −0.63the two differ by the full turn of the argument the principal branch discards.
Three rules gained the guard their neighbours ten lines below already had. (#1062)
Factorisation
Factorize was built entirely out of rewrite rules, so it factored what someone had written a
rule for and handed everything else back whole — while square-free decomposition, Zassenhaus over
ℚ and the multivariate GCD sat in the tree unused by it.
"x3 - 1".Factorize() x ^ 3 - 1 → (x - 1) * (x ^ 2 + x + 1)
"x4 - 5x2 + 4".Factorize() unchanged → (x + 1) * (x + 2) * (x - 2) * (x - 1)
"x2 + 2x + 1".Factorize() unchanged → (x + 1) ^ 2
The layer speaks only where the rules said nothing, so every answer they already gave is
unchanged — the order two factors come out in is arbitrary and theirs is the one on record. (#1018)
And the layer itself reaches further. Hensel lifting along an evaluation homomorphism (#1088,
#1089) factors bivariate polynomials that Kronecker's substitution refuses — not because its image
is too large but because it over-factors: x⁷ − y⁷ maps to t⁷(1 − t⁴⁹), whose factors are
cyclotomic. An evaluation image inflates nothing.
Factor("x12 - y12", "x") null → six factors, the full cyclotomic split
Factor("x7 - y7", "x") null → (x - y)(x⁶ + x⁵y + ⋯ + y⁶)
Where the substitution gives up entirely, an evaluation image can still prove a polynomial
irreducible — which since #1059 is an answer rather than a refusal, so
Factor("x2 + y2 + z2 + w2 + 1", "x") returns the polynomial instead of null. (#1087)
The rule sets are data
Thirty of thirty rule sets now have a form in which each rule is a value — a pattern, a
replacement, a soundness tier and a direction — proven to agree with the switch it replaces over
thousands of generated expressions. Twenty-seven run it. The three that do not are the canonical
orders, and that is a measurement rather than an omission.
It buys: every rule individually addressable (407 entries), per-rule soundness where only the set
had a tier before (181 Sound, 141 SoundUnderAssumptions), and 26 rules that can be read
backwards.
Performance, honestly
SimplifyEasy is about 13% slower than before the exchange — 82,676 ns to 93,732 ns on one
desktop, both arms, standard deviation under half a per cent. Every conversion was measured
against the commit in front of it and every one came back free or better; nothing was measured
against the start, and the sum of a run of free steps is +13%.
It would have been worse. Indexing each set's rules by node type recovered most of it, and a
bounded pattern is now walked by index rather than enumerated — 165.05 MB to 163.40 MB of
SolveMediumHard on its own.
The work shape is unchanged: 4,914 rule-set invocations on that input at both ends, so this is
per-operation overhead rather than extra work. version_performance_control.md records where it
goes, what three attempts to remove it measured, and the roughly 40% still unattributed.
That file also gained a measurement worth more than the column: the Kernel Benchmark run twice
on one commit is 30–57% apart on every benchmark, while allocation over the same pair agrees to
0.03%. Timing comparisons between its columns are evidence only above about 50%.
2.3.0
Correctness release, and the first one whose claim to that is measured on an outside corpus rather
than only on our own tests. Against Rubi's integration suite — 1774 problems that each carry an
antiderivative known to exist — this version answers 604 where 2.2.0-era master answered 536, and
gets 0 wrong where that answered 7. Six of those seven were NaN: a definite claim that no value
exists, made about integrals that have one.
Every changed answer is in BREAKING-CHANGES.md under 2.3.0 — since 2.2.0,
with the old value, the new one and why, each measured on a build of both sides. Read that first if
you have code depending on an answer.
AssemblyVersion stays 2.0.0.0. This release removes and renames nothing — 103 additions and 0
removals against the 2.2.0 public API baseline — so it is a drop-in replacement in both the binding
and the source sense, which 2.2.0 was not.
Wrong answers fixed
- The symbolic determinant was
NaNfor ordinary matrices. Gaussian elimination left the pivots as
literal divisions, so the expression was undefined wherever a pivot vanishes. Two of four ordinary
3×3 matrices came backNaN, one of them the singular example every linear-algebra course opens
with. It is Laplace expansion now, which never divides — and is faster, dramatically so on numeric
matrices. (#992) - A matrix was a member of every special set at once —
BB,ZZ,QQ,RR,CCand their
intersections — because membership was answered with a guard that is deliberately permissive about
what it has not ruled out. Asking "might this be a member" and reporting it as "is a member" are
different questions. (#995) - Differentiating over
piorebehaved as though they varied.sin(pi)differentiated by
MathS.piwas-1, which iscos(pi): the chain rule run over a symbol that cannot change. It is
0. (#993) Differentiate(x, n)returned raw chain-rule output forn >= 1, and because each pass
differentiated the unsimplified result of the last, the expression compounded —x^4three times was
a screenful where differentiating three times by hand is2 * x * 3 * 4. Same value, and only one of
them is an answer. (#1002)- A bound
piorestill carried the constant's value, so a binder could not bind them and
derivative(e^2, e)was0. A name a binder declares is a variable, whatever it is spelled. (#984) - Differentiating or integrating over something that cannot vary — a number in the variable
position — renamed it and answered the derivative of a question nobody asked. (#964)
Interoperability
ToSympyCodeemitted Python that does not run, for every set, every lambda, everypiecewise
and every non-vector matrix: unqualifiedFiniteSet,Interval,UnionandSagainst a preamble
of onlyimport sympy; a lambda with no body; a set builder that threw out of the exporter; and
Interval,PiecewiseandMatrixwriting their children as this library spells them rather than
as SymPy does. Measured by executing the generated program rather than reading it: 24 of 45 ran
before, 45 of 45 run now. (#985)
Names and reporting
- A set builder leaked its internal placeholder.
"{ k : k > 0 }".FreeVariableswas{ %1 }— a
name in no expression, not typeable, and different for a different predicate. It also brokeVars'
own promise in both directions at once: the name that occurs was missing and the one that does not
was there. (#989) Stringizeof aRationalread back as aDivf, so the round trip was not an identity. Fixed
by the parser change below rather than by anything aimed at it. (#873)- A quotient of two integer literals now parses as the
Rationalit denotes rather than as a
division.
Under the hood
The rule registry grew to cover every addressable rule set, with confluence and termination checked by
tooling rather than asserted — #746 tier 2
asks for exactly that. Core.Binding makes binder resolution happen at construction, which is what let
i, pi and e become bindable names.
Performance
The 1769th column of
version_performance_control.md,
taken on the same runner class as the 1620th and 1671st so the three are comparable. Every row faster
or flat. SolveEasy is 21.3 ms to 8.5 ms — a 2.5× speedup with a 2.3× allocation drop beside it,
which is how you tell work from machine noise.
What this release is not
It does not complete a #746 tier. It
advances tier 1 and tier 2 and finishes neither, which is why it is a minor version. The rewrite graph
that v2.0 is reserved for is still ahead.
2.2.0
Infrastructure release. 2.1.0 was mostly wrong answers becoming right ones; this one is mostly the
layer underneath them — a real polynomial layer, and a written specification of what canonical
form means here with both halves implemented. The corrected answers in it are largely consequences
of those two rather than separate fixes.
Every changed answer is in BREAKING-CHANGES.md under 2.2.0 — since 2.1.0,
with the old value, the new one, and why, measured on a build of each version. Read that first if you
have code depending on an answer.
AssemblyVersion stays 2.0.0.0. See the rename note at the bottom before dropping the DLL in
without recompiling.
A polynomial layer
The single item that #746 names as
unblocking a large fraction of the tracker. Multivariate GCD, resultants, square-free decomposition,
and factorisation over ℚ and finite fields. (#918, #920/#923, #921/#927)
It is not shipped for its own sake — three things in this release are consequences of having it:
- A polynomial equation that factors is solved through its factors.
x^5 + 2x^3 - 2x^2 - 4
returned three of its five roots, one of them a float; it returns all five, exact.x^4 + x^2 + 1
loses a nested radical. (#918) - A rational function is decomposed over the factors of its denominator, not only its roots, so
1/(x^4 + 3x^2 + 2)and1/(x^4 + 4)now integrate instead of coming back unevaluated. (#926) - A resultant is bounded by measured work rather than by a reasoned size limit, which raised the
ceiling from a Sylvester matrix of 24 to one of 40 without risking the blow-up the old bound was
guessing at. (#921/#927)
Canonical form: specified, measured, and offered
Docs/Contributing/CanonicalForm.md states the position rather than leaving it to be inferred:
canonical is about identity, simplest is about presentation, and there is no canonical form for
the whole language — zero-equivalence is undecidable once pi, exp, the trigonometric functions and
abs are in play (Richardson 1968). So the specification is a canonical form on a decidable
sublanguage, a normalisation elsewhere that must not be mistaken for one, and a search that is not
required to be canonical at all. (#928)
Both halves are now reachable from Entity, beside Simplify and Factorize:
Entity Canonicalize() // the commutative structure: 0 idempotence and
// 0 order-independence failures over 834 expressions
Entity? CanonicalizeAsRationalFunction() // rational functions over Q -- or null, which is the
// library saying it has no answer rather than guessingx/x canonicalises to 1 provided not x = 0 and is deliberately not equal to the canonical form of
1: the quotient is undefined where the polynomial is not. (#933, #935, #940)
Nothing applies either by default. Simplify and InnerSimplified return exactly what they
returned before. Turning canonical ordering on by default would change every commutative operand order
in every printed answer, and that is a decision for a release that says so.
Wrong answers fixed
sin(-x) + sin(x)was left as written and is0— the parity identities were not being applied.
cos(-x)andabs(-x)fold too. (#929/#931)InnerSimplifiedis idempotent again. An exact trigonometric value reached through a half turn
came back as-(-1)where it should have been1. The value was never wrong, but applying
InnerSimplifiedtwice gave a different tree from applying it once, and much of the library treats
what it returns as settled. (#930/#932)- A negative pair keeps its sign. (#936/#937)
- The logarithm's domain follows the reading, as every other node's already did, so
log(-3, -3)
is no longer declared undefined while evaluating to1. (#721/#890, #916) log(x, x)was1 provided x > 0—NaNat every negativex, and1atx = 1where the
logarithm isNaN. (#916)d/dx x^ncarriedprovided x > 0, a condition it never needed, making the derivative undefined
at every negativex. (#916)- A sum of logarithms is no longer gathered unless that is exact —
ln(a) + ln(b) -> ln(a*b)is
wrong by2*pi*ioff the positive reals. Two limits lost to that guard in 2.1.0 are back, via an
ambient scope rather than a new pass. (#922, #925)
Under the hood
- A rewrite rule's left-hand side can be data.
MatchPatternmatches by enumerating solutions, so
commutative operands backtrack properly, and three rule sets are expressed as data and proved
equivalent to theswitchthey mirror. Internal for now — it is a prerequisite for
#746's rewrite graph, and for a rule being
able to carry its own justification. (#248, #938) - A measured performance pair is published in
Docs/WhatsNew/version_performance_control.md, both
columns re-measured on one machine. It caught four solver benchmarks 7–21% slower with allocation up
10–20%, isolated to the polynomial layer by bisecting on allocation. That is the price of the
factoring solver, recorded rather than quietly absorbed — and the same document notes that none of
the ten solver benchmarks factors, so the suite measures that change's cost and none of its benefit.
One rename
Five members were spelled -ise on a surface that is otherwise Factorize, Latexize,
Normalization. Three had not shipped; two had:
| Was (2.1.0) | Is |
|---|---|
Transformation.Rationalisation |
Transformation.Rationalization |
RewriteRules.RationaliseDenominator |
RewriteRules.RationalizeDenominator |
Recompiling turns a stale reference into a compile error. Swapping the DLL without recompiling does
not — AssemblyVersion is pinned at 2.0.0.0 so the assembly still binds, and the call throws
MissingMethodException when it is reached. Documentation prose keeps British spelling; the convention
is about identifiers. (#940)
2.1.0
AngouriMath 2.1.0
Correctness release. Almost everything here is a wrong answer becoming a right one, and most of it was
found by harnesses rather than reported — boundary points where a rule's assumption fails, one child
process per case so a stack overflow is a result rather than the end of the run, every documented code
sample compiled and run, and the generated SymPy code executed rather than read.
Every changed answer is in BREAKING-CHANGES.md under 2.1.0 — since 2.0.0,
with the old value, the new one, and why, measured on a build of each version. Read that first if you
have code depending on an answer.
AssemblyVersion stays 2.0.0.0, so this is a drop-in replacement for 2.0.0 on a strong-named reference.
Wrong answers fixed
arcsin(sin(x))and three siblings no longer cancel off the principal branch.arcsin(sin(3))was
3; it ispi - 3. Four rules had been wrong since 2020. (#884)arctan(x) + arccotan(x)is no longer alwayspi/2— this library'sarccotanhas range
(-pi/2, pi/2], so the sum is-pi/2for negativex. (#887)ln(e^x)no longer simplifies tox, which is wrong whereverIm xleaves(-pi, pi]: at
x = 3*pi*ithe expression ispi*i. (#902)log(1, 1)was0and isNaN— it is0/0.log(1, 2)was+oo. (#890)abs(sgn(x))andsgn(abs(x))were1, and both are0atx = 0. (#892)- A logical connective is no longer strict in
NaN.False and uisFalsefor an operand with no
truth value, which is whatSimplifyalready answered while evaluation saidNaN. (#880) - A connective over a number now declines rather than reporting the same type error three
different ways. A number is not a truth value. (#897) - A conditional set's bound variable was named from a hash of the predicate, which could spell
true
and throw — an intermittent CI failure that would not reproduce. (#891)
Better answers
absfolds where the sign of its argument is known.abs(-sqrt(6))issqrt(6); a concrete
quadratic inequality no longer answers withabs(-sqrt(6)) / 2as an endpoint. (#881)-(a - b)is turned round wherever it sits — inside a power, a function's argument or a matrix, not
only at the root — andExpandnow descends into a matrix. A solved system's entries are shorter for
it. (#882)NaNis a literal. It printed asNaNand parsed back as a variable of that name, so
NaN - NaNwas0. (#906)MathS.ToSympyCodeemits Python that runs and stays exact. Any non-integer rational produced a
SyntaxError,NaNand the infinities were unbound names, and1/2arrived in SymPy as the float
0.5. (#909, #911)
Two answers withdrawn on purpose
Both are recorded in the changelog rather than quietly dropped.
lim x->+oo (x^2)^x / e^(2*x*ln(x))andlim x->+oo x^x / e^(x*ln(x) - ln(x))are unevaluated
where they used to be answered. They needln(a^c) = c*ln(a), which is false in general; on the way to
+oothe base really is positive, and there is currently no way to tell the simplifier so. Unevaluated
rather thanNaN, so the caller is told nothing was settled rather than told the limit does not exist.false and 0andtrue or 0wereFalseandTrueby short-circuit. Whether an operand is admissible
cannot depend on whether the operator happened to need it.
One word reserved
NaN is now a keyword, so it can no longer be a variable name — the same trade mod took in 2.0. Only
the exact spelling: NaNx and NaN_1 are still variables.
Performance
Measured, not hoped for: v2.0.0 and this release benchmarked minutes apart on one machine, published as
a pair in
Docs/WhatsNew/version_performance_control.md.
No regression — the largest real move is SolveMedium at +4.6%, the rest sits inside ±3%, and
allocation is flat with three rows byte-identical.
Known, and not fixed here
ln(x) + ln(x+1) -> ln(x*(1+x)) is still unsound off the positive reals, and log(x, x) -> 1 provided x > 0 declares itself undefined at x = -3 where it evaluates to 1. Both wait on
#721 — whether a domain is a property a node
carries or a query with the reading passed in — because guarding either one costs coverage that an
assumption travelling with the expression would not.
v2.0.0
v2.0.0-preview.2
The second preview of 2.0. Replaces 2.0.0-preview.1, which has a defect in Expand — see below. If you are testing against the preview, move to this one.
Please read BREAKING-CHANGES.md before upgrading. It lists every place the same input now gives a different result, with the value before and the value now, both measured on a build rather than taken from the diff.
What changed since preview.1
Expand no longer loses a term that takes no power
Expand turned RR + 1 into NaN, and with it ZZ + 1, CC + 1, QQ + 1, BB + 1 and true + 1. Simplify then returned NaN too, because it offers the expanded form as a candidate and NaN rates as the simplest thing on offer.
| 1.4.0 | 2.0.0-preview.1 | 2.0.0-preview.2 | |
|---|---|---|---|
"RR + 1".Simplify() |
RR + 1 |
NaN |
RR + 1 |
"ZZ + 1".Simplify() |
ZZ + 1 |
NaN |
ZZ + 1 |
Collecting like terms reduces every factor to a base and an exponent and puts the term back together, and a factor that appeared once came back as base^1. Raising to the first power is an identity only where the power is defined at all — RR^1 and true^1 are NaN — so the reassembly turned an expression that had a value into one that did not. Sets that can be shifted were never affected and still are not: { 1, 2 } + 1 is { 2, 3 }.
Found by running CSharpMath's test suite against preview.1: 955 green on 1.4.0, two red on the preview. This closes one of the two; the other is the documented radical change.
Documentation and measurement
integraltakes bounds, not a repetition count:integral(f, x, from, to)is now written down in the syntax reference, along with whyderivativetakes an order andintegraldoes not. The change itself was made in 1.4.0 and had never been recorded —BREAKING-CHANGES.mdnow has a section for it, since 1.4.0 is whatdotnet add packagestill installs.- The samples are built and run in CI. Two of them had been broken against the current release since January, hidden by a pin to 1.3.0; a third was broken in plain sight because nothing ran it.
- Trigonometry against precision is now benchmarked, and allocation is recorded alongside the timings.
The rest of 2.0 is unchanged from preview.1
Most of 2.0 is a wrong answer becoming a right one. That is still a breaking change if you built on the wrong one, and a large share of these changes are silent: the call still succeeds and quietly returns something else.
The loud breaks — the compiler finds these for you:
| was | is | |
|---|---|---|
| target frameworks | net7.0;netstandard2.0 |
netstandard2.0;net8.0;net10.0 |
| 28 members deprecated since 1.x | obsolete but present | removed |
Latexise, ILatexiseable, entity_latexise |
the British spelling | Latexize, ILatexizeable, entity_latexize |
MathS.Quantum.Factorise |
one letter from the unrelated Entity.Factorize |
MathS.Quantum.TensorFactorize |
MathS.Quantum.IsNormalised |
the British spelling | IsNormalized |
Minusf.Minuend / .Subtrahend |
named for the wrong operand | named for the right one |
The silent ones are what to test against — sqrt(x^2) left as written, -7 mod 3 now 2, sqrt(12) now 2*sqrt(3), numbers below 1e-16 kept, an identity equation solving to CC, many limits returning a value where they returned NaN, Stringize output parsing back. The full list with worked examples is in BREAKING-CHANGES.md.
Reporting
If something you relied on changed and it is not in BREAKING-CHANGES.md, that is a bug in the notes as much as in the code — please open an issue either way. The Expand defect above was found by running a downstream project's tests against preview.1, which is exactly what a preview is for.
Packages: AngouriMath, AngouriMath.FSharp, AngouriMath.Interactive, AngouriMath.Terminal.
v2.0.0-preview.1
The first preview of 2.0, the release where AngouriMath changes answers it was getting wrong.
Please read BREAKING-CHANGES.md before upgrading. It lists every place the same input now gives a different result, with the value before and the value now, both measured on a build rather than taken from the diff.
Why a preview rather than 2.0.0
Most of 2.0 is a wrong answer becoming a right one. That is still a breaking change if you built on the wrong one — and a large share of these changes are silent: the call still succeeds and quietly returns something else. No compiler error, no exception, just a different value.
Those are the ones a preview exists to surface. If you depend on AngouriMath, this is the build to try before 2.0.0 is final.
The loud breaks — the compiler will find these for you
| was | is | |
|---|---|---|
| target frameworks | net7.0;netstandard2.0 |
netstandard2.0;net8.0;net10.0 |
| 28 members deprecated since 1.x | obsolete but present | removed |
Latexise, ILatexiseable, entity_latexise |
the British spelling | Latexize, ILatexizeable, entity_latexize |
MathS.Quantum.Factorise |
one letter from the unrelated Entity.Factorize |
MathS.Quantum.TensorFactorize |
MathS.Quantum.IsNormalised |
the British spelling | IsNormalized |
Minusf.Minuend / .Subtrahend |
named for the wrong operand | named for the right one |
AssemblyVersion is pinned at 2.0.0.0 for the whole of 2.x, so later 2.x releases are drop-in replacements for this one.
The silent ones — these are what to test against
A sample; the full list with worked examples is in BREAKING-CHANGES.md.
sqrt(x^2)andsqrt(-x)are left as written instead of being simplified toxandi*sqrt(x), which were wrong for negativex.Real%follows the sign of the divisor:-7 % 3is2, was-1.- Radicals are reduced everywhere:
sqrt(12)is now2 * sqrt(3). - Numbers below
1e-16are kept rather than rounded to0. - An identity equation solves to all of
CC, not{ }or{ 0 }. - Many limits that returned
NaNor stayed unevaluated now return a value. Stringizeoutput parses back for powers, lambdas, applications, piecewises and complex numbers with a fractional imaginary part. If you parse printed output, read that section.- Boolean expressions are minimised where that is shorter, rather than factored.
- Some integrals return closed forms that were not antiderivatives before — and two that were answered correctly are now unevaluated, a deliberate loss.
Reporting
If something you relied on changed and it is not in BREAKING-CHANGES.md, that is a bug in the notes as much as in the code — please open an issue either way. A silent change found now is one that does not arrive against 2.0.0 final.
Packages: AngouriMath, AngouriMath.FSharp, AngouriMath.Interactive, AngouriMath.Terminal.
v1.4.0
What's Changed
- Terminal releases by @WhiteBlackGoose in #488
- Update TerminalNightly.yml by @WhiteBlackGoose in #489
- Assembly loader on computation expressions by @WhiteBlackGoose in #493
- New discord badge by @WhiteBlackGoose in #492
- Lambdas and functions by @WhiteBlackGoose in #496
- Function syntax for lambdas by @WhiteBlackGoose in #499
- Memory diagnoser added and perf report update by @WhiteBlackGoose in #501
- Issue 491 by @WhiteBlackGoose in #503
- Issue 502 by @WhiteBlackGoose in #504
- Generic math impl by @WhiteBlackGoose in #509
- Licenses fix by @WhiteBlackGoose in #513
- Separating experimental from the safe one by @WhiteBlackGoose in #517
- Update README.md by @WhiteBlackGoose in #518
- Versioning by @WhiteBlackGoose in #519
- Terminal as global tool by @WhiteBlackGoose in #521
- Terminal fixes by @WhiteBlackGoose in #522
- Removed *.user files. Issue 514 by @willTyler1 in #520
- Minor fixes by @WhiteBlackGoose in #523
- Memory usage benchmark by @WhiteBlackGoose in #527
- Imprecise equality by @WhiteBlackGoose in #533
- Links changed by @WhiteBlackGoose in #535
- Implement piecewise compilation by @Illuminati-CRAZ in #532
- Added more default defined symbols by @dogayalcin in #538
- Fixes of the terminal and compilation protocol by @WhiteBlackGoose in #543
- Versioning by @WhiteBlackGoose in #546
- Interactive Plot.polar draft implementation (#544) by @cyberillithid in #547
- Minor work by @WhiteBlackGoose in #551
- Updated versions for formatting by @WhiteBlackGoose in #553
- Bash Automation to Update Copyright information from 2021 to 2022 by @bimal-parajuli in #555
- Fix tests by @WhiteBlackGoose in #556
- Fix by @WhiteBlackGoose in #560
- Eta reduction by @WhiteBlackGoose in #564
- Update CODE_OF_CONDUCT.md by @WhiteBlackGoose in #566
- Tan bug fixed by @WhiteBlackGoose in #570
- Citation info by @WhiteBlackGoose in #574
- Use the highest version for prereleases instead of the lowest by @WhiteBlackGoose in #577
- Implemented xor simplification and xor sort by @DavidBeh in #576
- Fixing CI... by @WhiteBlackGoose in #578
- dib for C# by @WhiteBlackGoose in #581
- Matrix concatenation by @WhiteBlackGoose in #582
- More docs by @WhiteBlackGoose in #583
- Working on more docs by @WhiteBlackGoose in #586
- Fixed link for changelog (#528) by @djvoelker in #589
- Deb simple by @WhiteBlackGoose in #593
- New archs by @WhiteBlackGoose in #594
- minor fixes by @WhiteBlackGoose in #595
- Update pack-deb-linux.sh by @WhiteBlackGoose in #598
- Merging AngouriMath.Experimental by @WhiteBlackGoose in #612
- Infinite recursion in integral fix by @WhiteBlackGoose in #613
- Improvements to operations with collections and indexables by @Lehonti in #614
- Replaced Jupyter badge with .NET Interactive badge #545 by @mgnslndh in #616
- Issue 619 Bug: Solving a system of equations... by @adk7507 in #622
- Fix LaTeX for 2 * {3}^{4} by @Happypig375 in #638
- LaTeX overhaul by @Happypig375 in #639
- Fix CI by @Happypig375 in #640
- Upgrade ANTLR to 4.13.1 by @vignesh-jeevanandam in #633
- Update Benchmark.yml by @WhiteBlackGoose in #588
- fix: issue620 Updated referenced versions by @ArchiBC in #621
- Move AngouriMath up a folder by @Happypig375 in #643
- Move AngouriMath up a folder and fix paths by @Happypig375 in #644
- Fix by @Happypig375 in #645
- Extend NuGet workflow to support both MyGet and NuGet.org publishing by @Copilot in #646
- Add AngouriMath.Terminal to NuGet publishing workflow and use ProjectReference for internal dependencies by @Copilot in #647
- Deprecated -> No longer actively maintained by @Happypig375 in #649
- LaTeX chained comparison fix by @Happypig375 in #648
- Keep domains on simplify ("x/x" becomes "1 provided not x = 0"), fix 0/0 = 0 (now becomes undefined), fixed arcotanh and gamma definitions by @Happypig375 in #650
- Parenthesize LaTeX limit target for one-sided limits, parenthesize Provided by Priority by @Happypig375 in #651
- Do not simplify x in {1} to false, InnerEval merge with InnerSimplify, simplify 0/0 to NaN in InnerSimplify by @Happypig375 in #652
- Display not equals in Latexise, simplify Notf(Andf) and Notf(Orf) by @Happypig375 in #653
- Fix stack overflow for nonexistent two-sided limits by @Happypig375 in #654
- Change AngouriMath.Experimental to AngouriMath.Terminal MyGet on README by @Happypig375 in #655
- Place calculus operator priority between addition/subtraction and mutiplication/division in Latexise by @Happypig375 in #656
- Add C to integration result, change integral node to support range instead of iterations, implement u-substitution and quadratic denominator integral, integration of abs(x), sgn(x) and ln(abs(x))^2 by @Happypig375 in #657
- Place set union and minus at same precedence, place xor above or in precedence, fix chained comparison parsing by @Happypig375 in #658
- Additional definite integral testing by @Happypig375 in #659
- Stringize provided as associative by @Happypig375 in #660
New Contributors
- @willTyler1 made their first contribution in #520
- @Illuminati-CRAZ made their first contribution in #532
- @dogayalcin made their first contribution in #538
- @cyberillithid made their first contribution in #547
- @bimal-parajuli made their first contribution in #555
- @DavidBeh made their first contribution in #576
- @djvoelker made their first contribution in #589
- @Lehonti made their first contribution in #614
- @mgnslndh made their first contribution in #616
- @adk7507 made their first contribution in #622
- @vignesh-jeevanandam made their first contribution in #633
- @ArchiBC made their first contribution in https://github.com/asc-community/AngouriMath/pu...
v1.4.0-preview.7
What's Changed
- Parenthesize LaTeX limit target for one-sided limits, parenthesize Provided by Priority by @Happypig375 in #651
- Do not simplify x in {1} to false, InnerEval merge with InnerSimplify, simplify 0/0 to NaN in InnerSimplify by @Happypig375 in #652
- Display not equals in Latexise, simplify Notf(Andf) and Notf(Orf) by @Happypig375 in #653
- Fix stack overflow for nonexistent two-sided limits by @Happypig375 in #654
- Change AngouriMath.Experimental to AngouriMath.Terminal MyGet on README by @Happypig375 in #655
- Place calculus operator priority between addition/subtraction and mutiplication/division in Latexise by @Happypig375 in #656
Full Changelog: v1.4.0-preview.6...v1.4.0-preview.7
v1.4.0-preview.6
What's Changed
- Keep domains on simplify ("x/x" becomes "1 provided not x = 0"), fix 0/0 = 0 (now becomes undefined), fixed arcotanh and gamma definitions by @Happypig375 in #650
Full Changelog: v1.4.0-preview.5...v1.4.0-preview.6