source: git/factory/int_intdiv.cc @ ed66770

spielwiese
Last change on this file since ed66770 was ee668e, checked in by Jan Engelhardt <jengelh@…>, 12 years ago
factory/build: restore out-of-tree build support When attempting an OOT build, it fails to find <factory/cplusplus.h>, because cplusplus.h is always (even in in-tree builds) produced in "${builddir}", and not "${top_srcdir}/../factory". Furthermore, one must not rely on the basename of ${top_srcdir}, and going above ${top_srcdir} is undefined and may lead to spurious build failures. (Consider a hypothetical chroot on ${top_srcdir}). Therefore, create a directory include/factory and use -Iinclude such that <factory/*> yields a buildable state, move all exported header files there. Previous OOT build log: 17:22 seven:../factory/obj > make CXX cplusplus.o CXXLD cplusplus ./cplusplus > ./cplusplus.h ../bin/makeheader ../factory.template factory.h ../bin/makeheader ../factoryconf.template factoryconf.h YACC readcf.cc make all-am make[1]: Entering directory `/home/jengelh/obs/zu/home/jengelh/science/singsource/factory/obj' CXX libfactory_a-algext.o CXX libfactory_a-canonicalform.o In file included from ../cf_factory.h:12:0, from ../canonicalform.cc:7: ../../factory/cf_gmp.h:14:33: fatal error: factory/cplusplus.h: Ingen slik fil eller filkatalog compilation terminated. make[1]: *** [libfactory_a-canonicalform.o] Error 1 make[1]: Leaving directory `/home/jengelh/obs/zu/home/jengelh/science/singsource/factory/obj' make: *** [all] Error 2
  • Property mode set to 100644
File size: 9.9 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 <factory/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        mpz_t 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        mpz_t 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        mpz_t 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        mpz_t 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        mpz_t 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        mpz_t mpiC;
157        mpz_t 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        mpz_t 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        mpz_t 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            mpz_t 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        mpz_t 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        mpz_t 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    mpz_t q;
277    mpz_t 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        mpz_t 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            mpz_t 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        mpz_t q;
327        mpz_t 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.