Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
""" Wrapper for Singular's Rings
AUTHORS:
- Martin Albrecht (2009-07): initial implementation
- Kwankyu Lee (2010-06): added matrix term order support """ #***************************************************************************** # Copyright (C) 2009 Martin Albrecht <malb@informatik.uni-bremen.de> # # Distributed under the terms of the GNU General Public License (GPL) # http://www.gnu.org/licenses/ #***************************************************************************** from __future__ import print_function
from sage.cpython.string cimport str_to_bytes
from sage.libs.gmp.types cimport __mpz_struct from sage.libs.gmp.mpz cimport mpz_init_set_ui, mpz_init_set
from sage.libs.singular.decl cimport number, poly, ring, currRing from sage.libs.singular.decl cimport rChangeCurrRing, rCopy0, rComplete, rDelete, idInit from sage.libs.singular.decl cimport omAlloc0, omStrDup, omAlloc, omAlloc0Bin, sip_sring_bin, rnumber_bin from sage.libs.singular.decl cimport ringorder_dp, ringorder_Dp, ringorder_lp, ringorder_rp, ringorder_ds, ringorder_Ds, ringorder_ls, ringorder_M, ringorder_C, ringorder_wp, ringorder_Wp, ringorder_ws, ringorder_Ws, ringorder_a, rRingOrder_t from sage.libs.singular.decl cimport p_Copy, prCopyR from sage.libs.singular.decl cimport n_unknown, n_Zp, n_Q, n_R, n_GF, n_long_R, n_algExt,n_transExt,n_long_C, n_Z, n_Zn, n_Znm, n_Z2m, n_CF from sage.libs.singular.decl cimport n_coeffType, cfInitCharProc from sage.libs.singular.decl cimport rDefault, GFInfo, ZnmInfo, nInitChar, AlgExtInfo, nRegister, naInitChar
from sage.rings.integer cimport Integer from sage.rings.integer_ring cimport IntegerRing_class from sage.rings.integer_ring import ZZ from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing from sage.rings.number_field.number_field_base cimport NumberField from sage.rings.rational_field import RationalField from sage.rings.finite_rings.finite_field_base import FiniteField as FiniteField_generic
from sage.rings.polynomial.term_order import TermOrder from sage.rings.polynomial.multi_polynomial_libsingular cimport MPolynomial_libsingular, MPolynomialRing_libsingular from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
from cpython.object cimport Py_EQ, Py_NE
from collections import defaultdict
# mapping str --> SINGULAR representation order_dict = { "dp": ringorder_dp, "Dp": ringorder_Dp, "lp": ringorder_lp, "rp": ringorder_rp, "ds": ringorder_ds, "Ds": ringorder_Ds, "ls": ringorder_ls, "wp": ringorder_wp, "Wp": ringorder_Wp, "ws": ringorder_ws, "Ws": ringorder_Ws, "a": ringorder_a, }
############################################################################# cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL: """ Create a new Singular ring over the ``base_ring`` in ``n`` variables with the names ``names`` and the term order ``term_order``.
INPUT:
- ``base_ring`` - a Sage ring
- ``n`` - the number of variables (> 0)
- ``names`` - a list of names of length ``n``
- ``term_order`` - a term ordering
EXAMPLES::
sage: P.<x,y,z> = QQ[] sage: P Multivariate Polynomial Ring in x, y, z over Rational Field
sage: P.term_order() Degree reverse lexicographic term order
sage: P = PolynomialRing(GF(127),3,names='abc', order='lex') sage: P Multivariate Polynomial Ring in a, b, c over Finite Field of size 127
sage: P.term_order() Lexicographic term order
sage: z = QQ['z'].0 sage: K.<s> = NumberField(z^2 - 2) sage: P.<x,y> = PolynomialRing(K, 2)
sage: P.<x,y,z> = ZZ[]; P Multivariate Polynomial Ring in x, y, z over Integer Ring
sage: P.<x,y,z> = Zmod(2^10)[]; P Multivariate Polynomial Ring in x, y, z over Ring of integers modulo 1024
sage: P.<x,y,z> = Zmod(3^10)[]; P Multivariate Polynomial Ring in x, y, z over Ring of integers modulo 59049
sage: P.<x,y,z> = Zmod(2^100)[]; P Multivariate Polynomial Ring in x, y, z over Ring of integers modulo 1267650600228229401496703205376
sage: P.<x,y,z> = Zmod(2521352)[]; P Multivariate Polynomial Ring in x, y, z over Ring of integers modulo 2521352
sage: P.<x,y,z> = Zmod(25213521351515232)[]; P Multivariate Polynomial Ring in x, y, z over Ring of integers modulo 25213521351515232 """ cdef long cexponent cdef GFInfo* _param cdef ZnmInfo _info cdef ring* _ring cdef char **_names cdef char **_ext_names cdef int i,j cdef int nblcks cdef int offset cdef int nvars cdef int characteristic cdef int modbase
cdef MPolynomialRing_libsingular k cdef MPolynomial_libsingular minpoly cdef AlgExtInfo extParam
#cdef cfInitCharProc myfunctionptr;
# from the SINGULAR source code documentation for the rInit function ## characteristic -------------------------------------------------- ## input: 0 ch=0 : Q parameter=NULL ffChar=FALSE float_len (done) ## 0 1 : Q(a,...) *names FALSE (done) ## 0 -1 : R NULL FALSE 0 ## 0 -1 : R NULL FALSE prec. >6 ## 0 -1 : C *names FALSE prec. 0..? ## p p : Fp NULL FALSE (done) ## p -p : Fp(a) *names FALSE (done) ## q q : GF(q=p^n) *names TRUE (todo)
nlen = n else:
else: # ordinary orders
_block1[idx] = offset + n else:
# TODO: if we construct a free module don't hardcode! This # position determines whether we break ties at monomials first or # whether we break at indices first!
# _type = nRegister(n_algExt, <cfInitCharProc> naInitChar);
raise RuntimeError("Failed to allocate _cf ring.")
else:
# example for simpler ring creation interface without monomial orderings: #_ring = rDefault(characteristic, nvars, _names)
else:
# TODO: This is lazy, it should only call Singular stuff not PolynomialRing()
raise RuntimeError("Failed to allocate _cf ring.")
else:
else: # ringtype == n_Z2m
else:
else:
raise ValueError("Failed to allocate Singular ring.")
raise ValueError('newly created ring already in dictionary??')
############################################################################# ring_refcount_dict = defaultdict(int)
cdef class ring_wrapper_Py(object): r""" Python object wrapping the ring pointer.
This is useful to store ring pointers in Python containers.
You must not construct instances of this class yourself, use :func:`wrap_ring` instead.
EXAMPLES::
sage: from sage.libs.singular.ring import ring_wrapper_Py sage: ring_wrapper_Py <type 'sage.libs.singular.ring.ring_wrapper_Py'> """
cdef ring* _ring
def __cinit__(self): """ The Cython constructor.
EXAMPLES::
sage: from sage.libs.singular.ring import ring_wrapper_Py sage: t = ring_wrapper_Py(); t The ring pointer 0x0
These are just wrappers around a pointer, so it isn't really meaningful to pickle them::
sage: TestSuite(t).run(skip='_test_pickling') """
def __hash__(self): """ Return a hash value so that instances can be used as dictionary keys.
OUTPUT:
Integer.
EXAMPLES::
sage: from sage.libs.singular.ring import ring_wrapper_Py sage: t = ring_wrapper_Py() sage: t.__hash__() 0 """
def __repr__(self): """ Return a string representation.
OUTPUT:
String.
EXAMPLES::
sage: from sage.libs.singular.ring import ring_wrapper_Py sage: t = ring_wrapper_Py() sage: t The ring pointer 0x0 sage: t.__repr__() 'The ring pointer 0x0' """
# This could be written using __eq__ but that does not work # due to https://github.com/cython/cython/issues/2019 def __richcmp__(ring_wrapper_Py self, other, int op): """ Equality comparison between two ``ring_wrapper_Py`` instances, for use when hashing.
INPUT:
- ``right`` -- a :class:`ring_wrapper_Py`
OUTPUT:
True if both ``ring_wrapper_Py`` wrap the same pointer.
EXAMPLES::
sage: from sage.libs.singular.ring import (ring_wrapper_Py, ....: currRing_wrapper) sage: t = ring_wrapper_Py() sage: t == t True sage: P.<x,y,z> = QQ[] sage: t2 = currRing_wrapper() sage: t3 = currRing_wrapper() sage: t == t2 False sage: t2 == t3 True sage: t2 != t3 False sage: t2 == None False """ return NotImplemented
cdef wrap_ring(ring* R): """ Wrap a C ring pointer into a Python object.
INPUT:
- ``R`` -- a singular ring (a C datastructure).
OUTPUT:
A Python object :class:`ring_wrapper_Py` wrapping the C pointer. """
cdef ring *singular_ring_reference(ring *existing_ring) except NULL: """ Refcount the ring ``existing_ring``.
INPUT:
- ``existing_ring`` -- a Singular ring.
OUTPUT:
The same ring with its refcount increased. If ``existing_ring`` has not been refcounted yet, it will be after calling this function. If initially ``existing_ring`` was refcounted once, then after calling this function `n` times, you need to call :func:`singular_ring_delete` `n+1` times to actually deallocate the ring.
EXAMPLES::
sage: import gc sage: _ = gc.collect() sage: from sage.rings.polynomial.multi_polynomial_libsingular import MPolynomialRing_libsingular sage: from sage.libs.singular.groebner_strategy import GroebnerStrategy sage: from sage.libs.singular.ring import ring_refcount_dict sage: n = len(ring_refcount_dict) sage: prev_rings = set(ring_refcount_dict) sage: P = MPolynomialRing_libsingular(GF(541), 2, ('x', 'y'), TermOrder('degrevlex', 2)) sage: ring_ptr = set(ring_refcount_dict).difference(prev_rings).pop() sage: ring_ptr # random output The ring pointer 0x7f78a646b8d0 sage: ring_refcount_dict[ring_ptr] 4
sage: strat = GroebnerStrategy(Ideal([P.gen(0) + P.gen(1)])) sage: ring_refcount_dict[ring_ptr] 6
sage: del strat sage: _ = gc.collect() sage: ring_refcount_dict[ring_ptr] 4
sage: del P sage: _ = gc.collect() sage: ring_ptr in ring_refcount_dict True """ raise ValueError('singular_ring_reference(ring*) called with NULL pointer.')
############################################################################# cdef void singular_ring_delete(ring *doomed): """ Carefully deallocate the ring, without changing "currRing" (since this method can be called at unpredictable times due to garbage collection).
TESTS:
This example caused a segmentation fault with a previous version of this method::
sage: import gc sage: from sage.rings.polynomial.multi_polynomial_libsingular import MPolynomialRing_libsingular sage: R1 = MPolynomialRing_libsingular(GF(5), 2, ('x', 'y'), TermOrder('degrevlex', 2)) sage: R2 = MPolynomialRing_libsingular(GF(11), 2, ('x', 'y'), TermOrder('degrevlex', 2)) sage: R3 = MPolynomialRing_libsingular(GF(13), 2, ('x', 'y'), TermOrder('degrevlex', 2)) sage: _ = gc.collect() sage: foo = R1.gen(0) sage: del foo sage: del R1 sage: _ = gc.collect() sage: del R2 sage: _ = gc.collect() sage: del R3 sage: _ = gc.collect() """ # When this is called with a NULL pointer, we do nothing. # This is analogous to the libc function free().
return
global currRing else:
############################################################################# # helpers for debugging
cpdef poison_currRing(frame, event, arg): """ Poison the ``currRing`` pointer.
This function sets the ``currRing`` to an illegal value. By setting it as the python debug hook, you can poison the currRing before every evaluated Python command (but not within Cython code).
INPUT:
- ``frame``, ``event``, ``arg`` -- the standard arguments for the CPython debugger hook. They are not used.
OUTPUT:
Returns itself, which ensures that :func:`poison_currRing` will stay in the debugger hook.
EXAMPLES::
sage: previous_trace_func = sys.gettrace() # None if no debugger running sage: from sage.libs.singular.ring import poison_currRing sage: sys.settrace(poison_currRing) sage: sys.gettrace() <built-in function poison_currRing> sage: sys.settrace(previous_trace_func) # switch it off again """ global currRing
cpdef print_currRing(): """ Print the ``currRing`` pointer.
EXAMPLES::
sage: from sage.libs.singular.ring import print_currRing sage: print_currRing() # random output DEBUG: currRing == 0x7fc6fa6ec480
sage: from sage.libs.singular.ring import poison_currRing sage: _ = poison_currRing(None, None, None) sage: print_currRing() DEBUG: currRing == 0x0 """
def currRing_wrapper(): """ Returns a wrapper for the current ring, for use in debugging ring_refcount_dict.
EXAMPLES::
sage: from sage.libs.singular.ring import currRing_wrapper sage: currRing_wrapper() The ring pointer ... """ |