source: git/factory/int_rat.cc @ cacfb6

spielwiese
Last change on this file since cacfb6 was cacfb6, checked in by Hans Schönemann <hannes@…>, 14 years ago
renamed some old gmp functions git-svn-id: file:///usr/local/Singular/svn/trunk@12717 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 21.1 KB
Line 
1/* emacs edit mode for this file is -*- C++ -*- */
2/* $Id$ */
3
4#include <config.h>
5
6#include "assert.h"
7
8#include "cf_defs.h"
9#include "int_rat.h"
10#include "int_int.h"
11#include "imm.h"
12#include "canonicalform.h"
13#include "cf_factory.h"
14#include "gmpext.h"
15
16static int intgcd( int a, int b )
17{
18    if ( a < 0 ) a = -a;
19    if ( b < 0 ) b = -b;
20
21    int c;
22
23    while ( b != 0 )
24    {
25        c = a % b;
26        a = b;
27        b = c;
28    }
29    return a;
30}
31
32
33InternalRational::InternalRational()
34{
35    mpz_init( &_num );
36    mpz_init_set_si( &_den, 1 );
37}
38
39InternalRational::InternalRational( const int i )
40{
41    mpz_init_set_si( &_num, i );
42    mpz_init_set_si( &_den, 1 );
43}
44
45InternalRational::InternalRational( const int n, const int d )
46{
47    ASSERT( d != 0, "divide by zero" );
48    if ( n == 0 )
49    {
50        mpz_init_set_si( &_num, 0 );
51        mpz_init_set_si( &_den, 1 );
52    }
53    else
54    {
55        int g = intgcd( n, d );
56        if ( d < 0 )
57        {
58            mpz_init_set_si( &_num, -n / g );
59            mpz_init_set_si( &_den, -d / g );
60        }
61        else
62        {
63            mpz_init_set_si( &_num, n / g );
64            mpz_init_set_si( &_den, d / g );
65        }
66    }
67}
68
69InternalRational::InternalRational( const char * )
70{
71    // sollte nicht gebraucht werden !!!
72    ASSERT( 0, "fatal error" );
73    mpz_init( &_num );
74    mpz_init( &_den );
75}
76
77InternalRational::InternalRational( const MP_INT &n ) : _num(n)
78{
79    mpz_init_set_si( &_den, 1 );
80}
81
82InternalRational::InternalRational( const MP_INT &n, const MP_INT &d ) : _num(n), _den(d)
83{
84}
85
86InternalRational::~InternalRational()
87{
88    mpz_clear( &_num );
89    mpz_clear( &_den );
90}
91
92InternalCF* InternalRational::deepCopyObject() const
93{
94    MP_INT dummy_num;
95    MP_INT dummy_den;
96    mpz_init_set( &dummy_num, &_num );
97    mpz_init_set( &dummy_den, &_den );
98    return new InternalRational( dummy_num, dummy_den );
99}
100
101#ifndef NOSTREAMIO
102void InternalRational::print( OSTREAM & os, char * c )
103{
104    char * str = new char[mpz_sizeinbase( &_num, 10 ) + 2];
105    str = mpz_get_str( str, 10, &_num );
106    os << str << '/';
107    delete [] str;
108    str = new char[mpz_sizeinbase( &_den, 10 ) + 2];
109    str = mpz_get_str( str, 10, &_den );
110    os << str << c;
111    delete [] str;
112}
113#endif /* NOSTREAMIO */
114
115bool InternalRational::is_imm() const
116{
117    return mpz_cmp_si( &_den, 1 ) == 0 && mpz_is_imm( &_num );
118}
119
120InternalCF* InternalRational::genZero()
121{
122    if ( isZero() )
123        return copyObject();
124    else
125        return new InternalRational();
126}
127
128InternalCF* InternalRational::genOne()
129{
130    if ( isOne() )
131        return copyObject();
132    else
133        return new InternalRational( 1 );
134}
135
136//{{{ InternalCF * InternalRational::num (), den ()
137// docu: see CanonicalForm::num(), den()
138InternalCF * InternalRational::num ()
139{
140    if ( mpz_is_imm( &_num ) )
141    {
142        InternalCF * res = int2imm( mpz_get_si( &_num ) );
143        return res;
144    }
145    else
146    {
147        MP_INT dummy;
148        mpz_init_set( &dummy, &_num );
149        return new InternalInteger( dummy );
150    }
151}
152
153InternalCF * InternalRational::den ()
154{
155    if ( mpz_is_imm( &_den ) )
156    {
157        InternalCF * res = int2imm( mpz_get_si( &_den ) );
158        return res;
159    }
160    else
161    {
162        MP_INT dummy;
163        mpz_init_set( &dummy, &_den );
164        return new InternalInteger( dummy );
165    }
166}
167//}}}
168
169//{{{ InternalCF * InternalRational::neg ()
170// docu: see CanonicalForm::operator -()
171InternalCF *
172InternalRational::neg ()
173{
174    if ( getRefCount() > 1 )
175    {
176        decRefCount();
177        MP_INT dummy_num;
178        MP_INT dummy_den;
179        mpz_init_set( &dummy_num, &_num );
180        mpz_init_set( &dummy_den, &_den );
181        mpz_neg( &dummy_num, &dummy_num );
182        return new InternalRational( dummy_num, dummy_den );
183    }
184    else
185    {
186        mpz_neg( &_num, &_num );
187        return this;
188    }
189}
190//}}}
191
192InternalCF* InternalRational::addsame( InternalCF * c )
193{
194    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == RationalDomain, "illegal domain" );
195    MP_INT n, d, g;
196
197    mpz_init( &g ); mpz_init( &n ); mpz_init( &d );
198    mpz_gcd( &g, &_den, &MPQDEN( c ) );
199
200    if ( mpz_cmp_si( &g, 1 ) == 0 )
201    {
202        mpz_mul( &n, &_den, &MPQNUM( c ) );
203        mpz_mul( &g, &_num, &MPQDEN( c ) );
204        mpz_add( &n, &n, &g );
205        mpz_mul( &d, &_den, &MPQDEN( c ) );
206    }
207    else
208    {
209        MP_INT tmp1;
210        MP_INT tmp2;
211        mpz_init( &tmp1 );
212        mpz_fdiv_q( &tmp1, &_den, &g );
213        mpz_init( &tmp2 );
214        mpz_fdiv_q( &tmp2, &MPQDEN( c ), &g );
215        mpz_mul( &d, &tmp2, &_den );
216        mpz_mul( &tmp2, &tmp2, &_num );
217        mpz_mul( &tmp1, &tmp1, &MPQNUM( c ) );
218        mpz_add( &n, &tmp1, &tmp2 );
219        mpz_gcd( &g, &n, &d );
220        if ( mpz_cmp_si( &g, 1 ) != 0 )
221        {
222            mpz_fdiv_q( &n, &n, &g );
223            mpz_fdiv_q( &d, &d, &g );
224        }
225        mpz_clear( &tmp1 );
226        mpz_clear( &tmp2 );
227    }
228    mpz_clear( &g );
229    if ( deleteObject() ) delete this;
230    if ( mpz_cmp_si( &d, 1 ) == 0 )
231    {
232        mpz_clear( &d );
233        if ( mpz_is_imm( &n ) )
234        {
235            InternalCF * res = int2imm( mpz_get_si( &n ) );
236            mpz_clear( &n );
237            return res;
238        }
239        else
240        {
241            return new InternalInteger( n );
242        }
243    }
244    else
245        return new InternalRational( n, d );
246}
247
248InternalCF* InternalRational::subsame( InternalCF * c )
249{
250    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == RationalDomain, "illegal domain" );
251    MP_INT n, d, g;
252
253    mpz_init( &g ); mpz_init( &n ); mpz_init( &d );
254    mpz_gcd( &g, &_den, &MPQDEN( c ) );
255
256    if ( mpz_cmp_si( &g, 1 ) == 0 )
257    {
258        mpz_mul( &n, &_den, &MPQNUM( c ) );
259        mpz_mul( &g, &_num, &MPQDEN( c ) );
260        mpz_sub( &n, &g, &n );
261        mpz_mul( &d, &_den, &MPQDEN( c ) );
262    }
263    else
264    {
265        MP_INT tmp1;
266        MP_INT tmp2;
267        mpz_init( &tmp1 );
268        mpz_fdiv_q( &tmp1, &_den, &g );
269        mpz_init( &tmp2 );
270        mpz_fdiv_q( &tmp2, &MPQDEN( c ), &g );
271        mpz_mul( &d, &tmp2, &_den );
272        mpz_mul( &tmp2, &tmp2, &_num );
273        mpz_mul( &tmp1, &tmp1, &MPQNUM( c ) );
274        mpz_sub( &n, &tmp2, &tmp1 );
275        mpz_gcd( &g, &n, &d );
276        if ( mpz_cmp_si( &g, 1 ) != 0 )
277        {
278            mpz_fdiv_q( &n, &n, &g );
279            mpz_fdiv_q( &d, &d, &g );
280        }
281        mpz_clear( &tmp1 );
282        mpz_clear( &tmp2 );
283    }
284    mpz_clear( &g );
285    if ( deleteObject() ) delete this;
286    if ( mpz_cmp_si( &d, 1 ) == 0 )
287    {
288        mpz_clear( &d );
289        if ( mpz_is_imm( &n ) )
290        {
291            InternalCF * res = int2imm( mpz_get_si( &n ) );
292            mpz_clear( &n );
293            return res;
294        }
295        else
296        {
297            return new InternalInteger( n );
298        }
299    }
300    else
301        return new InternalRational( n, d );
302}
303
304InternalCF* InternalRational::mulsame( InternalCF * c )
305{
306    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == RationalDomain, "illegal domain" );
307    MP_INT n, d;
308
309    if ( this == c )
310    {
311        mpz_init( &n ); mpz_init( &d );
312        mpz_mul( &n, &_num, &_num );
313        mpz_mul( &d, &_den, &_den );
314    }
315    else
316    {
317        MP_INT g1, g2, tmp1, tmp2;
318        mpz_init( &g1 ); mpz_init( &g2 );
319        mpz_init( &n ); mpz_init( &d );
320        mpz_gcd( &g1, &_num, &MPQDEN( c ) );
321        mpz_gcd( &g2, &_den, &MPQNUM( c ) );
322        bool g1is1 = mpz_cmp_si( &g1, 1 ) == 0;
323        bool g2is1 = mpz_cmp_si( &g2, 1 ) == 0;
324        mpz_init( &tmp1 ); mpz_init( &tmp2 );
325        if ( ! g1is1 )
326            mpz_fdiv_q( &tmp1, &_num, &g1 );
327        else
328            mpz_set( &tmp1, &_num );
329        if ( ! g2is1 )
330            mpz_fdiv_q( &tmp2, &MPQNUM( c ), &g2 );
331        else
332            mpz_set( &tmp2, &MPQNUM( c ) );
333        mpz_mul( &n, &tmp1, &tmp2 );
334        if ( ! g1is1 )
335            mpz_fdiv_q( &tmp1, &MPQDEN( c ), &g1 );
336        else
337            mpz_set( &tmp1, &MPQDEN( c ) );
338        if ( ! g2is1 )
339            mpz_fdiv_q( &tmp2, &_den, &g2 );
340        else
341            mpz_set( &tmp2, &_den );
342        mpz_mul( &d, &tmp1, &tmp2 );
343        mpz_clear( &tmp1 ); mpz_clear( &tmp2 );
344        mpz_clear( &g1 ); mpz_clear( &g2 );
345    }
346    if ( deleteObject() ) delete this;
347    if ( mpz_cmp_si( &d, 1 ) == 0 )
348    {
349        mpz_clear( &d );
350        if ( mpz_is_imm( &n ) )
351        {
352            InternalCF * res = int2imm( mpz_get_si( &n ) );
353            mpz_clear( &n );
354            return res;
355        }
356        else
357        {
358            return new InternalInteger( n );
359        }
360    }
361    else
362        return new InternalRational( n, d );
363}
364
365InternalCF* InternalRational::dividesame( InternalCF * c )
366{
367    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == RationalDomain, "illegal domain" );
368
369    if ( this == c )
370    {
371        if ( deleteObject() ) delete this;
372        return CFFactory::basic( 1 );
373    }
374    else
375    {
376        MP_INT n, d;
377        MP_INT g1, g2, tmp1, tmp2;
378        mpz_init( &n ); mpz_init( &d );
379        mpz_init( &g1 ); mpz_init( &g2 );
380        mpz_gcd( &g1, &_num, &MPQNUM( c ) );
381        mpz_gcd( &g2, &_den, &MPQDEN( c ) );
382        bool g1is1 = mpz_cmp_si( &g1, 1 ) == 0;
383        bool g2is1 = mpz_cmp_si( &g2, 1 ) == 0;
384        mpz_init( &tmp1 ); mpz_init( &tmp2 );
385        if ( ! g1is1 )
386            mpz_fdiv_q( &tmp1, &_num, &g1 );
387        else
388            mpz_set( &tmp1, &_num );
389        if ( ! g2is1 )
390            mpz_fdiv_q( &tmp2, &MPQDEN( c ), &g2 );
391        else
392            mpz_set( &tmp2, &MPQDEN( c ) );
393        mpz_mul( &n, &tmp1, &tmp2 );
394        if ( ! g1is1 )
395            mpz_fdiv_q( &tmp1, &MPQNUM( c ), &g1 );
396        else
397            mpz_set( &tmp1, &MPQNUM( c ) );
398        if ( ! g2is1 )
399            mpz_fdiv_q( &tmp2, &_den, &g2 );
400        else
401            mpz_set( &tmp2, &_den );
402        mpz_mul( &d, &tmp1, &tmp2 );
403        mpz_clear( &tmp1 ); mpz_clear( &tmp2 );
404        mpz_clear( &g1 ); mpz_clear( &g2 );
405        if ( deleteObject() ) delete this;
406        if ( mpz_cmp_si( &d, 0 ) < 0 )
407        {
408            mpz_neg( &d, &d );
409            mpz_neg( &n, &n );
410        }
411        if ( mpz_cmp_si( &d, 1 ) == 0 )
412        {
413            mpz_clear( &d );
414            if ( mpz_is_imm( &n ) )
415            {
416                InternalCF * res = int2imm( mpz_get_si( &n ) );
417                mpz_clear( &n );
418                return res;
419            }
420            else
421            {
422                return new InternalInteger( n );
423            }
424        }
425        else
426            return new InternalRational( n, d );
427    }
428}
429
430InternalCF* InternalRational::divsame( InternalCF * c )
431{
432    return dividesame( c );
433}
434
435InternalCF* InternalRational::modulosame( InternalCF * c )
436{
437    return modsame( c );
438}
439
440InternalCF* InternalRational::modsame( InternalCF * )
441{
442    if ( deleteObject() ) delete this;
443    return CFFactory::basic( 0 );
444}
445
446void InternalRational::divremsame( InternalCF * c, InternalCF*& quot, InternalCF*& rem )
447{
448    quot = copyObject();
449    quot = quot->dividesame( c );
450    rem = CFFactory::basic( 0 );
451}
452
453bool InternalRational::divremsamet( InternalCF* c, InternalCF*& quot, InternalCF*& rem )
454{
455    divremsame( c, quot, rem );
456    return true;
457}
458
459//{{{ int InternalRational::comparesame, comparecoeff ( InternalCF * c )
460//{{{ docu
461//
462// comparesame(), comparecoeff() - compare with an
463//   InternalRational.
464//
465// comparesame() compares the CO=a/b and c=p/q using the
466// equivalence a/b < p/q iff a*q < p*b.
467//
468// comparecoeff() compares the CO=a/b and the integer c using the
469// equivalence a/b < c iff a < c*b.
470//
471// Note: Both operations may be relatively expensive due to the
472// multiplications.
473//
474// See also: CanonicalForm::operator <(), CanonicalForm::operator ==()
475//
476//}}}
477int
478InternalRational::comparesame ( InternalCF * c )
479{
480    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == RationalDomain, "incompatible base coefficients" );
481    MP_INT dummy1, dummy2;
482    mpz_init( &dummy1 ); mpz_init( &dummy2 );
483    mpz_mul( &dummy1, &_num, &MPQDEN( c ) );
484    mpz_mul( &dummy2, &_den, &MPQNUM( c ) );
485    int result = mpz_cmp( &dummy1, &dummy2 );
486    mpz_clear( &dummy1 ); mpz_clear( &dummy2 );
487    return result;
488}
489
490int
491InternalRational::comparecoeff ( InternalCF* c )
492{
493    if ( ::is_imm( c ) )
494    {
495        ASSERT( ::is_imm( c ) == INTMARK, "incompatible base coefficients" );
496        MP_INT dummy;
497        mpz_init_set_si( &dummy, imm2int( c ) );
498        mpz_mul( &dummy, &dummy, &_den );
499        int result = mpz_cmp( &_num, &dummy );
500        mpz_clear( &dummy );
501        return result;
502    }
503    else
504    {
505        ASSERT( c->levelcoeff() == IntegerDomain, "incompatible base coefficients" );
506        MP_INT dummy;
507        mpz_init( &dummy );
508        mpz_mul( &dummy, &_den, &InternalInteger::MPI( c ) );
509        int result = mpz_cmp( &_num, &dummy );
510        mpz_clear( &dummy );
511        return result;
512    }
513}
514//}}}
515
516InternalCF* InternalRational::addcoeff( InternalCF* c )
517{
518    ASSERT( ::is_imm( c ) == INTMARK || ! ::is_imm( c ), "expected integer" );
519    MP_INT n, d;
520    if ( ::is_imm( c ) )
521    {
522        int cc = imm2int( c );
523        if ( cc == 0 )
524            return this;
525        else  if ( cc < 0 )
526        {
527            mpz_init( &n );
528            mpz_mul_ui( &n, &_den, -cc );
529            mpz_sub( &n, &_num, &n );
530        }
531        else
532        {
533            mpz_init( &n );
534            mpz_mul_ui( &n, &_den, cc );
535            mpz_add( &n, &_num, &n );
536        }
537    }
538    else
539    {
540        ASSERT( c->levelcoeff() == IntegerDomain, "expected integer" );
541        mpz_init( &n );
542        mpz_mul( &n, &_den, &InternalInteger::MPI( c ) );
543        mpz_add( &n, &_num, &n );
544    }
545    mpz_init_set( &d, &_den );
546    // at this point there is no way that the result is not a true rational
547    if ( deleteObject() ) delete this;
548    return new InternalRational( n, d );
549}
550
551InternalCF* InternalRational::subcoeff( InternalCF* c, bool negate )
552{
553    ASSERT( ::is_imm( c ) == INTMARK || ! ::is_imm( c ), "expected integer" );
554    MP_INT n, d;
555    if ( ::is_imm( c ) )
556    {
557        int cc = imm2int( c );
558        if ( cc == 0 )
559            if ( negate )
560            {
561                if ( getRefCount() == 1 )
562                {
563                    mpz_neg( &_num, &_num );
564                    return this;
565                }
566                else
567                {
568                    decRefCount();
569                    mpz_init_set( &d, &_den );
570                    mpz_init_set( &n, &_num );
571                    mpz_neg( &n, &n );
572                    return new InternalRational( n, d );
573                }
574            }
575            else
576                return this;
577        mpz_init( &n );
578        if ( cc < 0 )
579        {
580            mpz_mul_ui( &n, &_den, -cc );
581            mpz_neg( &n, &n );
582        }
583        else
584            mpz_mul_ui( &n, &_den, cc );
585        if ( negate )
586            mpz_sub( &n, &n, &_num );
587        else
588            mpz_sub( &n, &_num, &n );
589    }
590    else
591    {
592        ASSERT( c->levelcoeff() == IntegerDomain, "expected integer" );
593        mpz_init( &n );
594        mpz_mul( &n, &_den, &InternalInteger::MPI( c ) );
595        if ( negate )
596            mpz_sub( &n, &n, &_num );
597        else
598            mpz_sub( &n, &_num, &n );
599    }
600    mpz_init_set( &d, &_den );
601    // at this point there is no way that the result is not a true rational
602    if ( deleteObject() ) delete this;
603    return new InternalRational( n, d );
604}
605
606InternalCF* InternalRational::mulcoeff( InternalCF* c )
607{
608    ASSERT( ::is_imm( c ) == INTMARK || ! ::is_imm( c ), "expected integer" );
609    MP_INT n, d, g;
610    if ( ::is_imm( c ) )
611    {
612        int cc = imm2int( c );
613        if ( cc == 0 )
614        {
615            if ( deleteObject() ) delete this;
616            return CFFactory::basic( 0 );
617        }
618        mpz_init_set_si( &n, cc );
619    }
620    else
621    {
622        ASSERT( c->levelcoeff() == IntegerDomain, "expected integer" );
623        mpz_init_set( &n, &InternalInteger::MPI( c ) );
624    }
625    mpz_init( &g );
626    mpz_gcd( &g, &n, &_den );
627    if ( mpz_cmp_si( &g, 1 ) == 0 )
628    {
629        mpz_mul( &n, &n, &_num );
630        mpz_init_set( &d, &_den );
631    }
632    else
633    {
634        mpz_fdiv_q( &n, &n, &g );
635        mpz_mul( &n, &n, &_num );
636        mpz_init( &d );
637        mpz_fdiv_q( &d, &_den, &g );
638    }
639    mpz_clear( &g );
640    if ( deleteObject() ) delete this;
641    if ( mpz_cmp_si( &d, 1 ) == 0 )
642    {
643        mpz_clear( &d );
644        if ( mpz_is_imm( &n ) )
645        {
646            InternalCF * res = int2imm( mpz_get_si( &n ) );
647            mpz_clear( &n );
648            return res;
649        }
650        else
651        {
652            return new InternalInteger( n );
653        }
654    }
655    else
656        return new InternalRational( n, d );
657}
658
659InternalCF* InternalRational::dividecoeff( InternalCF* c, bool invert )
660{
661    ASSERT( ::is_imm( c ) == INTMARK || ! ::is_imm( c ), "expected integer" );
662    MP_INT n, d, g;
663    if ( ::is_imm( c ) )
664    {
665        int cc = imm2int( c );
666        ASSERT( c != 0 || invert, "divide by zero" );
667        if ( cc == 0 )
668        {
669            // => invert
670            if ( deleteObject() ) delete this;
671            return CFFactory::basic( 0 );
672        }
673        if ( invert )
674        {
675            mpz_init_set_si( &n, cc );
676            mpz_mul( &n, &n, &_den );
677            mpz_init_set( &d, &_num );
678        }
679        else
680        {
681            mpz_init_set_si( &d, cc );
682            mpz_mul( &d, &d, &_den );
683            mpz_init_set( &n, &_num );
684        }
685    }
686    else
687    {
688        ASSERT( c->levelcoeff() == IntegerDomain, "expected integer" );
689        if ( invert )
690        {
691            mpz_init_set( &n, &InternalInteger::MPI( c ) );
692            mpz_mul( &n, &n, &_den );
693            mpz_init_set( &d, &_num );
694        }
695        else
696        {
697            mpz_init_set( &d, &InternalInteger::MPI( c ) );
698            mpz_mul( &d, &d, &_den );
699            mpz_init_set( &n, &_num );
700        }
701    }
702    if ( mpz_cmp_si( &d, 0 ) < 0 )
703    {
704        mpz_neg( &d, &d );
705        mpz_neg( &n, &n );
706    }
707    mpz_init( &g );
708    mpz_gcd( &g, &n, &d );
709    if ( mpz_cmp_si( &g, 1 ) != 0 )
710    {
711        mpz_fdiv_q( &d, &d, &g );
712        mpz_fdiv_q( &n, &n, &g );
713    }
714    mpz_clear( &g );
715    if ( deleteObject() ) delete this;
716    if ( ! invert )
717    {
718        // then there was no way for the result to become an integer
719        return new InternalRational( n, d );
720    }
721    if ( mpz_cmp_si( &d, 1 ) == 0 )
722    {
723        mpz_clear( &d );
724        if ( mpz_is_imm( &n ) )
725        {
726            InternalCF * res = int2imm( mpz_get_si( &n ) );
727            mpz_clear( &n );
728            return res;
729        }
730        else
731        {
732            return new InternalInteger( n );
733        }
734    }
735    else
736        return new InternalRational( n, d );
737}
738
739InternalCF* InternalRational::divcoeff( InternalCF* c, bool invert )
740{
741    return dividecoeff( c, invert );
742}
743
744InternalCF* InternalRational::modulocoeff( InternalCF* c, bool invert )
745{
746    return modcoeff( c, invert );
747}
748
749InternalCF* InternalRational::modcoeff( InternalCF* c, bool invert )
750{
751    ASSERT( ::is_imm( c ) == INTMARK || ! ::is_imm( c ), "integer expected" );
752    ASSERT( invert || ! ::is_imm( c ) || imm2int( c ) != 0, "divide by zero" );
753    if ( deleteObject() ) delete this;
754    return CFFactory::basic( 0 );
755}
756
757void InternalRational::divremcoeff( InternalCF* c, InternalCF*& quot, InternalCF*& rem, bool invert )
758{
759    quot = copyObject();
760    quot = quot->dividecoeff( c, invert );
761    rem = CFFactory::basic( 0 );
762}
763
764bool InternalRational::divremcoefft( InternalCF* c, InternalCF*& quot, InternalCF*& rem, bool invert )
765{
766    divremcoeff( c, quot, rem, invert );
767    return true;
768}
769
770//{{{ InternalCF * InternalRational::bgcdsame, bgcdcoeff ( const InternalCF * const )
771// docu: see CanonicalForm::bgcd()
772InternalCF *
773InternalRational::bgcdsame ( const InternalCF * const ) const
774{
775    return int2imm( 1 );
776}
777
778InternalCF *
779InternalRational::bgcdcoeff ( const InternalCF * const )
780{
781    return int2imm( 1 );
782}
783//}}}
784
785//{{{ InternalCF * InternalRational::bextgcdsame ( InternalCF * c, CanonicalForm & a, CanonicalForm & b )
786// docu: see CanonicalForm::bextgcd()
787InternalCF *
788InternalRational::bextgcdsame ( InternalCF *, CanonicalForm & a, CanonicalForm & b )
789{
790    a = 1/CanonicalForm( copyObject() ); b = 0;
791    return int2imm( 1 );
792}
793
794InternalCF *
795InternalRational::bextgcdcoeff ( InternalCF *, CanonicalForm & a, CanonicalForm & b )
796{
797    a = 1/CanonicalForm( copyObject() ); b = 0;
798    return int2imm( 1 );
799}
800//}}}
801
802InternalCF * InternalRational::normalize_myself()
803{
804    ASSERT( getRefCount() == 1, "illegal operation" );
805    MP_INT g;
806    mpz_init( &g );
807    mpz_gcd( &g, &_num, &_den );
808    if ( mpz_cmp_si( &g, 1 ) != 0 )
809    {
810        mpz_fdiv_q( &_num, &_num, &g );
811        mpz_fdiv_q( &_den, &_den, &g );
812    }
813    // Hier brauchen wir ein mpz_clear, J.M.
814    mpz_clear( &g );
815    if ( mpz_cmp_si( &_den, 0 ) < 0 )
816    {
817        mpz_neg( &_num, &_num );
818        mpz_neg( &_den, &_den );
819    }
820    if ( mpz_cmp_si( &_den, 1 ) == 0 )
821    {
822        if ( mpz_is_imm( &_num ) )
823        {
824            InternalCF * res = int2imm( mpz_get_si( &_num ) );
825            delete this;
826            return res;
827        }
828        else
829        {
830            MP_INT res;
831            mpz_init_set( &res, &_num );
832            delete this;
833            return new InternalInteger( res );
834        }
835    }
836    else
837        return this;
838}
839
840
841int InternalRational::intval() const
842{
843    ASSERT( mpz_cmp_si( &_den, 1 ) == 0, "illegal operation" );
844    return (int)mpz_get_si( &_num );
845}
846
847//{{{ int InternalRational::sign () const
848// docu: see CanonicalForm::sign()
849int
850InternalRational::sign () const
851{
852    return mpz_sgn( &_num );
853}
854//}}}
Note: See TracBrowser for help on using the repository browser.