source: git/factory/cf_inline.cc @ 5c3ea9

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