diff options
Diffstat (limited to 'polymatrix/expression/mixins/legendreseriesmixin.py')
-rw-r--r-- | polymatrix/expression/mixins/legendreseriesmixin.py | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/polymatrix/expression/mixins/legendreseriesmixin.py b/polymatrix/expression/mixins/legendreseriesmixin.py new file mode 100644 index 0000000..3232207 --- /dev/null +++ b/polymatrix/expression/mixins/legendreseriesmixin.py @@ -0,0 +1,62 @@ +import abc + +from polymatrix.utils.getstacklines import FrameSummary +from polymatrix.polymatrix.polymatrix import PolyMatrix +from polymatrix.polymatrix.init.initpolymatrix import init_poly_matrix +from polymatrix.expressionstate.expressionstate import ExpressionState +from polymatrix.expression.mixins.expressionbasemixin import ExpressionBaseMixin + + +class LegendreSeriesMixin(ExpressionBaseMixin): + @property + @abc.abstractmethod + def underlying(self) -> tuple[ExpressionBaseMixin]: + ... + + @property + @abc.abstractmethod + def degrees(self) -> tuple[int, ...] | None: + ... + + @property + @abc.abstractmethod + def stack(self) -> tuple[FrameSummary]: + ... + + # overwrites abstract method of `ExpressionBaseMixin` + def apply( + self, + state: ExpressionState, + ) -> tuple[ExpressionState, PolyMatrix]: + + state, underlying = self.underlying.apply(state) + + if self.degrees is None: + degrees = range(underlying.shape[0]) + else: + degrees = self.degrees + + terms = {} + + for degree in degrees: + # for degree in self.degree: + poly = underlying.get_poly(degree, 0) + + terms[degree, 0] = dict(poly) + + if 2 <= degree: + poly = underlying.get_poly(degree - 2, 0) + factor = - (degree - 1) / (degree + 1) + + for m, v in poly.items(): + if m in terms[degree, 0]: + terms[degree, 0][m] += v*factor + else: + terms[degree, 0][m] = v*factor + + poly_matrix = init_poly_matrix( + terms=terms, + shape=(len(terms), 1), + ) + + return state, poly_matrix |