source: sage/libs/cf/cf.pyxe @ 1202:e3777ef67c1c

Revision 1202:e3777ef67c1c, 49.7 KB checked in by was@…, 7 years ago (diff)

Clean up loose ends after exporting the darcs repository to hg format.

Line 
1r"""
2Interface to the Factory library.
3
4AUTHORS:
5    -- Martin Albrecht <malb@informatik.uni-bremen.de> (2006-05-01)
6    -- William Stein (2006-05-07): trivial reformating of long lines
7
8From the Factory manual:
9
10    Factory is a C++ class library which implements a recursive
11    canonical form representation of polynomial data. The library
12    enables the user to use multivariate polynomials over different
13    base domains such as Z, Q, GF(q) and algebraic as well as
14    transcendental extensions of Q and GF(q).
15
16    Factory was developed at the University of Kaiserslautern as an
17    independent part of the computer algebra system singular which
18    uses parts of Factory such as polynomial gcd's and polynomial
19    factorization. This manual describes the features of Factory and
20    how to use it. Since Factory uses inheritance, operator
21    overloading and templates, it will be helpful if the reader has
22    already some experience in C++ programming.
23
24    Factory uses a recursive representation of multivariate polynomial
25    data. Each polynomial in Factory is represented as a univariate
26    polynomial with coefficients that can be polynomials too. To have
27    a unique representation of polynomials we have to fix an ordering
28    on the variables. This ordering is managed by Factory's level
29    system. The basic data type which is introduced by Factory is the
30    class CanonicalForm which handles polynomials as well as elements
31    of the base domain.
32
33This interface is mainly a one-to-one copy of the low level polynomial
34arithmetic implemented in the Factory. It follows Factory's concept of
35representing multivariate polynomials recursive as univariate
36polynomials over polynomial rings.
37
38When using this library keep that in mind and avoid relying on
39variable names (i.e. strings) when interfacing this code with the rest
40of SAGE. Variables in the Factory are uniquely represented through
41their level and not their name (which may only have one character
42btw.)
43
44So far only integers, GF(p), and GF(p^n) have been inplemented as base
45domains.
46
47EXAMPLES:
48    sage: F = GF(5)
49    sage: cf.setBaseDomain(F)
50    sage: R = MPolynomialRing(F,2, names = ['x','y'])
51    sage: x,y = R.gens()
52    sage: f = y**2-x**9-x
53    sage: f == (cf.CF(y)**2-cf.CF(x)**9 - x)._sage_(R)
54    True
55    sage: n = 3
56    sage: astr = ['a'+str(i) for i in range(1,2*n)]
57    sage: R0 = MPolynomialRing(F,2*n+2,names = [str(x),str(y),'t']+astr)
58    sage: vars0 = R0.gens()
59    sage: t = vars0[2]
60    sage: xt = add([vars0[i]*t**(i-2) for i in range(3,2*n+2)])
61    sage: yt = t
62    sage: ft = f(xt,yt)
63    sage: ft == cf.CF(f)([(x,cf.CF(xt)),(y,cf.CF(yt))])._sage_(R0) #fast!
64    True
65
66\note{This interface is not very SAGE-ish and is rather meant to
67function as a backend for higher level classes like
68MPolynomial_polydict for fast polynomial arithmetic.  This libary is a
69bit behind Singluar if we shuffle few data to the engine, do lot's of
70computation and shuffle some data back. This loss of performance is
71believed to be due to the clumsy way we deal with memory allocation
72which can be addresses. If we shuffle around alot of data between SAGE
73and Singular it's performance decreases alot as much IPC overhead is
74involved, while Factory beats the native implementation.}
75
76TODO: Refactor to avoid memory allocations.
77"""
78
79#*****************************************************************************
80#
81#   SAGE: System for Algebra and Geometry Experimentation   
82#
83#       Copyright (C) 2006 William Stein <wstein@ucsd.edu>
84#
85#  Distributed under the terms of the GNU General Public License (GPL)
86#
87#    This code is distributed in the hope that it will be useful,
88#    but WITHOUT ANY WARRANTY; without even the implied warranty of
89#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
90#    General Public License for more details.
91#
92#  The full text of the GPL is available at:
93#
94#                  http://www.gnu.org/licenses/
95#*****************************************************************************
96
97
98#header{
99#include <factory.h>
100#include <iostream>
101#include <sstream>
102using namespace std;
103#}header
104
105cdef extern from "stdlib.h":
106    void free(void *ptr)
107
108#################################
109#cdef int _sig_on
110#cdef int _sig_off
111#cdef int _sig_check
112include 'interrupt.pxi'
113#################################
114
115include 'misc.pxi'
116
117cdef class Variable:
118
119    """
120    The class Variable defines a programming interface to the level
121    system of Factory.  Each object of class Variable refers to a
122    level and thus to a variable (determined by the level) of the
123    polynomial ring. Objects of class Variable must not only refer to
124    variables of the polynomial ring, but also to so called algebraic
125    and transcendental variables.
126
127    Arithmetic with Variables can be pretty weird, consider this:
128
129        sage: 1000*cf.Variable(1)
130        v_1*v_1000
131
132    This behavior is correct as 1000 is coerced into a Variable of
133    level 1000 whichs default name happens to be'v_1000'
134    """
135
136    cdef void *thisptr
137
138    def __init__(self, name=None, level=None):
139        """
140        The class Variable defines a programming interface to the
141        level system of Factory.  Each object of class Variable refers
142        to a level and thus to a variable (determined by the level) of
143        the polynomial ring. Objects of class Variable must not only
144        refer to variables of the polynomial ring, but also to so
145        called algebraic and transcendental variables.
146
147        INPUT:
148
149            name -- The level of the variable is specified to be the
150                    level of the variable which has name name. That means that
151                    the generated object can not only be a polynomial variable
152                    but also an algebraic or transcendental variable. In the
153                    case that there is no variable with name name the
154                    generated variable refers to the anonymous polynomial
155                    variable which has the lowest level. After the
156                    construction the name of the variable is set to name.
157
158            If name is an integer it is interpreted as a level.
159
160            level -- The constructor generates an object of class
161                     Variable with level set to level.  level has to be a level
162                     of a polynomial variable or of a transcendental variable.
163
164        The default constructor creates an object with level set to
165        LEVEL_BASEDOMAIN. Such a variable evaluates into the unit
166        element of the current base domain when converted to a
167        CanonicalForm
168        """
169        #embed{ void *Variable_init()
170            return new Variable();
171        #}embed
172
173        #embed{ void *Variable_initn(char name)
174            return new Variable(name);
175        #}embed
176
177        #embed{ void *Variable_initl(int level)
178            return new Variable(level);
179        #}embed
180
181        #embed{ void *Variable_initln( int level, char name)
182            return new Variable(level,name);
183        #}embed
184
185        cdef char *cNameStr
186        cdef char cName
187
188        from sage.ext.integer import Integer
189
190        if isinstance(name,int) or isinstance(name,Integer):
191            level=name
192            name =None
193
194        if name != None and isinstance(name,str):
195            cNameStr = name
196            cName = cNameStr[0]
197            if level!=None:
198                self.thisptr = Variable_initln(int(level), cName)
199            else:
200                self.thisptr = Variable_initn(cName)
201        else:
202            if level!=None:
203                self.thisptr = Variable_initl(int(level))
204            else:
205                self.thisptr = Variable_init()
206
207    def __dealloc__(Variable self):
208        delete_Variable(self.thisptr)
209
210    def level(self):
211        """
212        Returns the level of this variable.
213        """
214        #embed{ int Variable_level(void *obj)
215        return ((Variable *)obj)->level();
216        #}embed
217
218        return Variable_level(self.thisptr)
219
220    def name(Variable self):
221        """
222        Returns the name of this variable. Do not identify a Variable
223        via it's name() us it's level() instead.
224        """
225        #embed{ char Variable_name(void *obj)
226        return ((Variable *)obj)->name();
227        #}embed
228
229        # this is slow, but I crashed the nativ way
230        return str(CanonicalForm(self))
231
232    def highest(self):
233        #embed{ void *Variable_highest(void *obj)
234            return new Variable(((Variable *)obj)->highest());
235        #}embed
236        _sig_on
237        return make_Variable(Variable_highest(self.thisptr))
238
239    def next(self):
240        """
241        This method returns an object of class Variable which refers
242        to the variable which has the same level as self increased by
243        one.
244        """
245        #embed{ void *Variable_next(void *obj)
246            return new Variable(((Variable *)obj)->next());
247        #}embed
248        _sig_on
249        return make_Variable(Variable_next(self.thisptr))
250
251    def __cmp__(self, Variable other):
252        """
253        Comparison is performed by comparing the levels.
254        """
255        #embed{ int Variable_cmp(void *obj,void *obj2)
256        if(*(Variable *)obj == *(Variable *)obj2) {
257           return 0;
258        } else if( *(Variable *)obj < *(Variable *)obj2) {
259           return -1;
260        } else if( *(Variable *)obj > *(Variable *)obj2) {
261           return 1;
262        }   
263        #}embed
264
265        return Variable_cmp(self.thisptr,other.thisptr)
266
267    def __add__(self, other):
268        return CanonicalForm(self) + CanonicalForm(other)
269
270    def __sub__(self, other):
271        return CanonicalForm(self) - CanonicalForm(other)
272
273    def __mul__(self, other):
274        return CanonicalForm(self) * CanonicalForm(other)
275
276    def __div__(self, other):
277        return CanonicalForm(self) / CanonicalForm(other)
278
279    def __pow__(self, long other, ignored):
280        return CanonicalForm(self)**other
281
282    def __mod__(self, other):
283        return CanonicalForm(self) % CanonicalForm(other)
284
285    def __repr__(self):
286        #embed{ char *Variable_to_str(void* x)
287        ostringstream instore;
288        instore << *(Variable*)x ;
289        int n = strlen(instore.str().data());
290        char* buf = (char*)malloc(n+1);
291        strcpy(buf, instore.str().data());
292        #}embed
293
294##         cdef char *ret
295##         _sig_on
296##         ret = Variable_to_str(self.thisptr)
297##         _sig_off
298##         return string(ret)
299
300        #might be slow but it kept crashing otherwise
301        return str(CanonicalForm(self))
302
303
304
305
306#embed{ void delete_Variable( void *obj)
307if(obj) {
308    delete ((Variable*)obj);
309}
310#}embed
311
312cdef make_Variable(void *x):
313    """
314    """
315    cdef Variable y
316    _sig_off
317    y = Variable()
318    delete_Variable(y.thisptr)
319    y.thisptr = x
320    return y
321
322cdef class CanonicalForm:
323    """
324    CanonicalForm is the main class in the Factory
325    """
326    cdef void *thisptr
327    cdef void *iterator
328
329    def __init__(self,arg=None, arg2=None, kcache=None):
330        """
331        If arg is a Variable and exp==None this constructor generates
332        a canonical form out of the variable arg.  If the level of x
333        is the level of the base domain (LEVEL_BASEDOMAIN) then the
334        unit element of the current base domain is created.
335
336        If arg is an integer this constructor generates an object of
337        class CanonicalForm out of this integer. In the case of a
338        finite base domain the canonical mapping of the integers into
339        the domain is used.
340
341        If arg is a Variable and exp is an integer this constructor
342        generates an object of class CanonicalForm, which is the
343        polynomial arg^exp. In the case that x has level
344        LEVEL_BASEDOMAIN the unit element of the current base domain
345        is created.
346
347        If arg is a SAGE polynomial this constructor generates an
348        object of class CanonicalForm, which is a representaion of arg
349        over currently active base domain.  If arg is defined over a
350        finite extension field arg2 must be an algebraic Variable
351        representing this field. Those variables are returned by
352        setBaseDomain when called with a finite extension field as
353        parameter.
354
355        If arg is a string it is parsed by the CF library. It is not
356        recommended to use string IO for communication with this
357        library as names are not unique in this library and the result
358        might not match the expectations. The best practice here is to
359        construct a SAGE ring, pass the string to that ring and pass
360        the newly constructed SAGE polynomial to this library.
361
362        INPUT:
363            arg --   integer, Variable, Polynomial, or string
364            arg2 --  optional second argument in dependence of first one
365            kcache -- optional base field cache to use MPolynomial elements
366
367        EXAMPLES:
368            sage: R=PolynomialRing(GF(127),2)
369            sage: f=R('3234*x0*x1+6575*x0^2+52')
370            sage: cf.setBaseDomain(GF(127))
371            sage: cf.CF(f)
372            59*v_1*v_2+98*v_1^2+52
373            sage: cf.CF(f)._sage_(R)
374            52 + 59*x0*x1 + 98*x0^2
375            sage: cf.CF(f)._sage_(R)==f
376            True
377        """
378        #embed{ void *CF_init()
379            return new CanonicalForm();   
380        #}embed
381
382        #embed{ void *CF_initi(int arg)
383            return new CanonicalForm(arg);   
384        #}embed
385   
386        #embed{ void *CF_initV(void *arg)
387            return new CanonicalForm(*(Variable *)arg);
388        #}embed
389
390        #embed{ void *CF_initVn(void *arg, int exp)
391            return new CanonicalForm(*(Variable *)arg,exp);
392        #}embed
393
394        #embed{ void *CF_copy(void *arg)
395            return new CanonicalForm(*(CanonicalForm *)arg);
396        #}embed
397
398        #embed{ void *str_to_CF(char* s)
399            istringstream in;
400            in.str( s );
401            CanonicalForm* y = new CanonicalForm();
402            in >> *y;
403            return y;
404        #}embed
405
406        #embed{ void CF_polygen(void *ret, int c, int level, long e)
407            *(CanonicalForm*)ret += c * CanonicalForm(Variable(level),e);
408        #}embed
409
410        #embed{ void CF_mongen(void *ret, int level, long e)
411            if(e!=0)
412                *(CanonicalForm*)ret *= CanonicalForm(Variable(level),e);
413        #}embed
414
415        cdef CanonicalForm cPoly
416        cdef CanonicalForm t
417        cdef int varlevel
418
419        from sage.rings.multi_polynomial_element import is_MPolynomialRingElement
420        from sage.rings.field_element import is_FieldElement
421        from sage.rings.polynomial_element import is_Polynomial
422
423        # maybe a switch-case dict might be faster here?
424        if is_FieldElement(arg) and arg.parent().degree()!=1:
425            cPoly = CF(0)
426            if not isinstance(arg2,Variable):
427                arg2 = setBaseDomain(arg.parent())
428            varlevel  = arg2.level()
429            f = arg._pari_().lift().lift()
430            if f.poldegree() == 0:
431                self.thisptr = CF_initi(int(f))
432                return
433            for i from 0 <= i <= f.poldegree():
434                CF_polygen(cPoly.thisptr,int(f[i]),varlevel,i)
435            self.thisptr = cPoly.thisptr
436            return
437
438        elif is_MPolynomialRingElement(arg):
439            poly = CF(0)
440            for e,c in arg.element().dict().iteritems():
441                t = CF(0)
442                if kcache!=None:
443                    if not kcache.has_key(c):
444                        kcache[c]=CF(c,arg2)
445                    t = t + kcache[c]
446                else:
447                    t = t + CF(c,arg2)
448                for i in e.nonzero_positions():
449                    CF_mongen(t.thisptr,i+1,e[i])
450                poly = poly + t
451            cPoly = poly
452            self.thisptr = cPoly.thisptr
453            return
454
455        elif is_Polynomial(arg):
456            cPoly = CF(0)
457            v = Variable(1)
458            #TODO: speed can be improved here
459            for i from 0 <= i <= arg.degree():
460                cPoly = cPoly + CF(arg[i])*CF(v,i)
461            self.thisptr = cPoly.thisptr
462
463        elif isinstance(arg,CanonicalForm):
464            self.thisptr = CF_copy(<void*>(<CanonicalForm>arg).thisptr)
465
466        elif isinstance(arg,Variable) and arg2==None:
467            self.thisptr = CF_initV(<void*>(<Variable>arg).thisptr)
468
469        elif isinstance(arg,Variable) and arg2!=None:
470            self.thisptr = CF_initVn(<void*>(<Variable>arg).thisptr,int(arg2))
471
472        elif isinstance(arg,str):
473            arg = "".join([arg,";"])
474            self.thisptr = str_to_CF(arg)
475
476        elif arg==None:
477            self.thisptr = CF_init()
478
479        else:
480            try:
481                arg = int(arg)
482                self.thisptr = CF_initi(arg)
483            except:
484                raise TypeError, "Cannot create CanonicalForm with params %s and %s"%(arg, arg2)
485
486    def __repr__(self):#
487        """
488        """
489        #embed{ char *CF_to_str(void* x)
490        ostringstream instore;
491        instore << *(CanonicalForm*)x ;
492        int n = strlen(instore.str().data());
493        char* buf = (char*)malloc(n+1);
494        strcpy(buf, instore.str().data());
495        return buf;
496        #}embed
497
498        cdef char *ret
499        _sig_on
500        ret = CF_to_str(self.thisptr)
501        return string(ret)
502
503    def __add__(left, right):
504        #embed{ void *CF_add(void *l, void *r)
505        return new CanonicalForm((*(CanonicalForm*)l) + (*(CanonicalForm*)r));
506        #}embed
507
508        if not isinstance(left,CanonicalForm):
509            left,right = right,left
510        if not isinstance(right,CanonicalForm):
511            right = CanonicalForm(right)
512        _sig_on
513        return make_CF(CF_add((<CanonicalForm>left).thisptr,(<CanonicalForm>right).thisptr))
514
515    def __sub__(left, right):
516        #embed{ void *CF_sub(void *l, void *r)
517        return new CanonicalForm((*(CanonicalForm*)l) - (*(CanonicalForm*)r));
518        #}embed
519        cdef CanonicalForm cRight
520        cdef CanonicalForm cLeft
521        try:
522            cRight = CanonicalForm(right)
523            cLeft = CanonicalForm(left)
524        except TypeError:
525            raise ArithmeticError, "Cannot subtract %s from %s"%(right,left)
526        _sig_on
527        return make_CF(CF_sub(cLeft.thisptr,cRight.thisptr))
528
529    def __mul__(left, right):
530        #embed{ void *CF_mul(void *l, void *r)
531        return new CanonicalForm((*(CanonicalForm*)l) * (*(CanonicalForm*)r));
532        #}embed
533
534        cdef CanonicalForm cRight
535        cdef CanonicalForm cLeft
536        try:
537            cRight = CanonicalForm(right)
538            cLeft = CanonicalForm(left)
539        except TypeError:
540            raise ArithmeticError, "Cannot multiply %s and %s"%(left,right)
541        _sig_on
542        return make_CF(CF_mul(cLeft.thisptr,cRight.thisptr))
543
544    def __div__(left, right):
545        #embed{ void *CF_div(void *l, void *r)
546        return new CanonicalForm((*(CanonicalForm*)l) / (*(CanonicalForm*)r));
547        #}embed
548
549        cdef CanonicalForm cRight
550        cdef CanonicalForm cLeft
551        try:
552            cRight = CanonicalForm(right)
553            cLeft = CanonicalForm(left)
554        except TypeError:
555            raise ArithmeticError, "Cannot divide %s through %s"%(left,right)
556        _sig_on
557        return make_CF(CF_div(cLeft.thisptr,cRight.thisptr))
558
559    def __pow__(CanonicalForm self,long e, ignored):
560        #embed{ void *CF_pow(void *l, long e)
561        return new CanonicalForm( power((*(CanonicalForm*)l),e) );
562        #}embed
563        _sig_on
564        return make_CF(CF_pow(self.thisptr, e))
565
566    def __neg__(CanonicalForm self):
567        #embed{ void *CF_neg(void *l)
568        return new CanonicalForm(-(*(CanonicalForm*)l));
569        #}embed
570        _sig_on
571        return make_CF(CF_neg(self.thisptr))
572
573##    Commenting out all in place arithmetic as SAGE does not use in
574##    place arithmetic, e.g. when you e += 1 for an element which is
575##    also an element of a list the element in the list does not
576##    change in SAGE.
577
578##
579##     def __iadd__(CanonicalForm self,other):
580##         #embed{ void CF_iadd(void *l, void *r)
581##         (*(CanonicalForm*)l) += (*(CanonicalForm*)r);
582##         #}embed
583
584##         cdef CanonicalForm cOther
585##         try:
586##             cOther = CanonicalForm(other)
587##         except TypeError:
588##             raise ArithmeticError, "Cannot add %s and %s"%(self,other)
589
590##         CF_iadd(self.thisptr,cOther.thisptr)
591##         return self
592
593##     def __isub__(CanonicalForm self, other):
594##         #embed{ void *CF_isub(void *l, void *r)
595##         (*(CanonicalForm*)l) -= (*(CanonicalForm*)r);
596##         #}embed
597##         cdef CanonicalForm cOther
598##         try:
599##             cOther = CanonicalForm(other)
600##         except TypeError:
601##             raise ArithmeticError, "Cannot subtract %s from %s"%(other,self)
602##         CF_isub(self.thisptr,cOther.thisptr)
603##         return self
604
605##     def __imul__(CanonicalForm self, other):
606##         #embed{ void *CF_imul(void *l, void *r)
607##         (*(CanonicalForm*)l) *= (*(CanonicalForm*)r);
608##         #}embed
609
610##         cdef CanonicalForm cOther
611##         try:
612##             cOther = CanonicalForm(other)
613##         except TypeError:
614##             raise ArithmeticError, "Cannot multiply %s and %s"%(self,other)
615
616##         CF_imul(self.thisptr,cOther.thisptr)
617##         return self
618
619##     def __idiv__(CanonicalForm self, other):
620##         #embed{ void CF_idiv(void *l, void *r)
621##         (*(CanonicalForm*)l) /= (*(CanonicalForm*)r);
622##         #}embed
623
624##         cdef CanonicalForm cOther
625##         try:
626##             cOther = CanonicalForm(other)
627##         except TypeError:
628##             raise ArithmeticError, "Cannot divide %s through %s"%(self,other)
629
630##         CF_idiv(self.thisptr,cOther.thisptr)
631##         return self
632
633##     def __ipow__(CanonicalForm self,long e, ignored):
634##         #embed{ void CF_ipow(void *l, long e)
635##         (*(CanonicalForm*)l) = power((*(CanonicalForm*)l),e);
636##         #}embed
637##         CF_ipow(self.thisptr,e)
638##         return self
639
640
641    def __cmp__(CanonicalForm self,other):
642        """
643        It is possible to compare two canonical forms. Therefore, you can use
644        this operator. The behaviour of < and > in the case of polynomials is
645        not fixed yet, but may deal with levels and degrees in a future
646        release of the Factory library.
647        """
648        #embed{ int CF_cmp(void *obj,void *obj2)
649        if( *(CanonicalForm *)obj == *(CanonicalForm *)obj2 ) {
650           return 0;
651        } else if(*(CanonicalForm *)obj < *(CanonicalForm *)obj2) {
652           return -1;
653        } else if(*(CanonicalForm *)obj > *(CanonicalForm *)obj2) {
654           return 1;
655        }
656        #}embed
657
658        cdef int res
659        cdef CanonicalForm cOther
660        if not isinstance(other, CanonicalForm):
661            try:
662                cOther = CanonicalForm(other)
663            except TypeError:
664                raise TypeError, "Cannot compare %s and %s"%(self,other)
665        else:
666            cOther = other
667        _sig_on
668        res = CF_cmp(self.thisptr,cOther.thisptr)
669        _sig_off
670        return res
671
672    def __mod__(CanonicalForm self, other):
673        #embed{ void *CF_mod(void *l, void *r)
674        return new CanonicalForm((*(CanonicalForm*)l) % (*(CanonicalForm*)r));
675        #}embed
676
677        cdef CanonicalForm cOther
678        try:
679            cOther = CanonicalForm(other)
680        except TypeError:
681            raise ArithmeticError, "Cannot take %s modulo %s"%(self,other)
682        _sig_on
683        return make_CF(CF_mod(self.thisptr,cOther.thisptr))
684
685    def __getitem__(CanonicalForm self, i):
686        """
687        operator [] - return i'th coefficient from self.
688
689        Returns self if self is in a base domain and i equals zero.
690        Returns zero (from the current domain) if self is in a base
691        domain and i is larger than zero.  Otherwise, returns the
692        coefficient to x^i in self (if x denotes the main variable of
693        self) or zero if self does not contain x^i.  Elements in an
694        algebraic extension are considered polynomials.  i should be
695        larger or equal zero.
696
697        INPUT:
698            i -- exponent, this may be a tuple of exponents
699
700        EXAMPLE:
701            sage: r=MPolynomialRing(ZZ,2,['x','y'])
702            sage: x,y = r.gens()
703            sage: cf.setBaseDomain(ZZ)
704            sage: f=cf.CF(3*x*y^2)
705            sage: f[1]
706            0
707            sage: f[2]
708            3*v_1
709            sage: f[2,1]
710            3
711
712        NOTE:
713            Never use a loop like
714
715            for i in range(f.degree( )):
716                print f[ i ]
717
718            which is much slower than
719
720            for c in f:
721                print c
722
723        """
724        #embed{ void *CF_getitem(void *e,int i)
725        if (((CanonicalForm*)e)->degree() < i) {
726            return new CanonicalForm(0);
727        } else {
728            return new CanonicalForm((*(CanonicalForm*)e)[i]);
729        }
730        #}embed
731        cdef void *ret
732        if isinstance(i,int):
733            _sig_on
734            ret = CF_getitem(self.thisptr,i)
735            return make_CF(ret)
736        elif isinstance(i,tuple):
737            _sig_on
738            ret = self.thisptr
739            for j in i:
740                ret = CF_getitem(ret,int(j))
741            return make_CF(ret)
742        else:
743            raise TypeError, "Cannot return coefficent for %s"%i
744
745    def __iter__(CanonicalForm self):
746        """
747        Iterator with respect to the main variable. It returns
748        coeffients and expontents of terms. You may get the
749        variable these refer to by calling mvar() on self.
750        """
751        return self
752
753    def __next__(CanonicalForm self):
754        """
755        Iterator implementation.
756        """
757        #embed{ void *CF_iterinit(void *e)
758        return new CFIterator(*(CanonicalForm*)e);
759        #}embed
760
761        #embed{ void *CF_iter(void *it, int *exp)
762        if(((CFIterator*)it)->hasTerms()) {
763            CanonicalForm *ret = new CanonicalForm(((CFIterator*)it)->coeff());
764            *exp = ((CFIterator*)it)->exp();
765            (*(CFIterator*)it)++;
766            return ret;
767        } else {
768            return NULL;
769        }
770        #}embed
771
772        cdef void *ret
773        cdef int exp
774
775        if self.is_zero():
776            raise StopIteration
777
778        if self.iterator == NULL:
779            self.iterator = CF_iterinit(self.thisptr)
780
781        _sig_on
782        ret = CF_iter(self.iterator,&exp)
783        _sig_off
784        if ret!=NULL:
785            _sig_on
786            return (make_CF(ret),exp)
787        else:
788            self.iterator = CF_iterinit(self.thisptr)
789            raise StopIteration
790
791    def __call__(CanonicalForm self, arg):
792        """
793        Returns the current object with the substitution described
794        through arg performed.
795
796        If arg is a list or tuple and it's elements are not tuples it
797        is interpreted as a list of values to substituted in at their
798        list index.
799
800        If arg is a list or tuple and it's elements are tuples with
801        two elements then it is interpreted to hold the variable to be
802        substitute as the first element of those tuples and the value
803        to be substituted in as the second.
804
805        If arg is a dict it's keys are interpreted to describe the
806        variables and the matching values the values to be substituted
807        in.
808
809        INPUT:
810            arg -- tuple, list or dict to describe substitution
811
812        EXAMPLES:
813            sage: f=cf.CF(3)*cf.Variable(1)*cf.Variable(2)
814            sage: f
815            3*v_1*v_2
816            sage: f((cf.Variable(1),'2'))
817            6*v_1
818            sage: f((3,2))
819            18
820
821        """
822        #embed{ void CF_call(void *self, void *f, void *x)
823        (*(CanonicalForm*)self) = (*(CanonicalForm*)self)(*(CanonicalForm*)f,*(Variable*)x);
824        #}embed
825
826        cdef void *r
827        cdef Variable x
828        cdef CanonicalForm f
829
830        if isinstance(arg,tuple) or isinstance(arg,list):
831            if not isinstance(arg[0],tuple) and len(arg)==self.mvar().level():
832                r = CF_copy(self.thisptr)   
833                _sig_on
834                for i from 0 <= i < len(arg):
835                    f = CanonicalForm(arg[i])
836                    x = Variable(i+1)
837                    CF_call(r,f.thisptr,x.thisptr)
838                return make_CF(r)
839            elif len(arg[0])==2:
840                r = CF_copy(self.thisptr)
841                _sig_on
842                for var,val in arg:
843                    f = CanonicalForm(val)
844                    x = CanonicalForm(var).mvar() #safer than calling Variable
845                    CF_call(r,f.thisptr,x.thisptr)
846                return make_CF(r)
847        elif isinstance(arg,dict):
848            r = CF_copy(self.thisptr)
849            _sig_on
850            for var,val in arg.iteritems():
851                f = CanonicalForm(val)
852                x = CanonicalForm(var).mvar() #safer than calling Variable
853                CF_call(r,f.thisptr,x.thisptr)
854            return make_CF(r)
855        else:
856            raise TypeError, "Cannot substitute with parameter %s"%arg
857
858    def is_one(CanonicalForm self):
859        """
860        This predicate returns true if self represents the unit
861        element of the current base domain. There is also the
862        possibiliy to test if a CanonicalForm f is one via f == 1, but
863        f.is_one() is faster since there is no conversion of the
864        integer 1 into a CanonicalForm and then doing a comparison of
865        two objects of class CanonicalForm.
866        """
867        #embed{ int CF_isOne(void *e)
868        return ((CanonicalForm*)e)->isOne();
869        #}embed
870        return bool(CF_isOne(self.thisptr))
871
872    def is_zero(CanonicalForm self):
873        """
874        This predicate returns true if self represents the zero
875        element of the current base domain. Like the predicate is_one
876        using the predicate f.is_zero() is also faster than a
877        comparison via f == 0.
878        """
879        #embed{ int CF_isZero(void *e)
880        return ((CanonicalForm*)e)->isZero();
881        #}embed
882
883        return bool(CF_isZero(self.thisptr))
884
885    def is_imm(CanonicalForm self):
886        """
887        This predicate returns true if self is represented as an
888        immediate object (e.g. is a small integer or an object of a
889        finite base field).  See Chapter 14 [Internal Design], page
890        21, for information about how immediate objects are
891        represented.
892
893        The return value represents if self is represented as a
894        immediate value in the Factory and makes no statement about
895        this element in SAGE.
896        """
897        #embed{ int CF_isImm(void *e)
898        return ((CanonicalForm*)e)->isImm();
899        #}embed
900        return bool(CF_isImm(self.thisptr))
901
902    def _int_(CanonicalForm self):
903        """
904        This selector returns the integer value of self. This is only
905        valid if the value of self is in the range of the machine
906        integers. A good way to find out if this is the case is to
907        test if the current object is an immediate object via
908        self.is_imm().
909        """
910        #embed{ int CF_intval(void *e)
911        return ((CanonicalForm*)e)->intval();
912        #}embed
913        return CF_intval(self.thisptr)
914
915    def lc(CanonicalForm self):
916        """
917        Returns the leading coefficient of self with respect to
918        lexicographic ordering.  Elements in an algebraic extension
919        are considered polynomials so lc() always returns a leading
920        coefficient in a base domain.  This method is useful to get
921        the base domain over which self is defined.
922
923        Returns self if self is in a base domain.
924        """
925        #embed{ void *CF_lc(void *e)
926        return new CanonicalForm(((CanonicalForm*)e)->lc());
927        #}embed
928        _sig_on
929        return make_CF(CF_lc(self.thisptr))
930
931    def Lc(CanonicalForm self):
932        """
933        Returns the leading coefficient of self with respect to
934        lexicographic ordering.  In contrast to lc() elements in an
935        algebraic extension are considered coefficients so Lc() always
936        returns a leading coefficient in a coefficient domain.
937
938        Returns self if self is in a base domain.
939        """
940        #embed{ void *CF_Lc(void *e)
941        return new CanonicalForm(((CanonicalForm*)e)->Lc());
942        #}embed
943        _sig_on
944        return make_CF(CF_Lc(self.thisptr))
945
946    def LC(CanonicalForm self, v=None):
947        """
948        LC( ) returns the leading coefficient of self where self is
949        considered a univariate polynomial in its main variable.  An
950        element of an algebraic extension is considered an univariate
951        polynomial, too.
952
953        LC( v ) returns the leading coefficient of CO where CO is
954        considered an univariate polynomial in the polynomial variable v.
955
956        Returns self if self is in a base domain.
957
958        INPUT:
959            v -- if set the leading coefficient with respect to this
960                variable is returned.
961        OUTPUT:
962            CanonicalForm representing the lead coefficient.
963
964
965        """
966        #embed{ void *CF_LC(void *e,void *v)
967        if (v == NULL) {
968            return new CanonicalForm(((CanonicalForm*)e)->LC());
969        } else {
970            return new CanonicalForm( ((CanonicalForm*)e)->LC( *((Variable*)v) ) );
971        }
972        #}embed
973
974        if v==None:
975            _sig_on
976            return make_CF(CF_LC(self.thisptr,NULL))
977
978        if not isinstance(v, Variable):
979            v = Variable(v)
980        _sig_on
981        return make_CF(CF_LC(self.thisptr,(<Variable>v).thisptr))
982
983    def total_degree(CanonicalForm self):
984        """
985        Returns the total degree of self.
986        """
987        #embed{ int CF_total_degree(void *e)
988        return totaldegree(*(CanonicalForm*)e);
989        #}embed
990        return CF_total_degree(self.thisptr)
991
992    def degree(CanonicalForm self, x=None):
993        """
994        This selector returns the degree of self with respect to its
995        main variable or a provided variable.  If self is an element
996        of a coefficient domain the returned degree is zero except
997        that the current object represents the zero of a base domain
998        in which case -1 is returned.
999
1000        INPUT:
1001            variable -- if set the degree with respect to this
1002            variable will be returned.
1003        """
1004
1005        #embed{ int CF_degree(void *e,void *x)
1006        if (x == NULL) {
1007            return ((CanonicalForm*)e)->degree();
1008        } else {
1009            return ((CanonicalForm*)e)->degree( *((Variable*)x) );
1010        }
1011        #}embed
1012
1013        if x==None:
1014            return CF_degree(self.thisptr,NULL)
1015
1016        if not isinstance(x,Variable):
1017            variable = Variable(x)
1018        return CF_degree(self.thisptr,(<Variable>x).thisptr)
1019
1020    def lt(CanonicalForm self):
1021        """
1022        Returns the leading term with respect to the main variable.
1023
1024        This is equivalent to head() in the Factory C++ API.
1025        """
1026        #embed{ void *CF_head(void *e)
1027        return new CanonicalForm(head(*(CanonicalForm*)e));
1028        #}embed
1029        _sig_on
1030        return make_CF(CF_head(self.thisptr))
1031
1032    def tail(CanonicalForm self):
1033        """
1034        Returns f - lt(f)
1035        """
1036        #embed{ void *CF_tail(void *e)
1037        return new CanonicalForm((*(CanonicalForm*)e) - head(*(CanonicalForm*)e));
1038        #}embed
1039        _sig_on
1040        return make_CF(CF_tail(self.thisptr))
1041
1042
1043    def tailcoeff(CanonicalForm self):
1044        """
1045        This selector returns the tail coefficient of self. That is
1046        the non vanishing coefficient of the term with the lowest
1047        exponent. If self represents the zero element of a base domain
1048        then zero is returned.
1049        """
1050        #embed{ void *CF_tailcoeff(void *e)
1051        return new CanonicalForm(((CanonicalForm*)e)->tailcoeff());
1052        #}embed
1053        _sig_on
1054        return make_CF(CF_tailcoeff(self.thisptr))
1055
1056    def taildegree(CanonicalForm self):
1057        """
1058        This selector returns the lowest exponent of the terms of self
1059        that have non vanishing coefficients. If the self represents
1060        the zero element of a base domain then None is returned.
1061        """
1062        #embed{ int CF_taildegree(void *e)
1063        return ((CanonicalForm*)e)->taildegree();
1064        #}embed
1065
1066        cdef res
1067        res = CF_taildegree(self.thisptr)
1068        if res==-1:
1069            return
1070        else:
1071            return res
1072
1073    def mvar(CanonicalForm self):
1074        """
1075        This selector returns the main varible of self.  If self is an
1076        element of a base domain then Variable(LEVEL_BASEDOMAIN) is
1077        returned.
1078        """
1079        #embed{ void *CF_mvar(void *e)
1080        return new Variable(((CanonicalForm*)e)->mvar());
1081        #}embed
1082        _sig_on
1083        return make_Variable(CF_mvar(self.thisptr))
1084
1085    def level(CanonicalForm self):
1086        """
1087        This selector returns the level of the main variable of self.
1088        """
1089
1090        #embed{ int CF_level(void *e)
1091        return ((CanonicalForm*)e)->level();
1092        #}embed
1093
1094        return CF_level(self.thisptr)
1095
1096    def mapinto(CanonicalForm self, mapMe = False):
1097        """
1098        This method returns the mapping of the current object into the
1099        current base domain.  If the current object is a polynomial,
1100        then the value returned by mapdomain is the polynomial mapped
1101        into the polynomial ring over the current base domain.
1102
1103        INPUT:
1104            mapMe -- if True this object is mappend and nothing is returned
1105                (default: False)
1106        """
1107
1108        #embed{ void *CF_mapinto(void *self)
1109        return new CanonicalForm(((CanonicalForm*)self)->mapinto());
1110        #}embed
1111        #embed{ void CF_mapintos(void *self)
1112        *(CanonicalForm*)self = ((CanonicalForm*)self)->mapinto();
1113        #}embed
1114
1115        if mapMe:
1116            CF_mapintos(self.thisptr)
1117        else:
1118            _sig_on
1119            return make_CF(CF_mapinto(self.thisptr))
1120
1121    def inZ(CanonicalForm self):
1122        """
1123        This method returns true if the object is a rational integer.
1124        """
1125        #embed{ int CF_inZ(void *self)
1126        return ((CanonicalForm*)self)->inZ();
1127        #}embed
1128        return bool(CF_inZ(self.thisptr))
1129
1130    def inQ(CanonicalForm self):
1131        """
1132        This method returns true if the object is a rational number.
1133        """
1134        #embed{ int CF_inQ(void *self)
1135        return ((CanonicalForm*)self)->inQ();
1136        #}embed
1137        return bool(CF_inQ(self.thisptr))
1138
1139    def inFF(CanonicalForm self):
1140        """
1141        This method returns true if the object is an element of Fp.
1142        """
1143        #embed{ int CF_inFF(void *self)
1144        return ((CanonicalForm*)self)->inFF();
1145        #}embed
1146        return bool(CF_inFF(self.thisptr))
1147
1148    def inGF(CanonicalForm self):
1149        """
1150        This method returns true if the object is an element of GF(q).
1151            """
1152        #embed{ int CF_inGF(void *self)
1153        return ((CanonicalForm*)self)->inGF();
1154        #}embed
1155        return bool(CF_inGF(self.thisptr))
1156
1157    def inPP(CanonicalForm self):
1158        """
1159        This method returns true if the object is in a prime power domain.
1160        """
1161        #embed{ int CF_inPP(void *self)
1162        return ((CanonicalForm*)self)->inPP();
1163        #}embed
1164        return bool(CF_inPP(self.thisptr))
1165
1166    def inBaseDomain(CanonicalForm self):
1167        """
1168        This method returns true if the object is an element of a base domain,
1169        e.g. Z, Q, Z mod p, Fp or GF(q).
1170        """
1171        #embed{ int CF_inBaseDomain(void *self)
1172        return ((CanonicalForm*)self)->inBaseDomain();
1173        #}embed
1174        return bool(CF_inBaseDomain(self.thisptr))
1175
1176    def inExtension(CanonicalForm self):
1177        r"""
1178        This method returns true if the object is an element of an algebraic
1179        extension.
1180
1181        \code{In Factory this means that the object is not an element
1182        of GF(q) even if that would be true mathematically. All that
1183        can be said when inExtension returns true is, that the object
1184        contains an algebraic variable.}
1185        """
1186        #embed{ int CF_inExtension(void *self)
1187        return ((CanonicalForm*)self)->inExtension();
1188        #}embed
1189        return bool(CF_inExtension(self.thisptr))
1190
1191    def inCoeffDomain(CanonicalForm self):
1192        """
1193        This method returns true if the object is not a polynomial.
1194        """
1195        #embed{ int CF_inCoeffDomain(void *self)
1196        return ((CanonicalForm*)self)->inCoeffDomain();
1197        #}embed
1198        return bool(CF_inCoeffDomain(self.thisptr))
1199
1200    def inPolyDomain(CanonicalForm self):
1201        """
1202        This method returns true if the object is a polynomial.
1203        """
1204        #embed{ int CF_inPolyDomain(void *self)
1205        return ((CanonicalForm*)self)->inPolyDomain();
1206        #}embed
1207        return bool(CF_inPolyDomain(self.thisptr))
1208
1209
1210    def isFFinGF(CanonicalForm self):
1211        """
1212        """
1213        #embed{ int CF_isFFinGF(void *self)
1214        return ((CanonicalForm*)self)->isFFinGF();
1215        #}embed
1216        return bool(CF_isFFinGF(self.thisptr))
1217
1218    def is_univariate(CanonicalForm self):
1219        """
1220        Returns True if self is univariate, False otherwise
1221        """
1222        #embed{ int CF_isUnivariate(void *self)
1223        return ((CanonicalForm*)self)->isUnivariate();
1224        #}embed
1225        return bool(CF_isUnivariate(self.thisptr))
1226
1227    def is_homogeneous(CanonicalForm self):
1228        """
1229        Returns True if self is homogeneous, False otherwise
1230        """
1231        #embed{ int CF_isHomogeneous(void *self)
1232        return ((CanonicalForm*)self)->isHomogeneous();
1233        #}embed
1234        return bool(CF_isHomogeneous(self.thisptr))
1235
1236    def __cflist__(self, f, e):
1237        level = f.level()-1
1238        if f.inCoeffDomain():
1239            return  [] + [tuple([f,e])]
1240        else:
1241            retval = []
1242            for c,e2 in f:
1243                new_e = e.copy()
1244                if e2!=0:
1245                   new_e[level]=e2
1246                retval = retval + self.__cflist__(c,new_e)
1247            return retval
1248
1249    def _sage_(self, R, kcache=None):
1250        """
1251        Coerces self into R.
1252
1253        A very simple coercion strategy is used: The variable with
1254        level=1 is mapped to the first variable in the ring, the
1255        variable with level=2 to the second, etc. Elements of the
1256        coefficient domain are coerced via strings. So in that case
1257        variable names (e.g. of an algebraic variable) do matter in
1258        contrast to the warning stated earlier.
1259
1260        INPUT:
1261            R      -- ring to coerce to
1262            kcache -- optional finite field cache
1263
1264        EXAMPLES:
1265            sage: cf.setBaseDomain(GF(127))
1266            sage: R=MPolynomialRing(GF(127),2,'x')
1267            sage: f=cf.CF(R('3*x0+2'))
1268            sage: f._sage_(R)
1269            2 + 3*x0
1270            sage: k = GF(2**8)
1271            sage: v = cf.setBaseDomain(k)
1272            sage: R=MPolynomialRing(k,2,'x')
1273            sage: f=cf.CF(R('a^20*x0+a^10'),v);f
1274            a_1^7*v_1+a_1^5*v_1+a_1^4*v_1+a_1^2*v_1+a_1^6+a_1^5+a_1^4+a_1^2
1275            sage: f._sage_(R)
1276            a^6 + a^5 + a^4 + a^2 + (a^7 + a^5 + a^4 + a^2)*x0
1277        """
1278        from sage.rings.polynomial_ring import is_PolynomialRing
1279
1280        self.mapinto(mapMe=True)
1281
1282        if is_PolynomialRing(R):
1283            l = [0]*(self.degree()+1)
1284            base = R.base_ring()
1285            for c,e in self:
1286                cs = str(c)
1287                if kcache!=None:
1288                    if not kcache.has_key(cs):
1289                        kcache[cs]=base(cs)
1290                    l[e]=kcache[cs]
1291                else:
1292                    l[e]=base(cs)
1293            return R(l)
1294        else:
1295            d={}
1296            level = self.level()-1
1297            ngens = R.ngens()
1298
1299            from sage.rings.polydict import PolyDict,ETuple
1300
1301            kgen = str(R.base_ring().gen())
1302
1303            if self.is_zero():
1304                # obey binary compatibility
1305                return R(PolyDict({}))
1306
1307            if self.inCoeffDomain():
1308                # catch the constant case
1309                cs = str(self)
1310                if not self.inFF():
1311                    cs = cs.replace(str(self.mvar()),kgen)
1312                d[ETuple({},ngens)]=R.base_ring()(cs)
1313                return R(PolyDict(d,force_int_exponents=False,force_etuples=False))
1314
1315            for c,e in self:
1316                exp = {}
1317                if e!=0:
1318                   exp[level]= e
1319                l = self.__cflist__(c,exp)
1320                for c2,e2 in l:
1321                    if c2.is_zero():
1322                        continue
1323                    cs = str(c2)
1324                    if not c2.inFF():
1325                        cs = cs.replace(str(c2.mvar()),kgen)
1326                    if kcache!=None:
1327                        if not kcache.has_key(cs):
1328                            kcache[cs]=R.base_ring()(cs)
1329                        d[ETuple(e2,ngens)]=kcache[cs]
1330                    else:
1331                        d[ETuple(e2,ngens)]=R.base_ring()(cs)
1332            return R(PolyDict(d,force_int_exponents=False,force_etuples=False))
1333
1334    def lcm(CanonicalForm self,right):
1335        #embed{ void *CF_lcm(void *l, void *r)
1336        return new CanonicalForm(lcm(*(CanonicalForm*)l,(*(CanonicalForm*)r)));
1337        #}embed
1338
1339        if not isinstance(right,CanonicalForm):
1340            right = CanonicalForm(right)
1341        _sig_on
1342        return make_CF(CF_lcm(self.thisptr,(<CanonicalForm>right).thisptr))
1343
1344
1345
1346CF =  CanonicalForm
1347
1348#embed{ void delete_CF( void *obj)
1349if(obj) {
1350    delete ((CanonicalForm*)obj);
1351}
1352#}embed
1353
1354cdef make_CF(void *x):
1355    """
1356    """
1357    cdef CanonicalForm y
1358    _sig_off
1359    y = CanonicalForm()
1360    delete_CF(y.thisptr)
1361    y.thisptr = x
1362    return y
1363
1364
1365def setCharacteristic(int p):
1366    """
1367    Sets the characteristic for all following Factory operations to
1368    p. We also accept SAGE finite fields here which will be
1369    automatically coerced to a format the Factory can understand. If
1370    the finite fieldis an extension field the algebraic element 'a' is
1371    returned which is the root of the defining polynomial of the
1372    extension field.
1373
1374    INPUT:
1375        p -- characteristic to use in Factory
1376
1377    TODO:
1378        The Factory also supports p^n as base chacteristic but that
1379        would need the gftable lookup which is not provided in the
1380        format needed by the Factory through Singular.  Use rootOf()
1381        if you need to to construct GF(p^n) which however - I guess -
1382        is slower than the setCharacteristic(p,n) approach. If you
1383        provide this function with a SAGE finite field this behavior
1384        is implemented.
1385    """
1386    #embed{ void setCharacteristicp(int p)
1387    setCharacteristic(p);
1388    #}embed
1389
1390    #embed{ void setCharacteristicpn(int p, int n)
1391    setCharacteristic(p,n);
1392    #}embed
1393
1394    #embed{ void setCharacteristicpnn(int p, int n, char name)
1395    setCharacteristic(p,n,n);
1396    #}embed
1397
1398    setCharacteristicp(p)
1399
1400__domains__ = dict()
1401
1402def setBaseDomain(k,force=False):
1403    """
1404    Sets the CF BaseDomain so it matches k. At the moment
1405    GF(p), GF(p^n), and ZZ are supported. If an extension
1406    field is provided the algebraic variable used to describe
1407    this extension field is returned nothing otherwise. This
1408    variable is needed to coerce SAGE polynomials to CF polynomials.
1409
1410    This variable is also cached locally so if the same finite
1411    extension field is provided twice the same variable will be
1412    returned. This behavior can be overriden by setting force to True.
1413
1414    Caching the algebraic variable locally not only is faster than
1415    recreating one when needed it alsoe ensures coercion from SAGE
1416    polynomials yields the same results evertime, even if one lost
1417    track of the algebraic variable needed to coerce.
1418
1419    INPUT:
1420        force -- enforce creation of a new algebraic variable (default: False)
1421
1422    """
1423    global __domains__
1424
1425    from sage.rings.finite_field import is_FiniteField
1426
1427    setCharacteristicp(int(k.characteristic()))
1428
1429    if is_FiniteField(k) and k.degree()!=1:
1430        if not __domains__.has_key(k) or force==True:
1431            setCharacteristic(0) #make sure nex step works
1432            __domains__[k] = rootOf(k.polynomial())
1433            setCharacteristic(k.characteristic())
1434        return  __domains__[k]
1435
1436
1437
1438def getCharacteristic():
1439    """
1440    Returns the currently set characteristic
1441    """
1442    #embed{ int getCharacteristicp()
1443    return getCharacteristic();
1444    #}embed
1445    return getCharacteristicp()
1446
1447def rootOf(mipo, char *name = NULL):
1448    r"""
1449    This function returns the algebraic variable that is defined by
1450    the minimal polynomial mipo.  name has to be a name that is not
1451    yet assigned to a variable. This is the only way to define an
1452    algebraic variable. The level of the returned variable depends on
1453    how many algebraic variables are defined so far. The variable
1454    remains anonymous if the user does not specify a name.  mipo has
1455    to be an irreducible univariate polynomial over the current base
1456    domain.
1457
1458    INPUT:
1459        mipo -- minimal polynomial to define the algebraic variable,
1460            this must be a CanonicalForm or something coercable to
1461            ca CanonicalForm via the CanonicalForm constructor
1462
1463        name -- name to assign to the algebraic variable
1464
1465    \note{Do not use this function to construct a base domain for
1466    finite extension fields. Use setBaseDomain() instead.}
1467    """
1468    #embed{ void *rootOfpn(void *mipo, char name)
1469    return new Variable(rootOf(*(CanonicalForm*)mipo, name));
1470    #}embed
1471    #embed{ void *rootOfp(void *mipo)
1472    return new Variable(rootOf(*(CanonicalForm*)mipo));
1473    #}embed
1474
1475    cdef char *cName
1476    cdef char cChar
1477    cdef CanonicalForm cMipo
1478
1479    if not isinstance(mipo,CanonicalForm):
1480        cMipo = CanonicalForm(mipo)
1481    else:
1482        cMipo = mipo
1483
1484    if name == NULL or len(name)==0:
1485        _sig_on
1486        return make_Variable(rootOfp(cMipo.thisptr))
1487    else:
1488        cName = name
1489        cChar = cName[0]
1490        _sig_on
1491        return make_Variable(rootOfpn(cMipo.thisptr,cChar))
1492
1493def getMipo( a,  x=None ):
1494    """
1495    This function returns the minimal polynomial that defines the
1496    algebraic variable a. The minimal polynomial is returned as a
1497    CanonicalForm of variable x.
1498
1499    INPUT:
1500        a -- algebraic variable
1501        x -- variable the minimal polynomial is expressed in
1502    """
1503    #embed{ void *CF_getMipo(void *a, void *x)
1504    return new CanonicalForm(getMipo(*(Variable*)a,*(Variable*)x));
1505    #}embed
1506
1507    cdef Variable cA
1508    cdef Variable cX
1509
1510    if x==None:
1511        x='x'
1512
1513    if not isinstance(a,Variable):
1514        cA = Variable(a)
1515    else:
1516        cA = a
1517    if not isinstance(x,Variable):
1518        cX = Variable(x)
1519    else:
1520        cX = x
1521
1522    _sig_on
1523    return make_CF(CF_getMipo(cA.thisptr,cX.thisptr))
1524
Note: See TracBrowser for help on using the repository browser.