source: git/factory/imm.h @ 314f0a2

spielwiese
Last change on this file since 314f0a2 was 314f0a2, checked in by Hans Schoenemann <hannes@…>, 12 years ago
fix: better multiplication on 32bit machines
  • Property mode set to 100644
File size: 12.0 KB
Line 
1/* emacs edit mode for this file is -*- C++ -*- */
2
3#ifndef INCL_IMM_H
4#define INCL_IMM_H
5
6// #include "config.h"
7
8#ifndef NOSTREAMIO
9#ifdef HAVE_IOSTREAM
10#include <iostream>
11#define OSTREAM std::ostream
12#elif defined(HAVE_IOSTREAM_H)
13#include <iostream.h>
14#define OSTREAM ostream
15#endif
16#endif /* NOSTREAMIO */
17
18#include "cf_assert.h"
19
20#include "cf_defs.h"
21#include "cf_globals.h"
22#include "ffops.h"
23#include "gfops.h"
24#include "cf_factory.h"
25#include "canonicalform.h"
26#include "int_cf.h"
27
28const long INTMARK = 1;
29const long FFMARK = 2;
30const long GFMARK = 3;
31
32/* define type of your compilers 64 bit integer type */
33#ifndef INT64
34#define INT64 long long int
35#endif
36
37#if SIZEOF_LONG == 4
38const long MINIMMEDIATE = -268435454; // -2^28-2
39const long MAXIMMEDIATE = 268435454;  // 2^28-2
40#else
41const long MINIMMEDIATE = -(1L<<60)+2L; // -2^60-2
42const long MAXIMMEDIATE = (1L<<60)-2L;  // 2^60-2
43#endif
44
45#if defined(WINNT) && ! defined(__GNUC__)
46const INT64 MINIMMEDIATELL = -268435454i64;
47const INT64 MAXIMMEDIATELL = 268435454i64;
48#else
49const INT64 MINIMMEDIATELL = -268435454LL;
50const INT64 MAXIMMEDIATELL = 268435454LL;
51#endif
52
53//{{{ conversion functions
54//#ifdef HAS_ARITHMETIC_SHIFT
55#if 1
56
57inline long imm2int ( const InternalCF * const imm )
58{
59    return ((long)imm) >> 2;
60}
61
62inline InternalCF * int2imm ( long i )
63{
64    return (InternalCF*)((i << 2) | INTMARK );
65}
66
67#else
68
69inline int imm2int ( const InternalCF * const imm )
70{
71    // this could be better done by masking the sign bit
72    if ( ((int)((long)imm)) < 0 )
73        return -((-(long)imm) >> 2);
74    else
75        return (long)imm >> 2;
76}
77
78inline InternalCF * int2imm ( long i )
79{
80    if ( i < 0 )
81        return (InternalCF*)(-(((-i) << 2) | INTMARK));
82    else
83        return (InternalCF*)((i << 2) | INTMARK );
84}
85
86#endif
87
88inline InternalCF * int2imm_p ( long i )
89{
90    return (InternalCF*)((i << 2) | FFMARK );
91}
92
93inline InternalCF * int2imm_gf ( long i )
94{
95    return (InternalCF*)((i << 2) | GFMARK );
96}
97//}}}
98
99// predicates
100#if 0
101inline int is_imm ( const InternalCF * const ptr )
102{
103    // returns 0 if ptr is not immediate
104    return ( (long)ptr & 3 );
105}
106#endif
107
108//{{{ inline int imm_isone, imm_isone_p, imm_isone_gf ( const InternalCF * const ptr )
109// docu: see CanonicalForm::isOne()
110inline int
111imm_isone ( const InternalCF * const ptr )
112{
113    return imm2int( ptr ) == 1;
114}
115
116inline int
117imm_isone_p ( const InternalCF * const ptr )
118{
119    return imm2int( ptr ) == 1;
120}
121
122inline int
123imm_isone_gf ( const InternalCF * const ptr )
124{
125    return gf_isone( imm2int( ptr ) );
126}
127//}}}
128
129//{{{ inline int imm_iszero, imm_iszero_p, imm_iszero_gf ( const InternalCF * const ptr )
130// docu: see CanonicalForm::isZero()
131inline int
132imm_iszero ( const InternalCF * const ptr )
133{
134    return imm2int( ptr ) == 0;
135}
136
137inline int
138imm_iszero_p ( const InternalCF * const ptr )
139{
140    return imm2int( ptr ) == 0;
141}
142
143inline int
144imm_iszero_gf ( const InternalCF * const ptr )
145{
146    return gf_iszero( imm2int( ptr ) );
147}
148//}}}
149
150//{{{ conversion functions
151inline long imm_intval ( const InternalCF* const op )
152{
153    if ( is_imm( op ) == FFMARK )
154        if ( cf_glob_switches.isOn( SW_SYMMETRIC_FF ) )
155            return ff_symmetric( imm2int( op ) );
156        else
157            return imm2int( op );
158    else  if ( is_imm( op ) == GFMARK ) {
159        ASSERT( gf_isff( imm2int( op ) ), "invalid conversion" );
160        if ( cf_glob_switches.isOn( SW_SYMMETRIC_FF ) )
161            return ff_symmetric( gf_gf2ff( imm2int( op ) ) );
162        else
163            return gf_gf2ff( imm2int( op ) );
164    }
165    else
166        return imm2int( op );
167}
168//}}}
169
170//{{{ inline int imm_sign ( const InternalCF * const op )
171//{{{ docu
172//
173// imm_sign() - return sign of immediate object.
174//
175// If CO is an immediate integer, the sign is defined as usual.
176// If CO is an element of FF(p) and SW_SYMMETRIC_FF is on the
177// sign of CO is the sign of the symmetric representation of CO.
178// If CO is in GF(q) or in FF(p) and SW_SYMMETRIC_FF is off, the
179// sign of CO is zero iff CO is zero, otherwise the sign is one.
180//
181// See also: CanonicalForm::sign(), gf_sign()
182//
183//}}}
184inline int
185imm_sign ( const InternalCF * const op )
186{
187    if ( is_imm( op ) == FFMARK )
188        if ( imm2int( op ) == 0 )
189            return 0;
190        else  if ( cf_glob_switches.isOn( SW_SYMMETRIC_FF ) )
191            if ( ff_symmetric( imm2int( op ) ) > 0 )
192                return 1;
193            else
194                return -1;
195        else
196            return 1;
197    else  if ( is_imm( op ) == GFMARK )
198        return gf_sign( imm2int( op ) );
199    else  if ( imm2int( op ) == 0 )
200        return 0;
201    else  if ( imm2int( op ) > 0 )
202        return 1;
203    else
204        return -1;
205}
206//}}}
207
208//{{{ inline int imm_cmp, imm_cmp_p, imm_cmp_gf ( const InternalCF * const lhs, const InternalCF * const rhs )
209//{{{ docu
210//
211// imm_cmp(), imm_cmp_p(), imm_cmp_gf() - compare immediate objects.
212//
213// For immediate integers, it is clear how this should be done.
214// For objects from finite fields, it is not clear since they
215// are not ordered fields.  However, since we want to have a
216// total well order on polynomials we have to define a total well
217// order on all coefficients, too.  I decided to use simply the
218// order on the representation as `int's of such objects.
219//
220// See also: CanonicalForm::operator <(), CanonicalForm::operator ==()
221//
222//}}}
223inline int
224imm_cmp ( const InternalCF * const lhs, const InternalCF * const rhs )
225{
226    if ( imm2int( lhs ) == imm2int( rhs ) )
227        return 0;
228    else  if ( imm2int( lhs ) > imm2int( rhs ) )
229        return 1;
230    else
231        return -1;
232}
233
234inline int
235imm_cmp_p ( const InternalCF * const lhs, const InternalCF * const rhs )
236{
237    if ( imm2int( lhs ) == imm2int( rhs ) )
238        return 0;
239    else if ( imm2int( lhs ) > imm2int( rhs ) )
240        return 1;
241    else
242        return -1;
243}
244
245inline int
246imm_cmp_gf ( const InternalCF * const lhs, const InternalCF * const rhs )
247{
248    if ( imm2int( lhs ) == imm2int( rhs ) )
249        return 0;
250    // check is done in this way because zero should be minimal
251    else if ( imm2int( lhs ) > imm2int( rhs ) )
252        return -1;
253    else
254        return 1;
255}
256//}}}
257
258//{{{ arithmetic operators
259inline InternalCF * imm_add ( const InternalCF * const lhs, const InternalCF * const rhs )
260{
261    long result = imm2int( lhs ) + imm2int( rhs );
262    if ( ( result > MAXIMMEDIATE ) || ( result < MINIMMEDIATE ) )
263        return CFFactory::basic( result );
264    else
265        return int2imm( result );
266}
267
268inline InternalCF * imm_add_p ( const InternalCF * const lhs, const InternalCF * const rhs )
269{
270    return int2imm_p( ff_add( imm2int( lhs ), imm2int( rhs ) ) );
271}
272
273inline InternalCF * imm_add_gf ( const InternalCF * const lhs, const InternalCF * const rhs )
274{
275    return int2imm_gf( gf_add( imm2int( lhs ), imm2int( rhs ) ) );
276}
277
278inline InternalCF * imm_sub ( const InternalCF * const lhs, const InternalCF * const rhs )
279{
280    long result = imm2int( lhs ) - imm2int( rhs );
281    if ( ( result > MAXIMMEDIATE ) || ( result < MINIMMEDIATE ) )
282        return CFFactory::basic( result );
283    else
284        return int2imm( result );
285}
286
287inline InternalCF * imm_sub_p ( const InternalCF * const lhs, const InternalCF * const rhs )
288{
289    return int2imm_p( ff_sub( imm2int( lhs ), imm2int( rhs ) ) );
290}
291
292inline InternalCF * imm_sub_gf ( const InternalCF * const lhs, const InternalCF * const rhs )
293{
294    return int2imm_gf( gf_sub( imm2int( lhs ), imm2int( rhs ) ) );
295}
296
297inline InternalCF *
298imm_mul ( InternalCF * lhs, InternalCF * rhs )
299{
300    long a = imm2int( lhs );
301    long b = imm2int( rhs );
302    INT64 result = (INT64)a * (INT64)b;
303    #if SIZEOF_LONG == 4
304    if ((result>(INT64)MAXIMMEDIATE)||(result<(INT64)MINIMMEDIATE))
305    {
306        InternalCF * res = CFFactory::basic( IntegerDomain, a, true );
307        return res->mulcoeff( rhs );
308    }
309    #else
310    if ( ( a!=0L ) && ((result/a!=b)
311      ||(result>MAXIMMEDIATE)||(result<MINIMMEDIATE) ) )
312    {
313        InternalCF * res = CFFactory::basic( IntegerDomain, a, true );
314        return res->mulcoeff( rhs );
315    }
316    #endif
317    else
318        return int2imm( result );
319}
320
321inline InternalCF * imm_mul_p ( const InternalCF * const lhs, const InternalCF * const rhs )
322{
323    return int2imm_p( ff_mul( imm2int( lhs ), imm2int( rhs ) ) );
324}
325
326inline InternalCF * imm_mul_gf ( const InternalCF * const lhs, const InternalCF * const rhs )
327{
328    return int2imm_gf( gf_mul( imm2int( lhs ), imm2int( rhs ) ) );
329}
330
331inline InternalCF * imm_div ( const InternalCF * const lhs, const InternalCF * const rhs )
332{
333    long a = imm2int( lhs );
334    long b = imm2int( rhs );
335    if ( a > 0 )
336        return int2imm( a / b );
337    else  if ( b > 0 )
338        return int2imm( -((b-a-1)/b) );
339    else
340        return int2imm( (-a-b-1)/(-b) );
341}
342
343inline InternalCF * imm_divrat ( const InternalCF * const lhs, const InternalCF * const rhs )
344{
345    if ( cf_glob_switches.isOn( SW_RATIONAL ) )
346        return CFFactory::rational( imm2int( lhs ), imm2int( rhs ) );
347    else {
348        long a = imm2int( lhs );
349        long b = imm2int( rhs );
350        if ( a > 0 )
351            return int2imm( a / b );
352        else  if ( b > 0 )
353            return int2imm( -((b-a-1)/b) );
354        else
355            return int2imm( (-a-b-1)/(-b) );
356    }
357}
358
359inline InternalCF * imm_div_p ( const InternalCF * const lhs, const InternalCF * const rhs )
360{
361    return int2imm_p( ff_div( imm2int( lhs ), imm2int( rhs ) ) );
362}
363
364inline InternalCF * imm_div_gf ( const InternalCF * const lhs, const InternalCF * const rhs )
365{
366    return int2imm_gf( gf_div( imm2int( lhs ), imm2int( rhs ) ) );
367}
368
369inline InternalCF * imm_mod ( const InternalCF * const lhs, const InternalCF * const rhs )
370{
371    if ( cf_glob_switches.isOn( SW_RATIONAL ) )
372        return int2imm( 0 );
373    else {
374        long a = imm2int( lhs );
375        long b = imm2int( rhs );
376        if ( a > 0 )
377            if ( b > 0 )
378                return int2imm( a % b );
379            else
380                return int2imm( a % (-b) );
381        else
382            if ( b > 0 ) {
383                long r = (-a) % b;
384                return int2imm( (r==0) ? r : b-r );
385            }
386            else {
387                long r = (-a) % (-b);
388                return int2imm( (r==0) ? r : -b-r );
389            }
390    }
391}
392
393inline InternalCF * imm_mod_p ( const InternalCF * const, const InternalCF * const )
394{
395    return int2imm_p( 0 );
396}
397
398inline InternalCF * imm_mod_gf ( const InternalCF * const, const InternalCF * const )
399{
400    return int2imm_gf( gf_q );
401}
402
403inline void imm_divrem ( const InternalCF * const lhs, const InternalCF * const rhs, InternalCF * & q, InternalCF * & r )
404{
405    if ( cf_glob_switches.isOn( SW_RATIONAL ) ) {
406        q = imm_divrat( lhs, rhs );
407        r = CFFactory::basic( 0L );
408    }
409    else {
410        q = imm_div( lhs, rhs );
411        r = imm_mod( lhs, rhs );
412    }
413}
414
415inline void imm_divrem_p ( const InternalCF * const lhs, const InternalCF * const rhs, InternalCF * & q, InternalCF * & r )
416{
417    q = int2imm_p( ff_div( imm2int( lhs ), imm2int( rhs ) ) );
418    r = int2imm_p( 0 );
419}
420
421inline void imm_divrem_gf ( const InternalCF * const lhs, const InternalCF * const rhs, InternalCF * & q, InternalCF * & r )
422{
423    q = int2imm_gf( gf_div( imm2int( lhs ), imm2int( rhs ) ) );
424    r = int2imm_gf( gf_q );
425}
426
427//{{{ inline InternalCF * imm_neg, imm_neg_p, imm_neg_gf ( const InternalCF * const op )
428// docu: see CanonicalForm::operator -()
429inline InternalCF *
430imm_neg ( const InternalCF * const op )
431{
432    return int2imm( -imm2int( op ) );
433}
434
435inline InternalCF *
436imm_neg_p ( const InternalCF * const op )
437{
438    return int2imm_p( ff_neg( imm2int( op ) ) );
439}
440
441inline InternalCF *
442imm_neg_gf ( const InternalCF * const op )
443{
444    return int2imm_gf( gf_neg( imm2int( op ) ) );
445}
446//}}}
447//}}}
448
449//{{{ input/output
450#ifndef NOSTREAMIO
451inline void imm_print ( OSTREAM & os, const InternalCF * const op, const char * const str )
452{
453    if ( is_imm( op ) == FFMARK )
454        if ( cf_glob_switches.isOn( SW_SYMMETRIC_FF ) )
455            os << ff_symmetric( imm2int( op ) ) << str;
456        else
457            os << imm2int( op ) << str;
458    else  if ( is_imm( op ) == GFMARK ) {
459        gf_print( os, imm2int( op ) );
460        os << str;
461    }
462    else
463        os << imm2int( op ) << str;
464}
465#endif /* NOSTREAMIO */
466//}}}
467
468#endif /* ! INCL_IMM_H */
Note: See TracBrowser for help on using the repository browser.