source: git/factory/int_int.cc @ 8710ff0

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