source: git/factory/int_rat.cc @ ac8e1a

spielwiese
Last change on this file since ac8e1a was ac8e1a, checked in by Martin Lee <martinlee84@…>, 13 years ago
compiler warnings git-svn-id: file:///usr/local/Singular/svn/trunk@14267 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 21.2 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        {
560            if ( negate )
561            {
562                if ( getRefCount() == 1 )
563                {
564                    mpz_neg( &_num, &_num );
565                    return this;
566                }
567                else
568                {
569                    decRefCount();
570                    mpz_init_set( &d, &_den );
571                    mpz_init_set( &n, &_num );
572                    mpz_neg( &n, &n );
573                    return new InternalRational( n, d );
574                }
575            }
576            else
577                return this;
578        }
579        mpz_init( &n );
580        if ( cc < 0 )
581        {
582            mpz_mul_ui( &n, &_den, -cc );
583            mpz_neg( &n, &n );
584        }
585        else
586            mpz_mul_ui( &n, &_den, cc );
587        if ( negate )
588            mpz_sub( &n, &n, &_num );
589        else
590            mpz_sub( &n, &_num, &n );
591    }
592    else
593    {
594        ASSERT( c->levelcoeff() == IntegerDomain, "expected integer" );
595        mpz_init( &n );
596        mpz_mul( &n, &_den, &InternalInteger::MPI( c ) );
597        if ( negate )
598            mpz_sub( &n, &n, &_num );
599        else
600            mpz_sub( &n, &_num, &n );
601    }
602    mpz_init_set( &d, &_den );
603    // at this point there is no way that the result is not a true rational
604    if ( deleteObject() ) delete this;
605    return new InternalRational( n, d );
606}
607
608InternalCF* InternalRational::mulcoeff( InternalCF* c )
609{
610    ASSERT( ::is_imm( c ) == INTMARK || ! ::is_imm( c ), "expected integer" );
611    MP_INT n, d, g;
612    if ( ::is_imm( c ) )
613    {
614        int cc = imm2int( c );
615        if ( cc == 0 )
616        {
617            if ( deleteObject() ) delete this;
618            return CFFactory::basic( 0 );
619        }
620        mpz_init_set_si( &n, cc );
621    }
622    else
623    {
624        ASSERT( c->levelcoeff() == IntegerDomain, "expected integer" );
625        mpz_init_set( &n, &InternalInteger::MPI( c ) );
626    }
627    mpz_init( &g );
628    mpz_gcd( &g, &n, &_den );
629    if ( mpz_cmp_si( &g, 1 ) == 0 )
630    {
631        mpz_mul( &n, &n, &_num );
632        mpz_init_set( &d, &_den );
633    }
634    else
635    {
636        mpz_fdiv_q( &n, &n, &g );
637        mpz_mul( &n, &n, &_num );
638        mpz_init( &d );
639        mpz_fdiv_q( &d, &_den, &g );
640    }
641    mpz_clear( &g );
642    if ( deleteObject() ) delete this;
643    if ( mpz_cmp_si( &d, 1 ) == 0 )
644    {
645        mpz_clear( &d );
646        if ( mpz_is_imm( &n ) )
647        {
648            InternalCF * res = int2imm( mpz_get_si( &n ) );
649            mpz_clear( &n );
650            return res;
651        }
652        else
653        {
654            return new InternalInteger( n );
655        }
656    }
657    else
658        return new InternalRational( n, d );
659}
660
661InternalCF* InternalRational::dividecoeff( InternalCF* c, bool invert )
662{
663    ASSERT( ::is_imm( c ) == INTMARK || ! ::is_imm( c ), "expected integer" );
664    MP_INT n, d, g;
665    if ( ::is_imm( c ) )
666    {
667        int cc = imm2int( c );
668        ASSERT( c != 0 || invert, "divide by zero" );
669        if ( cc == 0 )
670        {
671            // => invert
672            if ( deleteObject() ) delete this;
673            return CFFactory::basic( 0 );
674        }
675        if ( invert )
676        {
677            mpz_init_set_si( &n, cc );
678            mpz_mul( &n, &n, &_den );
679            mpz_init_set( &d, &_num );
680        }
681        else
682        {
683            mpz_init_set_si( &d, cc );
684            mpz_mul( &d, &d, &_den );
685            mpz_init_set( &n, &_num );
686        }
687    }
688    else
689    {
690        ASSERT( c->levelcoeff() == IntegerDomain, "expected integer" );
691        if ( invert )
692        {
693            mpz_init_set( &n, &InternalInteger::MPI( c ) );
694            mpz_mul( &n, &n, &_den );
695            mpz_init_set( &d, &_num );
696        }
697        else
698        {
699            mpz_init_set( &d, &InternalInteger::MPI( c ) );
700            mpz_mul( &d, &d, &_den );
701            mpz_init_set( &n, &_num );
702        }
703    }
704    if ( mpz_cmp_si( &d, 0 ) < 0 )
705    {
706        mpz_neg( &d, &d );
707        mpz_neg( &n, &n );
708    }
709    mpz_init( &g );
710    mpz_gcd( &g, &n, &d );
711    if ( mpz_cmp_si( &g, 1 ) != 0 )
712    {
713        mpz_fdiv_q( &d, &d, &g );
714        mpz_fdiv_q( &n, &n, &g );
715    }
716    mpz_clear( &g );
717    if ( deleteObject() ) delete this;
718    if ( ! invert )
719    {
720        // then there was no way for the result to become an integer
721        return new InternalRational( n, d );
722    }
723    if ( mpz_cmp_si( &d, 1 ) == 0 )
724    {
725        mpz_clear( &d );
726        if ( mpz_is_imm( &n ) )
727        {
728            InternalCF * res = int2imm( mpz_get_si( &n ) );
729            mpz_clear( &n );
730            return res;
731        }
732        else
733        {
734            return new InternalInteger( n );
735        }
736    }
737    else
738        return new InternalRational( n, d );
739}
740
741InternalCF* InternalRational::divcoeff( InternalCF* c, bool invert )
742{
743    return dividecoeff( c, invert );
744}
745
746InternalCF* InternalRational::modulocoeff( InternalCF* c, bool invert )
747{
748    return modcoeff( c, invert );
749}
750
751InternalCF* InternalRational::modcoeff( InternalCF* c, bool invert )
752{
753    ASSERT( ::is_imm( c ) == INTMARK || ! ::is_imm( c ), "integer expected" );
754    ASSERT( invert || ! ::is_imm( c ) || imm2int( c ) != 0, "divide by zero" );
755    if ( deleteObject() ) delete this;
756    return CFFactory::basic( 0 );
757}
758
759void InternalRational::divremcoeff( InternalCF* c, InternalCF*& quot, InternalCF*& rem, bool invert )
760{
761    quot = copyObject();
762    quot = quot->dividecoeff( c, invert );
763    rem = CFFactory::basic( 0 );
764}
765
766bool InternalRational::divremcoefft( InternalCF* c, InternalCF*& quot, InternalCF*& rem, bool invert )
767{
768    divremcoeff( c, quot, rem, invert );
769    return true;
770}
771
772//{{{ InternalCF * InternalRational::bgcdsame, bgcdcoeff ( const InternalCF * const )
773// docu: see CanonicalForm::bgcd()
774InternalCF *
775InternalRational::bgcdsame ( const InternalCF * const ) const
776{
777    return int2imm( 1 );
778}
779
780InternalCF *
781InternalRational::bgcdcoeff ( const InternalCF * const )
782{
783    return int2imm( 1 );
784}
785//}}}
786
787//{{{ InternalCF * InternalRational::bextgcdsame ( InternalCF * c, CanonicalForm & a, CanonicalForm & b )
788// docu: see CanonicalForm::bextgcd()
789InternalCF *
790InternalRational::bextgcdsame ( InternalCF *, CanonicalForm & a, CanonicalForm & b )
791{
792    a = 1/CanonicalForm( copyObject() ); b = 0;
793    return int2imm( 1 );
794}
795
796InternalCF *
797InternalRational::bextgcdcoeff ( InternalCF *, CanonicalForm & a, CanonicalForm & b )
798{
799    a = 1/CanonicalForm( copyObject() ); b = 0;
800    return int2imm( 1 );
801}
802//}}}
803
804InternalCF * InternalRational::normalize_myself()
805{
806    ASSERT( getRefCount() == 1, "illegal operation" );
807    MP_INT g;
808    mpz_init( &g );
809    mpz_gcd( &g, &_num, &_den );
810    if ( mpz_cmp_si( &g, 1 ) != 0 )
811    {
812        mpz_fdiv_q( &_num, &_num, &g );
813        mpz_fdiv_q( &_den, &_den, &g );
814    }
815    // Hier brauchen wir ein mpz_clear, J.M.
816    mpz_clear( &g );
817    if ( mpz_cmp_si( &_den, 0 ) < 0 )
818    {
819        mpz_neg( &_num, &_num );
820        mpz_neg( &_den, &_den );
821    }
822    if ( mpz_cmp_si( &_den, 1 ) == 0 )
823    {
824        if ( mpz_is_imm( &_num ) )
825        {
826            InternalCF * res = int2imm( mpz_get_si( &_num ) );
827            delete this;
828            return res;
829        }
830        else
831        {
832            MP_INT res;
833            mpz_init_set( &res, &_num );
834            delete this;
835            return new InternalInteger( res );
836        }
837    }
838    else
839        return this;
840}
841
842
843int InternalRational::intval() const
844{
845    ASSERT( mpz_cmp_si( &_den, 1 ) == 0, "illegal operation" );
846    return (int)mpz_get_si( &_num );
847}
848
849//{{{ int InternalRational::sign () const
850// docu: see CanonicalForm::sign()
851int
852InternalRational::sign () const
853{
854    return mpz_sgn( &_num );
855}
856//}}}
Note: See TracBrowser for help on using the repository browser.