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
20 changes: 20 additions & 0 deletions BREAKING-CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,26 @@ the right shape, written out or once its operations are carried out, throws `Inv
| `"dot([1, 2], [3, 4])".ToEntity()` | throws `UnhandledParseException` | `1 * 3 + 2 * 4` |
| `"resultant(x^2 - 1, x - a, x)".ToEntity()` | throws `UnhandledParseException` | `a ^ 2 - 1` |

### The names of functions to come are refused by name

**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`,
`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`.
Each name without a bracket is still a variable, and short names such as `beta` and `norm` are still read as products
([#2182](https://github.com/asc-community/AngouriMath/issues/2182)).

| Input | Was (2.6.0) | Now |
|---|---|---|
| `"zeta(s)".ToEntity()` | `zeta * s` | throws `UnrecognizedFunctionParseException` |
| `"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` |
### 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
44 changes: 44 additions & 0 deletions Sources/AngouriMath/Core/Antlr/AngouriMath.g
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ options
$"there is no function {name}: AngouriMath has no {what}. It is refused by name " +
$"rather than read as the product of a variable named {name} with its argument, " +
$"which is what an unknown name followed by a bracket would otherwise mean");

// A name that will not be a function, because what it means is ambiguous or is already
// written exactly another way, refused with the spelling to use, as NN is refused with ZZ+
// and ZZ*. https://github.com/asc-community/AngouriMath/issues/2182
static Entity NotAFunctionHere(string name, string instead)
=> throw new UnrecognizedFunctionParseException(
$"{name} is not a function in AngouriMath: {instead}. It is refused by name rather " +
$"than read as the product of a variable named {name} with its argument");
}

@namespace { Antlr }
Expand Down Expand Up @@ -658,6 +666,42 @@ atom returns[Entity value]
between a missing function and a wrong answer. */

| 'trunc(' args = function_arguments ')' { $value = NotImplementedFunction("trunc", "rounding functions"); }
/* Names of functions to come, reserved so that each is refused rather than read as a
product until it is implemented: zeta(s) was zeta * s. Only names no one writes as a
variable before a bracket; beta, norm, grad, div, curl and the other short ones are left
as products until each lands. The names and their conventions are in
https://github.com/asc-community/AngouriMath/issues/2182 */
| 'zeta(' args = function_arguments ')' { $value = NotImplementedFunction("zeta", "Riemann or Hurwitz zeta function yet"); }
| 'riemannzeta(' args = function_arguments ')' { $value = NotImplementedFunction("riemannzeta", "Riemann zeta function yet"); }
| '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"); }
| 'fallingfactorial(' args = function_arguments ')' { $value = NotImplementedFunction("fallingfactorial", "falling factorial yet"); }
| 'factorialpower(' args = function_arguments ')' { $value = NotImplementedFunction("factorialpower", "falling factorial yet"); }
| 'risingfactorial(' args = function_arguments ')' { $value = NotImplementedFunction("risingfactorial", "rising factorial yet"); }
| 'forwarddifference(' args = function_arguments ')' { $value = NotImplementedFunction("forwarddifference", "forward difference yet"); }
| 'laplacian(' args = function_arguments ')' { $value = NotImplementedFunction("laplacian", "Laplacian yet"); }
| 'jacobian(' args = function_arguments ')' { $value = NotImplementedFunction("jacobian", "Jacobian yet"); }
| 'hessian(' args = function_arguments ')' { $value = NotImplementedFunction("hessian", "Hessian yet"); }
/* Names that will not be functions, refused with the spelling to use: what they mean is
ambiguous between sources, or is already written exactly another way. */
| 'heaviside(' args = function_arguments ')' { $value = NotAFunctionHere("heaviside", "its value at 0 is 0, 1/2 or 1 by source; write iverson(x > 0), iverson(x >= 0) or (1 + sgn(x))/2"); }
| 'unitstep(' args = function_arguments ')' { $value = NotAFunctionHere("unitstep", "write iverson(x >= 0), which is 1 at 0"); }
| 'isprime(' args = function_arguments ')' { $value = NotAFunctionHere("isprime", "write n in PP"); }
| 'pochhammer(' args = function_arguments ')' { $value = NotAFunctionHere("pochhammer", "(x)_n is the rising factorial to some and the falling one to others; write risingfactorial or fallingfactorial"); }
| 'doublefactorial(' args = function_arguments ')' { $value = NotAFunctionHere("doublefactorial", "the double factorial is to be the postfix n!!, which is not implemented yet"); }
| 'factorial2(' args = function_arguments ')' { $value = NotAFunctionHere("factorial2", "the double factorial is to be the postfix n!!, which is not implemented yet"); }
| 'fractionalpart(' args = function_arguments ')' { $value = NotAFunctionHere("fractionalpart", "write x mod 1, which is in [0, 1)"); }
| 'quotient(' args = function_arguments ')' { $value = NotAFunctionHere("quotient", "write floor(a / b)"); }
| 'domain(' args = function_arguments ')'
{
Assert("domain", 2, $args.list.Count);
Expand Down
60 changes: 59 additions & 1 deletion Sources/AngouriMath/Core/Antlr/AngouriMath.interp

Large diffs are not rendered by default.

84 changes: 71 additions & 13 deletions Sources/AngouriMath/Core/Antlr/AngouriMath.tokens
Original file line number Diff line number Diff line change
Expand Up @@ -196,14 +196,43 @@ T__194=195
T__195=196
T__196=197
T__197=198
NEWLINE=199
NUMBER=200
SPECIALSET=201
BOOLEAN=202
NAN=203
VARIABLE=204
COMMENT=205
WS=206
T__198=199
T__199=200
T__200=201
T__201=202
T__202=203
T__203=204
T__204=205
T__205=206
T__206=207
T__207=208
T__208=209
T__209=210
T__210=211
T__211=212
T__212=213
T__213=214
T__214=215
T__215=216
T__216=217
T__217=218
T__218=219
T__219=220
T__220=221
T__221=222
T__222=223
T__223=224
T__224=225
T__225=226
T__226=227
NEWLINE=228
NUMBER=229
SPECIALSET=230
BOOLEAN=231
NAN=232
VARIABLE=233
COMMENT=234
WS=235
'!'=1
'^'=2
'-'=3
Expand Down Expand Up @@ -398,8 +427,37 @@ WS=206
'im('=192
'imag('=193
'trunc('=194
'domain('=195
'piecewise('=196
'apply('=197
'lambda('=198
'NaN'=203
'zeta('=195
'riemannzeta('=196
'hurwitzzeta('=197
'lambertw('=198
'productlog('=199
'mobius('=200
'moebiusmu('=201
'divisorsigma('=202
'primenu('=203
'primeomega('=204
'primepi('=205
'harmonicnumber('=206
'catalannumber('=207
'multinomial('=208
'fallingfactorial('=209
'factorialpower('=210
'risingfactorial('=211
'forwarddifference('=212
'laplacian('=213
'jacobian('=214
'hessian('=215
'heaviside('=216
'unitstep('=217
'isprime('=218
'pochhammer('=219
'doublefactorial('=220
'factorial2('=221
'fractionalpart('=222
'quotient('=223
'domain('=224
'piecewise('=225
'apply('=226
'lambda('=227
'NaN'=232
Loading
Loading