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 
37 const long INTMARK = 1;
38 const long FFMARK = 2;
39 const 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
51 const long MINIMMEDIATE = -268435454; // -2^28+2
52 const long MAXIMMEDIATE = 268435454;  // 2^28-2
53 #else
54 const long MINIMMEDIATE = -(1L<<60)+2L; // -2^60+2
55 const long MAXIMMEDIATE = (1L<<60)-2L;  // 2^60-2
56 #endif
57 
58 #if defined(WINNT) && ! defined(__GNUC__)
59 const FACTORY_INT64 MINIMMEDIATELL = -268435454i64;
60 const FACTORY_INT64 MAXIMMEDIATELL = 268435454i64;
61 #else
62 const FACTORY_INT64 MINIMMEDIATELL = -268435454LL;
63 const FACTORY_INT64 MAXIMMEDIATELL = 268435454LL;
64 #endif
65 
66 //{{{ conversion functions
67 //#ifdef HAS_ARITHMETIC_SHIFT
68 #if 1
69 
imm2int(const InternalCF * const imm)70 static inline long imm2int ( const InternalCF * const imm )
71 {
72     return ((intptr_t)imm) >> 2;
73 }
74 
int2imm(long i)75 static inline InternalCF * int2imm ( long i )
76 {
77     return (InternalCF*)((i << 2) | INTMARK );
78 }
79 
80 #else
81 
imm2int(const InternalCF * const imm)82 static 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 
int2imm(long i)91 static 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 
int2imm_p(long i)101 inline InternalCF * int2imm_p ( long i )
102 {
103     return (InternalCF*)((i << 2) | FFMARK );
104 }
105 
int2imm_gf(long i)106 inline InternalCF * int2imm_gf ( long i )
107 {
108     return (InternalCF*)((i << 2) | GFMARK );
109 }
110 //}}}
111 
112 // predicates
113 #if 0
114 inline 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()
123 inline int
imm_isone(const InternalCF * const ptr)124 imm_isone ( const InternalCF * const ptr )
125 {
126     return imm2int( ptr ) == 1;
127 }
128 
129 inline int
imm_isone_p(const InternalCF * const ptr)130 imm_isone_p ( const InternalCF * const ptr )
131 {
132     return imm2int( ptr ) == 1;
133 }
134 
135 inline int
imm_isone_gf(const InternalCF * const ptr)136 imm_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()
144 inline int
imm_iszero(const InternalCF * const ptr)145 imm_iszero ( const InternalCF * const ptr )
146 {
147     return imm2int( ptr ) == 0;
148 }
149 
150 inline int
imm_iszero_p(const InternalCF * const ptr)151 imm_iszero_p ( const InternalCF * const ptr )
152 {
153     return imm2int( ptr ) == 0;
154 }
155 
156 inline int
imm_iszero_gf(const InternalCF * const ptr)157 imm_iszero_gf ( const InternalCF * const ptr )
158 {
159     return gf_iszero( imm2int( ptr ) );
160 }
161 //}}}
162 
163 //{{{ conversion functions
imm_intval(const InternalCF * const op)164 inline 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 **/
199 inline int
imm_sign(const InternalCF * const op)200 imm_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 **/
236 inline int
imm_cmp(const InternalCF * const lhs,const InternalCF * const rhs)237 imm_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 
247 inline int
imm_cmp_p(const InternalCF * const lhs,const InternalCF * const rhs)248 imm_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 
258 inline int
imm_cmp_gf(const InternalCF * const lhs,const InternalCF * const rhs)259 imm_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
imm_add(const InternalCF * const lhs,const InternalCF * const rhs)272 inline 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 
imm_add_p(const InternalCF * const lhs,const InternalCF * const rhs)281 inline 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 
imm_add_gf(const InternalCF * const lhs,const InternalCF * const rhs)286 inline 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 
imm_sub(const InternalCF * const lhs,const InternalCF * const rhs)291 inline 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 
imm_sub_p(const InternalCF * const lhs,const InternalCF * const rhs)300 inline 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 
imm_sub_gf(const InternalCF * const lhs,const InternalCF * const rhs)305 inline 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 
310 inline InternalCF *
imm_mul(InternalCF * lhs,InternalCF * rhs)311 imm_mul ( InternalCF * lhs, InternalCF * rhs )
312 {
313     long a = imm2int( lhs );
314     if (a == 0L)
315       return int2imm(0);
316     long b = imm2int( rhs );
317     int sa= 1;
318     unsigned FACTORY_INT64 aa, bb;
319     if (a < 0)
320     {
321       sa= -1;
322       aa= (unsigned FACTORY_INT64) (-a);
323     }
324     else
325       aa= (unsigned FACTORY_INT64) a;
326     if (b < 0)
327     {
328       sa= -sa;
329       bb= (unsigned FACTORY_INT64) (-b);
330     }
331     else
332       bb= (unsigned FACTORY_INT64) b;
333     unsigned FACTORY_INT64 result = aa*bb;
334     #if SIZEOF_LONG == 4
335     if (result>(unsigned FACTORY_INT64)MAXIMMEDIATE)
336     {
337         InternalCF * res = CFFactory::basic( IntegerDomain, a, true );
338         return res->mulcoeff( rhs );
339     }
340     #else
341     if ( ((result/aa!=bb) || (result>(unsigned FACTORY_INT64) MAXIMMEDIATE) ))
342     {
343         InternalCF * res = CFFactory::basic( IntegerDomain, a, true );
344         return res->mulcoeff( rhs );
345     }
346     #endif
347     else
348       return int2imm( sa*result );
349 }
350 
imm_mul_p(const InternalCF * const lhs,const InternalCF * const rhs)351 inline InternalCF * imm_mul_p ( const InternalCF * const lhs, const InternalCF * const rhs )
352 {
353     return int2imm_p( ff_mul( imm2int( lhs ), imm2int( rhs ) ) );
354 }
355 
imm_mul_gf(const InternalCF * const lhs,const InternalCF * const rhs)356 inline InternalCF * imm_mul_gf ( const InternalCF * const lhs, const InternalCF * const rhs )
357 {
358     return int2imm_gf( gf_mul( imm2int( lhs ), imm2int( rhs ) ) );
359 }
360 
imm_div(const InternalCF * const lhs,const InternalCF * const rhs)361 inline InternalCF * imm_div ( const InternalCF * const lhs, const InternalCF * const rhs )
362 {
363     long a = imm2int( lhs );
364     long b = imm2int( rhs );
365     if ( a > 0 )
366         return int2imm( a / b );
367     else  if ( b > 0 )
368         return int2imm( -((b-a-1)/b) );
369     else
370         return int2imm( (-a-b-1)/(-b) );
371 }
372 
imm_divrat(const InternalCF * const lhs,const InternalCF * const rhs)373 inline InternalCF * imm_divrat ( const InternalCF * const lhs, const InternalCF * const rhs )
374 {
375     if ( cf_glob_switches.isOn( SW_RATIONAL ) )
376         return CFFactory::rational( imm2int( lhs ), imm2int( rhs ) );
377     else {
378         long a = imm2int( lhs );
379         long b = imm2int( rhs );
380         if ( a > 0 )
381             return int2imm( a / b );
382         else  if ( b > 0 )
383             return int2imm( -((b-a-1)/b) );
384         else
385             return int2imm( (-a-b-1)/(-b) );
386     }
387 }
388 
imm_div_p(const InternalCF * const lhs,const InternalCF * const rhs)389 inline InternalCF * imm_div_p ( const InternalCF * const lhs, const InternalCF * const rhs )
390 {
391     return int2imm_p( ff_div( imm2int( lhs ), imm2int( rhs ) ) );
392 }
393 
imm_div_gf(const InternalCF * const lhs,const InternalCF * const rhs)394 inline InternalCF * imm_div_gf ( const InternalCF * const lhs, const InternalCF * const rhs )
395 {
396     return int2imm_gf( gf_div( imm2int( lhs ), imm2int( rhs ) ) );
397 }
398 
imm_mod(const InternalCF * const lhs,const InternalCF * const rhs)399 inline InternalCF * imm_mod ( const InternalCF * const lhs, const InternalCF * const rhs )
400 {
401     if ( cf_glob_switches.isOn( SW_RATIONAL ) )
402         return int2imm( 0 );
403     else {
404         long a = imm2int( lhs );
405         long b = imm2int( rhs );
406         if ( a > 0 )
407             if ( b > 0 )
408                 return int2imm( a % b );
409             else
410                 return int2imm( a % (-b) );
411         else
412             if ( b > 0 ) {
413                 long r = (-a) % b;
414                 return int2imm( (r==0) ? r : b-r );
415             }
416             else {
417                 long r = (-a) % (-b);
418                 return int2imm( (r==0) ? r : -b-r );
419             }
420     }
421 }
422 
imm_mod_p(const InternalCF * const,const InternalCF * const)423 inline InternalCF * imm_mod_p ( const InternalCF * const, const InternalCF * const )
424 {
425     return int2imm_p( 0 );
426 }
427 
imm_mod_gf(const InternalCF * const,const InternalCF * const)428 inline InternalCF * imm_mod_gf ( const InternalCF * const, const InternalCF * const )
429 {
430     return int2imm_gf( gf_q );
431 }
432 
imm_divrem(const InternalCF * const lhs,const InternalCF * const rhs,InternalCF * & q,InternalCF * & r)433 inline void imm_divrem ( const InternalCF * const lhs, const InternalCF * const rhs, InternalCF * & q, InternalCF * & r )
434 {
435     if ( cf_glob_switches.isOn( SW_RATIONAL ) ) {
436         q = imm_divrat( lhs, rhs );
437         r = CFFactory::basic( 0L );
438     }
439     else {
440         q = imm_div( lhs, rhs );
441         r = imm_mod( lhs, rhs );
442     }
443 }
444 
imm_divrem_p(const InternalCF * const lhs,const InternalCF * const rhs,InternalCF * & q,InternalCF * & r)445 inline void imm_divrem_p ( const InternalCF * const lhs, const InternalCF * const rhs, InternalCF * & q, InternalCF * & r )
446 {
447     q = int2imm_p( ff_div( imm2int( lhs ), imm2int( rhs ) ) );
448     r = int2imm_p( 0 );
449 }
450 
imm_divrem_gf(const InternalCF * const lhs,const InternalCF * const rhs,InternalCF * & q,InternalCF * & r)451 inline void imm_divrem_gf ( const InternalCF * const lhs, const InternalCF * const rhs, InternalCF * & q, InternalCF * & r )
452 {
453     q = int2imm_gf( gf_div( imm2int( lhs ), imm2int( rhs ) ) );
454     r = int2imm_gf( gf_q );
455 }
456 
457 //{{{ inline InternalCF * imm_neg, imm_neg_p, imm_neg_gf ( const InternalCF * const op )
458 // docu: see CanonicalForm::operator -()
459 inline InternalCF *
imm_neg(const InternalCF * const op)460 imm_neg ( const InternalCF * const op )
461 {
462     return int2imm( -imm2int( op ) );
463 }
464 
465 inline InternalCF *
imm_neg_p(const InternalCF * const op)466 imm_neg_p ( const InternalCF * const op )
467 {
468     return int2imm_p( ff_neg( imm2int( op ) ) );
469 }
470 
471 inline InternalCF *
imm_neg_gf(const InternalCF * const op)472 imm_neg_gf ( const InternalCF * const op )
473 {
474     return int2imm_gf( gf_neg( imm2int( op ) ) );
475 }
476 //}}}
477 //}}}
478 
479 //{{{ input/output
480 #ifndef NOSTREAMIO
imm_print(OSTREAM & os,const InternalCF * const op,const char * const str)481 inline void imm_print ( OSTREAM & os, const InternalCF * const op, const char * const str )
482 {
483     if ( is_imm( op ) == FFMARK )
484         if ( cf_glob_switches.isOn( SW_SYMMETRIC_FF ) )
485             os << ff_symmetric( imm2int( op ) ) << str;
486         else
487             os << imm2int( op ) << str;
488     else  if ( is_imm( op ) == GFMARK ) {
489         gf_print( os, imm2int( op ) );
490         os << str;
491     }
492     else
493         os << imm2int( op ) << str;
494 }
495 #endif /* NOSTREAMIO */
496 //}}}
497 
498 #endif /* ! INCL_IMM_H */
499