source: git/factory/int_rat.cc @ 96ce32

spielwiese
Last change on this file since 96ce32 was ef4ae2, checked in by Hans Schoenemann <hannes@…>, 4 years ago
opt: factory (mpz_init, is_imm, moved tests out of loops(addTermList) etc
  • Property mode set to 100644
File size: 21.4 KB
Line 
1/* emacs edit mode for this file is -*- C++ -*- */
2
3
4#include "config.h"
5
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/**
176 * @sa CanonicalForm::num(), CanonicalForm::den(), InternalRational::den()
177**/
178InternalCF * InternalRational::num ()
179{
180    if ( mpz_is_imm( _num ) )
181    {
182        InternalCF * res = int2imm( mpz_get_si( _num ) );
183        return res;
184    }
185    else
186    {
187        mpz_t dummy;
188        mpz_init_set( dummy, _num );
189        return new InternalInteger( dummy );
190    }
191}
192
193/**
194 * @sa CanonicalForm::num(), CanonicalForm::den(), InternalRational::num()
195**/
196InternalCF * InternalRational::den ()
197{
198    if ( mpz_is_imm( _den ) )
199    {
200        InternalCF * res = int2imm( mpz_get_si( _den ) );
201        return res;
202    }
203    else
204    {
205        mpz_t dummy;
206        mpz_init_set( dummy, _den );
207        return new InternalInteger( dummy );
208    }
209}
210
211/** InternalCF * InternalRational::neg ()
212 * @sa CanonicalForm::operator -()
213**/
214InternalCF *
215InternalRational::neg ()
216{
217    if ( getRefCount() > 1 )
218    {
219        decRefCount();
220        mpz_t dummy_num;
221        mpz_t dummy_den;
222        mpz_init_set( dummy_num, _num );
223        mpz_init_set( dummy_den, _den );
224        mpz_neg( dummy_num, dummy_num );
225        return new InternalRational( dummy_num, dummy_den );
226    }
227    else
228    {
229        mpz_neg( _num, _num );
230        return this;
231    }
232}
233
234InternalCF* InternalRational::addsame( InternalCF * c )
235{
236    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == RationalDomain, "illegal domain" );
237    mpz_t n, d, g;
238
239    mpz_init( g ); mpz_init( n ); mpz_init( d );
240    mpz_gcd( g, _den, MPQDEN( c ) );
241
242    if ( mpz_cmp_si( g, 1 ) == 0 )
243    {
244      mpz_mul( n, _den, MPQNUM( c ) );
245      mpz_mul( g, _num, MPQDEN( c ) );
246      mpz_add( n, n, g );
247      mpz_mul( d, _den, MPQDEN( c ) );
248    }
249    else
250    {
251      mpz_t tmp1;
252      mpz_t tmp2;
253      mpz_init( tmp1 );
254      mpz_divexact( tmp1, _den, g );
255      mpz_init( tmp2 );
256      mpz_divexact( tmp2, MPQDEN( c ), g );
257      mpz_mul( d, tmp2, _den );
258      mpz_mul( tmp2, tmp2, _num );
259      mpz_mul( tmp1, tmp1, MPQNUM( c ) );
260      mpz_add( n, tmp1, tmp2 );
261      mpz_gcd( g, n, d );
262      if ( mpz_cmp_si( g, 1 ) != 0 )
263      {
264          mpz_divexact( n, n, g );
265          mpz_divexact( 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    {
274      mpz_clear( d );
275      if ( mpz_is_imm( n ) )
276      {
277          InternalCF * res = int2imm( mpz_get_si( n ) );
278          mpz_clear( n );
279          return res;
280      }
281      else
282      {
283          return new InternalInteger( n );
284      }
285    }
286    else
287    {
288      return new InternalRational( n, d );
289    }
290}
291
292InternalCF* InternalRational::subsame( InternalCF * c )
293{
294    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == RationalDomain, "illegal domain" );
295    mpz_t n, d, g;
296
297    mpz_init( g ); mpz_init( n ); mpz_init( d );
298    mpz_gcd( g, _den, MPQDEN( c ) );
299
300    if ( mpz_cmp_si( g, 1 ) == 0 )
301    {
302        mpz_mul( n, _den, MPQNUM( c ) );
303        mpz_mul( g, _num, MPQDEN( c ) );
304        mpz_sub( n, g, n );
305        mpz_mul( d, _den, MPQDEN( c ) );
306    }
307    else
308    {
309        mpz_t tmp1;
310        mpz_t tmp2;
311        mpz_init( tmp1 );
312        mpz_divexact( tmp1, _den, g );
313        mpz_init( tmp2 );
314        mpz_divexact( tmp2, MPQDEN( c ), g );
315        mpz_mul( d, tmp2, _den );
316        mpz_mul( tmp2, tmp2, _num );
317        mpz_mul( tmp1, tmp1, MPQNUM( c ) );
318        mpz_sub( n, tmp2, tmp1 );
319        mpz_gcd( g, n, d );
320        if ( mpz_cmp_si( g, 1 ) != 0 )
321        {
322            mpz_divexact( n, n, g );
323            mpz_divexact( d, d, g );
324        }
325        mpz_clear( tmp1 );
326        mpz_clear( tmp2 );
327    }
328    mpz_clear( g );
329    if ( deleteObject() ) delete this;
330    if ( mpz_cmp_si( d, 1 ) == 0 )
331    {
332        mpz_clear( d );
333        if ( mpz_is_imm( n ) )
334        {
335            InternalCF * res = int2imm( mpz_get_si( n ) );
336            mpz_clear( n );
337            return res;
338        }
339        else
340        {
341            return new InternalInteger( n );
342        }
343    }
344    else
345        return new InternalRational( n, d );
346}
347
348InternalCF* InternalRational::mulsame( InternalCF * c )
349{
350    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == RationalDomain, "illegal domain" );
351    mpz_t n, d;
352    mpz_init( n ); mpz_init( d );
353
354    if ( this == c )
355    {
356        mpz_mul( n, _num, _num );
357        mpz_mul( d, _den, _den );
358    }
359    else
360    {
361        mpz_t g1, g2, tmp1, tmp2;
362        mpz_init( g1 ); mpz_init( g2 );
363        mpz_gcd( g1, _num, MPQDEN( c ) );
364        mpz_gcd( g2, _den, MPQNUM( c ) );
365        bool g1is1 = mpz_cmp_si( g1, 1 ) == 0;
366        bool g2is1 = mpz_cmp_si( g2, 1 ) == 0;
367        mpz_init( tmp1 ); mpz_init( tmp2 );
368        if ( ! g1is1 )
369            mpz_divexact( tmp1, _num, g1 );
370        else
371            mpz_set( tmp1, _num );
372        if ( ! g2is1 )
373            mpz_divexact( tmp2, MPQNUM( c ), g2 );
374        else
375            mpz_set( tmp2, MPQNUM( c ) );
376        mpz_mul( n, tmp1, tmp2 );
377        if ( ! g1is1 )
378            mpz_divexact( tmp1, MPQDEN( c ), g1 );
379        else
380            mpz_set( tmp1, MPQDEN( c ) );
381        if ( ! g2is1 )
382            mpz_divexact( tmp2, _den, g2 );
383        else
384            mpz_set( tmp2, _den );
385        mpz_mul( d, tmp1, tmp2 );
386        mpz_clear( tmp1 ); mpz_clear( tmp2 );
387        mpz_clear( g1 ); mpz_clear( g2 );
388    }
389    if ( deleteObject() ) delete this;
390    if ( mpz_cmp_si( d, 1 ) == 0 )
391    {
392        mpz_clear( d );
393        if ( mpz_is_imm( n ) )
394        {
395            InternalCF * res = int2imm( mpz_get_si( n ) );
396            mpz_clear( n );
397            return res;
398        }
399        else
400        {
401            return new InternalInteger( n );
402        }
403    }
404    else
405        return new InternalRational( n, d );
406}
407
408InternalCF* InternalRational::dividesame( InternalCF * c )
409{
410    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == RationalDomain, "illegal domain" );
411
412    if ( this == c )
413    {
414        if ( deleteObject() ) delete this;
415        return CFFactory::basic( 1 );
416    }
417    else
418    {
419        mpz_t n, d;
420        mpz_t g1, g2, tmp1, tmp2;
421        mpz_init( n ); mpz_init( d );
422        mpz_init( g1 ); mpz_init( g2 );
423        mpz_gcd( g1, _num, MPQNUM( c ) );
424        mpz_gcd( g2, _den, MPQDEN( c ) );
425        bool g1is1 = mpz_cmp_si( g1, 1 ) == 0;
426        bool g2is1 = mpz_cmp_si( g2, 1 ) == 0;
427        mpz_init( tmp1 ); mpz_init( tmp2 );
428        if ( ! g1is1 )
429            mpz_divexact( tmp1, _num, g1 );
430        else
431            mpz_set( tmp1, _num );
432        if ( ! g2is1 )
433            mpz_divexact( tmp2, MPQDEN( c ), g2 );
434        else
435            mpz_set( tmp2, MPQDEN( c ) );
436        mpz_mul( n, tmp1, tmp2 );
437        if ( ! g1is1 )
438            mpz_divexact( tmp1, MPQNUM( c ), g1 );
439        else
440            mpz_set( tmp1, MPQNUM( c ) );
441        if ( ! g2is1 )
442            mpz_divexact( tmp2, _den, g2 );
443        else
444            mpz_set( tmp2, _den );
445        mpz_mul( d, tmp1, tmp2 );
446        mpz_clear( tmp1 ); mpz_clear( tmp2 );
447        mpz_clear( g1 ); mpz_clear( g2 );
448        if ( deleteObject() ) delete this;
449        if ( mpz_cmp_si( d, 0 ) < 0 )
450        {
451            mpz_neg( d, d );
452            mpz_neg( n, n );
453        }
454        if ( mpz_cmp_si( d, 1 ) == 0 )
455        {
456            mpz_clear( d );
457            if ( mpz_is_imm( n ) )
458            {
459                InternalCF * res = int2imm( mpz_get_si( n ) );
460                mpz_clear( n );
461                return res;
462            }
463            else
464            {
465                return new InternalInteger( n );
466            }
467        }
468        else
469            return new InternalRational( n, d );
470    }
471}
472
473InternalCF* InternalRational::divsame( InternalCF * c )
474{
475    return dividesame( c );
476}
477
478InternalCF* InternalRational::modulosame( InternalCF * c )
479{
480    return modsame( c );
481}
482
483InternalCF* InternalRational::modsame( InternalCF * )
484{
485    if ( deleteObject() ) delete this;
486    return CFFactory::basic( 0 );
487}
488
489void InternalRational::divremsame( InternalCF * c, InternalCF*& quot, InternalCF*& rem )
490{
491    quot = copyObject();
492    quot = quot->dividesame( c );
493    rem = CFFactory::basic( 0 );
494}
495
496bool InternalRational::divremsamet( InternalCF* c, InternalCF*& quot, InternalCF*& rem )
497{
498    divremsame( c, quot, rem );
499    return true;
500}
501
502/**
503 * comparesame(), comparecoeff() - compare with an
504 *   InternalRational.
505 *
506 * comparesame() compares the CO=a/b and c=p/q using the
507 * equivalence a/b < p/q iff a*q < p*b.
508 *
509 * Note: 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
528/**
529 * comparecoeff() compares the CO=a/b and the integer c using the
530 * equivalence a/b < c iff a < c*b.
531 *
532 * Note: May be relatively expensive due to the
533 * multiplications.
534**/
535int
536InternalRational::comparecoeff ( InternalCF* c )
537{
538    if ( ::is_imm( c ) )
539    {
540        ASSERT( ::is_imm( c ) == INTMARK, "incompatible base coefficients" );
541        mpz_t dummy;
542        mpz_init_set_si( dummy, imm2int( c ) );
543        mpz_mul( dummy, dummy, _den );
544        int result = mpz_cmp( _num, dummy );
545        mpz_clear( dummy );
546        return result;
547    }
548    else
549    {
550        ASSERT( c->levelcoeff() == IntegerDomain, "incompatible base coefficients" );
551        mpz_t dummy;
552        mpz_init( dummy );
553        mpz_mul( dummy, _den, InternalInteger::MPI( c ) );
554        int result = mpz_cmp( _num, dummy );
555        mpz_clear( dummy );
556        return result;
557    }
558}
559
560InternalCF* InternalRational::addcoeff( InternalCF* c )
561{
562    ASSERT( ::is_imm( c ) == INTMARK || ! ::is_imm( c ), "expected integer" );
563    mpz_t n, d;
564    if ( ::is_imm( c ) )
565    {
566        long cc = imm2int( c );
567        if ( cc == 0 )
568            return this;
569        else
570        {
571          mpz_init( n );
572          if ( cc < 0 )
573          {
574            mpz_mul_ui( n, _den, -cc );
575            mpz_sub( n, _num, n );
576          }
577          else
578          {
579            mpz_mul_ui( n, _den, cc );
580            mpz_add( n, _num, n );
581          }
582        }
583    }
584    else
585    {
586        ASSERT( c->levelcoeff() == IntegerDomain, "expected integer" );
587        mpz_init( n );
588        mpz_mul( n, _den, InternalInteger::MPI( c ) );
589        mpz_add( n, _num, n );
590    }
591    mpz_init_set( d, _den );
592    // at this point there is no way that the result is not a true rational
593    if ( deleteObject() ) delete this;
594    return new InternalRational( n, d );
595}
596
597InternalCF* InternalRational::subcoeff( InternalCF* c, bool negate )
598{
599    ASSERT( ::is_imm( c ) == INTMARK || ! ::is_imm( c ), "expected integer" );
600    mpz_t n, d;
601    if ( ::is_imm( c ) )
602    {
603        long cc = imm2int( c );
604        if ( cc == 0 )
605        {
606            if ( negate )
607            {
608                if ( getRefCount() == 1 )
609                {
610                    mpz_neg( _num, _num );
611                    return this;
612                }
613                else
614                {
615                    decRefCount();
616                    mpz_init_set( d, _den );
617                    mpz_init_set( n, _num );
618                    mpz_neg( n, n );
619                    return new InternalRational( n, d );
620                }
621            }
622            else
623                return this;
624        }
625        mpz_init( n );
626        if ( cc < 0 )
627        {
628            mpz_mul_ui( n, _den, -cc );
629            mpz_neg( n, n );
630        }
631        else
632            mpz_mul_ui( n, _den, cc );
633        if ( negate )
634            mpz_sub( n, n, _num );
635        else
636            mpz_sub( n, _num, n );
637    }
638    else
639    {
640        ASSERT( c->levelcoeff() == IntegerDomain, "expected integer" );
641        mpz_init( n );
642        mpz_mul( n, _den, InternalInteger::MPI( c ) );
643        if ( negate )
644            mpz_sub( n, n, _num );
645        else
646            mpz_sub( n, _num, n );
647    }
648    mpz_init_set( d, _den );
649    // at this point there is no way that the result is not a true rational
650    if ( deleteObject() ) delete this;
651    return new InternalRational( n, d );
652}
653
654InternalCF* InternalRational::mulcoeff( InternalCF* c )
655{
656    ASSERT( ::is_imm( c ) == INTMARK || ! ::is_imm( c ), "expected integer" );
657    mpz_t n, d, g;
658    if ( ::is_imm( c ) )
659    {
660        long cc = imm2int( c );
661        if ( cc == 0 )
662        {
663            if ( deleteObject() ) delete this;
664            return CFFactory::basic( 0 );
665        }
666        mpz_init_set_si( n, cc );
667    }
668    else
669    {
670        ASSERT( c->levelcoeff() == IntegerDomain, "expected integer" );
671        mpz_init_set( n, InternalInteger::MPI( c ) );
672    }
673    mpz_init( g );
674    mpz_gcd( g, n, _den );
675    if ( mpz_cmp_si( g, 1 ) == 0 )
676    {
677        mpz_mul( n, n, _num );
678        mpz_init_set( d, _den );
679    }
680    else
681    {
682        mpz_divexact( n, n, g );
683        mpz_mul( n, n, _num );
684        mpz_init( d );
685        mpz_divexact( d, _den, g );
686    }
687    mpz_clear( g );
688    if ( deleteObject() ) delete this;
689    if ( mpz_cmp_si( d, 1 ) == 0 )
690    {
691        mpz_clear( d );
692        if ( mpz_is_imm( n ) )
693        {
694            InternalCF * res = int2imm( mpz_get_si( n ) );
695            mpz_clear( n );
696            return res;
697        }
698        else
699        {
700            return new InternalInteger( n );
701        }
702    }
703    else
704        return new InternalRational( n, d );
705}
706
707InternalCF* InternalRational::dividecoeff( InternalCF* c, bool invert )
708{
709    ASSERT( ::is_imm( c ) == INTMARK || ! ::is_imm( c ), "expected integer" );
710    mpz_t n, d, g;
711    if ( ::is_imm( c ) )
712    {
713        long cc = imm2int( c );
714        ASSERT( c != 0 || invert, "divide by zero" );
715        if ( cc == 0 )
716        {
717            // => invert
718            if ( deleteObject() ) delete this;
719            return CFFactory::basic( 0 );
720        }
721        if ( invert )
722        {
723            mpz_init_set_si( n, cc );
724            mpz_mul( n, n, _den );
725            mpz_init_set( d, _num );
726        }
727        else
728        {
729            mpz_init_set_si( d, cc );
730            mpz_mul( d, d, _den );
731            mpz_init_set( n, _num );
732        }
733    }
734    else
735    {
736        ASSERT( c->levelcoeff() == IntegerDomain, "expected integer" );
737        if ( invert )
738        {
739            mpz_init_set( n, InternalInteger::MPI( c ) );
740            mpz_mul( n, n, _den );
741            mpz_init_set( d, _num );
742        }
743        else
744        {
745            mpz_init_set( d, InternalInteger::MPI( c ) );
746            mpz_mul( d, d, _den );
747            mpz_init_set( n, _num );
748        }
749    }
750    if ( mpz_cmp_si( d, 0 ) < 0 )
751    {
752        mpz_neg( d, d );
753        mpz_neg( n, n );
754    }
755    mpz_init( g );
756    mpz_gcd( g, n, d );
757    if ( mpz_cmp_si( g, 1 ) != 0 )
758    {
759        mpz_divexact( d, d, g );
760        mpz_divexact( n, n, g );
761    }
762    mpz_clear( g );
763    if ( deleteObject() ) delete this;
764    if ( ! invert )
765    {
766        // then there was no way for the result to become an integer
767        return new InternalRational( n, d );
768    }
769    if ( mpz_cmp_si( d, 1 ) == 0 )
770    {
771        mpz_clear( d );
772        if ( mpz_is_imm( n ) )
773        {
774            InternalCF * res = int2imm( mpz_get_si( n ) );
775            mpz_clear( n );
776            return res;
777        }
778        else
779        {
780            return new InternalInteger( n );
781        }
782    }
783    else
784        return new InternalRational( n, d );
785}
786
787InternalCF* InternalRational::divcoeff( InternalCF* c, bool invert )
788{
789    return dividecoeff( c, invert );
790}
791
792InternalCF* InternalRational::modulocoeff( InternalCF* c, bool invert )
793{
794    return modcoeff( c, invert );
795}
796
797InternalCF* InternalRational::modcoeff( InternalCF* c, bool invert )
798{
799    ASSERT( ::is_imm( c ) == INTMARK || ! ::is_imm( c ), "integer expected" );
800    ASSERT( invert || ! ::is_imm( c ) || imm2int( c ) != 0, "divide by zero" );
801    if ( deleteObject() ) delete this;
802    return CFFactory::basic( 0 );
803}
804
805void InternalRational::divremcoeff( InternalCF* c, InternalCF*& quot, InternalCF*& rem, bool invert )
806{
807    quot = copyObject();
808    quot = quot->dividecoeff( c, invert );
809    rem = CFFactory::basic( 0 );
810}
811
812bool InternalRational::divremcoefft( InternalCF* c, InternalCF*& quot, InternalCF*& rem, bool invert )
813{
814    divremcoeff( c, quot, rem, invert );
815    return true;
816}
817
818/**
819 * @sa CanonicalForm::bgcd(), InternalRational::bgcdcoeff()
820**/
821InternalCF *
822InternalRational::bgcdsame ( const InternalCF * const ) const
823{
824    return int2imm( 1 );
825}
826
827/**
828 * @sa CanonicalForm::bgcd(), InternalRational::bgcdsame()
829**/
830InternalCF *
831InternalRational::bgcdcoeff ( const InternalCF * const )
832{
833    return int2imm( 1 );
834}
835
836/**
837 * @sa CanonicalForm::bextgcd(), InternalRational::bextgcdcoeff()
838**/
839InternalCF *
840InternalRational::bextgcdsame ( InternalCF *, CanonicalForm & a, CanonicalForm & b )
841{
842    a = 1/CanonicalForm( copyObject() ); b = 0;
843    return int2imm( 1 );
844}
845
846/**
847 * @sa CanonicalForm::bextgcd(), InternalRational::bextgcdsame()
848**/
849InternalCF *
850InternalRational::bextgcdcoeff ( InternalCF *, CanonicalForm & a, CanonicalForm & b )
851{
852    a = 1/CanonicalForm( copyObject() ); b = 0;
853    return int2imm( 1 );
854}
855
856/**
857 * reduce InternalRational to lowest terms
858**/
859InternalCF * InternalRational::normalize_myself()
860{
861    ASSERT( getRefCount() == 1, "illegal operation" );
862    mpz_t g;
863    mpz_init( g );
864    mpz_gcd( g, _num, _den );
865    if ( mpz_cmp_si( g, 1 ) != 0 )
866    {
867        mpz_divexact( _num, _num, g );
868        mpz_divexact( _den, _den, g );
869    }
870    mpz_clear( g );
871    if ( mpz_cmp_si( _den, 0 ) < 0 )
872    {
873        mpz_neg( _num, _num );
874        mpz_neg( _den, _den );
875    }
876    if ( mpz_cmp_si( _den, 1 ) == 0 )
877    {
878        if ( mpz_is_imm( _num ) )
879        {
880            InternalCF * res = int2imm( mpz_get_si( _num ) );
881            delete this;
882            return res;
883        }
884        else
885        {
886            mpz_t res;
887            mpz_init_set( res, _num );
888            delete this;
889            return new InternalInteger( res );
890        }
891    }
892    else
893        return this;
894}
895
896
897long InternalRational::intval() const
898{
899
900    ASSERT( mpz_cmp_si( _den, 1 ) == 0, "illegal operation" );
901    return mpz_get_si( _num );
902
903}
904
905/**
906 * @sa CanonicalForm::sign()
907**/
908int
909InternalRational::sign () const
910{
911    return mpz_sgn( _num );
912}
Note: See TracBrowser for help on using the repository browser.