source: git/factory/cf_inline.cc @ b1d287

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