My Project  debian-1:4.1.1-p2+ds-4build1
cf_inline.cc
Go to the documentation of this file.
1 /* emacs edit mode for this file is -*- C++ -*- */
2 
3 /**
4  *
5  * @file cf_inline.cc
6  *
7  * definition of configurable inline
8  * `CanonicalForm' methods.
9  *
10  * Hierarchy: canonicalform
11  *
12  * Header file: canonicalform.h
13  *
14  * Developers note:
15  * ----------------
16  * The central class in Factory is, of course, `CanonicalForm'.
17  * Hence it is a quiet reasonable to assume that inlining its
18  * most important methods will improve execution speed. The same
19  * holds for some methods of the `CFIterator' class. Everything
20  * on configurable inline `CanonicalForm' methods explained here
21  * applies mutatis mutandis to the `CFIterator' methods.
22  *
23  * However, inlining `CanonicalForm' methods has two major
24  * drawbacks:
25  *
26  * o If `CanonicalForm' methods simply would have been declared
27  * `inline' it would have been necessary to include the
28  * definition of `InternalCF' in `factory.h'. This would have
29  * been quite a contradiction to the internal nature of the
30  * class.
31  * Hence it seemed desirable to introduce a mechanism to have
32  * both the inlined versions for internal use and compiled
33  * versions for the library.
34  *
35  * o Second, inlining in most cases leads to larger object code.
36  * E.g., inlining `CanonicalForm::~CanonicalForm()' increases the
37  * object code by approx. 15% without any effect on computation
38  * speed.
39  * Thus another design aim was to keep things configurable.
40  * That is why the methods defined here are called
41  * "configurable inline methods".
42  *
43  * The low level solution to both problems is the macro
44  * `CF_INLINE' which either expands to `inline' or nothing. The
45  * counterpart `CF_NO_INLINE' exists only for convenience, it
46  * always expands to nothing. `CF_INLINE' is set immediately
47  * before defining resp. declaring the methods to exclude any
48  * esoteric influences from included files.
49  *
50  * The high level interface is the macro `CF_USE_INLINE'. If it
51  * is defined any header file that uses configurable inline
52  * methods defines them to be `inline', otherwise they are
53  * defined as ordinary methods. `CF_USE_INLINE' is defined in
54  * `config.h' only.
55  *
56  * To switch on (off) all configurable inline methods, it is
57  * sufficient to define (undefine) `CF_USE_INLINE' in `config.h'.
58  * To switch off separate configurable inline methods it is
59  * necessary to prefix their declaration in `canonicalform.h' by
60  * `CF_NO_INLINE' instead of `CF_INLINE'. Furthermore, to avoid
61  * duplicate symbols at link time, their definition in this file
62  * has to be wrapped by an `#ifndef INCL_CF_INLINE_CC'.
63  *
64  * It turned out that inlining the following methods (and only
65  * them) results in the best time to size ratio on Linux and HP
66  * machines:
67  * o all `CanonicalForm' constructors
68  * o the binary `CanonicalForm' operators `+' and `*'
69  *
70 **/
71 
72 // check whether we are included or translated and
73 // define `INCL_CF_INLINE_CC' if we are included
74 #ifdef INCL_CANONICALFORM_H
75 #define INCL_CF_INLINE_CC
76 #endif
77 
78 
79 #include "config.h"
80 
81 
82 #include "cf_assert.h"
83 
84 // temporarily switch off `CF_USE_INLINE' and include
85 // `canonicalform.h' if we are being translated.
86 // `CF_USE_INLINE_SAVE' is used to save the state of
87 // `CF_USE_INLINE'. It is unset after use.
88 #ifndef INCL_CF_INLINE_CC
89 #ifdef CF_USE_INLINE
90 #define CF_USE_INLINE_SAVE
91 #undef CF_USE_INLINE
92 #endif
93 #include "canonicalform.h"
94 #ifdef CF_USE_INLINE_SAVE
95 #define CF_USE_INLINE
96 #undef CF_USE_INLINE_SAVE
97 #endif
98 #endif /* ! INCL_CF_INLINE_CC */
99 
100 // regular include files
101 #include "int_cf.h"
102 #include "imm.h"
103 #include "cf_factory.h"
104 
105 // set the value of `CF_INLINE' for the following methods and
106 // functions
107 #if defined( CF_USE_INLINE ) && defined( INCL_CF_INLINE_CC )
108 #undef CF_INLINE
109 #define CF_INLINE inline
110 #else
111 #undef CF_INLINE
112 #define CF_INLINE
113 #endif /* ! defined( CF_USE_INLINE ) && defined( INCL_CF_INLINE_CC ) */
114 
115 // constructors, destructors, assignment
116 /** CF_INLINE CanonicalForm::CanonicalForm ()
117  *
118  *
119  * CanonicalForm() - create the default canonical form.
120  *
121  * The canonical form is initialized to zero from the current
122  * domain.
123  *
124 **/
125 CF_INLINE
127  : value( CFFactory::basic( 0L ) )
128 {
129 }
130 
131 /** CF_INLINE CanonicalForm::CanonicalForm ( const int i )
132  *
133  *
134  * CanonicalForm() - create a canonical form from an integer.
135  *
136  * The canonical form is initialized to the "canonical image" of
137  * `i' in the current domain. This is `i' itself for
138  * characteristic zero, `i' mod p for finite fields of
139  * characteristic p, and `i' mod p^n for prime power domains with
140  * p^n elements.
141  *
142 **/
143 CF_INLINE
145  : value( CFFactory::basic( (const long)i ) )
146 {
147 }
148 
149 CF_INLINE
151  : value( CFFactory::basic( i ) )
152 {
153 }
154 
155 /** CF_INLINE CanonicalForm::CanonicalForm ( const CanonicalForm & cf )
156  *
157  *
158  * CanonicalForm() - create a copy of a canonical form.
159  *
160  * Type info:
161  * ----------
162  * cf: Anything
163  *
164 **/
165 CF_INLINE
167  : value( is_imm( cf.value ) ? cf.value : cf.value->copyObject() )
168 {
169 }
170 
171 /** CF_INLINE CanonicalForm::CanonicalForm ( InternalCF * cf )
172  *
173  *
174  * CanonicalForm() - create a canonical form from a pointer to an
175  * internal canonical form.
176  *
177  * This constructor is reserved for internal usage.
178  *
179  * Developers note:
180  * ----------------
181  * The canonical form gets its value immediately from `cf'.
182  * `cf's reference counter is not incremented, so be careful with
183  * this constructor.
184  *
185 **/
186 CF_INLINE
188  : value( cf )
189 {
190 }
191 
192 /** CF_INLINE CanonicalForm::CanonicalForm ( const Variable & v )
193  *
194  *
195  * CanonicalForm() - create a canonical form from a variable.
196  *
197  * If `v' is a polynomial variable or an algebraic element the
198  * resulting polynomial (or algebraic element) is 1*`v'^1, the
199  * one being from the current domain.
200  *
201  * Variables of level `LEVELBASE' are transformed to one from the
202  * current domain.
203  *
204  * Type info:
205  * ----------
206  * v: Anything
207  *
208 **/
209 CF_INLINE
211  : value( CFFactory::poly( v ) )
212 {
213 }
214 
215 /** CF_INLINE CanonicalForm::CanonicalForm ( const Variable & v, int e )
216  *
217  *
218  * CanonicalForm() - create a canonical form from a power of a
219  * variable.
220  *
221  * If `v' is a polynomial variable or an algebraic element the
222  * resulting polynomial (or algebraic element) is 1*`v'^`e', the
223  * one being from the current domain. Algebraic elements are
224  * reduced modulo their minimal polynomial.
225  *
226  * Variables of level `LEVELBASE' are transformed to one from the
227  * current domain.
228  *
229  * Type info:
230  * ----------
231  * v: Anything
232  *
233 **/
234 CF_INLINE
236  : value( CFFactory::poly( v, e ) )
237 {
238  //ASSERT( e > 0, "math error: exponent has to be positive" );
239 }
240 
241 #ifndef INCL_CF_INLINE_CC
242 /** CF_INLINE CanonicalForm::~CanonicalForm ()
243  *
244  *
245  * ~CanonicalForm() - delete CO.
246  *
247  * Type info:
248  * ----------
249  * CO: Anything
250  *
251 **/
252 CF_INLINE
254 {
255  if ( (! is_imm( value )) && value->deleteObject() )
256  delete value;
257 }
258 #endif
259 
260 #ifndef INCL_CF_INLINE_CC
261 /** CF_INLINE CanonicalForm & CanonicalForm::operator = ( const CanonicalForm & cf )
262  *
263  *
264  * operator =() - assign `cf' to CO.
265  *
266  * Type info:
267  * ----------
268  * CO, cf: Anything
269  *
270 **/
273 {
274  if ( this != &cf ) {
275  if ( (! is_imm( value )) && value->deleteObject() )
276  delete value;
277  value = (is_imm( cf.value )) ? cf.value : cf.value->copyObject();
278  }
279  return *this;
280 }
281 
282 /**
283  *
284  * operator =() - assign long `cf' to CO.
285  *
286  * `cf' converted to a canonical form as described in the
287  * canonical form constructor which creates a canonical form from
288  * an integer.
289  *
290  * Type info:
291  * ----------
292  * CO: Anything
293  *
294  * Developers note:
295  * ----------------
296  * Strictly speaking, this operator is superfluous. The ordinary
297  * assignment operator together with automatic conversion from
298  * `int' to `CanonicalForm' would do the job, too. But this way
299  * the common operation of assigning an integer is faster.
300  *
301 **/
304 {
305  if ( (! is_imm( value )) && value->deleteObject() )
306  delete value;
308  return *this;
309 }
310 #endif
311 
312 // predicates
313 #ifndef INCL_CF_INLINE_CC
314 /** CF_INLINE bool CanonicalForm::isOne, isZero () const
315  *
316  *
317  * isOne(), isZero() - test whether a `CanonicalForm' equals one
318  * or zero, resp.
319  *
320  * The predicates `isOne()' and `isZero()' are much faster than
321  * the comparison operators. Furthermore, a test `f.isZero()' is
322  * independent from the current domain, whereas an expression
323  * `f == 0' is not.
324  *
325  * Type info:
326  * ----------
327  * CO: Anything
328  *
329  * Internal implementation:
330  * ------------------------
331  * Note that only immediate objects and objects of class
332  * `InternalPrimePower' may equal one or zero, resp.
333  *
334  * imm_isone(), imm_iszero()
335  * Trivial.
336  *
337  * imm_isone_p(), imm_iszero_p()
338  * Trivial.
339  *
340  * imm_isone_gf(), imm_iszero_gf()
341  * Use `gf_isone()' and `gf_iszero()', resp., to test whether CO
342  * equals zero or one, resp.
343  *
344  * InternalCF::isOne(), isZero()
345  * Always return false.
346  *
347  * InternalPrimePower::isOne(), isZero()
348  * Use `mpz_cpm_ui()' resp. `mpz_sgn()' to check the underlying
349  * mpi.
350  *
351  * @sa CanonicalForm::isZero()
352 **/
353 CF_INLINE bool
355 {
356  int what = is_imm( value );
357 
358  if ( ! what )
359  return value->isOne();
360  else if ( what == INTMARK )
361  return imm_isone( value );
362  else if ( what == FFMARK )
363  return imm_isone_p( value );
364  else
365  return imm_isone_gf( value );
366 }
367 
368 /**
369  * @sa CanonicalForm::isOne()
370 **/
371 CF_INLINE bool
373 {
374  int what = is_imm( value );
375 
376  if ( what == 0 )
377  return value->isZero();
378  else if ( what == INTMARK )
379  return imm_iszero( value );
380  else if ( what == FFMARK )
381  return imm_iszero_p( value );
382  else
383  return imm_iszero_gf( value );
384 }
385 #endif
386 
387 // arithmetic operators
388 #ifndef INCL_CF_INLINE_CC
389 /** CF_INLINE CanonicalForm operator - ( const CanonicalForm & cf )
390  *
391  *
392  * operator -() - return additive inverse of `cf'.
393  *
394  * Returns the additive inverse of `cf'. One should keep in mind
395  * that to negate a canonical form a complete (deep) copy of it
396  * has to be created.
397  *
398  * Type info:
399  * ----------
400  * cf: CurrentPP
401  *
402  * In fact, the type is almost `Anything', but it is, e.g., not
403  * possible to invert an element from a finite field when the
404  * characteristic of the current domain has changed.
405  *
406  * Internal implementation:
407  * ------------------------
408  * All internal methods check whether the reference counter
409  * equals one. If so CO is negated in-place. Otherwise, a new
410  * copy of CO is created and negated.
411  *
412  * imm_neg()
413  * Trivial.
414  *
415  * imm_neg_p()
416  * Use `ff_neg()' to negate CO.
417  *
418  * imm_neg_gf()
419  * Use `gf_neg()' to negate CO.
420  *
421  * InternalInteger::neg()
422  * Use `mpz_neg()' to negate the underlying mpi.
423  *
424  * InternalRational::neg ()
425  * Use `mpz_neg()' to negate the denominator.
426  *
427  * InternalPrimePower::neg()
428  * Subtract CO from `primepow' using `mpz_sub'.
429  *
430  * InternalPoly::neg()
431  * If reference counter is one use `negateTermList()' to negate
432  * the terms, otherwise create a negated copy using
433  * `copyTermList()'.
434  *
435  * @sa CanonicalForm::operator -=()
436 **/
439 {
441  int what = is_imm( result.value );
442 
443  if ( ! what )
444  result.value = result.value->neg();
445  else if ( what == INTMARK )
446  result.value = imm_neg( result.value );
447  else if ( what == FFMARK )
448  result.value = imm_neg_p( result.value );
449  else
450  result.value = imm_neg_gf( result.value );
451 
452  return result;
453 }
454 #endif
455 
456 // binary arithmetic operators and functions
457 /** CF_INLINE CanonicalForm operator +, -, *, /, % ( const CanonicalForm & lhs, const CanonicalForm & rhs )
458  *
459  *
460  * operators +, -, *, /, %(), div(), mod() - binary arithmetic
461  * operators.
462  *
463  * The binary operators have their standard (mathematical)
464  * semantics. As explained for the corresponding arithmetic
465  * assignment operators, the operators `/' and `%' return the
466  * quotient resp. remainder of (polynomial) division with
467  * remainder, whereas `div()' and `mod()' may be used for exact
468  * division and term-wise remaindering, resp.
469  *
470  * It is faster to use the arithmetic assignment operators (e.g.,
471  * `f += g;') instead of the binary operators (`f = f+g;' ).
472  *
473  * Type info:
474  * ----------
475  * lhs, rhs: CurrentPP
476  *
477  * There are weaker preconditions for some cases (e.g.,
478  * arithmetic operations with elements from Q or Z work in any
479  * domain), but type `CurrentPP' is the only one guaranteed to
480  * work for all cases.
481  *
482  * Developers note:
483  * ----------------
484  * All binary operators have their corresponding `CanonicalForm'
485  * assignment operators (e.g., `operator +()' corresponds to
486  * `CanonicalForm::operator +=()', `div()' corresponds to
487  * `CanonicalForm::div()).
488  *
489  * And that is how they are implemented, too: Each of the binary
490  * operators first creates a copy of `lhs', adds `rhs' to this
491  * copy using the assignment operator, and returns the result.
492  *
493  * @sa CanonicalForm::operator +=()
494 **/
496 operator + ( const CanonicalForm & lhs, const CanonicalForm & rhs )
497 {
498  CanonicalForm result( lhs );
499  result += rhs;
500  return result;
501 }
502 
503 #ifndef INCL_CF_INLINE_CC
505 operator - ( const CanonicalForm & lhs, const CanonicalForm & rhs )
506 {
507  CanonicalForm result( lhs );
508  result -= rhs;
509  return result;
510 }
511 #endif
512 
513 /**
514  * @sa CanonicalForm::operator *=()
515 **/
517 operator * ( const CanonicalForm & lhs, const CanonicalForm & rhs )
518 {
519  CanonicalForm result( lhs );
520  result *= rhs;
521  return result;
522 }
523 
524 #ifndef INCL_CF_INLINE_CC
525 /**
526  * @sa CanonicalForm::operator /=()
527 **/
529 operator / ( const CanonicalForm & lhs, const CanonicalForm & rhs )
530 {
531  CanonicalForm result( lhs );
532  result /= rhs;
533  return result;
534 }
535 
536 /**
537  * @sa CanonicalForm::operator %=()
538 **/
540 operator % ( const CanonicalForm & lhs, const CanonicalForm & rhs )
541 {
542  CanonicalForm result( lhs );
543  result %= rhs;
544  return result;
545 }
546 #endif
547 
548 #ifndef INCL_CF_INLINE_CC
549 /** CF_INLINE CanonicalForm div, mod ( const CanonicalForm & lhs, const CanonicalForm & rhs )
550  * @sa mod(), operator/(), CanonicalForm::operator /=()
551 **/
553 div ( const CanonicalForm & lhs, const CanonicalForm & rhs )
554 {
555  CanonicalForm result( lhs );
556  result.div( rhs );
557  return result;
558 }
559 
560 /**
561  * @sa div(), operator%(), CanonicalForm::operator %=()
562 **/
564 mod ( const CanonicalForm & lhs, const CanonicalForm & rhs )
565 {
566  CanonicalForm result( lhs );
567  result.mod( rhs );
568  return result;
569 }
570 #endif
canonicalform.h
operator%
CF_INLINE CanonicalForm operator%(const CanonicalForm &lhs, const CanonicalForm &rhs)
Definition: cf_inline.cc:540
result
return result
Definition: facAbsBiFact.cc:76
cf
CanonicalForm cf
Definition: cfModGcd.cc:4024
InternalCF::isZero
virtual bool isZero() const
Definition: int_cf.cc:24
InternalCF
virtual class for internal CanonicalForm's
Definition: int_cf.h:41
imm_neg_gf
InternalCF * imm_neg_gf(const InternalCF *const op)
Definition: imm.h:467
InternalCF::isOne
virtual bool isOne() const
bool InternalCF::isOne, isZero () const
Definition: int_cf.cc:18
imm_neg_p
InternalCF * imm_neg_p(const InternalCF *const op)
Definition: imm.h:461
CanonicalForm
factory's main class
Definition: canonicalform.h:77
CanonicalForm::value
InternalCF * value
Definition: canonicalform.h:85
InternalCF::copyObject
InternalCF * copyObject()
Definition: int_cf.h:62
CanonicalForm::isOne
CF_NO_INLINE bool isOne() const
CF_INLINE bool CanonicalForm::isOne, isZero () const.
Definition: cf_inline.cc:354
i
int i
Definition: cfEzgcd.cc:125
operator-
CF_INLINE CanonicalForm operator-(const CanonicalForm &cf)
CF_INLINE CanonicalForm operator - ( const CanonicalForm & cf )
Definition: cf_inline.cc:438
INTMARK
const long INTMARK
Definition: imm.h:37
FFMARK
const long FFMARK
Definition: imm.h:38
int_cf.h
div
CF_INLINE CanonicalForm div(const CanonicalForm &lhs, const CanonicalForm &rhs)
CF_INLINE CanonicalForm div, mod ( const CanonicalForm & lhs, const CanonicalForm & rhs )
Definition: cf_inline.cc:553
CFFactory::basic
static InternalCF * basic(long value)
Definition: cf_factory.cc:30
CanonicalForm::CanonicalForm
CF_INLINE CanonicalForm()
CF_INLINE CanonicalForm::CanonicalForm ()
Definition: cf_inline.cc:126
imm_isone
int imm_isone(const InternalCF *const ptr)
Definition: imm.h:124
CF_INLINE
#define CF_INLINE
Definition: cf_inline.cc:112
CFFactory
Definition: cf_factory.h:23
CanonicalForm::~CanonicalForm
CF_NO_INLINE ~CanonicalForm()
CF_INLINE CanonicalForm::~CanonicalForm ()
Definition: cf_inline.cc:253
operator*
CF_INLINE CanonicalForm operator*(const CanonicalForm &lhs, const CanonicalForm &rhs)
Definition: cf_inline.cc:517
imm.h
imm_iszero_p
int imm_iszero_p(const InternalCF *const ptr)
Definition: imm.h:151
CanonicalForm::operator=
CF_NO_INLINE CanonicalForm & operator=(const CanonicalForm &)
CF_INLINE CanonicalForm & CanonicalForm::operator = ( const CanonicalForm & cf )
Definition: cf_inline.cc:272
InternalCF::deleteObject
int deleteObject()
Definition: int_cf.h:61
imm_iszero_gf
int imm_iszero_gf(const InternalCF *const ptr)
Definition: imm.h:157
cf_factory.h
const
#define const
Definition: fegetopt.c:40
Variable
factory's class for variables
Definition: factory.h:117
imm_iszero
int imm_iszero(const InternalCF *const ptr)
Definition: imm.h:145
mod
CF_INLINE CanonicalForm mod(const CanonicalForm &lhs, const CanonicalForm &rhs)
Definition: cf_inline.cc:564
is_imm
int is_imm(const InternalCF *const ptr)
Definition: canonicalform.h:62
imm_isone_gf
int imm_isone_gf(const InternalCF *const ptr)
Definition: imm.h:136
imm_isone_p
int imm_isone_p(const InternalCF *const ptr)
Definition: imm.h:130
operator/
CF_INLINE CanonicalForm operator/(const CanonicalForm &lhs, const CanonicalForm &rhs)
Definition: cf_inline.cc:529
cf_assert.h
imm_neg
InternalCF * imm_neg(const InternalCF *const op)
Definition: imm.h:455
v
const Variable & v
< [in] a sqrfree bivariate poly
Definition: facBivar.h:37
CanonicalForm::isZero
CF_NO_INLINE bool isZero() const
Definition: cf_inline.cc:372
operator+
CF_INLINE CanonicalForm operator+(const CanonicalForm &lhs, const CanonicalForm &rhs)
CF_INLINE CanonicalForm operator +, -, *, /, % ( const CanonicalForm & lhs, const CanonicalForm & rhs...
Definition: cf_inline.cc:496