source: git/factory/int_rat.cc @ 79592ac

spielwiese
Last change on this file since 79592ac was 362fc67, checked in by Martin Lee <martinlee84@…>, 12 years ago
chg: remove $Id$
  • Property mode set to 100644
File size: 20.7 KB
Line 
1/* emacs edit mode for this file is -*- C++ -*- */
2
3#include "config.h"
4
5#include "cf_assert.h"
6
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
22    while ( b != 0 )
23    {
24        c = a % b;
25        a = b;
26        b = c;
27    }
28    return a;
29}
30
31
32InternalRational::InternalRational()
33{
34    mpz_init( _num );
35    mpz_init_set_si( _den, 1 );
36}
37
38InternalRational::InternalRational( const int i )
39{
40    mpz_init_set_si( _num, i );
41    mpz_init_set_si( _den, 1 );
42}
43
44InternalRational::InternalRational( const int n, const int d )
45{
46    ASSERT( d != 0, "divide by zero" );
47    if ( n == 0 )
48    {
49        mpz_init_set_si( _num, 0 );
50        mpz_init_set_si( _den, 1 );
51    }
52    else
53    {
54        int g = intgcd( n, d );
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        }
65    }
66}
67
68InternalRational::InternalRational( const char * )
69{
70    // sollte nicht gebraucht werden !!!
71    ASSERT( 0, "fatal error" );
72    mpz_init( _num );
73    mpz_init( _den );
74}
75
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 )
82{
83    _num[0]=*n;
84    mpz_init_set_si( _den, 1 );
85}
86
87InternalRational::InternalRational( const mpz_ptr n, const mpz_ptr d )
88{
89  _num[0]=*n;
90  _den[0]=*d;
91}
92
93InternalRational::~InternalRational()
94{
95    mpz_clear( _num );
96    mpz_clear( _den );
97}
98
99InternalCF* InternalRational::deepCopyObject() const
100{
101    mpz_t dummy_num;
102    mpz_t dummy_den;
103    mpz_init_set( dummy_num, _num );
104    mpz_init_set( dummy_den, _den );
105    return new InternalRational( dummy_num, dummy_den );
106}
107
108#ifndef NOSTREAMIO
109void InternalRational::print( OSTREAM & os, char * c )
110{
111    char * str = new char[mpz_sizeinbase( _num, 10 ) + 2];
112    str = mpz_get_str( str, 10, _num );
113    os << str << '/';
114    delete [] str;
115    str = new char[mpz_sizeinbase( _den, 10 ) + 2];
116    str = mpz_get_str( str, 10, _den );
117    os << str << c;
118    delete [] str;
119}
120#endif /* NOSTREAMIO */
121
122bool InternalRational::is_imm() const
123{
124    return mpz_cmp_si( _den, 1 ) == 0 && mpz_is_imm( _num );
125}
126
127InternalCF* InternalRational::genZero()
128{
129    if ( isZero() )
130        return copyObject();
131    else
132        return new InternalRational();
133}
134
135InternalCF* InternalRational::genOne()
136{
137    if ( isOne() )
138        return copyObject();
139    else
140        return new InternalRational( 1 );
141}
142
143//{{{ InternalCF * InternalRational::num (), den ()
144// docu: see CanonicalForm::num(), den()
145InternalCF * InternalRational::num ()
146{
147    if ( mpz_is_imm( _num ) )
148    {
149        InternalCF * res = int2imm( mpz_get_si( _num ) );
150        return res;
151    }
152    else
153    {
154        mpz_t dummy;
155        mpz_init_set( dummy, _num );
156        return new InternalInteger( dummy );
157    }
158}
159
160InternalCF * InternalRational::den ()
161{
162    if ( mpz_is_imm( _den ) )
163    {
164        InternalCF * res = int2imm( mpz_get_si( _den ) );
165        return res;
166    }
167    else
168    {
169        mpz_t dummy;
170        mpz_init_set( dummy, _den );
171        return new InternalInteger( dummy );
172    }
173}
174//}}}
175
176//{{{ InternalCF * InternalRational::neg ()
177// docu: see CanonicalForm::operator -()
178InternalCF *
179InternalRational::neg ()
180{
181    if ( getRefCount() > 1 )
182    {
183        decRefCount();
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 );
189        return new InternalRational( dummy_num, dummy_den );
190    }
191    else
192    {
193        mpz_neg( _num, _num );
194        return this;
195    }
196}
197//}}}
198
199InternalCF* InternalRational::addsame( InternalCF * c )
200{
201    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == RationalDomain, "illegal domain" );
202    mpz_t n, d, g;
203
204    mpz_init( g ); mpz_init( n ); mpz_init( d );
205    mpz_gcd( g, _den, MPQDEN( c ) );
206
207    if ( mpz_cmp_si( g, 1 ) == 0 )
208    {
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 ) );
213    }
214    else
215    {
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 )
228      {
229          mpz_divexact( n, n, g );
230          mpz_divexact( d, d, g );
231      }
232      mpz_clear( tmp1 );
233      mpz_clear( tmp2 );
234    }
235    mpz_clear( g );
236    if ( deleteObject() ) delete this;
237    if ( mpz_cmp_si( d, 1 ) == 0 )
238    {
239      mpz_clear( d );
240      if ( mpz_is_imm( n ) )
241      {
242          InternalCF * res = int2imm( mpz_get_si( n ) );
243          mpz_clear( n );
244          return res;
245      }
246      else
247      {
248          return new InternalInteger( n );
249      }
250    }
251    else
252    {
253      return new InternalRational( n, d );
254    }
255}
256
257InternalCF* InternalRational::subsame( InternalCF * c )
258{
259    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == RationalDomain, "illegal domain" );
260    mpz_t n, d, g;
261
262    mpz_init( g ); mpz_init( n ); mpz_init( d );
263    mpz_gcd( g, _den, MPQDEN( c ) );
264
265    if ( mpz_cmp_si( g, 1 ) == 0 )
266    {
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 ) );
271    }
272    else
273    {
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 )
286        {
287            mpz_divexact( n, n, g );
288            mpz_divexact( d, d, g );
289        }
290        mpz_clear( tmp1 );
291        mpz_clear( tmp2 );
292    }
293    mpz_clear( g );
294    if ( deleteObject() ) delete this;
295    if ( mpz_cmp_si( d, 1 ) == 0 )
296    {
297        mpz_clear( d );
298        if ( mpz_is_imm( n ) )
299        {
300            InternalCF * res = int2imm( mpz_get_si( n ) );
301            mpz_clear( n );
302            return res;
303        }
304        else
305        {
306            return new InternalInteger( n );
307        }
308    }
309    else
310        return new InternalRational( n, d );
311}
312
313InternalCF* InternalRational::mulsame( InternalCF * c )
314{
315    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == RationalDomain, "illegal domain" );
316    mpz_t n, d;
317    mpz_init( n ); mpz_init( d );
318
319    if ( this == c )
320    {
321        mpz_mul( n, _num, _num );
322        mpz_mul( d, _den, _den );
323    }
324    else
325    {
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 );
333        if ( ! g1is1 )
334            mpz_divexact( tmp1, _num, g1 );
335        else
336            mpz_set( tmp1, _num );
337        if ( ! g2is1 )
338            mpz_divexact( tmp2, MPQNUM( c ), g2 );
339        else
340            mpz_set( tmp2, MPQNUM( c ) );
341        mpz_mul( n, tmp1, tmp2 );
342        if ( ! g1is1 )
343            mpz_divexact( tmp1, MPQDEN( c ), g1 );
344        else
345            mpz_set( tmp1, MPQDEN( c ) );
346        if ( ! g2is1 )
347            mpz_divexact( tmp2, _den, g2 );
348        else
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 );
353    }
354    if ( deleteObject() ) delete this;
355    if ( mpz_cmp_si( d, 1 ) == 0 )
356    {
357        mpz_clear( d );
358        if ( mpz_is_imm( n ) )
359        {
360            InternalCF * res = int2imm( mpz_get_si( n ) );
361            mpz_clear( n );
362            return res;
363        }
364        else
365        {
366            return new InternalInteger( n );
367        }
368    }
369    else
370        return new InternalRational( n, d );
371}
372
373InternalCF* InternalRational::dividesame( InternalCF * c )
374{
375    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == RationalDomain, "illegal domain" );
376
377    if ( this == c )
378    {
379        if ( deleteObject() ) delete this;
380        return CFFactory::basic( 1 );
381    }
382    else
383    {
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 );
393        if ( ! g1is1 )
394            mpz_divexact( tmp1, _num, g1 );
395        else
396            mpz_set( tmp1, _num );
397        if ( ! g2is1 )
398            mpz_divexact( tmp2, MPQDEN( c ), g2 );
399        else
400            mpz_set( tmp2, MPQDEN( c ) );
401        mpz_mul( n, tmp1, tmp2 );
402        if ( ! g1is1 )
403            mpz_divexact( tmp1, MPQNUM( c ), g1 );
404        else
405            mpz_set( tmp1, MPQNUM( c ) );
406        if ( ! g2is1 )
407            mpz_divexact( tmp2, _den, g2 );
408        else
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 );
413        if ( deleteObject() ) delete this;
414        if ( mpz_cmp_si( d, 0 ) < 0 )
415        {
416            mpz_neg( d, d );
417            mpz_neg( n, n );
418        }
419        if ( mpz_cmp_si( d, 1 ) == 0 )
420        {
421            mpz_clear( d );
422            if ( mpz_is_imm( n ) )
423            {
424                InternalCF * res = int2imm( mpz_get_si( n ) );
425                mpz_clear( n );
426                return res;
427            }
428            else
429            {
430                return new InternalInteger( n );
431            }
432        }
433        else
434            return new InternalRational( n, d );
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
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//
482// See also: CanonicalForm::operator <(), CanonicalForm::operator ==()
483//
484//}}}
485int
486InternalRational::comparesame ( InternalCF * c )
487{
488    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == RationalDomain, "incompatible base coefficients" );
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 );
495    return result;
496}
497
498int
499InternalRational::comparecoeff ( InternalCF* c )
500{
501    if ( ::is_imm( c ) )
502    {
503        ASSERT( ::is_imm( c ) == INTMARK, "incompatible base coefficients" );
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 );
509        return result;
510    }
511    else
512    {
513        ASSERT( c->levelcoeff() == IntegerDomain, "incompatible base coefficients" );
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 );
519        return result;
520    }
521}
522//}}}
523
524InternalCF* InternalRational::addcoeff( InternalCF* c )
525{
526    ASSERT( ::is_imm( c ) == INTMARK || ! ::is_imm( c ), "expected integer" );
527    mpz_t n, d;
528    if ( ::is_imm( c ) )
529    {
530        int cc = imm2int( c );
531        if ( cc == 0 )
532            return this;
533        else
534        {
535          mpz_init( n );
536          if ( cc < 0 )
537          {
538            mpz_mul_ui( n, _den, -cc );
539            mpz_sub( n, _num, n );
540          }
541          else
542          {
543            mpz_mul_ui( n, _den, cc );
544            mpz_add( n, _num, n );
545          }
546        }
547    }
548    else
549    {
550        ASSERT( c->levelcoeff() == IntegerDomain, "expected integer" );
551        mpz_init( n );
552        mpz_mul( n, _den, InternalInteger::MPI( c ) );
553        mpz_add( n, _num, n );
554    }
555    mpz_init_set( d, _den );
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" );
564    mpz_t n, d;
565    if ( ::is_imm( c ) )
566    {
567        int cc = imm2int( c );
568        if ( cc == 0 )
569        {
570            if ( negate )
571            {
572                if ( getRefCount() == 1 )
573                {
574                    mpz_neg( _num, _num );
575                    return this;
576                }
577                else
578                {
579                    decRefCount();
580                    mpz_init_set( d, _den );
581                    mpz_init_set( n, _num );
582                    mpz_neg( n, n );
583                    return new InternalRational( n, d );
584                }
585            }
586            else
587                return this;
588        }
589        mpz_init( n );
590        if ( cc < 0 )
591        {
592            mpz_mul_ui( n, _den, -cc );
593            mpz_neg( n, n );
594        }
595        else
596            mpz_mul_ui( n, _den, cc );
597        if ( negate )
598            mpz_sub( n, n, _num );
599        else
600            mpz_sub( n, _num, n );
601    }
602    else
603    {
604        ASSERT( c->levelcoeff() == IntegerDomain, "expected integer" );
605        mpz_init( n );
606        mpz_mul( n, _den, InternalInteger::MPI( c ) );
607        if ( negate )
608            mpz_sub( n, n, _num );
609        else
610            mpz_sub( n, _num, n );
611    }
612    mpz_init_set( d, _den );
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" );
621    mpz_t n, d, g;
622    if ( ::is_imm( c ) )
623    {
624        int cc = imm2int( c );
625        if ( cc == 0 )
626        {
627            if ( deleteObject() ) delete this;
628            return CFFactory::basic( 0 );
629        }
630        mpz_init_set_si( n, cc );
631    }
632    else
633    {
634        ASSERT( c->levelcoeff() == IntegerDomain, "expected integer" );
635        mpz_init_set( n, InternalInteger::MPI( c ) );
636    }
637    mpz_init( g );
638    mpz_gcd( g, n, _den );
639    if ( mpz_cmp_si( g, 1 ) == 0 )
640    {
641        mpz_mul( n, n, _num );
642        mpz_init_set( d, _den );
643    }
644    else
645    {
646        mpz_divexact( n, n, g );
647        mpz_mul( n, n, _num );
648        mpz_init( d );
649        mpz_divexact( d, _den, g );
650    }
651    mpz_clear( g );
652    if ( deleteObject() ) delete this;
653    if ( mpz_cmp_si( d, 1 ) == 0 )
654    {
655        mpz_clear( d );
656        if ( mpz_is_imm( n ) )
657        {
658            InternalCF * res = int2imm( mpz_get_si( n ) );
659            mpz_clear( n );
660            return res;
661        }
662        else
663        {
664            return new InternalInteger( n );
665        }
666    }
667    else
668        return new InternalRational( n, d );
669}
670
671InternalCF* InternalRational::dividecoeff( InternalCF* c, bool invert )
672{
673    ASSERT( ::is_imm( c ) == INTMARK || ! ::is_imm( c ), "expected integer" );
674    mpz_t n, d, g;
675    if ( ::is_imm( c ) )
676    {
677        int cc = imm2int( c );
678        ASSERT( c != 0 || invert, "divide by zero" );
679        if ( cc == 0 )
680        {
681            // => invert
682            if ( deleteObject() ) delete this;
683            return CFFactory::basic( 0 );
684        }
685        if ( invert )
686        {
687            mpz_init_set_si( n, cc );
688            mpz_mul( n, n, _den );
689            mpz_init_set( d, _num );
690        }
691        else
692        {
693            mpz_init_set_si( d, cc );
694            mpz_mul( d, d, _den );
695            mpz_init_set( n, _num );
696        }
697    }
698    else
699    {
700        ASSERT( c->levelcoeff() == IntegerDomain, "expected integer" );
701        if ( invert )
702        {
703            mpz_init_set( n, InternalInteger::MPI( c ) );
704            mpz_mul( n, n, _den );
705            mpz_init_set( d, _num );
706        }
707        else
708        {
709            mpz_init_set( d, InternalInteger::MPI( c ) );
710            mpz_mul( d, d, _den );
711            mpz_init_set( n, _num );
712        }
713    }
714    if ( mpz_cmp_si( d, 0 ) < 0 )
715    {
716        mpz_neg( d, d );
717        mpz_neg( n, n );
718    }
719    mpz_init( g );
720    mpz_gcd( g, n, d );
721    if ( mpz_cmp_si( g, 1 ) != 0 )
722    {
723        mpz_divexact( d, d, g );
724        mpz_divexact( n, n, g );
725    }
726    mpz_clear( g );
727    if ( deleteObject() ) delete this;
728    if ( ! invert )
729    {
730        // then there was no way for the result to become an integer
731        return new InternalRational( n, d );
732    }
733    if ( mpz_cmp_si( d, 1 ) == 0 )
734    {
735        mpz_clear( d );
736        if ( mpz_is_imm( n ) )
737        {
738            InternalCF * res = int2imm( mpz_get_si( n ) );
739            mpz_clear( n );
740            return res;
741        }
742        else
743        {
744            return new InternalInteger( n );
745        }
746    }
747    else
748        return new InternalRational( n, d );
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
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
814InternalCF * InternalRational::normalize_myself()
815{
816    ASSERT( getRefCount() == 1, "illegal operation" );
817    mpz_t g;
818    mpz_init( g );
819    mpz_gcd( g, _num, _den );
820    if ( mpz_cmp_si( g, 1 ) != 0 )
821    {
822        mpz_divexact( _num, _num, g );
823        mpz_divexact( _den, _den, g );
824    }
825    // Hier brauchen wir ein mpz_clear, J.M.
826    mpz_clear( g );
827    if ( mpz_cmp_si( _den, 0 ) < 0 )
828    {
829        mpz_neg( _num, _num );
830        mpz_neg( _den, _den );
831    }
832    if ( mpz_cmp_si( _den, 1 ) == 0 )
833    {
834        if ( mpz_is_imm( _num ) )
835        {
836            InternalCF * res = int2imm( mpz_get_si( _num ) );
837            delete this;
838            return res;
839        }
840        else
841        {
842            mpz_t res;
843            mpz_init_set( res, _num );
844            delete this;
845            return new InternalInteger( res );
846        }
847    }
848    else
849        return this;
850}
851
852
853int InternalRational::intval() const
854{
855    ASSERT( mpz_cmp_si( _den, 1 ) == 0, "illegal operation" );
856    return (int)mpz_get_si( _num );
857}
858
859//{{{ int InternalRational::sign () const
860// docu: see CanonicalForm::sign()
861int
862InternalRational::sign () const
863{
864    return mpz_sgn( _num );
865}
866//}}}
Note: See TracBrowser for help on using the repository browser.