# source:sage/rings/polynomial_singular_interface.py@1565:a793b9ce795e

Revision 1565:a793b9ce795e, 14.6 KB checked in by William Stein <wstein@…>, 7 years ago (diff)

Lots of circular import de-entanglement.

Line
1"""
2Polynomial Interfaces to Singular
3
4AUTHORS:
5     -- Martin Albrecht <malb@informatik.uni-bremen.de> (2006-04-21)
6
7"""
8
9#*****************************************************************************
10#
11#   SAGE: System for Algebra and Geometry Experimentation
12#
13#       Copyright (C) 2006 William Stein <wstein@gmail.com>
14#
16#
17#    This code is distributed in the hope that it will be useful,
18#    but WITHOUT ANY WARRANTY; without even the implied warranty of
19#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20#    General Public License for more details.
21#
22#  The full text of the GPL is available at:
23#
25#*****************************************************************************
26
27import finite_field
28
29from sage.interfaces.all import singular as singular_default, is_SingularElement
30from complex_field import is_ComplexField
31from real_field import is_RealField
32import sage.rings.arith
33
34class PolynomialRing_singular_repr:
35    """
36    Implements methods to convert polynomial rings to Singular.
37
38    This class is a base class for all univariate and multivariate
39    polynomial rings which support conversion from and to Singular
40    rings.
41    """
42    def _singular_(self, singular=singular_default):
43        """
44        Returns a singular ring for this polynomial ring over a field.
45        Currently QQ, GF(p), and GF(p^n), CC, and RR are supported.
46
47        INPUT:
48            singular -- Singular instance
49
50        OUTPUT:
51            singular ring matching this ring
52
53        EXAMPLES:
54            sage: r=MPolynomialRing(GF(2**8),10,'x', order='revlex')
55            sage: r._singular_()
56            //   characteristic : 2
57            //   1 parameter    : a
58            //   minpoly        : (a^8+a^4+a^3+a^2+1)
59            //   number of vars : 10
60            //        block   1 : ordering rp
61            //                  : names    x0 x1 x2 x3 x4 x5 x6 x7 x8 x9
62            //        block   2 : ordering C
63            sage: r=MPolynomialRing(GF(127),2,'x', order='revlex')
64            sage: r._singular_()
65            //   characteristic : 127
66            //   number of vars : 2
67            //        block   1 : ordering rp
68            //                  : names    x0 x1
69            //        block   2 : ordering C
70            sage: r=MPolynomialRing(QQ,2,'x', order='revlex')
71            sage: r._singular_()
72            //   characteristic : 0
73            //   number of vars : 2
74            //        block   1 : ordering rp
75            //                  : names    x0 x1
76            //        block   2 : ordering C
77            sage: r=PolynomialRing(QQ)
78            sage: r._singular_()
79            //   characteristic : 0
80            //   number of vars : 1
81            //        block   1 : ordering lp
82            //                  : names    x
83            //        block   2 : ordering C
84            sage: r=PolynomialRing(GF(127))
85            sage: r._singular_()
86            //   characteristic : 127
87            //   number of vars : 1
88            //        block   1 : ordering lp
89            //                  : names    x
90            //        block   2 : ordering C
91            sage: r=PolynomialRing(GF(2**8),'y')
92            sage: r._singular_()
93            //   characteristic : 2
94            //   1 parameter    : a
95            //   minpoly        : (a^8+a^4+a^3+a^2+1)
96            //   number of vars : 1
97            //        block   1 : ordering lp
98            //                  : names    y
99            //        block   2 : ordering C
100            sage: R.<x,y> = PolynomialRing(CC,2)
101            sage: R._singular_()
102            //   characteristic : 0 (complex:15 digits, additional 0 digits)
103            //   1 parameter    : I
104            //   minpoly        : (I^2+1)
105            //   number of vars : 2
106            //        block   1 : ordering dp
107            //                  : names    x y
108            //        block   2 : ordering C
109            sage: R.<x,y> = PolynomialRing(RealField(100),2)
110            sage: R._singular_()
111            //   characteristic : 0 (real:29 digits, additional 0 digits)
112            //   number of vars : 2
113            //        block   1 : ordering dp
114            //                  : names    x y
115            //        block   2 : ordering C
116
117        WARNING:
118           If the base ring is a finite extension field the ring will
119           not only be returned but also be set as the current ring in
120           Singular.
121
122        NOTE:
123            Singular represents precision of floating point numbers base 10
124            while SAGE represents floating point precision base 2.
125        """
126        try:
127            R = self.__singular
128            if not (R.parent() is singular):
129                raise ValueError
130            R._check_valid()
131            if self.base_ring().is_prime_field():
132                return R
133            if self.base_ring().is_finite():
134                R.set_ring() #sorry for that, but needed for minpoly
135                if  singular.eval('minpoly') != self.__minpoly:
136                    singular.eval("minpoly=%s"%(self.__minpoly))
137            return R
138        except (AttributeError, ValueError):
139            return self._singular_init_(singular)
140
141    def _singular_init_(self, singular=singular_default):
142        """
143        Return a newly created Singular ring matching this ring.
144        """
145        if not self._can_convert_to_singular():
146            raise TypeError, "no conversion of this ring to a Singular ring defined"
147
148        if self.ngens()==1:
149            _vars = str(self.gen())
150            if "*" in _vars: # 1.000...000*x
151                _vars = _vars.split("*")[1]
152            order = 'lp'
153        else:
154            _vars = str(self.gens())
155            order = self.term_order().singular_str()
156
157        if is_RealField(self.base_ring()):
158            # singular converts to bits from base_10 in mpr_complex.cc by:
159            #  size_t bits = 1 + (size_t) ((float)digits * 3.5);
160            precision = self.base_ring().precision()
161            digits = sage.rings.arith.ceil((2*precision - 2)/7.0)
162            self.__singular = singular.ring("(real,%d,0)"%digits, _vars, order=order)
163
164        elif is_ComplexField(self.base_ring()):
165            # singular converts to bits from base_10 in mpr_complex.cc by:
166            #  size_t bits = 1 + (size_t) ((float)digits * 3.5);
167            precision = self.base_ring().precision()
168            digits = sage.rings.arith.ceil((2*precision - 2)/7.0)
169            self.__singular = singular.ring("(complex,%d,0,I)"%digits, _vars,  order=order)
170
171        elif self.base_ring().is_prime_field():
172            self.__singular = singular.ring(self.characteristic(), _vars, order=order)
173            return self.__singular
174
175        elif self.base_ring().is_finite(): #must be extension field
176            gen = str(self.base_ring().gen())
177            r = singular.ring( "(%s,%s)"%(self.characteristic(),gen), _vars, order=order)
178            self.__minpoly = "("+(str(self.base_ring().modulus()).replace("x",gen)).replace(" ","")+")"
179            singular.eval("minpoly=%s"%(self.__minpoly) )
180
181            self.__singular = r
182        else:
183            raise TypeError, "no conversion to a Singular ring defined"
184        return self.__singular
185
186    def _can_convert_to_singular(self):
187        """
188        Returns True if this rings base field/ring can be represented in
189        Singular. If this is true then this polynomial ring can be
190        represented in Singular.
191
192        GF(p), GF(p^n), Rationals, Reals, and Complexes are supported.
193        """
194        base_ring = self.base_ring()
195        return ( finite_field.is_FiniteField(base_ring)
196                 or base_ring.is_prime_field()
197                 or is_RealField(base_ring)
198                 or is_ComplexField(base_ring) )
199
200
201class Polynomial_singular_repr:
202    """
203    Implements coercion of polynomials to Singular polynomials.
204
205    This class is a base class for all (univariate and multivariate)
206    polynomial classes which support conversion from and to
207    Singular polynomials.
208    """
209    def _singular_(self, singular=singular_default, have_ring=False):
210        """
211        Return Singular polynomial matching this polynomial.
212
213        INPUT:
214            singular -- Singular instance to use
215
216            have_ring -- if True we will not attempt to set this
217                         element's ring as the current Singular
218                         ring. This is useful to speed up a batch of
219                         f._singular_() calls. However, it's dangerous
220                         as it might lead to wrong results if another
221                         ring is singluar.current_ring().  (default:
222                         False)
223
224        EXAMPLES:
225            sage: R = PolynomialRing(GF(7))
226            sage: x = R.gen()
227            sage: f = (x^3 + 2*x^2*x)^7; f
228            3*x^21
229            sage: h = f._singular_(); h
230            3*x^21
231            sage: R(h)
232            3*x^21
233            sage: R(h^20) == f^20
234            True
235            sage: R = PolynomialRing(GF(7), 2, ['x','y'])
236            sage: x, y = R.gens()
237            sage: f = (x^3 + 2*y^2*x)^7; f
238            2*x^7*y^14 + x^21
239            sage: h = f._singular_(); h
240            x^21+2*x^7*y^14
241            sage: R(h)
242            2*x^7*y^14 + x^21
243            sage: R(h^20) == f^20
244            True
245        """
246        if not have_ring:
247            self.parent()._singular_(singular).set_ring() #this is expensive
248
249        try:
250            self.__singular._check_valid()
251            if self.__singular.parent() is singular:
252                return self.__singular
253        except (AttributeError,ValueError):
254            pass
255        return self._singular_init_(singular,have_ring=have_ring)
256
257    def _singular_init_(self, singular=singular_default, have_ring=False):
258        """
259        Return corresponding Singular polynomial but enforce that a new
260        instance is created in the Singular interpreter.
261
263        """
264        if not have_ring:
265            self.parent()._singular_(singular).set_ring() #this is expensive
266
267        self.__singular = singular(str(self))
268
269        return self.__singular
270
271    def lcm(self, right, have_ring=False):
272        """
273        Returns the least common multiple of this element and the right element.
274
275        INPUT:
276            right -- multivariate polynomial
277            have_ring -- see self._singular_() (default:False)
278
279        OUTPUT:
280            multivariate polynomial representing the least common
281            multiple of self and right
282
283        ALGORITHM: Singular
284
285        EXAMPLES:
286            sage: r=MPolynomialRing(GF(2**8),2,'x')
287            sage: x,y=r.gens()
288            sage: k=r.base_ring()
289            sage: f=k('a^2+a')*x^2*y + k('a^4+a^3+a')*y + k('a^5')
290            sage: f.lcm(x^4)
291            a^5*x0^4 + (a^4 + a^3 + a)*x0^4*x1 + (a^2 + a)*x0^6*x1
292        """
293        lcm = self._singular_(have_ring=have_ring).lcm(right._singular_(have_ring=have_ring))
294        return lcm.sage_poly(self.parent())
295
296##     def lt(self, have_ring=False):
297##         """
298##         Returns the leading (or initial) term of a polynomial
299##         with respect to the monomial ordering.
300
301##         INPUT:
302##             have_ring -- see self.singular_() (default: False)
303
304##         OUTPUT:
305##             multivariate polynomial representing the lead term of self i.e.,
306##             self.lc()*self.lm()
307
308##         ALGORITHM: Singular
309
310##         EXAMPLES:
311##             sage: r=MPolynomialRing(GF(2**8),2,'x')
312##             sage: x,y=r.gens()
313##             sage: k=r.base_ring()
314##             sage: f=k('a^2+a')*x^2 + k('a^4+a^3+a')*y^2 + k('a^5')
315##             sage: f.lt()
316##             (a^2 + a)*x0^2
317
318##             sage: r=MPolynomialRing(GF(2**8),2,'x','deglex')
319##             sage: x,y=r.gens()
320##             sage: k=r.base_ring()
321##             sage: f=k('a^2+a')*x^2 + k('a^4+a^3+a')*y^3 + k('a^5')
322##             sage: f.lt()
323##             (a^4 + a^3 + a)*x1^3
324
325##         """
326##         try:
327##             return self.__lt
328##         except AttributeError:
330##             return self.__lt
331
332##     def lm(self, have_ring=False):
333##         """
334##         Returns the leading monomial of a multivariate polynomial as a
335##         multivariate polynomial whose coefficient is one.
336
337##         INPUT:
338##             have_ring -- see self.singular_() (default: False)
339
340##         OUTPUT:
341##             multivariate polynomial representing the lead monomial of self
342
343##         ALGORITHM: Singular
344
345##         EXAMPLES:
346##             sage: r=MPolynomialRing(GF(2**8),2,'x')
347##             sage: x,y=r.gens()
348##             sage: k=r.base_ring()
349##             sage: f=k('a^2+a')*x^2 + k('a^4+a^3+a')*y^2 + k('a^5')
350##             sage: f.lm()
351##             x0^2
352
353##             sage: r=MPolynomialRing(GF(2**8),2,'x','deglex')
354##             sage: x,y=r.gens()
355##             sage: k=r.base_ring()
356##             sage: f=k('a^2+a')*x^2 + k('a^4+a^3+a')*y^3 + k('a^5')
357##             sage: f.lm()
358##             x1^3
359##         """
360##         try:
361##             return self.__lm
362##         except AttributeError:
364##             return self.__lm
365
366##     def lc(self, have_ring=False):
367##         """
368##         Returns the leading (or initial) coefficient of a polynomial
369##         with respect to the monomial ordering.
370
371##         INPUT:
372##             have_ring -- see self.singular_() (default: False)
373
374##         OUTPUT:
375##             multivariate polynomial representing the lead coefficent of self
376
377##         ALGORITHM: Singular
378
379##         EXAMPLES:
380##             sage: r=MPolynomialRing(GF(2**8),2,'x')
381##             sage: x,y=r.gens()
382##             sage: k=r.base_ring()
383##             sage: f=k('a^2+a')*x^2 + k('a^4+a^3+a')*y^2 + k('a^5')
384##             sage: f.lc()
385##             a^2 + a
386
387##             sage: r=MPolynomialRing(GF(2**8),2,'x','deglex')
388##             sage: x,y=r.gens()
389##             sage: k=r.base_ring()
390##             sage: f=k('a^2+a')*x^2 + k('a^4+a^3+a')*y^3 + k('a^5')
391##             sage: f.lc()
392##             a^4 + a^3 + a
393
394##             sage: R.<x,y,z> = PolynomialRing(QQ,3)
395##             sage: f = (-1/3)*(1+x+y+z)
396##             sage: (f^3).lc()
397##             -1/27
398##         """
399##         try:
400##             return self.__lc
401##         except AttributeError: