source: git/factory/int_int.cc @ 181148

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