source: git/factory/canonicalform.cc @ 4a7a45

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