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

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