Ticket #8659: trac_8659-hold_powers.take4.patch

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

    # HG changeset patch
    # User Burcin Erocal <burcin@erocal.org>
    # Date 1329320725 -3600
    # Node ID 3e275d71d7185cdd52f3aea91bd45211c59e70d4
    # Parent  d10815c1cbe2c7c6390f32690da18a821c9f1789
    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  
    18171817              depends = ginac_depends + numpy_depends,
    18181818              libraries = ["pynac", "gmp"]),
    18191819
    1820     Extension('sage.symbolic.power_helper',
    1821               sources = ['sage/symbolic/power_helper.pyx'],
    1822               depends = ginac_depends,
    1823               language = 'c++'),
    1824    
    18251820    Extension('sage.symbolic.pynac',
    18261821              sources = ['sage/symbolic/pynac.pyx'],
    18271822              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
     
    23312343        sig_off()
    23322344       
    23332345        return x
    2334        
    2335        
    2336        
    2337        
    2338        
    2339        
    2340        
    2341        
    2342        
    2343 
    2344 
    2345        
    2346        
    2347 
    2348         sig_on()
    2349         if nn < 0:  # we used to call (self**(-n)).__invert__()) -- this should be loads faster
    2350             mpz_pow_ui(mpq_denref(x.value), mpq_numref(_self.value), -nn) #we switch den and num to invert
    2351             mpz_pow_ui(mpq_numref(x.value), mpq_denref(_self.value), -nn)
    2352         else:
    2353             mpz_pow_ui(mpq_numref(x.value), mpq_numref(_self.value), nn)
    2354             mpz_pow_ui(mpq_denref(x.value), mpq_denref(_self.value), nn)
    2355         sig_off()
    2356        
    2357         #print "returning"
    2358        
    2359         return x
    23602346
    23612347    def __pos__(self):
    23622348        """
  • sage/symbolic/expression.pyx

    diff --git a/sage/symbolic/expression.pyx b/sage/symbolic/expression.pyx
    a b  
    27392739            sqrt(I)
    27402740            sage: I^(2/3)
    27412741            I^(2/3)
     2742            sage: 2^(1/2)
     2743            sqrt(2)
     2744            sage: (2*I)^(1/2)
     2745            sqrt(2*I)
     2746
     2747        Test if we can take powers of elements of Q(i) #8659::
     2748
     2749            sage: t = I.pyobject().parent()(8)
     2750            sage: t^(1/2)
     2751            2*sqrt(2)
     2752            sage: (t^2)^(1/4)
     2753            2*4^(1/4)
    27422754        """
    27432755        cdef Expression base, nexp
    27442756
  • 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