source: git/factory/int_int.cc @ a52291

spielwiese
Last change on this file since a52291 was a52291, checked in by Martin Lee <martinlee84@…>, 12 years ago
replacing MP_INT by mpz_t Conflicts: factory/cf_factory.h
  • Property mode set to 100644
File size: 13.5 KB
RevLine 
[493c477]1/* emacs edit mode for this file is -*- C++ -*- */
[341696]2/* $Id$ */
[2dd068]3
[e4fe2b]4#include "config.h"
[86aed6]5
[a472b9]6#include "canonicalform.h"
[fc732a9]7#include "imm.h"
[2dd068]8#include "int_int.h"
9#include "int_rat.h"
[fc732a9]10#include "cf_gmp.h"
[2dd068]11#include "gmpext.h"
[54a019]12
[f79b94c]13#ifdef HAVE_OMALLOC
14const omBin InternalInteger::InternalInteger_bin = omGetSpecBin(sizeof(InternalInteger));
15#endif
16
[2dd068]17InternalInteger::InternalInteger()
18{
[a52291]19    mpz_init( thempi );
[2dd068]20}
21
22InternalInteger::InternalInteger( const int i )
23{
[a52291]24    mpz_init_set_si( thempi, i );
[2dd068]25}
26
[a52291]27InternalInteger::InternalInteger( const mpz_ptr mpi) { thempi[0]=*mpi;}
[2dd068]28
[d07137]29InternalInteger::InternalInteger( const char * str, const int base )
[2dd068]30{
[a52291]31    mpz_init_set_str( thempi, str, base );
[2dd068]32}
33
34InternalInteger::~InternalInteger()
35{
[a52291]36    mpz_clear( thempi );
[2dd068]37}
38
39InternalCF* InternalInteger::deepCopyObject() const
40{
[186402]41    mpz_t dummy;
[a52291]42    mpz_init_set( dummy, thempi );
43    return new InternalInteger( dummy );
[2dd068]44}
45
[718e670]46#ifndef NOSTREAMIO
[181148]47void InternalInteger::print( OSTREAM & os, char * c )
[2dd068]48{
[a52291]49    if ( *c == '*' && mpz_cmp_si( thempi, 1 ) == 0 )
[54a019]50        os << c+1;
[a52291]51    else if ( *c == '*' && mpz_cmp_si( thempi, -1 ) == 0 )
[54a019]52        os << '-' << c+1;
[2dd068]53    else {
[a52291]54        char * str = new char[mpz_sizeinbase( thempi, 10 ) + 2];
55        str = mpz_get_str( str, 10, thempi );
[54a019]56        os << str << c;
57        delete [] str;
[2dd068]58    }
59}
[718e670]60#endif /* NOSTREAMIO */
[2dd068]61
62bool InternalInteger::is_imm() const
63{
[a52291]64    return mpz_is_imm( thempi );
[2dd068]65}
66
67InternalCF* InternalInteger::genZero()
68{
69    if ( isZero() )
[54a019]70        return copyObject();
[2dd068]71    else
[54a019]72        return new InternalInteger();
[2dd068]73}
74
75InternalCF* InternalInteger::genOne()
76{
77    if ( isOne() )
[54a019]78        return copyObject();
[2dd068]79    else
[54a019]80        return new InternalInteger( 1 );
[2dd068]81}
82
[f1295f]83//{{{ InternalCF * InternalInteger::neg ()
84// docu: see CanonicalForm::operator -()
85InternalCF *
86InternalInteger::neg ()
[2dd068]87{
[1e6de6]88    if ( getRefCount() > 1 )
89    {
[54a019]90        decRefCount();
[186402]91        mpz_t dummy;
[a52291]92        mpz_init_set( dummy, thempi );
[186402]93        mpz_neg( dummy, dummy );
[a52291]94        return new InternalInteger( dummy );
[1e6de6]95    }
96    else
97    {
[a52291]98        mpz_neg( thempi, thempi );
[54a019]99        return this;
[2dd068]100    }
101}
[f1295f]102//}}}
[2dd068]103
104
105InternalCF* InternalInteger::addsame( InternalCF * c )
106{
[1e6de6]107    if ( getRefCount() > 1 )
108    {
[54a019]109        decRefCount();
[186402]110        mpz_t dummy;
111        mpz_init( dummy );
[a52291]112        mpz_add( dummy, thempi, MPI( c ) );
[186402]113        if ( mpz_is_imm( dummy ) )
[1e6de6]114        {
[186402]115            InternalCF * res = int2imm( mpz_get_si( dummy ) );
116            mpz_clear( dummy );
[54a019]117            return res;
118        }
119        else
[a52291]120            return new InternalInteger( dummy );
[2dd068]121    }
[1e6de6]122    else
123    {
[a52291]124        mpz_add( thempi, thempi, MPI( c ) );
125        if ( mpz_is_imm( thempi ) )
[1e6de6]126        {
[a52291]127            InternalCF * res = int2imm( mpz_get_si( thempi ) );
[54a019]128            delete this;
129            return res;
130        }
131        else
132            return this;
[2dd068]133    }
134}
135
136InternalCF* InternalInteger::subsame( InternalCF * c )
137{
[1e6de6]138    if ( getRefCount() > 1 )
139    {
[54a019]140        decRefCount();
[186402]141        mpz_t dummy;
142        mpz_init( dummy );
[a52291]143        mpz_sub( dummy, thempi, MPI( c ) );
[186402]144        if ( mpz_is_imm( dummy ) )
[1e6de6]145        {
[186402]146            InternalCF * res = int2imm( mpz_get_si( dummy ) );
147            mpz_clear( dummy );
[54a019]148            return res;
149        }
150        else
[a52291]151            return new InternalInteger( dummy );
[2dd068]152    }
[1e6de6]153    else
154    {
[a52291]155        mpz_sub( thempi, thempi, MPI( c ) );
156        if ( mpz_is_imm( thempi ) )
[1e6de6]157        {
[a52291]158            InternalCF * res = int2imm( mpz_get_si( thempi ) );
[54a019]159            delete this;
160            return res;
161        }
162        else
163            return this;
[2dd068]164    }
165}
166
167InternalCF* InternalInteger::mulsame( InternalCF * c )
168{
[1e6de6]169    if ( getRefCount() > 1 )
170    {
[54a019]171        decRefCount();
[186402]172        mpz_t dummy;
173        mpz_init( dummy );
[a52291]174        mpz_mul( dummy, thempi, MPI( c ) );
[f8e5457]175        #if 0
[186402]176        if ( mpz_is_imm( dummy ) )
[1e6de6]177        {
178        // can this happen ???
[186402]179            InternalCF * res = int2imm( mpz_get_si( dummy ) );
180            mpz_clear( dummy );
[54a019]181            return res;
182        }
183        else
[f8e5457]184        #endif
[a52291]185            return new InternalInteger( dummy );
[2dd068]186    }
[1e6de6]187    else
188    {
[a52291]189        mpz_mul( thempi, thempi, MPI( c ) );
[f8e5457]190        #if 0
[1e6de6]191        if ( mpz_is_imm( &thempi ) )
192        {
193        // can this happen ???
[54a019]194            InternalCF * res = int2imm( mpz_get_si( &thempi ) );
195            delete this;
196            return res;
197        }
198        else
[f8e5457]199        #endif
[54a019]200            return this;
[2dd068]201    }
202}
203
[398652]204//{{{ int InternalInteger::comparesame, comparecoeff ( InternalCF * c )
205// docu: see CanonicalForm::operator <(), CanonicalForm::operator ==()
206int
207InternalInteger::comparesame ( InternalCF * c )
208{
209    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == IntegerDomain, "incompatible base coefficients" );
[a52291]210    return mpz_cmp( thempi, MPI( c ) );
[398652]211}
212
213int
214InternalInteger::comparecoeff ( InternalCF * c )
[2dd068]215{
216    ASSERT( ::is_imm( c ) == INTMARK, "incompatible base coefficients" );
[a52291]217    return mpz_cmp_si( thempi, imm2int( c ) );
[2dd068]218}
[398652]219//}}}
[2dd068]220
221InternalCF* InternalInteger::addcoeff( InternalCF* c )
222{
223    ASSERT( ::is_imm( c ) == INTMARK, "incompatible base coefficients" );
224    int cc = imm2int( c );
[1e6de6]225    if ( getRefCount() > 1 )
226    {
[54a019]227        decRefCount();
[186402]228        mpz_t dummy;
229        mpz_init( dummy );
[54a019]230        if ( cc < 0 )
[a52291]231            mpz_sub_ui( dummy, thempi, -cc );
[54a019]232        else
[a52291]233            mpz_add_ui( dummy, thempi, cc );
[186402]234        if ( mpz_is_imm( dummy ) )
[1e6de6]235        {
[186402]236            InternalCF * res = int2imm( mpz_get_si( dummy ) );
237            mpz_clear( dummy );
[54a019]238            return res;
239        }
240        else
[a52291]241            return new InternalInteger( dummy );
[2dd068]242    }
[186402]243    else
244    {
[54a019]245        if ( cc < 0 )
[a52291]246            mpz_sub_ui( thempi, thempi, -cc );
[54a019]247        else
[a52291]248            mpz_add_ui( thempi, thempi, cc );
249        if ( mpz_is_imm( thempi ) )
[f8e5457]250        {
[a52291]251            InternalCF * res = int2imm( mpz_get_si( thempi ) );
[54a019]252            delete this;
253            return res;
254        }
255        else
256            return this;
[2dd068]257    }
258}
259
260InternalCF* InternalInteger::subcoeff( InternalCF* c, bool negate )
261{
262    ASSERT( ::is_imm( c ) == INTMARK, "incompatible base coefficients" );
263    int cc = imm2int( c );
[f8e5457]264    if ( getRefCount() > 1 )
265    {
[54a019]266        decRefCount();
[186402]267        mpz_t dummy;
[f8e5457]268        if ( negate )
269        {
[186402]270            mpz_init_set_si( dummy, cc );
[a52291]271            mpz_sub( dummy, dummy, thempi );
[54a019]272        }
[f8e5457]273        else
274        {
[186402]275            mpz_init( dummy );
[54a019]276            if ( cc < 0 )
[a52291]277                mpz_add_ui( dummy, thempi, -cc );
[54a019]278            else
[a52291]279                mpz_sub_ui( dummy, thempi, cc );
[54a019]280        }
[186402]281        if ( mpz_is_imm( dummy ) )
[f8e5457]282        {
[186402]283            InternalCF * res = int2imm( mpz_get_si( dummy ) );
284            mpz_clear( dummy );
[54a019]285            return res;
286        }
287        else
[a52291]288            return new InternalInteger( dummy );
[2dd068]289    }
[f8e5457]290    else
291    {
292        if ( negate )
293        {
[186402]294            mpz_t dummy;
295            mpz_init_set_si( dummy, cc );
[a52291]296            mpz_sub( thempi, dummy, thempi );
[186402]297            mpz_clear( dummy );
[54a019]298        }
299        else
300            if ( cc < 0 )
[a52291]301                mpz_add_ui( thempi, thempi, -cc );
[54a019]302            else
[a52291]303                mpz_sub_ui( thempi, thempi, cc );
304        if ( mpz_is_imm( thempi ) )
[f8e5457]305        {
[a52291]306            InternalCF * res = int2imm( mpz_get_si( thempi ) );
[54a019]307            delete this;
308            return res;
309        }
310        else
311            return this;
[2dd068]312    }
313}
314
315InternalCF* InternalInteger::mulcoeff( InternalCF* c )
316{
317    ASSERT( ::is_imm( c ) == INTMARK, "incompatible base coefficients" );
318    int cc = imm2int( c );
[f8e5457]319    if ( getRefCount() > 1 )
320    {
[54a019]321        decRefCount();
[186402]322        mpz_t dummy;
323        mpz_init( dummy );
[f8e5457]324        if ( cc < 0 )
325        {
[a52291]326            mpz_mul_ui( dummy, thempi, -cc );
[186402]327            mpz_neg( dummy, dummy );
[f8e5457]328        }
329        else
[a52291]330            mpz_mul_ui( dummy, thempi, cc );
[186402]331        if ( mpz_is_imm( dummy ) )
[f8e5457]332        {
[186402]333            InternalCF * res = int2imm( mpz_get_si( dummy ) );
334            mpz_clear( dummy );
[54a019]335            return res;
336        }
337        else
[a52291]338            return new InternalInteger( dummy );
[2dd068]339    }
[f8e5457]340    else
341    {
342        if ( cc < 0 )
343        {
[a52291]344            mpz_mul_ui( thempi, thempi, -cc );
345            mpz_neg( thempi, thempi );
[54a019]346        }
347        else
[a52291]348            mpz_mul_ui( thempi, thempi, cc );
349        if ( mpz_is_imm( thempi ) )
[f8e5457]350        {
[a52291]351            InternalCF * res = int2imm( mpz_get_si( thempi ) );
[54a019]352            delete this;
353            return res;
354        }
355        else
356            return this;
[2dd068]357    }
358}
359
[05d0b3]360//{{{ InternalCF * InternalInteger::bgcdsame, bgcdcoeff ( const InternalCF * const c )
361// docu: see CanonicalForm::bgcd()
362InternalCF *
363InternalInteger::bgcdsame ( const InternalCF * const c ) const
364{
365    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == IntegerDomain, "incompatible base coefficients" );
366
367    // simply return 1 if we are calculating over the rationals
368    if ( cf_glob_switches.isOn( SW_RATIONAL ) )
[54a019]369         return int2imm( 1 );
[05d0b3]370
371    // calculate gcd
[186402]372    mpz_t result;
373    mpz_init( result );
[a52291]374    mpz_gcd( result, thempi, MPI( c ) );
[186402]375    mpz_abs( result, result );
[05d0b3]376
377    // check for immediate result
[186402]378    if ( mpz_is_imm( result ) )
[f8e5457]379    {
[186402]380        InternalCF * res = int2imm( mpz_get_si( result ) );
381        mpz_clear( result );
[54a019]382        return res;
[05d0b3]383    }
384    else
[a52291]385        return new InternalInteger( result );
[05d0b3]386}
387
388InternalCF *
389InternalInteger::bgcdcoeff ( const InternalCF * const c )
390{
391    ASSERT( ::is_imm( c ) == INTMARK, "incompatible base coefficients" );
392
393    // simply return 1 if we are calculating over the rationals
394    if ( cf_glob_switches.isOn( SW_RATIONAL ) )
[54a019]395         return int2imm( 1 );
[05d0b3]396
397    int cInt = imm2int( c );
398
399    // trivial cases
400    if ( cInt == 1 || cInt == -1 )
[54a019]401        return int2imm( 1 );
[05d0b3]402    else if ( cInt == 0 )
[54a019]403        return copyObject();
[05d0b3]404
405    // calculate gcd.  We need a positive operand since
406    // `mpz_gcd_ui()' operates an unsigned int's only.
407    if ( cInt < 0 ) cInt = -cInt;
[186402]408    mpz_t dummy;
409    mpz_init( dummy );
[05d0b3]410    // we do not need dummy since we know that cInt != 0
[a52291]411    cInt = mpz_gcd_ui( dummy, thempi, cInt );
[186402]412    mpz_clear( dummy );
[05d0b3]413    if ( cInt < 0 ) cInt = -cInt;
414    return int2imm( cInt );
415}
416//}}}
417
418//{{{ InternalCF * InternalInteger::bextgcdsame( InternalCF * c, CanonicalForm & a, CanonicalForm & b )
419InternalCF *
420InternalInteger::bextgcdsame( InternalCF * c, CanonicalForm & a, CanonicalForm & b )
421{
422    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == IntegerDomain, "incompatible base coefficients" );
423
424    // simply return 1 if we are calculating over the rationals
[2b44a1]425    if ( cf_glob_switches.isOn( SW_RATIONAL ) )
426    {
[54a019]427        a = 1/CanonicalForm( copyObject() ); b = 0;
428        return int2imm( 1 );
[05d0b3]429    }
430
431    // calculate extended gcd
[186402]432    mpz_t result, aMPI, bMPI;
433    mpz_init( result );
434    mpz_init( aMPI );
435    mpz_init( bMPI );
[a52291]436    mpz_gcdext( result, aMPI, bMPI, thempi, MPI( c ) );
[54a019]437
[05d0b3]438    // check and modify signs
[186402]439    if ( mpz_sgn( result ) < 0 )
[2b44a1]440    {
[186402]441        mpz_neg( result, result );
442        mpz_neg( aMPI, aMPI );
443        mpz_neg( bMPI, bMPI );
[05d0b3]444    }
445
446    // postconditioning of result
[186402]447    if ( mpz_is_imm( aMPI ) )
[2b44a1]448    {
[186402]449        a = CanonicalForm( int2imm( mpz_get_si( aMPI ) ) );
450        mpz_clear( aMPI );
[2b44a1]451    }
452    else
[a52291]453        a = CanonicalForm( new InternalInteger( aMPI ) );
[186402]454    if ( mpz_is_imm( bMPI ) )
[2b44a1]455    {
[186402]456        b = CanonicalForm( int2imm( mpz_get_si( bMPI ) ) );
457        mpz_clear( bMPI );
[2b44a1]458    }
459    else
[a52291]460        b = CanonicalForm( new InternalInteger( bMPI ) );
[186402]461    if ( mpz_is_imm( result ) )
[2b44a1]462    {
[186402]463        InternalCF * res = int2imm( mpz_get_si( result ) );
464        mpz_clear( result );
[54a019]465        return res;
[05d0b3]466    }
467    else
[a52291]468        return new InternalInteger( result );
[05d0b3]469}
470
471InternalCF *
472InternalInteger::bextgcdcoeff( InternalCF * c, CanonicalForm & a, CanonicalForm & b )
473{
474    ASSERT( ::is_imm( c ) == INTMARK, "incompatible base coefficients" );
475
476    // simply return 1 if we are calculating over the rationals
[2b44a1]477    if ( cf_glob_switches.isOn( SW_RATIONAL ) )
478    {
[54a019]479        a = 1/CanonicalForm( copyObject() ); b = 0;
480        return int2imm( 1 );
[05d0b3]481    }
482
483    int cInt = imm2int( c );
484
485    // trivial cases
[2b44a1]486    if ( cInt == 1 || cInt == -1 )
487    {
[54a019]488        a = 0; b = cInt;
489        return int2imm( 1 );
[2b44a1]490    }
491    else if ( cInt == 0 )
492    {
[54a019]493        a = 1; b = 0;
494        return copyObject();
[05d0b3]495    }
496
497    // calculate q and r such that CO = q*cInt + r
498    InternalCF * q = 0, * r = 0;
499    divremcoeff( c, q, r, false );
500
501    // we do not repeat all the code to calculate the gcd of two
502    // immediates.  Note that r is an immediate since c != 0, so
503    // we do not have to destroy it.  q is destroyed by the
504    // CanonicalForm destructor, hence we do not need to worry
505    // about it, either.
506    CanonicalForm aPrime, bPrime;
507    CanonicalForm result = bextgcd( c, r, aPrime, bPrime );
508    a = bPrime;
509    b = aPrime - CanonicalForm( q ) * bPrime;
510
511    return result.getval();
512}
513//}}}
514
[2dd068]515int InternalInteger::intval() const
516{
[a52291]517  return (int)mpz_get_si( thempi );
[2dd068]518}
519
520int InternalInteger::intmod( int p ) const
521{
[a52291]522  return (int)mpz_fdiv_ui( thempi, (unsigned long)p );
[2dd068]523}
524
[c62f38]525//{{{ int InternalInteger::sign () const
526// docu: see CanonicalForm::sign()
527int
528InternalInteger::sign () const
[2dd068]529{
[a52291]530    return mpz_sgn( thempi );
[2dd068]531}
[c62f38]532//}}}
[2dd068]533
[c556da]534//{{{ InternalCF * InternalInteger::sqrt ()
[48c934]535// docu: see CanonicalForm::sqrt()
[c556da]536InternalCF *
[48c934]537InternalInteger::sqrt ()
[2dd068]538{
[a52291]539    ASSERT( mpz_cmp_si( thempi, 0 ) >= 0, "sqrt() argument < 0" );
[186402]540    mpz_t result;
541    mpz_init( result );
[a52291]542    mpz_sqrt( result, thempi );
[186402]543    if ( mpz_is_imm( result ) )
[2b44a1]544    {
[186402]545        InternalCF * res = int2imm( mpz_get_si( result ) );
546        mpz_clear( result );
[54a019]547        return res;
[2dd068]548    }
549    else
[a52291]550        return new InternalInteger( result );
[2dd068]551}
[48c934]552//}}}
[6e60d7]553
[48c934]554//{{{ int InternalInteger::ilog2 ()
[6e60d7]555// docu: see CanonicalForm::ilog2()
556int
[48c934]557InternalInteger::ilog2 ()
[6e60d7]558{
[a52291]559    ASSERT( mpz_cmp_si( thempi, 0 ) > 0, "log() argument <= 0" );
560    return mpz_sizeinbase( thempi, 2 ) - 1;
[6e60d7]561}
562//}}}
Note: See TracBrowser for help on using the repository browser.