source: git/factory/int_rat.cc @ 362fc67

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