summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--polymatrix/expression/mixins/powerexprmixin.py53
1 files changed, 32 insertions, 21 deletions
diff --git a/polymatrix/expression/mixins/powerexprmixin.py b/polymatrix/expression/mixins/powerexprmixin.py
index ffc9d07..4ca1b0b 100644
--- a/polymatrix/expression/mixins/powerexprmixin.py
+++ b/polymatrix/expression/mixins/powerexprmixin.py
@@ -28,40 +28,51 @@ class PowerExprMixin(ExpressionBaseMixin):
@abstractmethod
def right(self) -> ExpressionBaseMixin | int | float: ...
- @override
- def apply(self, state: ExpressionStateMixin) -> tuple[ExpressionStateMixin, PolyMatrixMixin]:
+ @staticmethod
+ def power(
+ state: ExpressionStateMixin,
+ left: ExpressionBaseMixin,
+ right: ExpressionBaseMixin | int | float
+ ) -> tuple[ExpressionStateMixin, PolyMatrixMixin]:
+ """ Compute the expression ```left ** right```. """
exponent: int | None = None
# Right (exponent) must end up being a scalar constant
- if isinstance(self.right, int):
- exponent = self.right
+ if isinstance(right, int):
+ exponent = right
- elif isinstance(self.right, float):
- exponent = int(self.right)
- if not math.isclose(self.right - exponent, 0):
+ elif isinstance(right, float):
+ exponent = int(right)
+ if not math.isclose(right - exponent, 0):
raise ValueError("Cannot raise a variable to a non-integral power. "
- f"Exponent {self.right} (float) is not close enough to an integer.")
+ f"Exponent {right} (float) is not close enough to an integer.")
- elif isinstance(self.right, ExpressionBaseMixin):
- state, right_polymatrix = self.right.apply(state)
- right = right_polymatrix.at(0, 0).constant()
+ elif isinstance(right, ExpressionBaseMixin):
+ state, right_polymatrix = right.apply(state)
- if not isinstance(right, int):
- exponent = int(right)
- if not math.isclose(right - exponent, 0):
+ r = right_polymatrix.at(0, 0).constant()
+ if not isinstance(r, int):
+ exponent = int(r)
+ if not math.isclose(r - exponent, 0):
raise ValueError("Cannot raise a variable to a non-integral power. "
- f"Exponent {right}, resulting from {self.right} is not an integer.")
+ f"Exponent {right}, resulting from {right} is not an integer.")
else:
- exponent = right
+ exponent = r
else:
- raise TypeError(f"Cannot raise {self.left} to {self.right}, ",
- f"because exponet has type {type(self.right)}")
+ raise TypeError(f"Cannot raise {left} to {right}, ",
+ f"because exponet has type {type(right)}")
- state, left = self.left.apply(state)
- result = left
+ state, base = left.apply(state)
+ result = base
for _ in range(exponent -1):
- state, result = ElemMultExprMixin.elem_mult(state, result, left)
+ state, result = ElemMultExprMixin.elem_mult(state, result, base)
return state, result
+ @override
+ def apply(self, state: ExpressionStateMixin) -> tuple[ExpressionStateMixin, PolyMatrixMixin]:
+ # Separated into staticmethod like elem_mult for code resuse in
+ # CombinationsExprMixin
+ return self.power(state, self.left, self.right)
+