Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions BREAKING-CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -440,8 +440,7 @@ the right shape, written out or once its operations are carried out, throws `Inv
**Not silent: these names followed by a bracket now throw `UnrecognizedFunctionParseException` where they were read as
products.** An unknown name followed by a bracket is a product, so `zeta(2)` was `zeta * 2` and simplified to
`2 * zeta`. The long names of the functions the library is to have are refused until each is implemented, as `trunc`
is: `zeta`, `riemannzeta`, `hurwitzzeta`, `lambertw`, `productlog`, `mobius`, `moebiusmu`, `divisorsigma`, `primenu`,
`primeomega`, `primepi`, `harmonicnumber`, `catalannumber`, `multinomial`, `fallingfactorial`, `factorialpower`,
is: `zeta`, `riemannzeta`, `hurwitzzeta`, `lambertw`, `productlog`, `harmonicnumber`, `catalannumber`, `multinomial`, `fallingfactorial`, `factorialpower`,
`risingfactorial`, `forwarddifference`, `laplacian`, `jacobian` and `hessian`. Names that will not be functions,
because what they mean differs between sources or is already written exactly, are refused with the spelling to use:
`heaviside`, `unitstep`, `isprime`, `pochhammer`, `doublefactorial`, `factorial2`, `fractionalpart` and `quotient`.
Expand All @@ -454,7 +453,24 @@ Each name without a bracket is still a variable, and short names such as `beta`
| `"zeta(2)".ToEntity().Simplify()` | `2 * zeta` | throws `UnrecognizedFunctionParseException` |
| `"isprime(7)".ToEntity()` | `isprime * 7` | throws `UnrecognizedFunctionParseException`: write `n in PP` |
| `"heaviside(x)".ToEntity()` | `heaviside * x` | throws `UnrecognizedFunctionParseException`: write `iverson(x > 0)`, `iverson(x >= 0)` or `(1 + sgn(x))/2` |
| `"divisorsigma(k, n)".ToEntity()` | throws `UnhandledParseException` | throws `UnrecognizedFunctionParseException` |
| `"multinomial(a, b, c)".ToEntity()` | throws `UnhandledParseException` | throws `UnrecognizedFunctionParseException` |

### The Möbius, divisor and prime-counting functions

**Not silent: `mobius(n)`, `divisorsigma(k, n)`, `primenu(n)`, `primeomega(n)` and `primepi(x)` are now functions, where
they were read as products or, with two arguments, were a parse error.** `mobius` (also `moebiusmu`) is the Möbius
function μ, `divisorsigma(k, n)` the sum of the `k`-th powers of the divisors of `n`, and `primenu` and `primeomega` the
number of prime factors without and with multiplicity, ω and Ω. Each is defined on the positive integers and is `NaN`
elsewhere. `primepi(x)` counts the primes at most the real number `x`
([#2182](https://github.com/asc-community/AngouriMath/issues/2182)).

| Input | Was (2.6.0) | Now |
|---|---|---|
| `"mobius(6)".ToEntity().Simplify()` | `6 * mobius` | `1` |
| `"divisorsigma(1, 6)".ToEntity().Simplify()` | throws `UnhandledParseException` | `12` |
| `"primeomega(12)".ToEntity().Simplify()` | `12 * primeomega` | `3` |
| `"primepi(10)".ToEntity().Evaled` | `primepi * 10` | `4` |
| `"mobius(0)".ToEntity().Simplify()` | `0` | `NaN` |
### A subscript may have a subscript

**Not silent: what was a parse error is a name.** A name took at most one `_`, so `x_1_2` and `X_a_beta` were lexer
Expand Down
3 changes: 3 additions & 0 deletions Sources/.editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -805,3 +805,6 @@ file_header_template=\nCopyright (c) 2019-2026 Angouri.\nAngouriMath is licensed

[Tests/UnitTests/Common/SimplifyOverASymbolicCommonDenominatorTest.cs]
file_header_template=\nCopyright (c) 2019-2026 Angouri.\nAngouriMath is licensed under MIT.\nDetails: https://github.com/asc-community/AngouriMath/blob/master/LICENSE.md.\nWebsite: https://am.angouri.org.\n

[Tests/UnitTests/Convenience/NumberTheoryFunctionsTest.cs]
file_header_template=\nCopyright (c) 2019-2026 Angouri.\nAngouriMath is licensed under MIT.\nDetails: https://github.com/asc-community/AngouriMath/blob/master/LICENSE.md.\nWebsite: https://am.angouri.org.\n
20 changes: 20 additions & 0 deletions Sources/AngouriMath/Convenience/MathS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,26 @@ public static class NumberTheory
/// </example>
public static Entity Phi(Entity integer) => new Phif(integer);

/// <summary>The Möbius function <c>μ(n)</c> of a positive integer</summary>
/// <remarks>https://github.com/asc-community/AngouriMath/issues/2182</remarks>
public static Entity Mobius(Entity n) => new Mobiusf(n);

/// <summary>The divisor function <c>σ_k(n)</c>: the sum of the <c>k</c>-th powers of the divisors of <c>n</c></summary>
/// <remarks>https://github.com/asc-community/AngouriMath/issues/2182</remarks>
public static Entity DivisorSigma(Entity order, Entity n) => new DivisorSigmaf(order, n);

/// <summary>The number of distinct prime factors <c>ω(n)</c> of a positive integer</summary>
/// <remarks>https://github.com/asc-community/AngouriMath/issues/2182</remarks>
public static Entity PrimeNu(Entity n) => new PrimeNuf(n);

/// <summary>The number of prime factors <c>Ω(n)</c> of a positive integer, with multiplicity</summary>
/// <remarks>https://github.com/asc-community/AngouriMath/issues/2182</remarks>
public static Entity PrimeOmega(Entity n) => new PrimeOmegaf(n);

/// <summary>The prime-counting function <c>π(x)</c>: how many primes are at most <c>x</c></summary>
/// <remarks>https://github.com/asc-community/AngouriMath/issues/2182</remarks>
public static Entity PrimePi(Entity x) => new PrimePif(x);

/// <summary>
/// The <c>n</c>-th prime, <c>prime(n)</c>: <c>prime(1)</c> is <c>2</c> and
/// <c>prime(25)</c> is <c>97</c>. Defined on the positive whole numbers, and a
Expand Down
12 changes: 6 additions & 6 deletions Sources/AngouriMath/Core/Antlr/AngouriMath.g
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,12 @@ atom returns[Entity value]
| 'phi(' args = function_arguments ')' { Assert("phi", 1, $args.list.Count); $value = MathS.NumberTheory.Phi($args.list[0]); }
| 'prime(' args = function_arguments ')' { Assert("prime", 1, $args.list.Count); $value = MathS.NumberTheory.Prime($args.list[0]); }
| 'valuation(' args = function_arguments ')' { Assert("valuation", 2, $args.list.Count); $value = MathS.NumberTheory.Valuation($args.list[0], $args.list[1]); }
| 'mobius(' args = function_arguments ')' { Assert("mobius", 1, $args.list.Count); $value = MathS.NumberTheory.Mobius($args.list[0]); }
| 'moebiusmu(' args = function_arguments ')' { Assert("moebiusmu", 1, $args.list.Count); $value = MathS.NumberTheory.Mobius($args.list[0]); }
| 'divisorsigma(' args = function_arguments ')' { Assert("divisorsigma", 2, $args.list.Count); $value = MathS.NumberTheory.DivisorSigma($args.list[0], $args.list[1]); }
| 'primenu(' args = function_arguments ')' { Assert("primenu", 1, $args.list.Count); $value = MathS.NumberTheory.PrimeNu($args.list[0]); }
| 'primeomega(' args = function_arguments ')' { Assert("primeomega", 1, $args.list.Count); $value = MathS.NumberTheory.PrimeOmega($args.list[0]); }
| 'primepi(' args = function_arguments ')' { Assert("primepi", 1, $args.list.Count); $value = MathS.NumberTheory.PrimePi($args.list[0]); }
| 'card(' args = function_arguments ')' { Assert("card", 1, $args.list.Count); $value = MathS.Sets.Card($args.list[0]); }
| 'powerset(' args = function_arguments ')' { Assert("powerset", 1, $args.list.Count); $value = MathS.Sets.PowerSet($args.list[0]); }
| 'union(' args = function_arguments ')' { Assert("union", 2, $args.list.Count); $value = $args.list[1] is Entity.Set.Inf { Element: Variable } unionRange ? MathS.Sets.IndexedUnion($args.list[0], unionRange.Element, unionRange.SupSet) : throw new InvalidArgumentParseException("union expects its second argument to say which name ranges over which set, as in union(A_i, i in I)"); }
Expand Down Expand Up @@ -681,12 +687,6 @@ atom returns[Entity value]
| 'hurwitzzeta(' args = function_arguments ')' { $value = NotImplementedFunction("hurwitzzeta", "Hurwitz zeta function yet"); }
| 'lambertw(' args = function_arguments ')' { $value = NotImplementedFunction("lambertw", "Lambert W function yet"); }
| 'productlog(' args = function_arguments ')' { $value = NotImplementedFunction("productlog", "Lambert W function yet"); }
| 'mobius(' args = function_arguments ')' { $value = NotImplementedFunction("mobius", "Mobius function yet"); }
| 'moebiusmu(' args = function_arguments ')' { $value = NotImplementedFunction("moebiusmu", "Mobius function yet"); }
| 'divisorsigma(' args = function_arguments ')' { $value = NotImplementedFunction("divisorsigma", "divisor function yet"); }
| 'primenu(' args = function_arguments ')' { $value = NotImplementedFunction("primenu", "count of distinct prime factors yet"); }
| 'primeomega(' args = function_arguments ')' { $value = NotImplementedFunction("primeomega", "count of prime factors with multiplicity yet"); }
| 'primepi(' args = function_arguments ')' { $value = NotImplementedFunction("primepi", "prime-counting function yet"); }
| 'harmonicnumber(' args = function_arguments ')' { $value = NotImplementedFunction("harmonicnumber", "harmonic numbers yet"); }
| 'catalannumber(' args = function_arguments ')' { $value = NotImplementedFunction("catalannumber", "Catalan numbers yet"); }
| 'multinomial(' args = function_arguments ')' { $value = NotImplementedFunction("multinomial", "multinomial coefficients yet"); }
Expand Down
12 changes: 6 additions & 6 deletions Sources/AngouriMath/Core/Antlr/AngouriMath.interp
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,12 @@ null
'phi('
'prime('
'valuation('
'mobius('
'moebiusmu('
'divisorsigma('
'primenu('
'primeomega('
'primepi('
'card('
'powerset('
'union('
Expand Down Expand Up @@ -201,12 +207,6 @@ null
'hurwitzzeta('
'lambertw('
'productlog('
'mobius('
'moebiusmu('
'divisorsigma('
'primenu('
'primeomega('
'primepi('
'harmonicnumber('
'catalannumber('
'multinomial('
Expand Down
114 changes: 57 additions & 57 deletions Sources/AngouriMath/Core/Antlr/AngouriMath.tokens
Original file line number Diff line number Diff line change
Expand Up @@ -385,63 +385,63 @@ WS=237
'phi('=148
'prime('=149
'valuation('=150
'card('=151
'powerset('=152
'union('=153
'intersection('=154
'complement('=155
'image('=156
'preimage('=157
'floor('=158
'ceil('=159
'ceiling('=160
'round('=161
'min('=162
'max('=163
'argmax('=164
'argmin('=165
'gcd('=166
'lcm('=167
'binomial('=168
'iverson('=169
'aleph('=170
'erf('=171
'erfc('=172
'erfi('=173
'Ei('=174
'li('=175
'polygamma('=176
'digamma('=177
'Si('=178
'Ci('=179
'Shi('=180
'Chi('=181
'det('=182
'transpose('=183
'dot('=184
'cross('=185
'resultant('=186
'conjugate('=187
'conj('=188
'arg('=189
'Re('=190
'Im('=191
're('=192
'real('=193
'im('=194
'imag('=195
'trunc('=196
'zeta('=197
'riemannzeta('=198
'hurwitzzeta('=199
'lambertw('=200
'productlog('=201
'mobius('=202
'moebiusmu('=203
'divisorsigma('=204
'primenu('=205
'primeomega('=206
'primepi('=207
'mobius('=151
'moebiusmu('=152
'divisorsigma('=153
'primenu('=154
'primeomega('=155
'primepi('=156
'card('=157
'powerset('=158
'union('=159
'intersection('=160
'complement('=161
'image('=162
'preimage('=163
'floor('=164
'ceil('=165
'ceiling('=166
'round('=167
'min('=168
'max('=169
'argmax('=170
'argmin('=171
'gcd('=172
'lcm('=173
'binomial('=174
'iverson('=175
'aleph('=176
'erf('=177
'erfc('=178
'erfi('=179
'Ei('=180
'li('=181
'polygamma('=182
'digamma('=183
'Si('=184
'Ci('=185
'Shi('=186
'Chi('=187
'det('=188
'transpose('=189
'dot('=190
'cross('=191
'resultant('=192
'conjugate('=193
'conj('=194
'arg('=195
'Re('=196
'Im('=197
're('=198
'real('=199
'im('=200
'imag('=201
'trunc('=202
'zeta('=203
'riemannzeta('=204
'hurwitzzeta('=205
'lambertw('=206
'productlog('=207
'harmonicnumber('=208
'catalannumber('=209
'multinomial('=210
Expand Down
Loading
Loading