source: git/factory/int_rat.cc @ 8710ff0

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