Ticket #11339: trac_11339_refcount_singular_rings.patch
File trac_11339_refcount_singular_rings.patch, 11.7 KB (added by , 10 years ago) |
---|
-
sage/libs/singular/groebner_strategy.pxd
# HG changeset patch # User Volker Braun <vbraun@stp.dias.ie> # Date 1308487956 -3600 # Node ID dca107e84dc194d9dae39c5e7e5e24c684dcda34 # Parent a48af224839e4eb2555175d15d703ecd81d0b4c1 Trac #11339: Refcount singular rings This patch introduces the necessary framework to refcount Singular rings. diff --git a/sage/libs/singular/groebner_strategy.pxd b/sage/libs/singular/groebner_strategy.pxd
a b 1 from sage.libs.singular.decl cimport skStrategy 1 from sage.libs.singular.decl cimport skStrategy, ring 2 2 3 from sage.rings.polynomial.multi_polynomial_libsingular cimport MPolynomialRing_libsingular, MPolynomial_libsingular 3 from sage.rings.polynomial.multi_polynomial_libsingular cimport \ 4 MPolynomialRing_libsingular, MPolynomial_libsingular 4 5 from sage.structure.sage_object cimport SageObject 5 6 6 7 7 8 cdef class GroebnerStrategy(SageObject): 8 9 cdef skStrategy *_strat 10 cdef ring *_parent_ring 9 11 cdef MPolynomialRing_libsingular _parent 10 12 cdef object _ideal 11 13 -
sage/libs/singular/groebner_strategy.pyx
diff --git a/sage/libs/singular/groebner_strategy.pyx b/sage/libs/singular/groebner_strategy.pyx
a b 27 27 from sage.libs.singular.decl cimport initEcartBBA, enterSBba, initBuchMoraCrit, initS, pNorm, id_Delete, kTest 28 28 from sage.libs.singular.decl cimport omfree, redNF, p_Copy, redtailBba 29 29 30 from sage.libs.singular.ring cimport singular_ring_reference, singular_ring_delete 31 30 32 from sage.rings.polynomial.multi_polynomial_ideal import MPolynomialIdeal 31 33 from sage.rings.polynomial.multi_polynomial_ideal_libsingular cimport sage_ideal_to_singular_ideal 32 34 from sage.rings.polynomial.multi_polynomial_libsingular cimport MPolynomial_libsingular, MPolynomialRing_libsingular, new_MP … … 42 44 43 45 Uses Singular via libSINGULAR 44 46 """ 45 def __ init__(self, L):47 def __cinit__(self, L): 46 48 """ 47 49 Create a new :class:`GroebnerStrategy` object for the 48 50 generators of the ideal ``L``. … … 100 102 101 103 cdef MPolynomialRing_libsingular R = <MPolynomialRing_libsingular>L.ring() 102 104 self._parent = R 105 self._parent_ring = singular_ring_reference(R._ring) 103 106 104 107 if not R.term_order().is_global(): 105 108 raise NotImplementedError("The local case is not implemented yet.") … … 141 144 sage: strat = GroebnerStrategy(I) 142 145 sage: del strat 143 146 """ 147 # WARNING: the Cython class self._parent is no longer accessible! 148 # see http://trac.sagemath.org/sage_trac/ticket/11339 144 149 cdef ring *oldRing = NULL 145 150 if self._strat: 146 151 omfree(self._strat.sevS) … … 152 157 omfree(self._strat.L) 153 158 omfree(self._strat.B) 154 159 omfree(self._strat.fromQ) 155 id_Delete(&self._strat.Shdl, self._parent ._ring)160 id_Delete(&self._strat.Shdl, self._parent_ring) 156 161 157 if self._parent ._ring != currRing:162 if self._parent_ring != currRing: 158 163 oldRing = currRing 159 rChangeCurrRing(self._parent ._ring)164 rChangeCurrRing(self._parent_ring) 160 165 delete_skStrategy(self._strat) 161 166 rChangeCurrRing(oldRing) 162 167 else: 163 168 delete_skStrategy(self._strat) 169 singular_ring_delete(self._parent_ring) 164 170 165 171 def _repr_(self): 166 172 """ -
sage/libs/singular/ring.pxd
diff --git a/sage/libs/singular/ring.pxd b/sage/libs/singular/ring.pxd
a b 14 14 15 15 from sage.libs.singular.decl cimport ring 16 16 17 18 # To work with singular rings, you need to balance singular_ring_new with 19 # singular_ring_delete or singular_ring_reference with 20 # singular_ring_delete. That is, either use one of the two patterns: 21 # 22 # cdef class myclass_new(): 23 # cdef ring* myring; 24 # cdef __cinit__(): 25 # self.myring = singular_ring_new(...) 26 # cdef __dealloc__(): 27 # singular_ring_delete(self.myring) 28 # 29 # cdef class myclass_reference(): 30 # cdef ring* refring; 31 # cdef __cinit__(ring* some_ring): 32 # self.refring = singular_ring_reference(some_ring) 33 # cdef __dealloc__(): 34 # singular_ring_delete(self.refring) 35 # 36 # You must not refer to Python/Cython classes in the Cython 37 # destructor, the following is INVALID: 38 # 39 # cdef class myclass_invalid(): 40 # cdef Parent parent; 41 # cdef __cinit__(Parent p): 42 # self.parent = p 43 # cdef __dealloc__(): 44 # do_something_with(self.parent.ring) # segfault 45 46 47 17 48 # create a new singular ring 18 49 cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL 19 50 20 # carefully delete a ring 21 cdef void singular_ring_delete(ring *ring) 51 # reference an existing ring 52 cdef ring *singular_ring_reference(ring *existing_ring) except NULL 53 54 # carefully delete a ring once its refcount is zero 55 cdef void singular_ring_delete(ring *doomed) -
sage/libs/singular/ring.pyx
diff --git a/sage/libs/singular/ring.pyx b/sage/libs/singular/ring.pyx
a b 55 55 "Ws": ringorder_Ws, 56 56 } 57 57 58 59 ############################################################################# 58 60 cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL: 59 61 """ 60 62 Create a new Singular ring over the ``base_ring`` in ``n`` … … 292 294 _ring.ShortOut = 0 293 295 294 296 rChangeCurrRing(_ring) 297 298 wrapped_ring = wrap_ring(_ring) 299 if wrapped_ring in ring_refcount_dict: 300 raise ValueError('newly created ring already in dictionary??') 301 ring_refcount_dict[wrapped_ring] = 1 295 302 return _ring 296 303 304 305 ############################################################################# 306 ring_refcount_dict = {} 307 308 309 cdef class ring_wrapper_Py(object): 310 r""" 311 Python object wrapping the ring pointer. 312 313 This is useful to store ring pointers in Python containers. 314 315 You must not construct instances of this class yourself, use 316 :func:`wrap_ring` instead. 317 318 EXAMPLES:: 319 320 sage: from sage.libs.singular.ring import ring_wrapper_Py 321 sage: ring_wrapper_Py 322 <type 'sage.libs.singular.ring.ring_wrapper_Py'> 323 """ 324 325 cdef ring* _ring 326 327 def __cinit__(self): 328 """ 329 The Cython constructor. 330 331 EXAMPLES:: 332 333 sage: from sage.libs.singular.ring import ring_wrapper_Py 334 sage: t = ring_wrapper_Py(); t 335 The ring pointer 0x0 336 sage: TestSuite(t).run() 337 """ 338 self._ring = NULL 339 340 def __hash__(self): 341 """ 342 Return a hash value so that instances can be used as dictionary keys. 343 344 OUTPUT: 345 346 Integer. 347 348 EXAMPLES:: 349 350 sage: from sage.libs.singular.ring import ring_wrapper_Py 351 sage: t = ring_wrapper_Py() 352 sage: t.__hash__() 353 0 354 """ 355 return <long>(self._ring) 356 357 def __repr__(self): 358 """ 359 Return a string representation. 360 361 OUTPUT: 362 363 String. 364 365 EXAMPLES:: 366 367 sage: from sage.libs.singular.ring import ring_wrapper_Py 368 sage: t = ring_wrapper_Py() 369 sage: t 370 The ring pointer 0x0 371 sage: t.__repr__() 372 'The ring pointer 0x0' 373 """ 374 return 'The ring pointer '+hex(self.__hash__()) 375 376 def __cmp__(ring_wrapper_Py left, ring_wrapper_Py right): 377 """ 378 Compare ``left`` and ``right`` so that instances can be used as dictionary keys. 379 380 INPUT: 381 382 - ``right`` -- a :class:`ring_wrapper_Py` 383 384 OUTPUT: 385 386 -1, 0, or +1 depending on whether ``left`` and ``right`` are 387 less than, equal, or greather than. 388 389 EXAMPLES:: 390 391 sage: from sage.libs.singular.ring import ring_wrapper_Py 392 sage: t = ring_wrapper_Py() 393 sage: t.__cmp__(t) 394 0 395 """ 396 if left._ring < right._ring: 397 return -1 398 if left._ring > right._ring: 399 return +1 400 return 0 401 402 403 cdef wrap_ring(ring* R): 404 """ 405 Wrap a C ring pointer into a Python object. 406 407 INPUT: 408 409 - ``R`` -- a singular ring (a C datastructure). 410 411 OUTPUT: 412 413 A Python object :class:`ring_wrapper_Py` wrapping the C pointer. 414 """ 415 cdef ring_wrapper_Py W = ring_wrapper_Py() 416 W._ring = R 417 return W 418 419 420 cdef ring *singular_ring_reference(ring *existing_ring) except NULL: 421 """ 422 Refcount the ring ``existing_ring``. 423 424 INPUT: 425 426 - ``existing_ring`` -- an existing Singular ring. 427 428 OUTPUT: 429 430 The same ring with its refcount increased. After calling this 431 function `n` times, you need to call :func:`singular_ring_delete` 432 `n+1` times to actually deallocate the ring. 433 434 EXAMPLE:: 435 436 sage: import gc 437 sage: from sage.rings.polynomial.multi_polynomial_libsingular import MPolynomialRing_libsingular 438 sage: from sage.libs.singular.groebner_strategy import GroebnerStrategy 439 sage: from sage.libs.singular.ring import ring_refcount_dict 440 sage: n = len(ring_refcount_dict) 441 sage: prev_rings = set(ring_refcount_dict.keys()) 442 sage: P = MPolynomialRing_libsingular(GF(541), 2, ('x', 'y'), TermOrder('degrevlex', 2)) 443 sage: ring_ptr = set(ring_refcount_dict.keys()).difference(prev_rings).pop() 444 sage: ring_ptr # random output 445 The ring pointer 0x7f78a646b8d0 446 sage: ring_refcount_dict[ring_ptr] 447 4 448 449 sage: strat = GroebnerStrategy(Ideal([P.gen(0) + P.gen(1)])) 450 sage: ring_refcount_dict[ring_ptr] 451 6 452 453 sage: del strat 454 sage: _ = gc.collect() 455 sage: ring_refcount_dict[ring_ptr] 456 4 457 458 sage: del P 459 sage: _ = gc.collect() 460 sage: ring_ptr in ring_refcount_dict 461 False 462 """ 463 if existing_ring==NULL: 464 raise ValueError('singular_ring_reference(ring*) called with NULL pointer.') 465 cdef object r = wrap_ring(existing_ring) 466 refcount = ring_refcount_dict.pop(r) 467 ring_refcount_dict[r] = refcount+1 468 return existing_ring 469 470 471 ############################################################################# 297 472 cdef void singular_ring_delete(ring *doomed): 298 473 """ 299 474 Carefully deallocate the ring, without changing "currRing" (since … … 320 495 sage: del R3 321 496 sage: _ = gc.collect() 322 497 """ 323 cdef ring *oldRing = NULL 324 if currRing != doomed: 325 oldRing = currRing 498 if doomed==NULL: 499 print 'singular_ring_delete(ring*) called with NULL pointer.' 500 # this function is typically called in __deallocate__, so we can't raise an exception 501 import traceback 502 traceback.print_stack() 503 504 if not ring_refcount_dict: # arbitrary finalization order when we shut Sage down 505 return 506 507 cdef ring_wrapper_Py r = wrap_ring(doomed) 508 refcount = ring_refcount_dict.pop(r) 509 if refcount > 1: 510 ring_refcount_dict[r] = refcount-1 511 return 512 513 cdef ring *oldRing = currRing 514 if currRing == doomed: 515 rDelete(doomed) 516 currRing = <ring*>NULL 517 else: 326 518 rChangeCurrRing(doomed) 327 519 rDelete(doomed) 328 520 rChangeCurrRing(oldRing) 329 else:330 (&currRing)[0] = NULL331 rDelete(doomed)332 521 -
sage/libs/singular/singular-cdefs.pxi
diff --git a/sage/libs/singular/singular-cdefs.pxi b/sage/libs/singular/singular-cdefs.pxi
a b 716 716 717 717 number *nlInit2(int i, int j) 718 718 719 # simplify rational number (cancel common factors) 720 721 number *nlNormalize(number *) 722 719 723 # copy a number 720 724 721 725 number *nlCopy(number *)