source: git/factory/int_rat.cc @ 07dec4

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