/* 0.26.0-alpha2 */import { Complex } from 'complex-esm';
import { Decimal } from 'decimal.js';
import { Expression, MathJsonIdentifier, MathJsonNumber } from '../math-json/types';
import type { LibraryCategory, LatexDictionaryEntry, LatexString, ParseLatexOptions } from './latex-syntax/public';
import { AssumeResult, BoxedFunctionDefinition, BoxedSymbolDefinition, IComputeEngine, IdentifierDefinitions, ExpressionMapInterface, RuntimeScope, Scope, SymbolDefinition, BoxedRuleSet, Rule, ComputeEngineStats, Metadata, FunctionDefinition, BoxedSubstitution, AssignValue, AngularUnit, CanonicalOptions } from './public';
import { Rational } from './numerics/rationals';
import { type IndexedLatexDictionary } from './latex-syntax/dictionary/definitions';
import { BoxedExpression, BoxedRule, EvaluateOptions, SemiBoxedExpression } from './boxed-expression/public';
import './boxed-expression/serialize.ts';
import { ExactNumericValueData, NumericValue, NumericValueData } from './numeric-value/public';
import { Type, TypeString } from '../common/type/types';
import { OneOf } from '../common/one-of';
import { BigNum } from './numerics/bignum';
/**
 *
 * To use the Compute Engine, create a `ComputeEngine` instance:
 *
 * ```js
 * ce = new ComputeEngine();
 * ```
 *
 * If using a mathfield, use the default Compute Engine instance from the
 * `MathfieldElement` class:
 *
 * ```js
 * ce = MathfieldElement.computeEngine
 * ```
 *
 * Use the instance to create boxed expressions with `ce.parse()` and `ce.box()`.
 *
 * ```js
 * const ce = new ComputeEngine();
 *
 * let expr = ce.parse("e^{i\\pi}");
 * console.log(expr.N().latex);
 * // ➔ "-1"
 *
 * expr = ce.box(["Expand", ["Power", ["Add", "a", "b"], 2]]);
 * console.log(expr.evaluate().latex);
 * // ➔ "a^2 +  2ab + b^2"
 * ```
 *
 * @category Compute Engine
 *
 */
export declare class ComputeEngine implements IComputeEngine {
    readonly True: BoxedExpression;
    readonly False: BoxedExpression;
    readonly Pi: BoxedExpression;
    readonly E: BoxedExpression;
    readonly Nothing: BoxedExpression;
    readonly Zero: BoxedExpression;
    readonly One: BoxedExpression;
    readonly Half: BoxedExpression;
    readonly NegativeOne: BoxedExpression;
    readonly Two: BoxedExpression;
    readonly I: BoxedExpression;
    readonly NaN: BoxedExpression;
    readonly PositiveInfinity: BoxedExpression;
    readonly NegativeInfinity: BoxedExpression;
    readonly ComplexInfinity: BoxedExpression;
    /** The symbol separating the whole part of a number from its fractional
     *  part in a LaTeX string.
     *
     * Commonly a period (`.`) in English, but a comma (`,`) in many European
     * languages. For the comma, use `"{,}"` so that the spacing is correct.
     *
     * Note that this is a LaTeX string and is used when parsing or serializing
     * LaTeX. MathJSON always uses a period.
     *
     * */
    decimalSeparator: LatexString;
    /** @internal */
    _BIGNUM_NAN: Decimal;
    /** @internal */
    _BIGNUM_ZERO: Decimal;
    /** @internal */
    _BIGNUM_ONE: Decimal;
    /** @internal */
    _BIGNUM_TWO: Decimal;
    /** @internal */
    _BIGNUM_HALF: Decimal;
    /** @internal */
    _BIGNUM_PI: Decimal;
    /** @internal */
    _BIGNUM_NEGATIVE_ONE: Decimal;
    /** @internal */
    private _precision;
    /** @ internal */
    private _angularUnit;
    /** @internal */
    private _tolerance;
    /** @internal */
    private _bignumTolerance;
    private _negBignumTolerance;
    /** @internal */
    private _cache;
    /** @internal */
    private _stats;
    /** @internal */
    private _cost?;
    /** @internal */
    private _commonSymbols;
    /** @internal */
    private _commonNumbers;
    /**
     * The current scope.
     *
     * A **scope** stores the definition of symbols and assumptions.
     *
     * Scopes form a stack, and definitions in more recent
     * scopes can obscure definitions from older scopes.
     *
     * The `ce.context` property represents the current scope.
     *
     */
    context: RuntimeScope | null;
    /**
     * Generation.
     *
     * The generation is incremented each time the context changes.
     * It is used to invalidate caches.
     * @internal
     */
    generation: number;
    /** In strict mode (the default) the Compute Engine performs
     * validation of domains and signature and may report errors.
     *
     * These checks may impact performance
     *
     * When strict mode is off, results may be incorrect or generate JavaScript
     * errors if the input is not valid.
     *
     */
    strict: boolean;
    /** Absolute time beyond which evaluation should not proceed.
     * @internal
     */
    deadline?: number;
    /**
     * Return identifier tables suitable for the specified categories, or `"all"`
     * for all categories (`"arithmetic"`, `"algebra"`, etc...).
     *
     * An identifier table defines how the symbols and function names in a
     * MathJSON expression should be interpreted, i.e. how to evaluate and
     * manipulate them.
     *
     */
    /** @internal */
    private _latexDictionaryInput;
    /** @internal */
    _indexedLatexDictionary: IndexedLatexDictionary;
    /** @internal */
    _bignum: Decimal.Constructor;
    static getStandardLibrary(categories?: LibraryCategory[] | LibraryCategory | 'all'): readonly IdentifierDefinitions[];
    /**
     * Return a LaTeX dictionary suitable for the specified category, or `"all"`
     * for all categories (`"arithmetic"`, `"algebra"`, etc...).
     *
     * A LaTeX dictionary is needed to translate between LaTeX and MathJSON.
     *
     * Each entry in the dictionary indicate how a LaTeX token (or string of
     * tokens) should be parsed into a MathJSON expression.
     *
     * For example an entry can define that the `\pi` LaTeX token should map to the
     * symbol `"Pi"`, or that the token `-` should map to the function
     * `["Negate",...]` when in a prefix position and to the function
     * `["Subtract", ...]` when in an infix position.
     *
     * Furthermore, the information in each dictionary entry is used to serialize
     * the LaTeX string corresponding to a MathJSON expression.
     *
     * Use with `ce.latexDictionary` to set the dictionary. You can complement
     * it with your own definitions, for example with:
     *
     * ```ts
     * ce.latexDictionary = [
     *  ...ce.getLatexDictionary("all"),
     *  {
     *    kind: "function",
     *    identifierTrigger: "concat",
     *    parse: "Concatenate"
     *  }
     * ];
     * ```
     */
    static getLatexDictionary(domain?: LibraryCategory | 'all'): readonly Readonly<LatexDictionaryEntry>[];
    /**
     * Construct a new `ComputeEngine` instance.
     *
     * Identifier tables define functions and symbols (in `options.ids`).
     * If no table is provided the MathJSON Standard Library is used (`ComputeEngine.getStandardLibrary()`)
     *
     * The LaTeX syntax dictionary is defined in `options.latexDictionary`.
     *
     * 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 (`Booleans`, `Numbers`, etc...) that are used by later
     * dictionaries.
     *
     *
     * @param options.precision Specific how many digits of precision
     * for the numeric calculations. Default is 300.
     *
     * @param options.tolerance If the absolute value of the difference of two
     * numbers is less than `tolerance`, they are considered equal. Used by
     * `chop()` as well.
     */
    constructor(options?: {
        ids?: readonly IdentifierDefinitions[];
        precision?: number | 'machine';
        tolerance?: number | 'auto';
    });
    get latexDictionary(): Readonly<LatexDictionaryEntry[]>;
    set latexDictionary(dic: Readonly<LatexDictionaryEntry[]>);
    get indexedLatexDictionary(): IndexedLatexDictionary;
    /** After the configuration of the engine has changed, clear the caches
     * so that new values can be recalculated.
     *
     * This needs to happen for example when the numeric precision changes.
     *
     * @internal
     */
    reset(): void;
    /** @internal */
    _register(_expr: BoxedExpression): void;
    /** @internal */
    _unregister(_expr: BoxedExpression): void;
    /** @internal */
    get stats(): ComputeEngineStats;
    get precision(): number;
    /** The precision, or number of significant digits, of numeric
     * calculations when the numeric mode is `"auto"` or `"bignum"`.
     *
     * To make calculations using more digits, at the cost of expanded memory
     * usage and slower computations, set the `precision` higher.
     *
     * If the numeric mode is not `"auto"` or `"bignum"`, it is set to `"auto"`.
     *
     * Trigonometric operations are accurate for precision up to 1,000.
     *
     */
    set precision(p: number | 'machine' | 'auto');
    /**
     * The unit used for angles in trigonometric functions.
     *
     * Default is `"rad"` (radians).
     */
    get angularUnit(): AngularUnit;
    set angularUnit(u: AngularUnit);
    /** @experimental */
    get timeLimit(): number;
    /** @experimental */
    get iterationLimit(): number;
    /** @experimental */
    get recursionLimit(): number;
    get 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`.
     */
    set tolerance(val: number | 'auto');
    /** Replace a number that is close to 0 with the exact integer 0.
     *
     * How close to 0 the number has to be to be considered 0 is determined by {@linkcode tolerance}.
     */
    chop(n: number): number;
    chop(n: Decimal): Decimal | 0;
    chop(n: Complex): Complex | 0;
    /** Create an arbitrary precision number.
     *
     * The return value is an object with methods to perform arithmetic
     * operations:
     * - `toNumber()`: convert to a JavaScript `number` with potential loss of precision
     * - `add()`
     * - `sub()`
     * - `neg()` (unary minus)
     * - `mul()`
     * - `div()`
     * - `pow()`
     * - `sqrt()` (square root)
     * - `cbrt()` (cube root)
     * - `exp()`  (e^x)
     * - `log()`
     * - `ln()` (natural logarithm)
     * - `mod()`
  
     * - `abs()`
     * - `ceil()`
     * - `floor()`
     * - `round()`
  
     * - `equals()`
     * - `gt()`
     * - `gte()`
     * - `lt()`
     * - `lte()`
     *
     * - `cos()`
     * - `sin()`
     * - `tanh()`
     * - `acos()`
     * - `asin()`
     * - `atan()`
     * - `cosh()`
     * - `sinh()`
     * - `acosh()`
     * - `asinh()`
     * - `atanh()`
     *
     * - `isFinite()`
     * - `isInteger()`
     * - `isNaN()`
     * - `isNegative()`
     * - `isPositive()`
     * - `isZero()`
     * - `sign()` (1, 0 or -1)
     *
     */
    bignum(a: Decimal.Value | bigint): Decimal;
    /** Create a complex number.
     * The return value is an object with methods to perform arithmetic
     * operations:
     * - `re` (real part, as a JavaScript `number`)
     * - `im` (imaginary part, as a JavaScript `number`)
     * - `add()`
     * - `sub()`
     * - `neg()` (unary minus)
     * - `mul()`
     * - `div()`
     * - `pow()`
     * - `sqrt()` (square root)
     * - `exp()`  (e^x)
     * - `log()`
     * - `ln()` (natural logarithm)
     * - `mod()`
  
     * - `abs()`
     * - `ceil()`
     * - `floor()`
     * - `round()`
  
     * - `arg()` the angle of the complex number
     * - `inverse()` the inverse of the complex number 1/z
     * - `conjugate()` the conjugate of the complex number
  
     * - `equals()`
     *
     * - `cos()`
     * - `sin()`
     * - `tanh()`
     * - `acos()`
     * - `asin()`
     * - `atan()`
     * - `cosh()`
     * - `sinh()`
     * - `acosh()`
     * - `asinh()`
     * - `atanh()`
     *
     * - `isFinite()`
     * - `isNaN()`
     * - `isZero()`
     * - `sign()` (1, 0 or -1)
     */
    complex(a: number | Decimal | Complex, b?: number | Decimal): Complex;
    /**
     *
     * Create a Numeric Value.
     *
     * @internal
     */
    _numericValue(value: number | bigint | OneOf<[BigNum | NumericValueData | ExactNumericValueData | Complex]>): NumericValue;
    /**
     * The cost function is used to determine the "cost" of an expression. For example, when simplifying an expression, the simplification that results in the lowest cost is chosen.
     */
    get costFunction(): (expr: BoxedExpression) => number;
    set costFunction(fn: ((expr: BoxedExpression) => number) | undefined);
    /**
     * Return a matching symbol definition, starting with the current
     * scope and going up the scope chain. Prioritize finding a match by
     * wikidata, if provided.
     */
    lookupSymbol(symbol: string, wikidata?: string, scope?: RuntimeScope): undefined | BoxedSymbolDefinition;
    /**
     * Return the definition for a function with this operator name.
     *
     * Start looking in the current context, than up the scope chain.
     *
     * This is a very rough lookup, since it doesn't account for the domain
     * of the argument or the codomain. However, it is useful during parsing
     * to differentiate between symbols that might represent a function application, e.g. `f` vs `x`.
     */
    lookupFunction(name: MathJsonIdentifier, scope?: RuntimeScope | null): undefined | BoxedFunctionDefinition;
    /**
     * Associate a new definition to a symbol in the current context.
     *
     * If a definition existed previously, it is replaced.
     *
     *
     * For internal use. Use `ce.declare()` instead.
     *
     * @internal
     */
    defineSymbol(name: string, def: SymbolDefinition): BoxedSymbolDefinition;
    _defineSymbol(name: string, def: SymbolDefinition): BoxedSymbolDefinition;
    /**
     * Associate a new FunctionDefinition to a function in the current context.
     *
     * If a definition existed previously, it is replaced.
     *
     * For internal use. Use `ce.declare()` instead.
     *
     * @internal
     */
    defineFunction(name: string, def: FunctionDefinition): BoxedFunctionDefinition;
    _defineFunction(name: string, def: FunctionDefinition): BoxedFunctionDefinition;
    /**
     *
     * Create a new scope and add it to the top of the scope stack
     *
     */
    pushScope(scope?: Partial<Scope>): IComputeEngine;
    /** Remove the most recent scope from the scope stack, and set its
     *  parent scope as the current scope. */
    popScope(): IComputeEngine;
    /** Set the current scope, return the previous scope. */
    swapScope(scope: RuntimeScope | null): RuntimeScope | null;
    /** @internal */
    _printScope(options?: {
        details?: boolean;
        maxDepth?: number;
    }, scope?: RuntimeScope | null, depth?: number): RuntimeScope | null;
    /**
     * Reset the value of any identifiers that have been assigned a value
     * in the current scope.
     * @internal */
    resetContext(): void;
    /**
     * Declare an identifier: specify their type and other attributes,
     * including optionally a value.
     *
     * Once the type of an identifier has been declared, it cannot be changed.
     * The type information is used to calculate the canonical form of
     * expressions and ensure they are valid. If the type could be changed
     * after the fact, previously valid expressions could become invalid.
     *
     * Set the type to `any` type for a very generic type, or use `unknown`
     * if the type is not known yet. If `unknown`, the type will be inferred
     * based on usage.
     *
     * An identifier can be redeclared with a different type, but only if
     * the type of the identifier was inferred. If the domain was explicitly
     * set, the identifier cannot be redeclared.
     *
     */
    declare(id: string, def: Type | TypeString | OneOf<[SymbolDefinition, FunctionDefinition]>): IComputeEngine;
    declare(identifiers: {
        [id: string]: Type | TypeString | OneOf<[SymbolDefinition, FunctionDefinition]>;
    }): IComputeEngine;
    /** Assign a value to an identifier in the current scope.
     * Use `undefined` to reset the identifier to no value.
     *
     * The identifier should be a valid MathJSON identifier
     * not a LaTeX string.
     *
     * The identifier can take the form "f(x, y") to create a function
     * with two parameters, "x" and "y".
     *
     * If the id was not previously declared, assigning a value will declare it.
     * Its type is inferred from the value.
     *
     * To more precisely define the type of the identifier, use `ce.declare()`
     * instead, which allows you to specify the type, value and other
     * attributes of the identifier.
     */
    assign(id: string, value: AssignValue): IComputeEngine;
    assign(ids: {
        [id: string]: AssignValue;
    }): IComputeEngine;
    /**
     * Same as assign(), but for internal use:
     * - skips validity checks
     * - does not auto-declare
     * - if assigning to a function, must pass a JS function
     *
     * @internal
     */
    _assign(id: string, value: BoxedExpression | ((ops: ReadonlyArray<BoxedExpression>, options: EvaluateOptions & {
        engine: IComputeEngine;
    }) => BoxedExpression | undefined)): void;
    /**
     * 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
     *
     * @internal
     */
    shouldContinueExecution(): boolean;
    /** @internal */
    checkContinueExecution(): void;
    /** @internal */
    cache<T>(cacheName: string, build: () => T, purge?: (t: T) => T | undefined): T;
    /** Return a boxed expression from a number, string or semiboxed expression.
     * Calls `ce.function()`, `ce.number()` or `ce.symbol()` as appropriate.
     */
    box(expr: NumericValue | SemiBoxedExpression, options?: {
        canonical?: CanonicalOptions;
        structural?: boolean;
    }): BoxedExpression;
    function(name: string, ops: ReadonlyArray<BoxedExpression> | ReadonlyArray<Expression>, options?: {
        metadata?: Metadata;
        canonical: CanonicalOptions;
        structural: boolean;
    }): BoxedExpression;
    /**
     *
     * Shortcut for `this.box(["Error",...])`.
     *
     * The result is canonical.
     */
    error(message: string | string[], where?: string): BoxedExpression;
    typeError(expected: Type, actual: undefined | Type, where?: string): BoxedExpression;
    /**
     * Add a`["Hold"]` wrapper to `expr.
     */
    hold(expr: BoxedExpression): BoxedExpression;
    /** Shortcut for `this.box(["Tuple", ...])`
     *
     * The result is canonical.
     */
    tuple(...elements: ReadonlyArray<number>): BoxedExpression;
    tuple(...elements: ReadonlyArray<BoxedExpression>): BoxedExpression;
    string(s: string, metadata?: Metadata): BoxedExpression;
    /** Return a boxed symbol */
    symbol(name: string, options?: {
        metadata?: Metadata;
        canonical?: CanonicalOptions;
    }): BoxedExpression;
    /**
     * This function tries to avoid creating a boxed number if `num` corresponds
     * to a common value for which we have a shared instance (-1, 0, NaN, etc...)
     */
    number(value: number | bigint | string | NumericValue | MathJsonNumber | Decimal | Complex | Rational, options?: {
        metadata: Metadata;
        canonical: CanonicalOptions;
    }): BoxedExpression;
    rules(rules: Rule | ReadonlyArray<Rule | BoxedRule> | BoxedRuleSet | undefined | null, options?: {
        canonical?: boolean;
    }): BoxedRuleSet;
    getRuleSet(id?: string): BoxedRuleSet | undefined;
    /**
     * Return a function expression, but the caller is responsible for making
     * sure that the arguments are canonical.
     *
     * Unlike ce.function(), the operator of the  result is the name argument.
     * Calling this function directly is potentially unsafe, as it bypasses
     * the canonicalization of the arguments.
     *
     * For example:
     *
     * - `ce._fn('Multiply', [1, 'x'])` returns `['Multiply', 1, 'x']` as a canonical expression, even though it doesn't follow the canonical form
     * - `ce.function('Multiply', [1, 'x']` returns `'x'` which is the correct canonical form
     *
     * @internal */
    _fn(name: MathJsonIdentifier, ops: ReadonlyArray<BoxedExpression>, options?: Metadata & {
        canonical?: boolean;
    }): BoxedExpression;
    /**
     * Parse a string of LaTeX and return a corresponding `BoxedExpression`.
     *
     * If the `canonical` option is set to `true`, the result will be canonical
     *
     */
    parse(latex: null, options?: Partial<ParseLatexOptions> & {
        canonical?: CanonicalOptions;
    }): null;
    parse(latex: LatexString, options?: Partial<ParseLatexOptions> & {
        canonical?: CanonicalOptions;
    }): BoxedExpression;
    get assumptions(): ExpressionMapInterface<boolean>;
    /**
     * Return a list of all the assumptions that match a pattern.
     *
     * ```js
     *  ce.assume(['Element', 'x', 'PositiveIntegers');
     *  ce.ask(['Greater', 'x', '_val'])
     *  //  -> [{'val': 0}]
     * ```
     */
    ask(pattern: BoxedExpression): BoxedSubstitution[];
    /**
     * Answer a query based on the current assumptions.
     *
     */
    verify(_query: BoxedExpression): boolean;
    /**
     * Add an assumption.
     *
     * Note that the assumption is put into canonical form before being added.
     *
     * Returns:
     * - `contradiction` if the new assumption is incompatible with previous
     * ones.
     * - `tautology` if the new assumption is redundant with previous ones.
     * - `ok` if the assumption was successfully added to the assumption set.
     *
     *
     */
    assume(predicate: BoxedExpression): AssumeResult;
    /** Remove all assumptions about one or more symbols */
    forget(symbol: undefined | string | string[]): void;
}
