You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 4-6.RSVP
Socket
Book a DemoInstallSign in
Socket

@cortex-js/compute-engine

Package Overview
Dependencies
Maintainers
1
Versions
51
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@cortex-js/compute-engine - npm Package Versions

13456

0.26.0

Diff
a
arnog
published 0.26.0 •

Changelog

Source

0.26.0 2024-10-01

Breaking Changes

  • The property expr.head has been deprecated. Use expr.operator instead. expr.head is still supported in this version but will be removed in a future update.

  • The MathJSON utility functions head() and op() have been renamed to operator() and operand() respectively.

  • The methods for algebraic operations (add, div, mul, etc...) have been moved from the Compute Engine to the Boxed Expression class. Instead of calling ce.add(a, b), call a.add(b).

    Those methods also behave more consistently: they apply some additional simplication rules over canonicalization. For example, while ce.parse('1 + 2') return ["Add", 1, 2], ce.box(1).add(2) will return 3.

  • The ce.numericMode option has been removed. Instead, set the ce.precision property to the desired precision. Set the precision to "machine" for machine precision calculations (about 15 digits). Set it to "auto" for a default of 21 digits. Set it to a number for a greater fixed precision.

  • The MathJSON Dictionary element has been deprecated. Use a Dictionary expression instead.

  • The ExtendedRealNumbers, ExtendedComplexNumbers domains have been deprecated. Use the RealNumbers and ComplexNumbers domains instead.

  • The "Domain" expression has been deprecated. Use types instead (see below).

  • Some BoxedExpression properties have been removed:

    • Instead of expr.isZero, use expr.is(0).
    • Instead of expr.isNotZero, use !expr.is(0).
    • Instead of expr.isOne, use expr.is(1).
    • Instead of expr.isNegativeOne, use expr.is(-1).
  • The signature of ce.declare() has changed. In particular, the N handler has been replaced with evaluate.

// Before
ce.declare('Mean', {
  N: (ce: IComputeEngine): BoxedExpression => {
    return ce.number(1);
  },
});

// Now
ce.declare('Mean', { evaluate: (ops, { engine }) => ce.number(1) });

New Features and Improvements

  • New Simplification Engine

    The way expressions are simplified has been completely rewritten. The new engine is more powerful and more flexible.

    The core API remains the same: to simplify an expression, use expr.simplify().

    To use a custom set of rules, pass the rules as an argument to simplify():

    expr.simplify({rules: [
      "|x:<0| -> -x",
      "|x:>=0| -> x",
    ]});
    

    There are a few changes to the way rules are represented. The priority property has been removed. Instead, rules are applied in the order in which they are defined.

    A rule can also now be a function that takes an expression and returns a new expression. For example:

    expr.simplify({rules: [
      (expr) => {
        if (expr.operator !== 'Abs') return undefined;
        const x = expr.args[0];
        return x.isNegative ? x.negate() : expr;
      }
    ]});
    

    This can be used to perform more complex transformations at the cost of more verbose JavaScript code.

    The algorithm for simplification has been simplified. It attempts to apply each rule in the rule set in turn, then restarts the process until no more rules can be applied or the result of applying a rule returns a previously seen expression.

    Function definitions previously included a simplify handler that could be used to perform simplifications specific to this function. This has been removed. Instead, use a rule that matches the function and returns the simplified expression.

  • Types

    Previously, an expression was associated with a domain such as RealNumbers or ComplexNumbers. This has been replaced with a more flexible system of types.

    A type is a set of values that an expression can take. For example, the type real is the set of real numbers, the type integer is the set of integers,

    The type of an expression can be set with the type property. For example:

    const expr = ce.parse('\\sqrt{-1}');
    console.info(expr.type); // -> imaginary
    

    The type of a symbol can be set when declaring the symbol. For example:

    ce.declare('x', 'imaginary');
    

    In addition to primitive types, the type system supports more complex types such union types, intersection types, and function types.

    For example, the type real|imaginary is the union of the real and imaginary numbers.

    When declaring a function, the type of the arguments and the return value can be specified. For example, to declare a function f that takes two integers and returns a real number:

    ce.declare('f', '(integer, integer) -> real');
    

    The sets of numbers are defined as follows:

    • number - any number, real or complex, including NaN and infinity
    • non_finite_number - NaN or infinity
    • real
    • finite_real - finite real numbers (exclude NaN and infinity)
    • imaginary - imaginary numbers (complex numbers with a real part of 0)
    • finite_imaginary
    • complex - complex numbers with a real and imaginary part not equal to 0
    • finite_complex
    • rational
    • finite_rational
    • integer
    • finite_integer

    To check the type of an expression, use the isSubtypeOf() method. For example:

    let expr = ce.parse('5');
    console.info(expr.type.isSubtypeOf('rational')); // -> true
    console.info(expr.type.isSubtypeOf('integer')); // -> true
    
    expr = ce.parse('\\frac{1}{2}');
    console.info(expr.type.isSubtypeOf('rational')); // -> true
    console.info(expr.type.isSubtypeOf('integer')); // -> false
    

    As a shortcut, the properties isReal, isRational, isInteger are available on boxed expressions. For example:

    let expr = ce.parse('5');
    console.info(expr.isInteger); // -> true
    console.info(expr.isRational); // -> true
    

    They are equivalent to expr.type.isSubtypeOf('integer') and expr.type.isSubtypeOf('rational') respectively.

    To check if a number has a non-zero imaginary part, use:

    let expr = ce.parse('5i');
    console.info(expr.isNumber && expr.isReal === false); // -> true
    
  • Collections

    Support for collections has been improved. Collections include List, Set, Tuple, Range, Interval, Linspace and Dictionary.

    It is now possible to check if an element is contained in a collection using an Element expression. For example:

    let expr = ce.parse('[1, 2, 3]');
    ce.box(['Element', 3, expr]).print(); // -> True
    ce.box(['Element', 5, expr]).print(); // -> False
    

    To check if a collection is a subset of another collection, use the Subset expression. For example:

    ce.box(['Subset', 'Integers', 'RealNumbers']).print(); // -> True
    

    Collections can also be compared for equality. For example:

    let set1 = ce.parse('\\lbrace 1, 2, 3 \\rbrace');
    let set2 = ce.parse('\\lbrace 3, 2, 1 \\rbrace');
    console.info(set1.isEqual(set2)); // -> true
    

    There are also additional convenience methods on boxed expressions:

    • expr.isCollection
    • expr.contains(element)
    • expr.size
    • expr.isSubsetOf(other)
    • expr.indexOf(element)
    • expr.at(index)
    • expr.each()
    • expr.get(key)
  • Exact calculations

    The Compute Engine has a new backed for numerical calculations. The new backed can handle arbitrary precision calculations, including real and complex numbers. It can also handle exact calculations, preserving calculations with rationals and radicals (square root of integers). For example 1/2 + 1/3 is evaluated to 5/6 instead of 0.8(3).

    To get an approximate result, use the N() method, for example ce.parse("\\frac12 + \\frac13").N().

    Previously the result of calculations was not always an exact number but returned a numerical approximation instead.

    This has now been improved by introducing a NumericValue type that encapsulates exact numbers and by doing all calculations in this type. Previously the calculations were handled manually in the various evaluation functions. This made the code complicated and error prone.

    A NumericValue is made of:

    • an imaginary part, represented as a fixed-precision number
    • a real part, represented either as a fixed or arbitrary precision number or as the product of a rational number and the square root of an integer.

    For example:

    • 234.567
    • 1/2
    • 3√5
    • √7/3
    • 4-3i

    While this is a significant change internally, the external API remains the same. The result of calculations should be more predictable and more accurate.

    One change to the public API is that the expr.numericValue property is now either a machine precision number or a NumericValue object.

  • Rule Wildcards

    When defining a rule as a LaTeX expression, single character identifiers are interpreted as wildcards. For example, the rule x + x -> 2x will match any expression with two identical terms. The wildcard corresponding to x is _x.

    It is now possible to define sequence wildcards and optional sequence wildcards. Sequence wildcards match 1 or more expressions, while optional sequence wildcards match 0 or more expressions.

    They are indicated in LaTeX as ...x and ...x? respectively. For example:

    expr.simplify("x + ...y -> 2x");
    

    If expr is a + b + c the rule will match and return 2a

    expr.simplify("x + ...y? -> 3x");
    

    If expr is a + b + c the rule will match and return 3a. If expr is a the rule will match and return 3a.

  • Conditional Rules

    Rules can now include conditions that are evaluated at runtime. If the condition is not satisfied, the rules does not apply.

    For example, to simplify the expression |x|:

    expr.simplify({rules: [
      "|x_{>=0}| -> x",
      "|x_{<0}| -> -x",
    ]});
    

    The condition is indicated as a subscript of the wildcard. The condition can be one of:

    • boolean - a boolean value, True or False

    • string - a string of characters

    • number - a number literal

    • symbol

    • expression

    • numeric - an expression that has a numeric value, i.e. 2√3, 1/2, 3.14

    • integer - an integer value, -2, -1, 0, 1, 2, 3, ...

    • natural - a natural number, 0, 1, 2, 3, ...

    • real - real numbers, including integers

    • imaginary - imaginary numbers, i.e. 2i, 3√-1 (not including real numbers)

    • complex - complex numbers, including real and imaginary

    • rational - rational numbers, 1/2, 3/4, 5/6, ...

    • irrational - irrational numbers, √2, √3, π, ...

    • algebraic - algebraic numbers, rational and irrational

    • transcendental - transcendental numbers, π, e, ...

    • positive - positive real numbers, > 0

    • negative - negative real numbers, < 0

    • nonnegative - nonnegative real numbers, >= 0

    • nonpositive - nonpositive real numbers, <= 0

    • even - even integers, 0, 2, 4, 6, ...

    • odd - odd integers, 1, 3, 5, 7, ...

    • prime :A000040 - prime numbers, 2, 3, 5, 7, 11, ...

    • composite :A002808 - composite numbers, 4, 6, 8, 9, 10, ...

    • notzero - a value that is not zero

    • notone - a value that is not one

    • finite - a finite value, not infinite

    • infinite

    • constant

    • variable

    • function

    • operator

    • relation - an equation or inequality

    • equation

    • inequality

    • vector - a tensor of rank 1

    • matrix - a tensor of rank 2

    • list - a collection of values

    • set - a collection of unique values

    • tuple - a fixed length list

    • single - a tuple of length 1

    • pair - a tuple of length 2

    • triple - a tuple of length 3

    • collection - a list, set, or tuple

    • tensor - a nested list of values of the same type

    • scalar - not a tensor or list

    or one of the following expressions:

    • >0' -> positive,
    • \gt0' -> positive,
    • <0' -> negative,
    • \lt0' -> negative,
    • >=0' -> nonnegative,
    • \geq0' -> nonnegative,
    • <=0' -> nonpositive,
    • \leq0' -> nonpositive,
    • !=0' -> notzero,
    • \neq0' -> notzero,
    • !=1' -> notone,
    • \neq1' -> notone,
    • \in\Z' -> integer,
    • \in\mathbb{Z}' -> integer,
    • \in\N' -> natural,
    • \in\mathbb{N}' -> natural,
    • \in\R' -> real,
    • \in\mathbb{R}' -> real,
    • \in\C' -> complex,
    • \in\mathbb{C}' -> complex,
    • \in\Q' -> rational,
    • \in\mathbb{Q}' -> rational,
    • \in\Z^+' -> integer,positive,
    • \in\Z^-' -> intger,negative,
    • \in\Z^*' -> nonzero,
    • \in\R^+' -> positive,
    • \in\R^-' -> negative,
    • \in\R^*' -> real,nonzero,
    • \in\N^*' -> integer,positive,
    • \in\N_0' -> integer,nonnegative,
    • \in\R\backslash\Q' -> irrational,

    More complex conditions can be specified following a semi-colon, for example:

    expr.simplify({x -> 2x; x < 10});
    

    Note that this syntax complements the existing rule syntax, and can be used together with the existing, more verbose, rule syntax.

    expr.simplify({rules: [
      {match: "x + x", replace: "2x", condition: "x < 10"}
    ]});
    

    This advanced syntax can specify more complex conditions, for example above the rule will only apply if x is less than 10.

  • Improved results for Expand. In some cases the expression was not fully expanded. For example, 4x(3x+2)-5(5x-4) now returns 12x^2 - 17x + 20. Previously it returned 4x(3x+2)+25x-20.

  • AsciiMath serialization The expr.toString() method now returns a serialization of the expression using the AsciiMath format.

    The serialization to AsciiMath can be customized using the toAsciiMath() method. For example:

    console.log(ce.box(['Sigma', 2]).toAsciiMath({functions: {Sigma: 'sigma'}}));
    // -> sigma(2)
    
  • The tolerance can now be specified with a value of "auto" which will use the precision to determine a reasonable tolerance. The tolerance is used when comparing two numbers for equality. The tolerance can be specified with the ce.tolerance property or in the Compute Engine constructor.

  • Boxed expressions have some additional properties:

    • expr.isNumberLiteral - true if the expression is a number literal.This is equivalent to checking if expr.numericValue is not null.
    • expr.re - the real part of the expression, if it is a number literal, undefined if not a number literal.
    • expr.im - the imaginary part of the expression, if it is a number literal, undefined if not a number literal.
    • expr.bignumRe - the real part of the expression as a bignum, if it is a number literal, undefined if not a number literal or a bignum representation is not available.
    • expr.bignumIm - the imaginary part of the expression as a bignum, if it is a number literal, undefined if not a number literal or if a bignum representation is not available.
    • expr.root() to get the root of the expression. For example, expr.root(3) will return the cube root of the expression.
    • Additionally, the relational operators (expr.isLess(), expr.isEqual(), etc...) now accept a number argument. For example, expr.isGreater(1) will return true if the expression is greater than 1.
  • Added LaTeX syntax to index collections. If a is a collection:

    • a[i] is parsed as ["At", "a", "i"].
    • a[i,j] is parsed as ["At", "a", "i", "j"].
    • a_i is parsed as ["At", "a", "i"].
    • a_{i,j} is parsed as ["At", "a", "i", "j"].
  • Added support for Kronecker delta notation, i.e. \delta_{ij}, which is parsed as ["KroneckerDelta", "i", "j"] and is equal to 1 if i = j and 0 otherwise.

    When a single index is provided the value of the function is 1 if the index is 0 and 0 otherwise

    When multiple index are provided, the value of the function is 1 if all the indexes are equal and 0 otherwise.

  • Added support for Iverson Bracket notation, i.e. [a = b], which is parsed as ["Boole", ["Equal", "a", "b"]] and is equal to 1 if its argument is true and 0 otherwise. The argument is expected to be a relational expression.

  • Implemented Unique and Tally on collections. Unique returns a collection with only the unique elements of the input collection, and Tally returns a collection with the count of each unique element.

    console.log(ce.box(['Unique', ['List', 1, 2, 3, 1, 2, 3, 4, 5]]).value);
    // -> [1, 2, 3, 4, 5]
    
    console.log(ce.box(['Tally', ['List', 1, 2, 3, 1, 2, 3, 4, 5]]).value);
    // -> [['List', 1, 2, 3, 4, 5], ['List', 2, 2, 2, 1, 1]]
    
  • Implemented the Map, Filter and Tabulate functions. These functions can be used to transform collections, for example:

    // Using LaTeX
    console.log(ce.parse('\\mathrm{Map}([3, 5, 7], x \\mapsto x^2)').toString());
    // -> [9, 25, 49]
    
    // Using boxed expressions
    console.log(
      ce.box(['Map', ['List', 3, 5, 7], ['Square', '_']]).value
    );
    // -> [9, 25, 49]
    
    console.log(ce.box(['Tabulate',['Square', '_'], 5]).value);
    // -> [1, 4, 9, 16, 25]
    

    Tabulate can be used with multiple indexes. For example, to generate a 4x4 unit matrix:

    console.log(ce.box(['Tabulate', ['If', ['Equal', '_1', '_2'], 1, 0]], 4, 4).value);
    // -> [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]
    
    // Using the Kronecker delta notation:
    console.log(ce.parse('\\mathrm{Tabulate}(i, j \\mapsto \\delta_{ij}, 4, 4)').value);
    // -> [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]
    
    
  • Added Random function. ["Random"] returns a real pseudo-random number betwen 0 and 1. ["Random", 10] returns an integer between 0 and 9, ["Random", 5, 10] returns an integer between 5 and 10.

  • Extended the definition of expr.isConstant. Previously, it only applied to symbols, e.g. Pi. Now it apply to all expressions. expr.isConstant is true if the expression is a number literal, a symbol with a constant value, or a pure function with constant arguments.

  • The boxed expression properties isPositive, isNegative, isNonNegative, isNonPositive, isZero, isNotZero now return a useful value for most function expressions. For example, ce.parse('|x + 1|').isPositive is true.

    If the value cannot be determined, the property will return undefined. For example, ce.parse('|x + 1|').isZero is undefined.

    If the expression is not a real number, the property will return NaN. For example, ce.parse('i').isPositive is NaN.

  • Added Choose function to compute binomial coefficients, i.e. Choose(5, 2) is equal to 10.

  • The fallback for non-constructible complex values of trigonometric functions is now implemented via rules.

  • The canonical order of the arguments has changed and should be more consistent and predictable. In particular, for polynomials, the monomial order is now degrevlex.

  • Canonical expressions can now include a Root expression. For example, the canonical form of \\sqrt[3]{5} is ["Root", 5, 3]. Previously, these were represented as ["Power", 5, ["Divide", 1, 3]].

  • The function definitions no longer have a N handler. Instead the evaluate handler has an optional {numericApproximation} argument.

Issues Resolved

  • #188 Throw an error when invalid expressions are boxed, for example ce.box(["Add", ["3"]]).

  • Some LaTeX renderer can't render \/, so use / instead.

  • When definitions are added to the LaTeX dictionary, they now take precedence over the built-in definitions. This allows users to override the built-in definitions.

  • Improved parsing of functions, including when a mixture of named and positional arguments are used.

  • #175 Matching some patterns when the target had not enough operands would result in a runtime error.

a
arnog
published 0.25.1 •

Changelog

Source

0.25.1 2024-06-27

Issues Resolved

  • #174 Fixed some simplifications, such as \frac{a^n}{a^m} = a^{n-m)

New Features

  • Rules can be defined using a new shorthand syntax, where each rule is a string of LaTeX:

    expr.simplify(["\\frac{x}{x} -> 1", "x + x -> 2x"]);
    

Single letter variables are assumed to be wildcards, so x is interpreted as the wildcard _x.

Additionally, the expanded form can also include LaTeX strings. The previous syntax using expressions can still be used, and the new and old syntax can be mixed.

For example:

expr.simplify([
  {
    match: "\\frac{x}{x}",
    replace: "1"
  },
  {
    match: ["Add", "x", "x"],
    replace: "2x"
  }
]);

The condition function can also be expressed as a LaTeX string.

  expr.simplify([ { match: "\\frac{x}{x}", replace: 1, condition: "x != 0" }, ]);

The shorthand syntax can be used any where a ruleset is expected, including with the ce.rule() function.

  • A new ce.getRuleSet() method gives access to the built-in rules.
  • #171 The Subtract and Divide function can now accept an arbitrary number of arguments. For example, ["Subtract", 1, 2, 3] is equivalent to ["Subtract", ["Subtract", 1, 2], 3].
a
arnog
published 0.25.0 •

Changelog

Source

0.25.0 2024-06-25

Breaking Changes

  • The canonical form of expressions has changed. It is now more consistent and simpler and should produce more predictable results.

    For example, previously ce.parse("1-x^2") would produce ["Subtract", 1, ["Square", "x"]].

    While this is a readable form, it introduces some complications when manipulating the expression: both the Subtract and Square functions have to be handled, in addition to Add and Power.

    The new canonical form of this expression is ["Add", 1, ["Negate", ["Power", "x", 2]]]. It is a bit more verbose, but it is simpler to manipulate.

  • The ce.serialize() method has been replaced with expr.toLatex() and expr.toMathJson(). The ce.latexOptions and ce.jsonSerializationOptions properties have been removed. Instead, pass the formating options directly to the toLatex() and toMathJson() methods. The ce.parse() method now takes an optional argument to specify the format of the input string.

  • The default JSON serialization of an expression has changed.

    Previously, the default JSON serialization, accessed via the .json property, had some transformations applied to it (sugaring) to make the JSON more human readable.

    For example, ce.parse("\frac12").json would return the symbol "Half" instead of ["Divide", 1, 2].

    However, this could lead to some confusion when manipulating the JSON directly. Since the JSON is intended to be used by machine more than humans, these additional transformations have been removed.

    The expr.json property now returns the JSON representing the expression, without any transformations.

    To get a version of JSON with some transformations applied use the ce.toMathJson() function.

    expr = ce.box(["Subtract", 1, ["Square", "x"]]);
    console.log(expr.json);
    // -> ["Add", 1, ["Negate", ["Power", "x", 2]]]
    expr.toMathJson()
    // -> ["Subtract", 1, ["Square", "x"]]
    expr.toMathJson({exclude: "Square"})
    // -> ["Subtract", 1, ["Power", "x", 2]]
    

    In practice, the impact of both of these changes should be minimal. If you were manipulating expressions using BoxedExpression, the new canonical form should make it easier to manipulate expressions. You can potentially simplify your code by removing special cases for functions such as Square and Subtract.

    If you were using the JSON serialization directly, you may also be able to simplify you code since the default output from expr.json is now more consistent and simpler.

  • The name of some number formatting options has changed. The number formatting options are an optional argument of ce.parse() and ce.toLatex(). See the NumberFormat and NumberSerializationFormat types.

  • The values +infinity, -infinity and NaN are now represented preferably with the symbols PositiveInfinity, NegativeInfinity and NaN respectively. Previously they were represented with numeric values, i.e. {num: "+Infinity"}, {num: "-Infinity"} and {num: "NaN"}. The numeric values are still supported, but the symbols are preferred.

  • The method expr.isNothing has been removed. Instead, use expr.symbol === "Nothing".

New Features

  • When serializing to LaTeX, the output can be "prettified". This involves modifying the LaTeX output to make it more pleasant to read, for example:

    • a+\\frac{-b}{c} -> a-\\frac{b}{c}
    • a\\times b^{-1} -> \\frac{a}{b}
    • \\frac{a}{b}\\frac{c}{d} -> \\frac{a\\cdot c}{b\\cdot d}
    • --2 -> 2

    This is on by default and can be turned off by setting the prettify option to false. For example:

    ce.parse("a+\\frac{-b}{c}").toLatex({prettify: true})
    // -> "a-\\frac{b}{c}"
    ce.parse("a+\\frac{-b}{c}").toLatex({prettify: false})
    // -> "a+\\frac{-b}{c}"
    
  • Numbers can have a different digit group length for the whole and fractional part of a number. For example, ce.toLatex(ce.parse("1234.5678"), {digitGroup: [3, 0]}) will return 1\,234.5678.

  • Numbers can now be formatted using South-East Asian Numbering System, i.e. lakh and crore. For example:

    ce.toLatex(ce.parse("12345678"), {digitGroup: "lakh"})
    // -> "1,23,45,678"
    
  • Expressions with Integrate functions can now be compiled to JavaScript. The compiled function can be used to evaluate the integral numerically. For example:

    const f = ce.parse("\\int_0^1 x^2 dx");
    const compiled = f.compile();
    console.log(compiled()); // -> 0.33232945619482307
    
  • #82 Support for angular units. The default is radians, but degrees can be used by setting ce.angularUnit = "deg". Other possible values are "grad" and "turn". This affects how unitless numbers with a trigonometric function are interpreted. For example, sin(90) will return 1 when ce.angularUnit is "deg", 0.8939966636005579 when ce.angularUnit is "grad" and 0 when ce.angularUnit is "turn".

  • Added expr.map(fn) method to apply a function to each subexpression of an expression. This can be useful to apply custom canonical forms and compare two expressions.

  • An optional canonical form can now be specified with the ce.function().

Issues Resolved

  • #173 Parsing 1++2 would result in an expression with a PreIncrement function. It is now correctly parsed as ["Add", 1, 2].
  • #161 Power expressions would not be processed when their argument was a Divide expression.
  • #165 More aggressive simplification of expressions with exponent greater than 3.
  • #169 Calculating a constant integral (and integral that did not depend on the variable) would result in a runtime error.
  • #164 Negative mixed fractions (e.g. -1\frac23) are now parsed correctly.
  • #162 Numeric evaluation of expressions with large exponents could result in machine precision numbers instead of bignum numbers.
  • #155 The expression ["Subtract", ["Multiply", 0.5, "x"], ["Divide", "x", 2]] will now evaluate to 0.
  • #154 In some cases, parsing implicit argument of trig function return more natural results, for example \cos a \sin b is now parsed as (\cos a)(\sin b) and not \cos (a \sin b).
  • #147 The associativity of some operators, including / was not applied correctly, resulting in unexpected results. For example, 1/2/3 would be parsed as ["Divide", 1, ["Divide", 2, 3]] instead of ["Divide", ["Divide", 1, 2], 3].
  • #146 When parsing an expression like x(x+1) where x is an undeclared symbol, do not infer that x is a function. Instead, infer that x is a variable and that the expression is a product.
  • #145 The expression ["Or", "False", "False"], that is when all the arguments are False, is now evaluates to False.
  • Fixed canonical form of e^x^2, and more generally apply power rule in more cases.
  • Added missing "Sech" and "Csch" functions.
  • The digit grouping serializing would place the separator in the wrong place for some numbers.
  • The avoidExponentsInRange formating option would not always avoid exponents in the specified range.
a
arnog
published 0.24.1 •
a
arnog
published 0.24.0 •

Changelog

Source

0.24.0 2024-02-23

Issues Resolved

  • Fix parsing of very deeply nested expressions.
  • Correctly apply rules to deeply nested expressions.
  • expr.print() now correctly prints the expression when using the minified version of the library.
  • expr.isEqual() now correctly compares equalities and inequalities.
  • expr.match() has been improved and works correctly in more cases. The signature of the match function has been changed so that the pattern is the first argument, i.e. instead of pattern.match(expr) use expr.match(pattern).
  • Fix expr.print() when using the minified version of the library.
  • #142 Accept complex expressions as the subcript of \ln and \log in LaTeX.
  • #139 Parse quantifiers \forall and \exists in LaTeX.
a
arnog
published 0.23.1 •

Changelog

Source

0.23.1 2024-01-27

Issues Resolved

  • Using a custom canonical order of "Multiply" would not distribute the Negate function.
  • #141 The canonical form "Order" was applied to non-commutative functions.
a
arnog
published 0.23.0 •

Changelog

Source

0.23.0 2024-01-01

New Features

  • Added ExpandAll function to expand an expression recursively.
  • Added Factor function to factor an expression.
  • Added Together function to combine rational expressions into a single fraction.

Issues Resolved

  • The expression \frac5 7 is now parsed correctly as \frac{5}{7} instead of \frac{5}{}7.
  • Do not sugar non-canonical expression. Previously, ce.parse('\\frac{1}{2}', {canonical: false}) would return Half instead of ['Divide', '1', '2'].
  • #132 Attempting to set a value to 0 with ce.defineSymbol("count", {value: 0}) would fail: the symbol would be undefined.
  • Correctly evaluate power expressions in some cases, for example (\sqrt2 + \sqrt2)^2.
  • Comparison of expressions containing non-exact numbers could fail. For example: 2(13.1+3.1x) and 26.2+6.2x would not be considered equal.

Improvements

  • Significant improvements to symbolic computation. Now, boxing, canonicalization and evaluation are more consistent and produce more predictable results.
  • Adedd the \neg command, synonym for \lnot -> Not.
  • Relational expressions (inequalities, etc...) are now properly factored.
  • Integers are now factored when simplifying, i.e. 2x = 4x -> x = 2x.
a
arnog
published 0.22.0 •

Changelog

Source

0.22.0 2023-11-13

Breaking Changes

  • Rule Syntax

    The syntax to describe rules has changed. The syntax for a rule was previously a tuple [lhs, rhs, {condition} ]. The new syntax is an object with the properties match, replace and condition. For example:

    • previous syntax: [["Add", "_x", "_x"], ["Multiply", 2, "_x"]]
    • new syntax: {match: ["Add", "_x", "_x"], replace: ["Multiply", 2, "_x"]}

    The condition property is optional, and is either a boxed function or a JavaScript function. For example, to add a condition that checks that _x is a number literal:

    {
      match: ["Add", "_x", "_x"],
      replace: ["Multiply", 2, "_x"],
      condition: ({_x}) => _x.isNumberLiteral
    }
    
  • CanonicalForm

    The CanonicalOrder function has been replaced by the more flexible CanonicalForm function. The CanonicalForm function takes an expression and a list of transformations to apply. To apply the same transformations as CanonicalOrder, use:

    ['CanonicalForm', expr, 'Order']
    

    These canonical forms can also be specified with box() and parse() options:

    ce.box(expr, { canonical: "Order" });
    ce.parse("x^2 + 2x + 1", { canonical: "Order" });
    

Work In Progress

  • Linear algebra functions: Rank, Shape,Reshape, Flatten, Determinant, Trace, Transpose, ConjugateTranspose, Inverse. See the Linear Algebra reference guide. Some of these function may not yet return correct result in all cases.

New Features

  • Added a expr.print() method as a synonym for console.log(expr.toString()).
  • Added an exact option (false by default) to the expr.match() pattern matching method. When true some additional patterns are automatically recognized, for example, x will match ["Multiply", '_a', 'x'] when exact is false, but not when exact is true.

Improvements

  • The equation solver used by expr.solve() has been improved and can now solve more equations.
  • The pattern matching engine has been improved and can now match more expressions, including sequences for commutative functions.
a
arnog
published 0.21.0 •

Changelog

Source

0.21.0 2023-11-02

New Features

  • #125 Parse and serialize environemnts, i.e. \begin{matrix} 1 & 2 \\ 3 & 4 \end{matrix} will be parsed as ["Matrix", ["List", ["List", 1, 2], ["List", 3, 4]]].

    A new section on Linear Algebra has some details on the supported formats.

    The linear algebra operations are limited at the moment, but will be expanded in the future.

  • Added IsSame function, which is the function expression corresponding to expr.isSame().

  • <s>Added CanonicalOrder function, which sorts the arguments of commutative functions into canonical order. This is useful to compare two non-canonical expressions for equality.</s>

ce.box(["CanonicalOrder", ["Add", 1, "x"]]).isSame(
  ce.box(["CanonicalOrder", ["Add", "x", 1]])
);
// -> true

Issue Resolved

  • When evaluating a sum (\sum) with a bound that is not a number, return the sum expression instead of an error.
a
arnog
published 0.20.2 •

Changelog

Source

0.20.2 2023-10-31

Issues Resolved

  • Fixed numerical evaluation of integrals and limits when parsed from LaTeX.
console.info(ce.parse("\\lim_{x \\to 0} \\frac{\\sin(x)}{x}").value);
// -> 1

console.info(ce.parse("\\int_{0}^{2} x^2 dx").value);
// -> 2.6666666666666665