source: git/factory/imm.h @ eaa04d

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