UNPKG

@stemcmicro/core

Version:

Computer Algebra System in TypeScript

1,141 lines (1,129 loc) 1.34 MB
/** * @stemcmicro/core 0.9.79 * (c) David Geo Holmes david.geo.holmes@gmail.com * Released under the MIT License. */ System.register(['@stemcmicro/native', '@stemcmicro/atoms', '@stemcmicro/diagnostics', '@stemcmicro/helpers', '@stemcmicro/tree', '@stemcmicro/context', '@stemcmicro/directive', '@stemcmicro/stack', '@stemcmicro/em-parse', '@stemcmicro/eigenmath'], (function (exports) { 'use strict'; var native_sym, Native, is_native, log$1, multiply$1, real$1, exp$1, create_sym, is_boo$1, Flt, negOne, is_num$1, is_rat, imu, is_flt$1, Rat, bigInt, is_tensor, zero, one, Tensor, create_int, BigInteger, is_sym$1, is_str$2, is_err, is_uom, is_blade, is_hyp$1, is_keyword, is_imu, Err, Cell, Map$1, create_flt$1, create_str$1, create_tensor, et, booT, epsilon, Str, piAsFlt$1, eAsFlt, two, four, half, negFour, three, nine, third, eight, Sym, Boo, assert_tensor, Hyp, create_tensor_elements_diagonal, is_map, is_tag, is_jsobject, create_boo, JsObject, assert_jsobject, assert_sym$1, booU, Uom, QQ, create_rat, zeroAsFlt$1, is_cell, assert_str, assert_map, assert_cell, assert_flt, create_hyp, booF, assert_rat, Keyword, create_tensor_elements, oneAsFlt$1, diagnostic, Diagnostics, is_localizable, Localizable, str_to_string, isone$1, is_add$1, is_multiply$1, is_power$1, guess, is_num_and_negative, is_rat_and_integer, is_num_and_eq_rational, is_cons_opr_eq_power, is_num_and_eq_number, is_num_and_eq_one_half, multiply_items, negate, subst, add$1, divide$1, is_mul_2_any_any, num_to_number, multiply, power, inverse, subtract$1, iszero, is_negative, is_cons_opr_eq_multiply, compare_num_num, is_cons_opr_eq_add, is_cons_opr_eq_sym, is_outer, is_inner_or_dot, lt_num_num, is_cons_opr_eq_inv, is_base_of_natural_logarithm, is_pi, is_num_and_eq_two, count_factors, contains_single_blade, abs$1, is_factorial$1, is_rat_and_fraction$1, convertMetricToNative, convert_tensor_to_strings, create_algebra_as_tensor, predicate_return_value, prolog_eval_varargs, float, is_safe_integer_range, is_opr_2_any_any, is_atom, nil, is_nil, is_cons, cadr$1, caddr$1, cadnr, items_to_cons, cdr, car, cons, assert_cons$1, assert_U$1, assert_cons_or_nil$1, cddr$1, cdddr, caadr$1, cadadr, is_cons2, cadddr$1, is_singleton, Lambda, SIGN_GT$1, SIGN_LT$1, SIGN_EQ$1, is_lambda, Directive, StackU, Stack, scan_meta, complexity, conjfunc, inner$1, push_rational, power$1, make_stack_draw, value_of, stopf, pop_integer, multiply$2, expfunc, add$2, sqrtfunc, subtract$2, negate$1, push_integer, multiply_factors$1, power_e_expo, stack_infix, stack_kronecker, stack_log, stack_mag, stack_mod, stack_noexpand, stack_outer, stack_rank, stack_arccosh, stack_arcsin, stack_arcsinh, stack_arctan, stack_arctanh, stack_arg, stack_binding, stack_circexp, stack_clock, stack_cos, stack_cosh, stack_exp, stack_expcos, stack_expcosh, stack_expsin, stack_expsinh, stack_exptan, stack_exptanh, stack_floor, stack_hadamard, stack_imag, stack_index, stack_inv, stack_minor, stack_minormatrix, stack_nroots, stack_polar, stack_rationalize, stack_real, stack_rect, stack_sin, stack_sinh, stack_sqrt, stack_testlt, stack_testge, stack_testgt, stack_transpose, stack_unit; return { setters: [function (module) { native_sym = module.native_sym; Native = module.Native; is_native = module.is_native; log$1 = module.log; multiply$1 = module.multiply; real$1 = module.real; exp$1 = module.exp; exports({ NATIVE_MAX: module.NATIVE_MAX, NATIVE_MIN: module.NATIVE_MIN, Native: module.Native, code_from_native_sym: module.code_from_native_sym, is_native_sym: module.is_native_sym, native_sym: module.native_sym }); }, function (module) { create_sym = module.create_sym; is_boo$1 = module.is_boo; Flt = module.Flt; negOne = module.negOne; is_num$1 = module.is_num; is_rat = module.is_rat; imu = module.imu; is_flt$1 = module.is_flt; Rat = module.Rat; bigInt = module.bigInt; is_tensor = module.is_tensor; zero = module.zero; one = module.one; Tensor = module.Tensor; create_int = module.create_int; BigInteger = module.BigInteger; is_sym$1 = module.is_sym; is_str$2 = module.is_str; is_err = module.is_err; is_uom = module.is_uom; is_blade = module.is_blade; is_hyp$1 = module.is_hyp; is_keyword = module.is_keyword; is_imu = module.is_imu; Err = module.Err; Cell = module.Cell; Map$1 = module.Map; create_flt$1 = module.create_flt; create_str$1 = module.create_str; create_tensor = module.create_tensor; et = module.et; booT = module.booT; epsilon = module.epsilon; Str = module.Str; piAsFlt$1 = module.piAsFlt; eAsFlt = module.eAsFlt; two = module.two; four = module.four; half = module.half; negFour = module.negFour; three = module.three; nine = module.nine; third = module.third; eight = module.eight; Sym = module.Sym; Boo = module.Boo; assert_tensor = module.assert_tensor; Hyp = module.Hyp; create_tensor_elements_diagonal = module.create_tensor_elements_diagonal; is_map = module.is_map; is_tag = module.is_tag; is_jsobject = module.is_jsobject; create_boo = module.create_boo; JsObject = module.JsObject; assert_jsobject = module.assert_jsobject; assert_sym$1 = module.assert_sym; booU = module.booU; Uom = module.Uom; QQ = module.QQ; create_rat = module.create_rat; zeroAsFlt$1 = module.zeroAsFlt; is_cell = module.is_cell; assert_str = module.assert_str; assert_map = module.assert_map; assert_cell = module.assert_cell; assert_flt = module.assert_flt; create_hyp = module.create_hyp; booF = module.booF; assert_rat = module.assert_rat; Keyword = module.Keyword; create_tensor_elements = module.create_tensor_elements; oneAsFlt$1 = module.oneAsFlt; }, function (module) { diagnostic = module.diagnostic; Diagnostics = module.Diagnostics; is_localizable = module.is_localizable; Localizable = module.Localizable; }, function (module) { str_to_string = module.str_to_string; isone$1 = module.isone; is_add$1 = module.is_add; is_multiply$1 = module.is_multiply; is_power$1 = module.is_power; guess = module.guess; is_num_and_negative = module.is_num_and_negative; is_rat_and_integer = module.is_rat_and_integer; is_num_and_eq_rational = module.is_num_and_eq_rational; is_cons_opr_eq_power = module.is_cons_opr_eq_power; is_num_and_eq_number = module.is_num_and_eq_number; is_num_and_eq_one_half = module.is_num_and_eq_one_half; multiply_items = module.multiply_items; negate = module.negate; subst = module.subst; add$1 = module.add; divide$1 = module.divide; is_mul_2_any_any = module.is_mul_2_any_any; num_to_number = module.num_to_number; multiply = module.multiply; power = module.power; inverse = module.inverse; subtract$1 = module.subtract; iszero = module.iszero; is_negative = module.is_negative; is_cons_opr_eq_multiply = module.is_cons_opr_eq_multiply; compare_num_num = module.compare_num_num; is_cons_opr_eq_add = module.is_cons_opr_eq_add; is_cons_opr_eq_sym = module.is_cons_opr_eq_sym; is_outer = module.is_outer; is_inner_or_dot = module.is_inner_or_dot; lt_num_num = module.lt_num_num; is_cons_opr_eq_inv = module.is_cons_opr_eq_inv; is_base_of_natural_logarithm = module.is_base_of_natural_logarithm; is_pi = module.is_pi; is_num_and_eq_two = module.is_num_and_eq_two; count_factors = module.count_factors; contains_single_blade = module.contains_single_blade; abs$1 = module.abs; is_factorial$1 = module.is_factorial; is_rat_and_fraction$1 = module.is_rat_and_fraction; convertMetricToNative = module.convertMetricToNative; convert_tensor_to_strings = module.convert_tensor_to_strings; create_algebra_as_tensor = module.create_algebra_as_tensor; predicate_return_value = module.predicate_return_value; prolog_eval_varargs = module.prolog_eval_varargs; float = module.float; is_safe_integer_range = module.is_safe_integer_range; is_opr_2_any_any = module.is_opr_2_any_any; exports("create_algebra_as_blades", module.create_algebra_as_blades); }, function (module) { is_atom = module.is_atom; nil = module.nil; is_nil = module.is_nil; is_cons = module.is_cons; cadr$1 = module.cadr; caddr$1 = module.caddr; cadnr = module.cadnr; items_to_cons = module.items_to_cons; cdr = module.cdr; car = module.car; cons = module.cons; assert_cons$1 = module.assert_cons; assert_U$1 = module.assert_U; assert_cons_or_nil$1 = module.assert_cons_or_nil; cddr$1 = module.cddr; cdddr = module.cdddr; caadr$1 = module.caadr; cadadr = module.cadadr; is_cons2 = module.is_cons2; cadddr$1 = module.cadddr; is_singleton = module.is_singleton; }, function (module) { Lambda = module.Lambda; SIGN_GT$1 = module.SIGN_GT; SIGN_LT$1 = module.SIGN_LT; SIGN_EQ$1 = module.SIGN_EQ; is_lambda = module.is_lambda; }, function (module) { Directive = module.Directive; }, function (module) { StackU = module.StackU; Stack = module.Stack; }, function (module) { scan_meta = module.scan_meta; }, function (module) { complexity = module.complexity; conjfunc = module.conjfunc; inner$1 = module.inner; push_rational = module.push_rational; power$1 = module.power; make_stack_draw = module.make_stack_draw; value_of = module.value_of; stopf = module.stopf; pop_integer = module.pop_integer; multiply$2 = module.multiply; expfunc = module.expfunc; add$2 = module.add; sqrtfunc = module.sqrtfunc; subtract$2 = module.subtract; negate$1 = module.negate; push_integer = module.push_integer; multiply_factors$1 = module.multiply_factors; power_e_expo = module.power_e_expo; stack_infix = module.stack_infix; stack_kronecker = module.stack_kronecker; stack_log = module.stack_log; stack_mag = module.stack_mag; stack_mod = module.stack_mod; stack_noexpand = module.stack_noexpand; stack_outer = module.stack_outer; stack_rank = module.stack_rank; stack_arccosh = module.stack_arccosh; stack_arcsin = module.stack_arcsin; stack_arcsinh = module.stack_arcsinh; stack_arctan = module.stack_arctan; stack_arctanh = module.stack_arctanh; stack_arg = module.stack_arg; stack_binding = module.stack_binding; stack_circexp = module.stack_circexp; stack_clock = module.stack_clock; stack_cos = module.stack_cos; stack_cosh = module.stack_cosh; stack_exp = module.stack_exp; stack_expcos = module.stack_expcos; stack_expcosh = module.stack_expcosh; stack_expsin = module.stack_expsin; stack_expsinh = module.stack_expsinh; stack_exptan = module.stack_exptan; stack_exptanh = module.stack_exptanh; stack_floor = module.stack_floor; stack_hadamard = module.stack_hadamard; stack_imag = module.stack_imag; stack_index = module.stack_index; stack_inv = module.stack_inv; stack_minor = module.stack_minor; stack_minormatrix = module.stack_minormatrix; stack_nroots = module.stack_nroots; stack_polar = module.stack_polar; stack_rationalize = module.stack_rationalize; stack_real = module.stack_real; stack_rect = module.stack_rect; stack_sin = module.stack_sin; stack_sinh = module.stack_sinh; stack_sqrt = module.stack_sqrt; stack_testlt = module.stack_testlt; stack_testge = module.stack_testge; stack_testgt = module.stack_testgt; stack_transpose = module.stack_transpose; stack_unit = module.stack_unit; }], execute: (function () { exports({ assert_sym: assert_sym, create_env: create_env, create_uom: create_uom, directive_from_flag: directive_from_flag, env_term: env_term, init_env: init_env, render_as_ascii: render_as_ascii, render_as_human: render_as_human, render_as_infix: render_as_infix, render_as_latex: render_as_latex, render_as_sexpr: render_as_sexpr, roots: roots, simplify: simplify$1, transform_tree: transform_tree }); const SIGN_LT = -1; const SIGN_EQ = 0; const SIGN_GT = 1; /** * The expression was ignored by the transformer, usually because it did not match the transformer. */ const TFLAG_NONE = 0; /** * The expression changed as a result of the transformation. */ const TFLAG_DIFF = 1 << 0; /** * The expression did not change as a result of the transformation because it is stable. */ const TFLAG_HALT = 1 << 1; /** * Returns true if flags has the "diff" bit set. */ function diffFlag(flags) { return (flags & TFLAG_DIFF) === TFLAG_DIFF; } const ALL_FEATURES = exports("ALL_FEATURES", ["Blade", "Boo", "Cell", "Flt", "Imu", "Map", "Rat", "Sym", "Tensor", "Uom"]); function directive_from_flag(value) { if (typeof value === "boolean") { return value ? 1 : 0; } else { return 0; } } const MODE_EXPANDING = 1; const MODE_FACTORING = 2; const MODE_SEQUENCE = [MODE_EXPANDING, MODE_FACTORING]; const MODE_FLAGS_ALL = MODE_EXPANDING | MODE_FACTORING; const PHASE_FLAGS_EXPANDING_UNION_FACTORING = MODE_EXPANDING | MODE_FACTORING; let Builder$k = class Builder { extension; constructor(extension) { this.extension = extension; } create(config) { return new this.extension(config); } }; function mkbuilder(extension) { return new Builder$k(extension); } /** * A convenience function for constructing transform results and peforming correct reference counting. * If the expressions are the same then we return the oldExpr (it may have better positional metadata), and TFLAG_NONE. * If the expressions differ, we return newExpr and TFLAG_DIFF. * */ function wrap_as_transform(newExpr, oldExpr) { if (newExpr.equals(oldExpr)) { // If the expressions have the same value, we return the oldExpr because it may have better meta information // such as pos and end properties. oldExpr.addRef(); return [TFLAG_NONE, oldExpr]; } else { newExpr.addRef(); return [TFLAG_DIFF, newExpr]; } } class ProgrammingError extends Error { constructor(message) { super(); this.name = "ProgrammingError"; if (typeof message === "string") { this.message = message; } } } /* eslint-disable @typescript-eslint/no-unused-vars */ class AtomExtensionFromExprHandler { handler; #type; #guard; constructor(handler, type, guard) { this.handler = handler; this.#type = type; this.#guard = guard; } get hash() { return this.#type; } get name() { return this.#type; } iscons() { return false; } operator() { throw new ProgrammingError(); } isKind(expr) { if (is_atom(expr)) { return this.#guard(expr); } else { return false; } } toHumanString(expr, $) { return str_to_string(this.handler.dispatch(expr, native_sym(Native.human), nil, $)); } toInfixString(expr, $) { return str_to_string(this.handler.dispatch(expr, native_sym(Native.infix), nil, $)); } toLatexString(expr, $) { return str_to_string(this.handler.dispatch(expr, native_sym(Native.latex), nil, $)); } toListString(expr, $) { return str_to_string(this.handler.dispatch(expr, native_sym(Native.sexpr), nil, $)); } evaluate(opr, argList, $) { throw new Error("evaluate method not implemented."); } transform(expr, env) { const newExpr = this.valueOf(expr, env); try { return wrap_as_transform(newExpr, expr); } finally { newExpr.release(); } } valueOf(expr, env) { return this.dispatch(expr, create_sym("valueof"), nil, env); } binL(lhs, opr, rhs, env) { return this.handler.binL(lhs, opr, rhs, env); } binR(rhs, opr, lhs, env) { return this.handler.binR(rhs, opr, lhs, env); } dispatch(target, opr, argList, env) { const response = this.handler.dispatch(target, opr, argList, env); if (is_nil(response)) { return diagnostic(Diagnostics.Property_0_does_not_exist_on_type_1, opr, create_sym(target.type)); } else { return response; } } subst(expr, oldExpr, newExpr, env) { throw new Error("subst method not implemented."); } test(expr, opr, env) { const response = this.handler.dispatch(expr, opr, nil, env); if (is_boo$1(response)) { return response.isTrue(); } else { throw diagnostic(Diagnostics.Property_0_does_not_exist_on_type_1, opr, create_sym(expr.type)); } } } class AtomExtensionBuilderFromExprHandlerBuilder { builder; type; guard; constructor(builder, type, guard) { this.builder = builder; this.type = type; this.guard = guard; } create(config) { return new AtomExtensionFromExprHandler(this.builder.create(), this.type, this.guard); } } exports("AtomExtensionBuilderFromExprHandlerBuilder", AtomExtensionBuilderFromExprHandlerBuilder); /** * */ class ExtensionFromExprHandler { handler; constructor(handler) { this.handler = handler; } get hash() { throw new Error("Method not implemented."); } get name() { throw new Error("Method not implemented."); } phases; dependencies; iscons() { throw new Error("Method not implemented."); } operator() { throw new Error("Method not implemented."); } isKind(expr, $) { throw new Error("Method not implemented."); } subst(expr, oldExpr, newExpr, $) { throw new Error("Method not implemented."); } toHumanString(expr, $) { throw new Error("Method not implemented."); } toInfixString(expr, $) { throw new Error("Method not implemented."); } toLatexString(expr, $) { throw new Error("Method not implemented."); } toListString(expr, $) { throw new Error("Method not implemented."); } evaluate(opr, argList, $) { throw new Error("Method not implemented."); } transform(expr, $) { throw new Error("Method not implemented."); } valueOf(expr, $) { throw new Error("Method not implemented."); } test(atom, opr, env) { return this.handler.test(atom, opr, env); } binL(lhs, opr, rhs, env) { return this.handler.binL(lhs, opr, rhs, env); } binR(rhs, opr, lhs, env) { return this.handler.binR(rhs, opr, lhs, env); } // eslint-disable-next-line @typescript-eslint/no-unused-vars dispatch(target, opr, argList, env) { return this.handler.dispatch(target, opr, argList, env); } } /** * Constructs a floating point number object from a number primitive. * @param value The floating point number value. * @param pos The start position of the number in the source text. * @param end The end position of the number in the source text. */ function create_flt(value, pos, end) { if (value === zeroAsFlt.d) { return zeroAsFlt; } if (value === oneAsFlt.d) { return oneAsFlt; } if (value === negOneAsFlt.d) { return negOneAsFlt; } if (value === twoAsFlt.d) { return twoAsFlt; } if (value === negTwoAsFlt.d) { return negTwoAsFlt; } // console.lg("wrap_as_flt", value); return new Flt(value, pos, end); } const zeroAsFlt = new Flt(0.0); const oneAsFlt = new Flt(1.0); const twoAsFlt = new Flt(2.0); const piAsFlt = new Flt(Math.PI); new Flt(1e-6); new Flt(Math.E); const negOneAsFlt = new Flt(-1.0); const negTwoAsFlt = new Flt(-2.0); // The canonical keys for various mathematical symbols. // These MUST be unique. // These MUST be stable over time. // Think of these as a universal standard identifying mathematical standards. // Implementations do not need to couple to this file, but they should use it as a standard. // TODO: Don't need to define functions; these are pluggable and should not be centrally defined. const MATH_ADD$1 = native_sym(Native.add); const MATH_COS = native_sym(Native.cos); const MATH_TAN = native_sym(Native.tan); native_sym(Native.subtract); const MATH_MUL$2 = native_sym(Native.multiply); native_sym(Native.divide); const MATH_POW$1 = native_sym(Native.pow); const MATH_OUTER = native_sym(Native.outer); const MATH_INNER = native_sym(Native.inner); const MATH_INV = native_sym(Native.inv); const MATH_LCO = native_sym(Native.lco); const MATH_RCO = native_sym(Native.rco); const MATH_SIN$1 = native_sym(Native.sin); native_sym(Native.succ); native_sym(Native.pred); native_sym(Native.E); const MATH_PI$1 = native_sym(Native.PI); const MATH_FACTORIAL = native_sym(Native.factorial); native_sym(Native.iszero); native_sym(Native.testlt); native_sym(Native.testgt); native_sym(Native.testle); /** * ':' */ create_sym(":"); /** * tau(x) = 2 * pi * x */ native_sym(Native.tau); const MATH_IMU$1 = native_sym(Native.IMU); // // WARNING This module should not depend on anything. // The imports below are for types only and will not create a dependency. // var PrintMode; (function (PrintMode) { /** * Two-dimensional rendering. */ PrintMode[PrintMode["Ascii"] = 0] = "Ascii"; /** * Like infix but with extra whitespace and may have multiplication operators removed. */ PrintMode[PrintMode["Human"] = 1] = "Human"; /** * Infix is how we normally write math but whitespace is removed and may be parsed by a computer. */ PrintMode[PrintMode["Infix"] = 2] = "Infix"; /** * MathJax compatible. */ PrintMode[PrintMode["LaTeX"] = 3] = "LaTeX"; /** * Symbolic Expression is LISP-like. */ PrintMode[PrintMode["SExpr"] = 4] = "SExpr"; PrintMode[PrintMode["EcmaScript"] = 5] = "EcmaScript"; })(PrintMode || (PrintMode = {})); class Defs { constructor() { // Nothing to see here yet. } /** * top of stack */ tos = 0; /** * The program execution stack. * TODO: This should be moved to the $ to achieve isolation of executions. * It should also not allow undefined and null values as this requires casting elsewhere. * Encapsulation with assertion may help. */ stack = []; } /** * Global (singleton) instance of Defs. */ const defs = new Defs(); /** * This should only be used for scripting when the stack is being used. * Otherwise, there should be a convenient way to throw structured Error(s). */ function halt(s) { move_top_of_stack(0); throw new Error(`Stop: ${s}`); } function move_top_of_stack(stackPos) { if (defs.tos <= stackPos) { // we are moving the stack pointer // "up" the stack (as if we were doing a push) defs.tos = stackPos; return; } // we are moving the stack pointer // "down" the stack i.e. as if we were // doing a pop, we can zero- // out all the elements that we pass // so we can reclaim the memory while (defs.tos > stackPos) { defs.stack[defs.tos] = null; defs.tos--; } } function noexpand_unary(func, arg, $) { $.pushDirective(Directive.expanding, 0); try { return func(arg, $); } finally { $.popDirective(); } } function noexpand_binary(func, lhs, rhs, $) { $.pushDirective(Directive.expanding, 0); try { return func(lhs, rhs, $); } finally { $.popDirective(); } } function doexpand_unary(func, arg, $) { $.pushDirective(Directive.expanding, 1); try { return func(arg, $); } finally { $.popDirective(); } } function doexpand_binary(func, lhs, rhs, $) { $.pushDirective(Directive.expanding, 1); try { return func(lhs, rhs, $); } finally { $.popDirective(); } } /** * */ class DynamicConstants { static NegOne($) { return $.getDirective(Directive.evaluatingAsFloat) ? negOneAsFlt : negOne; } static PI($) { return $.getDirective(Directive.evaluatingAsFloat) ? piAsFlt : MATH_PI$1; } } function length_of_cons_otherwise_zero(expr) { return is_cons(expr) ? [...expr].length : 0; } const do_simplify_nested_radicals = true; // TODO: Migrate to a situation of only creating these on demand by extensions. const ADD$9 = native_sym(Native.add); create_sym("adj"); create_sym("algebra"); const AND = create_sym("and"); const APPROXRATIO = create_sym("approxratio"); const ARCCOS$1 = create_sym("arccos"); const ARCCOSH = create_sym("arccosh"); const ARCSIN = create_sym("arcsin"); const ARCSINH = create_sym("arcsinh"); const ARCTAN = create_sym("arctan"); const ARCTANH = create_sym("arctanh"); create_sym("atomize"); const BESSELJ = create_sym("besselj"); const BESSELY = create_sym("bessely"); create_sym("binding"); const BINOMIAL = create_sym("binomial"); const CEILING = create_sym("ceiling"); const CHECK = create_sym("check"); const CHOOSE = create_sym("choose"); native_sym(Native.circexp); const CLEAR = create_sym("clear"); create_sym("clearall"); create_sym("clearpatterns"); const COEFF = create_sym("coeff"); create_sym("cofactor"); create_sym("compare"); create_sym("compare-factors"); create_sym("compare-terms"); const COMPONENT$2 = native_sym(Native.component); const CONDENSE = native_sym(Native.condense); const CONTRACT = create_sym("contract"); const COS$2 = MATH_COS; const COSH = create_sym("cosh"); create_sym("decomp"); const DEFINT = create_sym("defint"); create_sym("denominator"); const DET$1 = create_sym("det"); const DIM = create_sym("dim"); const DIRAC = create_sym("dirac"); create_sym("divide"); create_sym("divisors"); const DO = create_sym("do"); const DOT = create_sym("dot"); create_sym("draw"); create_sym("dsolve"); const EIGEN = create_sym("eigen"); const EIGENVAL = create_sym("eigenval"); const EIGENVEC = create_sym("eigenvec"); create_sym("equal"); const ERF = create_sym("erf"); const ERFC = create_sym("erfc"); /** * 'eval' */ const EVAL = create_sym("eval"); const EXP$3 = native_sym(Native.exp); const EXPAND$1 = native_sym(Native.expand); create_sym("expcos"); native_sym(Native.factor); const FACTORIAL = MATH_FACTORIAL; create_sym("factorpoly"); const FLOAT = native_sym(Native.float); const FLOOR = create_sym("floor"); /** * (fn [params*] expr*) */ const FN = native_sym(Native.fn); const FOR = create_sym("for"); /** * (Sym("function") body paramList) * * Notice that the syntax is different from ClojureScript, which is (fn params body), and params is a Tensor of symbols. */ const FUNCTION = native_sym(Native.function); const GAMMA = create_sym("gamma"); const GCD = native_sym(Native.gcd); const HERMITE = native_sym(Native.hermite); native_sym(Native.hilbert); create_sym("if"); const IMAG$1 = native_sym(Native.imag); native_sym(Native.inner); const INTEGRAL = native_sym(Native.integral); const INV$1 = MATH_INV; create_sym("invg"); create_sym("isinteger"); const ISPRIME = native_sym(Native.isprime); const LAGUERRE = create_sym("laguerre"); create_sym("laplace"); const LCM = create_sym("lcm"); native_sym(Native.lco); const LEGENDRE = create_sym("legendre"); const LET$1 = create_sym("let"); const LOG$1 = native_sym(Native.log); const MULTIPLY$2 = MATH_MUL$2; native_sym(Native.not); create_sym("nroots"); create_sym("number"); create_sym("numerator"); const OPERATOR = create_sym("operator"); const OR = create_sym("or"); native_sym(Native.outer); const PATTERN = create_sym("pattern"); native_sym(Native.polar); const POWER$2 = MATH_POW$1; const PRINT_LEAVE_E_ALONE = create_sym("printLeaveEAlone"); const PRINT_LEAVE_X_ALONE = create_sym("printLeaveXAlone"); create_sym("print"); const PRODUCT = create_sym("product"); const QUOTE = create_sym("quote"); create_sym("quotient"); const RANK = create_sym("rank"); native_sym(Native.rco); const REAL$1 = native_sym(Native.real); const ISREAL$3 = native_sym(Native.isreal); const ROUND$1 = create_sym("round"); native_sym(Native.rect); create_sym("roots"); const ASSIGN = native_sym(Native.assign); const SGN = create_sym("sgn"); const SIN = MATH_SIN$1; const SINH = create_sym("sinh"); create_sym("shape"); const SQRT$1 = create_sym("sqrt"); create_sym("stop"); native_sym(Native.subst); create_sym("-"); const SUM = create_sym("sum"); const TAN = MATH_TAN; const TANH = create_sym("tanh"); const TAYLOR = native_sym(Native.taylor); const TEST = native_sym(Native.test); const TESTGE = native_sym(Native.testge); const TESTGT = native_sym(Native.testgt); const TESTLE = native_sym(Native.testle); const TESTLT = native_sym(Native.testlt); const TRANSPOSE = create_sym("transpose"); const UNIT = create_sym("unit"); const UOM = create_sym("uom"); native_sym(Native.zero); create_sym("lastPrint"); create_sym("lastAsciiPrint"); create_sym("lastInfixPrint"); create_sym("lastLatexPrint"); create_sym("lastSexprPrint"); create_sym("lastHumanPrint"); create_sym("autoexpand"); create_sym("autofactor"); const BAKE = create_sym("bake"); create_sym("trace"); const METAA = create_sym("$METAA"); const METAB = create_sym("$METAB"); const METAX = create_sym("$METAX"); const SECRETX = create_sym("$SECRETX"); create_sym("version"); /** * 'a' */ create_sym("a"); create_sym("b"); create_sym("c"); /** * 'd' is commonly used for the derivative. */ const SYMBOL_D = create_sym("d"); const SYMBOL_I = create_sym("i"); const SYMBOL_J = create_sym("j"); create_sym("n"); create_sym("r"); const SYMBOL_S = create_sym("s"); const SYMBOL_T = create_sym("t"); /** * x */ const SYMBOL_X = create_sym("x"); const SYMBOL_Y = create_sym("y"); const SYMBOL_Z = create_sym("z"); const SYMBOL_IDENTITY_MATRIX = create_sym("I"); const SYMBOL_A_UNDERSCORE = create_sym("a_"); const SYMBOL_B_UNDERSCORE = create_sym("b_"); const SYMBOL_X_UNDERSCORE = create_sym("x_"); create_sym("$C1"); create_sym("$C2"); create_sym("$C3"); create_sym("$C4"); create_sym("$C5"); create_sym("$C6"); const MAXPRIMETAB = 10000; //define _USE_MATH_DEFINES // for MS C++ const MAXDIM = 24; const primetab = (function () { const primes = [2]; let i = 3; while (primes.length < MAXPRIMETAB) { let j = 0; const ceil = Math.sqrt(i); while (j < primes.length && primes[j] <= ceil) { if (i % primes[j] === 0) { j = -1; break; } j++; } if (j !== -1) { primes.push(i); } i += 2; } primes[MAXPRIMETAB] = 0; return primes; })(); function MSIGN(p) { if (p.isZero()) { return 0; } if (p.isPositive()) { return 1; } return -1; } /** * p.equals(n) */ function MEQUAL(p, n) { return p.equals(n); } // // TODO: In order not to torture our future selves, these should be documented and have coverage unit testing. // Maybe document the matching patterns? // Using block comments makes it possible to compose these with logical operators. // /** * The expression must be a Rat or Flt, otherwise the return value is false. * TODO: Interesting that this required expr > 0, when positive usually includes zero. * @param expr The expression being tested. */ function is_num_and_gt_zero(expr) { if (is_rat(expr)) { return MSIGN(expr.a) === 1; } else if (is_flt$1(expr)) { return expr.d > 0.0; } else { return false; } } /** * */ function is_num_and_eq_minus_one(p) { if (is_num$1(p)) { return p.isMinusOne(); } else { return false; } } /** * */ function is_plus_or_minus_one(x, $) { return isone$1(x, $) || is_num_and_eq_minus_one(x); } // -------------------------------------- function isunivarpolyfactoredorexpandedform(p, x) { // console.lg("isunivarpolyfactoredorexpandedform", `${p}`, `${x}`); if (x == null) { x = guess(p); } if (is_poly_factored_or_expanded_form(p, x) && countTrue(p.contains(SYMBOL_X), p.contains(SYMBOL_Y), p.contains(SYMBOL_Z)) === 1) { return x; } else { return false; } } function countTrue(...a) { // Number(true) = 1 return a.reduce((count, x) => count + Number(x), 0); } // -------------------------------------- // sometimes we want to check if we have a poly in our // hands, however it's in factored form and we don't // want to expand it. function is_poly_factored_or_expanded_form(p, x) { return is_poly_factored_or_expanded_form_factor(p, x); } function is_poly_factored_or_expanded_form_factor(p, x) { if (is_multiply$1(p)) { return p.tail().every((el) => { const bool = is_poly_factored_or_expanded_form_power(el, x); return bool; }); } else { return is_poly_factored_or_expanded_form_power(p, x); } } function is_poly_factored_or_expanded_form_power(p, x) { if (is_power$1(p)) { const base = p.base; const expo = p.expo; return is_rat(expo) && expo.isPositiveInteger() && is_poly_expanded_form_expr(base, x); } else { return is_poly_expanded_form_expr(p, x); } } // -------------------------------------- /** * Determines whether the expression, p, is a polynomial in the variable, x. */ function is_poly_expanded_form(p, x) { // console.lg(`is_poly_expanded_form ${print_expr(p, $)} ${x}`); if (p.contains(x)) { return is_poly_expanded_form_expr(p, x); } else { // If the expression does not contain the variable then it's a non-starter. return false; } } function is_poly_expanded_form_expr(p, x) { // console.lg(`is_poly_expanded_form_expr ${print_expr(p, $)} ${x}`); if (is_add$1(p)) { return p.tail().every((term) => is_poly_expanded_form_term(term, x)); } else { return is_poly_expanded_form_term(p, x); } } function is_poly_expanded_form_term(p, x) { // console.lg(`is_poly_expanded_form_term ${print_expr(p, $)} ${x}`); if (is_multiply$1(p)) { return p.tail().every((factor) => is_poly_expanded_form_factor(factor, x)); } else { return is_poly_expanded_form_factor(p, x); } } // eslint-disable-next-line @typescript-eslint/no-unused-vars function is_poly_expanded_form_factor(p, x) { // console.lg(`is_poly_expanded_form_factor ${print_expr(p, $)} ${x}`); if (p.equals(x)) { return true; } if (is_power$1(p) && p.base.equals(x)) { const expo = p.expo; return is_rat(expo) && expo.isPositiveInteger(); } if (p.contains(x)) { return false; } else { return true; } } function is_power_and_has_rational_exponent_and_negative_base(expr) { if (is_power$1(expr)) { const expo = expr.expo; if (is_rat(expo)) { if (is_num_and_negative(expr.base)) { return true; } } } return false; } function isimaginarynumberdouble(p, $) { return (is_multiply$1(p) && length_of_cons_otherwise_zero(p) === 3 && is_flt$1(cadnr(p, 1)) && is_power_and_has_rational_exponent_and_negative_base(cadnr(p, 2))) || $.equals(p, imu); } /** * (multiply Num i) */ function is_imaginary_number(expr) { if (is_multiply$1(expr)) { // (multiply a1 a2 a3 ...) if (length_of_cons_otherwise_zero(expr) === 3) { // (multiply x y) if (is_num$1(cadr$1(expr)) && caddr$1(expr).equals(imu)) { // (multiply Num i) return true; } if (expr.equals(imu)) { // Probbaly dead code because i => (pow -1 1/2), which isn't a (multiply ) return true; } if (is_power_and_has_rational_exponent_and_negative_base(caddr$1(expr))) { return true; } } } return false; } function iscomplexnumberdouble(p, $) { return (is_add$1(p) && length_of_cons_otherwise_zero(p) === 3 && is_flt$1(cadr$1(p)) && isimaginarynumberdouble(caddr$1(p), $)) || isimaginarynumberdouble(p, $); } /** * Determines whether expr is of the form (+ Num (something times i)) * For this to work it is crucial that the complex number terms be arranged with * the real part on the left hand side. e.g. 1.0 + 2.0*i. */ function is_complex_number(expr) { // console.lg(`is_complex_number ${render_as_sexpr(expr, $)}`); if (is_add$1(expr)) { // console.lg(`${$.toInfixString(expr)} is an add expression`); const n = length_of_cons_otherwise_zero(expr); // console.lg(`${$.toInfixString(expr)} n = ${n}`); if (n === 3) { const x = cadr$1(expr); // console.lg(`${$.toInfixString(expr)} X = ${$.toInfixString(X)}`); if (is_num$1(x)) { if (is_imaginary_number(caddr$1(expr)) || is_imaginary_number(expr)) { return true; } } } } return false; } function is_rat_and_even_integer(expr) { return is_rat_and_integer(expr) && expr.a.isEven(); } function isNumberOneOverSomething(p) { return is_rat(p) && p.isFraction() && MEQUAL(p.a.abs(), 1); } /** * */ function is_rat_and_fraction(p) { return is_rat(p) && p.isFraction(); } // p == -1/2 ? funct