source: git/factory/cf_inline.cc @ f5d2647

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