source: git/factory/canonicalform.cc @ 77aa42

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