Skip to content

Commit

Permalink
Trac #24440: Infinite loop from converting to QQbar
Browse files Browse the repository at this point in the history
{{{
sage: QQbar(tanh(pi + 0.1))

/home/ralf/sage/src/sage/structure/parent.pyx in
sage.structure.parent.Parent.__call__
(build/cythonized/sage/structure/parent.c:9406)()
    915         if mor is not None:
    916             if no_extra_args:
--> 917                 return mor._call_(x)
    918             else:
    919                 return mor._call_with_args(x, args, kwds)

/home/ralf/sage/src/sage/structure/coerce_maps.pyx in
sage.structure.coerce_maps.DefaultConvertMap_unique._call_
(build/cythonized/sage/structure/coerce_maps.c:4972)()
    153                 print(type(C), C)
    154                 print(type(C._element_constructor),
C._element_constructor)
--> 155             raise
    156
    157     cpdef Element _call_with_args(self, x, args=(), kwds={}):

/home/ralf/sage/src/sage/structure/coerce_maps.pyx in
sage.structure.coerce_maps.DefaultConvertMap_unique._call_
(build/cythonized/sage/structure/coerce_maps.c:4840)()
    148         cdef Parent C = self._codomain
    149         try:
--> 150             return C._element_constructor(x)
    151         except Exception:
    152             if print_warnings:

/home/ralf/sage/local/lib/python2.7/site-packages/sage/rings/qqbar.pyc
in _element_constructor_(self, x)
   1138             return AlgebraicNumber(x._descr)
   1139         elif hasattr(x, '_algebraic_'):
-> 1140             return x._algebraic_(QQbar)
   1141         return AlgebraicNumber(x)
   1142

/home/ralf/sage/src/sage/symbolic/expression.pyx in
sage.symbolic.expression.Expression._algebraic_
(build/cythonized/sage/symbolic/expression.cpp:12139)()
   1477         """
   1478         from sage.symbolic.expression_conversions import
algebraic
-> 1479         return algebraic(self, field)
   1480
   1481     def __hash__(self):

/home/ralf/sage/local/lib/python2.7/site-
packages/sage/symbolic/expression_conversions.pyc in algebraic(ex,
field)
   1046         0
   1047     """
-> 1048     return AlgebraicConverter(field)(ex)
   1049
   1050 ##############

/home/ralf/sage/local/lib/python2.7/site-
packages/sage/symbolic/expression_conversions.pyc in __call__(self, ex)
    224             return self.tuple(ex)
    225         else:
--> 226             return self.composition(ex, operator)
    227
    228     def get_fake_div(self, ex):

/home/ralf/sage/local/lib/python2.7/site-
packages/sage/symbolic/expression_conversions.pyc in composition(self,
ex, operator)
    987                 res = -QQbar.zeta(4)*(exp_ia - ~exp_ia)/(exp_ia
+ ~exp_ia)
    988         elif func_name in ['sinh', 'cosh', 'tanh']:
--> 989             exp_a = exp(operand)._algebraic_(QQbar)
    990             if func_name == 'sinh':
    991                 res = (exp_a - ~exp_a)/2

/home/ralf/sage/src/sage/symbolic/expression.pyx in
sage.symbolic.expression.Expression._algebraic_
(build/cythonized/sage/symbolic/expression.cpp:12139)()
   1477         """
   1478         from sage.symbolic.expression_conversions import
algebraic
-> 1479         return algebraic(self, field)
   1480
   1481     def __hash__(self):

/home/ralf/sage/local/lib/python2.7/site-
packages/sage/symbolic/expression_conversions.pyc in algebraic(ex,
field)
   1046         0
   1047     """
-> 1048     return AlgebraicConverter(field)(ex)
   1049
   1050 ##############

... last 6 frames repeated, from the frame below ...

/home/ralf/sage/local/lib/python2.7/site-
packages/sage/symbolic/expression_conversions.pyc in __call__(self, ex)
    216                 div = self.get_fake_div(ex)
    217                 return self.arithmetic(div, div.operator())
--> 218             return self.arithmetic(ex, operator)
    219         elif operator in relation_operators:
    220             return self.relation(ex, operator)

RuntimeError: maximum recursion depth exceeded in __instancecheck__
}}}
It seems that only `pi` as constant will trigger it.

URL: https://trac.sagemath.org/24440
Reported by: rws
Ticket author(s): Ralf Stephan
Reviewer(s): Sébastien Labbé
  • Loading branch information
Release Manager authored and vbraun committed May 5, 2018
2 parents f29aa2c + 39bfd96 commit eacca53
Showing 1 changed file with 26 additions and 4 deletions.
30 changes: 26 additions & 4 deletions src/sage/symbolic/expression_conversions.py
Original file line number Diff line number Diff line change
Expand Up @@ -956,13 +956,28 @@ def composition(self, ex, operator):
sage: a.composition(exp(pi*I*RR(1), hold=True), exp)
Traceback (most recent call last):
...
TypeError: no canonical coercion from Real Field with 53 bits of precision to Rational Field
TypeError: unable to convert e^(1.00000000000000*I*pi) to Algebraic Field
sage: a.composition(exp(pi*CC.gen(), hold=True), exp)
Traceback (most recent call last):
...
TypeError: no canonical coercion from Real Field with 53 bits of precision to Rational Field
TypeError: unable to convert e^(1.00000000000000*I*pi) to Algebraic Field
sage: bool(sin(pi*RR("0.7000000000000002")) > 0)
True
Check that :trac:`24440` is fixed::
sage: QQbar(tanh(pi + 0.1))
Traceback (most recent call last):
...
ValueError: unable to represent as an algebraic number
sage: QQbar(sin(I*pi/7))
Traceback (most recent call last):
...
ValueError: unable to represent as an algebraic number
sage: QQbar(sin(I*pi/7, hold=True))
Traceback (most recent call last):
...
ValueError: unable to represent as an algebraic number
"""
func = operator
operand, = ex.operands()
Expand All @@ -971,11 +986,16 @@ def composition(self, ex, operator):
# Note that comparing functions themselves goes via maxima, and is SLOW
func_name = repr(func)
if func_name == 'exp':
if operand.real():
if operand.is_trivial_zero():
return self.field(1)
if not (SR(-1).sqrt()*operand).is_real():
raise ValueError("unable to represent as an algebraic number")
# Coerce (not convert, see #22571) arg to a rational
arg = operand.imag()/(2*ex.parent().pi())
rat_arg = QQ.coerce(arg.pyobject())
try:
rat_arg = QQ.coerce(arg.pyobject())
except TypeError:
raise TypeError("unable to convert %r to %s"%(ex, self.field))
res = QQbar.zeta(rat_arg.denom())**rat_arg.numer()
elif func_name in ['sin', 'cos', 'tan']:
exp_ia = exp(SR(-1).sqrt()*operand)._algebraic_(QQbar)
Expand All @@ -986,6 +1006,8 @@ def composition(self, ex, operator):
else:
res = -QQbar.zeta(4)*(exp_ia - ~exp_ia)/(exp_ia + ~exp_ia)
elif func_name in ['sinh', 'cosh', 'tanh']:
if not (SR(-1).sqrt()*operand).is_real():
raise ValueError("unable to represent as an algebraic number")
exp_a = exp(operand)._algebraic_(QQbar)
if func_name == 'sinh':
res = (exp_a - ~exp_a)/2
Expand Down

0 comments on commit eacca53

Please sign in to comment.