source: git/factory/cf_inline.cc @ 3edea1

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