@@ -256,6 +256,13 @@ def eval_Sign(expr: BaseElement) -> Optional[BaseElement]:
256256 """
257257 if expr is a number, return its sign.
258258 """
259+ sympy_expr = expr .to_sympy ()
260+ if sympy_expr is not None :
261+ print (" sympy_expr" , sympy_expr )
262+ result = from_sympy (sympy .sign (sympy_expr ))
263+ if result is not None :
264+ return result
265+ return None
259266
260267 def eval_complex_sign (n : BaseElement ) -> Optional [BaseElement ]:
261268 if isinstance (n , Complex ):
@@ -694,36 +701,6 @@ def eval_Times(*items: BaseElement) -> BaseElement:
694701 )
695702
696703
697- # Here I used the convention of calling eval_* to functions that can produce a new expression, or None
698- # if the result can not be evaluated, or is trivial. For example, if we call eval_Power_number(Integer2, RationalOneHalf)
699- # it returns ``None`` instead of ``Expression(SymbolPower, Integer2, RationalOneHalf)``.
700- # The reason is that these functions are written to be part of replacement rules, to be applied during the evaluation process.
701- # In that process, a rule is considered applied if produces an expression that is different from the original one, or
702- # if the replacement function returns (Python's) ``None``.
703- #
704- # For example, when the expression ``Power[4, 1/2]`` is evaluated, a (Builtin) rule ``Power[base_, exp_]->eval_repl_rule(base, expr)``
705- # is applied. If the rule matches, `repl_rule` is called with arguments ``(4, 1/2)`` and produces `2`. As `Integer2.sameQ(Power[4, 1/2])`
706- # is False, then no new rules for `Power` are checked, and a new round of evaluation is atempted.
707- #
708- # On the other hand, if ``Power[3, 1/2]``, ``repl_rule`` can do two possible things: one is return ``Power[3, 1/2]``. If it does,
709- # the rule is considered applied. Then, the evaluation method checks if `Power[3, 1/2].sameQ(Power[3, 1/2])`. In this case it is true,
710- # and then the expression is kept as it is.
711- # The other possibility is to return (Python's) `None`. In that case, the evaluator considers that the rule failed to be applied,
712- # and look for another rule associated to ``Power``. To return ``None`` produces then a faster evaluation, since no ``sameQ`` call is needed,
713- # and do not prevent that other rules are attempted.
714- #
715- # The bad part of using ``None`` as a return is that I would expect that ``eval`` produces always a valid Expression, so if at some point of
716- # the code I call ``eval_Power_number(Integer3, RationalOneHalf)`` I get ``Expression(SymbolPower, Integer3, RationalOneHalf)``.
717- #
718- # From my point of view, it would make more sense to use the following convention:
719- # * if the method has signature ``eval_method(...)->BaseElement:`` then use the prefix ``eval_``
720- # * if the method has the siguature ``apply_method(...)->Optional[BaseElement]`` use the prefix ``apply_`` or maybe ``repl_``.
721- #
722- # In any case, let's keep the current convention.
723- #
724- #
725-
726-
727704def associate_powers (expr : BaseElement , power : BaseElement = Integer1 ) -> BaseElement :
728705 """
729706 base^a^b^c^...^power -> base^(a*b*c*...power)
0 commit comments