source: git/factory/int_int.cc @ 26da1d

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