source: git/factory/canonicalform.cc @ 40094f

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