source: git/factory/int_rat.cc @ a52291

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