svg_path_editor.math#

Attributes#

Classes#

Precision

Control numerical precision for mixed symbolic/numeric operations.

Functions#

canonical_decimal(x)

Normalize a Decimal to a canonical form.

dec_to_rat(x)

Convert a Decimal to a SymPy sympy.Rational.

rat_to_dec(x)

Convert a SymPy expression to Decimal with current precision.

as_bool(r)

Coerce a SymPy Boolean to builtin bool.

are_equal(a, b)

Test symbolic equality \(a = b\) using SymPy.

eq(a, b, *[, n])

Construct an (optionally relaxed) equality constraint \(a = b\).

le(a, b, *[, n])

Construct an (optionally relaxed) inequality \(a ≤ b\).

ge(a, b, *[, n])

Construct an (optionally relaxed) inequality \(a \ge b\).

lt(a, b, *[, n])

Construct an (optionally relaxed) strict inequality \(a < b\).

gt(a, b, *[, n])

Construct an (optionally relaxed) strict inequality \(a > b\).

is_zero(expr, *[, n])

Test whether an expression is zero.

subs(expr, subs, *[, n])

Substitute symbols in an expression, optionally with numeric evaluation.

evalf(expr, *, n)

Optionally evaluate an expression numerically.

_as_real_poly(poly, x)

Try to interpret poly as a univariate real polynomial in x.

cutoff_tiny(v[, n])

Replace numerically tiny floating values by exact zero.

quadratic_roots(a1, a0, *[, real_only, n])

Solve the monic quadratic equation

cubic_roots(a2, a1, a0, *[, real_only, n])

Solve the monic cubic equation

quartic_roots(a3, a2, a1, a0, *[, real_only, n])

Solve the monic quartic equation

polynomial_roots(poly, x, *[, real_only, n])

Compute roots of a univariate polynomial up to degree 4.

_sylvester_matrix(p, q)

Construct the Sylvester matrix of two polynomials \(p(x), q(x)\).

resultant(f, g, x, y[, n])

Resultant \(\operatorname{res}_y(f, g)\).

expand(expr)

Algebraically expand a SymPy expression.

Module Contents#

svg_path_editor.math.Number#
type svg_path_editor.math.Symbol = 'sp.Symbol'#
type svg_path_editor.math.Expr = 'sp.Expr'#
type svg_path_editor.math.Poly = 'sp.Poly'#
type svg_path_editor.math.Boolean = 'sp.logic.boolalg.Boolean'#
class svg_path_editor.math.Precision[source]#

Control numerical precision for mixed symbolic/numeric operations.

baseline defines the primary target precision, while additional can be used to carry extra guard digits during intermediate computations.

Variables:
  • baseline – Baseline number of significant digits.

  • additional – Additional guard digits to be used internally.

baseline: int#
additional: int#
property full: int#

Full number of significant digits to use.

Returns:

baseline + additional.

Return type:

int

svg_path_editor.math.canonical_decimal(x)[source]#

Normalize a Decimal to a canonical form.

Returns:

Decimal(0) for any zero value, otherwise x.normalize().

Parameters:

x (decimal.Decimal)

Return type:

decimal.Decimal

svg_path_editor.math.dec_to_rat(x)[source]#

Convert a Decimal to a SymPy sympy.Rational.

The conversion is exact with respect to the decimal representation: the Decimal is first converted to a string and then passed to sympy.Rational.

Parameters:

x (decimal.Decimal)

Return type:

Expr

svg_path_editor.math.rat_to_dec(x)[source]#

Convert a SymPy expression to Decimal with current precision.

The expression is evaluated numerically using sympy.Expr.evalf() with n = getcontext().prec and then converted to Decimal. The result is normalized via canonical_decimal().

Parameters:

x (Expr)

Return type:

decimal.Decimal

svg_path_editor.math.as_bool(r)[source]#

Coerce a SymPy Boolean to builtin bool.

Raises:

ValueError – If r cannot be simplified to a definite Boolean.

Parameters:

r (Boolean)

Return type:

bool

svg_path_editor.math.are_equal(a, b)[source]#

Test symbolic equality \(a = b\) using SymPy.

Returns:

True if SymPy proves a and b equal, otherwise False.

Raises:

ValueError – If the equality cannot be decided symbolically.

Parameters:
Return type:

bool

svg_path_editor.math.eq(a, b, *, n=None)[source]#

Construct an (optionally relaxed) equality constraint \(a = b\).

If n is None, an exact symbolic equality sympy.Eq is returned. Otherwise a relaxed inequality \(|a - b| < 10^{-\texttt{baseline}}\) is constructed.

Parameters:
Return type:

Boolean

svg_path_editor.math.le(a, b, *, n=None)[source]#

Construct an (optionally relaxed) inequality \(a ≤ b\).

If n is None, returns sympy.LessThan(a, b). Otherwise compares a with \(b + 10^{-\texttt{baseline}}\).

Parameters:
Return type:

Boolean

svg_path_editor.math.ge(a, b, *, n=None)[source]#

Construct an (optionally relaxed) inequality \(a \ge b\).

See le() for details.

Parameters:
Return type:

Boolean

svg_path_editor.math.lt(a, b, *, n=None)[source]#

Construct an (optionally relaxed) strict inequality \(a < b\).

If n is None, returns sympy.StrictLessThan(a, b). Otherwise compares a with \(b + 10^{-\texttt{baseline}}\).

Parameters:
Return type:

Boolean

svg_path_editor.math.gt(a, b, *, n=None)[source]#

Construct an (optionally relaxed) strict inequality \(a > b\).

See lt() for details.

Parameters:
Return type:

Boolean

svg_path_editor.math.is_zero(expr, *, n=None)[source]#

Test whether an expression is zero.

If n is None, use exact symbolic comparison expr == 0. Otherwise, evaluate numerically to n.full significant digits and test \(|\mathtt{expr}| ≤ 10^{-\texttt{baseline}}\).

Returns:

True if expr is considered zero, otherwise False.

Raises:

ValueError – If the exact symbolic comparison cannot be decided.

Parameters:
Return type:

bool

svg_path_editor.math.subs(expr, subs, *, n=None)[source]#

Substitute symbols in an expression, optionally with numeric evaluation.

If the expression contains floating-point numbers and n is not None, sympy.Expr.evalf() is used with the given precision and substitutions. Otherwise, standard symbolic substitution via sympy.Expr.subs() is performed.

Parameters:
  • expr (Expr) – Expression in which to perform substitutions.

  • subs (dict[Symbol, Expr]) – Mapping from symbols to replacement expressions.

  • n (Precision | None) – Optional precision for numerical evaluation.

Return type:

Expr

svg_path_editor.math.evalf(expr, *, n)[source]#

Optionally evaluate an expression numerically.

If n is None, return expr unchanged. Otherwise, return expr.evalf(n=n.full); if the imaginary part is at most \(10^{-\texttt{baseline}}\), the real part is returned.

Parameters:
Return type:

Expr

svg_path_editor.math._as_real_poly(poly, x)[source]#

Try to interpret poly as a univariate real polynomial in x.

Returns:

A sympy.Poly over a real domain, or None if this is not possible.

Parameters:
Return type:

Poly | None

svg_path_editor.math.cutoff_tiny(v, n=None)[source]#

Replace numerically tiny floating values by exact zero.

If v is a sympy.Float and is_zero(v, n=n) holds, sympy.S.Zero is returned, otherwise v is returned unchanged.

Parameters:
Return type:

Expr

svg_path_editor.math.quadratic_roots(a1, a0, *, real_only=True, n=None)[source]#

Solve the monic quadratic equation

\[z^2 + a_1 z + a_0 = 0\]

and return only the real roots if real_only=True (default).

The function implements the standard quadratic formula.

Parameters:
  • a1 (Expr) – Coefficient \(a_1\) of \(z\).

  • a0 (Expr) – Constant term \(a_0\).

  • real_only (bool) – If True, discard non-real roots.

  • n (Precision | None) – Optional precision used when classifying the discriminant as positive/non-negative via cutoff_tiny() and ge().

Returns:

A list of roots of \(z^2 + a_1 z + a_0 = 0\) sorted in nondecreasing order (if they are real).

svg_path_editor.math.cubic_roots(a2, a1, a0, *, real_only=True, n=None)[source]#

Solve the monic cubic equation

\[z^3 + a_2 z^2 + a_1 z + a_0 = 0\]

using the algorithm from https://quarticequations.com/Selected_Algorithms.pdf. Only the real roots are returned if real_only=True.

The algorithm follows the two main cases in the reference:

  • Case 1 (\(r^2 + q^3 > 0\)): one real root.

  • Case 2 (\(r^2 + q^3 ≤ 0\)): three real roots (Viète’s trigonometric form).

Parameters:
  • a2 (Expr) – Coefficient \(a_2\) of \(z^2\).

  • a1 (Expr) – Coefficient \(a_1\) of \(z\).

  • a0 (Expr) – Constant term \(a_0\).

  • real_only (bool) – If True, return only the real roots; otherwise all three (possibly complex) roots are returned.

  • n (Precision | None) – Optional precision used in is_zero(), gt(), eq(), and trigonometric evaluations.

Returns:

A list of roots of \(z^3 + a_2 z^2 + a_1 z + a_0 = 0\) sorted in nondecreasing order (if they are real).

Return type:

list[Expr]

svg_path_editor.math.quartic_roots(a3, a2, a1, a0, *, real_only=True, n=None)[source]#

Solve the monic quartic equation

\[z^4 + a_3 z^3 + a_2 z^2 + a_1 z + a_0 = 0\]

using the modified Euler algorithm of Wolters, as described in https://quarticequations.com/Selected_Algorithms.pdf.

Only real roots are returned if real_only=True.

The method uses the resolvent cubic

\[r^3 + \frac{b_2}{2}\,r^2 + \frac{b_2^2-4 b_0}{16}\,r - \frac{b_1^2}{64}=0,\]

whose three solutions \(r_1,r_2,r_3\) are obtained via cubic_roots(). The greatest real solution \(r_1\) with \(r_1 ≥ 0\) is then used to compute the four quartic roots.

Parameters:
  • a3 (Expr) – Coefficient \(a_3\) of \(z^3\).

  • a2 (Expr) – Coefficient \(a_2\) of \(z^2\).

  • a1 (Expr) – Coefficient \(a_1\) of \(z\).

  • a0 (Expr) – Constant term \(a_0\).

  • real_only (bool) – If True, discard complex roots derived from negative radicands.

  • n (Precision | None) – Optional precision used in the classification of real radicands via ge() and in cubic root computation.

Returns:

A list of real roots of \(z^4 + a_3 z^3 + a_2 z^2 + a_1 z + a_0 = 0\).

Return type:

list[Expr]

svg_path_editor.math.polynomial_roots(poly, x, *, real_only=True, n=None)[source]#

Compute roots of a univariate polynomial up to degree 4.

The input expression is converted to sympy.Poly in x and dispatched to the appropriate specialized solver:

The returned dictionary maps each root to its multiplicity using collections.Counter.

Parameters:
  • poly (Expr) – Polynomial expression in the variable x.

  • x (Symbol) – Polynomial variable.

  • real_only (bool) – If True, only real roots are produced by the specialized solvers.

  • n (Precision | None) – Optional precision forwarded to the root solvers.

Returns:

A mapping {root: multiplicity}.

Raises:

ValueError – If the polynomial degree is greater than 4 or for the identically zero polynomial (infinitely many solutions).

Return type:

dict[Expr, int]

svg_path_editor.math._sylvester_matrix(p, q)[source]#

Construct the Sylvester matrix of two polynomials \(p(x), q(x)\).

The input polynomials must be in the same variable and given as sympy.Poly instances. The resulting square matrix has size \((\deg(p) + \deg(q)) × (\deg(p) + \deg(q))\) and is constructed from shifted coefficient rows.

Parameters:
Return type:

sympy.Matrix

svg_path_editor.math.resultant(f, g, x, y, n=None)[source]#

Resultant \(\operatorname{res}_y(f, g)\).

Eliminates variable \(y\) from the system \(f(x, y) = 0\), \(g(x, y) = 0\).

If both expressions are real polynomials in \(y\), the resultant is computed as the determinant of the Sylvester matrix, then numerically evaluated with evalf() using precision n. Coefficients that are numerically zero (according to is_zero() with precision n) are normalized to exact zero.

Otherwise, sympy.resultant() is used.

Parameters:
Return type:

Expr

svg_path_editor.math.expand(expr)[source]#

Algebraically expand a SymPy expression.

Thin wrapper around sympy.expand().

Parameters:

expr (Expr)

Return type:

Expr