source: git/factory/cf_inline.cc @ 2234726

fieker-DuValspielwiese
Last change on this file since 2234726 was c862f0, checked in by Hans Schoenemann <hannes@…>, 3 years ago
cygwin port: shared lib libfactory
  • Property mode set to 100644
File size: 14.9 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#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**/
126CF_INLINE
127CanonicalForm::CanonicalForm ()
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
145CF_INLINE
146CanonicalForm::CanonicalForm ( const int i )
147    : value( CFFactory::basic( i ) )
148#else
149CF_INLINE
150CanonicalForm::CanonicalForm ( const int i )
151    : value( CFFactory::basic( (long)i ) )
152#endif
153{
154}
155
156CF_INLINE
157CanonicalForm::CanonicalForm ( const long i )
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**/
172CF_INLINE
173CanonicalForm::CanonicalForm ( const CanonicalForm & cf )
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**/
193CF_INLINE
194CanonicalForm::CanonicalForm ( InternalCF * cf )
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**/
216CF_INLINE
217CanonicalForm::CanonicalForm ( const Variable & v )
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**/
241CF_INLINE
242CanonicalForm::CanonicalForm ( const Variable & v, int e )
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**/
259CF_INLINE
260CanonicalForm::~CanonicalForm ()
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**/
278CF_INLINE CanonicalForm &
279CanonicalForm::operator = ( const CanonicalForm & cf )
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**/
309CF_INLINE CanonicalForm &
310CanonicalForm::operator = ( const long cf )
311{
312    if ( (! is_imm( value )) && value->deleteObject() )
313        delete value;
314    value = CFFactory::basic( cf );
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
361CanonicalForm::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**/
378CF_INLINE bool
379CanonicalForm::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**/
444CF_INLINE CanonicalForm
445operator - ( const CanonicalForm & cf )
446{
447    CanonicalForm result( cf );
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**/
502CF_INLINE CanonicalForm FACTORY_PUBLIC
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
511CF_INLINE CanonicalForm FACTORY_PUBLIC
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**/
523CF_INLINE CanonicalForm FACTORY_PUBLIC
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**/
535CF_INLINE CanonicalForm FACTORY_PUBLIC
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**/
546CF_INLINE CanonicalForm FACTORY_PUBLIC
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**/
559CF_INLINE CanonicalForm
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**/
570CF_INLINE CanonicalForm
571mod ( const CanonicalForm & lhs, const CanonicalForm & rhs )
572{
573    CanonicalForm result( lhs );
574    result.mod( rhs );
575    return result;
576}
577#endif
Note: See TracBrowser for help on using the repository browser.