source: git/factory/int_rat.cc @ 9f39e6

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