source: git/factory/int_rat.cc @ e4fe2b

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