Source code for pyecsca.ec.formula.unroll

from typing import List, Tuple

from astunparse import unparse
from public import public
from sympy import Expr, symbols, Poly
from ...misc.cache import sympify

from .base import Formula


[docs] @public def unroll_formula_expr(formula: Formula) -> List[Tuple[str, Expr]]: """ Unroll a given formula symbolically to obtain symbolic expressions for its intermediate values. :param formula: Formula to unroll. :return: List of symbolic intermediate values, with associated variable names. """ params = { var: symbols(var) for var in formula.coordinate_model.curve_model.parameter_names } inputs = { f"{var}{i}": symbols(f"{var}{i}") for var in formula.coordinate_model.variables for i in range(1, formula.num_inputs + 1) } for coord_assumption in formula.coordinate_model.assumptions: assumption_string = unparse(coord_assumption).strip() lhs, rhs = assumption_string.split(" = ") if lhs in params: expr = sympify(rhs, evaluate=False) params[lhs] = expr for assumption_string in formula.assumptions_str: lhs, rhs = assumption_string.split(" == ") if lhs in formula.parameters: # Handle a symbolic assignment to a new parameter. expr = sympify(rhs, evaluate=False) for curve_param, value in params.items(): expr = expr.subs(curve_param, value) params[lhs] = expr locls = {**params, **inputs} values: List[Tuple[str, Expr]] = [] for op in formula.code: result: Expr = op(**locls) # type: ignore locls[op.result] = result values.append((op.result, result)) return values
[docs] @public def unroll_formula(formula: Formula) -> List[Tuple[str, Poly]]: """ Unroll a given formula symbolically to obtain symbolic expressions (as Polynomials) for its intermediate values. :param formula: Formula to unroll. :return: List of symbolic intermediate values, with associated variable names. """ values = unroll_formula_expr(formula) polys = [] for name, result in values: if result.free_symbols: gens = list(result.free_symbols) gens.sort(key=str) poly = Poly(result, *gens) polys.append((name, poly)) else: # TODO: We cannot create a Poly here, because the result does not have free symbols (i.e. it is a constant) pass return polys