Ticket #8659: trac_8659-hold_powers.take3.patch

File trac_8659-hold_powers.take3.patch, 6.5 KB (added by burcin, 8 years ago)
  • module_list.py

    # HG changeset patch
    # User Burcin Erocal <burcin@erocal.org>
    # Date 1329320725 -3600
    Trac 8659: remove sage.symbolic.power_helper in favor of hold=True
    
    sage.symbolic.power_helper module uses a hack to prevent running into infinite
    loops when evaluating powers like 2^(1/2). In these cases, the symbolics
    library would call the rational __pow__() method again when trying to simplify
    this expression further. Using the hold functionality merged in #9878, we can
    prevent automatic evalution of power expressions. Thus
    sage.symbolic.power_helper module is not needed any more.
    
    
    diff --git a/module_list.py b/module_list.py
    a b  
    17751775              depends = ginac_depends + numpy_depends,
    17761776              libraries = ["pynac", "gmp"]),
    17771777
    1778     Extension('sage.symbolic.power_helper',
    1779               sources = ['sage/symbolic/power_helper.pyx'],
    1780               depends = ginac_depends,
    1781               language = 'c++'),
    1782    
    17831778    Extension('sage.symbolic.pynac',
    17841779              sources = ['sage/symbolic/pynac.pyx'],
    17851780              language = 'c++',
  • sage/rings/number_field/number_field_element.pyx

    diff --git a/sage/rings/number_field/number_field_element.pyx b/sage/rings/number_field/number_field_element.pyx
    a b  
    5050from sage.libs.all import pari_gen, pari
    5151from sage.libs.pari.gen import PariError
    5252from sage.structure.element cimport Element, generic_power_c
    53 from sage.structure.element import canonical_coercion
     53from sage.structure.element import canonical_coercion, parent
    5454
    5555QQ = sage.rings.rational_field.QQ
    5656ZZ = sage.rings.integer_ring.ZZ
     
    16251625            cbase, cexp = canonical_coercion(base, exp)
    16261626            if not isinstance(cbase, NumberFieldElement):
    16271627                return cbase ** cexp
    1628             from sage.symbolic.power_helper import try_symbolic_power
     1628            # Return a symbolic expression.
     1629            # We use the hold=True keyword argument to prevent the
     1630            # symbolics library from trying to simplify this expression
     1631            # again. This would lead to infinite loops otherwise.
     1632            from sage.symbolic.ring import SR
    16291633            try:
    1630                 return try_symbolic_power(base, exp)
    1631             except ValueError:
    1632                 if isinstance(exp, Rational):
    1633                     # pynac can handle this case
    1634                     return None
    1635                 else:
    1636                     raise
    1637 
     1634                res = QQ(base)**exp
     1635            except TypeError:
     1636                pass
     1637            else:
     1638                if res.parent() is not SR:
     1639                    return parent(cbase)(res)
     1640                return res
     1641            sbase = SR(base)
     1642            if sbase.operator() is operator.pow:
     1643                nbase, pexp = sbase.operands()
     1644                return nbase.power(pexp * exp, hold=True)
     1645            else:
     1646                return sbase.power(exp, hold=True)
     1647           
    16381648    cdef void _reduce_c_(self):
    16391649        """
    16401650        Pull out common factors from the numerator and denominator!
  • sage/rings/rational.pyx

    diff --git a/sage/rings/rational.pyx b/sage/rings/rational.pyx
    a b  
    22252225            3/5*(-1)^(1/3)
    22262226            sage: (-27/125)^(1/2)
    22272227            3/5*sqrt(-3/5)
     2228
     2229        The result is normalized to have the rational power in the numerator::
     2230
     2231            sage: 2^(-1/2)
     2232            1/2*sqrt(2)
     2233            sage: 8^(-1/5)
     2234            1/8*8^(4/5)
     2235            sage: 3^(-3/2)
     2236            1/9*sqrt(3)
    22282237        """
    22292238        if dummy is not None:
    22302239            raise ValueError, "__pow__ dummy variable not used"
     
    22592268                    return c * I.pyobject() ** (n.numerator() % 4)
    22602269                elif c != 1:
    22612270                    return c * d**n
    2262                 # this is the only sensible answer that avoids rounding and
    2263                 # an infinite recursion.
    2264                 from sage.symbolic.power_helper import try_symbolic_power
    2265                 try:
    2266                     return try_symbolic_power(self, n)
    2267                 except ValueError:
    2268                     # pynac recognizes this and holds the value
    2269                     return None
     2271                # Can't simplify the power, return a symbolic expression.
     2272                # We use the hold=True keyword argument to prevent the
     2273                # symbolics library from trying to simplify this expression
     2274                # again. This would lead to infinite loops otherwise.
     2275                from sage.symbolic.ring import SR
     2276                if n < 0:
     2277                    int_exp = -(n.floor())
     2278                    return SR(1/self**int_exp)*\
     2279                            SR(self).power(int_exp+n, hold=True)
     2280                else:
     2281                    return SR(self).power(n, hold=True)
    22702282
    22712283            if PY_TYPE_CHECK(n, Element):
    22722284                return (<Element>n)._parent(self)**n
  • sage/symbolic/expression.pyx

    diff --git a/sage/symbolic/expression.pyx b/sage/symbolic/expression.pyx
    a b  
    26402640            sqrt(I)
    26412641            sage: I^(2/3)
    26422642            I^(2/3)
     2643
     2644        Test if we can take powers of elements of Q(i) #8659::
     2645
     2646            sage: t = I.pyobject().parent()(8)
     2647            sage: t^(1/2)
     2648            2*sqrt(2)
     2649            sage: (t^2)^(1/4)
     2650            2*4^(1/4)
    26432651        """
    26442652        cdef Expression base, nexp
    26452653
  • deleted file sage/symbolic/power_helper.pxd

    diff --git a/sage/symbolic/power_helper.pxd b/sage/symbolic/power_helper.pxd
    deleted file mode 100644
    + -  
    1 cpdef object try_symbolic_power(object o, object p)
  • deleted file sage/symbolic/power_helper.pyx

    diff --git a/sage/symbolic/power_helper.pyx b/sage/symbolic/power_helper.pyx
    deleted file mode 100644
    + -  
    1 import ring
    2 
    3 cdef bint __pynac_pow = False
    4 
    5 cpdef object try_symbolic_power(object obj, object p):
    6     """
    7     While evaluating powers, pynac calls Sage again to check if a fractional
    8     power is an exact root. This leads to infinite recursions and crashes.
    9     We use this hack to prevent an infinite recursion.
    10 
    11     TESTS::
    12        
    13         sage: 2^(1/2)
    14         sqrt(2)
    15         sage: (2*I)^(1/2)
    16         sqrt(2*I)
    17 
    18     """
    19     global __pynac_pow
    20     if __pynac_pow:
    21         __pynac_pow = False
    22         raise ValueError, "recursion"
    23     else:
    24         try:
    25             __pynac_pow = True
    26             return ring.SR(obj)**ring.SR(p)
    27         finally:
    28             __pynac_pow = False