Ticket #13447: trac_13447-rely_on_singular_refcount.patch

File trac_13447-rely_on_singular_refcount.patch, 17.1 KB (added by SimonKing, 7 years ago)

Use Singular's refcounter for refcounting

  • sage/libs/singular/function.pxd

    # HG changeset patch
    # User Simon King <simon.king@uni-jena.de>
    # Date 1347900112 25200
    # Node ID eca1b57c72e06d366bcc49dd00ec51a556f3d049
    # Parent  d3c4342687384e481349a5d3b401636896f5864a
    #13447: Remove the custom ring refcount, and entirely rely on the refcounter provided by Singular
    
    diff --git a/sage/libs/singular/function.pxd b/sage/libs/singular/function.pxd
    a b  
    1818from sage.libs.singular.decl cimport leftv, idhdl, syStrategy, matrix, poly, ideal, intvec
    1919from sage.libs.singular.decl cimport ring as singular_ring
    2020from sage.rings.polynomial.multi_polynomial_libsingular cimport MPolynomialRing_libsingular, MPolynomial_libsingular
     21from sage.libs.singular.ring cimport singular_ring_reference, singular_ring_delete
    2122
    2223cdef poly* access_singular_poly(p) except <poly*> -1
    2324cdef singular_ring* access_singular_ring(r) except <singular_ring*> -1
  • sage/libs/singular/function.pyx

    diff --git a/sage/libs/singular/function.pyx b/sage/libs/singular/function.pyx
    a b  
    146146        if not self.is_commutative():
    147147            return "<noncommutative RingWrap>"
    148148        return "<RingWrap>"
    149    
     149
    150150    def __dealloc__(self):
    151         if self._ring!=NULL:
    152             self._ring.ref -= 1
     151        singular_ring_delete(self._ring)
    153152
    154153    def ngens(self):
    155154        """
     
    816815        """
    817816        Append the ring ``r`` to the list.
    818817        """
    819         cdef ring *_r =  access_singular_ring(r)
    820         _r.ref+=1
     818        cdef ring *_r =  singular_ring_reference(access_singular_ring(r))
    821819        return self._append(<void *>_r, RING_CMD)
    822820
    823821    cdef leftv *append_matrix(self, mat) except NULL:
     
    957955           
    958956
    959957        elif rtyp == RING_CMD or rtyp==QRING_CMD:
    960             return new_RingWrap( <ring*> to_convert.data )
     958            # We need to incref the to-be-converted data,
     959            # since apparently removing to_convert.data would
     960            # decref it.
     961            return new_RingWrap( singular_ring_reference(<ring*> to_convert.data) )
    961962
    962963        elif rtyp == MATRIX_CMD:
    963964            return self.to_sage_matrix(<matrix*>  to_convert.data )
     
    17901791#cdef ring*?
    17911792cdef inline RingWrap new_RingWrap(ring* r):
    17921793    cdef RingWrap ring_wrap_result = PY_NEW(RingWrap)
    1793     ring_wrap_result._ring = r
    1794     ring_wrap_result._ring.ref += 1
    1795    
     1794    ring_wrap_result._ring = singular_ring_reference(r)
    17961795    return ring_wrap_result
  • sage/libs/singular/groebner_strategy.pxd

    diff --git a/sage/libs/singular/groebner_strategy.pxd b/sage/libs/singular/groebner_strategy.pxd
    a b  
    1515
    1616cdef class NCGroebnerStrategy(SageObject):
    1717    cdef skStrategy *_strat
     18    cdef ring *_parent_ring
    1819    cdef NCPolynomialRing_plural _parent
    1920    cdef object _ideal
    2021
  • sage/libs/singular/groebner_strategy.pyx

    diff --git a/sage/libs/singular/groebner_strategy.pyx b/sage/libs/singular/groebner_strategy.pyx
    a b  
    339339
    340340        cdef NCPolynomialRing_plural R = <NCPolynomialRing_plural>L.ring()
    341341        self._parent = R
     342        self._parent_ring = singular_ring_reference(R._ring)
    342343
    343344        if not R.term_order().is_global():
    344345            raise NotImplementedError("The local case is not implemented yet.")
     
    394395            omfree(self._strat.fromQ)
    395396            id_Delete(&self._strat.Shdl, self._parent._ring)
    396397
    397             if self._parent._ring != currRing:
     398            if self._parent_ring != currRing:
    398399                oldRing = currRing
    399                 rChangeCurrRing(self._parent._ring)
     400                rChangeCurrRing(self._parent_ring)
    400401                delete_skStrategy(self._strat)
    401402                rChangeCurrRing(oldRing)
    402403            else:
    403404                delete_skStrategy(self._strat)
     405        singular_ring_delete(self._parent_ring)
    404406
    405407    def _repr_(self):
    406408        """
  • sage/libs/singular/ring.pxd

    diff --git a/sage/libs/singular/ring.pxd b/sage/libs/singular/ring.pxd
    a b  
    4848# create a new singular ring
    4949cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL
    5050
    51 # reference an existing ring
     51# incref an existing ring
    5252cdef ring *singular_ring_reference(ring *existing_ring) except NULL
    5353
    5454# carefully delete a ring once its refcount is zero
  • sage/libs/singular/ring.pyx

    diff --git a/sage/libs/singular/ring.pyx b/sage/libs/singular/ring.pyx
    a b  
    328328
    329329
    330330#############################################################################
    331 ring_refcount_dict = {}
    332 
    333331
    334332cdef class ring_wrapper_Py(object):
    335333    r"""
     
    462460        sage: _ = gc.collect()
    463461        sage: from sage.rings.polynomial.multi_polynomial_libsingular import MPolynomialRing_libsingular
    464462        sage: from sage.libs.singular.groebner_strategy import GroebnerStrategy
    465         sage: from sage.libs.singular.ring import ring_refcount_dict
    466         sage: n = len(ring_refcount_dict)
    467         sage: prev_rings = set(ring_refcount_dict.keys())
     463        sage: n = len([x for x in gc.get_objects() if isinstance(x,MPolynomialRing_libsingular)])
    468464        sage: P = MPolynomialRing_libsingular(GF(541), 2, ('x', 'y'), TermOrder('degrevlex', 2))
    469         sage: ring_ptr = set(ring_refcount_dict.keys()).difference(prev_rings).pop()
    470         sage: ring_ptr  # random output
    471         The ring pointer 0x7f78a646b8d0
    472         sage: ring_refcount_dict[ring_ptr]
    473         4
    474465
    475466        sage: strat = GroebnerStrategy(Ideal([P.gen(0) + P.gen(1)]))
    476         sage: ring_refcount_dict[ring_ptr]
    477         6
    478467       
    479468        sage: del strat
    480         sage: _ = gc.collect()
    481         sage: ring_refcount_dict[ring_ptr]
    482         4
    483 
    484469        sage: del P
    485470        sage: _ = gc.collect()
    486         sage: ring_ptr in ring_refcount_dict
    487         False
     471        sage: n == len([x for x in gc.get_objects() if isinstance(x,MPolynomialRing_libsingular)])
     472        True
    488473    """
    489474    if existing_ring==NULL:
    490475        raise ValueError('singular_ring_reference(ring*) called with NULL pointer.')
     
    524509        # this function is typically called in __deallocate__, so we can't raise an exception
    525510        import traceback
    526511        traceback.print_stack()
    527 
    528     if not ring_refcount_dict:  # arbitrary finalization order when we shut Sage down
    529512        return
    530513
    531     if doomed.ref > 1:
    532         doomed.ref = doomed.ref-1
     514    doomed.ref = doomed.ref-1
     515    if doomed.ref > 0:
     516        return
     517
     518    if doomed.ref < 0:
     519        print "singular_ring_delete(ring*) called with a ring that had no references."
     520        import traceback
     521        traceback.print_stack()
    533522        return
    534523
    535524    global currRing
  • sage/modular/modsym/ambient.py

    diff --git a/sage/modular/modsym/ambient.py b/sage/modular/modsym/ambient.py
    a b  
    13411341    def boundary_space(self):
    13421342        r"""
    13431343        Return the subspace of boundary modular symbols of this modular symbols ambient space.
    1344        
     1344
    13451345        EXAMPLES::
    1346        
    1347             sage: ModularSymbols(20,2).boundary_space()
     1346
     1347            sage: M = ModularSymbols(20, 2)
     1348            sage: B = M.boundary_space(); B
    13481349            Space of Boundary Modular Symbols for Congruence Subgroup Gamma0(20) of weight 2 and over Rational Field
    1349             sage: ModularSymbols(20,2).dimension()
     1350            sage: M.cusps()
     1351            [Infinity, 0, -1/4, 1/5, -1/2, 1/10]
     1352            sage: M.dimension()
    13501353            7
    1351             sage: ModularSymbols(20,2).boundary_space().dimension()
     1354            sage: B.dimension()
    13521355            6
     1356
    13531357        """
    13541358        raise NotImplementedError
    13551359       
  • sage/rings/polynomial/multi_polynomial_libsingular.pyx

    diff --git a/sage/rings/polynomial/multi_polynomial_libsingular.pyx b/sage/rings/polynomial/multi_polynomial_libsingular.pyx
    a b  
    392392        if self._ring != NULL:  # the constructor did not raise an exception
    393393            singular_ring_delete(self._ring)
    394394
     395    def _get_refcount(self):
     396        """
     397        Return the number of references set to this ring.
     398
     399        NOTE:
     400
     401        This is mainly for doctesting.
     402
     403        EXAMPLES::
     404
     405            sage: import gc
     406            sage: gc.collect()  # random
     407            sage: R.<x,y,z> = GF(5)[]
     408            sage: n = R._get_refcount()
     409            sage: p = x*y+z
     410            sage: R._get_refcount() == n+1
     411            True
     412            sage: del p
     413            sage: gc.collect()  # random
     414            sage: R._get_refcount() == n
     415            True
     416
     417        """
     418        if self._ring==NULL:
     419            return 0
     420        return self._ring.ref
     421   
    395422    def __copy__(self):
    396423        """
    397424        Copy ``self``.
     
    402429       
    403430            sage: import gc
    404431            sage: from sage.rings.polynomial.multi_polynomial_libsingular import MPolynomialRing_libsingular
    405             sage: from sage.libs.singular.ring import ring_refcount_dict
    406432            sage: gc.collect()  # random output
    407             sage: n = len(ring_refcount_dict)
     433            sage: n = len([x for x in gc.get_objects() if isinstance(x,MPolynomialRing_libsingular)])
    408434            sage: R = MPolynomialRing_libsingular(GF(547), 2, ('x', 'y'), TermOrder('degrevlex', 2))
    409             sage: len(ring_refcount_dict) == n + 1
     435            sage: len([x for x in gc.get_objects() if isinstance(x,MPolynomialRing_libsingular)]) == n+1
    410436            True
    411437
    412438            sage: Q = copy(R)   # indirect doctest
     
    417443            sage: del p
    418444            sage: del q
    419445            sage: gc.collect() # random output
    420             sage: len(ring_refcount_dict) == n   
     446            sage: len([x for x in gc.get_objects() if isinstance(x,MPolynomialRing_libsingular)]) == n
    421447            True
    422448        """
    423449        return self
  • sage/rings/polynomial/plural.pxd

    diff --git a/sage/rings/polynomial/plural.pxd b/sage/rings/polynomial/plural.pxd
    a b  
    44from sage.structure.element cimport RingElement, Element
    55from sage.structure.parent cimport Parent
    66from sage.libs.singular.function cimport RingWrap
     7from sage.libs.singular.ring cimport singular_ring_reference
    78from sage.rings.polynomial.multi_polynomial_libsingular cimport MPolynomialRing_libsingular
    89
    910
     
    2930
    3031cdef class NCPolynomial_plural(RingElement):
    3132    cdef poly *_poly
     33    cdef ring *_parent_ring
    3234    cpdef _repr_short_(self)
    3335    cdef long _hash_c(self)
    3436    cpdef is_constant(self)
  • sage/rings/polynomial/plural.pyx

    diff --git a/sage/rings/polynomial/plural.pyx b/sage/rings/polynomial/plural.pyx
    a b  
    111111from sage.structure.parent_gens cimport ParentWithGens
    112112
    113113# singular rings
    114 from sage.libs.singular.ring cimport singular_ring_new, singular_ring_delete, wrap_ring
     114from sage.libs.singular.ring cimport singular_ring_new, singular_ring_delete
    115115import sage.libs.singular.ring
    116116
    117117from sage.rings.integer cimport Integer
     
    335335        cdef RingWrap rw = ncalgebra(self._c, self._d, ring = P)
    336336
    337337        #       rw._output()
    338         self._ring = rw._ring
     338        self._ring = singular_ring_reference(rw._ring)
    339339        self._ring.ShortOut = 0
    340340
    341341        self.__ngens = n
     
    408408            sage: _ = gc.collect()
    409409        """
    410410        singular_ring_delete(self._ring)
    411    
     411
     412    def _get_refcount(self):
     413        """
     414        Return the number of references to the underlying c data of this ring.
     415
     416        NOTE:
     417
     418        This is mainly for doctesting.
     419
     420        EXAMPLES::
     421
     422            sage: import gc
     423            sage: gc.collect()    # random
     424            sage: from sage.libs.singular.groebner_strategy import NCGroebnerStrategy
     425            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
     426            sage: H.<x,y,z> = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y})
     427            sage: n = H._get_refcount()
     428            sage: I = H.ideal([y^2, x^2, z^2-H.one_element()])
     429            sage: strat = NCGroebnerStrategy(I)
     430
     431        We have created three elements of `H` and one Groebner strategy.
     432        Each create a reference to the underlying c data. Hence, we have::
     433
     434            sage: H._get_refcount() == n+4
     435            True
     436            sage: del strat
     437            sage: gc.collect()   # random
     438            sage: H._get_refcount() == n+3
     439            True
     440            sage: del I
     441            sage: gc.collect()   # random
     442            sage: H._get_refcount() == n
     443            True
     444            sage: p = x*y+z
     445            sage: H._get_refcount() == n+1
     446            True
     447            sage: del p
     448            sage: gc.collect()   # random
     449            sage: H._get_refcount() == n
     450            True
     451
     452        """
     453        if self._ring==NULL:
     454            return 0
     455        return self._ring.ref
     456
    412457    def _element_constructor_(self, element):
    413458        """
    414459        Make sure element is a valid member of self, and return the constructed element.
     
    853898       
    854899        from sage.libs.singular.function import singular_function
    855900        ring = singular_function('ring')
    856         return ring(L, ring=self)
     901        cdef RingWrap W = ring(L, ring=self)
     902        # Apparently, the "ring" function does *not* increment the reference
     903        # count to the ring.
     904        W._ring = singular_ring_reference(W._ring)
     905        return W
    857906
    858907# TODO: Implement this properly!
    859908#    def quotient(self, I):
     
    13571406        """
    13581407        self._poly = NULL
    13591408        self._parent = <ParentWithBase>parent
     1409        self._parent_ring = singular_ring_reference(parent._ring)
    13601410
    13611411    def __dealloc__(self):
    1362         # TODO: Warn otherwise!
    1363         # for some mysterious reason, various things may be NULL in some cases
    1364         if self._parent is not <ParentWithBase>None and (<NCPolynomialRing_plural>self._parent)._ring != NULL and self._poly != NULL:
    1365             p_Delete(&self._poly, (<NCPolynomialRing_plural>self._parent)._ring)
     1412        if self._poly != NULL:
     1413            if self._parent_ring != NULL:
     1414                p_Delete(&self._poly, self._parent_ring)
     1415        singular_ring_delete(self._parent_ring)
    13661416
    13671417#    def __call__(self, *x, **kwds): # ?
    13681418
     
    17571807            sage: f # indirect doctest
    17581808            x^3 - x*z*y + z^2 + z
    17591809        """
    1760         cdef ring *_ring = (<NCPolynomialRing_plural>self._parent)._ring
     1810        cdef ring *_ring = self._parent_ring
    17611811        s = singular_polynomial_str(self._poly, _ring)
    17621812        return s
    17631813
     
    26772727    """
    26782728    cdef NCPolynomial_plural p = PY_NEW(NCPolynomial_plural)
    26792729    p._parent = <ParentWithBase>parent
     2730    p._parent_ring = singular_ring_reference(parent._ring)
    26802731    p._poly = juice
    26812732    p_Normalize(p._poly, parent._ring)
    26822733    return p
     
    27122763
    27132764    Check that #13145 has been resolved::
    27142765
    2715         sage: h = hash(R.gen() + 1) # sets currRing
    2716         sage: from sage.libs.singular.ring import ring_refcount_dict, currRing_wrapper
    2717         sage: curcnt = ring_refcount_dict[currRing_wrapper()]
    2718         sage: newR = new_CRing(W, H.base_ring())
    2719         sage: ring_refcount_dict[currRing_wrapper()] - curcnt
    2720         1
     2766        sage: import gc
     2767        sage: gc.collect()    # random
     2768        sage: from sage.libs.singular.groebner_strategy import NCGroebnerStrategy
     2769        sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
     2770        sage: H.<x,y,z> = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y})
     2771        sage: n = H._get_refcount()
     2772        sage: I = H.ideal([y^2, x^2, z^2-H.one_element()])
     2773        sage: strat = NCGroebnerStrategy(I)
     2774
     2775    We have created three elements and one Groebner strategy, and thus have
     2776    four additional references to the underlying c data::
     2777
     2778        sage: H._get_refcount() == n+4
     2779        True
     2780        sage: del strat, I
     2781        sage: gc.collect()   # random
     2782        sage: H._get_refcount() == n
     2783        True
     2784
    27212785    """
    27222786    assert( rw.is_commutative() )
    2723        
     2787
    27242788    cdef MPolynomialRing_libsingular self = <MPolynomialRing_libsingular>PY_NEW(MPolynomialRing_libsingular)
    2725        
    2726     self._ring = rw._ring
    2727 
    2728     wrapped_ring = wrap_ring(self._ring)
    2729     cur_refcnt = sage.libs.singular.ring.ring_refcount_dict.get(wrapped_ring, 0)
    2730     sage.libs.singular.ring.ring_refcount_dict[wrapped_ring] = cur_refcnt + 1
     2789
     2790    self._ring = singular_ring_reference(rw._ring)
    27312791
    27322792    self._ring.ShortOut = 0
    27332793       
     
    27902850    assert( not rw.is_commutative() )
    27912851   
    27922852    cdef NCPolynomialRing_plural self = <NCPolynomialRing_plural>PY_NEW(NCPolynomialRing_plural)
    2793     self._ring = rw._ring
    2794 
    2795     wrapped_ring = wrap_ring(self._ring)
    2796     cur_refcnt = sage.libs.singular.ring.ring_refcount_dict.get(wrapped_ring, 0)
    2797     sage.libs.singular.ring.ring_refcount_dict[wrapped_ring] = cur_refcnt + 1
     2853    self._ring = singular_ring_reference(rw._ring)
    27982854
    27992855    self._ring.ShortOut = 0
    28002856       
     
    29082964    I = H.ideal([H.gen(i) *H.gen(i) for i in alt_vars]).twostd()
    29092965    L = H._ringlist()
    29102966    L[3] = I
    2911     W = H._list_to_ring(L)
     2967    cdef RingWrap W = H._list_to_ring(L)
    29122968    return new_NRing(W, H.base_ring())
    29132969
    29142970cdef poly *addwithcarry(poly *tempvector, poly *maxvector, int pos, ring *_ring):