source: git/factory/int_int.cc @ c284ce

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