source: git/factory/int_int.cc @ 767da0

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