source: git/factory/imm.h @ 021751

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