Compute Engine

Functions

The function attempts to match a pattern with a subject expression.

If the match is successful, it returns a Substitution indicating how to transform the pattern to become the subject.

If the pattern is not a match, it returns null.

This function attempts the match purely structurally, without any knowledge about commutative and associative properties of functions.

In most cases, you’ll want to account for these properties. To do so, use the ce.match() function instead.

match(subject: Expression<T>, pattern: Expression<T>, options?: {numericTolerance: number}): Substitution<T> | "null"
subject: Expression<T>
pattern: Expression<T>
options:
numericTolerance: number;
Substitution<T> | "null"

substitute(expr: Expression<T>, substitution: Substitution<T>): Expression<T>
expr: Expression<T>
substitution: Substitution<T>
Expression<T>

version: ""

Implements ComputeEngineInterface

Create a CustomEngine instance to customize its behavior and the syntax and operation dictionaries it uses.

The constructor of ComputeEngine will compile and optimize the dictionary upfront.

Construct a new ComputeEngine environment.

If no options.dictionaries is provided a default set of dictionaries is used. The ComputeEngine.getDictionaries() method can be called to access some subset of dictionaries, e.g. for arithmetic, calculus, etc… The order of the dictionaries matter: the definitions from the later ones override the definitions from earlier ones. The first dictionary should be the 'core' dictionary which include some basic definitions such as domains (Boolean, Number, etc…) that are used by later dictionaries.

options:
ComputeEngine<T>

The current executin context, a runtime scope.

A scope is a dictionary that contains the definition of local symbols.

Scopes form a stack, and definitions in more recent scopes can obscure definitions from older scopes.

cost: (expr: Expression<number>): number

numericFormat: NumericFormat

Internal format to represent numbers:

• auto: the best format is determined based on the calculations to perform and the requested precision.
• number: use the machine format (64-bit float, 52-bit, about 15 digits of precision).
• decimal: arbitrary precision floating-point numbers, as provided by the “decimal.js” library
• complex: complex numbers: two 64-bit float, as provided by the “complex.js” library

precision: number

The default precision of the compute engine: the number of significant digits when performing numeric evaluations, such as when calling ce.N().

To make calculations using machine floating point representation, set precision to "machine" (15 by default).

To make calculations using more digits, at the cost of expended memory usage and slower computations, set the precision higher.

Trigonometric operations are accurate for precision up to 1,000.

Some functions, such as ce.N() have an option to specify the precision. If no precision is specified in these functions, the precision of the compute engine is used.

tolerance: number

Values smaller than the tolerance are considered to be zero for the purpose of comparison, i.e. if |b - a| <= tolerance, b is considered equal to a.

Return a numerical approximation of an expression.

N(expr: Expression<number>, options?: {precision: number}): Expression<number>
expr: Expression<number>
options:
precision: number;
Expression<number>

Return a list of all the assumptions that match a pattern.

ce.assume(x, 'PositiveInteger');
//  -> [{'val': 0}]
pattern: Expression<number>
Substitution<number>[]

Return contradiction if the new assumption is incompatible with previous ones.

Return tautology if the new assumption is redundant with previous ones.

Return ok if the assumption was successfully added to the assumption set.

Note that the assumption is put into normal form before being added.

assume(symbol: Expression<number>, domain: Domain): AssumeResult
symbol: Expression<number>
domain: Domain
AssumeResult

assume(predicate: Expression<number>): AssumeResult
predicate: Expression<number>
AssumeResult

cache(key: string, fn: (): T): T
key: string
fn: (): T
T

Format the expression to the canonical form.

In the canonical form, some operations are simplified (subtractions becomes additions of negative, division become multiplications of inverse, etc…) and terms are ordered using a deglex order. This can make subsequent operations easier.

canonical(expr: Expression<number>): Expression<number>
expr: Expression<number>
Expression<number>

checkContinueExecution(): void

chop(n: any): any
n: any
any

Return the domain of the expression

domain(expr: Expression<number>): Expression<number>
expr: Expression<number>
Expression<number>

Apply the definitions in the supplied dictionary to an expression and return the result.

Evaluating some expressions can take a very long time. Some can invole making network queries. To avoid blocking the main event loop, this function is asynchronous and returns a Promise

Use result = await engine.evaluate(expr) to get the result without blocking.

evaluate(expr: Expression<number>, options?: {iterationLimit: number; timeLimit: number}): Promise<Expression<number>>
expr: Expression<number>
options:
iterationLimit: number;
timeLimit: number;
Promise<Expression<number>>

forget(symbol?: string | string[]): void
symbol:
• | string
• | string[]

Transform an expression by applying one or more rewriting rules to it, recursively.

There are many ways to symbolically manipulate an expression, but transformations with form have the following characteristics:

• they don’t require calculations or assumptions about the domain of free variables or the value of constants
• the output expression is expressed with more primitive functions, for example subtraction is replaced with addition
format(expr: Expression<number>, forms?: Form | Form[]): Expression<number>
expr: Expression<number>
forms:
• | Form
• | Form[]
Expression<number>

getDefinition(name: string): Definition<any>
name: string
Definition<any>

getFunctionDefinition(name: string): FunctionDefinition<number>
name: string
FunctionDefinition<number>

Return the variables in the expression

getVars(expr: Expression<number>): Set<string>
expr: Expression<number>
Set<string>

Determines if the predicate is satisfied based on the known assumptions.

Return undefined if the value of the predicate cannot be determined.

ce.is(["Equal", "x", 0]);
ce.is(["Equal", 3, 4]);
is(symbol: Expression<number>, domain: Domain): boolean
symbol: Expression<number>
domain: Domain
boolean

is(predicate: Expression<number>): boolean
predicate: Expression<number>
boolean

isAlgebraic(x: Expression<T>): boolean
x: Expression<T>
boolean

isComplex(x: Expression<T>): boolean
x: Expression<T>
boolean

isElement(x: Expression<T>, set: Expression<T>): boolean
x: Expression<T>
set: Expression<T>
boolean

isEqual(lhs: Expression<number>, rhs: Expression<number>): boolean
lhs: Expression<number>
rhs: Expression<number>
boolean

isExtendedReal(x: Expression<T>): boolean
x: Expression<T>
boolean

Not ± Infinity, not NaN

isFinite(x: Expression<T>): boolean
x: Expression<T>
boolean

isGreater(lhs: Expression<number>, rhs: Expression<number>): boolean
lhs: Expression<number>
rhs: Expression<number>
boolean

isGreaterEqual(lhs: Expression<number>, rhs: Expression<number>): boolean
lhs: Expression<number>
rhs: Expression<number>
boolean

isInfinity(x: Expression<T>): boolean
x: Expression<T>
boolean

isInteger(x: Expression<T>): boolean
x: Expression<T>
boolean

isLess(lhs: Expression<number>, rhs: Expression<number>): boolean
lhs: Expression<number>
rhs: Expression<number>
boolean

isLessEqual(lhs: Expression<number>, rhs: Expression<number>): boolean
lhs: Expression<number>
rhs: Expression<number>
boolean

x < 0

isNegative(x: Expression<T>): boolean
x: Expression<T>
boolean

isNegativeOne(x: Expression<T>): boolean
x: Expression<T>
boolean

x >= 0

isNonNegative(x: Expression<T>): boolean
x: Expression<T>
boolean

x <= 0

isNonPositive(x: Expression<T>): boolean
x: Expression<T>
boolean

isNotZero(x: Expression<T>): boolean
x: Expression<T>
boolean

isNumeric(x: Expression<T>): boolean
x: Expression<T>
boolean

isOne(x: Expression<T>): boolean
x: Expression<T>
boolean

x > 0

isPositive(x: Expression<T>): boolean
x: Expression<T>
boolean

isRational(x: Expression<T>): boolean
x: Expression<T>
boolean

isReal(x: Expression<T>): boolean
x: Expression<T>
boolean

isSubsetOf(lhs: any, rhs: any): boolean
lhs: any
rhs: any
boolean

isZero(x: Expression<T>): boolean
x: Expression<T>
boolean

match(expr: Expression<T>, pattern: Expression<T>, options?: {exact: boolean; numericTolerance: number}): Substitution<number>
expr: Expression<T>
pattern: Expression<T>
options:
exact: boolean;
numericTolerance: number;
Substitution<number>

parse(s: string): Expression<number>
s: string
Expression<number>

Remove the topmost scope from the scope stack.

popScope(): void

Create a new scope and add it to the top of the scope stack

pushScope(options?: {assumptions: Expression<number>[]; dictionary: Readonly<Dictionary<any>>; scope: Partial<Scope>}): void
options:
assumptions: Expression<number>[];
scope: Partial<Scope>;

Apply repeatedly a set of rules to an expression.

replace(expr: Expression<T>, rules: RuleSet<T>): Expression<T>
expr: Expression<T>
rules: RuleSet<T>
Expression<T>

serialize(x: Expression<number>): string
x: Expression<number>
string

Return false if the execution should stop.

This can occur if:

• an error has been signaled
• the time limit or memory limit has been exceeded
shouldContinueExecution(): boolean
boolean

Call this function if an unexpected condition occurs during execution of a function in the engine.

An ErrorSignal is a problem that cannot be recovered from.

A WarningSignal indicates a minor problem that does not prevent the execution to continue.

signal(sig: WarningSignal | ErrorSignal): void
sig:

Attempt to simplify an expression, that is rewrite it in a simpler form, making use of the available assumptions.

The simplification steps will proceed multiple times until either: 1/ the expression stop changing 2/ the number of iteration exceeds iterationLimit 3/ the time to compute exceeds timeLimit, expressed in seconds

If no timeLimit or iterationLimit are provided, the values from the current ComputeEngine context are used. By default those values are an infinite amount of iterations and a 2s time limit.

simplify(expr: Expression<number>, options?: {iterationLimit: number; simplifications: Simplification[]; timeLimit: number}): Expression<number>
expr: Expression<number>
options:
iterationLimit: number;
simplifications: Simplification[];
timeLimit: number;
Expression<number>

solve(expr: Expression<T>, vars: string[]): Expression<T>[]
expr: Expression<T>
vars: string[]
Expression<T>[]

Return dictionaries suitable for the specified categories, or "all" for all categories ("arithmetic", "algebra", etc…).

A symbol dictionary defines how the symbols and function names in a MathJSON expression should be interpreted, i.e. how to evaluate and manipulate them.

categories:
• | "all"
• | DictionaryCategory[]

InternalComputeEngine

Extends Error

new CortexError(errorSignal: Signal): CortexError
errorSignal: Signal
CortexError

toString(): string
string

new LatexSyntax(options?: NumberFormattingOptions & ParseLatexOptions<number> & SerializeLatexOptions & {computeEngine: ComputeEngine<any>; dictionary: readonly LatexDictionaryEntry<T>[]; onError: WarningSignalHandler}): LatexSyntax<T>
options:
LatexSyntax<T>

parse(latex: string): Expression<number>
latex: string
Expression<number>

serialize(expr: Expression<T>): string
expr: Expression<T>
string

getDictionary(domain: DictionaryCategory | "all"): readonly LatexDictionaryEntry<any>[]
domain:
• | DictionaryCategory
• | "all"

ComputeEngine<any>

WarningSignalHandler

Types

comment: string;

A human readable string to annotate an expression, since JSON does not allow comments in its encoding

documentation: string;

error: string;

A human readable string to indicate a syntax error or other problem when parsing or evaluating an expression.

latex: string;

A visual representation in LaTeX of the expression.

This can be useful to preserve non-semantic details, for example parentheses in an expression or styling attributes

openmathCd: string;

A base URL for an OpenMath content dictionary. This key applies to this node and all its children.

The default value is “http://www.openmath.org/cd”.

openmathSymbol: string;

A short string indicating an entry in an OpenMath Content Dictionary.

For example: arith1/#abs.

sourceContent: string;

The source from which this expression was generated.

It could be a LaTeX expression, or some other source language

sourceOffsets: [start: number, end: number];

A character offset in sourceContent or sourceUrl from which this expression was generated

sourceUrl: string;

A url to the source of this expression.

wikibase: string;

A base URL for the wikidata key.

A full URL can be produced by concatenating this key with the wikidata key. This key applies to this node and all its children.

The default value is “https://www.wikidata.org/wiki/”

wikidata: string;

A short string indicating an entry in a wikibase.

For example "Q167" is the wikidata entry for the Pi constant.

• unknown-symbol: a symbol was encountered which does not have a definition.
• unknown-operator: a presumed operator was encountered which does not have a definition.

• unknown-function: a LaTeX command was encountered which does not have a definition.

• unexpected-command: a LaTeX command was encountered when only a string was expected

• unexpected-superscript: a superscript was encountered in an unexpected context, or no powerFunction was defined. By default, superscript can be applied to numbers, symbols or expressions, but not to operators (e.g. 2+^34) or to punctuation.

• unexpected-subscript: a subscript was encountered in an unexpected context or no 'subscriptFunctionwas defined. By default, subscripts are not expected on numbers, operators or symbols. Some commands (e.g.\sum) do expected a subscript.

• unexpected-sequence: some adjacent elements were encountered (for example xy), but no invisibleOperator is defined, therefore the elements can’t be combined. The default invisibleOperator is multiply, but you can also use list.

• expected-argument: a LaTeX command that requires one or more argument was encountered without the required arguments.

• expected-operand: an operator was encountered without its required operands.

• non-associative-operator: an operator which is not associative was encountered in an associative context, for example: a < b < c (assuming < is defined as non-associative)

• postfix-operator-requires-one-operand: a postfix operator which requires a single argument was encountered with no arguments or more than one argument

• prefix-operator-requires-one-operand: a prefix operator which requires a single argument was encountered with no arguments or more than one argument

• base-out-of-range: The base is expected to be between 2 and 36.

• | "expected-argument"
• | "unexpected-argument"
• | "expected-operator"
• | "expected-operand"
• | "invalid-name"
• | "invalid-dictionary-entry"
• | "unknown-symbol"
• | "unknown-operator"
• | "unknown-function"
• | "unknown-command"
• | "unexpected-command"
• | "unbalanced-symbols"
• | "unexpected-superscript"
• | "unexpected-subscript"
• | "unexpected-sequence"
• | "non-associative-operator"
• | "function-has-too-many-arguments"
• | "function-has-too-few-arguments"
• | "operator-requires-one-operand"
• | "infix-operator-requires-two-operands"
• | "prefix-operator-requires-one-operand"
• | "postfix-operator-requires-one-operand"
• | "associative-function-has-too-few-arguments"
• | "commutative-function-has-too-few-arguments"
• | "hold-first-function-has-too-few-arguments"
• | "hold-rest-function-has-too-few-arguments"
• | "base-out-of-range"
• | "syntax-error"

A MathJSON expression is a recursive data structure.

The leaf nodes of an expression are numbers, strings and symbols. The dictionary and function nodes can contain expressions themselves.

The type variable T indicates which numeric type are valid. For a canonical, well-formed, MathJSON expression, this is limited to the number type. However, for the purpose of internal calculations this can be extended to other numeric types. For example, internally the Compute Engine also uses Decimal and Complex classes.

<T extends number> =

<T extends number> = LatexDictionaryEntry<T>[]

Maps a string of LaTeX tokens to a function or symbol and vice-versa.

<T extends number> =
arguments: "group" | "implicit" | "";

If kind is ‘symbol’. Indicate if this symbol can be followed by arguments. The presence of arguments will indicate that the arguments should be applied to the symbol. Otherwise, the invisible operator is applied to the symbol and the arguments.

If arguments is "group":

“f(x)” -> ["f", "x"] “f x” -> ["multiply", "f", "x"]

If arguments is "":

“f(x)” -> ["multiply", "f", ["group", "x"]] “f x” -> ["multiply", "f", "x"]

If arguments is "group/primary" and the symbol is followed either by a group or by a primary (prefix + symbol + subsupfix + postfix). Used for trig functions. i.e. \sin x vs \sin(x):

“f(x)” -> ["f", "x"] “f x” -> ["f", "x"]

associativity: "right" | "left" | "non" | "both";

If kind is ‘infix’

• both: a + b + c -> +(a, b, c)
• left: a / b / c -> /(/(a, b), c)
• right: a = b = c -> =(a, =(b, c))
• non: a < b < c -> syntax error
• a both-associative operator has an unlimited number of arguments
• a left, right or non associative operator has at most two arguments

Applicable if not a symbol.

closeDelimiter: Delimiter | LatexToken[];
kind: "symbol" | "matchfix" | "infix" | "prefix" | "postfix" | "environment";

The kind of entry. If none is provided, symbol is assumed.

Infix position, with an operand before and an operand after: a ⊛ b.

Example: +, \times

Prefix position, with an operand after: ⊛ a

Example: -, \not

Postfix position, with an operand before: a ⊛

Example: !

The name of an environment, as used in \begin{matrix} where "matrix" is the name of the environment.

name: string;

Map a MathJSON function or symbol name to this entry.

Each entry should have at least a name or a parse property.

An entry with no name cannot be serialized: the name is used to map a MathJSON function or symbol name to the appropriate entry for serializing. However, an entry with no name defines a parsing synonym (for example for the symbol \varnothing which is a synonym for \emptyset).

If not parse property is provided, only the trigger is used to select this entry. Otherwise, the if the trigger of the entry matches the current token, the parse function is invoked.

openDelimiter: Delimiter | LatexToken[];

If kind is 'matchfix': the closeDelimiter and trigger property are required

optionalLatexArg: number;

If kind is ‘symbol’.

If a LaTeX command (i.e. the trigger starts with \, e.g. \sqrt) indicates the number of optional arguments expected (indicate with square brackets).

For example, for the \sqrt command, 1: \sqrt[3]{x}

parse: Expression | ParserFunction<T>;

If the current token matches the trigger for this entry the parse method is used to produce a matching Expression.

When the parse method is called (if the kind is different than matchfix), the scanner is pointing to the token right after the trigger.

The context can be considered in the parse method, for example by checking the domain of the left-hand-side expression, or the current precedence level. A rhs expression can be tentatively scanned for, for example by calling scanner.matchExpression().

If the match is not successful, parse should return [lhs, null]

For example, the \times command distinguishes being applied to two numbers (in which case it’s the Multiply function) or to two sets (in which case it’s the CartesianProduct function).

For matchfix kind, the parse function is called after the trigger (the open delimiter), 0 or more expressions (separated by separator) and the closing delimiter have been scanned. The lhs argument is the expressions in between the open and close delimiter. If multiple expressions, it is passed as a ['Sequence',...].

If the parse property is a string, it’s a shorthand for the parse method (lhs) => [lhs, parse].

If the parse property is not provided, the name is used instead as the result of the parsing when the trigger matches.

precedence: number;

Applies to infix, symbol (used for correct wrapping)

requiredLatexArg: number;

If kind is ‘symbol’`.

If a LaTeX command (i.e. the trigger starts with \, e.g. \frac) indicates the number of required arguments expected (indicated with curly braces).

For example, for the \frac command, 2: \frac{1}{n}

serialize: SerializerFunction<T> | LatexString;

Transform an expression into a LaTeX string. If no serialize property is provided, the trigger is used

trigger: LatexString | LatexToken[];

The trigger is the set of tokens that will make this record eligible for attempting to parse the stream and generate an expression. After the trigger matches, the parse function is called, if available.

matchfix operators use openDelimiter and closeDelimiter instead.

A LatexString is a regular string of LaTeX, for example: \frac{\pi}{2}

string

A LatexToken is a token as returned by Scanner.peek.

It can be one of the indicated constants, or a string that starts with a \ for LaTeX commands, or another LaTeX characters, which include digits, letters and punctuation.

• | string
• | "<{>"
• | "<}>"
• | ""
• | "<$>" • | "<$\$>"

<T extends number> =

<T extends number> =

A MathJSON numeric quantity.

The string is a string of:

• an optional - minus sign
• a string of decimal digits
• an optional fraction part (a . decimal point followed by decimal digits)
• an optional exponent part (a e or E exponent marker followed by an optional - minus sign, followed by a string of digits).
• an optional format indicator:
• n to indicate the preceding is a BigInt
• d to indicate the preceding is an arbitrary precision Decimal number

For example: -12.34, 0.234e-56, 123454d.

• num: "NaN" | "-Infinity" | "+Infinity" | string;
&
• Attributes

beginExponentMarker: LatexString;
beginRepeatingDigits: LatexString;
decimalMarker: LatexString;

A string representing the decimal marker, the string separating the whole portion of a number from the fractional portion, i.e. the ‘.’ in ‘3.1415’.

Some countries use a comma rather than a dot. In this case it is recommended to use "{,}"" as the marker: the surrounding bracket ensure there is no additional gap after the comma.

Default: "."

endExponentMarker: LatexString;
endRepeatingDigits: LatexString;
exponentProduct: LatexString;
groupSeparator: LatexString;

A string representing the separator between groups of digits, used to improve readability of numbers with lots of digits.

If you change it to another value, be aware that this may lead to unexpected results. For example, if changing it to , the expression x_{1,2} will parse as x with a subscript of 1.2, rather than x with two subscripts, 1 and 2.

Default: "\\," (thin space, 3/18mu) (Resolution 7 of the 1948 CGPM)

imaginaryNumber: LatexString;
negativeInfinity: LatexString;
notANumber: LatexString;
notation: "engineering" | "auto" | "scientific";
positiveInfinity: LatexString;
precision: number;
truncationMarker: LatexString;

<T extends number> =
applyInvisibleOperator: "auto" | "null" | (lhs: Expression<T>, scanner: Scanner<T>): Expression<T> | "null";

This function is invoked when a number is followed by a symbol, an open delimiter or a function.

If this function is set to null, the lhs and rhs are joined as a Sequence.

If this function is set to undefined it behaves in the following way:

• a number followed by a numeric expression is considered as separated with an invisible multiplication sign, and the two are joined as [‘Multiply’, lhs, rhs].
• a number followed by a rational number is considered to be separated with an invisible plus, and the two are joined as [‘Add’, lhs,

For example with 2\frac{3}{4}: ["Add", 2, ["Divide", 3, 4]]

parseArgumentsOfUnknownLatexCommands: boolean;

When an unknown LaTeX command is encountered, attempt to parse any arguments it may have.

For example, \foo{x+1} would produce ['\foo', ['Add', 'x', 1]] if this property is true, ['LatexSymbols', '\foo', '<{>', 'x', '+', 1, '<{>'] otherwise.

parseNumbers: boolean;

When a number is encountered, parse it.

Otherwise, return each token making up the number (minus sign, digits, decimal separator, etc…).

Default: true

parseUnknownToken: (token: LatexToken, scanner: Scanner): "symbol" | "function" | "skip" | "error";

The parseUnknownToken function is invoked when a token (a, \alpha…) is encountered at a position where a symbol or a function could be parsed.

If it returns symbol or function, the token is interpreted as a symbol or function, respectively.

If a function and the token is followed by an apply function operator (typically, parentheses), parse them as arguments to the function.

If skip, the token is skipped as if it was not present. This is convenient for purely presentational commands, such as \displaystyle.

If error, an error condition is raised.

preserveLatex: boolean;

If true, the expression will be decorated with the LaTeX fragments corresponding to each elements of the expression

skipSpace: boolean;

If true, ignore space characters.

Default: true

Custom parser function.

It is triggered by a LaTeX fragment (the latex argument). When invoked, the scanner points right after that LaTeX fragment. The scanner should be moved, by calling scanner.next() for every consumed token.

If it was in an infix or postfix context, lhs will represent the left-hand side argument. In a prefix or matchfix context, lhs is null.

In a superfix (^) or subfix (_) context (that is if the first token of the trigger is ^ or _), lhs is ["Superscript", lhs, rhs] and ["Subscript", lhs, rhs], respectively.

The function should return a tuple:

• Its first element is an unprocessed left-hand side, if any. If the left-hand-side has been consumed (for example if this was a valid infix operator), the first element of the tuple should be null.

• Its second element is the resulting expression.

<T extends number> = (lhs: Expression<T> | "null", scanner: Scanner<T>, minPrec: number): [lhs: Expression<T> | "null", result: Expression<T> | "null"]

• | "timeout"
• | "out-of-memory"
• | "recursion-depth-exceeded"
• | "iteration-limit-exceeded"

applyFunctionStyle: (expr: Expression, level: number): "paren" | "leftright" | "big" | "none";
fractionStyle: (expr: Expression, level: number): "quotient" | "inline-solidus" | "nice-solidus" | "reciprocal" | "factor";
groupStyle: (expr: Expression, level: number): "paren" | "leftright" | "big" | "none";
invisibleMultiply: LatexString;

LaTeX string used to render an invisible multiply, e.g. in ‘2x’. Leave it empty to join the adjacent terms, or use \cdot to insert a \cdot operator between them, i.e. 2\cdot x.

Empty by default.

invisiblePlus: LatexString;

LaTeX string used for an invisible plus, e.g. in ‘1 3/4’. Leave it empty to join the main number and the fraction, i.e. render it as 1\frac{3}{4}, or use + to insert a + operator between them, i.e. 1+\frac{3}{4}

Empty by default.

logicStyle: (expr: Expression, level: number): "word" | "boolean" | "uppercase-word" | "punctuation";
multiply: LatexString;

LaTeX string used for an explicit multiply operator,

Default: \times

numericSetStyle: (expr: Expression, level: number): "compact" | "regular" | "interval" | "set-builder";
powerStyle: (expr: Expression, level: number): "root" | "solidus" | "quotient";
rootStyle: (expr: Expression, level: number): "radical" | "quotient" | "solidus";

<T extends number> = (serializer: Serializer<T>, expr: T | Expression<T>): string

If applicable, the head of the function about which the signal was raised

message: SignalMessage;

An error/warning code or, a code with one or more arguments specific to the signal code.

origin: SignalOrigin;

Location where the signal was raised.

severity: "warning" | "error";

• | SignalCode
• | [SignalCode, ...any[]]

around: string;
column: number;
line: number;
offset: number;
source: string;
url: string;