source: git/factory/canonicalform.cc @ 9fd0b1

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