source: git/factory/cf_inline.cc @ 72bfc8

spielwiese
Last change on this file since 72bfc8 was 57daf8, checked in by Martin Lee <martinlee84@…>, 12 years ago
chg: switched off assert for positive exponent since I need Laurent polynomials in cfNewtonPolygon.cc
  • Property mode set to 100644
File size: 14.5 KB
Line 
1/* emacs edit mode for this file is -*- C++ -*- */
2/* $Id$ */
3
4//{{{ docu
5//
6// cf_inline.cc - definition of configurable inline
7//   `CanonicalForm' methods.
8//
9// Hierarchy: canonicalform
10//
11// Header file: canonicalform.h
12//
13// Developers note:
14// ----------------
15// The central class in Factory is, of course, `CanonicalForm'.
16// Hence it is a quiet reasonable to assume that inlining its
17// most important methods will improve execution speed.  The same
18// holds for some methods of the `CFIterator' class.  Everything
19// on configurable inline `CanonicalForm' methods explained here
20// applies mutatis mutandis to the `CFIterator' methods.
21//
22// However, inlining `CanonicalForm' methods has two major
23// drawbacks:
24//
25// o If `CanonicalForm' methods simply would have been declared
26//   `inline' it would have been necessary to include the
27//   definition of `InternalCF' in `factory.h'.  This would have
28//   been quite a contradiction to the internal nature of the
29//   class.
30//   Hence it seemed desirable to introduce a mechanism to have
31//   both the inlined versions for internal use and compiled
32//   versions for the library.
33//
34// o Second, inlining in most cases leads to larger object code.
35//   E.g., inlining `CanonicalForm::~CanonicalForm()' increases the
36//   object code by approx. 15% without any effect on computation
37//   speed.
38//   Thus another design aim was to keep things configurable.
39//   That is why the methods defined here are called
40//   "configurable inline methods".
41//
42// The low level solution to both problems is the macro
43// `CF_INLINE' which either expands to `inline' or nothing.  The
44// counterpart `CF_NO_INLINE' exists only for convenience, it
45// always expands to nothing.  `CF_INLINE' is set immediately
46// before defining resp. declaring the methods to exclude any
47// esoteric influences from included files.
48//
49// The high level interface is the macro `CF_USE_INLINE'.  If it
50// is defined any header file that uses configurable inline
51// methods defines them to be `inline', otherwise they are
52// defined as ordinary methods.  `CF_USE_INLINE' is defined in
53// `config.h' only.
54//
55// To switch on (off) all configurable inline methods, it is
56// sufficient to define (undefine) `CF_USE_INLINE' in `config.h'.
57// To switch off separate configurable inline methods it is
58// necessary to prefix their declaration in `canonicalform.h' by
59// `CF_NO_INLINE' instead of `CF_INLINE'.  Furthermore, to avoid
60// duplicate symbols at link time, their definition in this file
61// has to be wrapped by an `#ifndef INCL_CF_INLINE_CC'.
62//
63// It turned out that inlining the following methods (and only
64// them) results in the best time to size ratio on Linux and HP
65// machines:
66// o all `CanonicalForm' constructors
67// o the binary `CanonicalForm' operators `+' and `*'
68//
69//}}}
70
71// check whether we are included or translated and
72// define `INCL_CF_INLINE_CC' if we are included
73#ifdef INCL_CANONICALFORM_H
74#define INCL_CF_INLINE_CC
75#endif
76
77#include "config.h"
78
79#include "cf_assert.h"
80
81// temporarily switch off `CF_USE_INLINE' and include
82// `canonicalform.h' if we are being translated.
83// `CF_USE_INLINE_SAVE' is used to save the state of
84// `CF_USE_INLINE'.  It is unset after use.
85#ifndef INCL_CF_INLINE_CC
86#ifdef CF_USE_INLINE
87#define CF_USE_INLINE_SAVE
88#undef CF_USE_INLINE
89#endif
90#include "canonicalform.h"
91#ifdef CF_USE_INLINE_SAVE
92#define CF_USE_INLINE
93#undef CF_USE_INLINE_SAVE
94#endif
95#endif /* ! INCL_CF_INLINE_CC */
96
97// regular include files
98#include "int_cf.h"
99#include "imm.h"
100#include "cf_factory.h"
101
102// set the value of `CF_INLINE' for the following methods and
103// functions
104#if defined( CF_USE_INLINE ) && defined( INCL_CF_INLINE_CC )
105#undef CF_INLINE
106#define CF_INLINE inline
107#else
108#undef CF_INLINE
109#define CF_INLINE
110#endif /* ! defined( CF_USE_INLINE ) && defined( INCL_CF_INLINE_CC ) */
111
112// constructors, destructors, assignment
113//{{{ CF_INLINE CanonicalForm::CanonicalForm ()
114//{{{ docu
115//
116// CanonicalForm() - create the default canonical form.
117//
118// The canonical form is initialized to zero from the current
119// domain.
120//
121//}}}
122CF_INLINE
123CanonicalForm::CanonicalForm ()
124    : value( CFFactory::basic( (int)0 ) )
125{
126}
127//}}}
128
129//{{{ CF_INLINE CanonicalForm::CanonicalForm ( const int i )
130//{{{ docu
131//
132// CanonicalForm() - create a canonical form from an integer.
133//
134// The canonical form is initialized to the "canonical image" of
135// `i' in the current domain.  This is `i' itself for
136// characteristic zero, `i' mod p for finite fields of
137// characteristic p, and `i' mod p^n for prime power domains with
138// p^n elements.
139//
140//}}}
141CF_INLINE
142CanonicalForm::CanonicalForm ( const int i )
143    : value( CFFactory::basic( i ) )
144{
145}
146//}}}
147
148//{{{ CF_INLINE CanonicalForm::CanonicalForm ( const CanonicalForm & cf )
149//{{{ docu
150//
151// CanonicalForm() - create a copy of a canonical form.
152//
153// Type info:
154// ----------
155// cf: Anything
156//
157//}}}
158CF_INLINE
159CanonicalForm::CanonicalForm ( const CanonicalForm & cf )
160    : value( is_imm( cf.value ) ? cf.value : cf.value->copyObject() )
161{
162}
163//}}}
164
165//{{{ CF_INLINE CanonicalForm::CanonicalForm ( InternalCF * cf )
166//{{{ docu
167//
168// CanonicalForm() - create a canonical form from a pointer to an
169//   internal canonical form.
170//
171// This constructor is reserved for internal usage.
172//
173// Developers note:
174// ----------------
175// The canonical form gets its value immediately from `cf'.
176// `cf's reference counter is not incremented, so be careful with
177// this constructor.
178//
179//}}}
180CF_INLINE
181CanonicalForm::CanonicalForm ( InternalCF * cf )
182    : value( cf )
183{
184}
185//}}}
186
187//{{{ CF_INLINE CanonicalForm::CanonicalForm ( const Variable & v )
188//{{{ docu
189//
190// CanonicalForm() - create a canonical form from a variable.
191//
192// If `v' is a polynomial variable or an algebraic element the
193// resulting polynomial (or algebraic element) is 1*`v'^1, the
194// one being from the current domain.
195//
196// Variables of level `LEVELBASE' are transformed to one from the
197// current domain.
198//
199// Type info:
200// ----------
201// v: Anything
202//
203//}}}
204CF_INLINE
205CanonicalForm::CanonicalForm ( const Variable & v )
206    : value( CFFactory::poly( v ) )
207{
208}
209//}}}
210
211//{{{ CF_INLINE CanonicalForm::CanonicalForm ( const Variable & v, int e )
212//{{{ docu
213//
214// CanonicalForm() - create a canonical form from a power of a
215//   variable.
216//
217// If `v' is a polynomial variable or an algebraic element the
218// resulting polynomial (or algebraic element) is 1*`v'^`e', the
219// one being from the current domain.  Algebraic elements are
220// reduced modulo their minimal polynomial.
221//
222// Variables of level `LEVELBASE' are transformed to one from the
223// current domain.
224//
225// Type info:
226// ----------
227// v: Anything
228//
229//}}}
230CF_INLINE
231CanonicalForm::CanonicalForm ( const Variable & v, int e )
232    : value( CFFactory::poly( v, e ) )
233{
234    //ASSERT( e > 0, "math error: exponent has to be positive" );
235}
236//}}}
237
238#ifndef INCL_CF_INLINE_CC
239//{{{ CF_INLINE CanonicalForm::~CanonicalForm ()
240//{{{ docu
241//
242// ~CanonicalForm() - delete CO.
243//
244// Type info:
245// ----------
246// CO: Anything
247//
248//}}}
249CF_INLINE
250CanonicalForm::~CanonicalForm ()
251{
252    if ( (! is_imm( value )) && value->deleteObject() )
253        delete value;
254}
255//}}}
256#endif
257
258#ifndef INCL_CF_INLINE_CC
259//{{{ CF_INLINE CanonicalForm & CanonicalForm::operator = ( const CanonicalForm & cf )
260//{{{ docu
261//
262// operator =() - assign `cf' to CO.
263//
264// Type info:
265// ----------
266// CO, cf: Anything
267//
268//}}}
269CF_INLINE CanonicalForm &
270CanonicalForm::operator = ( const CanonicalForm & cf )
271{
272    if ( this != &cf ) {
273        if ( (! is_imm( value )) && value->deleteObject() )
274            delete value;
275        value = (is_imm( cf.value )) ? cf.value : cf.value->copyObject();
276    }
277    return *this;
278}
279//}}}
280
281//{{{ CF_INLINE CanonicalForm & CanonicalForm::operator = ( const int cf )
282//{{{ docu
283//
284// operator =() - assign integer `cf' to CO.
285//
286// `cf' converted to a canonical form as described in the
287// canonical form constructor which creates a canonical form from
288// an integer.
289//
290// Type info:
291// ----------
292// CO: Anything
293//
294// Developers note:
295// ----------------
296// Strictly speaking, this operator is superfluous.  The ordinary
297// assignment operator together with automatic conversion from
298// `int' to `CanonicalForm' would do the job, too.  But this way
299// the common operation of assigning an integer is faster.
300//
301//}}}
302CF_INLINE CanonicalForm &
303CanonicalForm::operator = ( const int cf )
304{
305    if ( (! is_imm( value )) && value->deleteObject() )
306        delete value;
307    value = CFFactory::basic( cf );
308    return *this;
309}
310//}}}
311#endif
312
313// predicates
314#ifndef INCL_CF_INLINE_CC
315//{{{ CF_INLINE bool CanonicalForm::isOne, isZero () const
316//{{{ docu
317//
318// isOne(), isZero() - test whether a `CanonicalForm' equals one
319//   or zero, resp.
320//
321// The predicates `isOne()' and `isZero()' are much faster than
322// the comparison operators.  Furthermore, a test `f.isZero()' is
323// independent from the current domain, whereas an expression
324// `f == 0' is not.
325//
326// Type info:
327// ----------
328// CO: Anything
329//
330// Internal implementation:
331// ------------------------
332// Note that only immediate objects and objects of class
333// `InternalPrimePower' may equal one or zero, resp.
334//
335// imm_isone(), imm_iszero()
336// Trivial.
337//
338// imm_isone_p(), imm_iszero_p()
339// Trivial.
340//
341// imm_isone_gf(), imm_iszero_gf()
342// Use `gf_isone()' and `gf_iszero()', resp., to test whether CO
343// equals zero or one, resp.
344//
345// InternalCF::isOne(), isZero()
346// Always return false.
347//
348// InternalPrimePower::isOne(), isZero()
349// Use `mpz_cpm_ui()' resp. `mpz_sgn()' to check the underlying
350// mpi.
351//
352//}}}
353CF_INLINE bool
354CanonicalForm::isOne () const
355{
356    int what = is_imm( value );
357
358    if ( ! what )
359        return value->isOne();
360    else  if ( what == INTMARK )
361        return imm_isone( value );
362    else if ( what == FFMARK )
363        return imm_isone_p( value );
364    else
365        return imm_isone_gf( value );
366}
367
368CF_INLINE bool
369CanonicalForm::isZero () const
370{
371    int what = is_imm( value );
372
373    if ( what == 0 )
374        return value->isZero();
375    else  if ( what == INTMARK )
376        return imm_iszero( value );
377    else if ( what == FFMARK )
378        return imm_iszero_p( value );
379    else
380        return imm_iszero_gf( value );
381}
382//}}}
383#endif
384
385// arithmetic operators
386#ifndef INCL_CF_INLINE_CC
387//{{{ CF_INLINE CanonicalForm operator - ( const CanonicalForm & cf )
388//{{{ docu
389//
390// operator -() - return additive inverse of `cf'.
391//
392// Returns the additive inverse of `cf'.  One should keep in mind
393// that to negate a canonical form a complete (deep) copy of it
394// has to be created.
395//
396// Type info:
397// ----------
398// cf: CurrentPP
399//
400// In fact, the type is almost `Anything', but it is, e.g., not
401// possible to invert an element from a finite field when the
402// characteristic of the current domain has changed.
403//
404// Internal implementation:
405// ------------------------
406// All internal methods check whether the reference counter
407// equals one.  If so CO is negated in-place.  Otherwise, a new
408// copy of CO is created and negated.
409//
410// imm_neg()
411// Trivial.
412//
413// imm_neg_p()
414// Use `ff_neg()' to negate CO.
415//
416// imm_neg_gf()
417// Use `gf_neg()' to negate CO.
418//
419// InternalInteger::neg()
420// Use `mpz_neg()' to negate the underlying mpi.
421//
422// InternalRational::neg ()
423// Use `mpz_neg()' to negate the denominator.
424//
425// InternalPrimePower::neg()
426// Subtract CO from `primepow' using `mpz_sub'.
427//
428// InternalPoly::neg()
429// If reference counter is one use `negateTermList()' to negate
430// the terms, otherwise create a negated copy using
431// `copyTermList()'.
432//
433//}}}
434CF_INLINE CanonicalForm
435operator - ( const CanonicalForm & cf )
436{
437    CanonicalForm result( cf );
438    int what = is_imm( result.value );
439
440    if ( ! what )
441        result.value = result.value->neg();
442    else  if ( what == INTMARK )
443        result.value = imm_neg( result.value );
444    else if ( what == FFMARK )
445        result.value = imm_neg_p( result.value );
446    else
447        result.value = imm_neg_gf( result.value );
448
449    return result;
450}
451//}}}
452#endif
453
454// binary arithmetic operators and functions
455//{{{ CF_INLINE CanonicalForm operator +, -, *, /, % ( const CanonicalForm & lhs, const CanonicalForm & rhs )
456//{{{ docu
457//
458// operators +, -, *, /, %(), div(), mod() - binary arithmetic
459//   operators.
460//
461// The binary operators have their standard (mathematical)
462// semantics.  As explained for the corresponding arithmetic
463// assignment operators, the operators `/' and `%' return the
464// quotient resp. remainder of (polynomial) division with
465// remainder, whereas `div()' and `mod()' may be used for exact
466// division and term-wise remaindering, resp.
467//
468// It is faster to use the arithmetic assignment operators (e.g.,
469// `f += g;') instead of the binary operators (`f = f+g;' ).
470//
471// Type info:
472// ----------
473// lhs, rhs: CurrentPP
474//
475// There are weaker preconditions for some cases (e.g.,
476// arithmetic operations with elements from Q or Z work in any
477// domain), but type `CurrentPP' is the only one guaranteed to
478// work for all cases.
479//
480// Developers note:
481// ----------------
482// All binary operators have their corresponding `CanonicalForm'
483// assignment operators (e.g., `operator +()' corresponds to
484// `CanonicalForm::operator +=()', `div()' corresponds to
485// `CanonicalForm::div()).
486//
487// And that is how they are implemented, too: Each of the binary
488// operators first creates a copy of `lhs', adds `rhs' to this
489// copy using the assignment operator, and returns the result.
490//
491//}}}
492CF_INLINE CanonicalForm
493operator + ( const CanonicalForm & lhs, const CanonicalForm & rhs )
494{
495    CanonicalForm result( lhs );
496    result += rhs;
497    return result;
498}
499
500#ifndef INCL_CF_INLINE_CC
501CF_INLINE CanonicalForm
502operator - ( const CanonicalForm & lhs, const CanonicalForm & rhs )
503{
504    CanonicalForm result( lhs );
505    result -= rhs;
506    return result;
507}
508#endif
509
510CF_INLINE CanonicalForm
511operator * ( const CanonicalForm & lhs, const CanonicalForm & rhs )
512{
513    CanonicalForm result( lhs );
514    result *= rhs;
515    return result;
516}
517
518#ifndef INCL_CF_INLINE_CC
519CF_INLINE CanonicalForm
520operator / ( const CanonicalForm & lhs, const CanonicalForm & rhs )
521{
522    CanonicalForm result( lhs );
523    result /= rhs;
524    return result;
525}
526
527CF_INLINE CanonicalForm
528operator % ( const CanonicalForm & lhs, const CanonicalForm & rhs )
529{
530    CanonicalForm result( lhs );
531    result %= rhs;
532    return result;
533}
534#endif
535//}}}
536
537#ifndef INCL_CF_INLINE_CC
538//{{{ CF_INLINE CanonicalForm div, mod ( const CanonicalForm & lhs, const CanonicalForm & rhs )
539// docu: see binary operators above
540CF_INLINE CanonicalForm
541div ( const CanonicalForm & lhs, const CanonicalForm & rhs )
542{
543    CanonicalForm result( lhs );
544    result.div( rhs );
545    return result;
546}
547
548CF_INLINE CanonicalForm
549mod ( const CanonicalForm & lhs, const CanonicalForm & rhs )
550{
551    CanonicalForm result( lhs );
552    result.mod( rhs );
553    return result;
554}
555//}}}
556#endif
Note: See TracBrowser for help on using the repository browser.