source: git/factory/canonicalform.cc @ ac7e53

fieker-DuValspielwiese
Last change on this file since ac7e53 was c5323e, checked in by Jens Schmidt <schmidt@…>, 27 years ago
stream-io wrapped by NOSTREAMIO git-svn-id: file:///usr/local/Singular/svn/trunk@81 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 31.4 KB
Line 
1// emacs editmode for this file is -*- C++ -*-
2// $Id: canonicalform.cc,v 1.3 1997-03-26 16:27:09 schmidt Exp $
3
4/*
5$Log: not supported by cvs2svn $
6Revision 1.2  1996/07/02 11:18:32  stobbe
7"initCanonicalForm: now initializes the switch system.
8"
9
10Revision 1.1  1996/06/13 07:15:50  stobbe
11"CanonicalForm::deriv(x): bug fix, result is now swapped back if x is not
12                         the main variable of *this
13"
14
15Revision 1.0  1996/05/17 10:59:42  stobbe
16Initial revision
17
18*/
19
20#include "assert.h"
21
22#include "cf_defs.h"
23
24#include "cf_globals.h"
25#include "canonicalform.h"
26#include "cf_iter.h"
27#include "int_cf.h"
28#include "cf_factory.h"
29#include "imm.h"
30#include "gfops.h"
31#include "cf_binom.h"
32#if defined (USE_MEMUTIL) && ! defined (USE_OLD_MEMMAN)
33#include "memman.h"
34#endif
35
36#ifndef NOSTREAMIO
37CanonicalForm readCF( istream& );
38#endif /* NOSTREAMIO */
39
40CanonicalForm::CanonicalForm() : value( CFFactory::basic( (int)0 ) )
41{
42}
43
44CanonicalForm::CanonicalForm( const int i ) : value( CFFactory::basic( i ) )
45{
46}
47
48CanonicalForm::CanonicalForm( const CanonicalForm & cf ) : value( is_imm( cf.value ) ? cf.value : cf.value->copyObject() )
49{
50}
51
52CanonicalForm::CanonicalForm( InternalCF * cf ) : value( cf )
53{
54}
55
56CanonicalForm::CanonicalForm( const Variable & v ) : value( CFFactory::poly( v ) )
57{
58}
59
60CanonicalForm::CanonicalForm( const Variable & v, int e ) : value( CFFactory::poly( v, e ) )
61{
62}
63
64CanonicalForm::CanonicalForm( const char * str ) : value( CFFactory::basic( str ) )
65{
66}
67
68CanonicalForm::~CanonicalForm()
69{
70    if ( (! is_imm( value )) && value->deleteObject() )
71        delete value;
72}
73
74InternalCF*
75CanonicalForm::getval() const
76{
77    if ( is_imm( value ) )
78        return value;
79    else
80        return value->copyObject();
81}
82
83bool
84CanonicalForm::isOne() const
85{
86    if ( is_imm( value ) == FFMARK )
87        return imm_isone_p( value );
88    else  if ( is_imm( value ) == GFMARK )
89        return imm_isone_gf( value );
90    else  if ( is_imm( value ) )
91        return imm_isone( value );
92    else
93        return value->isOne();
94}
95
96bool
97CanonicalForm::isZero() const
98{
99    if ( is_imm( value ) == FFMARK )
100        return imm_iszero_p( value );
101    else  if ( is_imm( value ) == GFMARK )
102        return imm_iszero_gf( value );
103    else  if ( is_imm( value ) )
104        return imm_iszero( value );
105    else
106        return value->isZero();
107}
108
109bool
110CanonicalForm::isImm() const
111{
112    return is_imm( value );
113}
114
115bool
116CanonicalForm::inZ() const
117{
118    if ( is_imm( value ) == INTMARK )
119        return true;
120    else if ( is_imm( value ) )
121        return false;
122    else
123        return value->levelcoeff() == IntegerDomain;
124}
125
126bool
127CanonicalForm::inQ() const
128{
129    if ( is_imm( value ) == INTMARK )
130        return true;
131    else if ( is_imm( value ) )
132        return false;
133    else
134        return value->levelcoeff() == IntegerDomain ||
135            value->levelcoeff() == RationalDomain;
136}
137
138bool
139CanonicalForm::inFF() const
140{
141    return is_imm( value ) == FFMARK;
142}
143
144bool
145CanonicalForm::inGF() const
146{
147    return is_imm( value ) == GFMARK;
148}
149
150bool
151CanonicalForm::inPP() const
152{
153    return ! is_imm( value ) && ( value->levelcoeff() == PrimePowerDomain );
154}
155
156bool
157CanonicalForm::inBaseDomain() const
158{
159    if ( is_imm( value ) )
160        return true;
161    else
162        return value->inBaseDomain();
163}
164
165bool
166CanonicalForm::inExtension() const
167{
168    if ( is_imm( value ) )
169        return false;
170    else
171        return value->inExtension();
172}
173
174bool
175CanonicalForm::inCoeffDomain() const
176{
177    if ( is_imm( value ) )
178        return true;
179    else
180        return value->inCoeffDomain();
181}
182
183bool
184CanonicalForm::inPolyDomain() const
185{
186    if ( is_imm( value ) )
187        return false;
188    else
189        return value->inPolyDomain();
190}
191
192bool
193CanonicalForm::inQuotDomain() const
194{
195    if ( is_imm( value ) )
196        return false;
197    else
198        return value->inQuotDomain();
199}
200
201int
202CanonicalForm::intval() const
203{
204    if ( is_imm( value ) )
205        return imm_intval( value );
206    else
207        return value->intval();
208}
209
210CanonicalForm
211CanonicalForm::lc() const
212{
213    if ( is_imm( value ) )
214        return *this;
215    else
216        return value->lc();
217}
218
219CanonicalForm
220CanonicalForm::LC() const
221{
222    if ( inBaseDomain() )
223        return *this;
224    else
225        return value->LC();
226}
227
228CanonicalForm
229CanonicalForm::LC( const Variable & v ) const
230{
231    if ( inBaseDomain() )
232        return *this;
233    else  if ( v == mvar() )
234        return value->LC();
235    else {
236        CanonicalForm f = swapvar( *this, v, mvar() );
237        if ( f.mvar() == mvar() )
238            return swapvar( f.value->LC(), v, mvar() );
239        else
240            return *this;
241    }
242}
243
244int
245CanonicalForm::degree() const
246{
247    if ( isZero() )
248        return -1;
249    else  if ( is_imm( value ) )
250        return 0;
251    else
252        return value->degree();
253}
254
255int
256CanonicalForm::degree( const Variable & v ) const
257{
258    if ( isZero() )
259        return -1;
260    else  if ( is_imm( value ) )
261        return 0;
262    else  if ( inBaseDomain() )
263        return 0;
264    else  if ( v == mvar() )
265        return value->degree();
266    else  if ( v > mvar() )
267        return 0;
268    else {
269        CanonicalForm f = swapvar( *this, v, mvar() );
270        if ( f.mvar() == mvar() )
271            return f.value->degree();
272        else
273            return 0;
274    }
275}
276
277int
278CanonicalForm::taildegree() const
279{
280    if ( isZero() )
281        return -1;
282    else  if ( is_imm( value ) )
283        return 0;
284    else
285        return value->taildegree();
286}
287
288CanonicalForm
289CanonicalForm::tailcoeff() const
290{
291    if ( inCoeffDomain() )
292        return *this;
293    else
294        return value->tailcoeff();
295}
296
297int
298CanonicalForm::level() const
299{
300    if ( is_imm( value ) )
301        return LEVELBASE;
302    else
303        return value->level();
304}
305
306Variable
307CanonicalForm::mvar() const
308{
309    if ( is_imm( value ) || value->inBaseDomain() )
310        return Variable();
311    else
312        return value->variable();
313}
314
315CanonicalForm
316CanonicalForm::num() const
317{
318    if ( is_imm( value ) )
319        return *this;
320    else
321        return CanonicalForm( value->num() );
322}
323
324CanonicalForm
325CanonicalForm::den() const
326{
327    if ( is_imm( value ) )
328        return 1;
329    else
330        return CanonicalForm( value->den() );
331}
332
333CanonicalForm
334CanonicalForm::deepCopy() const
335{
336    if ( is_imm( value ) )
337        return *this;
338    else
339        return CanonicalForm( value->deepCopyObject() );
340}
341
342CanonicalForm
343CanonicalForm::gcd( const CanonicalForm & ) const
344{
345//    return ::gcd( *this, f );
346    return 1;
347}
348
349CanonicalForm
350CanonicalForm::deriv() const
351{
352    if ( inCoeffDomain() )
353        return 0;
354    else {
355        CanonicalForm res = 0;
356        Variable x = mvar();
357        for ( CFIterator i = *this; i.hasTerms(); i++ )
358            if ( i.exp() > 0 )
359                res += power( x, i.exp()-1 ) * i.coeff() * i.exp();
360        return res;
361    }
362}
363
364CanonicalForm
365CanonicalForm::deriv( const Variable & x ) const
366{
367    if ( inCoeffDomain() )
368        return 0;
369    else {
370        CanonicalForm res = 0;
371        Variable y = mvar();
372        for ( CFIterator i = (y==x) ? *this : swapvar( *this, x, y ); i.hasTerms(); i++ )
373            if ( i.exp() > 0 )
374                res += power( y, i.exp()-1 ) * i.coeff() * i.exp();
375        return (y==x) ? res : swapvar( res, x, y );
376    }
377}
378
379CanonicalForm
380CanonicalForm::genCoeff( int type, int i )
381{
382    return CanonicalForm( CFFactory::basic( type, i ) );
383}
384
385CanonicalForm
386CanonicalForm::genZero() const
387{
388    int what = is_imm( value );
389    if ( what == FFMARK )
390        return CanonicalForm( CFFactory::basic( FiniteFieldDomain, 0 ) );
391    else  if ( what == GFMARK )
392        return CanonicalForm( CFFactory::basic( GaloisFieldDomain, 0 ) );
393    else  if ( what )
394        return CanonicalForm( CFFactory::basic( IntegerDomain, 0 ) );
395    else
396        return CanonicalForm( value->genZero() );
397}
398
399CanonicalForm
400CanonicalForm::genOne() const
401{
402    int what = is_imm( value );
403    if ( what == FFMARK )
404        return CanonicalForm( CFFactory::basic( FiniteFieldDomain, 1 ) );
405    else  if ( what == GFMARK )
406        return CanonicalForm( CFFactory::basic( GaloisFieldDomain, 1 ) );
407    else  if ( what )
408        return CanonicalForm( CFFactory::basic( IntegerDomain, 1 ) );
409    else
410        return CanonicalForm( value->genOne() );
411}
412
413bool
414CanonicalForm::isUnivariate() const
415{
416    if ( is_imm( value ) )
417        return false;
418    else
419        return value->isUnivariate();
420}
421
422#ifndef NOSTREAMIO
423void
424CanonicalForm::print( ostream & os, char * str ) const
425{
426    if ( is_imm( value ) )
427        imm_print( os, value, str );
428    else
429        value->print( os, str );
430}
431#endif /* NOSTREAMIO */
432
433bool
434operator == ( const CanonicalForm & lhs, const CanonicalForm & rhs )
435{
436    int what = is_imm( lhs.value );
437    if ( what )
438        if ( what == is_imm( rhs.value ) )
439            return lhs.value == rhs.value;
440        else
441            return false;
442    else  if ( is_imm( rhs.value ) )
443        return false;
444    else  if ( lhs.level() == rhs.level() )
445        if ( lhs.value->levelcoeff() >= rhs.value->levelcoeff() )
446            return lhs.value->comparesame( rhs.value ) == 0;
447        else
448            return rhs.value->comparesame( lhs.value ) == 0;
449    else
450        return false;
451}
452
453bool
454operator != ( const CanonicalForm & lhs, const CanonicalForm & rhs )
455{
456    int what = is_imm( lhs.value );
457    if ( what )
458        if ( what == is_imm( rhs.value ) )
459            return lhs.value != rhs.value;
460        else
461            return true;
462    else  if ( is_imm( rhs.value ) )
463        return true;
464    else  if ( lhs.level() == rhs.level() )
465        if ( lhs.value->levelcoeff() >= rhs.value->levelcoeff() )
466            return lhs.value->comparesame( rhs.value ) != 0;
467        else
468            return rhs.value->comparesame( lhs.value ) != 0;
469    else
470        return true;
471}
472
473bool
474operator > ( const CanonicalForm & lhs, const CanonicalForm & rhs )
475{
476    int what = is_imm( lhs.value );
477    if ( what ) {
478        ASSERT ( ! is_imm( rhs.value ) || (what==is_imm( rhs.value )), "illegal base coefficients" );
479        if ( what == INTMARK ) {
480            if ( what == is_imm( rhs.value ) )
481                return imm_cmp( lhs.value, rhs.value ) > 0;
482            else
483                return rhs.value->comparecoeff( lhs.value ) < 0;
484        }
485        else  if ( what == FFMARK ) {
486            if ( what == is_imm( rhs.value ) )
487                return imm_cmp_p( lhs.value, rhs.value ) > 0;
488            else
489                return rhs.value->comparecoeff( lhs.value ) < 0;
490        }
491        else {
492            if ( what == is_imm( rhs.value ) )
493                return imm_cmp_gf( lhs.value, rhs.value ) > 0;
494            else
495                return rhs.value->comparecoeff( lhs.value ) < 0;
496        }
497    }
498    else  if ( is_imm( rhs.value ) )
499        return lhs.value->comparecoeff( rhs.value ) > 0;
500    else  if ( lhs.level() == rhs.level() )
501        if ( lhs.value->levelcoeff() == rhs.value->levelcoeff() )
502            return lhs.value->comparesame( rhs.value ) > 0;
503        else  if ( lhs.value->levelcoeff() > rhs.value->levelcoeff() )
504            return lhs.value->comparecoeff( lhs.value ) > 0;
505        else
506            return rhs.value->comparecoeff( lhs.value ) < 0;
507    else
508        return lhs.value->level() > rhs.value->level();
509}
510
511bool
512operator < ( const CanonicalForm & lhs, const CanonicalForm & rhs )
513{
514    int what = is_imm( lhs.value );
515    if ( what ) {
516        ASSERT ( ! is_imm( rhs.value ) || (what==is_imm( rhs.value )), "illegal base coefficients" );
517        if ( what == INTMARK ) {
518            if ( what == is_imm( rhs.value ) )
519                return imm_cmp( lhs.value, rhs.value ) < 0;
520            else
521                return rhs.value->comparecoeff( lhs.value ) > 0;
522        }
523        else  if ( what == FFMARK ) {
524            if ( what == is_imm( rhs.value ) )
525                return imm_cmp( lhs.value, rhs.value ) < 0;
526            else
527                return rhs.value->comparecoeff( lhs.value ) > 0;
528        }
529        else {
530            if ( what == is_imm( rhs.value ) )
531                return imm_cmp( lhs.value, rhs.value ) < 0;
532            else
533                return rhs.value->comparecoeff( lhs.value ) > 0;
534        }
535    }
536    else  if ( is_imm( rhs.value ) )
537        return lhs.value->comparecoeff( rhs.value ) < 0;
538    else  if ( lhs.level() == rhs.level() )
539        if ( lhs.value->levelcoeff() == rhs.value->levelcoeff() )
540            return lhs.value->comparesame( rhs.value ) < 0;
541        else  if ( lhs.value->levelcoeff() > rhs.value->levelcoeff() )
542            return lhs.value->comparecoeff( lhs.value ) < 0;
543        else
544            return rhs.value->comparecoeff( lhs.value ) > 0;
545    else
546        return lhs.value->level() < rhs.value->level();
547}
548
549CanonicalForm&
550CanonicalForm::operator = ( const CanonicalForm & cf )
551{
552    if ( this != &cf ) {
553        if ( (! is_imm( value )) && value->deleteObject() )
554            delete value;
555        value = (is_imm( cf.value )) ? cf.value : cf.value->copyObject();
556    }
557    return *this;
558}
559
560CanonicalForm&
561CanonicalForm::operator = ( const int cf )
562{
563    if ( (! is_imm( value )) && value->deleteObject() )
564        delete value;
565    value = CFFactory::basic( cf );
566    return *this;
567}
568
569CanonicalForm&
570CanonicalForm::operator += ( const CanonicalForm & cf )
571{
572    int what = is_imm( value );
573    if ( what ) {
574        ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" );
575        if ( (what = is_imm( cf.value )) == FFMARK )
576            value = imm_add_p( value, cf.value );
577        else  if ( what == GFMARK )
578            value = imm_add_gf( value, cf.value );
579        else  if ( what )
580            value = imm_add( value, cf.value );
581        else {
582            InternalCF * dummy = cf.value->copyObject();
583            value = dummy->addcoeff( value );
584        }
585    }
586    else  if ( is_imm( cf.value ) )
587        value = value->addcoeff( cf.value );
588    else  if ( value->level() == cf.value->level() ) {
589        if ( value->levelcoeff() == cf.value->levelcoeff() )
590            value = value->addsame( cf.value );
591        else  if ( value->levelcoeff() > cf.value->levelcoeff() )
592            value = value->addcoeff( cf.value );
593        else {
594            InternalCF * dummy = cf.value->copyObject();
595            dummy = dummy->addcoeff( value );
596            if ( value->deleteObject() ) delete value;
597            value = dummy;
598        }
599    }
600    else  if ( level() > cf.level() )
601        value = value->addcoeff( cf.value );
602    else {
603        InternalCF * dummy = cf.value->copyObject();
604        dummy = dummy->addcoeff( value );
605        if ( value->deleteObject() ) delete value;
606        value = dummy;
607    }
608    return *this;
609}
610
611CanonicalForm&
612CanonicalForm::operator -= ( const CanonicalForm & cf )
613{
614    int what = is_imm( value );
615    if ( what ) {
616        ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" );
617        if ( (what = is_imm( cf.value )) == FFMARK )
618            value = imm_sub_p( value, cf.value );
619        else  if ( what == GFMARK )
620            value = imm_sub_gf( value, cf.value );
621        else  if ( what )
622            value = imm_sub( value, cf.value );
623        else {
624            InternalCF * dummy = cf.value->copyObject();
625            value = dummy->subcoeff( value, true );
626        }
627    }
628    else  if ( is_imm( cf.value ) )
629        value = value->subcoeff( cf.value, false );
630    else  if ( value->level() == cf.value->level() ) {
631        if ( value->levelcoeff() == cf.value->levelcoeff() )
632            value = value->subsame( cf.value );
633        else  if ( value->levelcoeff() > cf.value->levelcoeff() )
634            value = value->subcoeff( cf.value, false );
635        else {
636            InternalCF * dummy = cf.value->copyObject();
637            dummy = dummy->subcoeff( value, true );
638            if ( value->deleteObject() ) delete value;
639            value = dummy;
640        }
641    }
642    else  if ( level() > cf.level() )
643        value = value->subcoeff( cf.value, false );
644    else {
645        InternalCF * dummy = cf.value->copyObject();
646        dummy = dummy->subcoeff( value, true );
647        if ( value->deleteObject() ) delete value;
648        value = dummy;
649    }
650    return *this;
651}
652
653CanonicalForm&
654CanonicalForm::operator *= ( const CanonicalForm & cf )
655{
656    int what = is_imm( value );
657    if ( what ) {
658        ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" );
659        if ( (what = is_imm( cf.value )) == FFMARK )
660            value = imm_mul_p( value, cf.value );
661        else  if ( what == GFMARK )
662            value = imm_mul_gf( value, cf.value );
663        else  if ( what )
664            value = imm_mul( value, cf.value );
665        else {
666            InternalCF * dummy = cf.value->copyObject();
667            value = dummy->mulcoeff( value );
668        }
669    }
670    else  if ( is_imm( cf.value ) )
671        value = value->mulcoeff( cf.value );
672    else  if ( value->level() == cf.value->level() ) {
673        if ( value->levelcoeff() == cf.value->levelcoeff() )
674            value = value->mulsame( cf.value );
675        else  if ( value->levelcoeff() > cf.value->levelcoeff() )
676            value = value->mulcoeff( cf.value );
677        else {
678            InternalCF * dummy = cf.value->copyObject();
679            dummy = dummy->mulcoeff( value );
680            if ( value->deleteObject() ) delete value;
681            value = dummy;
682        }
683    }
684    else  if ( level() > cf.level() )
685        value = value->mulcoeff( cf.value );
686    else {
687        InternalCF * dummy = cf.value->copyObject();
688        dummy = dummy->mulcoeff( value );
689        if ( value->deleteObject() ) delete value;
690        value = dummy;
691    }
692    return *this;
693}
694
695CanonicalForm&
696CanonicalForm::operator /= ( const CanonicalForm & cf )
697{
698    int what = is_imm( value );
699    if ( what ) {
700        ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" );
701        if ( (what = is_imm( cf.value )) == FFMARK )
702            value = imm_div_p( value, cf.value );
703        else  if ( what == GFMARK )
704            value = imm_div_gf( value, cf.value );
705        else  if ( what )
706            value = imm_divrat( value, cf.value );
707        else {
708            InternalCF * dummy = cf.value->copyObject();
709            value = dummy->dividecoeff( value, true );
710        }
711    }
712    else  if ( is_imm( cf.value ) )
713        value = value->dividecoeff( cf.value, false );
714    else  if ( value->level() == cf.value->level() ) {
715        if ( value->levelcoeff() == cf.value->levelcoeff() )
716            value = value->dividesame( cf.value );
717        else  if ( value->levelcoeff() > cf.value->levelcoeff() )
718            value = value->dividecoeff( cf.value, false );
719        else {
720            InternalCF * dummy = cf.value->copyObject();
721            dummy = dummy->dividecoeff( value, true );
722            if ( value->deleteObject() ) delete value;
723            value = dummy;
724        }
725    }
726    else  if ( level() > cf.level() )
727        value = value->dividecoeff( cf.value, false );
728    else {
729        InternalCF * dummy = cf.value->copyObject();
730        dummy = dummy->dividecoeff( value, true );
731        if ( value->deleteObject() ) delete value;
732        value = dummy;
733    }
734    return *this;
735}
736
737CanonicalForm&
738CanonicalForm::div ( const CanonicalForm & cf )
739{
740    int what = is_imm( value );
741    if ( what ) {
742        ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" );
743        if ( (what = is_imm( cf.value )) == FFMARK )
744            value = imm_div_p( value, cf.value );
745        else  if ( what == GFMARK )
746            value = imm_div_gf( value, cf.value );
747        else  if ( what )
748            value = imm_div( value, cf.value );
749        else {
750            InternalCF * dummy = cf.value->copyObject();
751            value = dummy->divcoeff( value, true );
752        }
753    }
754    else  if ( is_imm( cf.value ) )
755        value = value->divcoeff( cf.value, false );
756    else  if ( value->level() == cf.value->level() ) {
757        if ( value->levelcoeff() == cf.value->levelcoeff() )
758            value = value->divsame( cf.value );
759        else  if ( value->levelcoeff() > cf.value->levelcoeff() )
760            value = value->divcoeff( cf.value, false );
761        else {
762            InternalCF * dummy = cf.value->copyObject();
763            dummy = dummy->divcoeff( value, true );
764            if ( value->deleteObject() ) delete value;
765            value = dummy;
766        }
767    }
768    else  if ( level() > cf.level() )
769        value = value->divcoeff( cf.value, false );
770    else {
771        InternalCF * dummy = cf.value->copyObject();
772        dummy = dummy->divcoeff( value, true );
773        if ( value->deleteObject() ) delete value;
774        value = dummy;
775    }
776    return *this;
777}
778
779CanonicalForm&
780CanonicalForm::operator %= ( const CanonicalForm& cf )
781{
782    int what = is_imm( value );
783    if ( what ) {
784        ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" );
785        if ( (what = is_imm( cf.value )) == FFMARK )
786            value = imm_mod_p( value, cf.value );
787        else  if ( what == GFMARK )
788            value = imm_mod_gf( value, cf.value );
789        else  if ( what )
790            value = imm_mod( value, cf.value );
791        else {
792            InternalCF * dummy = cf.value->copyObject();
793            value = dummy->modulocoeff( value, true );
794        }
795    }
796    else  if ( is_imm( cf.value ) )
797        value = value->modulocoeff( cf.value, false );
798    else  if ( value->level() == cf.value->level() ) {
799        if ( value->levelcoeff() == cf.value->levelcoeff() )
800            value = value->modulosame( cf.value );
801        else  if ( value->levelcoeff() > cf.value->levelcoeff() )
802            value = value->modulocoeff( cf.value, false );
803        else {
804            InternalCF * dummy = cf.value->copyObject();
805            dummy = dummy->modulocoeff( value, true );
806            if ( value->deleteObject() ) delete value;
807            value = dummy;
808        }
809    }
810    else  if ( level() > cf.level() )
811        value = value->modulocoeff( cf.value, false );
812    else {
813        InternalCF * dummy = cf.value->copyObject();
814        dummy = dummy->modulocoeff( value, true );
815        if ( value->deleteObject() ) delete value;
816        value = dummy;
817    }
818    return *this;
819}
820
821CanonicalForm&
822CanonicalForm::mod( const CanonicalForm & cf )
823{
824    int what = is_imm( value );
825    if ( what ) {
826        ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" );
827        if ( (what = is_imm( cf.value )) == FFMARK )
828            value = imm_mod_p( value, cf.value );
829        else  if ( what == GFMARK )
830            value = imm_mod_gf( value, cf.value );
831        else  if ( what )
832            value = imm_mod( value, cf.value );
833        else {
834            InternalCF * dummy = cf.value->copyObject();
835            value = dummy->modcoeff( value, true );
836        }
837    }
838    else  if ( is_imm( cf.value ) )
839        value = value->modcoeff( cf.value, false );
840    else  if ( value->level() == cf.value->level() ) {
841        if ( value->levelcoeff() == cf.value->levelcoeff() )
842            value = value->modsame( cf.value );
843        else  if ( value->levelcoeff() > cf.value->levelcoeff() )
844            value = value->modcoeff( cf.value, false );
845        else {
846            InternalCF * dummy = cf.value->copyObject();
847            dummy = dummy->modcoeff( value, true );
848            if ( value->deleteObject() ) delete value;
849            value = dummy;
850        }
851    }
852    else  if ( level() > cf.level() )
853        value = value->modcoeff( cf.value, false );
854    else {
855        InternalCF * dummy = cf.value->copyObject();
856        dummy = dummy->modcoeff( value, true );
857        if ( value->deleteObject() ) delete value;
858        value = dummy;
859    }
860    return *this;
861}
862
863CanonicalForm
864operator - ( const CanonicalForm & cf )
865{
866    CanonicalForm result( cf );
867    int what = is_imm( result.value );
868    if ( what == FFMARK )
869        result.value = imm_neg_p( result.value );
870    else  if ( what == GFMARK )
871        result.value = imm_neg_gf( result.value );
872    else  if ( what )
873        result.value = imm_neg( result.value );
874    else
875        result.value = result.value->neg();
876    return result;
877}
878
879CanonicalForm
880operator + ( const CanonicalForm &c1, const CanonicalForm &c2 )
881{
882    CanonicalForm result( c1 );
883    result += c2;
884    return result;
885}
886
887CanonicalForm
888operator - ( const CanonicalForm &c1, const CanonicalForm &c2 )
889{
890    CanonicalForm result( c1 );
891    result -= c2;
892    return result;
893}
894
895CanonicalForm
896operator * ( const CanonicalForm &c1, const CanonicalForm &c2 )
897{
898    CanonicalForm result( c1 );
899    result *= c2;
900    return result;
901}
902
903CanonicalForm
904operator / ( const CanonicalForm &c1, const CanonicalForm &c2 )
905{
906    CanonicalForm result( c1 );
907    result /= c2;
908    return result;
909}
910
911CanonicalForm
912div ( const CanonicalForm &c1, const CanonicalForm &c2 )
913{
914    CanonicalForm result( c1 );
915    result.div( c2 );
916    return result;
917}
918
919CanonicalForm
920mod ( const CanonicalForm &c1, const CanonicalForm &c2 )
921{
922    CanonicalForm result( c1 );
923    result.mod( c2 );
924    return result;
925}
926
927CanonicalForm
928operator % ( const CanonicalForm &c1, const CanonicalForm &c2 )
929{
930    CanonicalForm result( c1 );
931    result %= c2;
932    return result;
933}
934
935void
936divrem ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & q, CanonicalForm & r )
937{
938    InternalCF * qq = 0, * rr = 0;
939    int what = is_imm( f.value );
940    if ( what )
941        if ( is_imm( g.value ) ) {
942            if ( what == FFMARK )
943                imm_divrem_p( f.value, g.value, qq, rr );
944            else  if ( what == GFMARK )
945                imm_divrem_gf( f.value, g.value, qq, rr );
946            else
947                imm_divrem( f.value, g.value, qq, rr );
948        }
949        else
950            g.value->divremcoeff( f.value, qq, rr, true );
951    else  if ( (what=is_imm( g.value )) )
952        f.value->divremcoeff( g.value, qq, rr, false );
953    else  if ( f.value->level() == g.value->level() )
954        if ( f.value->levelcoeff() == g.value->levelcoeff() )
955            f.value->divremsame( g.value, qq, rr );
956        else  if ( f.value->levelcoeff() > g.value->levelcoeff() )
957            f.value->divremcoeff( g.value, qq, rr, false );
958        else
959            g.value->divremcoeff( f.value, qq, rr, true );
960    else  if ( f.value->level() > g.value->level() )
961        f.value->divremcoeff( g.value, qq, rr, false );
962    else
963        g.value->divremcoeff( f.value, qq, rr, true );
964    ASSERT( qq != 0 && rr != 0, "error in divrem" );
965    q = CanonicalForm( qq );
966    r = CanonicalForm( rr );
967}
968
969bool
970divremt ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & q, CanonicalForm & r )
971{
972    InternalCF * qq = 0, * rr = 0;
973    int what = is_imm( f.value );
974    bool result = true;
975    if ( what )
976        if ( is_imm( g.value ) ) {
977            if ( what == FFMARK )
978                imm_divrem_p( f.value, g.value, qq, rr );
979            else  if ( what == GFMARK )
980                imm_divrem_gf( f.value, g.value, qq, rr );
981            else
982                imm_divrem( f.value, g.value, qq, rr );
983        }
984        else
985            result = g.value->divremcoefft( f.value, qq, rr, true );
986    else  if ( (what=is_imm( g.value )) )
987        result = f.value->divremcoefft( g.value, qq, rr, false );
988    else  if ( f.value->level() == g.value->level() )
989        if ( f.value->levelcoeff() == g.value->levelcoeff() )
990            result = f.value->divremsamet( g.value, qq, rr );
991        else  if ( f.value->levelcoeff() > g.value->levelcoeff() )
992            result = f.value->divremcoefft( g.value, qq, rr, false );
993        else
994            result = g.value->divremcoefft( f.value, qq, rr, true );
995    else  if ( f.value->level() > g.value->level() )
996        result = f.value->divremcoefft( g.value, qq, rr, false );
997    else
998        result = g.value->divremcoefft( f.value, qq, rr, true );
999    if ( result ) {
1000        ASSERT( qq != 0 && rr != 0, "error in divrem" );
1001        q = CanonicalForm( qq );
1002        r = CanonicalForm( rr );
1003    }
1004    else {
1005        q = 0; r = 0;
1006    }
1007    return result;
1008}
1009
1010#ifndef NOSTREAMIO
1011ostream&
1012operator << ( ostream & os, const CanonicalForm & cf )
1013{
1014    cf.print( os, "" );
1015    return os;
1016}
1017#endif /* NOSTREAMIO */
1018
1019#ifndef NOSTREAMIO
1020istream&
1021operator >> ( istream & is, CanonicalForm & cf )
1022{
1023    cf = readCF( is );
1024    return is;
1025}
1026#endif /* NOSTREAMIO */
1027
1028CanonicalForm
1029CanonicalForm::operator () ( const CanonicalForm & f ) const
1030{
1031    if ( inBaseDomain() )
1032        return *this;
1033    else {
1034        CanonicalForm result = 0;
1035        for ( CFIterator i = *this; i.hasTerms(); i++ )
1036            if ( i.exp() == 0 )
1037                result += i.coeff();
1038            else
1039                result += power( f, i.exp() ) * i.coeff();
1040        return result;
1041    }
1042}
1043
1044CanonicalForm
1045CanonicalForm::operator () ( const CanonicalForm & f, const Variable & v ) const
1046{
1047    if ( inBaseDomain() || v > mvar() )
1048        return *this;
1049    else  if ( v == mvar() ) {
1050        CanonicalForm result = 0;
1051        for ( CFIterator i = *this; i.hasTerms(); i++ )
1052            if ( i.exp() == 0 )
1053                result += i.coeff();
1054            else
1055                result += power( f, i.exp() ) * i.coeff();
1056        return result;
1057    }
1058    else {
1059        CanonicalForm G = swapvar( *this, v, Variable::highest() );
1060        if ( G.mvar() != Variable::highest() )
1061            return *this;
1062        CanonicalForm result = 0;
1063        for ( CFIterator i = G; i.hasTerms(); ++i )
1064            if ( i.exp() == 0 )
1065                result += i.coeff();
1066            else
1067                result += power( f, i.exp() ) * i.coeff();
1068        return result;
1069    }
1070}
1071
1072CanonicalForm
1073CanonicalForm::operator[] ( int i ) const
1074{
1075    return value->coeff( i );
1076}
1077
1078int
1079CanonicalForm::sign() const
1080{
1081    if ( is_imm( value ) )
1082        return imm_sign( value );
1083    else
1084        return value->sign();
1085}
1086
1087CanonicalForm
1088power ( const CanonicalForm & f, int n )
1089{
1090    ASSERT( n >= 0, "illegal exponent" );
1091    if ( f == 0 )
1092        return 0;
1093    else  if ( f == 1 )
1094        return f;
1095    else  if ( f == -1 ) {
1096        if ( n % 2 == 0 )
1097            return 1;
1098        else
1099            return -1;
1100    }
1101    else  if ( n == 0 )
1102        return 1;
1103    else {
1104        CanonicalForm result = f;
1105        for ( int i = 1; i < n; i++ )
1106            result *= f;
1107        return result;
1108    }
1109}
1110
1111CanonicalForm
1112power ( const Variable & v, int n )
1113{
1114    ASSERT( n >= 0, "illegal exponent" );
1115    if ( n == 0 )
1116        return 1;
1117    else  if ( n == 1 )
1118        return v;
1119    else  if ( v.level() < 0 ) {
1120        CanonicalForm result( v, n-1 );
1121        return result * v;
1122    }
1123    else
1124        return CanonicalForm( v, n );
1125}
1126
1127
1128int initializeGMP();
1129int initializeCharacteristic();
1130
1131int
1132initCanonicalForm( void )
1133{
1134    static bool initialized = false;
1135    if ( ! initialized ) {
1136#if defined (USE_MEMUTIL) && ! defined (USE_OLD_MEMMAN)
1137        (void)mmInit();
1138#endif
1139
1140        Off( SW_RATIONAL );
1141        Off( SW_QUOTIENT );
1142        Off( SW_SYMMETRIC_FF );
1143        Off( SW_BERLEKAMP );
1144        Off( SW_FAC_USE_BIG_PRIMES );
1145        Off( SW_FAC_QUADRATICLIFT );
1146        Off( SW_USE_EZGCD );
1147
1148        (void)initializeCharacteristic();
1149        (void)initializeGMP();
1150        initPT();
1151        initialized = true;
1152    }
1153    return 1;
1154}
1155
1156
1157CanonicalForm
1158CanonicalForm::mapinto () const
1159{
1160    ASSERT( is_imm( value ) ||  ! value->inExtension(), "cannot map into different Extension" );
1161    if ( is_imm( value ) )
1162        if ( getCharacteristic() == 0 )
1163            if ( is_imm( value ) == FFMARK )
1164                return CanonicalForm( int2imm( ff_symmetric( imm2int( value ) ) ) );
1165            else  if ( is_imm( value ) == GFMARK )
1166                return CanonicalForm( int2imm( ff_symmetric( gf_gf2ff( imm2int( value ) ) ) ) );
1167            else
1168                return *this;
1169        else  if ( CFFactory::gettype() == PrimePowerDomain )
1170            return CanonicalForm( CFFactory::basic( imm2int( value ) ) );
1171        else  if ( getGFDegree() == 1 )
1172            return CanonicalForm( int2imm_p( ff_norm( imm2int( value ) ) ) );
1173        else
1174            return CanonicalForm( int2imm_gf( ff_norm( imm2int( value ) ) ) );
1175    else  if ( value->inBaseDomain() )
1176        if ( getCharacteristic() == 0 )
1177            if ( value->levelcoeff() == PrimePowerDomain )
1178                return CFFactory::basic( getmpi( value, true ) );
1179            else
1180                return *this;
1181        else  if ( CFFactory::gettype() == PrimePowerDomain ) {
1182            ASSERT( value->levelcoeff() == PrimePowerDomain || value->levelcoeff() == IntegerDomain, "no proper map defined" );
1183            if ( value->levelcoeff() == PrimePowerDomain )
1184                return *this;
1185            else
1186                return CFFactory::basic( getmpi( value ) );
1187        }
1188        else {
1189            int val;
1190            if ( value->levelcoeff() == IntegerDomain )
1191                val = value->intmod( ff_prime );
1192            else  if ( value->levelcoeff() == RationalDomain )
1193                return num().mapinto() / den().mapinto();
1194            else {
1195                ASSERT( 0, "illegal domain" );
1196                return 0;
1197            }
1198            if ( getGFDegree() > 1 )
1199                return CanonicalForm( int2imm_gf( gf_int2gf( val ) ) );
1200            else
1201                return CanonicalForm( int2imm_p( val ) );
1202        }
1203    else {
1204        Variable x = value->variable();
1205        CanonicalForm result;
1206        for ( CFIterator i = *this; i.hasTerms(); i++ )
1207            result += power( x, i.exp() ) * i.coeff().mapinto();
1208        return result;
1209    }
1210}
1211
1212void
1213On( int sw )
1214{
1215    cf_glob_switches.On( sw );
1216}
1217
1218void
1219Off( int sw )
1220{
1221    cf_glob_switches.Off( sw );
1222}
1223
1224bool
1225isOn( int sw )
1226{
1227    return cf_glob_switches.isOn( sw );
1228}
1229
1230bool
1231CanonicalForm::isFFinGF() const
1232{
1233    return is_imm( value ) == GFMARK && gf_isff( imm2int( value ) );
1234}
1235
1236static void
1237fillVarsRec ( const CanonicalForm & f, int * vars )
1238{
1239    int n;
1240    if ( (n = f.level()) > 0 ) {
1241        vars[n] = 1;
1242        CFIterator i;
1243        for ( i = f; i.hasTerms(); ++i )
1244            fillVarsRec( i.coeff(), vars );
1245    }
1246}
1247
1248CanonicalForm
1249CanonicalForm::sqrt ( ) const
1250{
1251    if ( is_imm( value ) ) {
1252        ASSERT( is_imm( value ) == INTMARK, "not implemented" );
1253        int a = imm2int( value );
1254        if ( a == 1 )
1255            return CanonicalForm( CFFactory::basic( 1 ) );
1256        else {
1257            int h, x0, x1 = a;
1258            do {
1259                x0 = x1;
1260                h = x0 * x0 + a - 1;
1261                if ( h % (2 * x0) == 0 )
1262                    x1 = h / (2 * x0);
1263                else
1264                    x1 = (h - 1)  / (2 * x0);
1265            } while ( x1 < x0 );
1266            return CanonicalForm( CFFactory::basic( x1 ) );
1267        }
1268    }
1269    else
1270        return CanonicalForm( value->sqrt() );
1271}
1272
1273
1274int
1275getNumVars( const CanonicalForm & f )
1276{
1277    int n;
1278    if ( f.inCoeffDomain() )
1279        return 0;
1280    else  if ( (n = f.level()) == 1 )
1281        return 1;
1282    else {
1283        int * vars = new int[ n+1 ];
1284        int i;
1285        for ( i = 0; i < n; i++ ) vars[i] = 0;
1286        for ( CFIterator I = f; I.hasTerms(); ++I )
1287            fillVarsRec( I.coeff(), vars );
1288        int m = 0;
1289        for ( i = 1; i < n; i++ )
1290            if ( vars[i] != 0 ) m++;
1291        delete [] vars;
1292        return m+1;
1293    }
1294}
1295
1296CanonicalForm
1297getVars( const CanonicalForm & f )
1298{
1299    int n;
1300    if ( f.inCoeffDomain() )
1301        return 1;
1302    else  if ( (n = f.level()) == 1 )
1303        return Variable( 1 );
1304    else {
1305        int * vars = new int[ n+1 ];
1306        int i;
1307        for ( i = 0; i <= n; i++ ) vars[i] = 0;
1308        for ( CFIterator I = f; I.hasTerms(); ++I )
1309            fillVarsRec( I.coeff(), vars );
1310        CanonicalForm result = 1;
1311        for ( i = n; i > 0; i-- )
1312            if ( vars[i] != 0 ) result *= Variable( i );
1313        delete [] vars;
1314        return f.mvar() * result;
1315    }
1316}
1317
1318bool
1319divides ( const CanonicalForm & f, const CanonicalForm & g )
1320{
1321    if ( g.level() > 0 && g.level() == f.level() )
1322        if ( divides( f.tailcoeff(), g.tailcoeff() ) && divides( f.LC(), g.LC() ) ) {
1323            CanonicalForm q, r;
1324            bool ok = divremt( g, f, q, r );
1325            return ok && r == 0;
1326        }
1327        else
1328            return false;
1329    else {
1330        CanonicalForm q, r;
1331        bool ok = divremt( g, f, q, r );
1332        return ok && r == 0;
1333    }
1334}
Note: See TracBrowser for help on using the repository browser.