Changeset 6660:333f153e3474


Ignore:
Timestamp:
09/05/07 20:04:21 (6 years ago)
Author:
Robert Bradshaw <robertwb@…>
Branch:
default
Message:

inplace operations in element hierarchy

Location:
sage/structure
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • sage/structure/coerce.pxi

    r6655 r6660  
    5858        return "unsupported operand parent(s) for '%s': '%s' and '%s'"%(n, parent_c(x), parent_c(y)) 
    5959 
     60################################################################################# 
     61# Inline arithmatic dispatchers for ModuleElements and RingElements 
     62################################################################################# 
     63 
    6064cdef inline ModuleElement _add_c(ModuleElement left, ModuleElement right): 
    6165    if HAS_DICTIONARY(left): 
     
    6973    else: 
    7074        return left._iadd_c_impl(right) 
     75 
     76cdef inline ModuleElement _sub_c(ModuleElement left, ModuleElement right): 
     77    if HAS_DICTIONARY(left): 
     78        return left._sub_(right) 
     79    else: 
     80        return left._sub_c_impl(right) 
     81         
     82cdef inline ModuleElement _isub_c(ModuleElement left, ModuleElement right): 
     83    if HAS_DICTIONARY(left): 
     84        return left._isub_(right) 
     85    else: 
     86        return left._isub_c_impl(right) 
     87 
     88# rmul -- left * self 
     89cdef inline ModuleElement _rmul_c(ModuleElement right, RingElement left): 
     90    if HAS_DICTIONARY(right):  
     91        return right._rmul_(left) 
     92    else: 
     93        return right._rmul_c_impl(left) 
     94 
     95# lmul -- self * right 
     96cdef inline ModuleElement _lmul_c(ModuleElement left, RingElement right): 
     97    if HAS_DICTIONARY(left):  
     98        return left._lmul_(right) 
     99    else: 
     100        return left._lmul_c_impl(right) 
     101 
     102# ilmul -- inplace self * right 
     103cdef inline ModuleElement _ilmul_c(ModuleElement self, RingElement right): 
     104    if HAS_DICTIONARY(self):  
     105        return self._ilmul_(right) 
     106    else: 
     107        return self._ilmul_c_impl(right) 
     108 
     109cdef inline RingElement _mul_c(RingElement left, RingElement right): 
     110    if HAS_DICTIONARY(left): 
     111        return left._mul_(right) 
     112    else: 
     113        return left._mul_c_impl(right) 
     114         
     115cdef inline RingElement _imul_c(RingElement left, RingElement right): 
     116    if HAS_DICTIONARY(left): 
     117        return left._imul_(right) 
     118    else: 
     119        return left._imul_c_impl(right) 
     120 
     121cdef inline RingElement _div_c(RingElement left, RingElement right): 
     122    if HAS_DICTIONARY(left): 
     123        return left._div_(right) 
     124    else: 
     125        return left._div_c_impl(right) 
     126         
     127cdef inline RingElement _idiv_c(RingElement left, RingElement right): 
     128    if HAS_DICTIONARY(left): 
     129        return left._idiv_(right) 
     130    else: 
     131        return left._idiv_c_impl(right) 
     132 
     133cdef enum: 
     134    # 3 references: handle, scope container, and arithmatic call stack 
     135    inplace_threshold = 0 
  • sage/structure/coerce.pyx

    r6659 r6660  
    243243         
    244244    cdef bin_op_c(self, x, y, op): 
    245          
    246         if (op is not op_add) and (op is not op_sub) and (op is not op_iadd) and not (op is not op_isub): 
     245        if (op is not op_add) and (op is not op_sub) and (op is not op_iadd) and (op is not op_isub): 
    247246            # Actions take preference over common-parent coercions. 
    248247            xp = parent_c(x) 
  • sage/structure/element.pxd

    r6655 r6660  
    3636cdef class ModuleElement(Element): 
    3737    cdef ModuleElement _add_c(self, ModuleElement right)    # do *NOT* override, but OK to call directly 
    38     cdef ModuleElement _iadd_c(self, ModuleElement right)    # do *NOT* override, but OK to call directly 
    3938    cdef ModuleElement _sub_c(self, ModuleElement right)    # do *NOT* override, but OK to call directly 
    4039    cdef ModuleElement _neg_c(self)                         # do *NOT* override, but OK to call directly 
     
    4544 
    4645    cdef ModuleElement _add_c_impl(self, ModuleElement right)  # OK to override, but do NOT call 
    47     cdef ModuleElement _iadd_c_impl(self, ModuleElement right)  # OK to override, but do NOT call 
    4846    cdef ModuleElement _sub_c_impl(self, ModuleElement right)  # OK to override, but do NOT call 
    4947    cdef ModuleElement _neg_c_impl(self)                       # OK to override, but do *NOT* call directly 
    5048    cdef ModuleElement _lmul_c_impl(self, RingElement right)   # OK to override, but do *NOT* call directly 
    5149    cdef ModuleElement _rmul_c_impl(self, RingElement left)    # OK to override, but do *NOT* call directly 
     50     
     51    # Inplace operations, override, do *NOT* call directly 
     52    cdef ModuleElement _iadd_c_impl(self, ModuleElement right) 
     53    cdef ModuleElement _isub_c_impl(self, ModuleElement right) 
     54    cdef ModuleElement _ilmul_c_impl(self, RingElement right) 
    5255 
    5356    # Coerce x to the base ring of self and return the result. 
     
    8689    cdef RingElement _div_c_impl(self, RingElement right)     # OK to override, but do *NOT* call directly 
    8790     
     91    # Inplace operations, override, do *NOT* call directly 
     92    cdef RingElement _imul_c_impl(self, RingElement right) 
     93    cdef RingElement _idiv_c_impl(self, RingElement right) 
     94 
    8895cdef class CommutativeRingElement(RingElement): 
    8996    pass 
  • sage/structure/element.pyx

    r6655 r6660  
    152152   implementations of either _add_ or _add_c_impl. 
    153153 
     154 
     155For speed, there are also {\bf inplace} version of the arithmatic commands.  
     156DD NOT call them directly, they may mutate the object and will be called  
     157when and only when it has been determined that the old object will no longer  
     158be accessible from the calling function after this operation.  
     159 
     160{\bf def RingElement._iadd_} 
     161 
     162   This is the function you should override to inplace implement addition  
     163   in a python subclass of RingElement. 
     164 
     165   WARNING: if you override this in a *pyrex* class, it won't get called. 
     166   You should override _iadd_c_impl instead. It is especially important to 
     167   keep this in mind whenever you move a class down from python to pyrex. 
     168 
     169   The two arguments to this function are guaranteed to have the 
     170   SAME PARENT. Its return value MUST have the SAME PARENT as its 
     171   arguments. 
     172 
     173   The default implementation of this function is to call _add_c_impl, 
     174   so if no-one has defined a python implementation, the correct pyrex 
     175   implementation will get called. 
     176 
     177{\bf cdef RingElement._iadd_c_impl} 
     178 
     179   This is the function you should override to inplace implement addition  
     180   in a pyrex subclass of RingElement. 
     181 
     182   The two arguments to this function are guaranteed to have the 
     183   SAME PARENT. Its return value MUST have the SAME PARENT as its 
     184   arguments. 
     185 
     186   The default implementation of this function is to call _add_c 
     187    
    154188""" 
    155189 
     
    648682        # ModuleElements. Otherwise use the slower test via PY_TYPE_CHECK.) 
    649683        if have_same_parent(left, right): 
    650             if  (<RefPyObject *>left).ob_refcnt <= 2: 
    651                 # This is a temporary variable (incref due to calling, and at the top of this fn).  
    652                 return (<ModuleElement>left)._iadd_c(<ModuleElement>right) 
     684            # If we hold the only references to this object, we can 
     685            # safely mutate it. NOTE the threshold is different by one 
     686            # for __add__ and __iadd__.  
     687            if  (<RefPyObject *>left).ob_refcnt < inplace_threshold: 
     688                return _iadd_c(<ModuleElement>left, <ModuleElement>right) 
    653689            else: 
    654                 return (<ModuleElement>left)._add_c(<ModuleElement>right) 
     690                return _add_c(<ModuleElement>left, <ModuleElement>right) 
    655691        global coercion_model 
    656692        return coercion_model.bin_op_c(left, right, operator.add) 
    657693         
    658     def __iadd__(ModuleElement self, right): 
    659         if have_same_parent(self, right): 
    660             if  (<RefPyObject *>self).ob_refcnt <= 3: 
    661                 return self._iadd_c(<ModuleElement>right) 
    662             else: 
    663                 return self._add_c(right) 
    664         else: 
    665             global coercion_model 
    666             return coercion_model.bin_op_c(self, right, operator.iadd) 
    667              
    668     cdef ModuleElement _iadd_c(self, ModuleElement right): 
    669         if HAS_DICTIONARY(self): 
    670             return self._iadd_(right) 
    671         else: 
    672             return self._iadd_c_impl(right) 
    673              
    674     def _iadd_(self, right): 
    675         return self._iadd_c_impl(right) 
    676          
    677     cdef ModuleElement _iadd_c_impl(self, ModuleElement right): 
    678         return self._add_c(right) 
    679  
    680  
    681694    cdef ModuleElement _add_c(left, ModuleElement right): 
    682695        """ 
     
    718731        return left._add_c_impl(right) 
    719732 
     733    def __iadd__(ModuleElement self, right): 
     734        if have_same_parent(self, right): 
     735            if  (<RefPyObject *>self).ob_refcnt <= inplace_threshold: 
     736                return _iadd_c(<ModuleElement>self, <ModuleElement>right) 
     737            else: 
     738                return _add_c(<ModuleElement>self, <ModuleElement>right) 
     739        else: 
     740            global coercion_model 
     741            return coercion_model.bin_op_c(self, right, operator.iadd) 
     742                         
     743    def _iadd_(self, right): 
     744        return self._iadd_c_impl(right) 
     745         
     746    cdef ModuleElement _iadd_c_impl(self, ModuleElement right): 
     747        return self._add_c(right) 
     748 
    720749    ################################################## 
    721750    # Subtraction 
     
    728757        """ 
    729758        if have_same_parent(left, right): 
    730             return (<ModuleElement>left)._sub_c(<ModuleElement>right) 
     759            if  (<RefPyObject *>left).ob_refcnt < inplace_threshold: 
     760                return _isub_c(<ModuleElement>left, <ModuleElement>right) 
     761            else: 
     762                return _sub_c(<ModuleElement>left, <ModuleElement>right) 
    731763        global coercion_model 
    732764        return coercion_model.bin_op_c(left, right, operator.sub) 
     
    769801        return left._sub_c_impl(right) 
    770802         
     803         
     804    def __isub__(ModuleElement self, right): 
     805        if have_same_parent(self, right): 
     806            if  (<RefPyObject *>self).ob_refcnt <= inplace_threshold: 
     807                return _isub_c(<ModuleElement>self, <ModuleElement>right) 
     808            else: 
     809                return _sub_c(<ModuleElement>self, <ModuleElement>right) 
     810        else: 
     811            global coercion_model 
     812            return coercion_model.bin_op_c(self, right, operator.isub) 
     813                         
     814    def _isub_(self, right): 
     815        return self._isub_c_impl(right) 
     816         
     817    cdef ModuleElement _isub_c_impl(self, ModuleElement right): 
     818        return self._sub_c(right) 
     819 
    771820    ################################################## 
    772821    # Negation 
     
    9591008        return self._lmul_c_impl(right) 
    9601009         
     1010    cdef ModuleElement _ilmul_c_impl(self, RingElement right): 
     1011        return _lmul_c(self, right) 
     1012         
    9611013    cdef RingElement coerce_to_base_ring(self, x): 
    9621014        if PY_TYPE_CHECK(x, Element) and (<Element>x)._parent is self._parent._base: 
     
    12461298    ################################## 
    12471299 
    1248     # The default behavior for scalars is just to coerce into the parent ring.  
    12491300    cdef ModuleElement _lmul_c_impl(self, RingElement right): 
     1301        # We raise an error to invoke the default action of coercing into self 
    12501302        raise NotImplementedError, "parents %s %s %s" % (parent_c(self), parent_c(right), parent_c(self) is parent_c(right)) 
    1251 #        return self._mul_c(<RingElement>(self._parent._coerce_c(right))) 
    12521303 
    12531304    cdef ModuleElement _rmul_c_impl(self, RingElement left): 
     1305        # We raise an error to invoke the default action of coercing into self 
    12541306        raise NotImplementedError 
    1255 #        return (<RingElement>(self._parent._coerce_c(left)))._mul_c(self) 
    1256  
     1307         
    12571308    def __mul__(self, right): 
    12581309        """ 
     
    13651416 
    13661417        """ 
    1367         global coercion_model 
    13681418        # Try fast pathway if they are both RingElements and the parents match. 
    13691419        # (We know at least one of the arguments is a RingElement. So if their 
     
    13711421        # Otherwise use the slower test via PY_TYPE_CHECK.) 
    13721422        if have_same_parent(self, right): 
    1373             return (<RingElement>self)._mul_c(<RingElement>right) 
    1374  
    1375         if not (PY_TYPE_CHECK(self, Element) and PY_TYPE_CHECK(right, Element)): 
    1376             # one of self or right is not even an Element.  
    1377             return coercion_model.bin_op_c(self, right, operator.mul) 
    1378          
     1423            if  (<RefPyObject *>self).ob_refcnt < inplace_threshold: 
     1424                return _imul_c(<RingElement>self, <RingElement>right) 
     1425            else: 
     1426                return _mul_c(<RingElement>self, <RingElement>right) 
     1427 
    13791428        # Always do this 
     1429        global coercion_model 
    13801430        return coercion_model.bin_op_c(self, right, operator.mul) 
    13811431 
     
    14501500        return self._mul_c_impl(right) 
    14511501         
     1502    def __imul__x(left, right): 
     1503        if have_same_parent(left, right): 
     1504            if  (<RefPyObject *>left).ob_refcnt <= inplace_threshold: 
     1505                return _imul_c(<RingElement>left, <RingElement>right) 
     1506            else: 
     1507                return _mul_c(<RingElement>left, <RingElement>right) 
     1508 
     1509        global coercion_model 
     1510        return coercion_model.bin_op_c(left, right, operator.imul) 
     1511         
     1512    def _imul_(self, right): 
     1513        return self._imul_c_impl(right) 
     1514         
     1515    cdef RingElement _imul_c_impl(RingElement self, RingElement right): 
     1516        return _mul_c(self, right) 
     1517         
    14521518    def __pow__(self, n, dummy): 
    14531519        """ 
     
    15031569        """ 
    15041570        if have_same_parent(self, right): 
    1505             return (<RingElement>self)._div_c(<RingElement>right) 
     1571            if  (<RefPyObject *>self).ob_refcnt < inplace_threshold: 
     1572                return _idiv_c(<RingElement>self, <RingElement>right) 
     1573            else: 
     1574                return _div_c(<RingElement>self, <RingElement>right) 
     1575        global coercion_model 
    15061576        return coercion_model.bin_op_c(self, right, operator.div) 
    1507  
    15081577             
    15091578 
     
    15391608        return self._div_c_impl(right) 
    15401609 
     1610    def __idiv__(self, right): 
     1611        """ 
     1612        Top-level multiplication operator for ring elements. 
     1613        See extensive documentation at the top of element.pyx. 
     1614        """ 
     1615        if have_same_parent(self, right): 
     1616            if  (<RefPyObject *>self).ob_refcnt <= inplace_threshold: 
     1617                return _idiv_c(<RingElement>self, <RingElement>right) 
     1618            else: 
     1619                return _div_c(<RingElement>self, <RingElement>right) 
     1620        global coercion_model 
     1621        return coercion_model.bin_op_c(self, right, operator.idiv) 
     1622 
     1623    def _idiv_(self, right): 
     1624        return self._idiv_c_impl(right) 
     1625         
     1626    cdef RingElement _idiv_c_impl(RingElement self, RingElement right): 
     1627        return _div_c(self, right) 
     1628         
    15411629    def __pos__(self): 
    15421630        return self 
Note: See TracChangeset for help on using the changeset viewer.