source: git/factory/int_intdiv.cc @ 1101a8

fieker-DuValspielwiese
Last change on this file since 1101a8 was 16f511, checked in by Oleksandr Motsak <motsak@…>, 11 years ago
Fixed the usage of "config.h" (if defined HAVE_CONFIG_H)
  • Property mode set to 100644
File size: 10.0 KB
RevLine 
[fc732a9]1/* emacs edit mode for this file is -*- C++ -*- */
2
3//{{{ docu
4//
5// int_intdiv.cc - `InternalInteger' division algorithms.
6//
7//}}}
8
[16f511]9#ifdef HAVE_CONFIG_H
[e4fe2b]10#include "config.h"
[16f511]11#endif /* HAVE_CONFIG_H */
[fc732a9]12
[64df343]13#include "canonicalform.h"
[fc732a9]14#include "imm.h"
15#include "int_cf.h"
16#include "int_int.h"
17#include "int_rat.h"
[ee668e]18#include <factory/cf_gmp.h>
[fc732a9]19#include "gmpext.h"
[6db552]20#include "templates/ftmpl_functions.h"
[fc732a9]21
22//{{{ InternalCF * InternalInteger::dividesame, dividecoeff ( InternalCF * c )
23// docu: see CanonicalForm::operator /()
24InternalCF *
25InternalInteger::dividesame ( InternalCF * c )
26{
27    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == IntegerDomain,
[806c18]28            "type error: InternalInteger expected" );
[fc732a9]29
30    if ( c == this ) {
[806c18]31        if ( deleteObject() ) delete this;
32        return int2imm( 1 );
[fc732a9]33    }
34
35    if ( cf_glob_switches.isOn( SW_RATIONAL ) ) {
[a52291]36        mpz_t n, d;
37        mpz_init_set( n, thempi );
38        mpz_init_set( d, MPI( c ) );
[806c18]39        if ( deleteObject() ) delete this;
40        InternalRational * result = new InternalRational( n, d );
41        return result->normalize_myself();
[fc732a9]42    }
43
44    if ( getRefCount() > 1 ) {
[806c18]45        decRefCount();
[a52291]46        mpz_t mpiResult;
47        mpz_init( mpiResult );
48        if ( mpz_sgn( MPI( c ) ) > 0 )
49            mpz_fdiv_q( mpiResult, thempi, MPI( c ) );
[806c18]50        else
[a52291]51            mpz_cdiv_q( mpiResult, thempi, MPI( c ) );
[806c18]52        return normalizeMPI( mpiResult );
[fc732a9]53    } else {
[a52291]54        if ( mpz_sgn( MPI( c ) ) > 0 )
55            mpz_fdiv_q( thempi, thempi, MPI( c ) );
[806c18]56        else
[a52291]57            mpz_cdiv_q( thempi, thempi, MPI( c ) );
[806c18]58        return normalizeMyself();
[fc732a9]59    }
60}
61
62InternalCF *
63InternalInteger::dividecoeff ( InternalCF * c, bool invert )
64{
65    ASSERT( ::is_imm( c ) == INTMARK,
[806c18]66            "type error: immediate integer expected" );
[fc732a9]67    ASSERT( invert || imm2int( c ) != 0,
[806c18]68            "math error: divide by zero" );
[fc732a9]69
[8710ff0]70    long intC = imm2int( c );
[fc732a9]71
72    if ( cf_glob_switches.isOn( SW_RATIONAL ) ) {
[a52291]73        mpz_t n, d;
[806c18]74        if ( invert ) {
[a52291]75            mpz_init_set_si( n, intC );
76            mpz_init_set( d, thempi );
[806c18]77        } else {
[a52291]78            mpz_init_set( n, thempi );
79            mpz_init_set_si( d, intC );
[806c18]80        }
81        if ( deleteObject() ) delete this;
82        InternalRational * result = new InternalRational( n, d );
83        return result->normalize_myself();
[fc732a9]84    }
85
86    if ( invert ) {
[a52291]87        int mpiSign = mpz_sgn( thempi );
[806c18]88        if ( deleteObject() ) delete this;
89        if ( intC >= 0 )
90            return int2imm( 0 );
91        else
92            return int2imm( -mpiSign );
[fc732a9]93    } else if ( getRefCount() > 1 ) {
[806c18]94        decRefCount();
[a52291]95        mpz_t mpiResult;
96        mpz_init( mpiResult );
[806c18]97        if ( intC > 0 )
[a52291]98            mpz_fdiv_q_ui( mpiResult, thempi, intC );
[806c18]99        else {
[a52291]100            mpz_fdiv_q_ui( mpiResult, thempi, -intC );
101            mpz_neg( mpiResult, mpiResult );
[806c18]102        }
103        return normalizeMPI( mpiResult );
[fc732a9]104    } else {
[806c18]105        if ( intC > 0 )
[a52291]106            mpz_fdiv_q_ui( thempi, thempi, intC );
[806c18]107        else {
[a52291]108            mpz_fdiv_q_ui( thempi, thempi, -intC );
109            mpz_neg( thempi, thempi );
[806c18]110        }
111        return normalizeMyself();
[fc732a9]112    }
113}
114//}}}
115
116//{{{ InternalCF * InternalInteger::divsame, divcoeff ( InternalCF * c )
117// docu: see CanonicalForm::div()
118InternalCF *
119InternalInteger::divsame ( InternalCF * c )
120{
121    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == IntegerDomain,
[806c18]122            "type error: InternalInteger expected" );
[fc732a9]123
[b391de]124    if ( c == this ) {
[806c18]125        if ( deleteObject() ) delete this;
126        return int2imm( 1 );
[b391de]127    }
128
[fc732a9]129    if ( getRefCount() > 1 ) {
[806c18]130        deleteObject();
[a52291]131        mpz_t mpiResult;
132        mpz_init( mpiResult );
133        mpz_divexact( mpiResult, thempi, MPI( c ) );
[806c18]134        return normalizeMPI( mpiResult );
[fc732a9]135    } else {
[a52291]136        mpz_divexact( thempi, thempi, MPI( c ) );
[806c18]137        return normalizeMyself();
[fc732a9]138    }
139}
140
141InternalCF *
142InternalInteger::divcoeff ( InternalCF * c, bool invert )
143{
144    ASSERT( ::is_imm( c ) == INTMARK,
[806c18]145            "type error: immediate integer expected" );
[b391de]146    ASSERT( invert || imm2int( c ) != 0,
[806c18]147            "math error: divide by zero" );
[b391de]148    ASSERT( ! invert || imm2int( c ) == 0,
[806c18]149            "math error: c does not divide CO" );
[fc732a9]150
151    if ( invert ) {
[806c18]152        if ( deleteObject() ) delete this;
153        // this may happen iff `c' == 0
154        return int2imm( 0 );
[fc732a9]155    } else if ( getRefCount() > 1 ) {
[806c18]156        deleteObject();
[a52291]157        mpz_t mpiC;
158        mpz_t mpiResult;
159        mpz_init_set_si( mpiC, imm2int( c ) );
160        mpz_init( mpiResult );
161        mpz_divexact( mpiResult, thempi, mpiC );
162        mpz_clear( mpiC );
[806c18]163        return normalizeMPI( mpiResult );
[fc732a9]164    } else {
[a52291]165        mpz_t mpiC;
166        mpz_init_set_si( mpiC, imm2int( c ) );
167        mpz_divexact( thempi, thempi, mpiC );
168        mpz_clear( mpiC );
[806c18]169        return normalizeMyself();
[fc732a9]170    }
171}
172//}}}
173
174//{{{ InternalCF * InternalInteger::modulosame, modulocoeff ( InternalCF * c )
175// docu: see CanonicalForm::operator %()
176InternalCF *
177InternalInteger::modulosame ( InternalCF * c )
178{
179    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == IntegerDomain,
[806c18]180            "type error: InternalInteger expected" );
[fc732a9]181
[b391de]182    if ( (c == this) || cf_glob_switches.isOn( SW_RATIONAL ) ) {
[806c18]183        if ( deleteObject() ) delete this;
184        return int2imm( 0 );
[fc732a9]185    }
186
187    if ( getRefCount() > 1 ) {
[806c18]188        decRefCount();
[a52291]189        mpz_t mpiResult;
190        mpz_init( mpiResult );
191        mpz_mod( mpiResult, thempi, MPI( c ) );
[806c18]192        return uiNormalizeMPI( mpiResult );
[fc732a9]193    } else {
[a52291]194        mpz_mod( thempi, thempi, MPI( c ) );
[806c18]195        return uiNormalizeMyself();
[fc732a9]196    }
197}
198
199InternalCF *
200InternalInteger::modulocoeff ( InternalCF * c, bool invert )
201{
202    ASSERT( ::is_imm( c ) == INTMARK,
[806c18]203            "type error: immediate integer expected" );
[fc732a9]204    ASSERT( invert || imm2int( c ) != 0,
[806c18]205            "math error: divide by zero" );
[fc732a9]206
207    if ( cf_glob_switches.isOn( SW_RATIONAL ) ) {
[806c18]208        if ( deleteObject() ) delete this;
209        return int2imm( 0 );
[fc732a9]210    }
211
[8710ff0]212    long intC = imm2int( c );
[fc732a9]213
214    if ( invert ) {
[806c18]215        if ( intC >= 0 ) {
216            if ( deleteObject() ) delete this;
217            return c;
218        } else {
219            // no checks for refCount == 1 are done.  It is not worth ...
[a52291]220            mpz_t mpiResult;
221            mpz_init_set( mpiResult, thempi );
222            mpz_abs( mpiResult, mpiResult );
223            mpz_sub_ui( mpiResult, mpiResult, -intC );
[806c18]224            if ( deleteObject() ) delete this;
225            return uiNormalizeMPI( mpiResult );
226        }
[fc732a9]227    } else {
[a52291]228        mpz_t dummy;
229        mpz_init( dummy );
230        InternalCF * result = int2imm( mpz_mod_ui( dummy, thempi, tabs( intC ) ) );
231        mpz_clear( dummy );
[806c18]232        if ( deleteObject() ) delete this;
233        return result;
[fc732a9]234    }
235}
236//}}}
237
238//{{{ InternalCF * InternalInteger::modsame, modcoeff ( InternalCF * c )
239// docu: see CanonicalForm::mod()
240InternalCF *
241InternalInteger::modsame ( InternalCF * c )
242{
243    return modulosame( c );
244}
245
246InternalCF *
247InternalInteger::modcoeff ( InternalCF * c, bool invert )
248{
249    return modulocoeff( c, invert );
250}
251//}}}
252
253//{{{ void InternalInteger::divremsame, divremcoeff ( InternalCF * c, InternalCF * & quot, InternalCF * & rem )
254// docu: see CanonicalForm::divrem()
255void
256InternalInteger::divremsame ( InternalCF * c, InternalCF * & quot, InternalCF * & rem )
257{
[b391de]258    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == IntegerDomain,
[806c18]259            "type error: InternalInteger expected" );
[b391de]260
261    if ( c == this ) {
[806c18]262        quot = int2imm( 1 );
263        rem = int2imm( 0 );
264        return;
[fc732a9]265    }
[b391de]266
267    if ( cf_glob_switches.isOn( SW_RATIONAL ) ) {
[a52291]268        mpz_t n, d;
269        mpz_init_set( n, thempi );
270        mpz_init_set( d, MPI( c ) );
[806c18]271        InternalRational * result = new InternalRational( n, d );
272        quot = result->normalize_myself();
273        rem = int2imm( 0 );
274        return;
[fc732a9]275    }
[b391de]276
[a52291]277    mpz_t q;
278    mpz_t r;
279    mpz_init( q ); mpz_init( r );
280    if ( mpz_sgn( MPI( c ) ) > 0 )
281        mpz_fdiv_qr( q, r, thempi, MPI( c ) );
[b391de]282    else
[a52291]283        mpz_cdiv_qr( q, r, thempi, MPI( c ) );
[b391de]284
285    quot = normalizeMPI( q );
286    rem = uiNormalizeMPI( r );
[fc732a9]287}
288
289void
290InternalInteger::divremcoeff ( InternalCF * c, InternalCF * & quot, InternalCF * & rem, bool invert )
291{
[b391de]292    ASSERT( ::is_imm( c ) == INTMARK,
[806c18]293            "type error: immediate integer expected" );
[b391de]294    ASSERT( invert || imm2int( c ) != 0,
[806c18]295            "math error: divide by zero" );
[b391de]296
[8710ff0]297    long intC = imm2int( c );
[fc732a9]298
299    if ( cf_glob_switches.isOn( SW_RATIONAL ) ) {
[a52291]300        mpz_t n, d;
[806c18]301        if ( invert ) {
[a52291]302            mpz_init_set_si( n, intC );
303            mpz_init_set( d, thempi );
[806c18]304        } else {
[a52291]305            mpz_init_set( n, thempi );
306            mpz_init_set_si( d, intC );
[806c18]307        }
308        InternalRational * result = new InternalRational( n, d );
309        quot = result->normalize_myself();
310        rem = int2imm( 0 );
311        return;
[fc732a9]312    }
313
314    if ( invert ) {
[806c18]315        if ( intC >= 0 ) {
316            rem = c;
317            quot = int2imm( 0 );
318        } else {
[a52291]319            mpz_t mpiResult;
320            mpz_init_set( mpiResult, thempi );
321            mpz_abs( mpiResult, mpiResult );
322            mpz_sub_ui( mpiResult, mpiResult, -intC );
[806c18]323            rem = uiNormalizeMPI( mpiResult );
[a52291]324            quot = int2imm( -mpz_sgn( thempi ) );
[806c18]325        }
[b391de]326    } else {
[a52291]327        mpz_t q;
328        mpz_t dummy;
329        mpz_init( q ); mpz_init( dummy );
[806c18]330        if ( intC > 0 ) {
[a52291]331            rem = int2imm( mpz_fdiv_qr_ui( q, dummy, thempi, intC ) );
[806c18]332            quot = normalizeMPI( q );
333        } else {
[a52291]334            rem = int2imm( mpz_fdiv_qr_ui( q, dummy, thempi, -intC ) );
335            mpz_neg( q, q );
[806c18]336            quot = normalizeMPI( q );
337        }
[a52291]338        mpz_clear( dummy );
[fc732a9]339    }
340}
341//}}}
342
343//{{{ bool InternalInteger::divremsamet, divremcoefft ( InternalCF * c, InternalCF * & quot, InternalCF * & rem )
344// docu: see CanonicalForm::divremt()
345bool
346InternalInteger::divremsamet ( InternalCF * c, InternalCF * & quot, InternalCF * & rem )
347{
348    divremsame( c, quot, rem );
349    return true;
350}
351
352bool
353InternalInteger::divremcoefft ( InternalCF * c, InternalCF * & quot, InternalCF * & rem, bool invert )
354{
355    divremcoeff( c, quot, rem, invert );
356    return true;
357}
358//}}}
Note: See TracBrowser for help on using the repository browser.