source: git/factory/int_rat.cc @ d8a7da

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