source: git/factory/canonicalform.cc @ ec970e

spielwiese
Last change on this file since ec970e was e28e6d, checked in by Martin Lee <martinlee84@…>, 13 years ago
towards better arithmetic in Z_p[x]/(f) for reducible f git-svn-id: file:///usr/local/Singular/svn/trunk@14326 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 55.1 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
793//same as divremt but handles zero divisors in case we are in Z_p[x]/(f) where f is not irreducible
794CanonicalForm &
795CanonicalForm::tryDiv ( const CanonicalForm & cf, const CanonicalForm& M, bool& fail )
796{
797    ASSERT (getCharacteristic() > 0, "expected positive characteristic");
798    ASSERT (!getReduce (M.mvar()), "do not reduce modulo M");
799    fail= false;
800    int what = is_imm( value );
801    if ( what ) {
802        ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" );
803        if ( (what = is_imm( cf.value )) == FFMARK )
804            value = imm_div_p( value, cf.value );
805        else  if ( what == GFMARK )
806            value = imm_div_gf( value, cf.value );
807        else {
808            InternalCF * dummy = cf.value->copyObject();
809            value = dummy->divcoeff( value, true );
810        }
811    }
812    else  if ( is_imm( cf.value ) )
813        value = value->tryDivcoeff (cf.value, false, M, fail);
814    else  if ( value->level() == cf.value->level() ) {
815        if ( value->levelcoeff() == cf.value->levelcoeff() )
816            value = value->tryDivsame( cf.value, M, fail );
817        else  if ( value->levelcoeff() > cf.value->levelcoeff() )
818            value = value->tryDivcoeff( cf.value, false, M, fail );
819        else {
820            InternalCF * dummy = cf.value->copyObject();
821            dummy = dummy->tryDivcoeff( value, true, M, fail );
822            if ( value->deleteObject() ) delete value;
823            value = dummy;
824        }
825    }
826    else  if ( level() > cf.level() )
827        value = value->tryDivcoeff( cf.value, false, M, fail );
828    else {
829        InternalCF * dummy = cf.value->copyObject();
830        dummy = dummy->tryDivcoeff( value, true, M, fail );
831        if ( value->deleteObject() ) delete value;
832        value = dummy;
833    }
834    return *this;
835}
836
837CanonicalForm &
838CanonicalForm::operator %= ( const CanonicalForm & cf )
839{
840    int what = is_imm( value );
841    if ( what ) {
842        ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" );
843        if ( (what = is_imm( cf.value )) == FFMARK )
844            value = imm_mod_p( value, cf.value );
845        else  if ( what == GFMARK )
846            value = imm_mod_gf( value, cf.value );
847        else  if ( what )
848            value = imm_mod( value, cf.value );
849        else {
850            InternalCF * dummy = cf.value->copyObject();
851            value = dummy->modulocoeff( value, true );
852        }
853    }
854    else  if ( is_imm( cf.value ) )
855        value = value->modulocoeff( cf.value, false );
856    else  if ( value->level() == cf.value->level() ) {
857        if ( value->levelcoeff() == cf.value->levelcoeff() )
858            value = value->modulosame( cf.value );
859        else  if ( value->levelcoeff() > cf.value->levelcoeff() )
860            value = value->modulocoeff( cf.value, false );
861        else {
862            InternalCF * dummy = cf.value->copyObject();
863            dummy = dummy->modulocoeff( value, true );
864            if ( value->deleteObject() ) delete value;
865            value = dummy;
866        }
867    }
868    else  if ( level() > cf.level() )
869        value = value->modulocoeff( cf.value, false );
870    else {
871        InternalCF * dummy = cf.value->copyObject();
872        dummy = dummy->modulocoeff( value, true );
873        if ( value->deleteObject() ) delete value;
874        value = dummy;
875    }
876    return *this;
877}
878
879CanonicalForm &
880CanonicalForm::mod ( const CanonicalForm & cf )
881{
882    int what = is_imm( value );
883    if ( what ) {
884        ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" );
885        if ( (what = is_imm( cf.value )) == FFMARK )
886            value = imm_mod_p( value, cf.value );
887        else  if ( what == GFMARK )
888            value = imm_mod_gf( value, cf.value );
889        else  if ( what )
890            value = imm_mod( value, cf.value );
891        else {
892            InternalCF * dummy = cf.value->copyObject();
893            value = dummy->modcoeff( value, true );
894        }
895    }
896    else  if ( is_imm( cf.value ) )
897        value = value->modcoeff( cf.value, false );
898    else  if ( value->level() == cf.value->level() ) {
899        if ( value->levelcoeff() == cf.value->levelcoeff() )
900            value = value->modsame( cf.value );
901        else  if ( value->levelcoeff() > cf.value->levelcoeff() )
902            value = value->modcoeff( cf.value, false );
903        else {
904            InternalCF * dummy = cf.value->copyObject();
905            dummy = dummy->modcoeff( value, true );
906            if ( value->deleteObject() ) delete value;
907            value = dummy;
908        }
909    }
910    else  if ( level() > cf.level() )
911        value = value->modcoeff( cf.value, false );
912    else {
913        InternalCF * dummy = cf.value->copyObject();
914        dummy = dummy->modcoeff( value, true );
915        if ( value->deleteObject() ) delete value;
916        value = dummy;
917    }
918    return *this;
919}
920
921void
922divrem ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & q, CanonicalForm & r )
923{
924    InternalCF * qq = 0, * rr = 0;
925    int what = is_imm( f.value );
926    if ( what )
927        if ( is_imm( g.value ) ) {
928            if ( what == FFMARK )
929                imm_divrem_p( f.value, g.value, qq, rr );
930            else  if ( what == GFMARK )
931                imm_divrem_gf( f.value, g.value, qq, rr );
932            else
933                imm_divrem( f.value, g.value, qq, rr );
934        }
935        else
936            g.value->divremcoeff( f.value, qq, rr, true );
937    else  if ( (what=is_imm( g.value )) )
938        f.value->divremcoeff( g.value, qq, rr, false );
939    else  if ( f.value->level() == g.value->level() )
940        if ( f.value->levelcoeff() == g.value->levelcoeff() )
941            f.value->divremsame( g.value, qq, rr );
942        else  if ( f.value->levelcoeff() > g.value->levelcoeff() )
943            f.value->divremcoeff( g.value, qq, rr, false );
944        else
945            g.value->divremcoeff( f.value, qq, rr, true );
946    else  if ( f.value->level() > g.value->level() )
947        f.value->divremcoeff( g.value, qq, rr, false );
948    else
949        g.value->divremcoeff( f.value, qq, rr, true );
950    ASSERT( qq != 0 && rr != 0, "error in divrem" );
951    q = CanonicalForm( qq );
952    r = CanonicalForm( rr );
953}
954
955bool
956divremt ( 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    bool result = true;
961    if ( what )
962        if ( is_imm( g.value ) ) {
963            if ( what == FFMARK )
964                imm_divrem_p( f.value, g.value, qq, rr );
965            else  if ( what == GFMARK )
966                imm_divrem_gf( f.value, g.value, qq, rr );
967            else
968                imm_divrem( f.value, g.value, qq, rr );
969        }
970        else
971            result = g.value->divremcoefft( f.value, qq, rr, true );
972    else  if ( (what=is_imm( g.value )) )
973        result = f.value->divremcoefft( g.value, qq, rr, false );
974    else  if ( f.value->level() == g.value->level() )
975        if ( f.value->levelcoeff() == g.value->levelcoeff() )
976            result = f.value->divremsamet( g.value, qq, rr );
977        else  if ( f.value->levelcoeff() > g.value->levelcoeff() )
978            result = f.value->divremcoefft( g.value, qq, rr, false );
979        else
980            result = g.value->divremcoefft( f.value, qq, rr, true );
981    else  if ( f.value->level() > g.value->level() )
982        result = f.value->divremcoefft( g.value, qq, rr, false );
983    else
984        result = g.value->divremcoefft( f.value, qq, rr, true );
985    if ( result ) {
986        ASSERT( qq != 0 && rr != 0, "error in divrem" );
987        q = CanonicalForm( qq );
988        r = CanonicalForm( rr );
989    }
990    else {
991        q = 0; r = 0;
992    }
993    return result;
994}
995
996//same as divremt but handles zero divisors in case we are in Z_p[x]/(f) where f is not irreducible
997bool
998tryDivremt ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & q, CanonicalForm & r, const CanonicalForm& M, bool& fail )
999{
1000    ASSERT (getCharacteristic() > 0, "expected positive characteristic");
1001    ASSERT (!getReduce (M.mvar()), "do not reduce modulo M");
1002    fail= false;
1003    InternalCF * qq = 0, * rr = 0;
1004    int what = is_imm( f.value );
1005    bool result = true;
1006    if ( what )
1007        if ( is_imm( g.value ) ) {
1008            if ( what == FFMARK )
1009                imm_divrem_p( f.value, g.value, qq, rr );
1010            else  if ( what == GFMARK )
1011                imm_divrem_gf( f.value, g.value, qq, rr );
1012        }
1013        else
1014            result = g.value->tryDivremcoefft( f.value, qq, rr, true, M, fail );
1015    else  if ( (what=is_imm( g.value )) )
1016        result = f.value->tryDivremcoefft( g.value, qq, rr, false, M, fail );
1017    else  if ( f.value->level() == g.value->level() )
1018        if ( f.value->levelcoeff() == g.value->levelcoeff() )
1019            result = f.value->tryDivremsamet( g.value, qq, rr, M, fail );
1020        else  if ( f.value->levelcoeff() > g.value->levelcoeff() )
1021            result = f.value->tryDivremcoefft( g.value, qq, rr, false, M, fail );
1022        else
1023            result = g.value->tryDivremcoefft( f.value, qq, rr, true, M, fail );
1024    else  if ( f.value->level() > g.value->level() )
1025        result = f.value->tryDivremcoefft( g.value, qq, rr, false, M, fail );
1026    else
1027        result = g.value->tryDivremcoefft( f.value, qq, rr, true, M, fail );
1028    if (fail)
1029    {
1030      q= 0;
1031      r= 0;
1032      return false;
1033    }
1034    if ( result ) {
1035        ASSERT( qq != 0 && rr != 0, "error in divrem" );
1036        q = CanonicalForm( qq );
1037        r = CanonicalForm( rr );
1038        q= reduce (q, M);
1039        r= reduce (r, M);
1040    }
1041    else {
1042        q = 0; r = 0;
1043    }
1044    return result;
1045}
1046
1047//}}}
1048
1049//{{{ CanonicalForm CanonicalForm::operator () ( f ), operator () ( f, v ) const
1050//{{{ docu
1051//
1052// operator ()() - evaluation operator.
1053//
1054// Both operators return CO if CO is in a base domain.
1055//
1056// operator () ( f ) returns CO with f inserted for the main
1057// variable.  Elements in an algebraic extension are considered
1058// polynomials.
1059//
1060// operator () ( f, v ) returns CO with f inserted for v.
1061// Elements in an algebraic extension are considered polynomials
1062// and v may be an algebraic variable.
1063//
1064//}}}
1065CanonicalForm
1066CanonicalForm::operator () ( const CanonicalForm & f ) const
1067{
1068    if ( is_imm( value ) || value->inBaseDomain() )
1069        return *this;
1070    else {
1071#if 0
1072        CFIterator i = *this;
1073        int lastExp = i.exp();
1074        CanonicalForm result = i.coeff();
1075        i++;
1076        while ( i.hasTerms() ) {
1077            if ( (lastExp - i.exp()) == 1 )
1078                result *= f;
1079            else
1080                result *= power( f, lastExp - i.exp() );
1081            result += i.coeff();
1082            lastExp = i.exp();
1083            i++;
1084        }
1085        if ( lastExp != 0 )
1086            result *= power( f, lastExp );
1087#else
1088        CFIterator i = *this;
1089        int lastExp = i.exp();
1090        CanonicalForm result = i.coeff();
1091        i++;
1092        while ( i.hasTerms() )
1093        {
1094            int i_exp=i.exp();
1095            if ( (lastExp - i_exp /* i.exp()*/) == 1 )
1096                result *= f;
1097            else
1098                result *= power( f, lastExp - i_exp /*i.exp()*/ );
1099            result += i.coeff();
1100            lastExp = i_exp /*i.exp()*/;
1101            i++;
1102        }
1103        if ( lastExp != 0 )
1104            result *= power( f, lastExp );
1105#endif
1106        return result;
1107    }
1108}
1109
1110CanonicalForm
1111CanonicalForm::operator () ( const CanonicalForm & f, const Variable & v ) const
1112{
1113    if ( is_imm( value ) || value->inBaseDomain() )
1114        return *this;
1115
1116    Variable x = value->variable();
1117    if ( v > x )
1118        return *this;
1119    else  if ( v == x )
1120        return (*this)( f );
1121    else {
1122        // v is less than main variable of f
1123        CanonicalForm result = 0;
1124        for ( CFIterator i = *this; i.hasTerms(); i++ )
1125            result += i.coeff()( f, v ) * power( x, i.exp() );
1126        return result;
1127    }
1128}
1129//}}}
1130
1131//{{{ CanonicalForm CanonicalForm::operator [] ( int i ) const
1132//{{{ docu
1133//
1134// operator []() - return i'th coefficient from CO.
1135//
1136// Returns CO if CO is in a base domain and i equals zero.
1137// Returns zero (from the current domain) if CO is in a base
1138// domain and i is larger than zero.  Otherwise, returns the
1139// coefficient to x^i in CO (if x denotes the main variable of
1140// CO) or zero if CO does not contain x^i.  Elements in an
1141// algebraic extension are considered polynomials.  i should be
1142// larger or equal zero.
1143//
1144// Note: Never use a loop like
1145//
1146// for ( int i = degree( f ); i >= 0; i-- )
1147//     foo( i, f[ i ] );
1148//
1149// which is much slower than
1150//
1151// for ( int i = degree( f ), CFIterator I = f; I.hasTerms(); I++ ) {
1152//     // fill gap with zeroes
1153//     for ( ; i > I.exp(); i-- )
1154//         foo( i, 0 );
1155//     // at this point, i == I.exp()
1156//     foo( i, i.coeff() );
1157//     i--;
1158// }
1159// // work through trailing zeroes
1160// for ( ; i >= 0; i-- )
1161//     foo( i, 0 );
1162//
1163//}}}
1164CanonicalForm
1165CanonicalForm::operator [] ( int i ) const
1166{
1167    ASSERT( i >= 0, "index to operator [] less than zero" );
1168    if ( is_imm( value ) )
1169        if ( i == 0 )
1170            return *this;
1171        else
1172            return CanonicalForm( 0 );
1173    else
1174        return value->coeff( i );
1175}
1176//}}}
1177
1178//{{{ CanonicalForm CanonicalForm::deriv (), deriv ( x )
1179//{{{ docu
1180//
1181// deriv() - return the formal derivation of CO.
1182//
1183// deriv() derives CO with respect to its main variable.  Returns
1184// zero from the current domain if f is in a coefficient domain.
1185//
1186// deriv( x ) derives CO with respect to x.  x should be a
1187// polynomial variable.  Returns zero from the current domain if
1188// f is in a coefficient domain.
1189//
1190// See also: ::deriv()
1191//
1192//}}}
1193CanonicalForm
1194CanonicalForm::deriv () const
1195{
1196    if ( is_imm( value ) || value->inCoeffDomain() )
1197        return CanonicalForm( 0 );
1198    else {
1199        CanonicalForm result = 0;
1200        Variable x = value->variable();
1201        for ( CFIterator i = *this; i.hasTerms(); i++ )
1202            if ( i.exp() > 0 )
1203                result += power( x, i.exp()-1 ) * i.coeff() * i.exp();
1204        return result;
1205    }
1206}
1207
1208CanonicalForm
1209CanonicalForm::deriv ( const Variable & x ) const
1210{
1211    ASSERT( x.level() > 0, "cannot derive with respect to algebraic variables" );
1212    if ( is_imm( value ) || value->inCoeffDomain() )
1213        return CanonicalForm( 0 );
1214
1215    Variable y = value->variable();
1216    if ( x > y )
1217        return CanonicalForm( 0 );
1218    else if ( x == y )
1219        return deriv();
1220    else {
1221        CanonicalForm result = 0;
1222        for ( CFIterator i = *this; i.hasTerms(); i++ )
1223            result += i.coeff().deriv( x ) * power( y, i.exp() );
1224        return result;
1225    }
1226}
1227//}}}
1228
1229//{{{ int CanonicalForm::sign () const
1230//{{{ docu
1231//
1232// sign() - return sign of CO.
1233//
1234// If CO is an integer or a rational number, the sign is defined
1235// as usual.  If CO is an element of a prime power domain or of
1236// FF(p) and SW_SYMMETRIC_FF is on, the sign of CO is the sign of
1237// the symmetric representation of CO.  If CO is in GF(q) or in
1238// FF(p) and SW_SYMMETRIC_FF is off, the sign of CO is zero iff
1239// CO is zero, otherwise the sign is one.
1240//
1241// If CO is a polynomial or in an extension of one of the base
1242// domains, the sign of CO is the sign of its leading
1243// coefficient.
1244//
1245// See also: InternalCF::sign(), InternalInteger::sign(),
1246// InternalPrimePower::sign(), InternalRational::sign(),
1247// InternalPoly::sign(), imm_sign(), gf_sign()
1248//
1249//}}}
1250int
1251CanonicalForm::sign () const
1252{
1253    if ( is_imm( value ) )
1254        return imm_sign( value );
1255    else
1256        return value->sign();
1257}
1258//}}}
1259
1260//{{{ CanonicalForm CanonicalForm::sqrt () const
1261//{{{ docu
1262//
1263// sqrt() - calculate integer square root.
1264//
1265// CO has to be an integer greater or equal zero.  Returns the
1266// largest integer less or equal sqrt(CO).
1267//
1268// In the immediate case, we use the newton method to find the
1269// root.  The algorithm is from H. Cohen - 'A Course in
1270// Computational Algebraic Number Theory', ch. 1.7.1.
1271//
1272// See also: InternalCF::sqrt(), InternalInteger::sqrt(), ::sqrt()
1273//
1274//}}}
1275CanonicalForm
1276CanonicalForm::sqrt () const
1277{
1278    if ( is_imm( value ) ) {
1279        ASSERT( is_imm( value ) == INTMARK, "sqrt() not implemented" );
1280        int n = imm2int( value );
1281        ASSERT( n >= 0, "arg to sqrt() less than zero" );
1282        if ( n == 0 || n == 1 )
1283            return CanonicalForm( n );
1284        else {
1285            int x, y = n;
1286            do {
1287                x = y;
1288                // the intermediate result may not fit into an
1289                // integer, but the result does
1290                y = (unsigned int)(x + n/x)/2;
1291            } while ( y < x );
1292            return CanonicalForm( x );
1293        }
1294    }
1295    else
1296        return CanonicalForm( value->sqrt() );
1297}
1298//}}}
1299
1300//{{{ int CanonicalForm::ilog2 () const
1301//{{{ docu
1302//
1303// ilog2() - integer logarithm to base 2.
1304//
1305// Returns the largest integer less or equal logarithm of CO to
1306// base 2.  CO should be a positive integer.
1307//
1308// See also: InternalCF::ilog2(), InternalInteger::ilog2(), ::ilog2()
1309//
1310//}}}
1311int
1312CanonicalForm::ilog2 () const
1313{
1314    if ( is_imm( value ) )
1315    {
1316        ASSERT( is_imm( value ) == INTMARK, "ilog2() not implemented" );
1317        int a = imm2int( value );
1318        ASSERT( a > 0, "arg to ilog2() less or equal zero" );
1319        return ::ilog2(a);
1320    }
1321    else
1322        return value->ilog2();
1323}
1324//}}}
1325
1326//{{{ bool operator ==, operator != ( const CanonicalForm & lhs, const CanonicalForm & rhs )
1327//{{{ docu
1328//
1329// operator ==(), operator !=() - compare canonical forms on
1330//   (in)equality.
1331//
1332// operator ==() returns true iff lhs equals rhs.
1333// operator !=() returns true iff lhs does not equal rhs.
1334//
1335// This is the point in factory where we essentially use that
1336// CanonicalForms in fact are canonical.  There must not be two
1337// different representations of the same mathematical object,
1338// otherwise, such (in)equality will not be recognized by these
1339// operators.  In other word, we rely on the fact that structural
1340// different factory objects in any case represent different
1341// mathematical objects.
1342//
1343// So we use the following procedure to test on equality (and
1344// analogously on inequality).  First, we check whether lhs.value
1345// equals rhs.value.  If so we are ready and return true.
1346// Second, if one of the operands is immediate, but the other one
1347// not, we return false.  Third, if the operand's levels differ
1348// we return false.  Fourth, if the operand's levelcoeffs differ
1349// we return false.  At last, we call the corresponding internal
1350// method to compare both operands.
1351//
1352// Both operands should have coefficients from the same base domain.
1353//
1354// Note: To compare with the zero or the unit of the current domain,
1355// you better use the methods `CanonicalForm::isZero()' or
1356// `CanonicalForm::isOne()', resp., than something like `f == 0',
1357// since the latter is quite a lot slower.
1358//
1359// See also: InternalCF::comparesame(),
1360// InternalInteger::comparesame(), InternalRational::comparesame(),
1361// InternalPrimePower::comparesame(), InternalPoly::comparesame()
1362//
1363//}}}
1364bool
1365operator == ( const CanonicalForm & lhs, const CanonicalForm & rhs )
1366{
1367    if ( lhs.value == rhs.value )
1368        return true;
1369    else if ( is_imm( rhs.value ) || is_imm( lhs.value ) ) {
1370        ASSERT( ! is_imm( rhs.value ) ||
1371                ! is_imm( lhs.value ) ||
1372                is_imm( rhs.value ) == is_imm( lhs.value ),
1373                "incompatible operands" );
1374        return false;
1375    }
1376    else  if ( lhs.value->level() != rhs.value->level() )
1377        return false;
1378    else  if ( lhs.value->levelcoeff() != rhs.value->levelcoeff() )
1379        return false;
1380    else
1381        return rhs.value->comparesame( lhs.value ) == 0;
1382}
1383
1384bool
1385operator != ( const CanonicalForm & lhs, const CanonicalForm & rhs )
1386{
1387    if ( lhs.value == rhs.value )
1388        return false;
1389    else if ( is_imm( rhs.value ) || is_imm( lhs.value ) ) {
1390        ASSERT( ! is_imm( rhs.value ) ||
1391                ! is_imm( lhs.value ) ||
1392                is_imm( rhs.value ) == is_imm( lhs.value ),
1393                "incompatible operands" );
1394        return true;
1395    }
1396    else  if ( lhs.value->level() != rhs.value->level() )
1397        return true;
1398    else  if ( lhs.value->levelcoeff() != rhs.value->levelcoeff() )
1399        return true;
1400    else        return rhs.value->comparesame( lhs.value ) != 0;
1401}
1402//}}}
1403
1404//{{{ bool operator >, operator < ( const CanonicalForm & lhs, const CanonicalForm & rhs )
1405//{{{ docu
1406//
1407// operator >(), operator <() - compare canonical forms. on size or
1408//   level.
1409//
1410// The most common and most useful application of these operators
1411// is to compare two integers or rationals, of course.  However,
1412// these operators are defined on all other base domains and on
1413// polynomials, too.  From a mathematical point of view this may
1414// seem meaningless, since there is no ordering on finite fields
1415// or on polynomials respecting the algebraic structure.
1416// Nevertheless, from a programmer's point of view it may be
1417// sensible to order these objects, e.g. to sort them.
1418//
1419// Therefore, the ordering defined by these operators in any case
1420// is a total ordering which fulfills the law of trichotomy.
1421//
1422// It is clear how this is done in the case of the integers and
1423// the rationals.  For finite fields, all you can say is that
1424// zero is the minimal element w.r.t. the ordering, the other
1425// elements are ordered in an arbitrary (but total!)  way.  For
1426// polynomials, you have an ordering derived from the
1427// lexicographical ordering of monomials.  E.g. if lm(f) < lm(g)
1428// w.r.t. lexicographic ordering, then f < g.  For more details,
1429// refer to the documentation of `InternalPoly::operator <()'.
1430//
1431// Both operands should have coefficients from the same base domain.
1432//
1433// The scheme how both operators are implemented is allmost the
1434// same as for the assignment operators (check for immediates,
1435// then check levels, then check levelcoeffs, then call the
1436// appropriate internal comparesame()/comparecoeff() method).
1437// For more information, confer to the overview for the
1438// arithmetic operators.
1439//
1440// See also: InternalCF::comparesame(),
1441// InternalInteger::comparesame(), InternalRational::comparesame(),
1442// InternalPrimePower::comparesame(), InternalPoly::comparesame(),
1443// InternalCF::comparecoeff(), InternalInteger::comparecoeff(),
1444// InternalRational::comparecoeff(),
1445// InternalPrimePower::comparecoeff(), InternalPoly::comparecoeff(),
1446// imm_cmp(), imm_cmp_p(), imm_cmp_gf()
1447//
1448//}}}
1449bool
1450operator > ( const CanonicalForm & lhs, const CanonicalForm & rhs )
1451{
1452    int what = is_imm( rhs.value );
1453    if ( is_imm( lhs.value ) ) {
1454        ASSERT( ! what || (what == is_imm( lhs.value )), "incompatible operands" );
1455        if ( what == 0 )
1456            return rhs.value->comparecoeff( lhs.value ) < 0;
1457        else if ( what == INTMARK )
1458            return imm_cmp( lhs.value, rhs.value ) > 0;
1459        else if ( what == FFMARK )
1460            return imm_cmp_p( lhs.value, rhs.value ) > 0;
1461        else
1462            return imm_cmp_gf( lhs.value, rhs.value ) > 0;
1463    }
1464    else  if ( what )
1465        return lhs.value->comparecoeff( rhs.value ) > 0;
1466    else  if ( lhs.value->level() == rhs.value->level() )
1467        if ( lhs.value->levelcoeff() == rhs.value->levelcoeff() )
1468            return lhs.value->comparesame( rhs.value ) > 0;
1469        else  if ( lhs.value->levelcoeff() > rhs.value->levelcoeff() )
1470            return lhs.value->comparecoeff( rhs.value ) > 0;
1471        else
1472            return rhs.value->comparecoeff( lhs.value ) < 0;
1473    else
1474        return lhs.value->level() > rhs.value->level();
1475}
1476
1477bool
1478operator < ( const CanonicalForm & lhs, const CanonicalForm & rhs )
1479{
1480    int what = is_imm( rhs.value );
1481    if ( is_imm( lhs.value ) ) {
1482        ASSERT( ! what || (what == is_imm( lhs.value )), "incompatible operands" );
1483        if ( what == 0 )
1484            return rhs.value->comparecoeff( lhs.value ) > 0;
1485        else if ( what == INTMARK )
1486            return imm_cmp( lhs.value, rhs.value ) < 0;
1487        else if ( what == FFMARK )
1488            return imm_cmp_p( lhs.value, rhs.value ) < 0;
1489        else
1490            return imm_cmp_gf( lhs.value, rhs.value ) < 0;
1491    }
1492    else  if ( what )
1493        return lhs.value->comparecoeff( rhs.value ) < 0;
1494    else  if ( lhs.value->level() == rhs.value->level() )
1495        if ( lhs.value->levelcoeff() == rhs.value->levelcoeff() )
1496            return lhs.value->comparesame( rhs.value ) < 0;
1497        else  if ( lhs.value->levelcoeff() > rhs.value->levelcoeff() )
1498            return lhs.value->comparecoeff( rhs.value ) < 0;
1499        else
1500            return rhs.value->comparecoeff( lhs.value ) > 0;
1501    else
1502        return lhs.value->level() < rhs.value->level();
1503}
1504//}}}
1505
1506//{{{ CanonicalForm bgcd ( const CanonicalForm & f, const CanonicalForm & g )
1507//{{{ docu
1508//
1509// bgcd() - return base coefficient gcd.
1510//
1511// If both f and g are integers and `SW_RATIONAL' is off the
1512// positive greatest common divisor of f and g is returned.
1513// Otherwise, if `SW_RATIONAL' is on or one of f and g is not an
1514// integer, the greatest common divisor is trivial: either zero
1515// if f and g equal zero or one (both from the current domain).
1516//
1517// f and g should come from one base domain which should be not
1518// the prime power domain.
1519//
1520// Implementation:
1521//
1522// CanonicalForm::bgcd() handles the immediate case with a
1523//   standard euclidean algorithm.  For the non-immediate cases
1524//   `InternalCF::bgcdsame()' or `InternalCF::bgcdcoeff()', resp. are
1525//   called following the usual level/levelcoeff approach.
1526//
1527// InternalCF::bgcdsame() and
1528// InternalCF::bgcdcoeff() throw an assertion ("not implemented")
1529//
1530// InternalInteger::bgcdsame() is a wrapper around `mpz_gcd()'
1531//   which takes some care about immediate results and the sign
1532//   of the result
1533// InternalInteger::bgcdcoeff() is a wrapper around
1534//   `mpz_gcd_ui()' which takes some care about the sign
1535//   of the result
1536//
1537// InternalRational::bgcdsame() and
1538// InternalRational::bgcdcoeff() always return one
1539//
1540//}}}
1541CanonicalForm
1542bgcd ( const CanonicalForm & f, const CanonicalForm & g )
1543{
1544    // check immediate cases
1545    int what = is_imm( g.value );
1546    if ( is_imm( f.value ) )
1547    {
1548        ASSERT( ! what || (what == is_imm( f.value )), "incompatible operands" );
1549        if ( what == 0 )
1550            return g.value->bgcdcoeff( f.value );
1551        else if ( what == INTMARK && ! cf_glob_switches.isOn( SW_RATIONAL ) )
1552        {
1553            // calculate gcd using standard integer
1554            // arithmetic
1555            int fInt = imm2int( f.value );
1556            int gInt = imm2int( g.value );
1557
1558            if ( fInt < 0 ) fInt = -fInt;
1559            if ( gInt < 0 ) gInt = -gInt;
1560            // swap fInt and gInt
1561            if ( gInt > fInt )
1562            {
1563                int swap = gInt;
1564                gInt = fInt;
1565                fInt = swap;
1566            }
1567
1568            // now, 0 <= gInt <= fInt.  Start the loop.
1569            while ( gInt )
1570            {
1571                // calculate (fInt, gInt) = (gInt, fInt%gInt)
1572                int r = fInt % gInt;
1573                fInt = gInt;
1574                gInt = r;
1575            }
1576
1577            return CanonicalForm( fInt );
1578        }
1579        else
1580            // we do not go for maximal speed for these stupid
1581            // special cases
1582            return CanonicalForm( f.isZero() && g.isZero() ? 0 : 1 );
1583    }
1584    else if ( what )
1585        return f.value->bgcdcoeff( g.value );
1586
1587    int fLevel = f.value->level();
1588    int gLevel = g.value->level();
1589
1590    // check levels
1591    if ( fLevel == gLevel )
1592    {
1593        fLevel = f.value->levelcoeff();
1594        gLevel = g.value->levelcoeff();
1595
1596        // check levelcoeffs
1597        if ( fLevel == gLevel )
1598            return f.value->bgcdsame( g.value );
1599        else if ( fLevel < gLevel )
1600            return g.value->bgcdcoeff( f.value );
1601        else
1602            return f.value->bgcdcoeff( g.value );
1603    }
1604    else if ( fLevel < gLevel )
1605        return g.value->bgcdcoeff( f.value );
1606    else
1607        return f.value->bgcdcoeff( g.value );
1608}
1609//}}}
1610
1611//{{{ CanonicalForm bextgcd ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & a, CanonicalForm & b )
1612//{{{ docu
1613//
1614// bextgcd() - return base coefficient extended gcd.
1615//
1616//}}}
1617CanonicalForm
1618bextgcd ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & a, CanonicalForm & b )
1619{
1620    // check immediate cases
1621    int what = is_imm( g.value );
1622    if ( is_imm( f.value ) ) {
1623        ASSERT( ! what || (what == is_imm( f.value )), "incompatible operands" );
1624        if ( what == 0 )
1625            return g.value->bextgcdcoeff( f.value, b, a );
1626        else if ( what == INTMARK && ! cf_glob_switches.isOn( SW_RATIONAL ) ) {
1627            // calculate extended gcd using standard integer
1628            // arithmetic
1629            int fInt = imm2int( f.value );
1630            int gInt = imm2int( g.value );
1631
1632            // to avoid any system dpendencies with `%', we work
1633            // with positive numbers only.  To a pity, we have to
1634            // redo all the checks when assigning to a and b.
1635            if ( fInt < 0 ) fInt = -fInt;
1636            if ( gInt < 0 ) gInt = -gInt;
1637            // swap fInt and gInt
1638            if ( gInt > fInt ) {
1639                int swap = gInt;
1640                gInt = fInt;
1641                fInt = swap;
1642            }
1643
1644            int u = 1; int v = 0;
1645            int uNext = 0; int vNext = 1;
1646
1647            // at any step, we have:
1648            // fInt_0 * u + gInt_0 * v = fInt
1649            // fInt_0 * uNext + gInt_0 * vNext = gInt
1650            // where fInt_0 and gInt_0 denote the values of fint
1651            // and gInt, resp., at the beginning
1652            while ( gInt ) {
1653                int r = fInt % gInt;
1654                int q = fInt / gInt;
1655                int uSwap = u - q * uNext;
1656                int vSwap = v - q * vNext;
1657
1658                // update variables
1659                fInt = gInt;
1660                gInt = r;
1661                u = uNext; v = vNext;
1662                uNext = uSwap; vNext = vSwap;
1663            }
1664
1665            // now, assign to a and b
1666            int fTest = imm2int( f.value );
1667            int gTest = imm2int( g.value );
1668            if ( gTest > fTest ) {
1669                a = v; b = u;
1670            } else {
1671                a = u; b = v;
1672            }
1673            if ( fTest < 0 ) a = -a;
1674            if ( gTest < 0 ) b = -b;
1675            return CanonicalForm( fInt );
1676        } else
1677            // stupid special cases
1678            if ( ! f.isZero() ) {
1679                a = 1/f; b = 0; return CanonicalForm( 1 );
1680            } else if ( ! g.isZero() ) {
1681                a = 0; b = 1/g; return CanonicalForm( 1 );
1682            } else {
1683                a = 0; b = 0; return CanonicalForm( 0 );
1684            }
1685    }
1686    else if ( what )
1687        return f.value->bextgcdcoeff( g.value, a, b );
1688
1689    int fLevel = f.value->level();
1690    int gLevel = g.value->level();
1691
1692    // check levels
1693    if ( fLevel == gLevel ) {
1694        fLevel = f.value->levelcoeff();
1695        gLevel = g.value->levelcoeff();
1696
1697        // check levelcoeffs
1698        if ( fLevel == gLevel )
1699            return f.value->bextgcdsame( g.value, a, b );
1700        else if ( fLevel < gLevel )
1701            return g.value->bextgcdcoeff( f.value, b, a );
1702        else
1703            return f.value->bextgcdcoeff( g.value, a, b );
1704    }
1705    else if ( fLevel < gLevel )
1706        return g.value->bextgcdcoeff( f.value, b, a );
1707    else
1708        return f.value->bextgcdcoeff( g.value, a, b );
1709}
1710//}}}
1711
1712CanonicalForm
1713blcm ( const CanonicalForm & f, const CanonicalForm & g )
1714{
1715    if ( f.isZero() || g.isZero() )
1716        return CanonicalForm( 0 );
1717/*
1718    else if (f.isOne())
1719        return g;
1720    else if (g.isOne())
1721        return f;
1722*/
1723    else
1724        return (f / bgcd( f, g )) * g;
1725}
1726
1727//{{{ input/output
1728#ifndef NOSTREAMIO
1729void
1730CanonicalForm::print( OSTREAM & os, char * str ) const
1731{
1732    if ( is_imm( value ) )
1733        imm_print( os, value, str );
1734    else
1735        value->print( os, str );
1736}
1737
1738void
1739CanonicalForm::print( OSTREAM & os ) const
1740{
1741    if ( is_imm( value ) )
1742        imm_print( os, value, "" );
1743    else
1744        value->print( os, "" );
1745}
1746
1747OSTREAM&
1748operator << ( OSTREAM & os, const CanonicalForm & cf )
1749{
1750    cf.print( os, "" );
1751    return os;
1752}
1753
1754ISTREAM&
1755operator >> ( ISTREAM & is, CanonicalForm & cf )
1756{
1757    cf = readCF( is );
1758    return is;
1759}
1760#endif /* NOSTREAMIO */
1761//}}}
1762
1763//{{{ genCoeff(), genOne(), genZero()
1764CanonicalForm
1765CanonicalForm::genCoeff( int type, int i )
1766{
1767    return CanonicalForm( CFFactory::basic( type, i ) );
1768}
1769
1770CanonicalForm
1771CanonicalForm::genZero() const
1772{
1773    int what = is_imm( value );
1774    if ( what == FFMARK )
1775        return CanonicalForm( CFFactory::basic( FiniteFieldDomain, 0 ) );
1776    else  if ( what == GFMARK )
1777        return CanonicalForm( CFFactory::basic( GaloisFieldDomain, 0 ) );
1778    else  if ( what )
1779        return CanonicalForm( CFFactory::basic( IntegerDomain, 0 ) );
1780    else
1781        return CanonicalForm( value->genZero() );
1782}
1783
1784CanonicalForm
1785CanonicalForm::genOne() const
1786{
1787    int what = is_imm( value );
1788    if ( what == FFMARK )
1789        return CanonicalForm( CFFactory::basic( FiniteFieldDomain, 1 ) );
1790    else  if ( what == GFMARK )
1791        return CanonicalForm( CFFactory::basic( GaloisFieldDomain, 1 ) );
1792    else  if ( what )
1793        return CanonicalForm( CFFactory::basic( IntegerDomain, 1 ) );
1794    else
1795        return CanonicalForm( value->genOne() );
1796}
1797//}}}
1798
1799//{{{ exponentiation
1800CanonicalForm
1801power ( const CanonicalForm & f, int n )
1802{
1803  ASSERT( n >= 0, "illegal exponent" );
1804  if ( f.isZero() )
1805    return 0;
1806  else  if ( f.isOne() )
1807    return f;
1808  else  if ( f == -1 )
1809  {
1810    if ( n % 2 == 0 )
1811      return 1;
1812    else
1813      return -1;
1814  }
1815  else  if ( n == 0 )
1816    return 1;
1817
1818  //else if (f.inGF())
1819  //{
1820  //}
1821  else
1822  {
1823    CanonicalForm g,h;
1824    h=f;
1825    while(n%2==0)
1826    {
1827      h*=h;
1828      n/=2;
1829    }
1830    g=h;
1831    while(1)
1832    {
1833      n/=2;
1834      if(n==0)
1835        return g;
1836      h*=h;
1837      if(n%2!=0) g*=h;
1838    }
1839  }
1840}
1841
1842CanonicalForm
1843power ( const Variable & v, int n )
1844{
1845    ASSERT( n >= 0, "illegal exponent" );
1846    if ( n == 0 )
1847        return 1;
1848    else  if ( n == 1 )
1849        return v;
1850    else  if (( v.level() < 0 ) && (hasMipo(v)))
1851    {
1852        CanonicalForm result( v, n-1 );
1853        return result * v;
1854    }
1855    else
1856        return CanonicalForm( v, n );
1857}
1858//}}}
1859
1860//{{{ switches
1861void
1862On( int sw )
1863{
1864    cf_glob_switches.On( sw );
1865}
1866
1867void
1868Off( int sw )
1869{
1870    cf_glob_switches.Off( sw );
1871}
1872
1873bool
1874isOn( int sw )
1875{
1876    return cf_glob_switches.isOn( sw );
1877}
1878//}}}
Note: See TracBrowser for help on using the repository browser.