source: git/factory/int_intdiv.cc @ fc7220

fieker-DuValspielwiese
Last change on this file since fc7220 was 1ca317, checked in by Jens Schmidt <schmidt@…>, 26 years ago
* int_intdiv.cc (modulocoeff): extra call added for `mpz_mod_ui()' with void return value. Wrapped by #define `__MWERKS__'. git-svn-id: file:///usr/local/Singular/svn/trunk@2301 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 9.1 KB
Line 
1/* emacs edit mode for this file is -*- C++ -*- */
2/* $Id: int_intdiv.cc,v 1.6 1998-07-07 16:34:35 schmidt Exp $ */
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 "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#ifdef __MWERKS__
230        mpz_mod_ui( &dummy, &thempi, tabs( intC ) );
231        InternalCF * result = int2imm( mpz_get_ui( &dummy ) );
232#else
233        InternalCF * result = int2imm( mpz_mod_ui( &dummy, &thempi, tabs( intC ) ) );
234#endif
235        mpz_clear( &dummy );
236        if ( deleteObject() ) delete this;
237        return result;
238    }
239}
240//}}}
241
242//{{{ InternalCF * InternalInteger::modsame, modcoeff ( InternalCF * c )
243// docu: see CanonicalForm::mod()
244InternalCF *
245InternalInteger::modsame ( InternalCF * c )
246{
247    return modulosame( c );
248}
249
250InternalCF *
251InternalInteger::modcoeff ( InternalCF * c, bool invert )
252{
253    return modulocoeff( c, invert );
254}
255//}}}
256
257//{{{ void InternalInteger::divremsame, divremcoeff ( InternalCF * c, InternalCF * & quot, InternalCF * & rem )
258// docu: see CanonicalForm::divrem()
259void
260InternalInteger::divremsame ( InternalCF * c, InternalCF * & quot, InternalCF * & rem )
261{
262    ASSERT( ! ::is_imm( c ) && c->levelcoeff() == IntegerDomain,
263            "type error: InternalInteger expected" );
264
265    if ( c == this ) {
266        quot = int2imm( 1 );
267        rem = int2imm( 0 );
268        return;
269    }
270
271    if ( cf_glob_switches.isOn( SW_RATIONAL ) ) {
272        MP_INT n, d;
273        mpz_init_set( &n, &thempi );
274        mpz_init_set( &d, &MPI( c ) );
275        InternalRational * result = new InternalRational( n, d );
276        quot = result->normalize_myself();
277        rem = int2imm( 0 );
278        return;
279    }
280
281    MP_INT q;
282    MP_INT r;
283    mpz_init( &q ); mpz_init( &r );
284    if ( mpz_sgn( &MPI( c ) ) > 0 )
285        mpz_fdiv_qr( &q, &r, &thempi, &MPI( c ) );
286    else
287        mpz_cdiv_qr( &q, &r, &thempi, &MPI( c ) );
288
289    quot = normalizeMPI( q );
290    rem = uiNormalizeMPI( r );
291}
292
293void
294InternalInteger::divremcoeff ( InternalCF * c, InternalCF * & quot, InternalCF * & rem, bool invert )
295{
296    ASSERT( ::is_imm( c ) == INTMARK,
297            "type error: immediate integer expected" );
298    ASSERT( invert || imm2int( c ) != 0,
299            "math error: divide by zero" );
300
301    int intC = imm2int( c );
302
303    if ( cf_glob_switches.isOn( SW_RATIONAL ) ) {
304        MP_INT n, d;
305        if ( invert ) {
306            mpz_init_set_si( &n, intC );
307            mpz_init_set( &d, &thempi );
308        } else {
309            mpz_init_set( &n, &thempi );
310            mpz_init_set_si( &d, intC );
311        }
312        InternalRational * result = new InternalRational( n, d );
313        quot = result->normalize_myself();
314        rem = int2imm( 0 );
315        return;
316    }
317
318    if ( invert ) {
319        if ( intC >= 0 ) {
320            rem = c;
321            quot = int2imm( 0 );
322        } else {
323            MP_INT mpiResult;
324            mpz_init_set( &mpiResult, &thempi );
325            mpz_abs( &mpiResult, &mpiResult );
326            mpz_sub_ui( &mpiResult, &mpiResult, -intC );
327            rem = uiNormalizeMPI( mpiResult );
328            quot = int2imm( -mpz_sgn( &thempi ) );
329        }
330    } else {
331        MP_INT q;
332        MP_INT dummy;
333        mpz_init( &q ); mpz_init( &dummy );
334        if ( intC > 0 ) {
335            rem = int2imm( mpz_fdiv_qr_ui( &q, &dummy, &thempi, intC ) );
336            quot = normalizeMPI( q );
337        } else {
338            rem = int2imm( mpz_fdiv_qr_ui( &q, &dummy, &thempi, -intC ) );
339            mpz_neg( &q, &q );
340            quot = normalizeMPI( q );
341        }
342        mpz_clear( &dummy );
343    }
344}
345//}}}
346
347//{{{ bool InternalInteger::divremsamet, divremcoefft ( InternalCF * c, InternalCF * & quot, InternalCF * & rem )
348// docu: see CanonicalForm::divremt()
349bool
350InternalInteger::divremsamet ( InternalCF * c, InternalCF * & quot, InternalCF * & rem )
351{
352    divremsame( c, quot, rem );
353    return true;
354}
355
356bool
357InternalInteger::divremcoefft ( InternalCF * c, InternalCF * & quot, InternalCF * & rem, bool invert )
358{
359    divremcoeff( c, quot, rem, invert );
360    return true;
361}
362//}}}
Note: See TracBrowser for help on using the repository browser.