source: git/factory/int_rat.cc @ 1daf0d

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