diff options
Diffstat (limited to 'pyecsca')
| -rw-r--r-- | pyecsca/ec/formula.py | 35 | ||||
| -rw-r--r-- | pyecsca/ec/op.py | 34 |
2 files changed, 63 insertions, 6 deletions
diff --git a/pyecsca/ec/formula.py b/pyecsca/ec/formula.py index f80e9fa..5f4c7cb 100644 --- a/pyecsca/ec/formula.py +++ b/pyecsca/ec/formula.py @@ -1,5 +1,6 @@ from ast import parse, Expression -from typing import List, Any, ClassVar, MutableMapping +from typing import List, Set, Any, ClassVar, MutableMapping +from itertools import product from pkg_resources import resource_stream from public import public @@ -22,10 +23,22 @@ class Formula(object): return f"{self.__class__.__name__}({self.name} for {self.coordinate_model})" @property - def output_index(cls): + def input_index(self): + raise NotImplementedError + + @property + def output_index(self) -> int: """The starting index where this formula stores its outputs.""" raise NotImplementedError + @property + def inputs(self) -> Set[str]: + raise NotImplementedError + + @property + def outputs(self) -> Set[str]: + raise NotImplementedError + class EFDFormula(Formula): @@ -60,8 +73,22 @@ class EFDFormula(Formula): self.code.append(CodeOp(code_module)) @property - def output_index(cls): - return max(cls.num_inputs + 1, 3) + def input_index(self): + return 1 + + @property + def output_index(self): + return max(self.num_inputs + 1, 3) + + @property + def inputs(self): + return set(var + str(i) for var, i in product(self.coordinate_model.variables, + range(1, 1 + self.num_inputs))) + + @property + def outputs(self): + return set(var + str(i) for var, i in product(self.coordinate_model.variables, + range(self.output_index, self.output_index + self.num_outputs))) def __eq__(self, other): if not isinstance(other, EFDFormula): diff --git a/pyecsca/ec/op.py b/pyecsca/ec/op.py index 169f3bb..11c3079 100644 --- a/pyecsca/ec/op.py +++ b/pyecsca/ec/op.py @@ -1,4 +1,4 @@ -from ast import Module, walk, Name, BinOp, operator +from ast import Module, walk, Name, BinOp, Constant, operator, Mult, Div, Add, Sub, Pow from types import CodeType from typing import FrozenSet, Optional @@ -26,6 +26,7 @@ class CodeOp(Op): self.result = assign.targets[0].id params = set() variables = set() + constants = set() op = None for node in walk(assign.value): if isinstance(node, Name): @@ -34,15 +35,44 @@ class CodeOp(Op): variables.add(name) else: params.add(name) + elif isinstance(node, Constant): + constants.add(node.value) elif isinstance(node, BinOp): op = node.op + self.left = self.__to_name(node.left) + self.right = self.__to_name(node.right) self.operator = op self.parameters = frozenset(params) self.variables = frozenset(variables) + self.constants = frozenset(constants) self.compiled = compile(self.code, "", mode="exec") + def __to_name(self, node): + if isinstance(node, Name): + return node.id + elif isinstance(node, Constant): + return node.value + else: + return None + + def __to_opsymbol(self, op): + if isinstance(op, Mult): + return "*" + elif isinstance(op, Div): + return "/" + elif isinstance(op, Add): + return "+" + elif isinstance(op, Sub): + return "-" + elif isinstance(op, Pow): + return "^" + return "" + + def __str__(self): + return f"{self.result} = {self.left}{self.__to_opsymbol(self.operator)}{self.right}" + def __repr__(self): - return f"CodeOp({self.result} = f(params={self.parameters}, vars={self.variables}))" + return f"CodeOp({self.result} = f(params={self.parameters}, vars={self.variables}, consts={self.constants}))" def __call__(self, *args, **kwargs: Mod) -> Mod: loc = dict(kwargs) |
