source: git/factory/canonicalform.cc @ ba5e9e

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