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**/
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
147 : value( CFFactory::basic( i ) )
148#else
151 : value( CFFactory::basic( (long)i ) )
152#endif
153{
154}
155
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**/
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**/
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**/
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**/
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**/
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**/
310CanonicalForm::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**/
360CF_INLINE bool
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**/
378CF_INLINE bool
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**/
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**/
503operator + ( 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
512operator - ( 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**/
524operator * ( 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**/
536operator / ( 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**/
547operator % ( 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**/
560div ( 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**/
571mod ( 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:4083
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
InternalCF * copyObject()
Definition: int_cf.h:62
virtual bool isZero() const
Definition: int_cf.cc:24
int deleteObject()
Definition: int_cf.h:61
virtual bool isOne() const
bool InternalCF::isOne, isZero () const
Definition: int_cf.cc:18
factory's class for variables
Definition: factory.h:127
return result
Definition: facAbsBiFact.cc:75
const Variable & v
< [in] a sqrfree bivariate poly
Definition: facBivar.h:39
#define const
Definition: fegetopt.c:39
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
int imm_iszero(const InternalCF *const ptr)
Definition: imm.h:145
int imm_iszero_gf(const InternalCF *const ptr)
Definition: imm.h:157
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
InternalCF * imm_neg_p(const InternalCF *const op)
Definition: imm.h:466
int imm_isone_gf(const InternalCF *const ptr)
Definition: imm.h:136
InternalCF * imm_neg(const InternalCF *const op)
Definition: imm.h:460
InternalCF * imm_neg_gf(const InternalCF *const op)
Definition: imm.h:472
Factory's internal CanonicalForm's.