My Project
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 #include "cf_assert.h"
82 
83 // temporarily switch off `CF_USE_INLINE' and include
84 // `canonicalform.h' if we are being translated.
85 // `CF_USE_INLINE_SAVE' is used to save the state of
86 // `CF_USE_INLINE'. It is unset after use.
87 #ifndef INCL_CF_INLINE_CC
88 #ifdef CF_USE_INLINE
89 #define CF_USE_INLINE_SAVE
90 #undef CF_USE_INLINE
91 #endif
92 #include "canonicalform.h"
93 #ifdef CF_USE_INLINE_SAVE
94 #define CF_USE_INLINE
95 #undef CF_USE_INLINE_SAVE
96 #endif
97 #endif /* ! INCL_CF_INLINE_CC */
98 
99 // regular include files
100 #include "int_cf.h"
101 #include "imm.h"
102 #include "cf_factory.h"
103 
104 // set the value of `CF_INLINE' for the following methods and
105 // functions
106 #if defined( CF_USE_INLINE ) && defined( INCL_CF_INLINE_CC )
107 #ifndef __CYGWIN__
108 #undef CF_INLINE
109 #define CF_INLINE inline
110 #endif
111 #else
112 #undef CF_INLINE
113 #define CF_INLINE
114 #endif /* ! defined( CF_USE_INLINE ) && defined( INCL_CF_INLINE_CC ) */
115 
116 // constructors, destructors, assignment
117 /** CF_INLINE CanonicalForm::CanonicalForm ()
118  *
119  *
120  * CanonicalForm() - create the default canonical form.
121  *
122  * The canonical form is initialized to zero from the current
123  * domain.
124  *
125 **/
126 CF_INLINE
128  : value( CFFactory::basic( 0 ) )
129 {
130 }
131 
132 /** CF_INLINE CanonicalForm::CanonicalForm ( const int i )
133  *
134  *
135  * CanonicalForm() - create a canonical form from an integer.
136  *
137  * The canonical form is initialized to the "canonical image" of
138  * `i' in the current domain. This is `i' itself for
139  * characteristic zero, `i' mod p for finite fields of
140  * characteristic p, and `i' mod p^n for prime power domains with
141  * p^n elements.
142  *
143 **/
144 #if SIZEOF_LONG == 8
145 CF_INLINE
147  : value( CFFactory::basic( i ) )
148 #else
149 CF_INLINE
151  : value( CFFactory::basic( (long)i ) )
152 #endif
153 {
154 }
155 
156 CF_INLINE
158  : value( CFFactory::basic( i ) )
159 {
160 }
161 
162 /** CF_INLINE CanonicalForm::CanonicalForm ( const CanonicalForm & cf )
163  *
164  *
165  * CanonicalForm() - create a copy of a canonical form.
166  *
167  * Type info:
168  * ----------
169  * cf: Anything
170  *
171 **/
172 CF_INLINE
174  : value( is_imm( cf.value ) ? cf.value : cf.value->copyObject() )
175 {
176 }
177 
178 /** CF_INLINE CanonicalForm::CanonicalForm ( InternalCF * cf )
179  *
180  *
181  * CanonicalForm() - create a canonical form from a pointer to an
182  * internal canonical form.
183  *
184  * This constructor is reserved for internal usage.
185  *
186  * Developers note:
187  * ----------------
188  * The canonical form gets its value immediately from `cf'.
189  * `cf's reference counter is not incremented, so be careful with
190  * this constructor.
191  *
192 **/
193 CF_INLINE
195  : value( cf )
196 {
197 }
198 
199 /** CF_INLINE CanonicalForm::CanonicalForm ( const Variable & v )
200  *
201  *
202  * CanonicalForm() - create a canonical form from a variable.
203  *
204  * If `v' is a polynomial variable or an algebraic element the
205  * resulting polynomial (or algebraic element) is 1*`v'^1, the
206  * one being from the current domain.
207  *
208  * Variables of level `LEVELBASE' are transformed to one from the
209  * current domain.
210  *
211  * Type info:
212  * ----------
213  * v: Anything
214  *
215 **/
216 CF_INLINE
218  : value( CFFactory::poly( v ) )
219 {
220 }
221 
222 /** CF_INLINE CanonicalForm::CanonicalForm ( const Variable & v, int e )
223  *
224  *
225  * CanonicalForm() - create a canonical form from a power of a
226  * variable.
227  *
228  * If `v' is a polynomial variable or an algebraic element the
229  * resulting polynomial (or algebraic element) is 1*`v'^`e', the
230  * one being from the current domain. Algebraic elements are
231  * reduced modulo their minimal polynomial.
232  *
233  * Variables of level `LEVELBASE' are transformed to one from the
234  * current domain.
235  *
236  * Type info:
237  * ----------
238  * v: Anything
239  *
240 **/
241 CF_INLINE
243  : value( CFFactory::poly( v, e ) )
244 {
245  //ASSERT( e > 0, "math error: exponent has to be positive" );
246 }
247 
248 #ifndef INCL_CF_INLINE_CC
249 /** CF_INLINE CanonicalForm::~CanonicalForm ()
250  *
251  *
252  * ~CanonicalForm() - delete CO.
253  *
254  * Type info:
255  * ----------
256  * CO: Anything
257  *
258 **/
259 CF_INLINE
261 {
262  if ( (! is_imm( value )) && value->deleteObject() )
263  delete value;
264 }
265 #endif
266 
267 #ifndef INCL_CF_INLINE_CC
268 /** CF_INLINE CanonicalForm & CanonicalForm::operator = ( const CanonicalForm & cf )
269  *
270  *
271  * operator =() - assign `cf' to CO.
272  *
273  * Type info:
274  * ----------
275  * CO, cf: Anything
276  *
277 **/
280 {
281  if ( this != &cf ) {
282  if ( (! is_imm( value )) && value->deleteObject() )
283  delete value;
284  value = (is_imm( cf.value )) ? cf.value : cf.value->copyObject();
285  }
286  return *this;
287 }
288 
289 /**
290  *
291  * operator =() - assign long `cf' to CO.
292  *
293  * `cf' converted to a canonical form as described in the
294  * canonical form constructor which creates a canonical form from
295  * an integer.
296  *
297  * Type info:
298  * ----------
299  * CO: Anything
300  *
301  * Developers note:
302  * ----------------
303  * Strictly speaking, this operator is superfluous. The ordinary
304  * assignment operator together with automatic conversion from
305  * `int' to `CanonicalForm' would do the job, too. But this way
306  * the common operation of assigning an integer is faster.
307  *
308 **/
310 CanonicalForm::operator = ( const long cf )
311 {
312  if ( (! is_imm( value )) && value->deleteObject() )
313  delete value;
315  return *this;
316 }
317 #endif
318 
319 // predicates
320 #ifndef INCL_CF_INLINE_CC
321 /** CF_INLINE bool CanonicalForm::isOne, isZero () const
322  *
323  *
324  * isOne(), isZero() - test whether a `CanonicalForm' equals one
325  * or zero, resp.
326  *
327  * The predicates `isOne()' and `isZero()' are much faster than
328  * the comparison operators. Furthermore, a test `f.isZero()' is
329  * independent from the current domain, whereas an expression
330  * `f == 0' is not.
331  *
332  * Type info:
333  * ----------
334  * CO: Anything
335  *
336  * Internal implementation:
337  * ------------------------
338  * Note that only immediate objects and objects of class
339  * `InternalPrimePower' may equal one or zero, resp.
340  *
341  * imm_isone(), imm_iszero()
342  * Trivial.
343  *
344  * imm_isone_p(), imm_iszero_p()
345  * Trivial.
346  *
347  * imm_isone_gf(), imm_iszero_gf()
348  * Use `gf_isone()' and `gf_iszero()', resp., to test whether CO
349  * equals zero or one, resp.
350  *
351  * InternalCF::isOne(), isZero()
352  * Always return false.
353  *
354  * InternalPrimePower::isOne(), isZero()
355  * Use `mpz_cpm_ui()' resp. `mpz_sgn()' to check the underlying
356  * mpi.
357  *
358  * @sa CanonicalForm::isZero()
359 **/
360 CF_INLINE bool
361 CanonicalForm::isOne () const
362 {
363  int what = is_imm( value );
364 
365  if ( ! what )
366  return value->isOne();
367  else if ( what == INTMARK )
368  return imm_isone( value );
369  else if ( what == FFMARK )
370  return imm_isone_p( value );
371  else
372  return imm_isone_gf( value );
373 }
374 
375 /**
376  * @sa CanonicalForm::isOne()
377 **/
378 CF_INLINE bool
379 CanonicalForm::isZero () const
380 {
381  int what = is_imm( value );
382 
383  if ( what == 0 )
384  return value->isZero();
385  else if ( what == INTMARK )
386  return imm_iszero( value );
387  else if ( what == FFMARK )
388  return imm_iszero_p( value );
389  else
390  return imm_iszero_gf( value );
391 }
392 #endif
393 
394 // arithmetic operators
395 #ifndef INCL_CF_INLINE_CC
396 /** CF_INLINE CanonicalForm operator - ( const CanonicalForm & cf )
397  *
398  *
399  * operator -() - return additive inverse of `cf'.
400  *
401  * Returns the additive inverse of `cf'. One should keep in mind
402  * that to negate a canonical form a complete (deep) copy of it
403  * has to be created.
404  *
405  * Type info:
406  * ----------
407  * cf: CurrentPP
408  *
409  * In fact, the type is almost `Anything', but it is, e.g., not
410  * possible to invert an element from a finite field when the
411  * characteristic of the current domain has changed.
412  *
413  * Internal implementation:
414  * ------------------------
415  * All internal methods check whether the reference counter
416  * equals one. If so CO is negated in-place. Otherwise, a new
417  * copy of CO is created and negated.
418  *
419  * imm_neg()
420  * Trivial.
421  *
422  * imm_neg_p()
423  * Use `ff_neg()' to negate CO.
424  *
425  * imm_neg_gf()
426  * Use `gf_neg()' to negate CO.
427  *
428  * InternalInteger::neg()
429  * Use `mpz_neg()' to negate the underlying mpi.
430  *
431  * InternalRational::neg ()
432  * Use `mpz_neg()' to negate the denominator.
433  *
434  * InternalPrimePower::neg()
435  * Subtract CO from `primepow' using `mpz_sub'.
436  *
437  * InternalPoly::neg()
438  * If reference counter is one use `negateTermList()' to negate
439  * the terms, otherwise create a negated copy using
440  * `copyTermList()'.
441  *
442  * @sa CanonicalForm::operator -=()
443 **/
445 operator - ( const CanonicalForm & cf )
446 {
448  int what = is_imm( result.value );
449 
450  if ( ! what )
451  result.value = result.value->neg();
452  else if ( what == INTMARK )
453  result.value = imm_neg( result.value );
454  else if ( what == FFMARK )
455  result.value = imm_neg_p( result.value );
456  else
457  result.value = imm_neg_gf( result.value );
458 
459  return result;
460 }
461 #endif
462 
463 // binary arithmetic operators and functions
464 /** CF_INLINE CanonicalForm operator +, -, *, /, % ( const CanonicalForm & lhs, const CanonicalForm & rhs )
465  *
466  *
467  * operators +, -, *, /, %(), div(), mod() - binary arithmetic
468  * operators.
469  *
470  * The binary operators have their standard (mathematical)
471  * semantics. As explained for the corresponding arithmetic
472  * assignment operators, the operators `/' and `%' return the
473  * quotient resp. remainder of (polynomial) division with
474  * remainder, whereas `div()' and `mod()' may be used for exact
475  * division and term-wise remaindering, resp.
476  *
477  * It is faster to use the arithmetic assignment operators (e.g.,
478  * `f += g;') instead of the binary operators (`f = f+g;' ).
479  *
480  * Type info:
481  * ----------
482  * lhs, rhs: CurrentPP
483  *
484  * There are weaker preconditions for some cases (e.g.,
485  * arithmetic operations with elements from Q or Z work in any
486  * domain), but type `CurrentPP' is the only one guaranteed to
487  * work for all cases.
488  *
489  * Developers note:
490  * ----------------
491  * All binary operators have their corresponding `CanonicalForm'
492  * assignment operators (e.g., `operator +()' corresponds to
493  * `CanonicalForm::operator +=()', `div()' corresponds to
494  * `CanonicalForm::div()).
495  *
496  * And that is how they are implemented, too: Each of the binary
497  * operators first creates a copy of `lhs', adds `rhs' to this
498  * copy using the assignment operator, and returns the result.
499  *
500  * @sa CanonicalForm::operator +=()
501 **/
503 operator + ( const CanonicalForm & lhs, const CanonicalForm & rhs )
504 {
505  CanonicalForm result( lhs );
506  result += rhs;
507  return result;
508 }
509 
510 #ifndef INCL_CF_INLINE_CC
512 operator - ( const CanonicalForm & lhs, const CanonicalForm & rhs )
513 {
514  CanonicalForm result( lhs );
515  result -= rhs;
516  return result;
517 }
518 #endif
519 
520 /**
521  * @sa CanonicalForm::operator *=()
522 **/
524 operator * ( const CanonicalForm & lhs, const CanonicalForm & rhs )
525 {
526  CanonicalForm result( lhs );
527  result *= rhs;
528  return result;
529 }
530 
531 #ifndef INCL_CF_INLINE_CC
532 /**
533  * @sa CanonicalForm::operator /=()
534 **/
536 operator / ( const CanonicalForm & lhs, const CanonicalForm & rhs )
537 {
538  CanonicalForm result( lhs );
539  result /= rhs;
540  return result;
541 }
542 
543 /**
544  * @sa CanonicalForm::operator %=()
545 **/
547 operator % ( const CanonicalForm & lhs, const CanonicalForm & rhs )
548 {
549  CanonicalForm result( lhs );
550  result %= rhs;
551  return result;
552 }
553 #endif
554 
555 #ifndef INCL_CF_INLINE_CC
556 /** CF_INLINE CanonicalForm div, mod ( const CanonicalForm & lhs, const CanonicalForm & rhs )
557  * @sa mod(), operator/(), CanonicalForm::operator /=()
558 **/
560 div ( const CanonicalForm & lhs, const CanonicalForm & rhs )
561 {
562  CanonicalForm result( lhs );
563  result.div( rhs );
564  return result;
565 }
566 
567 /**
568  * @sa div(), operator%(), CanonicalForm::operator %=()
569 **/
571 mod ( const CanonicalForm & lhs, const CanonicalForm & rhs )
572 {
573  CanonicalForm result( lhs );
574  result.mod( rhs );
575  return result;
576 }
577 #endif
Rational operator/(const Rational &a, const Rational &b)
Definition: GMPrat.cc:422
Header for factory's main class CanonicalForm.
CF_NO_INLINE FACTORY_PUBLIC CanonicalForm div(const CanonicalForm &, const CanonicalForm &)
CF_NO_INLINE FACTORY_PUBLIC CanonicalForm mod(const CanonicalForm &, const CanonicalForm &)
CF_NO_INLINE FACTORY_PUBLIC CanonicalForm operator%(const CanonicalForm &, const CanonicalForm &)
int is_imm(const InternalCF *const ptr)
Definition: canonicalform.h:65
int i
Definition: cfEzgcd.cc:132
else
Definition: cfGcdAlgExt.cc:195
CanonicalForm cf
Definition: cfModGcd.cc:4085
assertions for Factory
Interface to generate InternalCF's over various domains from intrinsic types or mpz_t's.
CF_INLINE CanonicalForm FACTORY_PUBLIC operator+(const CanonicalForm &lhs, const CanonicalForm &rhs)
CF_INLINE CanonicalForm operator +, -, *, /, % ( const CanonicalForm & lhs, const CanonicalForm & rhs...
Definition: cf_inline.cc:503
CF_INLINE CanonicalForm FACTORY_PUBLIC operator*(const CanonicalForm &lhs, const CanonicalForm &rhs)
Definition: cf_inline.cc:524
#define CF_INLINE
Definition: cf_inline.cc:109
static InternalCF * basic(int value)
Definition: cf_factory.cc:61
factory's main class
Definition: canonicalform.h:86
InternalCF * value
Definition: canonicalform.h:88
CF_NO_INLINE bool isZero() const
CF_NO_INLINE ~CanonicalForm()
CF_INLINE CanonicalForm()
CF_INLINE CanonicalForm::CanonicalForm ()
Definition: cf_inline.cc:127
CF_NO_INLINE bool isOne() const
CF_NO_INLINE CanonicalForm & operator=(const CanonicalForm &)
virtual class for internal CanonicalForm's
Definition: int_cf.h:47
virtual bool isZero() const
Definition: int_cf.cc:24
int deleteObject()
Definition: int_cf.h:61
InternalCF * copyObject()
Definition: int_cf.h:62
virtual bool isOne() const
bool InternalCF::isOne, isZero () const
Definition: int_cf.cc:18
factory's class for variables
Definition: factory.h:134
return result
Definition: facAbsBiFact.cc:75
const Variable & v
< [in] a sqrfree bivariate poly
Definition: facBivar.h:39
#define const
Definition: fegetopt.c:41
fglmVector operator-(const fglmVector &v)
Definition: fglmvec.cc:398
#define FACTORY_PUBLIC
Definition: globaldefs.h:25
operations on immediates, that is elements of F_p, GF, Z, Q that fit into intrinsic int,...
int imm_isone_p(const InternalCF *const ptr)
Definition: imm.h:130
int imm_isone(const InternalCF *const ptr)
Definition: imm.h:124
InternalCF * imm_neg_p(const InternalCF *const op)
Definition: imm.h:466
int imm_iszero(const InternalCF *const ptr)
Definition: imm.h:145
int imm_iszero_gf(const InternalCF *const ptr)
Definition: imm.h:157
InternalCF * imm_neg(const InternalCF *const op)
Definition: imm.h:460
const long FFMARK
Definition: imm.h:38
int imm_iszero_p(const InternalCF *const ptr)
Definition: imm.h:151
const long INTMARK
Definition: imm.h:37
int imm_isone_gf(const InternalCF *const ptr)
Definition: imm.h:136
InternalCF * imm_neg_gf(const InternalCF *const op)
Definition: imm.h:472
Factory's internal CanonicalForm's.