source: git/factory/cf_inline.cc @ d87069

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