source: git/factory/int_rat.cc @ 718e670

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