source: git/factory/canonicalform.cc @ e4fe2b

spielwiese
Last change on this file since e4fe2b was e4fe2b, checked in by Oleksandr Motsak <motsak@…>, 13 years ago
FIX: Fixed huge BUG in cf_gmp.h CHG: starting to cleanup factory
  • 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 "cf_assert.h"
7#include "cf_factory.h"
8
9#include "cf_defs.h"
10#include "cf_globals.h"
11#include "canonicalform.h"
12#include "cf_iter.h"
13#include "int_cf.h"
14#include "cf_algorithm.h"
15#include "imm.h"
16#include "gfops.h"
17#include "cf_binom.h"
18
19#if defined (USE_MEMUTIL) && ! defined (USE_OLD_MEMMAN)
20#include "memman.h"
21#endif
22
23#include "cf_gmp.h"
24
25
26#ifndef NOSTREAMIO
27CanonicalForm readCF( ISTREAM& );
28#endif /* NOSTREAMIO */
29
30//{{{ initialization
31int initializeGMP();
32int initializeCharacteristic();
33
34#ifdef SINGULAR
35extern int mmInit(void);
36#endif
37
38int
39initCanonicalForm( void )
40{
41    static bool initialized = false;
42    if ( ! initialized ) {
43#if (defined (USE_MEMUTIL) && ! defined (USE_OLD_MEMMAN)) || defined (SINGULAR)
44        (void)mmInit();
45#endif
46
47        (void)initializeCharacteristic();
48        (void)initializeGMP();
49        initPT();
50        initialized = true;
51    }
52    return 1;
53}
54//}}}
55
56//{{{ constructors, destructors, selectors
57CanonicalForm::CanonicalForm( const char * str, const int base ) : value( CFFactory::basic( str, base ) )
58{
59}
60
61InternalCF*
62CanonicalForm::getval() const
63{
64    if ( is_imm( value ) )
65        return value;
66    else
67        return value->copyObject();
68}
69
70CanonicalForm
71CanonicalForm::deepCopy() const
72{
73    if ( is_imm( value ) )
74        return *this;
75    else
76        return CanonicalForm( value->deepCopyObject() );
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
226int
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// See also: InternalCF::tailcoeff(), InternalCF::tailcoeff(),
488// InternalPoly::tailcoeff(), InternalPoly::taildegree,
489// ::tailcoeff(), ::taildegree()
490//
491//}}}
492CanonicalForm
493CanonicalForm::tailcoeff () const
494{
495    if ( is_imm( value ) || value->inCoeffDomain() )
496        return *this;
497    else
498        return value->tailcoeff();
499}
500
501int
502CanonicalForm::taildegree () const
503{
504    int what = is_imm( value );
505    if ( what )
506        if ( what == FFMARK )
507            return imm_iszero_p( value ) ? -1 : 0;
508        else if ( what == INTMARK )
509            return imm_iszero( value ) ? -1 : 0;
510        else
511            return imm_iszero_gf( value ) ? -1 : 0;
512    else
513        return value->taildegree();
514}
515//}}}
516
517//{{{ int CanonicalForm::level (), Variable CanonicalForm::mvar () const
518//{{{ docu
519//
520// level(), mvar() - return level and main variable of CO.
521//
522// level() returns the level of CO.  For a list of the levels and
523// their meanings, see cf_defs.h.
524//
525// mvar() returns the main variable of CO or Variable() if CO is
526// in a base domain.
527//
528// See also: InternalCF::level(), InternalCF::variable(),
529// InternalPoly::level(), InternalPoly::variable(), ::level(),
530// ::mvar()
531//
532//}}}
533int
534CanonicalForm::level () const
535{
536    if ( is_imm( value ) )
537        return LEVELBASE;
538    else
539        return value->level();
540}
541
542Variable
543CanonicalForm::mvar () const
544{
545    if ( is_imm( value ) )
546        return Variable();
547    else
548        return value->variable();
549}
550//}}}
551
552//{{{ CanonicalForm CanonicalForm::num (), den () const
553//{{{ docu
554//
555// num(), den() - return numinator and denominator of CO.
556//
557// num() returns the numinator of CO if CO is a rational number,
558// CO itself otherwise.
559//
560// den() returns the denominator of CO if CO is a rational
561// number, 1 (from the current domain!) otherwise.
562//
563// See also: InternalCF::num(), InternalCF::den(),
564// InternalRational::num(), InternalRational::den(), ::num(),
565// ::den()
566//
567//}}}
568CanonicalForm
569CanonicalForm::num () const
570{
571    if ( is_imm( value ) )
572        return *this;
573    else
574        return CanonicalForm( value->num() );
575}
576
577CanonicalForm
578CanonicalForm::den () const
579{
580    if ( is_imm( value ) )
581        return CanonicalForm( 1 );
582    else
583        return CanonicalForm( value->den() );
584}
585//}}}
586
587//{{{ assignment operators
588CanonicalForm &
589CanonicalForm::operator += ( const CanonicalForm & cf )
590{
591    int what = is_imm( value );
592    if ( what ) {
593        ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" );
594        if ( (what = is_imm( cf.value )) == FFMARK )
595            value = imm_add_p( value, cf.value );
596        else  if ( what == GFMARK )
597            value = imm_add_gf( value, cf.value );
598        else  if ( what )
599            value = imm_add( value, cf.value );
600        else {
601            InternalCF * dummy = cf.value->copyObject();
602            value = dummy->addcoeff( value );
603        }
604    }
605    else  if ( is_imm( cf.value ) )
606        value = value->addcoeff( cf.value );
607    else  if ( value->level() == cf.value->level() ) {
608        if ( value->levelcoeff() == cf.value->levelcoeff() )
609            value = value->addsame( cf.value );
610        else  if ( value->levelcoeff() > cf.value->levelcoeff() )
611            value = value->addcoeff( cf.value );
612        else {
613            InternalCF * dummy = cf.value->copyObject();
614            dummy = dummy->addcoeff( value );
615            if ( value->deleteObject() ) delete value;
616            value = dummy;
617        }
618    }
619    else  if ( level() > cf.level() )
620        value = value->addcoeff( cf.value );
621    else {
622        InternalCF * dummy = cf.value->copyObject();
623        dummy = dummy->addcoeff( value );
624        if ( value->deleteObject() ) delete value;
625        value = dummy;
626    }
627    return *this;
628}
629
630CanonicalForm &
631CanonicalForm::operator -= ( const CanonicalForm & cf )
632{
633    int what = is_imm( value );
634    if ( what ) {
635        ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" );
636        if ( (what = is_imm( cf.value )) == FFMARK )
637            value = imm_sub_p( value, cf.value );
638        else  if ( what == GFMARK )
639            value = imm_sub_gf( value, cf.value );
640        else  if ( what )
641            value = imm_sub( value, cf.value );
642        else {
643            InternalCF * dummy = cf.value->copyObject();
644            value = dummy->subcoeff( value, true );
645        }
646    }
647    else  if ( is_imm( cf.value ) )
648        value = value->subcoeff( cf.value, false );
649    else  if ( value->level() == cf.value->level() ) {
650        if ( value->levelcoeff() == cf.value->levelcoeff() )
651            value = value->subsame( cf.value );
652        else  if ( value->levelcoeff() > cf.value->levelcoeff() )
653            value = value->subcoeff( cf.value, false );
654        else {
655            InternalCF * dummy = cf.value->copyObject();
656            dummy = dummy->subcoeff( value, true );
657            if ( value->deleteObject() ) delete value;
658            value = dummy;
659        }
660    }
661    else  if ( level() > cf.level() )
662        value = value->subcoeff( cf.value, false );
663    else {
664        InternalCF * dummy = cf.value->copyObject();
665        dummy = dummy->subcoeff( value, true );
666        if ( value->deleteObject() ) delete value;
667        value = dummy;
668    }
669    return *this;
670}
671
672CanonicalForm &
673CanonicalForm::operator *= ( const CanonicalForm & cf )
674{
675    int what = is_imm( value );
676    if ( what ) {
677        ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" );
678        if ( (what = is_imm( cf.value )) == FFMARK )
679            value = imm_mul_p( value, cf.value );
680        else  if ( what == GFMARK )
681            value = imm_mul_gf( value, cf.value );
682        else  if ( what )
683            value = imm_mul( value, cf.value );
684        else {
685            InternalCF * dummy = cf.value->copyObject();
686            value = dummy->mulcoeff( value );
687        }
688    }
689    else  if ( is_imm( cf.value ) )
690        value = value->mulcoeff( cf.value );
691    else  if ( value->level() == cf.value->level() ) {
692        if ( value->levelcoeff() == cf.value->levelcoeff() )
693            value = value->mulsame( cf.value );
694        else  if ( value->levelcoeff() > cf.value->levelcoeff() )
695            value = value->mulcoeff( cf.value );
696        else {
697            InternalCF * dummy = cf.value->copyObject();
698            dummy = dummy->mulcoeff( value );
699            if ( value->deleteObject() ) delete value;
700            value = dummy;
701        }
702    }
703    else  if ( level() > cf.level() )
704        value = value->mulcoeff( cf.value );
705    else {
706        InternalCF * dummy = cf.value->copyObject();
707        dummy = dummy->mulcoeff( value );
708        if ( value->deleteObject() ) delete value;
709        value = dummy;
710    }
711    return *this;
712}
713
714CanonicalForm &
715CanonicalForm::operator /= ( const CanonicalForm & cf )
716{
717    int what = is_imm( value );
718    if ( what ) {
719        ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" );
720        if ( (what = is_imm( cf.value )) == FFMARK )
721            value = imm_div_p( value, cf.value );
722        else  if ( what == GFMARK )
723            value = imm_div_gf( value, cf.value );
724        else  if ( what )
725            value = imm_divrat( value, cf.value );
726        else {
727            InternalCF * dummy = cf.value->copyObject();
728            value = dummy->dividecoeff( value, true );
729        }
730    }
731    else  if ( is_imm( cf.value ) )
732        value = value->dividecoeff( cf.value, false );
733    else  if ( value->level() == cf.value->level() ) {
734        if ( value->levelcoeff() == cf.value->levelcoeff() )
735            value = value->dividesame( cf.value );
736        else  if ( value->levelcoeff() > cf.value->levelcoeff() )
737            value = value->dividecoeff( cf.value, false );
738        else {
739            InternalCF * dummy = cf.value->copyObject();
740            dummy = dummy->dividecoeff( value, true );
741            if ( value->deleteObject() ) delete value;
742            value = dummy;
743        }
744    }
745    else  if ( level() > cf.level() )
746        value = value->dividecoeff( cf.value, false );
747    else {
748        InternalCF * dummy = cf.value->copyObject();
749        dummy = dummy->dividecoeff( value, true );
750        if ( value->deleteObject() ) delete value;
751        value = dummy;
752    }
753    return *this;
754}
755
756CanonicalForm &
757CanonicalForm::div ( const CanonicalForm & cf )
758{
759    int what = is_imm( value );
760    if ( what ) {
761        ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" );
762        if ( (what = is_imm( cf.value )) == FFMARK )
763            value = imm_div_p( value, cf.value );
764        else  if ( what == GFMARK )
765            value = imm_div_gf( value, cf.value );
766        else  if ( what )
767            value = imm_div( value, cf.value );
768        else {
769            InternalCF * dummy = cf.value->copyObject();
770            value = dummy->divcoeff( value, true );
771        }
772    }
773    else  if ( is_imm( cf.value ) )
774        value = value->divcoeff( cf.value, false );
775    else  if ( value->level() == cf.value->level() ) {
776        if ( value->levelcoeff() == cf.value->levelcoeff() )
777            value = value->divsame( cf.value );
778        else  if ( value->levelcoeff() > cf.value->levelcoeff() )
779            value = value->divcoeff( cf.value, false );
780        else {
781            InternalCF * dummy = cf.value->copyObject();
782            dummy = dummy->divcoeff( value, true );
783            if ( value->deleteObject() ) delete value;
784            value = dummy;
785        }
786    }
787    else  if ( level() > cf.level() )
788        value = value->divcoeff( cf.value, false );
789    else {
790        InternalCF * dummy = cf.value->copyObject();
791        dummy = dummy->divcoeff( value, true );
792        if ( value->deleteObject() ) delete value;
793        value = dummy;
794    }
795    return *this;
796}
797
798//same as divremt but handles zero divisors in case we are in Z_p[x]/(f) where f is not irreducible
799CanonicalForm &
800CanonicalForm::tryDiv ( const CanonicalForm & cf, const CanonicalForm& M, bool& fail )
801{
802    ASSERT (getCharacteristic() > 0, "expected positive characteristic");
803    ASSERT (!getReduce (M.mvar()), "do not reduce modulo M");
804    fail= false;
805    int what = is_imm( value );
806    if ( what ) {
807        ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" );
808        if ( (what = is_imm( cf.value )) == FFMARK )
809            value = imm_div_p( value, cf.value );
810        else  if ( what == GFMARK )
811            value = imm_div_gf( value, cf.value );
812        else {
813            InternalCF * dummy = cf.value->copyObject();
814            value = dummy->divcoeff( value, true );
815        }
816    }
817    else  if ( is_imm( cf.value ) )
818        value = value->tryDivcoeff (cf.value, false, M, fail);
819    else  if ( value->level() == cf.value->level() ) {
820        if ( value->levelcoeff() == cf.value->levelcoeff() )
821            value = value->tryDivsame( cf.value, M, fail );
822        else  if ( value->levelcoeff() > cf.value->levelcoeff() )
823            value = value->tryDivcoeff( cf.value, false, M, fail );
824        else {
825            InternalCF * dummy = cf.value->copyObject();
826            dummy = dummy->tryDivcoeff( value, true, M, fail );
827            if ( value->deleteObject() ) delete value;
828            value = dummy;
829        }
830    }
831    else  if ( level() > cf.level() )
832        value = value->tryDivcoeff( cf.value, false, M, fail );
833    else {
834        InternalCF * dummy = cf.value->copyObject();
835        dummy = dummy->tryDivcoeff( value, true, M, fail );
836        if ( value->deleteObject() ) delete value;
837        value = dummy;
838    }
839    return *this;
840}
841
842CanonicalForm &
843CanonicalForm::operator %= ( const CanonicalForm & cf )
844{
845    int what = is_imm( value );
846    if ( what ) {
847        ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" );
848        if ( (what = is_imm( cf.value )) == FFMARK )
849            value = imm_mod_p( value, cf.value );
850        else  if ( what == GFMARK )
851            value = imm_mod_gf( value, cf.value );
852        else  if ( what )
853            value = imm_mod( value, cf.value );
854        else {
855            InternalCF * dummy = cf.value->copyObject();
856            value = dummy->modulocoeff( value, true );
857        }
858    }
859    else  if ( is_imm( cf.value ) )
860        value = value->modulocoeff( cf.value, false );
861    else  if ( value->level() == cf.value->level() ) {
862        if ( value->levelcoeff() == cf.value->levelcoeff() )
863            value = value->modulosame( cf.value );
864        else  if ( value->levelcoeff() > cf.value->levelcoeff() )
865            value = value->modulocoeff( cf.value, false );
866        else {
867            InternalCF * dummy = cf.value->copyObject();
868            dummy = dummy->modulocoeff( value, true );
869            if ( value->deleteObject() ) delete value;
870            value = dummy;
871        }
872    }
873    else  if ( level() > cf.level() )
874        value = value->modulocoeff( cf.value, false );
875    else {
876        InternalCF * dummy = cf.value->copyObject();
877        dummy = dummy->modulocoeff( value, true );
878        if ( value->deleteObject() ) delete value;
879        value = dummy;
880    }
881    return *this;
882}
883
884CanonicalForm &
885CanonicalForm::mod ( const CanonicalForm & cf )
886{
887    int what = is_imm( value );
888    if ( what ) {
889        ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" );
890        if ( (what = is_imm( cf.value )) == FFMARK )
891            value = imm_mod_p( value, cf.value );
892        else  if ( what == GFMARK )
893            value = imm_mod_gf( value, cf.value );
894        else  if ( what )
895            value = imm_mod( value, cf.value );
896        else {
897            InternalCF * dummy = cf.value->copyObject();
898            value = dummy->modcoeff( value, true );
899        }
900    }
901    else  if ( is_imm( cf.value ) )
902        value = value->modcoeff( cf.value, false );
903    else  if ( value->level() == cf.value->level() ) {
904        if ( value->levelcoeff() == cf.value->levelcoeff() )
905            value = value->modsame( cf.value );
906        else  if ( value->levelcoeff() > cf.value->levelcoeff() )
907            value = value->modcoeff( cf.value, false );
908        else {
909            InternalCF * dummy = cf.value->copyObject();
910            dummy = dummy->modcoeff( value, true );
911            if ( value->deleteObject() ) delete value;
912            value = dummy;
913        }
914    }
915    else  if ( level() > cf.level() )
916        value = value->modcoeff( cf.value, false );
917    else {
918        InternalCF * dummy = cf.value->copyObject();
919        dummy = dummy->modcoeff( value, true );
920        if ( value->deleteObject() ) delete value;
921        value = dummy;
922    }
923    return *this;
924}
925
926void
927divrem ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & q, CanonicalForm & r )
928{
929    InternalCF * qq = 0, * rr = 0;
930    int what = is_imm( f.value );
931    if ( what )
932        if ( is_imm( g.value ) ) {
933            if ( what == FFMARK )
934                imm_divrem_p( f.value, g.value, qq, rr );
935            else  if ( what == GFMARK )
936                imm_divrem_gf( f.value, g.value, qq, rr );
937            else
938                imm_divrem( f.value, g.value, qq, rr );
939        }
940        else
941            g.value->divremcoeff( f.value, qq, rr, true );
942    else  if ( (what=is_imm( g.value )) )
943        f.value->divremcoeff( g.value, qq, rr, false );
944    else  if ( f.value->level() == g.value->level() )
945        if ( f.value->levelcoeff() == g.value->levelcoeff() )
946            f.value->divremsame( g.value, qq, rr );
947        else  if ( f.value->levelcoeff() > g.value->levelcoeff() )
948            f.value->divremcoeff( g.value, qq, rr, false );
949        else
950            g.value->divremcoeff( f.value, qq, rr, true );
951    else  if ( f.value->level() > g.value->level() )
952        f.value->divremcoeff( g.value, qq, rr, false );
953    else
954        g.value->divremcoeff( f.value, qq, rr, true );
955    ASSERT( qq != 0 && rr != 0, "error in divrem" );
956    q = CanonicalForm( qq );
957    r = CanonicalForm( rr );
958}
959
960bool
961divremt ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & q, CanonicalForm & r )
962{
963    InternalCF * qq = 0, * rr = 0;
964    int what = is_imm( f.value );
965    bool result = true;
966    if ( what )
967        if ( is_imm( g.value ) ) {
968            if ( what == FFMARK )
969                imm_divrem_p( f.value, g.value, qq, rr );
970            else  if ( what == GFMARK )
971                imm_divrem_gf( f.value, g.value, qq, rr );
972            else
973                imm_divrem( f.value, g.value, qq, rr );
974        }
975        else
976            result = g.value->divremcoefft( f.value, qq, rr, true );
977    else  if ( (what=is_imm( g.value )) )
978        result = f.value->divremcoefft( g.value, qq, rr, false );
979    else  if ( f.value->level() == g.value->level() )
980        if ( f.value->levelcoeff() == g.value->levelcoeff() )
981            result = f.value->divremsamet( g.value, qq, rr );
982        else  if ( f.value->levelcoeff() > g.value->levelcoeff() )
983            result = f.value->divremcoefft( g.value, qq, rr, false );
984        else
985            result = g.value->divremcoefft( f.value, qq, rr, true );
986    else  if ( f.value->level() > g.value->level() )
987        result = f.value->divremcoefft( g.value, qq, rr, false );
988    else
989        result = g.value->divremcoefft( f.value, qq, rr, true );
990    if ( result ) {
991        ASSERT( qq != 0 && rr != 0, "error in divrem" );
992        q = CanonicalForm( qq );
993        r = CanonicalForm( rr );
994    }
995    else {
996        q = 0; r = 0;
997    }
998    return result;
999}
1000
1001//same as divremt but handles zero divisors in case we are in Z_p[x]/(f) where f is not irreducible
1002bool
1003tryDivremt ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & q, CanonicalForm & r, const CanonicalForm& M, bool& fail )
1004{
1005    ASSERT (getCharacteristic() > 0, "expected positive characteristic");
1006    ASSERT (!getReduce (M.mvar()), "do not reduce modulo M");
1007    fail= false;
1008    InternalCF * qq = 0, * rr = 0;
1009    int what = is_imm( f.value );
1010    bool result = true;
1011    if ( what )
1012        if ( is_imm( g.value ) ) {
1013            if ( what == FFMARK )
1014                imm_divrem_p( f.value, g.value, qq, rr );
1015            else  if ( what == GFMARK )
1016                imm_divrem_gf( f.value, g.value, qq, rr );
1017        }
1018        else
1019            result = g.value->tryDivremcoefft( f.value, qq, rr, true, M, fail );
1020    else  if ( (what=is_imm( g.value )) )
1021        result = f.value->tryDivremcoefft( g.value, qq, rr, false, M, fail );
1022    else  if ( f.value->level() == g.value->level() )
1023        if ( f.value->levelcoeff() == g.value->levelcoeff() )
1024            result = f.value->tryDivremsamet( g.value, qq, rr, M, fail );
1025        else  if ( f.value->levelcoeff() > g.value->levelcoeff() )
1026            result = f.value->tryDivremcoefft( g.value, qq, rr, false, M, fail );
1027        else
1028            result = g.value->tryDivremcoefft( f.value, qq, rr, true, M, fail );
1029    else  if ( f.value->level() > g.value->level() )
1030        result = f.value->tryDivremcoefft( g.value, qq, rr, false, M, fail );
1031    else
1032        result = g.value->tryDivremcoefft( f.value, qq, rr, true, M, fail );
1033    if (fail)
1034    {
1035      q= 0;
1036      r= 0;
1037      return false;
1038    }
1039    if ( result ) {
1040        ASSERT( qq != 0 && rr != 0, "error in divrem" );
1041        q = CanonicalForm( qq );
1042        r = CanonicalForm( rr );
1043        q= reduce (q, M);
1044        r= reduce (r, M);
1045    }
1046    else {
1047        q = 0; r = 0;
1048    }
1049    return result;
1050}
1051
1052//}}}
1053
1054//{{{ CanonicalForm CanonicalForm::operator () ( f ), operator () ( f, v ) const
1055//{{{ docu
1056//
1057// operator ()() - evaluation operator.
1058//
1059// Both operators return CO if CO is in a base domain.
1060//
1061// operator () ( f ) returns CO with f inserted for the main
1062// variable.  Elements in an algebraic extension are considered
1063// polynomials.
1064//
1065// operator () ( f, v ) returns CO with f inserted for v.
1066// Elements in an algebraic extension are considered polynomials
1067// and v may be an algebraic variable.
1068//
1069//}}}
1070CanonicalForm
1071CanonicalForm::operator () ( const CanonicalForm & f ) const
1072{
1073    if ( is_imm( value ) || value->inBaseDomain() )
1074        return *this;
1075    else {
1076#if 0
1077        CFIterator i = *this;
1078        int lastExp = i.exp();
1079        CanonicalForm result = i.coeff();
1080        i++;
1081        while ( i.hasTerms() ) {
1082            if ( (lastExp - i.exp()) == 1 )
1083                result *= f;
1084            else
1085                result *= power( f, lastExp - i.exp() );
1086            result += i.coeff();
1087            lastExp = i.exp();
1088            i++;
1089        }
1090        if ( lastExp != 0 )
1091            result *= power( f, lastExp );
1092#else
1093        CFIterator i = *this;
1094        int lastExp = i.exp();
1095        CanonicalForm result = i.coeff();
1096        i++;
1097        while ( i.hasTerms() )
1098        {
1099            int i_exp=i.exp();
1100            if ( (lastExp - i_exp /* i.exp()*/) == 1 )
1101                result *= f;
1102            else
1103                result *= power( f, lastExp - i_exp /*i.exp()*/ );
1104            result += i.coeff();
1105            lastExp = i_exp /*i.exp()*/;
1106            i++;
1107        }
1108        if ( lastExp != 0 )
1109            result *= power( f, lastExp );
1110#endif
1111        return result;
1112    }
1113}
1114
1115CanonicalForm
1116CanonicalForm::operator () ( const CanonicalForm & f, const Variable & v ) const
1117{
1118    if ( is_imm( value ) || value->inBaseDomain() )
1119        return *this;
1120
1121    Variable x = value->variable();
1122    if ( v > x )
1123        return *this;
1124    else  if ( v == x )
1125        return (*this)( f );
1126    else {
1127        // v is less than main variable of f
1128        CanonicalForm result = 0;
1129        for ( CFIterator i = *this; i.hasTerms(); i++ )
1130            result += i.coeff()( f, v ) * power( x, i.exp() );
1131        return result;
1132    }
1133}
1134//}}}
1135
1136//{{{ CanonicalForm CanonicalForm::operator [] ( int i ) const
1137//{{{ docu
1138//
1139// operator []() - return i'th coefficient from CO.
1140//
1141// Returns CO if CO is in a base domain and i equals zero.
1142// Returns zero (from the current domain) if CO is in a base
1143// domain and i is larger than zero.  Otherwise, returns the
1144// coefficient to x^i in CO (if x denotes the main variable of
1145// CO) or zero if CO does not contain x^i.  Elements in an
1146// algebraic extension are considered polynomials.  i should be
1147// larger or equal zero.
1148//
1149// Note: Never use a loop like
1150//
1151// for ( int i = degree( f ); i >= 0; i-- )
1152//     foo( i, f[ i ] );
1153//
1154// which is much slower than
1155//
1156// for ( int i = degree( f ), CFIterator I = f; I.hasTerms(); I++ ) {
1157//     // fill gap with zeroes
1158//     for ( ; i > I.exp(); i-- )
1159//         foo( i, 0 );
1160//     // at this point, i == I.exp()
1161//     foo( i, i.coeff() );
1162//     i--;
1163// }
1164// // work through trailing zeroes
1165// for ( ; i >= 0; i-- )
1166//     foo( i, 0 );
1167//
1168//}}}
1169CanonicalForm
1170CanonicalForm::operator [] ( int i ) const
1171{
1172    ASSERT( i >= 0, "index to operator [] less than zero" );
1173    if ( is_imm( value ) )
1174        if ( i == 0 )
1175            return *this;
1176        else
1177            return CanonicalForm( 0 );
1178    else
1179        return value->coeff( i );
1180}
1181//}}}
1182
1183//{{{ CanonicalForm CanonicalForm::deriv (), deriv ( x )
1184//{{{ docu
1185//
1186// deriv() - return the formal derivation of CO.
1187//
1188// deriv() derives CO with respect to its main variable.  Returns
1189// zero from the current domain if f is in a coefficient domain.
1190//
1191// deriv( x ) derives CO with respect to x.  x should be a
1192// polynomial variable.  Returns zero from the current domain if
1193// f is in a coefficient domain.
1194//
1195// See also: ::deriv()
1196//
1197//}}}
1198CanonicalForm
1199CanonicalForm::deriv () const
1200{
1201    if ( is_imm( value ) || value->inCoeffDomain() )
1202        return CanonicalForm( 0 );
1203    else {
1204        CanonicalForm result = 0;
1205        Variable x = value->variable();
1206        for ( CFIterator i = *this; i.hasTerms(); i++ )
1207            if ( i.exp() > 0 )
1208                result += power( x, i.exp()-1 ) * i.coeff() * i.exp();
1209        return result;
1210    }
1211}
1212
1213CanonicalForm
1214CanonicalForm::deriv ( const Variable & x ) const
1215{
1216    ASSERT( x.level() > 0, "cannot derive with respect to algebraic variables" );
1217    if ( is_imm( value ) || value->inCoeffDomain() )
1218        return CanonicalForm( 0 );
1219
1220    Variable y = value->variable();
1221    if ( x > y )
1222        return CanonicalForm( 0 );
1223    else if ( x == y )
1224        return deriv();
1225    else {
1226        CanonicalForm result = 0;
1227        for ( CFIterator i = *this; i.hasTerms(); i++ )
1228            result += i.coeff().deriv( x ) * power( y, i.exp() );
1229        return result;
1230    }
1231}
1232//}}}
1233
1234//{{{ int CanonicalForm::sign () const
1235//{{{ docu
1236//
1237// sign() - return sign of CO.
1238//
1239// If CO is an integer or a rational number, the sign is defined
1240// as usual.  If CO is an element of a prime power domain or of
1241// FF(p) and SW_SYMMETRIC_FF is on, the sign of CO is the sign of
1242// the symmetric representation of CO.  If CO is in GF(q) or in
1243// FF(p) and SW_SYMMETRIC_FF is off, the sign of CO is zero iff
1244// CO is zero, otherwise the sign is one.
1245//
1246// If CO is a polynomial or in an extension of one of the base
1247// domains, the sign of CO is the sign of its leading
1248// coefficient.
1249//
1250// See also: InternalCF::sign(), InternalInteger::sign(),
1251// InternalPrimePower::sign(), InternalRational::sign(),
1252// InternalPoly::sign(), imm_sign(), gf_sign()
1253//
1254//}}}
1255int
1256CanonicalForm::sign () const
1257{
1258    if ( is_imm( value ) )
1259        return imm_sign( value );
1260    else
1261        return value->sign();
1262}
1263//}}}
1264
1265//{{{ CanonicalForm CanonicalForm::sqrt () const
1266//{{{ docu
1267//
1268// sqrt() - calculate integer square root.
1269//
1270// CO has to be an integer greater or equal zero.  Returns the
1271// largest integer less or equal sqrt(CO).
1272//
1273// In the immediate case, we use the newton method to find the
1274// root.  The algorithm is from H. Cohen - 'A Course in
1275// Computational Algebraic Number Theory', ch. 1.7.1.
1276//
1277// See also: InternalCF::sqrt(), InternalInteger::sqrt(), ::sqrt()
1278//
1279//}}}
1280CanonicalForm
1281CanonicalForm::sqrt () const
1282{
1283    if ( is_imm( value ) ) {
1284        ASSERT( is_imm( value ) == INTMARK, "sqrt() not implemented" );
1285        int n = imm2int( value );
1286        ASSERT( n >= 0, "arg to sqrt() less than zero" );
1287        if ( n == 0 || n == 1 )
1288            return CanonicalForm( n );
1289        else {
1290            int x, y = n;
1291            do {
1292                x = y;
1293                // the intermediate result may not fit into an
1294                // integer, but the result does
1295                y = (unsigned int)(x + n/x)/2;
1296            } while ( y < x );
1297            return CanonicalForm( x );
1298        }
1299    }
1300    else
1301        return CanonicalForm( value->sqrt() );
1302}
1303//}}}
1304
1305//{{{ int CanonicalForm::ilog2 () const
1306//{{{ docu
1307//
1308// ilog2() - integer logarithm to base 2.
1309//
1310// Returns the largest integer less or equal logarithm of CO to
1311// base 2.  CO should be a positive integer.
1312//
1313// See also: InternalCF::ilog2(), InternalInteger::ilog2(), ::ilog2()
1314//
1315//}}}
1316int
1317CanonicalForm::ilog2 () const
1318{
1319    if ( is_imm( value ) )
1320    {
1321        ASSERT( is_imm( value ) == INTMARK, "ilog2() not implemented" );
1322        int a = imm2int( value );
1323        ASSERT( a > 0, "arg to ilog2() less or equal zero" );
1324        return ::ilog2(a);
1325    }
1326    else
1327        return value->ilog2();
1328}
1329//}}}
1330
1331//{{{ bool operator ==, operator != ( const CanonicalForm & lhs, const CanonicalForm & rhs )
1332//{{{ docu
1333//
1334// operator ==(), operator !=() - compare canonical forms on
1335//   (in)equality.
1336//
1337// operator ==() returns true iff lhs equals rhs.
1338// operator !=() returns true iff lhs does not equal rhs.
1339//
1340// This is the point in factory where we essentially use that
1341// CanonicalForms in fact are canonical.  There must not be two
1342// different representations of the same mathematical object,
1343// otherwise, such (in)equality will not be recognized by these
1344// operators.  In other word, we rely on the fact that structural
1345// different factory objects in any case represent different
1346// mathematical objects.
1347//
1348// So we use the following procedure to test on equality (and
1349// analogously on inequality).  First, we check whether lhs.value
1350// equals rhs.value.  If so we are ready and return true.
1351// Second, if one of the operands is immediate, but the other one
1352// not, we return false.  Third, if the operand's levels differ
1353// we return false.  Fourth, if the operand's levelcoeffs differ
1354// we return false.  At last, we call the corresponding internal
1355// method to compare both operands.
1356//
1357// Both operands should have coefficients from the same base domain.
1358//
1359// Note: To compare with the zero or the unit of the current domain,
1360// you better use the methods `CanonicalForm::isZero()' or
1361// `CanonicalForm::isOne()', resp., than something like `f == 0',
1362// since the latter is quite a lot slower.
1363//
1364// See also: InternalCF::comparesame(),
1365// InternalInteger::comparesame(), InternalRational::comparesame(),
1366// InternalPrimePower::comparesame(), InternalPoly::comparesame()
1367//
1368//}}}
1369bool
1370operator == ( const CanonicalForm & lhs, const CanonicalForm & rhs )
1371{
1372    if ( lhs.value == rhs.value )
1373        return true;
1374    else if ( is_imm( rhs.value ) || is_imm( lhs.value ) ) {
1375        ASSERT( ! is_imm( rhs.value ) ||
1376                ! is_imm( lhs.value ) ||
1377                is_imm( rhs.value ) == is_imm( lhs.value ),
1378                "incompatible operands" );
1379        return false;
1380    }
1381    else  if ( lhs.value->level() != rhs.value->level() )
1382        return false;
1383    else  if ( lhs.value->levelcoeff() != rhs.value->levelcoeff() )
1384        return false;
1385    else
1386        return rhs.value->comparesame( lhs.value ) == 0;
1387}
1388
1389bool
1390operator != ( const CanonicalForm & lhs, const CanonicalForm & rhs )
1391{
1392    if ( lhs.value == rhs.value )
1393        return false;
1394    else if ( is_imm( rhs.value ) || is_imm( lhs.value ) ) {
1395        ASSERT( ! is_imm( rhs.value ) ||
1396                ! is_imm( lhs.value ) ||
1397                is_imm( rhs.value ) == is_imm( lhs.value ),
1398                "incompatible operands" );
1399        return true;
1400    }
1401    else  if ( lhs.value->level() != rhs.value->level() )
1402        return true;
1403    else  if ( lhs.value->levelcoeff() != rhs.value->levelcoeff() )
1404        return true;
1405    else        return rhs.value->comparesame( lhs.value ) != 0;
1406}
1407//}}}
1408
1409//{{{ bool operator >, operator < ( const CanonicalForm & lhs, const CanonicalForm & rhs )
1410//{{{ docu
1411//
1412// operator >(), operator <() - compare canonical forms. on size or
1413//   level.
1414//
1415// The most common and most useful application of these operators
1416// is to compare two integers or rationals, of course.  However,
1417// these operators are defined on all other base domains and on
1418// polynomials, too.  From a mathematical point of view this may
1419// seem meaningless, since there is no ordering on finite fields
1420// or on polynomials respecting the algebraic structure.
1421// Nevertheless, from a programmer's point of view it may be
1422// sensible to order these objects, e.g. to sort them.
1423//
1424// Therefore, the ordering defined by these operators in any case
1425// is a total ordering which fulfills the law of trichotomy.
1426//
1427// It is clear how this is done in the case of the integers and
1428// the rationals.  For finite fields, all you can say is that
1429// zero is the minimal element w.r.t. the ordering, the other
1430// elements are ordered in an arbitrary (but total!)  way.  For
1431// polynomials, you have an ordering derived from the
1432// lexicographical ordering of monomials.  E.g. if lm(f) < lm(g)
1433// w.r.t. lexicographic ordering, then f < g.  For more details,
1434// refer to the documentation of `InternalPoly::operator <()'.
1435//
1436// Both operands should have coefficients from the same base domain.
1437//
1438// The scheme how both operators are implemented is allmost the
1439// same as for the assignment operators (check for immediates,
1440// then check levels, then check levelcoeffs, then call the
1441// appropriate internal comparesame()/comparecoeff() method).
1442// For more information, confer to the overview for the
1443// arithmetic operators.
1444//
1445// See also: InternalCF::comparesame(),
1446// InternalInteger::comparesame(), InternalRational::comparesame(),
1447// InternalPrimePower::comparesame(), InternalPoly::comparesame(),
1448// InternalCF::comparecoeff(), InternalInteger::comparecoeff(),
1449// InternalRational::comparecoeff(),
1450// InternalPrimePower::comparecoeff(), InternalPoly::comparecoeff(),
1451// imm_cmp(), imm_cmp_p(), imm_cmp_gf()
1452//
1453//}}}
1454bool
1455operator > ( const CanonicalForm & lhs, const CanonicalForm & rhs )
1456{
1457    int what = is_imm( rhs.value );
1458    if ( is_imm( lhs.value ) ) {
1459        ASSERT( ! what || (what == is_imm( lhs.value )), "incompatible operands" );
1460        if ( what == 0 )
1461            return rhs.value->comparecoeff( lhs.value ) < 0;
1462        else if ( what == INTMARK )
1463            return imm_cmp( lhs.value, rhs.value ) > 0;
1464        else if ( what == FFMARK )
1465            return imm_cmp_p( lhs.value, rhs.value ) > 0;
1466        else
1467            return imm_cmp_gf( lhs.value, rhs.value ) > 0;
1468    }
1469    else  if ( what )
1470        return lhs.value->comparecoeff( rhs.value ) > 0;
1471    else  if ( lhs.value->level() == rhs.value->level() )
1472        if ( lhs.value->levelcoeff() == rhs.value->levelcoeff() )
1473            return lhs.value->comparesame( rhs.value ) > 0;
1474        else  if ( lhs.value->levelcoeff() > rhs.value->levelcoeff() )
1475            return lhs.value->comparecoeff( rhs.value ) > 0;
1476        else
1477            return rhs.value->comparecoeff( lhs.value ) < 0;
1478    else
1479        return lhs.value->level() > rhs.value->level();
1480}
1481
1482bool
1483operator < ( const CanonicalForm & lhs, const CanonicalForm & rhs )
1484{
1485    int what = is_imm( rhs.value );
1486    if ( is_imm( lhs.value ) ) {
1487        ASSERT( ! what || (what == is_imm( lhs.value )), "incompatible operands" );
1488        if ( what == 0 )
1489            return rhs.value->comparecoeff( lhs.value ) > 0;
1490        else if ( what == INTMARK )
1491            return imm_cmp( lhs.value, rhs.value ) < 0;
1492        else if ( what == FFMARK )
1493            return imm_cmp_p( lhs.value, rhs.value ) < 0;
1494        else
1495            return imm_cmp_gf( lhs.value, rhs.value ) < 0;
1496    }
1497    else  if ( what )
1498        return lhs.value->comparecoeff( rhs.value ) < 0;
1499    else  if ( lhs.value->level() == rhs.value->level() )
1500        if ( lhs.value->levelcoeff() == rhs.value->levelcoeff() )
1501            return lhs.value->comparesame( rhs.value ) < 0;
1502        else  if ( lhs.value->levelcoeff() > rhs.value->levelcoeff() )
1503            return lhs.value->comparecoeff( rhs.value ) < 0;
1504        else
1505            return rhs.value->comparecoeff( lhs.value ) > 0;
1506    else
1507        return lhs.value->level() < rhs.value->level();
1508}
1509//}}}
1510
1511//{{{ CanonicalForm bgcd ( const CanonicalForm & f, const CanonicalForm & g )
1512//{{{ docu
1513//
1514// bgcd() - return base coefficient gcd.
1515//
1516// If both f and g are integers and `SW_RATIONAL' is off the
1517// positive greatest common divisor of f and g is returned.
1518// Otherwise, if `SW_RATIONAL' is on or one of f and g is not an
1519// integer, the greatest common divisor is trivial: either zero
1520// if f and g equal zero or one (both from the current domain).
1521//
1522// f and g should come from one base domain which should be not
1523// the prime power domain.
1524//
1525// Implementation:
1526//
1527// CanonicalForm::bgcd() handles the immediate case with a
1528//   standard euclidean algorithm.  For the non-immediate cases
1529//   `InternalCF::bgcdsame()' or `InternalCF::bgcdcoeff()', resp. are
1530//   called following the usual level/levelcoeff approach.
1531//
1532// InternalCF::bgcdsame() and
1533// InternalCF::bgcdcoeff() throw an assertion ("not implemented")
1534//
1535// InternalInteger::bgcdsame() is a wrapper around `mpz_gcd()'
1536//   which takes some care about immediate results and the sign
1537//   of the result
1538// InternalInteger::bgcdcoeff() is a wrapper around
1539//   `mpz_gcd_ui()' which takes some care about the sign
1540//   of the result
1541//
1542// InternalRational::bgcdsame() and
1543// InternalRational::bgcdcoeff() always return one
1544//
1545//}}}
1546CanonicalForm
1547bgcd ( const CanonicalForm & f, const CanonicalForm & g )
1548{
1549    // check immediate cases
1550    int what = is_imm( g.value );
1551    if ( is_imm( f.value ) )
1552    {
1553        ASSERT( ! what || (what == is_imm( f.value )), "incompatible operands" );
1554        if ( what == 0 )
1555            return g.value->bgcdcoeff( f.value );
1556        else if ( what == INTMARK && ! cf_glob_switches.isOn( SW_RATIONAL ) )
1557        {
1558            // calculate gcd using standard integer
1559            // arithmetic
1560            int fInt = imm2int( f.value );
1561            int gInt = imm2int( g.value );
1562
1563            if ( fInt < 0 ) fInt = -fInt;
1564            if ( gInt < 0 ) gInt = -gInt;
1565            // swap fInt and gInt
1566            if ( gInt > fInt )
1567            {
1568                int swap = gInt;
1569                gInt = fInt;
1570                fInt = swap;
1571            }
1572
1573            // now, 0 <= gInt <= fInt.  Start the loop.
1574            while ( gInt )
1575            {
1576                // calculate (fInt, gInt) = (gInt, fInt%gInt)
1577                int r = fInt % gInt;
1578                fInt = gInt;
1579                gInt = r;
1580            }
1581
1582            return CanonicalForm( fInt );
1583        }
1584        else
1585            // we do not go for maximal speed for these stupid
1586            // special cases
1587            return CanonicalForm( f.isZero() && g.isZero() ? 0 : 1 );
1588    }
1589    else if ( what )
1590        return f.value->bgcdcoeff( g.value );
1591
1592    int fLevel = f.value->level();
1593    int gLevel = g.value->level();
1594
1595    // check levels
1596    if ( fLevel == gLevel )
1597    {
1598        fLevel = f.value->levelcoeff();
1599        gLevel = g.value->levelcoeff();
1600
1601        // check levelcoeffs
1602        if ( fLevel == gLevel )
1603            return f.value->bgcdsame( g.value );
1604        else if ( fLevel < gLevel )
1605            return g.value->bgcdcoeff( f.value );
1606        else
1607            return f.value->bgcdcoeff( g.value );
1608    }
1609    else if ( fLevel < gLevel )
1610        return g.value->bgcdcoeff( f.value );
1611    else
1612        return f.value->bgcdcoeff( g.value );
1613}
1614//}}}
1615
1616//{{{ CanonicalForm bextgcd ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & a, CanonicalForm & b )
1617//{{{ docu
1618//
1619// bextgcd() - return base coefficient extended gcd.
1620//
1621//}}}
1622CanonicalForm
1623bextgcd ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & a, CanonicalForm & b )
1624{
1625    // check immediate cases
1626    int what = is_imm( g.value );
1627    if ( is_imm( f.value ) ) {
1628        ASSERT( ! what || (what == is_imm( f.value )), "incompatible operands" );
1629        if ( what == 0 )
1630            return g.value->bextgcdcoeff( f.value, b, a );
1631        else if ( what == INTMARK && ! cf_glob_switches.isOn( SW_RATIONAL ) ) {
1632            // calculate extended gcd using standard integer
1633            // arithmetic
1634            int fInt = imm2int( f.value );
1635            int gInt = imm2int( g.value );
1636
1637            // to avoid any system dpendencies with `%', we work
1638            // with positive numbers only.  To a pity, we have to
1639            // redo all the checks when assigning to a and b.
1640            if ( fInt < 0 ) fInt = -fInt;
1641            if ( gInt < 0 ) gInt = -gInt;
1642            // swap fInt and gInt
1643            if ( gInt > fInt ) {
1644                int swap = gInt;
1645                gInt = fInt;
1646                fInt = swap;
1647            }
1648
1649            int u = 1; int v = 0;
1650            int uNext = 0; int vNext = 1;
1651
1652            // at any step, we have:
1653            // fInt_0 * u + gInt_0 * v = fInt
1654            // fInt_0 * uNext + gInt_0 * vNext = gInt
1655            // where fInt_0 and gInt_0 denote the values of fint
1656            // and gInt, resp., at the beginning
1657            while ( gInt ) {
1658                int r = fInt % gInt;
1659                int q = fInt / gInt;
1660                int uSwap = u - q * uNext;
1661                int vSwap = v - q * vNext;
1662
1663                // update variables
1664                fInt = gInt;
1665                gInt = r;
1666                u = uNext; v = vNext;
1667                uNext = uSwap; vNext = vSwap;
1668            }
1669
1670            // now, assign to a and b
1671            int fTest = imm2int( f.value );
1672            int gTest = imm2int( g.value );
1673            if ( gTest > fTest ) {
1674                a = v; b = u;
1675            } else {
1676                a = u; b = v;
1677            }
1678            if ( fTest < 0 ) a = -a;
1679            if ( gTest < 0 ) b = -b;
1680            return CanonicalForm( fInt );
1681        } else
1682            // stupid special cases
1683            if ( ! f.isZero() ) {
1684                a = 1/f; b = 0; return CanonicalForm( 1 );
1685            } else if ( ! g.isZero() ) {
1686                a = 0; b = 1/g; return CanonicalForm( 1 );
1687            } else {
1688                a = 0; b = 0; return CanonicalForm( 0 );
1689            }
1690    }
1691    else if ( what )
1692        return f.value->bextgcdcoeff( g.value, a, b );
1693
1694    int fLevel = f.value->level();
1695    int gLevel = g.value->level();
1696
1697    // check levels
1698    if ( fLevel == gLevel ) {
1699        fLevel = f.value->levelcoeff();
1700        gLevel = g.value->levelcoeff();
1701
1702        // check levelcoeffs
1703        if ( fLevel == gLevel )
1704            return f.value->bextgcdsame( g.value, a, b );
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    else if ( fLevel < gLevel )
1711        return g.value->bextgcdcoeff( f.value, b, a );
1712    else
1713        return f.value->bextgcdcoeff( g.value, a, b );
1714}
1715//}}}
1716
1717CanonicalForm
1718blcm ( const CanonicalForm & f, const CanonicalForm & g )
1719{
1720    if ( f.isZero() || g.isZero() )
1721        return CanonicalForm( 0 );
1722/*
1723    else if (f.isOne())
1724        return g;
1725    else if (g.isOne())
1726        return f;
1727*/
1728    else
1729        return (f / bgcd( f, g )) * g;
1730}
1731
1732//{{{ input/output
1733#ifndef NOSTREAMIO
1734void
1735CanonicalForm::print( OSTREAM & os, char * str ) const
1736{
1737    if ( is_imm( value ) )
1738        imm_print( os, value, str );
1739    else
1740        value->print( os, str );
1741}
1742
1743void
1744CanonicalForm::print( OSTREAM & os ) const
1745{
1746    if ( is_imm( value ) )
1747        imm_print( os, value, "" );
1748    else
1749        value->print( os, "" );
1750}
1751
1752OSTREAM&
1753operator << ( OSTREAM & os, const CanonicalForm & cf )
1754{
1755    cf.print( os, "" );
1756    return os;
1757}
1758
1759ISTREAM&
1760operator >> ( ISTREAM & is, CanonicalForm & cf )
1761{
1762    cf = readCF( is );
1763    return is;
1764}
1765#endif /* NOSTREAMIO */
1766//}}}
1767
1768//{{{ genCoeff(), genOne(), genZero()
1769CanonicalForm
1770CanonicalForm::genCoeff( int type, int i )
1771{
1772    return CanonicalForm( CFFactory::basic( type, i ) );
1773}
1774
1775CanonicalForm
1776CanonicalForm::genZero() const
1777{
1778    int what = is_imm( value );
1779    if ( what == FFMARK )
1780        return CanonicalForm( CFFactory::basic( FiniteFieldDomain, 0 ) );
1781    else  if ( what == GFMARK )
1782        return CanonicalForm( CFFactory::basic( GaloisFieldDomain, 0 ) );
1783    else  if ( what )
1784        return CanonicalForm( CFFactory::basic( IntegerDomain, 0 ) );
1785    else
1786        return CanonicalForm( value->genZero() );
1787}
1788
1789CanonicalForm
1790CanonicalForm::genOne() const
1791{
1792    int what = is_imm( value );
1793    if ( what == FFMARK )
1794        return CanonicalForm( CFFactory::basic( FiniteFieldDomain, 1 ) );
1795    else  if ( what == GFMARK )
1796        return CanonicalForm( CFFactory::basic( GaloisFieldDomain, 1 ) );
1797    else  if ( what )
1798        return CanonicalForm( CFFactory::basic( IntegerDomain, 1 ) );
1799    else
1800        return CanonicalForm( value->genOne() );
1801}
1802//}}}
1803
1804//{{{ exponentiation
1805CanonicalForm
1806power ( const CanonicalForm & f, int n )
1807{
1808  ASSERT( n >= 0, "illegal exponent" );
1809  if ( f.isZero() )
1810    return 0;
1811  else  if ( f.isOne() )
1812    return f;
1813  else  if ( f == -1 )
1814  {
1815    if ( n % 2 == 0 )
1816      return 1;
1817    else
1818      return -1;
1819  }
1820  else  if ( n == 0 )
1821    return 1;
1822
1823  //else if (f.inGF())
1824  //{
1825  //}
1826  else
1827  {
1828    CanonicalForm g,h;
1829    h=f;
1830    while(n%2==0)
1831    {
1832      h*=h;
1833      n/=2;
1834    }
1835    g=h;
1836    while(1)
1837    {
1838      n/=2;
1839      if(n==0)
1840        return g;
1841      h*=h;
1842      if(n%2!=0) g*=h;
1843    }
1844  }
1845}
1846
1847CanonicalForm
1848power ( const Variable & v, int n )
1849{
1850    ASSERT( n >= 0, "illegal exponent" );
1851    if ( n == 0 )
1852        return 1;
1853    else  if ( n == 1 )
1854        return v;
1855    else  if (( v.level() < 0 ) && (hasMipo(v)))
1856    {
1857        CanonicalForm result( v, n-1 );
1858        return result * v;
1859    }
1860    else
1861        return CanonicalForm( v, n );
1862}
1863//}}}
1864
1865//{{{ switches
1866void
1867On( int sw )
1868{
1869    cf_glob_switches.On( sw );
1870}
1871
1872void
1873Off( int sw )
1874{
1875    cf_glob_switches.Off( sw );
1876}
1877
1878bool
1879isOn( int sw )
1880{
1881    return cf_glob_switches.isOn( sw );
1882}
1883//}}}
Note: See TracBrowser for help on using the repository browser.