source: git/factory/imm.h @ 1bc850

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