source: git/factory/int_int.cc @ 05d0b3

spielwiese
Last change on this file since 05d0b3 was 05d0b3, checked in by Jens Schmidt <schmidt@…>, 26 years ago
* int_cf.cc, int_int.cc int_rat.cc (bgcdsame, bgcdcoeff, bextgcdsame, bextgcdcoeff): new methods. Declarations added. git-svn-id: file:///usr/local/Singular/svn/trunk@1043 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 22.7 KB
Line 
1/* emacs edit mode for this file is -*- C++ -*- */
2/* $Id: int_int.cc,v 1.11 1998-01-22 10:54:15 schmidt Exp $ */
3
4#include <config.h>
5
6#include "assert.h"
7
8#include "cf_defs.h"
9#include "cf_globals.h"
10#include "int_int.h"
11#include "int_rat.h"
12#include "imm.h"
13#include "canonicalform.h"
14#include "gmpext.h"
15
16InternalInteger::InternalInteger()
17{
18    mpz_init( &thempi );
19}
20
21InternalInteger::InternalInteger( const int i )
22{
23    mpz_init_set_si( &thempi, i );
24}
25
26InternalInteger::InternalInteger( const MP_INT & mpi) : thempi( mpi ) {}
27
28InternalInteger::InternalInteger( const char * str )
29{
30    mpz_init_set_str( &thempi, str, 10 );
31}
32
33InternalInteger::~InternalInteger()
34{
35    mpz_clear( &thempi );
36}
37
38InternalCF* InternalInteger::deepCopyObject() const
39{
40    MP_INT dummy;
41    mpz_init_set( &dummy, &thempi );
42    return new InternalInteger( dummy );
43}
44
45#ifndef NOSTREAMIO
46void InternalInteger::print( ostream & os, char * c )
47{
48    if ( *c == '*' && mpz_cmp_si( &thempi, 1 ) == 0 )
49        os << c+1;
50    else if ( *c == '*' && mpz_cmp_si( &thempi, -1 ) == 0 )
51        os << '-' << c+1;
52    else {
53        char * str = new char[mpz_sizeinbase( &thempi, 10 ) + 2];
54        str = mpz_get_str( str, 10, &thempi );
55        os << str << c;
56        delete [] str;
57    }
58}
59#endif /* NOSTREAMIO */
60
61bool InternalInteger::isZero() const
62{
63    return mpz_cmp_si( &thempi, 0 ) == 0;
64}
65
66bool InternalInteger::isOne() const
67{
68    return mpz_cmp_si( &thempi, 1 ) == 0;
69}
70
71bool InternalInteger::is_imm() const
72{
73    return mpz_is_imm( &thempi );
74}
75
76InternalCF* InternalInteger::genZero()
77{
78    if ( isZero() )
79        return copyObject();
80    else
81        return new InternalInteger();
82}
83
84InternalCF* InternalInteger::genOne()
85{
86    if ( isOne() )
87        return copyObject();
88    else
89        return new InternalInteger( 1 );
90}
91
92InternalCF* InternalInteger::neg()
93{
94    if ( getRefCount() > 1 ) {
95        decRefCount();
96        MP_INT dummy;
97        mpz_init( &dummy );
98        mpz_neg( &dummy, &thempi );
99        return new InternalInteger( dummy );
100    }
101    else {
102        mpz_neg( &thempi, &thempi );
103        return this;
104    }
105}
106
107
108InternalCF* InternalInteger::addsame( InternalCF * c )
109{
110    if ( getRefCount() > 1 ) {
111        decRefCount();
112        MP_INT dummy;
113        mpz_init( &dummy );
114        mpz_add( &dummy, &thempi, &MPI( c ) );
115        if ( mpz_is_imm( &dummy ) ) {
116            InternalCF * res = int2imm( mpz_get_si( &dummy ) );
117            mpz_clear( &dummy );
118            return res;
119        }
120        else
121            return new InternalInteger( dummy );
122    }
123    else {
124        mpz_add( &thempi, &thempi, &MPI( c ) );
125        if ( mpz_is_imm( &thempi ) ) {
126            InternalCF * res = int2imm( mpz_get_si( &thempi ) );
127            delete this;
128            return res;
129        }
130        else
131            return this;
132    }
133}
134
135InternalCF* InternalInteger::subsame( InternalCF * c )
136{
137    if ( getRefCount() > 1 ) {
138        decRefCount();
139        MP_INT dummy;
140        mpz_init( &dummy );
141        mpz_sub( &dummy, &thempi, &MPI( c ) );
142        if ( mpz_is_imm( &dummy ) ) {
143            InternalCF * res = int2imm( mpz_get_si( &dummy ) );
144            mpz_clear( &dummy );
145            return res;
146        }
147        else
148            return new InternalInteger( dummy );
149    }
150    else {
151        mpz_sub( &thempi, &thempi, &MPI( c ) );
152        if ( mpz_is_imm( &thempi ) ) {
153            InternalCF * res = int2imm( mpz_get_si( &thempi ) );
154            delete this;
155            return res;
156        }
157        else
158            return this;
159    }
160}
161
162InternalCF* InternalInteger::mulsame( InternalCF * c )
163{
164    if ( getRefCount() > 1 ) {
165        decRefCount();
166        MP_INT dummy;
167        mpz_init( &dummy );
168        mpz_mul( &dummy, &thempi, &MPI( c ) );
169        if ( mpz_is_imm( &dummy ) ) {
170            InternalCF * res = int2imm( mpz_get_si( &dummy ) );
171            mpz_clear( &dummy );
172            return res;
173        }
174        else
175            return new InternalInteger( dummy );
176    }
177    else {
178        mpz_mul( &thempi, &thempi, &MPI( c ) );
179        if ( mpz_is_imm( &thempi ) ) {
180            InternalCF * res = int2imm( mpz_get_si( &thempi ) );
181            delete this;
182            return res;
183        }
184        else
185            return this;
186    }
187}
188
189InternalCF* InternalInteger::dividesame( InternalCF * c )
190{
191    return divsame( c );
192}
193
194InternalCF* InternalInteger::divsame( InternalCF * c )
195{
196    if ( c == this ) {
197        if ( deleteObject() ) delete this;
198        return CFFactory::basic( 1 );
199    }
200    if ( cf_glob_switches.isOn( SW_RATIONAL ) ) {
201        MP_INT n, d;
202        mpz_init_set( &n, &thempi );
203        mpz_init_set( &d, &MPI( c ) );
204        if ( deleteObject() ) delete this;
205        InternalRational * result = new InternalRational( n, d );
206        return result->normalize_myself();
207    }
208    if ( getRefCount() > 1 ) {
209        decRefCount();
210        MP_INT quot;
211        MP_INT rem;
212        int signmpi = mpz_cmp_si( &thempi, 0 );
213        int signc = mpz_cmp_si( &MPI( c ), 0 );
214        if ( signmpi < 0 )
215            mpz_neg( &thempi, &thempi );
216        if ( signc < 0 )
217            mpz_neg( &MPI( c ), &MPI( c ) );
218        mpz_init( &quot ); mpz_init( &rem );
219        mpz_divmod( &quot, &rem, &thempi, &MPI( c ) );
220        if ( signmpi < 0 )
221            mpz_neg( &thempi, &thempi );
222        if ( signc < 0 )
223            mpz_neg( &MPI( c ), &MPI( c ) );
224        if ( signmpi < 0 && signc < 0 ) {
225            if ( mpz_cmp_si( &rem, 0 ) != 0 )
226                mpz_add_ui( &quot, &quot, 1 );
227        }
228        else  if ( signc < 0 )
229            mpz_neg( &quot, &quot );
230        else  if ( signmpi < 0 ) {
231            mpz_neg( &quot, &quot );
232            if ( mpz_cmp_si( &rem, 0 ) != 0 )
233                mpz_sub_ui( &quot, &quot, 1 );
234        }
235        mpz_clear( &rem );
236        if ( mpz_is_imm( &quot ) ) {
237            InternalCF * res = int2imm( mpz_get_si( &quot ) );
238            mpz_clear( &quot );
239            return res;
240        }
241        else
242            return new InternalInteger( quot );
243    }
244    else {
245        MP_INT rem;
246        mpz_init( &rem );
247        int signmpi = mpz_cmp_si( &thempi, 0 );
248        int signc = mpz_cmp_si( &MPI( c ), 0 );
249        if ( signmpi < 0 )
250            mpz_neg( &thempi, &thempi );
251        if ( signc < 0 )
252            mpz_neg( &MPI( c ), &MPI( c ) );
253        mpz_divmod( &thempi, &rem, &thempi, &MPI( c ) );
254        if ( signc < 0 )
255            mpz_neg( &MPI( c ), &MPI( c ) );
256        if ( signmpi < 0 && signc < 0 ) {
257            if ( mpz_cmp_si( &rem, 0 ) != 0 )
258                mpz_add_ui( &thempi, &thempi, 1 );
259        }
260        else  if ( signc < 0 )
261            mpz_neg( &thempi, &thempi );
262        else  if ( signmpi < 0 ) {
263            mpz_neg( &thempi, &thempi );
264            if ( mpz_cmp_si( &rem, 0 ) != 0 )
265                mpz_sub_ui( &thempi, &thempi, 1 );
266        }
267        mpz_clear( &rem );
268        if ( mpz_is_imm( &thempi ) ) {
269            InternalCF * res = int2imm( mpz_get_si( &thempi ) );
270            delete this;
271            return res;
272        }
273        else
274            return this;
275    }
276}
277
278InternalCF* InternalInteger::modulosame ( InternalCF * c )
279{
280    return modsame( c );
281}
282
283InternalCF* InternalInteger::modsame( InternalCF * c )
284{
285    if ( cf_glob_switches.isOn( SW_RATIONAL ) || c == this ) {
286        if ( deleteObject() ) delete this;
287        return CFFactory::basic( 0 );
288    }
289    if ( getRefCount() > 1 ) {
290        decRefCount();
291        MP_INT dummy;
292        mpz_init( &dummy );
293        int signmpi = mpz_cmp_si( &thempi, 0 );
294        int signc = mpz_cmp_si( &MPI( c ), 0 );
295        if ( signmpi < 0 )
296            mpz_neg( &thempi, &thempi );
297        if ( signc < 0 )
298            mpz_neg( &MPI( c ), &MPI( c ) );
299        mpz_mod( &dummy, &thempi, &MPI( c ) );
300        if ( signmpi < 0 && mpz_cmp_si( &dummy, 0 ) != 0 ) {
301            mpz_sub( &dummy, &MPI( c ), &dummy );
302        }
303        if ( signmpi < 0 )
304            mpz_neg( &thempi, &thempi );
305        if ( signc < 0 )
306            mpz_neg( &MPI( c ), &MPI( c ) );
307        if ( mpz_is_imm( &dummy ) ) {
308            InternalCF * res = int2imm( mpz_get_si( &dummy ) );
309            mpz_clear( &dummy );
310            return res;
311        }
312        else
313            return new InternalInteger( dummy );
314    }
315    else {
316        int signmpi = mpz_cmp_si( &thempi, 0 );
317        int signc = mpz_cmp_si( &MPI( c ), 0 );
318        if ( signmpi < 0 )
319            mpz_neg( &thempi, &thempi );
320        if ( signc < 0 )
321            mpz_neg( &MPI( c ), &MPI( c ) );
322        mpz_mod( &thempi, &thempi, &MPI( c ) );
323        if ( signmpi < 0 && mpz_cmp_si( &thempi, 0 ) != 0 ) {
324            mpz_sub( &thempi, &MPI( c ), &thempi );
325        }
326        if ( signc < 0 )
327            mpz_neg( &MPI( c ), &MPI( c ) );
328        if ( mpz_is_imm( &thempi ) ) {
329            InternalCF * res = int2imm( mpz_get_si( &thempi ) );
330            delete this;
331            return res;
332        }
333        else
334            return this;
335    }
336}
337
338void InternalInteger::divremsame( InternalCF * c, InternalCF*& quot, InternalCF*& rem )
339{
340    if ( cf_glob_switches.isOn( SW_RATIONAL ) ) {
341        quot = copyObject();
342        quot = quot->dividesame( c );
343        rem = CFFactory::basic( 0 );
344    }
345    else  if ( c == this ) {
346        quot = CFFactory::basic( 1 );
347        rem = CFFactory::basic( 0 );
348    }
349    else {
350        MP_INT q;
351        MP_INT r;
352        mpz_init( &q ); mpz_init( &r );
353        int signmpi = mpz_cmp_si( &thempi, 0 );
354        int signc = mpz_cmp_si( &MPI( c ), 0 );
355        if ( signmpi < 0 )
356            mpz_neg( &thempi, &thempi );
357        if ( signc < 0 )
358            mpz_neg( &MPI( c ), &MPI( c ) );
359        mpz_divmod( &q, &r, &thempi, &MPI( c ) );
360        if ( signmpi < 0 && mpz_cmp_si( &r, 0 ) != 0 ) {
361            mpz_sub( &r, &MPI( c ), &r );
362        }
363        if ( signmpi < 0 )
364            mpz_neg( &thempi, &thempi );
365        if ( signc < 0 )
366            mpz_neg( &MPI( c ), &MPI( c ) );
367        if ( signmpi < 0 && signc < 0 ) {
368            if ( mpz_cmp_si( &r, 0 ) != 0 )
369                mpz_add_ui( &q, &q, 1 );
370        }
371        else  if ( signc < 0 )
372            mpz_neg( &q, &q );
373        else  if ( signmpi < 0 ) {
374            mpz_neg( &q, &q );
375            if ( mpz_cmp_si( &r, 0 ) != 0 )
376                mpz_sub_ui( &q, &q, 1 );
377        }
378        if ( mpz_is_imm( &q ) )
379            quot = int2imm( mpz_get_si( &q ) );
380        else
381            quot = new InternalInteger( q );
382        if ( mpz_is_imm( &r ) )
383            rem = int2imm( mpz_get_si( &r ) );
384        else
385            rem = new InternalInteger( r );
386    }
387}
388
389bool InternalInteger::divremsamet( InternalCF* c, InternalCF*& quot, InternalCF*& rem )
390{
391    divremsame( c, quot, rem );
392    return true;
393}
394
395//{{{ int InternalInteger::comparesame, comparecoeff ( InternalCF * c )
396// docu: see CanonicalForm::operator <(), CanonicalForm::operator ==()
397int
398InternalInteger::comparesame ( InternalCF * c )
399{
400    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == IntegerDomain, "incompatible base coefficients" );
401    return mpz_cmp( &thempi, &MPI( c ) );
402}
403
404int
405InternalInteger::comparecoeff ( InternalCF * c )
406{
407    ASSERT( ::is_imm( c ) == INTMARK, "incompatible base coefficients" );
408    return mpz_cmp_si( &thempi, imm2int( c ) );
409}
410//}}}
411
412InternalCF* InternalInteger::addcoeff( InternalCF* c )
413{
414    ASSERT( ::is_imm( c ) == INTMARK, "incompatible base coefficients" );
415    int cc = imm2int( c );
416    if ( getRefCount() > 1 ) {
417        decRefCount();
418        MP_INT dummy;
419        mpz_init( &dummy );
420        if ( cc < 0 )
421            mpz_sub_ui( &dummy, &thempi, -cc );
422        else
423            mpz_add_ui( &dummy, &thempi, cc );
424        if ( mpz_is_imm( &dummy ) ) {
425            InternalCF * res = int2imm( mpz_get_si( &dummy ) );
426            mpz_clear( &dummy );
427            return res;
428        }
429        else
430            return new InternalInteger( dummy );
431    }
432    else {
433        if ( cc < 0 )
434            mpz_sub_ui( &thempi, &thempi, -cc );
435        else
436            mpz_add_ui( &thempi, &thempi, cc );
437        if ( mpz_is_imm( &thempi ) ) {
438            InternalCF * res = int2imm( mpz_get_si( &thempi ) );
439            delete this;
440            return res;
441        }
442        else
443            return this;
444    }
445}
446
447InternalCF* InternalInteger::subcoeff( InternalCF* c, bool negate )
448{
449    ASSERT( ::is_imm( c ) == INTMARK, "incompatible base coefficients" );
450    int cc = imm2int( c );
451    if ( getRefCount() > 1 ) {
452        decRefCount();
453        MP_INT dummy;
454        if ( negate ) {
455            mpz_init_set_si( &dummy, cc );
456            mpz_sub( &dummy, &dummy, &thempi );
457        }
458        else {
459            mpz_init( &dummy );
460            if ( cc < 0 )
461                mpz_add_ui( &dummy, &thempi, -cc );
462            else
463                mpz_sub_ui( &dummy, &thempi, cc );
464        }
465        if ( mpz_is_imm( &dummy ) ) {
466            InternalCF * res = int2imm( mpz_get_si( &dummy ) );
467            mpz_clear( &dummy );
468            return res;
469        }
470        else
471            return new InternalInteger( dummy );
472    }
473    else {
474        if ( negate ) {
475            MP_INT dummy;
476            mpz_init_set_si( &dummy, cc );
477            mpz_sub( &thempi, &dummy, &thempi );
478            mpz_clear( &dummy );
479        }
480        else
481            if ( cc < 0 )
482                mpz_add_ui( &thempi, &thempi, -cc );
483            else
484                mpz_sub_ui( &thempi, &thempi, cc );
485        if ( mpz_is_imm( &thempi ) ) {
486            InternalCF * res = int2imm( mpz_get_si( &thempi ) );
487            delete this;
488            return res;
489        }
490        else
491            return this;
492    }
493}
494
495InternalCF* InternalInteger::mulcoeff( InternalCF* c )
496{
497    ASSERT( ::is_imm( c ) == INTMARK, "incompatible base coefficients" );
498    int cc = imm2int( c );
499    if ( getRefCount() > 1 ) {
500        decRefCount();
501        MP_INT dummy;
502        mpz_init( &dummy );
503        if ( cc < 0 ) {
504            mpz_mul_ui( &dummy, &thempi, -cc );
505            mpz_neg( &dummy, &dummy );
506        }
507        else
508            mpz_mul_ui( &dummy, &thempi, cc );
509        if ( mpz_is_imm( &dummy ) ) {
510            InternalCF * res = int2imm( mpz_get_si( &dummy ) );
511            mpz_clear( &dummy );
512            return res;
513        }
514        else
515            return new InternalInteger( dummy );
516    }
517    else {
518        MP_INT dummy;
519        mpz_init_set_si( &dummy, cc );
520        if ( cc < 0 ) {
521            mpz_mul_ui( &thempi, &thempi, -cc );
522            mpz_neg( &thempi, &thempi );
523        }
524        else
525            mpz_mul_ui( &thempi, &thempi, cc );
526        if ( mpz_is_imm( &thempi ) ) {
527            InternalCF * res = int2imm( mpz_get_si( &thempi ) );
528            delete this;
529            return res;
530        }
531        else
532            return this;
533    }
534}
535
536InternalCF* InternalInteger::dividecoeff( InternalCF* c, bool invert )
537{
538    return divcoeff( c, invert );
539}
540
541InternalCF* InternalInteger::divcoeff( InternalCF* c, bool invert )
542{
543    ASSERT( invert || ! ::is_imm( c ) || imm2int( c ) != 0, "divide by zero" );
544    int cc = imm2int( c );
545    if ( cf_glob_switches.isOn( SW_RATIONAL ) ) {
546        MP_INT n, d;
547        if ( invert ) {
548            mpz_init_set_si( &n, cc );
549            mpz_init_set( &d, &thempi );
550        }
551        else {
552            mpz_init_set_si( &d, cc );
553            mpz_init_set( &n, &thempi );
554        }
555        if ( deleteObject() ) delete this;
556        InternalRational * result = new InternalRational( n, d );
557        return result->normalize_myself();
558    }
559    ASSERT( ::is_imm( c ) == INTMARK, "incompatible base coefficients" );
560    MP_INT quot;
561    MP_INT rem;
562    int signmpi = mpz_cmp_si( &thempi, 0 );
563    int signc = cc;
564    mpz_init( &quot ); mpz_init( &rem );
565    if ( signmpi < 0 )
566        mpz_neg( &thempi, &thempi );
567    if ( signc < 0 )
568        cc = -cc;
569    if ( invert ) {
570        MP_INT ccc;
571        mpz_init_set_si( &ccc, cc );
572        mpz_divmod( &quot, &rem, &ccc, &thempi );
573        mpz_clear( &ccc );
574        if ( signmpi < 0 )
575            mpz_neg( &thempi, &thempi );
576        if ( signmpi < 0 && signc < 0 ) {
577            if ( mpz_cmp_si( &rem, 0 ) != 0 )
578                mpz_add_ui( &quot, &quot, 1 );
579        }
580        else  if ( signmpi < 0 )
581            mpz_neg( &quot, &quot );
582        else  if ( signc < 0 ) {
583            mpz_neg( &quot, &quot );
584            if ( mpz_cmp_si( &rem, 0 ) != 0 )
585                mpz_sub_ui( &quot, &quot, 1 );
586        }
587    }
588    else {
589        mpz_divmod_ui( &quot, &rem, &thempi, cc );
590        if ( signmpi < 0 )
591            mpz_neg( &thempi, &thempi );
592        if ( signmpi < 0 && signc < 0 ) {
593            if ( mpz_cmp_si( &rem, 0 ) != 0 )
594                mpz_add_ui( &quot, &quot, 1 );
595        }
596        else  if ( signc < 0 )
597            mpz_neg( &quot, &quot );
598        else  if ( signmpi < 0 ) {
599            mpz_neg( &quot, &quot );
600            if ( mpz_cmp_si( &rem, 0 ) != 0 )
601                mpz_sub_ui( &quot, &quot, 1 );
602        }
603    }
604    mpz_clear( &rem );
605    if ( deleteObject() ) delete this;
606    if ( mpz_is_imm( &quot ) ) {
607        InternalCF * res = int2imm( mpz_get_si( &quot ) );
608        mpz_clear( &quot );
609        return res;
610    }
611    else
612        return new InternalInteger( quot );
613}
614
615InternalCF* InternalInteger::modulocoeff( InternalCF * c, bool invert )
616{
617    return modcoeff( c, invert );
618}
619
620InternalCF* InternalInteger::modcoeff( InternalCF* c, bool invert )
621{
622    ASSERT( ::is_imm( c ) == INTMARK, "incompatible base coefficients" );
623    if ( cf_glob_switches.isOn( SW_RATIONAL ) ) {
624        // in rational mode remainder is zero
625        if ( deleteObject() ) delete this;
626        return CFFactory::basic( 0 );
627    }
628    int cc = imm2int( c );
629    MP_INT rem;
630    int signmpi = mpz_cmp_si( &thempi, 0 );
631    int signc = cc;
632    mpz_init( &rem );
633    if ( signmpi < 0 )
634        mpz_neg( &thempi, &thempi );
635    if ( signc < 0 )
636        cc = -cc;
637    if ( invert ) {
638        MP_INT ccc;
639        mpz_init_set_si( &ccc, cc );
640        mpz_mod( &rem, &ccc, &thempi );
641        mpz_clear( &ccc );
642        if ( signc < 0 && mpz_cmp_si( &rem, 0 ) != 0 ) {
643            mpz_sub( &rem, &thempi, &rem );
644        }
645        if ( signmpi < 0 )
646            mpz_neg( &thempi, &thempi );
647    }
648    else {
649        mpz_mod_ui( &rem, &thempi, cc );
650        if ( signmpi < 0 && mpz_cmp_si( &rem, 0 ) != 0 ) {
651            mpz_neg( &rem, &rem );
652            mpz_add_ui( &rem, &rem, cc );
653        }
654        if ( signmpi < 0 )
655            mpz_neg( &thempi, &thempi );
656    }
657    if ( deleteObject() ) delete this;
658    if ( mpz_is_imm( &rem ) ) {
659        InternalCF * res = int2imm( mpz_get_si( &rem ) );
660        mpz_clear( &rem );
661        return res;
662    }
663    else
664        return new InternalInteger( rem );
665}
666
667void InternalInteger::divremcoeff( InternalCF* c, InternalCF*& quot, InternalCF*& rem, bool invert )
668{
669    ASSERT( ::is_imm( c ) == INTMARK, "incompatible base coefficients" );
670
671    if ( cf_glob_switches.isOn( SW_RATIONAL ) ) {
672        quot = copyObject();
673        quot = quot->dividecoeff( c, invert );
674        rem = CFFactory::basic( 0 );
675        return;
676    }
677    quot = copyObject();
678    quot = quot->divcoeff( c, invert );
679    rem = copyObject();
680    rem = rem->modcoeff( c, invert );
681    return;
682    int cc = imm2int( c );
683    MP_INT q, r;
684    int signmpi = mpz_cmp_si( &thempi, 0 );
685    int signc = cc;
686
687    mpz_init( &q ); mpz_init( &r );
688    if ( signmpi < 0 )
689        mpz_neg( &thempi, &thempi );
690    if ( signc < 0 )
691        cc = -cc;
692    if ( invert ) {
693        MP_INT ccc;
694        mpz_init_set_si( &ccc, cc );
695        mpz_divmod( &q, &r, &ccc, &thempi );
696        mpz_clear( &ccc );
697        if ( signc < 0 && signmpi < 0 ) {
698            if ( mpz_cmp_si( &r, 0 ) != 0 ) {
699                mpz_add_ui( &q, &q, 1 );
700                mpz_sub( &r, &thempi, &r );
701            }
702        }
703        else  if ( signc < 0 ) {
704            if ( mpz_cmp_si( &r, 0 ) != 0 ) {
705                mpz_add_ui( &q, &q, 1 );
706                mpz_neg( &q, &q );
707                mpz_sub( &r, &thempi, &r );
708            }
709        }
710        else  if ( signmpi < 0 )
711            mpz_neg( &q, &q );
712    }
713    else {
714        mpz_divmod_ui( &q, &r, &thempi, cc );
715        if ( signmpi < 0 && signc < 0 ) {
716            if ( mpz_cmp_si( &r, 0 ) != 0 ) {
717                mpz_add_ui( &q, &q, 1 );
718                mpz_neg( &r, &r );
719                mpz_add_ui( &r, &r, cc );
720            }
721        }
722        else  if ( signmpi < 0 ) {
723            if ( mpz_cmp_si( &r, 0 ) != 0 ) {
724                mpz_add_ui( &q, &q, 1 );
725                mpz_neg( &q, &q );
726                mpz_neg( &r, &r );
727                mpz_add_ui( &r, &r, cc );
728            }
729        }
730        else  if ( signc < 0 )
731            mpz_neg( &q, &q );
732    }
733    if ( signmpi < 0 )
734        mpz_neg( &thempi, &thempi );
735    if ( mpz_is_imm( &r ) ) {
736        rem = int2imm( mpz_get_si( &r ) );
737        mpz_clear( &r );
738    }
739    else
740        rem = new InternalInteger( r );
741    if ( mpz_is_imm( &q ) ) {
742        quot = int2imm( mpz_get_si( &q ) );
743        mpz_clear( &q );
744    }
745    else
746        quot = new InternalInteger( q );
747}
748
749bool InternalInteger::divremcoefft( InternalCF* c, InternalCF*& quot, InternalCF*& rem, bool invert )
750{
751    ASSERT( ::is_imm( c ) == INTMARK, "incompatible base coefficients" );
752    divremcoeff( c, quot, rem, invert );
753    return true;
754}
755
756//{{{ InternalCF * InternalInteger::bgcdsame, bgcdcoeff ( const InternalCF * const c )
757// docu: see CanonicalForm::bgcd()
758InternalCF *
759InternalInteger::bgcdsame ( const InternalCF * const c ) const
760{
761    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == IntegerDomain, "incompatible base coefficients" );
762
763    // simply return 1 if we are calculating over the rationals
764    if ( cf_glob_switches.isOn( SW_RATIONAL ) )
765         return int2imm( 1 );
766
767    // calculate gcd
768    MP_INT result;
769    mpz_init( &result );
770    mpz_gcd( &result, &thempi, &MPI( c ) );
771    mpz_abs( &result, &result );
772
773    // check for immediate result
774    if ( mpz_is_imm( &result ) ) {
775        InternalCF * res = int2imm( mpz_get_si( &result ) );
776        mpz_clear( &result );
777        return res;
778    }
779    else
780        return new InternalInteger( result );
781}
782
783InternalCF *
784InternalInteger::bgcdcoeff ( const InternalCF * const c )
785{
786    ASSERT( ::is_imm( c ) == INTMARK, "incompatible base coefficients" );
787
788    // simply return 1 if we are calculating over the rationals
789    if ( cf_glob_switches.isOn( SW_RATIONAL ) )
790         return int2imm( 1 );
791
792    int cInt = imm2int( c );
793
794    // trivial cases
795    if ( cInt == 1 || cInt == -1 )
796        return int2imm( 1 );
797    else if ( cInt == 0 )
798        return copyObject();
799
800    // calculate gcd.  We need a positive operand since
801    // `mpz_gcd_ui()' operates an unsigned int's only.
802    if ( cInt < 0 ) cInt = -cInt;
803    MP_INT dummy;
804    mpz_init( &dummy );
805    // we do not need dummy since we know that cInt != 0
806    cInt = mpz_gcd_ui( &dummy, &thempi, cInt );
807    mpz_clear( &dummy );
808    if ( cInt < 0 ) cInt = -cInt;
809    return int2imm( cInt );
810}
811//}}}
812
813//{{{ InternalCF * InternalInteger::bextgcdsame( InternalCF * c, CanonicalForm & a, CanonicalForm & b )
814InternalCF *
815InternalInteger::bextgcdsame( InternalCF * c, CanonicalForm & a, CanonicalForm & b )
816{
817    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == IntegerDomain, "incompatible base coefficients" );
818
819    // simply return 1 if we are calculating over the rationals
820    if ( cf_glob_switches.isOn( SW_RATIONAL ) ) {
821        a = 1/CanonicalForm( copyObject() ); b = 0;
822        return int2imm( 1 );
823    }
824
825    // calculate extended gcd
826    MP_INT result;
827    MP_INT aMPI;
828    MP_INT bMPI;
829    mpz_init( &result );
830    mpz_init( &aMPI );
831    mpz_init( &bMPI );
832    mpz_gcdext( &result, &aMPI, &bMPI, &thempi, &MPI( c ) );
833   
834    // check and modify signs
835    if ( mpz_sgn( &result ) < 0 ) {
836        mpz_neg( &result, &result );
837        mpz_neg( &aMPI, &aMPI );
838        mpz_neg( &bMPI, &bMPI );
839    }
840
841    // postconditioning of result
842    if ( mpz_is_imm( &aMPI ) ) {
843        a = CanonicalForm( int2imm( mpz_get_si( &aMPI ) ) );
844        mpz_clear( &aMPI );
845    } else
846        a = CanonicalForm( new InternalInteger( aMPI ) );
847    if ( mpz_is_imm( &bMPI ) ) {
848        b = CanonicalForm( int2imm( mpz_get_si( &bMPI ) ) );
849        mpz_clear( &bMPI );
850    } else
851        b = CanonicalForm( new InternalInteger( bMPI ) );
852    if ( mpz_is_imm( &result ) ) {
853        InternalCF * res = int2imm( mpz_get_si( &result ) );
854        mpz_clear( &result );
855        return res;
856    }
857    else
858        return new InternalInteger( result );
859}
860
861InternalCF *
862InternalInteger::bextgcdcoeff( InternalCF * c, CanonicalForm & a, CanonicalForm & b )
863{
864    ASSERT( ::is_imm( c ) == INTMARK, "incompatible base coefficients" );
865
866    // simply return 1 if we are calculating over the rationals
867    if ( cf_glob_switches.isOn( SW_RATIONAL ) ) {
868        a = 1/CanonicalForm( copyObject() ); b = 0;
869        return int2imm( 1 );
870    }
871
872    int cInt = imm2int( c );
873
874    // trivial cases
875    if ( cInt == 1 || cInt == -1 ) {
876        a = 0; b = cInt;
877        return int2imm( 1 );
878    } else if ( cInt == 0 ) {
879        a = 1; b = 0;
880        return copyObject();
881    }
882
883    // calculate q and r such that CO = q*cInt + r
884    InternalCF * q = 0, * r = 0;
885    divremcoeff( c, q, r, false );
886
887    // we do not repeat all the code to calculate the gcd of two
888    // immediates.  Note that r is an immediate since c != 0, so
889    // we do not have to destroy it.  q is destroyed by the
890    // CanonicalForm destructor, hence we do not need to worry
891    // about it, either.
892    CanonicalForm aPrime, bPrime;
893    CanonicalForm result = bextgcd( c, r, aPrime, bPrime );
894    a = bPrime;
895    b = aPrime - CanonicalForm( q ) * bPrime;
896
897    return result.getval();
898}
899//}}}
900
901int InternalInteger::intval() const
902{
903  return (int)mpz_get_si( &thempi );
904}
905
906int InternalInteger::intmod( int p ) const
907{
908  return (int)mpz_mmod_ui( 0, &thempi, (unsigned long)p );
909}
910
911//{{{ int InternalInteger::sign () const
912// docu: see CanonicalForm::sign()
913int
914InternalInteger::sign () const
915{
916    return mpz_sgn( &thempi );
917}
918//}}}
919
920//{{{ InternalCF * InternalInteger::sqrt ()
921// docu: see CanonicalForm::sqrt()
922InternalCF *
923InternalInteger::sqrt ()
924{
925    ASSERT( mpz_cmp_si( &thempi, 0 ) >= 0, "sqrt() argument < 0" );
926    MP_INT result;
927    mpz_init( &result );
928    mpz_sqrt( &result, &thempi );
929    if ( mpz_is_imm( &result ) ) {
930        InternalCF * res = int2imm( mpz_get_si( &result ) );
931        mpz_clear( &result );
932        return res;
933    }
934    else
935        return new InternalInteger( result );
936}
937//}}}
938
939//{{{ int InternalInteger::ilog2 ()
940// docu: see CanonicalForm::ilog2()
941int
942InternalInteger::ilog2 ()
943{
944    ASSERT( mpz_cmp_si( &thempi, 0 ) > 0, "log() argument <= 0" );
945    return mpz_sizeinbase( &thempi, 2 ) - 1;
946}
947//}}}
Note: See TracBrowser for help on using the repository browser.