source: git/factory/int_intdiv.cc @ 276c3f

spielwiese
Last change on this file since 276c3f was 6db552, checked in by Hans Schoenemann <hannes@…>, 13 years ago
removed include-wrapppers git-svn-id: file:///usr/local/Singular/svn/trunk@13772 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 10.0 KB
Line 
1/* emacs edit mode for this file is -*- C++ -*- */
2/* $Id$ */
3
4//{{{ docu
5//
6// int_intdiv.cc - `InternalInteger' division algorithms.
7//
8//}}}
9
10#include <config.h>
11
12#include "canonicalform.h"
13#include "imm.h"
14#include "int_cf.h"
15#include "int_int.h"
16#include "int_rat.h"
17#include "cf_gmp.h"
18#include "gmpext.h"
19#include "templates/ftmpl_functions.h"
20
21//{{{ InternalCF * InternalInteger::dividesame, dividecoeff ( InternalCF * c )
22// docu: see CanonicalForm::operator /()
23InternalCF *
24InternalInteger::dividesame ( InternalCF * c )
25{
26    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == IntegerDomain,
27            "type error: InternalInteger expected" );
28
29    if ( c == this ) {
30        if ( deleteObject() ) delete this;
31        return int2imm( 1 );
32    }
33
34    if ( cf_glob_switches.isOn( SW_RATIONAL ) ) {
35        MP_INT n, d;
36        mpz_init_set( &n, &thempi );
37        mpz_init_set( &d, &MPI( c ) );
38        if ( deleteObject() ) delete this;
39        InternalRational * result = new InternalRational( n, d );
40        return result->normalize_myself();
41    }
42
43    if ( getRefCount() > 1 ) {
44        decRefCount();
45        MP_INT mpiResult;
46        mpz_init( &mpiResult );
47        if ( mpz_sgn( &MPI( c ) ) > 0 )
48            mpz_fdiv_q( &mpiResult, &thempi, &MPI( c ) );
49        else
50            mpz_cdiv_q( &mpiResult, &thempi, &MPI( c ) );
51        return normalizeMPI( mpiResult );
52    } else {
53        if ( mpz_sgn( &MPI( c ) ) > 0 )
54            mpz_fdiv_q( &thempi, &thempi, &MPI( c ) );
55        else
56            mpz_cdiv_q( &thempi, &thempi, &MPI( c ) );
57        return normalizeMyself();
58    }
59}
60
61InternalCF *
62InternalInteger::dividecoeff ( InternalCF * c, bool invert )
63{
64    ASSERT( ::is_imm( c ) == INTMARK,
65            "type error: immediate integer expected" );
66    ASSERT( invert || imm2int( c ) != 0,
67            "math error: divide by zero" );
68
69    int intC = imm2int( c );
70
71    if ( cf_glob_switches.isOn( SW_RATIONAL ) ) {
72        MP_INT n, d;
73        if ( invert ) {
74            mpz_init_set_si( &n, intC );
75            mpz_init_set( &d, &thempi );
76        } else {
77            mpz_init_set( &n, &thempi );
78            mpz_init_set_si( &d, intC );
79        }
80        if ( deleteObject() ) delete this;
81        InternalRational * result = new InternalRational( n, d );
82        return result->normalize_myself();
83    }
84
85    if ( invert ) {
86        int mpiSign = mpz_sgn( &thempi );
87        if ( deleteObject() ) delete this;
88        if ( intC >= 0 )
89            return int2imm( 0 );
90        else
91            return int2imm( -mpiSign );
92    } else if ( getRefCount() > 1 ) {
93        decRefCount();
94        MP_INT mpiResult;
95        mpz_init( &mpiResult );
96        if ( intC > 0 )
97            mpz_fdiv_q_ui( &mpiResult, &thempi, intC );
98        else {
99            mpz_fdiv_q_ui( &mpiResult, &thempi, -intC );
100            mpz_neg( &mpiResult, &mpiResult );
101        }
102        return normalizeMPI( mpiResult );
103    } else {
104        if ( intC > 0 )
105            mpz_fdiv_q_ui( &thempi, &thempi, intC );
106        else {
107            mpz_fdiv_q_ui( &thempi, &thempi, -intC );
108            mpz_neg( &thempi, &thempi );
109        }
110        return normalizeMyself();
111    }
112}
113//}}}
114
115//{{{ InternalCF * InternalInteger::divsame, divcoeff ( InternalCF * c )
116// docu: see CanonicalForm::div()
117InternalCF *
118InternalInteger::divsame ( InternalCF * c )
119{
120    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == IntegerDomain,
121            "type error: InternalInteger expected" );
122
123    if ( c == this ) {
124        if ( deleteObject() ) delete this;
125        return int2imm( 1 );
126    }
127
128    if ( getRefCount() > 1 ) {
129        deleteObject();
130        MP_INT mpiResult;
131        mpz_init( &mpiResult );
132        mpz_divexact( &mpiResult, &thempi, &MPI( c ) );
133        return normalizeMPI( mpiResult );
134    } else {
135        mpz_divexact( &thempi, &thempi, &MPI( c ) );
136        return normalizeMyself();
137    }
138}
139
140InternalCF *
141InternalInteger::divcoeff ( InternalCF * c, bool invert )
142{
143    ASSERT( ::is_imm( c ) == INTMARK,
144            "type error: immediate integer expected" );
145    ASSERT( invert || imm2int( c ) != 0,
146            "math error: divide by zero" );
147    ASSERT( ! invert || imm2int( c ) == 0,
148            "math error: c does not divide CO" );
149
150    if ( invert ) {
151        if ( deleteObject() ) delete this;
152        // this may happen iff `c' == 0
153        return int2imm( 0 );
154    } else if ( getRefCount() > 1 ) {
155        deleteObject();
156        MP_INT mpiC;
157        MP_INT mpiResult;
158        mpz_init_set_si( &mpiC, imm2int( c ) );
159        mpz_init( &mpiResult );
160        mpz_divexact( &mpiResult, &thempi, &mpiC );
161        mpz_clear( &mpiC );
162        return normalizeMPI( mpiResult );
163    } else {
164        MP_INT mpiC;
165        mpz_init_set_si( &mpiC, imm2int( c ) );
166        mpz_divexact( &thempi, &thempi, &mpiC );
167        mpz_clear( &mpiC );
168        return normalizeMyself();
169    }
170}
171//}}}
172
173//{{{ InternalCF * InternalInteger::modulosame, modulocoeff ( InternalCF * c )
174// docu: see CanonicalForm::operator %()
175InternalCF *
176InternalInteger::modulosame ( InternalCF * c )
177{
178    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == IntegerDomain,
179            "type error: InternalInteger expected" );
180
181    if ( (c == this) || cf_glob_switches.isOn( SW_RATIONAL ) ) {
182        if ( deleteObject() ) delete this;
183        return int2imm( 0 );
184    }
185
186    if ( getRefCount() > 1 ) {
187        decRefCount();
188        MP_INT mpiResult;
189        mpz_init( &mpiResult );
190        mpz_mod( &mpiResult, &thempi, &MPI( c ) );
191        return uiNormalizeMPI( mpiResult );
192    } else {
193        mpz_mod( &thempi, &thempi, &MPI( c ) );
194        return uiNormalizeMyself();
195    }
196}
197
198InternalCF *
199InternalInteger::modulocoeff ( InternalCF * c, bool invert )
200{
201    ASSERT( ::is_imm( c ) == INTMARK,
202            "type error: immediate integer expected" );
203    ASSERT( invert || imm2int( c ) != 0,
204            "math error: divide by zero" );
205
206    if ( cf_glob_switches.isOn( SW_RATIONAL ) ) {
207        if ( deleteObject() ) delete this;
208        return int2imm( 0 );
209    }
210
211    int intC = imm2int( c );
212
213    if ( invert ) {
214        if ( intC >= 0 ) {
215            if ( deleteObject() ) delete this;
216            return c;
217        } else {
218            // no checks for refCount == 1 are done.  It is not worth ...
219            MP_INT mpiResult;
220            mpz_init_set( &mpiResult, &thempi );
221            mpz_abs( &mpiResult, &mpiResult );
222            mpz_sub_ui( &mpiResult, &mpiResult, -intC );
223            if ( deleteObject() ) delete this;
224            return uiNormalizeMPI( mpiResult );
225        }
226    } else {
227        MP_INT dummy;
228        mpz_init( &dummy );
229        InternalCF * result = int2imm( mpz_mod_ui( &dummy, &thempi, tabs( intC ) ) );
230        mpz_clear( &dummy );
231        if ( deleteObject() ) delete this;
232        return result;
233    }
234}
235//}}}
236
237//{{{ InternalCF * InternalInteger::modsame, modcoeff ( InternalCF * c )
238// docu: see CanonicalForm::mod()
239InternalCF *
240InternalInteger::modsame ( InternalCF * c )
241{
242    return modulosame( c );
243}
244
245InternalCF *
246InternalInteger::modcoeff ( InternalCF * c, bool invert )
247{
248    return modulocoeff( c, invert );
249}
250//}}}
251
252//{{{ void InternalInteger::divremsame, divremcoeff ( InternalCF * c, InternalCF * & quot, InternalCF * & rem )
253// docu: see CanonicalForm::divrem()
254void
255InternalInteger::divremsame ( InternalCF * c, InternalCF * & quot, InternalCF * & rem )
256{
257    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == IntegerDomain,
258            "type error: InternalInteger expected" );
259
260    if ( c == this ) {
261        quot = int2imm( 1 );
262        rem = int2imm( 0 );
263        return;
264    }
265
266    if ( cf_glob_switches.isOn( SW_RATIONAL ) ) {
267        MP_INT n, d;
268        mpz_init_set( &n, &thempi );
269        mpz_init_set( &d, &MPI( c ) );
270        InternalRational * result = new InternalRational( n, d );
271        quot = result->normalize_myself();
272        rem = int2imm( 0 );
273        return;
274    }
275
276    MP_INT q;
277    MP_INT r;
278    mpz_init( &q ); mpz_init( &r );
279    if ( mpz_sgn( &MPI( c ) ) > 0 )
280        mpz_fdiv_qr( &q, &r, &thempi, &MPI( c ) );
281    else
282        mpz_cdiv_qr( &q, &r, &thempi, &MPI( c ) );
283
284    quot = normalizeMPI( q );
285    rem = uiNormalizeMPI( r );
286}
287
288void
289InternalInteger::divremcoeff ( InternalCF * c, InternalCF * & quot, InternalCF * & rem, bool invert )
290{
291    ASSERT( ::is_imm( c ) == INTMARK,
292            "type error: immediate integer expected" );
293    ASSERT( invert || imm2int( c ) != 0,
294            "math error: divide by zero" );
295
296    int intC = imm2int( c );
297
298    if ( cf_glob_switches.isOn( SW_RATIONAL ) ) {
299        MP_INT n, d;
300        if ( invert ) {
301            mpz_init_set_si( &n, intC );
302            mpz_init_set( &d, &thempi );
303        } else {
304            mpz_init_set( &n, &thempi );
305            mpz_init_set_si( &d, intC );
306        }
307        InternalRational * result = new InternalRational( n, d );
308        quot = result->normalize_myself();
309        rem = int2imm( 0 );
310        return;
311    }
312
313    if ( invert ) {
314        if ( intC >= 0 ) {
315            rem = c;
316            quot = int2imm( 0 );
317        } else {
318            MP_INT mpiResult;
319            mpz_init_set( &mpiResult, &thempi );
320            mpz_abs( &mpiResult, &mpiResult );
321            mpz_sub_ui( &mpiResult, &mpiResult, -intC );
322            rem = uiNormalizeMPI( mpiResult );
323            quot = int2imm( -mpz_sgn( &thempi ) );
324        }
325    } else {
326        MP_INT q;
327        MP_INT dummy;
328        mpz_init( &q ); mpz_init( &dummy );
329        if ( intC > 0 ) {
330            rem = int2imm( mpz_fdiv_qr_ui( &q, &dummy, &thempi, intC ) );
331            quot = normalizeMPI( q );
332        } else {
333            rem = int2imm( mpz_fdiv_qr_ui( &q, &dummy, &thempi, -intC ) );
334            mpz_neg( &q, &q );
335            quot = normalizeMPI( q );
336        }
337        mpz_clear( &dummy );
338    }
339}
340//}}}
341
342//{{{ bool InternalInteger::divremsamet, divremcoefft ( InternalCF * c, InternalCF * & quot, InternalCF * & rem )
343// docu: see CanonicalForm::divremt()
344bool
345InternalInteger::divremsamet ( InternalCF * c, InternalCF * & quot, InternalCF * & rem )
346{
347    divremsame( c, quot, rem );
348    return true;
349}
350
351bool
352InternalInteger::divremcoefft ( InternalCF * c, InternalCF * & quot, InternalCF * & rem, bool invert )
353{
354    divremcoeff( c, quot, rem, invert );
355    return true;
356}
357//}}}
Note: See TracBrowser for help on using the repository browser.