UNPKG

stemcmicro

Version:

Computer Algebra System in TypeScript

810 lines (795 loc) 24.5 kB
import { Native } from 'math-expression-native'; export { NATIVE_MAX, NATIVE_MIN, Native, code_from_native_sym, is_native_sym, native_sym } from 'math-expression-native'; import { Sym, CellHost, Tensor, Cell } from 'math-expression-atoms'; import { LambdaExpr, CompareFn as CompareFn$1, ExprHandler, ExprContext } from 'math-expression-context'; import { U, Cons, Shareable, Atom } from 'math-expression-tree'; declare enum SyntaxKind { /** * ClojureScript Language. */ ClojureScript = 1, /** * Eigenmath Scripting Language by George Weigt. */ Eigenmath = 2, /** * EcmaScript Language */ EcmaScript = 3, /** * Python Scripting Language */ PythonScript = 4 } declare function human_readable_syntax_kind(syntaxKind: SyntaxKind): "ClojureScript" | "EcmaScript" | "Eigenmath" | "PythonScript"; declare const syntaxKinds: SyntaxKind[]; declare class Stack<T> { #private; tos: number; constructor(elements?: T[]); get length(): number; set length(length: number); get top(): T; getAt(i: number): T; setAt(i: number, element: T): void; peek(index: number): T; push(element: T): void; pushItems(items: T[]): void; pop(): T; popItems(n: number): T[]; /** * [a,b,c,d,e] => [a,b,d,e,c] (n=3) */ rotateL(n: number): void; /** * [a,b,c,d,e] => [a,b,e,c,d] (n=3) */ rotateR(n: number): void; copy(): Stack<T>; some(predicate: (value: T, index: number, array: T[]) => boolean): boolean; splice(start: number, deleteCount?: number): T[]; /** * Changes the order of the top two elements on the stack. */ swap(): void; } declare class Thing { readonly proto: unknown; getter: unknown; setter: unknown; properties: unknown; constructor(proto: unknown); } interface Scope { thing: Thing; evaluate(opr: Native, ...args: U[]): U; hasBinding(sym: Sym, target: Cons): boolean; getBinding(sym: Sym, target: Cons): U; setBinding(sym: Sym, binding: U): void; hasUserFunction(sym: Sym): boolean; getUserFunction(sym: Sym): U; setUserFunction(sym: Sym, usrfunc: U): void; valueOf(expr: U): U; } declare class State { readonly input: U; readonly $: Scope; /** * For use by evaluators. Let's the evaluator know it is being called for the first time. * The evaluator is responsible for updating the value to false if it chooses to use it. */ firstTime: boolean; /** * MUST be initialized to false. */ done: boolean; doneArg: boolean[]; /** * For use by evaluators to keep track of evaluated arguments. */ argValues: U[]; /** * Contains the value from the previous invocation of the evaluator. */ value: U; /** * The inputs from the invocation of the module. */ inputs: U[]; /** * The values from the invocation of the module. */ values: U[]; doneCallee: number; doneArgs: boolean; funcThis: unknown; func: unknown; arguments: unknown; constructor(input: U, $: Scope); } interface StepperHandler { atom(after: U, before: U): void; } interface StepperConfig { allowUndeclaredVars: boolean; } declare class Stepper { #private; POLYFILL_TIMEOUT: number; /** * @param module * @param options * @param initFunc */ constructor(module: Cons, options?: Partial<StepperConfig>, initFunc?: (runner: Stepper, globalObject: Thing) => void); createScope(node: unknown, parentScope: Scope): Scope; createObjectProto(proto: unknown | null): Thing; defineFunction(name: Sym, lambda: LambdaExpr): void; initGlobal(globalObject: Thing): void; run(handler?: StepperHandler): boolean; /** * Execute one step of the interpreter. * @returns true if there are more instructions to execute. */ next(handler?: StepperHandler): boolean; get stack(): Stack<State>; addListener(listener: ExprEngineListener): void; removeListener(listener: ExprEngineListener): void; } interface ProgramControl { compareFn(opr: Sym): CompareFn$1; getDirective(directive: number): number; pushDirective(directive: number, value: number): void; popDirective(): void; getSymbolPrintName(sym: Sym): string; } interface ProgramStack extends Shareable { get length(): number; set length(length: number); concat(exprs: U[]): void; get isatom(): boolean; get iscons(): boolean; get istrue(): boolean; dupl(): void; peek(): U; pop(): U; push(expr: U): void; head(): void; rest(): void; rotateL(n: number): void; rotateR(n: number): void; swap(): void; getAt(i: number): U; setAt(i: number, expr: U): void; splice(start: number, deleteCount?: number): U[]; } interface ProgramEnv extends Shareable { clearBindings(): void; executeProlog(script: string[]): void; getBinding(opr: Sym, target: Cons): U; getUserFunction(name: Sym): U; hasBinding(opr: Sym, target: Cons): boolean; hasUserFunction(name: Sym): boolean; setBinding(opr: Sym, binding: U): void; setUserFunction(name: Sym, userfunc: U): void; defineUserSymbol(name: Sym): void; handlerFor<T extends U>(expr: T): ExprHandler<T>; /** * If a stack is provided, the computed value is pushed onto the stack and nil is returned. */ valueOf(expr: U, stack?: Pick<ProgramStack, "push">): U; hasState(key: string): boolean; getState(key: string): Shareable; setState(key: string, value: Shareable): void; } interface StackFunction { (x: Cons, env: ProgramEnv, ctrl: ProgramControl, $: ProgramStack): void; } interface ProgramIO { get inbuf(): string; set inbuf(inbuf: string); get listeners(): ExprEngineListener[]; get trace1(): number; set trace1(trace1: number); get trace2(): number; set trace2(trace2: number); } interface EnvConfig { allowUndeclaredVars: UndeclaredVars; assumes: { [name: string]: Partial<Predicates>; }; dependencies: FEATURE[]; enable: Directive[]; disable: Directive[]; noOptimize: boolean; useCaretForExponentiation: boolean; useDerivativeShorthandLowerD: boolean; useIntegersForPredicates: boolean; useParenForTensors: boolean; syntaxKind?: SyntaxKind; } type Sign = -1 | 0 | 1; type TFLAGS = number; /** * Corresponds to the 'name' property on an Atom. */ type FEATURE = "Blade" | "Boo" | "Cell" | "Flt" | "Imu" | "Map" | "Rat" | "Sym" | "Tensor" | "Uom"; /** * Determines how an expression is evaluated. */ declare enum Directive { /** * Convert familiar expressions to canonical form. Mutually exclusive with familiarize. */ canonicalize = 0, /** * Replace sin with cos. Mutually exclusive with convertCosToSim. */ convertSinToCos = 1, /** * Replace cos with sin. Mutually exclusive with convertSinToCos. */ convertCosToSin = 2, /** * Convert canonical expressions to familiar form. Mutually exclusive with canonicalize. */ familiarize = 3, /** * Is not the same as the expand function. * Mutually exclusive with factoring. */ expanding = 4, /** * Determines whether abs(a + b + c ...) is expanded. */ expandAbsSum = 5, /** * Determines whether cos(a + b + c ...) is expanded. */ expandCosSum = 6, /** * Determines whether (a + b + c ...) raised to a positive integer exponent is expanded. * The default is true. */ expandPowSum = 7, /** * Determines whether cos(a + b + c ...) is expanded. */ expandSinSum = 8, /** * Determines whether numeric types are converted to floating point numbers for numeric evaluation. * * The default value as false. */ evaluatingAsFloat = 9, /** * Determines whether complex numbers are driven towards clock form. * The other possibilities are polar and rectanglular. * * The default value is false. */ complexAsClock = 10, /** * Determines whether complex numbers are driven towards polar form. * The other possibilities are clock and rectanglular. * * The default value is false. */ complexAsPolar = 11, /** * Determines whether complex numbers are driven towards rectangular form. * The other possibilities are clock and polar. * * The default value is false. */ complexAsRectangular = 12, /** * Determines whether exponential functions are converted ti exponential form. */ convertExpToTrig = 13, /** * Determines whether trigonometric functions are converted to exponential form. * * The default is false. */ convertTrigToExp = 14, /** * Determines whether zero terms are kept in sums in attempt to preserve the dynamic type. * The alternative is to use a canonical zero value, usually that for rational numbers. * * The default value is false. */ keepZeroTermsInSums = 15, /** * Is not the same as the factor function. * Mutually exclusive with expanding. */ factoring = 16, /** * Determines whether floating point numbers are rendered as EcmaScript numbers. * If not, floating point numbers are rendered in a proprietary format. * * The default value is false. */ renderFloatAsEcmaScript = 17, /** * Determines whether caret token '^' will be used for exponentiation or for the exterior product. * Using the caret token for exponetitation is common in mathematical tools but not in programming languages. * * The default value is false. */ useCaretForExponentiation = 18, /** * Determines whether test funtions will return Boo or Rat values. * * The default value is false. */ useIntegersForPredicates = 19, useParenForTensors = 20, depth = 21, drawing = 22, nonstop = 23, forceFixedPrintout = 24, maxFixedPrintoutDigits = 25, printMode = 26, codeGen = 27 } /** * */ interface PrintHandler { print(...items: string[]): void; } type CompareFn = (lhs: U, rhs: U) => Sign; /** * */ interface ExprComparator { compare(lhs: U, rhs: U, $: ExtensionEnv): Sign; } /** * Not to be confused with a LambdaExpr. * Here the first argument is the expression including the operator. */ type EvalFunction = (expr: Cons, $: ExtensionEnv) => U; type KeywordRunner = ($: ExtensionEnv) => void; interface Predicates { /** * An algebraic number is any number that is a root of a non-zero polynomial having rational coefficients. * All algebraic numbers are complex. * An algebraic number may or may not be real. * Includes all rational numbers. */ algebraic: boolean; /** * An element of the field of antihermitian operators. * Defaults to false. */ antihermitian: boolean; /** * A commutative expression. * A commutative expression commutes with all other expressions under multiplication. * If an expression a has commutative then a * b == b * a for any other expression b (even if b is not commutative). * Unlike all other assumptions predicates commutative must always be true or false and can never be undefined. * Also unlike all other predicates commutative defaults to true. */ commutative: boolean; /** * A complex number is any number of the form x+i*y where x and y are real. * All complex numbers are finite. Includes all real numbers. */ complex: boolean; extended_negative: boolean; extended_nonnegative: boolean; extended_nonpositive: boolean; extended_nonzero: boolean; extended_positive: boolean; /** * A finite expression. * Any expression that is not infinite is considered finite. */ finite: boolean; /** * An element of the field of Hermitian operators. */ hermitian: boolean; /** * The extension of the complex numbers to include infinitesimals and infinite numbers. */ hypercomplex: boolean; /** * The extension of the real numbers to include infinitesimals and infinite numbers. */ hyperreal: boolean; imaginary: boolean; /** * An infinite expression. */ infinite: boolean; infinitesimal: boolean; integer: boolean; irrational: boolean; negative: boolean; noninteger: boolean; nonnegative: boolean; nonpositive: boolean; nonzero: boolean; /** * A real number that is greater than zero. * All positive numbers are finite so infinity is not positive. */ positive: boolean; rational: boolean; real: boolean; /** * A complex number that is not algebraic. * All transcendental numbers are complex. * A transcendental number may or may not be real but can never be rational. * Defaults to false. */ transcendental: boolean; zero: boolean; } /** * */ interface ExtensionEnv extends ExprContext, ProgramEnv, ProgramControl, Pick<ProgramIO, "listeners"> { addAtomListener(subscriber: AtomListener): void; removeAtomListener(subscriber: AtomListener): void; getCellHost(): CellHost; setCellHost(host: CellHost): void; getProlog(): readonly string[]; getPrintHandler(): PrintHandler; setPrintHandler(handler: PrintHandler): void; abs(expr: U): U; algebra(metric: Tensor<U>, labels: Tensor<U>): Tensor<U>; /** * */ add(...args: U[]): U; arccos(expr: U): U; arcsin(expr: U): U; arctan(expr: U): U; arg(expr: U): U; clock(expr: U): U; conj(expr: U): U; cos(expr: U): U; clearBindings(): void; clearOperators(): void; compareFn(opr: Sym): CompareFn; component(tensor: Tensor<U>, indices: U): U; /** * Defines the implementation of a function that is used to transform (name ...) expressions. */ defineEvalFunction(opr: Sym, evalFunction: EvalFunction): void; defineFunction(match: U, lambda: LambdaExpr): void; defineStackFunction(opr: Sym, stackFunction: StackFunction): void; /** * e.g. clearall */ defineKeyword(sym: Sym, runner: KeywordRunner): void; defineExtension(builder: ExtensionBuilder<U>, immediate?: boolean): void; defineUserSymbol(name: Sym): void; derivedEnv(): ExtensionEnv; divide(lhs: U, rhs: U): U; /** * */ equals(lhs: U, rhs: U): boolean; evaluate(opr: Native, ...args: U[]): U; executeProlog(prolog: readonly string[]): void; exp(expr: U): U; factor(expr: U): U; /** * */ factorize(poly: U, x: U): U; float(expr: U): U; getDirective(directive: number): number; getSymbolPredicates(sym: Sym): Predicates; /** * Used during rendering. */ getSymbolPrintName(sym: Sym): string; getSymbolUsrFunc(sym: Sym): U; getSymbolsInfo(): { sym: Sym; value: U; }[]; /** * Used to make the environment ready after all operator builders have been added. */ buildOperators(): void; im(expr: U): U; /** * */ inner(lhs: U, rhs: U): U; /** * Generalized predicate testing. * @param predicate * @param expr */ is(predicate: Sym, expr: U): boolean; iscomplex(expr: U): boolean; isExpanding(): boolean; isFactoring(): boolean; /** * Meaning is imaginary valued. i.e. evaluates to i times a real number. */ isimag(expr: U): boolean; isinfinite(expr: U): boolean; isinfinitesimal(expr: U): boolean; isminusone(expr: U): boolean; isnegative(expr: U): boolean; /** * @deprecated The implementation doesn't need a full context. */ isone(expr: U): boolean; ispositive(expr: U): boolean; isreal(expr: U): boolean; /** * Determines whether expr is scalar-valued. */ isscalar(expr: U): boolean; /** * A convenience for appling the predicate function to the expression. */ iszero(expr: U): boolean; /** * */ log(expr: U): U; /** * */ multiply(...args: U[]): U; /** * */ negate(expr: U): U; extensionFor(expr: U): Extension<U> | undefined; /** * */ outer(...args: U[]): U; polar(expr: U): U; /** * */ power(base: U, expo: U): U; re(expr: U): U; rect(expr: U): U; remove(varName: Sym): void; pushDirective(directive: number, value: number): void; popDirective(): void; setSymbolOrder(sym: Sym, order: ExprComparator): void; setSymbolPredicates(sym: Sym, predicates: Partial<Predicates>): void; setSymbolPrintName(sym: Sym, printName: string): void; setSymbolUsrFunc(sym: Sym, usrfunc: U): void; simplify(expr: U): U; sin(expr: U): U; sqrt(expr: U): U; st(expr: U): U; subst(newExpr: U, oldExpr: U, expr: U): U; /** * */ subtract(lhs: U, rhs: U): U; toInfixString(expr: U): string; toLatexString(expr: U): string; toSExprString(expr: U): string; transform(expr: U): [TFLAGS, U]; valueOf(expr: U): U; } /** * The interface that MUST be implemented by extensions to the environment. * The type parameter,T, allows you to constrain the argument types of the * methods that you implement. e.g. If isKind() only matches a Cons, then set T * to be Cons. If isKind() only matches Sym, set T to be Sym. In more general * cases, use a more general type. The rule is that isKind determines which expression are matched, * and when the other method are called (they all contain at least one argument that matches T), * it determines the possible dynamic types for T. */ interface ExtensionBuilder<T extends U> { create(config: Readonly<EnvConfig>): Extension<T>; } /** * */ interface Extension<T extends U> extends ExprHandler<T> { readonly hash: string; readonly name: string; readonly phases?: number; readonly dependencies?: FEATURE[]; iscons(): this is Extension<Cons>; operator(): Sym; isKind(expr: U, env: ExprContext): boolean; toHumanString(expr: T, env: ExprContext): string; toInfixString(expr: T, env: ExprContext): string; toLatexString(expr: T, env: ExprContext): string; toListString(expr: T, env: ExprContext): string; /** * This method assumes that the opr is in the operator slot of a combination. * Except for Sym, that's an experimental proposition. */ evaluate(opr: T, argList: Cons, $: ExprContext): [TFLAGS, U]; transform(expr: T, $: ExprContext): [TFLAGS, U]; valueOf(expr: T, $: ExprContext): U; } interface ParseConfig { useCaretForExponentiation: boolean; useParenForTensors: boolean; explicitAssocAdd: boolean; explicitAssocExt: boolean; explicitAssocMul: boolean; syntaxKind: SyntaxKind; } interface RenderConfig { format: "Ascii" | "Human" | "Infix" | "LaTeX" | "SExpr" | "SVG"; useCaretForExponentiation: boolean; useParenForTensors: boolean; } declare enum Concept { Last = 1, TTY = 2 } interface AtomListener { reset(from: U, to: U, source: Cell): void; } interface ExprEngineListener { output(output: string): void; } interface ExprHandlerBuilder<T extends U> { create(): ExprHandler<T>; } interface ExprEngine extends Pick<ProgramEnv, "clearBindings"> { clearBindings(): void; executeProlog(prolog: string[]): void; executeScript(sourceText: string): { values: U[]; prints: string[]; errors: Error[]; }; defineAtomHandler<T extends Atom>(builder: ExprHandlerBuilder<T>, type: string, guard: (expr: Atom) => boolean): void; defineFunction(name: Sym, lambda: LambdaExpr): void; parse(sourceText: string, options?: Partial<ParseConfig>): { trees: U[]; errors: Error[]; }; parseModule(sourceText: string, options?: Partial<ParseConfig>): { module: Cons; errors: Error[]; }; simplify(expr: U): U; valueOf(expr: U): U; getBinding(opr: Sym, target: Cons): U; hasBinding(opr: Sym, target: Cons): boolean; setBinding(opr: Sym, binding: U): void; hasUserFunction(name: Sym): boolean; getUserFunction(name: Sym): U; setUserFunction(name: Sym, userfunc: U): void; symbol(concept: Concept): Sym; renderAsString(expr: U, config?: Partial<RenderConfig>): string; addAtomListener(listener: AtomListener): void; removeAtomListener(listener: AtomListener): void; addListener(listener: ExprEngineListener): void; removeListener(listener: ExprEngineListener): void; release(): void; } /** * Determines the action upon attempts to access an undeclared variable. */ declare enum UndeclaredVars { Err = 1,// ClojureScript Nil = 2 } interface EngineConfig { allowUndeclaredVars: UndeclaredVars; prolog: string[]; syntaxKind: SyntaxKind; useCaretForExponentiation: boolean; useDerivativeShorthandLowerD: boolean; useIntegersForPredicates: boolean; } declare function create_engine(options?: Partial<EngineConfig>): ExprEngine; /** * @param p * @param x * @returns */ declare function roots(p: U, x: U, $: ExprContext): Tensor; interface ExprTransformOptions { autoExpand?: boolean; autoFactor?: boolean; /** * Directives that become enabled by setting to true. */ enable?: Directive[]; /** * Directives that become disabled by setting to false. */ disable?: Directive[]; useIntegersForPredicates?: boolean; } interface ScriptExecuteOptions extends ExprTransformOptions { /** * Determines whether execptions are caught and returned in the errors property. */ catchExceptions?: boolean; /** * Determines what kind of parser is used for the sourceText. */ syntaxKind?: SyntaxKind; } interface ScriptContextOptions extends ScriptExecuteOptions { /** * The default is ???. */ allowUndeclaredVars?: UndeclaredVars; /** * The assumptions about unbound symbols. */ assumes?: { [name: string]: Partial<Predicates>; }; dependencies?: string[]; /** * Determines whether the circumflex (caret) character, '^', will be used during parsing to denote exponentiation. * The alternative is to use '**', freeing the caret character for use with outer products which is convenient * in applications using Geometric Algebra. The default value is false. */ useCaretForExponentiation?: boolean; useDerivativeShorthandLowerD?: boolean; /** * */ prolog?: string[]; /** * Determines whether test functions will return boolean or integer values. * * The default is false. */ useIntegersForPredicates?: boolean; /** * Determines whether parentheses, "(" and ")", or square brackets, "[" and "]", will be used to delimit tensors. */ useParenForTensors?: boolean; } interface ScriptContext { readonly $: ExtensionEnv; clearBindings(): void; defineFunction(pattern: U, impl: LambdaExpr): void; getSymbolProps(sym: Sym): Predicates; getBinding(opr: Sym, target: Cons): U; getSymbolsInfo(): { sym: Sym; value: U; }[]; evaluate(tree: U, options?: ExprTransformOptions): { value: U; prints: string[]; errors: Error[]; }; executeProlog(prolog: string[]): void; executeScript(sourceText: string, options?: ScriptExecuteOptions): { values: U[]; prints: string[]; errors: Error[]; }; renderAsAscii(expr: U): string; renderAsHuman(expr: U): string; renderAsInfix(expr: U): string; renderAsLaTeX(expr: U): string; renderAsSExpr(expr: U): string; simplify(expr: U): U; addRef(): void; release(): void; } /** * TODO: The REP should migrate toward the ExprEngine API. * @deprecated Used only by development REPL. */ declare function create_script_context(contextOptions?: ScriptContextOptions): ScriptContext; export { type AtomListener, Concept, type EngineConfig, type ExprEngine, type ExprEngineListener, type ExprHandlerBuilder, type FEATURE, type ParseConfig, type RenderConfig, type Scope, Stack, State, Stepper, type StepperConfig, type StepperHandler, SyntaxKind, Thing, UndeclaredVars, create_engine, create_script_context, human_readable_syntax_kind, roots, syntaxKinds };