source: git/factory/cf_inline.cc @ be587d

spielwiese
Last change on this file since be587d was be587d, checked in by Hans Schoenemann <hannes@…>, 5 years ago
compiler warnings in factory
  • 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
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**/
125CF_INLINE
126CanonicalForm::CanonicalForm ()
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**/
143CF_INLINE
144CanonicalForm::CanonicalForm ( const int i )
145    : value( CFFactory::basic( (long)i ) )
146{
147}
148
149CF_INLINE
150CanonicalForm::CanonicalForm ( const long i )
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**/
165CF_INLINE
166CanonicalForm::CanonicalForm ( const CanonicalForm & cf )
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**/
186CF_INLINE
187CanonicalForm::CanonicalForm ( InternalCF * cf )
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**/
209CF_INLINE
210CanonicalForm::CanonicalForm ( const Variable & v )
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**/
234CF_INLINE
235CanonicalForm::CanonicalForm ( const Variable & v, int e )
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**/
252CF_INLINE
253CanonicalForm::~CanonicalForm ()
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**/
271CF_INLINE CanonicalForm &
272CanonicalForm::operator = ( const CanonicalForm & cf )
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**/
302CF_INLINE CanonicalForm &
303CanonicalForm::operator = ( const long cf )
304{
305    if ( (! is_imm( value )) && value->deleteObject() )
306        delete value;
307    value = CFFactory::basic( cf );
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**/
353CF_INLINE bool
354CanonicalForm::isOne () const
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**/
371CF_INLINE bool
372CanonicalForm::isZero () const
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**/
437CF_INLINE CanonicalForm
438operator - ( const CanonicalForm & cf )
439{
440    CanonicalForm result( cf );
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**/
495CF_INLINE CanonicalForm
496operator + ( 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
504CF_INLINE CanonicalForm
505operator - ( 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**/
516CF_INLINE CanonicalForm
517operator * ( 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**/
528CF_INLINE CanonicalForm
529operator / ( 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**/
539CF_INLINE CanonicalForm
540operator % ( 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**/
552CF_INLINE CanonicalForm
553div ( 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**/
563CF_INLINE CanonicalForm
564mod ( const CanonicalForm & lhs, const CanonicalForm & rhs )
565{
566    CanonicalForm result( lhs );
567    result.mod( rhs );
568    return result;
569}
570#endif
Note: See TracBrowser for help on using the repository browser.