Ticket #8659: trac_8659-hold_powers.patch

File trac_8659-hold_powers.patch, 5.5 KB (added by burcin, 9 years ago)
  • module_list.py

    # HG changeset patch
    # User Burcin Erocal <burcin@erocal.org>
    # Date 1300828691 -3600
    # Node ID c9842deaf06154f189011b678cccbfe76f7b8c92
    # Parent  cb6b2c489f63cb74689a231753c75c23f4f405da
    trac 8659: use the new hold parameter when creating power expressions in the symbolic ring.
    
    We used a hack in the sage.symbolic.power_helper module 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  
    16561656              depends = ginac_depends + numpy_depends,
    16571657              libraries = ["pynac", "gmp"]),
    16581658
    1659     Extension('sage.symbolic.power_helper',
    1660               sources = ['sage/symbolic/power_helper.pyx'],
    1661               depends = ginac_depends,
    1662               language = 'c++'),
    1663    
    16641659    Extension('sage.symbolic.pynac',
    16651660              sources = ['sage/symbolic/pynac.pyx'],
    16661661              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  
    12821282            (PY_TYPE_CHECK(exp, Integer) or PY_TYPE_CHECK_EXACT(exp, int) or exp in ZZ)):
    12831283            return generic_power_c(base, exp, None)
    12841284        else:
    1285             from sage.symbolic.power_helper import try_symbolic_power
    1286             return try_symbolic_power(base, exp)
     1285            # Return a symbolic expression.
     1286            # We use the hold=True keyword argument to prevent the
     1287            # symbolics library from trying to simplify this expression
     1288            # again. This would lead to infite loops otherwise.
     1289            from sage.symbolic.ring import SR
     1290            import operator
     1291            sbase = SR(base)
     1292            if sbase.operator() is operator.pow:
     1293                nbase, nexp = sbase.operands()
     1294                return SR(nbase).power(nexp*exp, hold=True)
     1295            else:
     1296                return SR(base).power(exp, hold=True)
    12871297
    12881298    cdef void _reduce_c_(self):
    12891299        """
  • sage/rings/rational.pyx

    diff --git a/sage/rings/rational.pyx b/sage/rings/rational.pyx
    a b  
    20652065            3/5*(-1)^(1/3)
    20662066            sage: (-27/125)^(1/2)
    20672067            3/5*sqrt(-3/5)
     2068
     2069        The result is normalized to have the rational power in the numerator::
     2070
     2071            sage: 2^(-1/2)
     2072            1/2*sqrt(2)
     2073            sage: 8^(-1/5)
     2074            1/8*8^(4/5)
    20682075        """
    20692076        if dummy is not None:
    20702077            raise ValueError, "__pow__ dummy variable not used"
     
    20992106                    return c * I.pyobject() ** (n.numerator() % 4)
    21002107                elif c != 1:
    21012108                    return c * d**n
    2102                 # this is the only sensible answer that avoids rounding and
    2103                 # an infinite recursion.
    2104                 from sage.symbolic.power_helper import try_symbolic_power
    2105                 return try_symbolic_power(self, n)
     2109                # Can't simplify the power, return a symbolic expression.
     2110                # We use the hold=True keyword argument to prevent the
     2111                # symbolics library from trying to simplify this expression
     2112                # again. This would lead to infite loops otherwise.
     2113                from sage.symbolic.ring import SR
     2114                if n < 0:
     2115                    return SR(1/self)*SR(self).power(1+n, hold=True)
     2116                else:
     2117                    return SR(self).power(n, hold=True)
    21062118
    21072119            if PY_TYPE_CHECK(n, Element):
    21082120                return (<Element>n)._parent(self)**n
  • sage/symbolic/expression.pyx

    diff --git a/sage/symbolic/expression.pyx b/sage/symbolic/expression.pyx
    a b  
    24492449            2.2999999999999998^(x^3 - x^2 + 1/3)
    24502450            sage: complex(1,3)^(sqrt(2))
    24512451            (1+3j)^sqrt(2)
     2452
     2453        Test if we can take powers of elements of Q(i) #8659::
     2454
     2455            sage: t = I.pyobject().parent()(8)
     2456            sage: t^(1/2)
     2457            sqrt(8)
     2458            sage: (t^2)^(1/4)
     2459            64^(1/4)
    24522460        """
    24532461        cdef Expression base, nexp
    24542462       
  • 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         return None
    23     else:
    24         try:
    25             __pynac_pow = True
    26             return ring.SR(obj)**ring.SR(p)
    27         finally:
    28             __pynac_pow = False