source: git/factory/imm.h @ a723558

fieker-DuValspielwiese
Last change on this file since a723558 was be587d, checked in by Hans Schoenemann <hannes@…>, 5 years ago
compiler warnings in factory
  • 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    {
168        if ( cf_glob_switches.isOn( SW_SYMMETRIC_FF ) )
169            return ff_symmetric( imm2int( op ) );
170        else
171            return imm2int( op );
172    }
173    else  if ( is_imm( op ) == GFMARK )
174    {
175        ASSERT( gf_isff( imm2int( op ) ), "invalid conversion" );
176        if ( cf_glob_switches.isOn( SW_SYMMETRIC_FF ) )
177            return ff_symmetric( gf_gf2ff( imm2int( op ) ) );
178        else
179            return gf_gf2ff( imm2int( op ) );
180    }
181    /*else*/
182        return imm2int( op );
183}
184//}}}
185
186/**
187 *
188 * imm_sign() - return sign of immediate object.
189 *
190 * If CO is an immediate integer, the sign is defined as usual.
191 * If CO is an element of FF(p) and SW_SYMMETRIC_FF is on the
192 * sign of CO is the sign of the symmetric representation of CO.
193 * If CO is in GF(q) or in FF(p) and SW_SYMMETRIC_FF is off, the
194 * sign of CO is zero iff CO is zero, otherwise the sign is one.
195 *
196 * @sa CanonicalForm::sign(), gf_sign()
197 *
198**/
199inline int
200imm_sign ( const InternalCF * const op )
201{
202    if ( is_imm( op ) == FFMARK )
203        if ( imm2int( op ) == 0 )
204            return 0;
205        else  if ( cf_glob_switches.isOn( SW_SYMMETRIC_FF ) )
206            if ( ff_symmetric( imm2int( op ) ) > 0 )
207                return 1;
208            else
209                return -1;
210        else
211            return 1;
212    else  if ( is_imm( op ) == GFMARK )
213        return gf_sign( imm2int( op ) );
214    else  if ( imm2int( op ) == 0 )
215        return 0;
216    else  if ( imm2int( op ) > 0 )
217        return 1;
218    else
219        return -1;
220}
221
222/**
223 *
224 * imm_cmp(), imm_cmp_p(), imm_cmp_gf() - compare immediate objects.
225 *
226 * For immediate integers, it is clear how this should be done.
227 * For objects from finite fields, it is not clear since they
228 * are not ordered fields.  However, since we want to have a
229 * total well order on polynomials we have to define a total well
230 * order on all coefficients, too. We decided to use simply the
231 * order on the representation as `int's of such objects.
232 *
233 * @sa CanonicalForm::operator <(), CanonicalForm::operator ==()
234 *
235**/
236inline int
237imm_cmp ( const InternalCF * const lhs, const InternalCF * const rhs )
238{
239    if ( imm2int( lhs ) == imm2int( rhs ) )
240        return 0;
241    else  if ( imm2int( lhs ) > imm2int( rhs ) )
242        return 1;
243    else
244        return -1;
245}
246
247inline int
248imm_cmp_p ( const InternalCF * const lhs, const InternalCF * const rhs )
249{
250    if ( imm2int( lhs ) == imm2int( rhs ) )
251        return 0;
252    else if ( imm2int( lhs ) > imm2int( rhs ) )
253        return 1;
254    else
255        return -1;
256}
257
258inline int
259imm_cmp_gf ( const InternalCF * const lhs, const InternalCF * const rhs )
260{
261    if ( imm2int( lhs ) == imm2int( rhs ) )
262        return 0;
263    // check is done in this way because zero should be minimal
264    else if ( imm2int( lhs ) > imm2int( rhs ) )
265        return -1;
266    else
267        return 1;
268}
269//}}}
270
271//{{{ arithmetic operators
272inline InternalCF * imm_add ( const InternalCF * const lhs, const InternalCF * const rhs )
273{
274    long result = imm2int( lhs ) + imm2int( rhs );
275    if ( ( result > MAXIMMEDIATE ) || ( result < MINIMMEDIATE ) )
276        return CFFactory::basic( result );
277    else
278        return int2imm( result );
279}
280
281inline InternalCF * imm_add_p ( const InternalCF * const lhs, const InternalCF * const rhs )
282{
283    return int2imm_p( ff_add( imm2int( lhs ), imm2int( rhs ) ) );
284}
285
286inline InternalCF * imm_add_gf ( const InternalCF * const lhs, const InternalCF * const rhs )
287{
288    return int2imm_gf( gf_add( imm2int( lhs ), imm2int( rhs ) ) );
289}
290
291inline InternalCF * imm_sub ( const InternalCF * const lhs, const InternalCF * const rhs )
292{
293    long result = imm2int( lhs ) - imm2int( rhs );
294    if ( ( result > MAXIMMEDIATE ) || ( result < MINIMMEDIATE ) )
295        return CFFactory::basic( result );
296    else
297        return int2imm( result );
298}
299
300inline InternalCF * imm_sub_p ( const InternalCF * const lhs, const InternalCF * const rhs )
301{
302    return int2imm_p( ff_sub( imm2int( lhs ), imm2int( rhs ) ) );
303}
304
305inline InternalCF * imm_sub_gf ( const InternalCF * const lhs, const InternalCF * const rhs )
306{
307    return int2imm_gf( gf_sub( imm2int( lhs ), imm2int( rhs ) ) );
308}
309
310inline InternalCF *
311imm_mul ( InternalCF * lhs, InternalCF * rhs )
312{
313    long a = imm2int( lhs );
314    long b = imm2int( rhs );
315    int sa= 1;
316    unsigned FACTORY_INT64 aa, bb;
317    if (a < 0)
318    {
319      sa= -1;
320      aa= (unsigned FACTORY_INT64) (-a);
321    }
322    else
323      aa= (unsigned FACTORY_INT64) a;
324    if (b < 0)
325    {
326      sa= -sa;
327      bb= (unsigned FACTORY_INT64) (-b);
328    }
329    else
330      bb= (unsigned FACTORY_INT64) b;
331    unsigned FACTORY_INT64 result = aa*bb;
332    #if SIZEOF_LONG == 4
333    if (result>(unsigned FACTORY_INT64)MAXIMMEDIATE)
334    {
335        InternalCF * res = CFFactory::basic( IntegerDomain, a, true );
336        return res->mulcoeff( rhs );
337    }
338    #else
339    if ( ( a!=0L ) && ((result/aa!=bb) || (result>(unsigned FACTORY_INT64) MAXIMMEDIATE) ))
340    {
341        InternalCF * res = CFFactory::basic( IntegerDomain, a, true );
342        return res->mulcoeff( rhs );
343    }
344    #endif
345    else
346      return int2imm( sa*result );
347}
348
349inline InternalCF * imm_mul_p ( const InternalCF * const lhs, const InternalCF * const rhs )
350{
351    return int2imm_p( ff_mul( imm2int( lhs ), imm2int( rhs ) ) );
352}
353
354inline InternalCF * imm_mul_gf ( const InternalCF * const lhs, const InternalCF * const rhs )
355{
356    return int2imm_gf( gf_mul( imm2int( lhs ), imm2int( rhs ) ) );
357}
358
359inline InternalCF * imm_div ( const InternalCF * const lhs, const InternalCF * const rhs )
360{
361    long a = imm2int( lhs );
362    long b = imm2int( rhs );
363    if ( a > 0 )
364        return int2imm( a / b );
365    else  if ( b > 0 )
366        return int2imm( -((b-a-1)/b) );
367    else
368        return int2imm( (-a-b-1)/(-b) );
369}
370
371inline InternalCF * imm_divrat ( const InternalCF * const lhs, const InternalCF * const rhs )
372{
373    if ( cf_glob_switches.isOn( SW_RATIONAL ) )
374        return CFFactory::rational( imm2int( lhs ), imm2int( rhs ) );
375    else {
376        long a = imm2int( lhs );
377        long b = imm2int( rhs );
378        if ( a > 0 )
379            return int2imm( a / b );
380        else  if ( b > 0 )
381            return int2imm( -((b-a-1)/b) );
382        else
383            return int2imm( (-a-b-1)/(-b) );
384    }
385}
386
387inline InternalCF * imm_div_p ( const InternalCF * const lhs, const InternalCF * const rhs )
388{
389    return int2imm_p( ff_div( imm2int( lhs ), imm2int( rhs ) ) );
390}
391
392inline InternalCF * imm_div_gf ( const InternalCF * const lhs, const InternalCF * const rhs )
393{
394    return int2imm_gf( gf_div( imm2int( lhs ), imm2int( rhs ) ) );
395}
396
397inline InternalCF * imm_mod ( const InternalCF * const lhs, const InternalCF * const rhs )
398{
399    if ( cf_glob_switches.isOn( SW_RATIONAL ) )
400        return int2imm( 0 );
401    else {
402        long a = imm2int( lhs );
403        long b = imm2int( rhs );
404        if ( a > 0 )
405            if ( b > 0 )
406                return int2imm( a % b );
407            else
408                return int2imm( a % (-b) );
409        else
410            if ( b > 0 ) {
411                long r = (-a) % b;
412                return int2imm( (r==0) ? r : b-r );
413            }
414            else {
415                long r = (-a) % (-b);
416                return int2imm( (r==0) ? r : -b-r );
417            }
418    }
419}
420
421inline InternalCF * imm_mod_p ( const InternalCF * const, const InternalCF * const )
422{
423    return int2imm_p( 0 );
424}
425
426inline InternalCF * imm_mod_gf ( const InternalCF * const, const InternalCF * const )
427{
428    return int2imm_gf( gf_q );
429}
430
431inline void imm_divrem ( const InternalCF * const lhs, const InternalCF * const rhs, InternalCF * & q, InternalCF * & r )
432{
433    if ( cf_glob_switches.isOn( SW_RATIONAL ) ) {
434        q = imm_divrat( lhs, rhs );
435        r = CFFactory::basic( 0L );
436    }
437    else {
438        q = imm_div( lhs, rhs );
439        r = imm_mod( lhs, rhs );
440    }
441}
442
443inline void imm_divrem_p ( const InternalCF * const lhs, const InternalCF * const rhs, InternalCF * & q, InternalCF * & r )
444{
445    q = int2imm_p( ff_div( imm2int( lhs ), imm2int( rhs ) ) );
446    r = int2imm_p( 0 );
447}
448
449inline void imm_divrem_gf ( const InternalCF * const lhs, const InternalCF * const rhs, InternalCF * & q, InternalCF * & r )
450{
451    q = int2imm_gf( gf_div( imm2int( lhs ), imm2int( rhs ) ) );
452    r = int2imm_gf( gf_q );
453}
454
455//{{{ inline InternalCF * imm_neg, imm_neg_p, imm_neg_gf ( const InternalCF * const op )
456// docu: see CanonicalForm::operator -()
457inline InternalCF *
458imm_neg ( const InternalCF * const op )
459{
460    return int2imm( -imm2int( op ) );
461}
462
463inline InternalCF *
464imm_neg_p ( const InternalCF * const op )
465{
466    return int2imm_p( ff_neg( imm2int( op ) ) );
467}
468
469inline InternalCF *
470imm_neg_gf ( const InternalCF * const op )
471{
472    return int2imm_gf( gf_neg( imm2int( op ) ) );
473}
474//}}}
475//}}}
476
477//{{{ input/output
478#ifndef NOSTREAMIO
479inline void imm_print ( OSTREAM & os, const InternalCF * const op, const char * const str )
480{
481    if ( is_imm( op ) == FFMARK )
482        if ( cf_glob_switches.isOn( SW_SYMMETRIC_FF ) )
483            os << ff_symmetric( imm2int( op ) ) << str;
484        else
485            os << imm2int( op ) << str;
486    else  if ( is_imm( op ) == GFMARK ) {
487        gf_print( os, imm2int( op ) );
488        os << str;
489    }
490    else
491        os << imm2int( op ) << str;
492}
493#endif /* NOSTREAMIO */
494//}}}
495
496#endif /* ! INCL_IMM_H */
Note: See TracBrowser for help on using the repository browser.