source: git/factory/canonicalform.cc @ 3ae414

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