source: git/factory/int_int.cc @ fc7220

fieker-DuValspielwiese
Last change on this file since fc7220 was f79b94c, checked in by Olaf Bachmann <obachman@…>, 24 years ago
* support for omalloc git-svn-id: file:///usr/local/Singular/svn/trunk@4564 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 12.1 KB
Line 
1/* emacs edit mode for this file is -*- C++ -*- */
2/* $Id: int_int.cc,v 1.15 2000-09-04 13:31:29 obachman 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 )
30{
31    mpz_init_set_str( &thempi, str, 10 );
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        MP_INT dummy;
307        mpz_init_set_si( &dummy, cc );
308        if ( cc < 0 ) {
309            mpz_mul_ui( &thempi, &thempi, -cc );
310            mpz_neg( &thempi, &thempi );
311        }
312        else
313            mpz_mul_ui( &thempi, &thempi, cc );
314        if ( mpz_is_imm( &thempi ) ) {
315            InternalCF * res = int2imm( mpz_get_si( &thempi ) );
316            delete this;
317            return res;
318        }
319        else
320            return this;
321    }
322}
323
324//{{{ InternalCF * InternalInteger::bgcdsame, bgcdcoeff ( const InternalCF * const c )
325// docu: see CanonicalForm::bgcd()
326InternalCF *
327InternalInteger::bgcdsame ( const InternalCF * const c ) const
328{
329    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == IntegerDomain, "incompatible base coefficients" );
330
331    // simply return 1 if we are calculating over the rationals
332    if ( cf_glob_switches.isOn( SW_RATIONAL ) )
333         return int2imm( 1 );
334
335    // calculate gcd
336    MP_INT result;
337    mpz_init( &result );
338    mpz_gcd( &result, &thempi, &MPI( c ) );
339    mpz_abs( &result, &result );
340
341    // check for immediate result
342    if ( mpz_is_imm( &result ) ) {
343        InternalCF * res = int2imm( mpz_get_si( &result ) );
344        mpz_clear( &result );
345        return res;
346    }
347    else
348        return new InternalInteger( result );
349}
350
351InternalCF *
352InternalInteger::bgcdcoeff ( const InternalCF * const c )
353{
354    ASSERT( ::is_imm( c ) == INTMARK, "incompatible base coefficients" );
355
356    // simply return 1 if we are calculating over the rationals
357    if ( cf_glob_switches.isOn( SW_RATIONAL ) )
358         return int2imm( 1 );
359
360    int cInt = imm2int( c );
361
362    // trivial cases
363    if ( cInt == 1 || cInt == -1 )
364        return int2imm( 1 );
365    else if ( cInt == 0 )
366        return copyObject();
367
368    // calculate gcd.  We need a positive operand since
369    // `mpz_gcd_ui()' operates an unsigned int's only.
370    if ( cInt < 0 ) cInt = -cInt;
371    MP_INT dummy;
372    mpz_init( &dummy );
373    // we do not need dummy since we know that cInt != 0
374    cInt = mpz_gcd_ui( &dummy, &thempi, cInt );
375    mpz_clear( &dummy );
376    if ( cInt < 0 ) cInt = -cInt;
377    return int2imm( cInt );
378}
379//}}}
380
381//{{{ InternalCF * InternalInteger::bextgcdsame( InternalCF * c, CanonicalForm & a, CanonicalForm & b )
382InternalCF *
383InternalInteger::bextgcdsame( InternalCF * c, CanonicalForm & a, CanonicalForm & b )
384{
385    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == IntegerDomain, "incompatible base coefficients" );
386
387    // simply return 1 if we are calculating over the rationals
388    if ( cf_glob_switches.isOn( SW_RATIONAL ) ) {
389        a = 1/CanonicalForm( copyObject() ); b = 0;
390        return int2imm( 1 );
391    }
392
393    // calculate extended gcd
394    MP_INT result;
395    MP_INT aMPI;
396    MP_INT bMPI;
397    mpz_init( &result );
398    mpz_init( &aMPI );
399    mpz_init( &bMPI );
400    mpz_gcdext( &result, &aMPI, &bMPI, &thempi, &MPI( c ) );
401   
402    // check and modify signs
403    if ( mpz_sgn( &result ) < 0 ) {
404        mpz_neg( &result, &result );
405        mpz_neg( &aMPI, &aMPI );
406        mpz_neg( &bMPI, &bMPI );
407    }
408
409    // postconditioning of result
410    if ( mpz_is_imm( &aMPI ) ) {
411        a = CanonicalForm( int2imm( mpz_get_si( &aMPI ) ) );
412        mpz_clear( &aMPI );
413    } else
414        a = CanonicalForm( new InternalInteger( aMPI ) );
415    if ( mpz_is_imm( &bMPI ) ) {
416        b = CanonicalForm( int2imm( mpz_get_si( &bMPI ) ) );
417        mpz_clear( &bMPI );
418    } else
419        b = CanonicalForm( new InternalInteger( bMPI ) );
420    if ( mpz_is_imm( &result ) ) {
421        InternalCF * res = int2imm( mpz_get_si( &result ) );
422        mpz_clear( &result );
423        return res;
424    }
425    else
426        return new InternalInteger( result );
427}
428
429InternalCF *
430InternalInteger::bextgcdcoeff( InternalCF * c, CanonicalForm & a, CanonicalForm & b )
431{
432    ASSERT( ::is_imm( c ) == INTMARK, "incompatible base coefficients" );
433
434    // simply return 1 if we are calculating over the rationals
435    if ( cf_glob_switches.isOn( SW_RATIONAL ) ) {
436        a = 1/CanonicalForm( copyObject() ); b = 0;
437        return int2imm( 1 );
438    }
439
440    int cInt = imm2int( c );
441
442    // trivial cases
443    if ( cInt == 1 || cInt == -1 ) {
444        a = 0; b = cInt;
445        return int2imm( 1 );
446    } else if ( cInt == 0 ) {
447        a = 1; b = 0;
448        return copyObject();
449    }
450
451    // calculate q and r such that CO = q*cInt + r
452    InternalCF * q = 0, * r = 0;
453    divremcoeff( c, q, r, false );
454
455    // we do not repeat all the code to calculate the gcd of two
456    // immediates.  Note that r is an immediate since c != 0, so
457    // we do not have to destroy it.  q is destroyed by the
458    // CanonicalForm destructor, hence we do not need to worry
459    // about it, either.
460    CanonicalForm aPrime, bPrime;
461    CanonicalForm result = bextgcd( c, r, aPrime, bPrime );
462    a = bPrime;
463    b = aPrime - CanonicalForm( q ) * bPrime;
464
465    return result.getval();
466}
467//}}}
468
469int InternalInteger::intval() const
470{
471  return (int)mpz_get_si( &thempi );
472}
473
474int InternalInteger::intmod( int p ) const
475{
476  return (int)mpz_mmod_ui( 0, &thempi, (unsigned long)p );
477}
478
479//{{{ int InternalInteger::sign () const
480// docu: see CanonicalForm::sign()
481int
482InternalInteger::sign () const
483{
484    return mpz_sgn( &thempi );
485}
486//}}}
487
488//{{{ InternalCF * InternalInteger::sqrt ()
489// docu: see CanonicalForm::sqrt()
490InternalCF *
491InternalInteger::sqrt ()
492{
493    ASSERT( mpz_cmp_si( &thempi, 0 ) >= 0, "sqrt() argument < 0" );
494    MP_INT result;
495    mpz_init( &result );
496    mpz_sqrt( &result, &thempi );
497    if ( mpz_is_imm( &result ) ) {
498        InternalCF * res = int2imm( mpz_get_si( &result ) );
499        mpz_clear( &result );
500        return res;
501    }
502    else
503        return new InternalInteger( result );
504}
505//}}}
506
507//{{{ int InternalInteger::ilog2 ()
508// docu: see CanonicalForm::ilog2()
509int
510InternalInteger::ilog2 ()
511{
512    ASSERT( mpz_cmp_si( &thempi, 0 ) > 0, "log() argument <= 0" );
513    return mpz_sizeinbase( &thempi, 2 ) - 1;
514}
515//}}}
Note: See TracBrowser for help on using the repository browser.