source: git/factory/canonicalform.cc @ 2b44a1

spielwiese
Last change on this file since 2b44a1 was 2b44a1, checked in by Hans Schönemann <hannes@…>, 16 years ago
*hannes: format git-svn-id: file:///usr/local/Singular/svn/trunk@10452 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 51.3 KB
Line 
1/* emacs edit mode for this file is -*- C++ -*- */
2/* $Id: canonicalform.cc,v 1.41 2007-12-04 15:24:53 Singular Exp $ */
3
4#include <config.h>
5
6#include "assert.h"
7
8#include "cf_defs.h"
9#include "cf_globals.h"
10#include "canonicalform.h"
11#include "cf_iter.h"
12#include "int_cf.h"
13#include "cf_factory.h"
14#include "cf_algorithm.h"
15#include "imm.h"
16#include "gfops.h"
17#include "cf_binom.h"
18#if defined (USE_MEMUTIL) && ! defined (USE_OLD_MEMMAN)
19#include "memman.h"
20#endif
21
22#ifndef NOSTREAMIO
23CanonicalForm readCF( ISTREAM& );
24#endif /* NOSTREAMIO */
25
26//{{{ initialization
27int initializeGMP();
28int initializeCharacteristic();
29#ifdef SINGULAR
30extern int mmInit(void);
31#endif
32
33int
34initCanonicalForm( void )
35{
36    static bool initialized = false;
37    if ( ! initialized ) {
38#if (defined (USE_MEMUTIL) && ! defined (USE_OLD_MEMMAN)) || defined (SINGULAR)
39        (void)mmInit();
40#endif
41
42        (void)initializeCharacteristic();
43        (void)initializeGMP();
44        initPT();
45        initialized = true;
46    }
47    return 1;
48}
49//}}}
50
51//{{{ constructors, destructors, selectors
52CanonicalForm::CanonicalForm( const char * str, const int base ) : value( CFFactory::basic( str, base ) )
53{
54}
55
56InternalCF*
57CanonicalForm::getval() const
58{
59    if ( is_imm( value ) )
60        return value;
61    else
62        return value->copyObject();
63}
64
65CanonicalForm
66CanonicalForm::deepCopy() const
67{
68    if ( is_imm( value ) )
69        return *this;
70    else
71        return CanonicalForm( value->deepCopyObject() );
72}
73//}}}
74
75//{{{ predicates
76#if 0
77bool
78CanonicalForm::isImm() const
79{
80    return is_imm( value );
81}
82#endif
83
84bool
85CanonicalForm::inZ() const
86{
87    if ( is_imm( value ) == INTMARK )
88        return true;
89    else if ( is_imm( value ) )
90        return false;
91    else
92        return value->levelcoeff() == IntegerDomain;
93}
94
95bool
96CanonicalForm::inQ() const
97{
98    if ( is_imm( value ) == INTMARK )
99        return true;
100    else if ( is_imm( value ) )
101        return false;
102    else
103        return value->levelcoeff() == IntegerDomain ||
104            value->levelcoeff() == RationalDomain;
105}
106
107bool
108CanonicalForm::inFF() const
109{
110    return is_imm( value ) == FFMARK;
111}
112
113bool
114CanonicalForm::inGF() const
115{
116    return is_imm( value ) == GFMARK;
117}
118
119bool
120CanonicalForm::inPP() const
121{
122    return ! is_imm( value ) && ( value->levelcoeff() == PrimePowerDomain );
123}
124
125bool
126CanonicalForm::inBaseDomain() const
127{
128    if ( is_imm( value ) )
129        return true;
130    else
131        return value->inBaseDomain();
132}
133
134bool
135CanonicalForm::inExtension() const
136{
137    if ( is_imm( value ) )
138        return false;
139    else
140        return value->inExtension();
141}
142
143bool
144CanonicalForm::inCoeffDomain() const
145{
146    if ( is_imm( value ) )
147        return true;
148    else
149        return value->inCoeffDomain();
150}
151
152bool
153CanonicalForm::inPolyDomain() const
154{
155    if ( is_imm( value ) )
156        return false;
157    else
158        return value->inPolyDomain();
159}
160
161bool
162CanonicalForm::inQuotDomain() const
163{
164    if ( is_imm( value ) )
165        return false;
166    else
167        return value->inQuotDomain();
168}
169
170bool
171CanonicalForm::isFFinGF() const
172{
173    return is_imm( value ) == GFMARK && gf_isff( imm2int( value ) );
174}
175
176bool
177CanonicalForm::isUnivariate() const
178{
179    if ( is_imm( value ) )
180        return false;
181    else
182        return value->isUnivariate();
183}
184
185// is_homogeneous returns 1 iff f is homogeneous, 0 otherwise//
186bool
187CanonicalForm::isHomogeneous() const
188{
189  if (this->isZero()) return true;
190  else if (this->inCoeffDomain()) return true;
191  else
192  {
193#if 0
194    CFIterator i;
195    int cdeg = -2, dummy;
196    for ( i = *this; i.hasTerms(); i++ )
197    {
198      if (!(i.coeff().isHomogeneous())) return false;
199      if ( (dummy = totaldegree( i.coeff() ) + i.exp()) != cdeg )
200      {
201         if (cdeg == -2) cdeg = dummy;
202         else return false;
203      }
204    }
205    return true;
206#else
207    CFList termlist= get_Terms(*this);
208    CFListIterator i;
209    int deg= totaldegree(termlist.getFirst());
210
211    for ( i=termlist; i.hasItem(); i++ )
212      if ( totaldegree(i.getItem()) != deg ) return false;
213    return true;
214#endif
215  }
216}
217
218//}}}
219
220//{{{ conversion functions
221int
222CanonicalForm::intval() const
223{
224    if ( is_imm( value ) )
225        return imm_intval( value );
226    else
227        return value->intval();
228}
229
230CanonicalForm
231CanonicalForm::mapinto () const
232{
233    ASSERT( is_imm( value ) ||  ! value->inExtension(), "cannot map into different Extension" );
234    if ( is_imm( value ) )
235        if ( getCharacteristic() == 0 )
236            if ( is_imm( value ) == FFMARK )
237                return CanonicalForm( int2imm( ff_symmetric( imm2int( value ) ) ) );
238            else  if ( is_imm( value ) == GFMARK )
239                return CanonicalForm( int2imm( ff_symmetric( gf_gf2ff( imm2int( value ) ) ) ) );
240            else
241                return *this;
242        else  if ( CFFactory::gettype() == PrimePowerDomain )
243            return CanonicalForm( CFFactory::basic( imm2int( value ) ) );
244        else  if ( getGFDegree() == 1 )
245            return CanonicalForm( int2imm_p( ff_norm( imm2int( value ) ) ) );
246        else
247            return CanonicalForm( int2imm_gf( gf_int2gf( imm2int( value ) ) ) );
248    else  if ( value->inBaseDomain() )
249        if ( getCharacteristic() == 0 )
250            if ( value->levelcoeff() == PrimePowerDomain )
251                return CFFactory::basic( getmpi( value, true ) );
252            else
253                return *this;
254        else  if ( CFFactory::gettype() == PrimePowerDomain ) {
255            ASSERT( value->levelcoeff() == PrimePowerDomain || value->levelcoeff() == IntegerDomain, "no proper map defined" );
256            if ( value->levelcoeff() == PrimePowerDomain )
257                return *this;
258            else
259                return CFFactory::basic( getmpi( value ) );
260        }
261        else {
262            int val;
263            if ( value->levelcoeff() == IntegerDomain )
264                val = value->intmod( ff_prime );
265            else  if ( value->levelcoeff() == RationalDomain )
266                return num().mapinto() / den().mapinto();
267            else {
268                ASSERT( 0, "illegal domain" );
269                return 0;
270            }
271            if ( getGFDegree() > 1 )
272                return CanonicalForm( int2imm_gf( gf_int2gf( val ) ) );
273            else
274                return CanonicalForm( int2imm_p( val ) );
275        }
276    else {
277        Variable x = value->variable();
278        CanonicalForm result;
279        for ( CFIterator i = *this; i.hasTerms(); i++ )
280            result += power( x, i.exp() ) * i.coeff().mapinto();
281        return result;
282    }
283}
284//}}}
285
286//{{{ CanonicalForm CanonicalForm::lc (), Lc (), LC (), LC ( v ) const
287//{{{ docu
288//
289// lc(), Lc(), LC() - leading coefficient functions.
290//
291// All methods return CO if CO is in a base domain.
292//
293// lc() returns the leading coefficient of CO with respect to
294// lexicographic ordering.  Elements in an algebraic extension
295// are considered polynomials so lc() always returns a leading
296// coefficient in a base domain.  This method is useful to get
297// the base domain over which CO is defined.
298//
299// Lc() returns the leading coefficient of CO with respect to
300// lexicographic ordering.  In contrast to lc() elements in an
301// algebraic extension are considered coefficients so Lc() always
302// returns a leading coefficient in a coefficient domain.
303//
304// LC() returns the leading coefficient of CO where CO is
305// considered a univariate polynomial in its main variable.  An
306// element of an algebraic extension is considered an univariate
307// polynomial, too.
308//
309// LC( v ) returns the leading coefficient of CO where CO is
310// considered an univariate polynomial in the polynomial variable
311// v.
312// Note: If v is less than the main variable of CO we have to
313// swap variables which may be quite expensive.
314//
315// Examples:
316// Let x < y be polynomial variables, a an algebraic variable.
317//
318// (3*a*x*y^2+y+x).lc() = 3
319// (3*a*x*y^2+y+x).Lc() = 3*a
320// (3*a*x*y^2+y+x).LC() = 3*a*x
321// (3*a*x*y^2+y+x).LC( x ) = 3*a*y^2+1
322//
323// (3*a^2+4*a).lc() = 3
324// (3*a^2+4*a).Lc() = 3*a^2+4*a
325// (3*a^2+4*a).LC() = 3
326// (3*a^2+4*a).LC( x ) = 3*a^2+4*a
327//
328// See also: InternalCF::lc(), InternalCF::Lc(), InternalCF::LC(),
329// InternalPoly::lc(), InternalPoly::Lc(), InternalPoly::LC(),
330// ::lc(), ::Lc(), ::LC(), ::LC( v )
331//
332//}}}
333CanonicalForm
334CanonicalForm::lc () const
335{
336    if ( is_imm( value ) )
337        return *this;
338    else
339        return value->lc();
340}
341
342CanonicalForm
343CanonicalForm::Lc () const
344{
345    if ( is_imm( value ) || value->inCoeffDomain() )
346        return *this;
347    else
348        return value->Lc();
349}
350
351CanonicalForm
352CanonicalForm::LC () const
353{
354    if ( is_imm( value ) )
355        return *this;
356    else
357        return value->LC();
358}
359
360CanonicalForm
361CanonicalForm::LC ( const Variable & v ) const
362{
363    if ( is_imm( value ) || value->inCoeffDomain() )
364        return *this;
365
366    Variable x = value->variable();
367    if ( v > x )
368        return *this;
369    else if ( v == x )
370        return value->LC();
371    else {
372        CanonicalForm f = swapvar( *this, v, x );
373         if ( f.mvar() == x )
374             return swapvar( f.value->LC(), v, x );
375         else
376            // v did not occur in f
377            return *this;
378    }
379}
380//}}}
381
382//{{{ int CanonicalForm::degree (), degree ( v ) const
383//{{{ docu
384//
385// degree() - degree methods.
386//
387// Both methods returns -1 for the zero polynomial and 0 if
388// CO is in a base domain.
389//
390// degree() returns the degree of CO in its main variable.
391// Elements in an algebraic extension are considered polynomials.
392//
393// degree( v ) returns the degree of CO with respect to v.
394// Elements in an algebraic extension are considered polynomials,
395// and v may be algebraic.
396//
397// See also: InternalCf::degree(), InternalPoly::degree(),
398// ::degree(), ::degree( v )
399//
400//}}}
401int
402CanonicalForm::degree() const
403{
404    int what = is_imm( value );
405    if ( what )
406        if ( what == FFMARK )
407            return imm_iszero_p( value ) ? -1 : 0;
408        else if ( what == INTMARK )
409            return imm_iszero( value ) ? -1 : 0;
410        else
411            return imm_iszero_gf( value ) ? -1 : 0;
412    else
413        return value->degree();
414}
415
416int
417CanonicalForm::degree( const Variable & v ) const
418{
419    int what = is_imm( value );
420    if ( what )
421        if ( what == FFMARK )
422            return imm_iszero_p( value ) ? -1 : 0;
423        else if ( what == INTMARK )
424            return imm_iszero( value ) ? -1 : 0;
425        else
426            return imm_iszero_gf( value ) ? -1 : 0;
427    else if ( value->inBaseDomain() )
428        return value->degree();
429
430    Variable x = value->variable();
431    if ( v == x )
432        return value->degree();
433    else  if ( v > x )
434        // relatively to v, f is in a coefficient ring
435        return 0;
436    else {
437        int coeffdeg, result = 0;
438        // search for maximum of coefficient degree
439        for ( CFIterator i = *this; i.hasTerms(); i++ ) {
440            coeffdeg = i.coeff().degree( v );
441            if ( coeffdeg > result )
442                result = coeffdeg;
443        }
444        return result;
445    }
446}
447//}}}
448
449//{{{ CanonicalForm CanonicalForm::tailcoeff (), int CanonicalForm::taildegree () const
450//{{{ docu
451//
452// tailcoeff(), taildegree() - return least coefficient and
453//   degree, resp.
454//
455// tailcoeff() returns the coefficient of the term with the least
456// degree in CO where CO is considered an univariate polynomial
457// in its main variable.  Elements in an algebraic extension are
458// considered coefficients.
459//
460// taildegree() returns -1 for the zero polynomial, 0 if CO is in
461// a base domain, otherwise the least degree of CO where CO is
462// considered a univariate polynomial in its main variable.  In
463// contrast to tailcoeff(), elements in an algebraic extension
464// are considered polynomials, not coefficients, and such may
465// have a taildegree larger than zero.
466//
467// See also: InternalCF::tailcoeff(), InternalCF::tailcoeff(),
468// InternalPoly::tailcoeff(), InternalPoly::taildegree,
469// ::tailcoeff(), ::taildegree()
470//
471//}}}
472CanonicalForm
473CanonicalForm::tailcoeff () const
474{
475    if ( is_imm( value ) || value->inCoeffDomain() )
476        return *this;
477    else
478        return value->tailcoeff();
479}
480
481int
482CanonicalForm::taildegree () const
483{
484    int what = is_imm( value );
485    if ( what )
486        if ( what == FFMARK )
487            return imm_iszero_p( value ) ? -1 : 0;
488        else if ( what == INTMARK )
489            return imm_iszero( value ) ? -1 : 0;
490        else
491            return imm_iszero_gf( value ) ? -1 : 0;
492    else
493        return value->taildegree();
494}
495//}}}
496
497//{{{ int CanonicalForm::level (), Variable CanonicalForm::mvar () const
498//{{{ docu
499//
500// level(), mvar() - return level and main variable of CO.
501//
502// level() returns the level of CO.  For a list of the levels and
503// their meanings, see cf_defs.h.
504//
505// mvar() returns the main variable of CO or Variable() if CO is
506// in a base domain.
507//
508// See also: InternalCF::level(), InternalCF::variable(),
509// InternalPoly::level(), InternalPoly::variable(), ::level(),
510// ::mvar()
511//
512//}}}
513int
514CanonicalForm::level () const
515{
516    if ( is_imm( value ) )
517        return LEVELBASE;
518    else
519        return value->level();
520}
521
522Variable
523CanonicalForm::mvar () const
524{
525    if ( is_imm( value ) )
526        return Variable();
527    else
528        return value->variable();
529}
530//}}}
531
532//{{{ CanonicalForm CanonicalForm::num (), den () const
533//{{{ docu
534//
535// num(), den() - return numinator and denominator of CO.
536//
537// num() returns the numinator of CO if CO is a rational number,
538// CO itself otherwise.
539//
540// den() returns the denominator of CO if CO is a rational
541// number, 1 (from the current domain!) otherwise.
542//
543// See also: InternalCF::num(), InternalCF::den(),
544// InternalRational::num(), InternalRational::den(), ::num(),
545// ::den()
546//
547//}}}
548CanonicalForm
549CanonicalForm::num () const
550{
551    if ( is_imm( value ) )
552        return *this;
553    else
554        return CanonicalForm( value->num() );
555}
556
557CanonicalForm
558CanonicalForm::den () const
559{
560    if ( is_imm( value ) )
561        return CanonicalForm( 1 );
562    else
563        return CanonicalForm( value->den() );
564}
565//}}}
566
567//{{{ assignment operators
568CanonicalForm &
569CanonicalForm::operator += ( const CanonicalForm & cf )
570{
571    int what = is_imm( value );
572    if ( what ) {
573        ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" );
574        if ( (what = is_imm( cf.value )) == FFMARK )
575            value = imm_add_p( value, cf.value );
576        else  if ( what == GFMARK )
577            value = imm_add_gf( value, cf.value );
578        else  if ( what )
579            value = imm_add( value, cf.value );
580        else {
581            InternalCF * dummy = cf.value->copyObject();
582            value = dummy->addcoeff( value );
583        }
584    }
585    else  if ( is_imm( cf.value ) )
586        value = value->addcoeff( cf.value );
587    else  if ( value->level() == cf.value->level() ) {
588        if ( value->levelcoeff() == cf.value->levelcoeff() )
589            value = value->addsame( cf.value );
590        else  if ( value->levelcoeff() > cf.value->levelcoeff() )
591            value = value->addcoeff( cf.value );
592        else {
593            InternalCF * dummy = cf.value->copyObject();
594            dummy = dummy->addcoeff( value );
595            if ( value->deleteObject() ) delete value;
596            value = dummy;
597        }
598    }
599    else  if ( level() > cf.level() )
600        value = value->addcoeff( cf.value );
601    else {
602        InternalCF * dummy = cf.value->copyObject();
603        dummy = dummy->addcoeff( value );
604        if ( value->deleteObject() ) delete value;
605        value = dummy;
606    }
607    return *this;
608}
609
610CanonicalForm &
611CanonicalForm::operator -= ( const CanonicalForm & cf )
612{
613    int what = is_imm( value );
614    if ( what ) {
615        ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" );
616        if ( (what = is_imm( cf.value )) == FFMARK )
617            value = imm_sub_p( value, cf.value );
618        else  if ( what == GFMARK )
619            value = imm_sub_gf( value, cf.value );
620        else  if ( what )
621            value = imm_sub( value, cf.value );
622        else {
623            InternalCF * dummy = cf.value->copyObject();
624            value = dummy->subcoeff( value, true );
625        }
626    }
627    else  if ( is_imm( cf.value ) )
628        value = value->subcoeff( cf.value, false );
629    else  if ( value->level() == cf.value->level() ) {
630        if ( value->levelcoeff() == cf.value->levelcoeff() )
631            value = value->subsame( cf.value );
632        else  if ( value->levelcoeff() > cf.value->levelcoeff() )
633            value = value->subcoeff( cf.value, false );
634        else {
635            InternalCF * dummy = cf.value->copyObject();
636            dummy = dummy->subcoeff( value, true );
637            if ( value->deleteObject() ) delete value;
638            value = dummy;
639        }
640    }
641    else  if ( level() > cf.level() )
642        value = value->subcoeff( cf.value, false );
643    else {
644        InternalCF * dummy = cf.value->copyObject();
645        dummy = dummy->subcoeff( value, true );
646        if ( value->deleteObject() ) delete value;
647        value = dummy;
648    }
649    return *this;
650}
651
652CanonicalForm &
653CanonicalForm::operator *= ( const CanonicalForm & cf )
654{
655    int what = is_imm( value );
656    if ( what ) {
657        ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" );
658        if ( (what = is_imm( cf.value )) == FFMARK )
659            value = imm_mul_p( value, cf.value );
660        else  if ( what == GFMARK )
661            value = imm_mul_gf( value, cf.value );
662        else  if ( what )
663            value = imm_mul( value, cf.value );
664        else {
665            InternalCF * dummy = cf.value->copyObject();
666            value = dummy->mulcoeff( value );
667        }
668    }
669    else  if ( is_imm( cf.value ) )
670        value = value->mulcoeff( cf.value );
671    else  if ( value->level() == cf.value->level() ) {
672        if ( value->levelcoeff() == cf.value->levelcoeff() )
673            value = value->mulsame( cf.value );
674        else  if ( value->levelcoeff() > cf.value->levelcoeff() )
675            value = value->mulcoeff( cf.value );
676        else {
677            InternalCF * dummy = cf.value->copyObject();
678            dummy = dummy->mulcoeff( value );
679            if ( value->deleteObject() ) delete value;
680            value = dummy;
681        }
682    }
683    else  if ( level() > cf.level() )
684        value = value->mulcoeff( cf.value );
685    else {
686        InternalCF * dummy = cf.value->copyObject();
687        dummy = dummy->mulcoeff( value );
688        if ( value->deleteObject() ) delete value;
689        value = dummy;
690    }
691    return *this;
692}
693
694CanonicalForm &
695CanonicalForm::operator /= ( const CanonicalForm & cf )
696{
697    int what = is_imm( value );
698    if ( what ) {
699        ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" );
700        if ( (what = is_imm( cf.value )) == FFMARK )
701            value = imm_div_p( value, cf.value );
702        else  if ( what == GFMARK )
703            value = imm_div_gf( value, cf.value );
704        else  if ( what )
705            value = imm_divrat( value, cf.value );
706        else {
707            InternalCF * dummy = cf.value->copyObject();
708            value = dummy->dividecoeff( value, true );
709        }
710    }
711    else  if ( is_imm( cf.value ) )
712        value = value->dividecoeff( cf.value, false );
713    else  if ( value->level() == cf.value->level() ) {
714        if ( value->levelcoeff() == cf.value->levelcoeff() )
715            value = value->dividesame( cf.value );
716        else  if ( value->levelcoeff() > cf.value->levelcoeff() )
717            value = value->dividecoeff( cf.value, false );
718        else {
719            InternalCF * dummy = cf.value->copyObject();
720            dummy = dummy->dividecoeff( value, true );
721            if ( value->deleteObject() ) delete value;
722            value = dummy;
723        }
724    }
725    else  if ( level() > cf.level() )
726        value = value->dividecoeff( cf.value, false );
727    else {
728        InternalCF * dummy = cf.value->copyObject();
729        dummy = dummy->dividecoeff( value, true );
730        if ( value->deleteObject() ) delete value;
731        value = dummy;
732    }
733    return *this;
734}
735
736CanonicalForm &
737CanonicalForm::div ( const CanonicalForm & cf )
738{
739    int what = is_imm( value );
740    if ( what ) {
741        ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" );
742        if ( (what = is_imm( cf.value )) == FFMARK )
743            value = imm_div_p( value, cf.value );
744        else  if ( what == GFMARK )
745            value = imm_div_gf( value, cf.value );
746        else  if ( what )
747            value = imm_div( value, cf.value );
748        else {
749            InternalCF * dummy = cf.value->copyObject();
750            value = dummy->divcoeff( value, true );
751        }
752    }
753    else  if ( is_imm( cf.value ) )
754        value = value->divcoeff( cf.value, false );
755    else  if ( value->level() == cf.value->level() ) {
756        if ( value->levelcoeff() == cf.value->levelcoeff() )
757            value = value->divsame( cf.value );
758        else  if ( value->levelcoeff() > cf.value->levelcoeff() )
759            value = value->divcoeff( cf.value, false );
760        else {
761            InternalCF * dummy = cf.value->copyObject();
762            dummy = dummy->divcoeff( value, true );
763            if ( value->deleteObject() ) delete value;
764            value = dummy;
765        }
766    }
767    else  if ( level() > cf.level() )
768        value = value->divcoeff( cf.value, false );
769    else {
770        InternalCF * dummy = cf.value->copyObject();
771        dummy = dummy->divcoeff( value, true );
772        if ( value->deleteObject() ) delete value;
773        value = dummy;
774    }
775    return *this;
776}
777
778CanonicalForm &
779CanonicalForm::operator %= ( const CanonicalForm & cf )
780{
781    int what = is_imm( value );
782    if ( what ) {
783        ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" );
784        if ( (what = is_imm( cf.value )) == FFMARK )
785            value = imm_mod_p( value, cf.value );
786        else  if ( what == GFMARK )
787            value = imm_mod_gf( value, cf.value );
788        else  if ( what )
789            value = imm_mod( value, cf.value );
790        else {
791            InternalCF * dummy = cf.value->copyObject();
792            value = dummy->modulocoeff( value, true );
793        }
794    }
795    else  if ( is_imm( cf.value ) )
796        value = value->modulocoeff( cf.value, false );
797    else  if ( value->level() == cf.value->level() ) {
798        if ( value->levelcoeff() == cf.value->levelcoeff() )
799            value = value->modulosame( cf.value );
800        else  if ( value->levelcoeff() > cf.value->levelcoeff() )
801            value = value->modulocoeff( cf.value, false );
802        else {
803            InternalCF * dummy = cf.value->copyObject();
804            dummy = dummy->modulocoeff( value, true );
805            if ( value->deleteObject() ) delete value;
806            value = dummy;
807        }
808    }
809    else  if ( level() > cf.level() )
810        value = value->modulocoeff( cf.value, false );
811    else {
812        InternalCF * dummy = cf.value->copyObject();
813        dummy = dummy->modulocoeff( value, true );
814        if ( value->deleteObject() ) delete value;
815        value = dummy;
816    }
817    return *this;
818}
819
820CanonicalForm &
821CanonicalForm::mod ( const CanonicalForm & cf )
822{
823    int what = is_imm( value );
824    if ( what ) {
825        ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" );
826        if ( (what = is_imm( cf.value )) == FFMARK )
827            value = imm_mod_p( value, cf.value );
828        else  if ( what == GFMARK )
829            value = imm_mod_gf( value, cf.value );
830        else  if ( what )
831            value = imm_mod( value, cf.value );
832        else {
833            InternalCF * dummy = cf.value->copyObject();
834            value = dummy->modcoeff( value, true );
835        }
836    }
837    else  if ( is_imm( cf.value ) )
838        value = value->modcoeff( cf.value, false );
839    else  if ( value->level() == cf.value->level() ) {
840        if ( value->levelcoeff() == cf.value->levelcoeff() )
841            value = value->modsame( cf.value );
842        else  if ( value->levelcoeff() > cf.value->levelcoeff() )
843            value = value->modcoeff( cf.value, false );
844        else {
845            InternalCF * dummy = cf.value->copyObject();
846            dummy = dummy->modcoeff( value, true );
847            if ( value->deleteObject() ) delete value;
848            value = dummy;
849        }
850    }
851    else  if ( level() > cf.level() )
852        value = value->modcoeff( cf.value, false );
853    else {
854        InternalCF * dummy = cf.value->copyObject();
855        dummy = dummy->modcoeff( value, true );
856        if ( value->deleteObject() ) delete value;
857        value = dummy;
858    }
859    return *this;
860}
861
862void
863divrem ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & q, CanonicalForm & r )
864{
865    InternalCF * qq = 0, * rr = 0;
866    int what = is_imm( f.value );
867    if ( what )
868        if ( is_imm( g.value ) ) {
869            if ( what == FFMARK )
870                imm_divrem_p( f.value, g.value, qq, rr );
871            else  if ( what == GFMARK )
872                imm_divrem_gf( f.value, g.value, qq, rr );
873            else
874                imm_divrem( f.value, g.value, qq, rr );
875        }
876        else
877            g.value->divremcoeff( f.value, qq, rr, true );
878    else  if ( (what=is_imm( g.value )) )
879        f.value->divremcoeff( g.value, qq, rr, false );
880    else  if ( f.value->level() == g.value->level() )
881        if ( f.value->levelcoeff() == g.value->levelcoeff() )
882            f.value->divremsame( g.value, qq, rr );
883        else  if ( f.value->levelcoeff() > g.value->levelcoeff() )
884            f.value->divremcoeff( g.value, qq, rr, false );
885        else
886            g.value->divremcoeff( f.value, qq, rr, true );
887    else  if ( f.value->level() > g.value->level() )
888        f.value->divremcoeff( g.value, qq, rr, false );
889    else
890        g.value->divremcoeff( f.value, qq, rr, true );
891    ASSERT( qq != 0 && rr != 0, "error in divrem" );
892    q = CanonicalForm( qq );
893    r = CanonicalForm( rr );
894}
895
896bool
897divremt ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & q, CanonicalForm & r )
898{
899    InternalCF * qq = 0, * rr = 0;
900    int what = is_imm( f.value );
901    bool result = true;
902    if ( what )
903        if ( is_imm( g.value ) ) {
904            if ( what == FFMARK )
905                imm_divrem_p( f.value, g.value, qq, rr );
906            else  if ( what == GFMARK )
907                imm_divrem_gf( f.value, g.value, qq, rr );
908            else
909                imm_divrem( f.value, g.value, qq, rr );
910        }
911        else
912            result = g.value->divremcoefft( f.value, qq, rr, true );
913    else  if ( (what=is_imm( g.value )) )
914        result = f.value->divremcoefft( g.value, qq, rr, false );
915    else  if ( f.value->level() == g.value->level() )
916        if ( f.value->levelcoeff() == g.value->levelcoeff() )
917            result = f.value->divremsamet( g.value, qq, rr );
918        else  if ( f.value->levelcoeff() > g.value->levelcoeff() )
919            result = f.value->divremcoefft( g.value, qq, rr, false );
920        else
921            result = g.value->divremcoefft( f.value, qq, rr, true );
922    else  if ( f.value->level() > g.value->level() )
923        result = f.value->divremcoefft( g.value, qq, rr, false );
924    else
925        result = g.value->divremcoefft( f.value, qq, rr, true );
926    if ( result ) {
927        ASSERT( qq != 0 && rr != 0, "error in divrem" );
928        q = CanonicalForm( qq );
929        r = CanonicalForm( rr );
930    }
931    else {
932        q = 0; r = 0;
933    }
934    return result;
935}
936//}}}
937
938//{{{ CanonicalForm CanonicalForm::operator () ( f ), operator () ( f, v ) const
939//{{{ docu
940//
941// operator ()() - evaluation operator.
942//
943// Both operators return CO if CO is in a base domain.
944//
945// operator () ( f ) returns CO with f inserted for the main
946// variable.  Elements in an algebraic extension are considered
947// polynomials.
948//
949// operator () ( f, v ) returns CO with f inserted for v.
950// Elements in an algebraic extension are considered polynomials
951// and v may be an algebraic variable.
952//
953//}}}
954CanonicalForm
955CanonicalForm::operator () ( const CanonicalForm & f ) const
956{
957    if ( is_imm( value ) || value->inBaseDomain() )
958        return *this;
959    else {
960#if 0
961        CFIterator i = *this;
962        int lastExp = i.exp();
963        CanonicalForm result = i.coeff();
964        i++;
965        while ( i.hasTerms() ) {
966            if ( (lastExp - i.exp()) == 1 )
967                result *= f;
968            else
969                result *= power( f, lastExp - i.exp() );
970            result += i.coeff();
971            lastExp = i.exp();
972            i++;
973        }
974        if ( lastExp != 0 )
975            result *= power( f, lastExp );
976#else
977        CFIterator i = *this;
978        int lastExp = i.exp();
979        CanonicalForm result = i.coeff();
980        i++;
981        while ( i.hasTerms() )
982        {
983            int i_exp=i.exp();
984            if ( (lastExp - i_exp /* i.exp()*/) == 1 )
985                result *= f;
986            else
987                result *= power( f, lastExp - i_exp /*i.exp()*/ );
988            result += i.coeff();
989            lastExp = i_exp /*i.exp()*/;
990            i++;
991        }
992        if ( lastExp != 0 )
993            result *= power( f, lastExp );
994#endif
995        return result;
996    }
997}
998
999CanonicalForm
1000CanonicalForm::operator () ( const CanonicalForm & f, const Variable & v ) const
1001{
1002    if ( is_imm( value ) || value->inBaseDomain() )
1003        return *this;
1004
1005    Variable x = value->variable();
1006    if ( v > x )
1007        return *this;
1008    else  if ( v == x )
1009        return (*this)( f );
1010    else {
1011        // v is less than main variable of f
1012        CanonicalForm result = 0;
1013        for ( CFIterator i = *this; i.hasTerms(); i++ )
1014            result += i.coeff()( f, v ) * power( x, i.exp() );
1015        return result;
1016    }
1017}
1018//}}}
1019
1020//{{{ CanonicalForm CanonicalForm::operator [] ( int i ) const
1021//{{{ docu
1022//
1023// operator []() - return i'th coefficient from CO.
1024//
1025// Returns CO if CO is in a base domain and i equals zero.
1026// Returns zero (from the current domain) if CO is in a base
1027// domain and i is larger than zero.  Otherwise, returns the
1028// coefficient to x^i in CO (if x denotes the main variable of
1029// CO) or zero if CO does not contain x^i.  Elements in an
1030// algebraic extension are considered polynomials.  i should be
1031// larger or equal zero.
1032//
1033// Note: Never use a loop like
1034//
1035// for ( int i = degree( f ); i >= 0; i-- )
1036//     foo( i, f[ i ] );
1037//
1038// which is much slower than
1039//
1040// for ( int i = degree( f ), CFIterator I = f; I.hasTerms(); I++ ) {
1041//     // fill gap with zeroes
1042//     for ( ; i > I.exp(); i-- )
1043//         foo( i, 0 );
1044//     // at this point, i == I.exp()
1045//     foo( i, i.coeff() );
1046//     i--;
1047// }
1048// // work through trailing zeroes
1049// for ( ; i >= 0; i-- )
1050//     foo( i, 0 );
1051//
1052//}}}
1053CanonicalForm
1054CanonicalForm::operator [] ( int i ) const
1055{
1056    ASSERT( i >= 0, "index to operator [] less than zero" );
1057    if ( is_imm( value ) )
1058        if ( i == 0 )
1059            return *this;
1060        else
1061            return CanonicalForm( 0 );
1062    else
1063        return value->coeff( i );
1064}
1065//}}}
1066
1067//{{{ CanonicalForm CanonicalForm::deriv (), deriv ( x )
1068//{{{ docu
1069//
1070// deriv() - return the formal derivation of CO.
1071//
1072// deriv() derives CO with respect to its main variable.  Returns
1073// zero from the current domain if f is in a coefficient domain.
1074//
1075// deriv( x ) derives CO with respect to x.  x should be a
1076// polynomial variable.  Returns zero from the current domain if
1077// f is in a coefficient domain.
1078//
1079// See also: ::deriv()
1080//
1081//}}}
1082CanonicalForm
1083CanonicalForm::deriv () const
1084{
1085    if ( is_imm( value ) || value->inCoeffDomain() )
1086        return CanonicalForm( 0 );
1087    else {
1088        CanonicalForm result = 0;
1089        Variable x = value->variable();
1090        for ( CFIterator i = *this; i.hasTerms(); i++ )
1091            if ( i.exp() > 0 )
1092                result += power( x, i.exp()-1 ) * i.coeff() * i.exp();
1093        return result;
1094    }
1095}
1096
1097CanonicalForm
1098CanonicalForm::deriv ( const Variable & x ) const
1099{
1100    ASSERT( x.level() > 0, "cannot derive with respect to algebraic variables" );
1101    if ( is_imm( value ) || value->inCoeffDomain() )
1102        return CanonicalForm( 0 );
1103
1104    Variable y = value->variable();
1105    if ( x > y )
1106        return CanonicalForm( 0 );
1107    else if ( x == y )
1108        return deriv();
1109    else {
1110        CanonicalForm result = 0;
1111        for ( CFIterator i = *this; i.hasTerms(); i++ )
1112            result += i.coeff().deriv( x ) * power( y, i.exp() );
1113        return result;
1114    }
1115}
1116//}}}
1117
1118//{{{ int CanonicalForm::sign () const
1119//{{{ docu
1120//
1121// sign() - return sign of CO.
1122//
1123// If CO is an integer or a rational number, the sign is defined
1124// as usual.  If CO is an element of a prime power domain or of
1125// FF(p) and SW_SYMMETRIC_FF is on, the sign of CO is the sign of
1126// the symmetric representation of CO.  If CO is in GF(q) or in
1127// FF(p) and SW_SYMMETRIC_FF is off, the sign of CO is zero iff
1128// CO is zero, otherwise the sign is one.
1129//
1130// If CO is a polynomial or in an extension of one of the base
1131// domains, the sign of CO is the sign of its leading
1132// coefficient.
1133//
1134// See also: InternalCF::sign(), InternalInteger::sign(),
1135// InternalPrimePower::sign(), InternalRational::sign(),
1136// InternalPoly::sign(), imm_sign(), gf_sign()
1137//
1138//}}}
1139int
1140CanonicalForm::sign () const
1141{
1142    if ( is_imm( value ) )
1143        return imm_sign( value );
1144    else
1145        return value->sign();
1146}
1147//}}}
1148
1149//{{{ CanonicalForm CanonicalForm::sqrt () const
1150//{{{ docu
1151//
1152// sqrt() - calculate integer square root.
1153//
1154// CO has to be an integer greater or equal zero.  Returns the
1155// largest integer less or equal sqrt(CO).
1156//
1157// In the immediate case, we use the newton method to find the
1158// root.  The algorithm is from H. Cohen - 'A Course in
1159// Computational Algebraic Number Theory', ch. 1.7.1.
1160//
1161// See also: InternalCF::sqrt(), InternalInteger::sqrt(), ::sqrt()
1162//
1163//}}}
1164CanonicalForm
1165CanonicalForm::sqrt () const
1166{
1167    if ( is_imm( value ) ) {
1168        ASSERT( is_imm( value ) == INTMARK, "sqrt() not implemented" );
1169        int n = imm2int( value );
1170        ASSERT( n >= 0, "arg to sqrt() less than zero" );
1171        if ( n == 0 || n == 1 )
1172            return CanonicalForm( n );
1173        else {
1174            int x, y = n;
1175            do {
1176                x = y;
1177                // the intermediate result may not fit into an
1178                // integer, but the result does
1179                y = (unsigned int)(x + n/x)/2;
1180            } while ( y < x );
1181            return CanonicalForm( x );
1182        }
1183    }
1184    else
1185        return CanonicalForm( value->sqrt() );
1186}
1187//}}}
1188
1189//{{{ int CanonicalForm::ilog2 () const
1190//{{{ docu
1191//
1192// ilog2() - integer logarithm to base 2.
1193//
1194// Returns the largest integer less or equal logarithm of CO to
1195// base 2.  CO should be a positive integer.
1196//
1197// See also: InternalCF::ilog2(), InternalInteger::ilog2(), ::ilog2()
1198//
1199//}}}
1200int
1201CanonicalForm::ilog2 () const
1202{
1203    if ( is_imm( value ) ) {
1204        ASSERT( is_imm( value ) == INTMARK, "ilog2() not implemented" );
1205        int a = imm2int( value );
1206        ASSERT( a > 0, "arg to ilog2() less or equal zero" );
1207        int n = -1;
1208        while ( a != 0 ) {
1209            n++;
1210            a /= 2;
1211        }
1212        return n;
1213    }
1214    else
1215        return value->ilog2();
1216}
1217//}}}
1218
1219//{{{ bool operator ==, operator != ( const CanonicalForm & lhs, const CanonicalForm & rhs )
1220//{{{ docu
1221//
1222// operator ==(), operator !=() - compare canonical forms on
1223//   (in)equality.
1224//
1225// operator ==() returns true iff lhs equals rhs.
1226// operator !=() returns true iff lhs does not equal rhs.
1227//
1228// This is the point in factory where we essentially use that
1229// CanonicalForms in fact are canonical.  There must not be two
1230// different representations of the same mathematical object,
1231// otherwise, such (in)equality will not be recognized by these
1232// operators.  In other word, we rely on the fact that structural
1233// different factory objects in any case represent different
1234// mathematical objects.
1235//
1236// So we use the following procedure to test on equality (and
1237// analogously on inequality).  First, we check whether lhs.value
1238// equals rhs.value.  If so we are ready and return true.
1239// Second, if one of the operands is immediate, but the other one
1240// not, we return false.  Third, if the operand's levels differ
1241// we return false.  Fourth, if the operand's levelcoeffs differ
1242// we return false.  At last, we call the corresponding internal
1243// method to compare both operands.
1244//
1245// Both operands should have coefficients from the same base domain.
1246//
1247// Note: To compare with the zero or the unit of the current domain,
1248// you better use the methods `CanonicalForm::isZero()' or
1249// `CanonicalForm::isOne()', resp., than something like `f == 0',
1250// since the latter is quite a lot slower.
1251//
1252// See also: InternalCF::comparesame(),
1253// InternalInteger::comparesame(), InternalRational::comparesame(),
1254// InternalPrimePower::comparesame(), InternalPoly::comparesame()
1255//
1256//}}}
1257bool
1258operator == ( const CanonicalForm & lhs, const CanonicalForm & rhs )
1259{
1260    if ( lhs.value == rhs.value )
1261        return true;
1262    else if ( is_imm( rhs.value ) || is_imm( lhs.value ) ) {
1263        ASSERT( ! is_imm( rhs.value ) ||
1264                ! is_imm( lhs.value ) ||
1265                is_imm( rhs.value ) == is_imm( lhs.value ),
1266                "incompatible operands" );
1267        return false;
1268    }
1269    else  if ( lhs.value->level() != rhs.value->level() )
1270        return false;
1271    else  if ( lhs.value->levelcoeff() != rhs.value->levelcoeff() )
1272        return false;
1273    else
1274        return rhs.value->comparesame( lhs.value ) == 0;
1275}
1276
1277bool
1278operator != ( const CanonicalForm & lhs, const CanonicalForm & rhs )
1279{
1280    if ( lhs.value == rhs.value )
1281        return false;
1282    else if ( is_imm( rhs.value ) || is_imm( lhs.value ) ) {
1283        ASSERT( ! is_imm( rhs.value ) ||
1284                ! is_imm( lhs.value ) ||
1285                is_imm( rhs.value ) == is_imm( lhs.value ),
1286                "incompatible operands" );
1287        return true;
1288    }
1289    else  if ( lhs.value->level() != rhs.value->level() )
1290        return true;
1291    else  if ( lhs.value->levelcoeff() != rhs.value->levelcoeff() )
1292        return true;
1293    else        return rhs.value->comparesame( lhs.value ) != 0;
1294}
1295//}}}
1296
1297//{{{ bool operator >, operator < ( const CanonicalForm & lhs, const CanonicalForm & rhs )
1298//{{{ docu
1299//
1300// operator >(), operator <() - compare canonical forms. on size or
1301//   level.
1302//
1303// The most common and most useful application of these operators
1304// is to compare two integers or rationals, of course.  However,
1305// these operators are defined on all other base domains and on
1306// polynomials, too.  From a mathematical point of view this may
1307// seem meaningless, since there is no ordering on finite fields
1308// or on polynomials respecting the algebraic structure.
1309// Nevertheless, from a programmer's point of view it may be
1310// sensible to order these objects, e.g. to sort them.
1311//
1312// Therefore, the ordering defined by these operators in any case
1313// is a total ordering which fulfills the law of trichotomy.
1314//
1315// It is clear how this is done in the case of the integers and
1316// the rationals.  For finite fields, all you can say is that
1317// zero is the minimal element w.r.t. the ordering, the other
1318// elements are ordered in an arbitrary (but total!)  way.  For
1319// polynomials, you have an ordering derived from the
1320// lexicographical ordering of monomials.  E.g. if lm(f) < lm(g)
1321// w.r.t. lexicographic ordering, then f < g.  For more details,
1322// refer to the documentation of `InternalPoly::operator <()'.
1323//
1324// Both operands should have coefficients from the same base domain.
1325//
1326// The scheme how both operators are implemented is allmost the
1327// same as for the assignment operators (check for immediates,
1328// then check levels, then check levelcoeffs, then call the
1329// appropriate internal comparesame()/comparecoeff() method).
1330// For more information, confer to the overview for the
1331// arithmetic operators.
1332//
1333// See also: InternalCF::comparesame(),
1334// InternalInteger::comparesame(), InternalRational::comparesame(),
1335// InternalPrimePower::comparesame(), InternalPoly::comparesame(),
1336// InternalCF::comparecoeff(), InternalInteger::comparecoeff(),
1337// InternalRational::comparecoeff(),
1338// InternalPrimePower::comparecoeff(), InternalPoly::comparecoeff(),
1339// imm_cmp(), imm_cmp_p(), imm_cmp_gf()
1340//
1341//}}}
1342bool
1343operator > ( const CanonicalForm & lhs, const CanonicalForm & rhs )
1344{
1345    int what = is_imm( rhs.value );
1346    if ( is_imm( lhs.value ) ) {
1347        ASSERT( ! what || (what == is_imm( lhs.value )), "incompatible operands" );
1348        if ( what == 0 )
1349            return rhs.value->comparecoeff( lhs.value ) < 0;
1350        else if ( what == INTMARK )
1351            return imm_cmp( lhs.value, rhs.value ) > 0;
1352        else if ( what == FFMARK )
1353            return imm_cmp_p( lhs.value, rhs.value ) > 0;
1354        else
1355            return imm_cmp_gf( lhs.value, rhs.value ) > 0;
1356    }
1357    else  if ( what )
1358        return lhs.value->comparecoeff( rhs.value ) > 0;
1359    else  if ( lhs.value->level() == rhs.value->level() )
1360        if ( lhs.value->levelcoeff() == rhs.value->levelcoeff() )
1361            return lhs.value->comparesame( rhs.value ) > 0;
1362        else  if ( lhs.value->levelcoeff() > rhs.value->levelcoeff() )
1363            return lhs.value->comparecoeff( rhs.value ) > 0;
1364        else
1365            return rhs.value->comparecoeff( lhs.value ) < 0;
1366    else
1367        return lhs.value->level() > rhs.value->level();
1368}
1369
1370bool
1371operator < ( const CanonicalForm & lhs, const CanonicalForm & rhs )
1372{
1373    int what = is_imm( rhs.value );
1374    if ( is_imm( lhs.value ) ) {
1375        ASSERT( ! what || (what == is_imm( lhs.value )), "incompatible operands" );
1376        if ( what == 0 )
1377            return rhs.value->comparecoeff( lhs.value ) > 0;
1378        else if ( what == INTMARK )
1379            return imm_cmp( lhs.value, rhs.value ) < 0;
1380        else if ( what == FFMARK )
1381            return imm_cmp_p( lhs.value, rhs.value ) < 0;
1382        else
1383            return imm_cmp_gf( lhs.value, rhs.value ) < 0;
1384    }
1385    else  if ( what )
1386        return lhs.value->comparecoeff( rhs.value ) < 0;
1387    else  if ( lhs.value->level() == rhs.value->level() )
1388        if ( lhs.value->levelcoeff() == rhs.value->levelcoeff() )
1389            return lhs.value->comparesame( rhs.value ) < 0;
1390        else  if ( lhs.value->levelcoeff() > rhs.value->levelcoeff() )
1391            return lhs.value->comparecoeff( rhs.value ) < 0;
1392        else
1393            return rhs.value->comparecoeff( lhs.value ) > 0;
1394    else
1395        return lhs.value->level() < rhs.value->level();
1396}
1397//}}}
1398
1399//{{{ CanonicalForm bgcd ( const CanonicalForm & f, const CanonicalForm & g )
1400//{{{ docu
1401//
1402// bgcd() - return base coefficient gcd.
1403//
1404// If both f and g are integers and `SW_RATIONAL' is off the
1405// positive greatest common divisor of f and g is returned.
1406// Otherwise, if `SW_RATIONAL' is on or one of f and g is not an
1407// integer, the greatest common divisor is trivial: either zero
1408// if f and g equal zero or one (both from the current domain).
1409//
1410// f and g should come from one base domain which should be not
1411// the prime power domain.
1412//
1413// Implementation:
1414//
1415// CanonicalForm::bgcd() handles the immediate case with a
1416//   standard euclidean algorithm.  For the non-immediate cases
1417//   `InternalCF::bgcdsame()' or `InternalCF::bgcdcoeff()', resp. are
1418//   called following the usual level/levelcoeff approach.
1419//
1420// InternalCF::bgcdsame() and
1421// InternalCF::bgcdcoeff() throw an assertion ("not implemented")
1422//
1423// InternalInteger::bgcdsame() is a wrapper around `mpz_gcd()'
1424//   which takes some care about immediate results and the sign
1425//   of the result
1426// InternalInteger::bgcdcoeff() is a wrapper around
1427//   `mpz_gcd_ui()' which takes some care about the sign
1428//   of the result
1429//
1430// InternalRational::bgcdsame() and
1431// InternalRational::bgcdcoeff() always return one
1432//
1433//}}}
1434CanonicalForm
1435bgcd ( const CanonicalForm & f, const CanonicalForm & g )
1436{
1437    // check immediate cases
1438    int what = is_imm( g.value );
1439    if ( is_imm( f.value ) )
1440    {
1441        ASSERT( ! what || (what == is_imm( f.value )), "incompatible operands" );
1442        if ( what == 0 )
1443            return g.value->bgcdcoeff( f.value );
1444        else if ( what == INTMARK && ! cf_glob_switches.isOn( SW_RATIONAL ) )
1445        {
1446            // calculate gcd using standard integer
1447            // arithmetic
1448            int fInt = imm2int( f.value );
1449            int gInt = imm2int( g.value );
1450
1451            if ( fInt < 0 ) fInt = -fInt;
1452            if ( gInt < 0 ) gInt = -gInt;
1453            // swap fInt and gInt
1454            if ( gInt > fInt )
1455            {
1456                int swap = gInt;
1457                gInt = fInt;
1458                fInt = swap;
1459            }
1460
1461            // now, 0 <= gInt <= fInt.  Start the loop.
1462            while ( gInt )
1463            {
1464                // calculate (fInt, gInt) = (gInt, fInt%gInt)
1465                int r = fInt % gInt;
1466                fInt = gInt;
1467                gInt = r;
1468            }
1469
1470            return CanonicalForm( fInt );
1471        }
1472        else
1473            // we do not go for maximal speed for these stupid
1474            // special cases
1475            return CanonicalForm( f.isZero() && g.isZero() ? 0 : 1 );
1476    }
1477    else if ( what )
1478        return f.value->bgcdcoeff( g.value );
1479
1480    int fLevel = f.value->level();
1481    int gLevel = g.value->level();
1482
1483    // check levels
1484    if ( fLevel == gLevel )
1485    {
1486        fLevel = f.value->levelcoeff();
1487        gLevel = g.value->levelcoeff();
1488
1489        // check levelcoeffs
1490        if ( fLevel == gLevel )
1491            return f.value->bgcdsame( g.value );
1492        else if ( fLevel < gLevel )
1493            return g.value->bgcdcoeff( f.value );
1494        else
1495            return f.value->bgcdcoeff( g.value );
1496    }
1497    else if ( fLevel < gLevel )
1498        return g.value->bgcdcoeff( f.value );
1499    else
1500        return f.value->bgcdcoeff( g.value );
1501}
1502//}}}
1503
1504//{{{ CanonicalForm bextgcd ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & a, CanonicalForm & b )
1505//{{{ docu
1506//
1507// bextgcd() - return base coefficient extended gcd.
1508//
1509//}}}
1510CanonicalForm
1511bextgcd ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & a, CanonicalForm & b )
1512{
1513    // check immediate cases
1514    int what = is_imm( g.value );
1515    if ( is_imm( f.value ) ) {
1516        ASSERT( ! what || (what == is_imm( f.value )), "incompatible operands" );
1517        if ( what == 0 )
1518            return g.value->bextgcdcoeff( f.value, b, a );
1519        else if ( what == INTMARK && ! cf_glob_switches.isOn( SW_RATIONAL ) ) {
1520            // calculate extended gcd using standard integer
1521            // arithmetic
1522            int fInt = imm2int( f.value );
1523            int gInt = imm2int( g.value );
1524
1525            // to avoid any system dpendencies with `%', we work
1526            // with positive numbers only.  To a pity, we have to
1527            // redo all the checks when assigning to a and b.
1528            if ( fInt < 0 ) fInt = -fInt;
1529            if ( gInt < 0 ) gInt = -gInt;
1530            // swap fInt and gInt
1531            if ( gInt > fInt ) {
1532                int swap = gInt;
1533                gInt = fInt;
1534                fInt = swap;
1535            }
1536
1537            int u = 1; int v = 0;
1538            int uNext = 0; int vNext = 1;
1539
1540            // at any step, we have:
1541            // fInt_0 * u + gInt_0 * v = fInt
1542            // fInt_0 * uNext + gInt_0 * vNext = gInt
1543            // where fInt_0 and gInt_0 denote the values of fint
1544            // and gInt, resp., at the beginning
1545            while ( gInt ) {
1546                int r = fInt % gInt;
1547                int q = fInt / gInt;
1548                int uSwap = u - q * uNext;
1549                int vSwap = v - q * vNext;
1550
1551                // update variables
1552                fInt = gInt;
1553                gInt = r;
1554                u = uNext; v = vNext;
1555                uNext = uSwap; vNext = vSwap;
1556            }
1557
1558            // now, assign to a and b
1559            int fTest = imm2int( f.value );
1560            int gTest = imm2int( g.value );
1561            if ( gTest > fTest ) {
1562                a = v; b = u;
1563            } else {
1564                a = u; b = v;
1565            }
1566            if ( fTest < 0 ) a = -a;
1567            if ( gTest < 0 ) b = -b;
1568            return CanonicalForm( fInt );
1569        } else
1570            // stupid special cases
1571            if ( ! f.isZero() ) {
1572                a = 1/f; b = 0; return CanonicalForm( 1 );
1573            } else if ( ! g.isZero() ) {
1574                a = 0; b = 1/g; return CanonicalForm( 1 );
1575            } else {
1576                a = 0; b = 0; return CanonicalForm( 0 );
1577            }
1578    }
1579    else if ( what )
1580        return f.value->bextgcdcoeff( g.value, a, b );
1581
1582    int fLevel = f.value->level();
1583    int gLevel = g.value->level();
1584
1585    // check levels
1586    if ( fLevel == gLevel ) {
1587        fLevel = f.value->levelcoeff();
1588        gLevel = g.value->levelcoeff();
1589
1590        // check levelcoeffs
1591        if ( fLevel == gLevel )
1592            return f.value->bextgcdsame( g.value, a, b );
1593        else if ( fLevel < gLevel )
1594            return g.value->bextgcdcoeff( f.value, b, a );
1595        else
1596            return f.value->bextgcdcoeff( g.value, a, b );
1597    }
1598    else if ( fLevel < gLevel )
1599        return g.value->bextgcdcoeff( f.value, b, a );
1600    else
1601        return f.value->bextgcdcoeff( g.value, a, b );
1602}
1603//}}}
1604
1605CanonicalForm
1606blcm ( const CanonicalForm & f, const CanonicalForm & g )
1607{
1608    if ( f.isZero() || g.isZero() )
1609        return CanonicalForm( 0 );
1610/*
1611    else if (f.isOne())
1612        return g;
1613    else if (g.isOne())
1614        return f;
1615*/
1616    else
1617        return (f / bgcd( f, g )) * g;
1618}
1619
1620//{{{ input/output
1621#ifndef NOSTREAMIO
1622void
1623CanonicalForm::print( OSTREAM & os, char * str ) const
1624{
1625    if ( is_imm( value ) )
1626        imm_print( os, value, str );
1627    else
1628        value->print( os, str );
1629}
1630
1631void
1632CanonicalForm::print( OSTREAM & os ) const
1633{
1634    if ( is_imm( value ) )
1635        imm_print( os, value, "" );
1636    else
1637        value->print( os, "" );
1638}
1639
1640OSTREAM&
1641operator << ( OSTREAM & os, const CanonicalForm & cf )
1642{
1643    cf.print( os, "" );
1644    return os;
1645}
1646
1647ISTREAM&
1648operator >> ( ISTREAM & is, CanonicalForm & cf )
1649{
1650#ifndef SINGULAR
1651    cf = readCF( is );
1652    return is;
1653#else /* SINGULAR */
1654    return is;
1655#endif /* SINGULAR */
1656}
1657#endif /* NOSTREAMIO */
1658//}}}
1659
1660//{{{ genCoeff(), genOne(), genZero()
1661CanonicalForm
1662CanonicalForm::genCoeff( int type, int i )
1663{
1664    return CanonicalForm( CFFactory::basic( type, i ) );
1665}
1666
1667CanonicalForm
1668CanonicalForm::genZero() const
1669{
1670    int what = is_imm( value );
1671    if ( what == FFMARK )
1672        return CanonicalForm( CFFactory::basic( FiniteFieldDomain, 0 ) );
1673    else  if ( what == GFMARK )
1674        return CanonicalForm( CFFactory::basic( GaloisFieldDomain, 0 ) );
1675    else  if ( what )
1676        return CanonicalForm( CFFactory::basic( IntegerDomain, 0 ) );
1677    else
1678        return CanonicalForm( value->genZero() );
1679}
1680
1681CanonicalForm
1682CanonicalForm::genOne() const
1683{
1684    int what = is_imm( value );
1685    if ( what == FFMARK )
1686        return CanonicalForm( CFFactory::basic( FiniteFieldDomain, 1 ) );
1687    else  if ( what == GFMARK )
1688        return CanonicalForm( CFFactory::basic( GaloisFieldDomain, 1 ) );
1689    else  if ( what )
1690        return CanonicalForm( CFFactory::basic( IntegerDomain, 1 ) );
1691    else
1692        return CanonicalForm( value->genOne() );
1693}
1694//}}}
1695
1696//{{{ exponentiation
1697CanonicalForm
1698power ( const CanonicalForm & f, int n )
1699{
1700  ASSERT( n >= 0, "illegal exponent" );
1701  if ( f.isZero() )
1702    return 0;
1703  else  if ( f.isOne() )
1704    return f;
1705  else  if ( f == -1 )
1706  {
1707    if ( n % 2 == 0 )
1708      return 1;
1709    else
1710      return -1;
1711  }
1712  else  if ( n == 0 )
1713    return 1;
1714
1715  //else if (f.inGF())
1716  //{
1717  //}
1718  else
1719  {
1720    CanonicalForm g,h;
1721    h=f;
1722    while(n%2==0)
1723    {
1724      h*=h;
1725      n/=2;
1726    }
1727    g=h;
1728    while(1)
1729    {
1730      n/=2;
1731      if(n==0)
1732        return g;
1733      h*=h;
1734      if(n%2!=0) g*=h;
1735    }
1736  }
1737}
1738
1739CanonicalForm
1740power ( const Variable & v, int n )
1741{
1742    ASSERT( n >= 0, "illegal exponent" );
1743    if ( n == 0 )
1744        return 1;
1745    else  if ( n == 1 )
1746        return v;
1747    else  if ( v.level() < 0 )
1748    {
1749        CanonicalForm result( v, n-1 );
1750        return result * v;
1751    }
1752    else
1753        return CanonicalForm( v, n );
1754}
1755//}}}
1756
1757//{{{ switches
1758void
1759On( int sw )
1760{
1761    cf_glob_switches.On( sw );
1762}
1763
1764void
1765Off( int sw )
1766{
1767    cf_glob_switches.Off( sw );
1768}
1769
1770bool
1771isOn( int sw )
1772{
1773    return cf_glob_switches.isOn( sw );
1774}
1775//}}}
Note: See TracBrowser for help on using the repository browser.