source: git/factory/canonicalform.cc @ 0b447e

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