source: git/factory/imm.h @ 80b8fe

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