source: git/factory/cf_inline.cc @ 276c3f

spielwiese
Last change on this file since 276c3f was 806c18, checked in by Hans Schoenemann <hannes@…>, 13 years ago
format git-svn-id: file:///usr/local/Singular/svn/trunk@13655 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 14.6 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 "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// `e' has to be positive.
226//
227// Type info:
228// ----------
229// v: Anything
230//
231//}}}
232CF_INLINE
233CanonicalForm::CanonicalForm ( const Variable & v, int e )
234    : value( CFFactory::poly( v, e ) )
235{
236    ASSERT( e > 0, "math error: exponent has to be positive" );
237}
238//}}}
239
240#ifndef INCL_CF_INLINE_CC
241//{{{ CF_INLINE CanonicalForm::~CanonicalForm ()
242//{{{ docu
243//
244// ~CanonicalForm() - delete CO.
245//
246// Type info:
247// ----------
248// CO: Anything
249//
250//}}}
251CF_INLINE
252CanonicalForm::~CanonicalForm ()
253{
254    if ( (! is_imm( value )) && value->deleteObject() )
255        delete value;
256}
257//}}}
258#endif
259
260#ifndef INCL_CF_INLINE_CC
261//{{{ CF_INLINE CanonicalForm & CanonicalForm::operator = ( const CanonicalForm & cf )
262//{{{ docu
263//
264// operator =() - assign `cf' to CO.
265//
266// Type info:
267// ----------
268// CO, cf: Anything
269//
270//}}}
271CF_INLINE CanonicalForm &
272CanonicalForm::operator = ( const CanonicalForm & cf )
273{
274    if ( this != &cf ) {
275        if ( (! is_imm( value )) && value->deleteObject() )
276            delete value;
277        value = (is_imm( cf.value )) ? cf.value : cf.value->copyObject();
278    }
279    return *this;
280}
281//}}}
282
283//{{{ CF_INLINE CanonicalForm & CanonicalForm::operator = ( const int cf )
284//{{{ docu
285//
286// operator =() - assign integer `cf' to CO.
287//
288// `cf' converted to a canonical form as described in the
289// canonical form constructor which creates a canonical form from
290// an integer.
291//
292// Type info:
293// ----------
294// CO: Anything
295//
296// Developers note:
297// ----------------
298// Strictly speaking, this operator is superfluous.  The ordinary
299// assignment operator together with automatic conversion from
300// `int' to `CanonicalForm' would do the job, too.  But this way
301// the common operation of assigning an integer is faster.
302//
303//}}}
304CF_INLINE CanonicalForm &
305CanonicalForm::operator = ( const int cf )
306{
307    if ( (! is_imm( value )) && value->deleteObject() )
308        delete value;
309    value = CFFactory::basic( cf );
310    return *this;
311}
312//}}}
313#endif
314
315// predicates
316#ifndef INCL_CF_INLINE_CC
317//{{{ CF_INLINE bool CanonicalForm::isOne, isZero () const
318//{{{ docu
319//
320// isOne(), isZero() - test whether a `CanonicalForm' equals one
321//   or zero, resp.
322//
323// The predicates `isOne()' and `isZero()' are much faster than
324// the comparison operators.  Furthermore, a test `f.isZero()' is
325// independent from the current domain, whereas an expression
326// `f == 0' is not.
327//
328// Type info:
329// ----------
330// CO: Anything
331//
332// Internal implementation:
333// ------------------------
334// Note that only immediate objects and objects of class
335// `InternalPrimePower' may equal one or zero, resp.
336//
337// imm_isone(), imm_iszero()
338// Trivial.
339//
340// imm_isone_p(), imm_iszero_p()
341// Trivial.
342//
343// imm_isone_gf(), imm_iszero_gf()
344// Use `gf_isone()' and `gf_iszero()', resp., to test whether CO
345// equals zero or one, resp.
346//
347// InternalCF::isOne(), isZero()
348// Always return false.
349//
350// InternalPrimePower::isOne(), isZero()
351// Use `mpz_cpm_ui()' resp. `mpz_sgn()' to check the underlying
352// mpi.
353//
354//}}}
355CF_INLINE bool
356CanonicalForm::isOne () const
357{
358    int what = is_imm( value );
359
360    if ( ! what )
361        return value->isOne();
362    else  if ( what == INTMARK )
363        return imm_isone( value );
364    else if ( what == FFMARK )
365        return imm_isone_p( value );
366    else
367        return imm_isone_gf( value );
368}
369
370CF_INLINE bool
371CanonicalForm::isZero () const
372{
373    int what = is_imm( value );
374
375    if ( what == 0 )
376        return value->isZero();
377    else  if ( what == INTMARK )
378        return imm_iszero( value );
379    else if ( what == FFMARK )
380        return imm_iszero_p( value );
381    else
382        return imm_iszero_gf( value );
383}
384//}}}
385#endif
386
387// arithmetic operators
388#ifndef INCL_CF_INLINE_CC
389//{{{ CF_INLINE CanonicalForm operator - ( const CanonicalForm & cf )
390//{{{ docu
391//
392// operator -() - return additive inverse of `cf'.
393//
394// Returns the additive inverse of `cf'.  One should keep in mind
395// that to negate a canonical form a complete (deep) copy of it
396// has to be created.
397//
398// Type info:
399// ----------
400// cf: CurrentPP
401//
402// In fact, the type is almost `Anything', but it is, e.g., not
403// possible to invert an element from a finite field when the
404// characteristic of the current domain has changed.
405//
406// Internal implementation:
407// ------------------------
408// All internal methods check whether the reference counter
409// equals one.  If so CO is negated in-place.  Otherwise, a new
410// copy of CO is created and negated.
411//
412// imm_neg()
413// Trivial.
414//
415// imm_neg_p()
416// Use `ff_neg()' to negate CO.
417//
418// imm_neg_gf()
419// Use `gf_neg()' to negate CO.
420//
421// InternalInteger::neg()
422// Use `mpz_neg()' to negate the underlying mpi.
423//
424// InternalRational::neg ()
425// Use `mpz_neg()' to negate the denominator.
426//
427// InternalPrimePower::neg()
428// Subtract CO from `primepow' using `mpz_sub'.
429//
430// InternalPoly::neg()
431// If reference counter is one use `negateTermList()' to negate
432// the terms, otherwise create a negated copy using
433// `copyTermList()'.
434//
435//}}}
436CF_INLINE CanonicalForm
437operator - ( const CanonicalForm & cf )
438{
439    CanonicalForm result( cf );
440    int what = is_imm( result.value );
441
442    if ( ! what )
443        result.value = result.value->neg();
444    else  if ( what == INTMARK )
445        result.value = imm_neg( result.value );
446    else if ( what == FFMARK )
447        result.value = imm_neg_p( result.value );
448    else
449        result.value = imm_neg_gf( result.value );
450
451    return result;
452}
453//}}}
454#endif
455
456// binary arithmetic operators and functions
457//{{{ CF_INLINE CanonicalForm operator +, -, *, /, % ( const CanonicalForm & lhs, const CanonicalForm & rhs )
458//{{{ docu
459//
460// operators +, -, *, /, %(), div(), mod() - binary arithmetic
461//   operators.
462//
463// The binary operators have their standard (mathematical)
464// semantics.  As explained for the corresponding arithmetic
465// assignment operators, the operators `/' and `%' return the
466// quotient resp. remainder of (polynomial) division with
467// remainder, whereas `div()' and `mod()' may be used for exact
468// division and term-wise remaindering, resp.
469//
470// It is faster to use the arithmetic assignment operators (e.g.,
471// `f += g;') instead of the binary operators (`f = f+g;' ).
472//
473// Type info:
474// ----------
475// lhs, rhs: CurrentPP
476//
477// There are weaker preconditions for some cases (e.g.,
478// arithmetic operations with elements from Q or Z work in any
479// domain), but type `CurrentPP' is the only one guaranteed to
480// work for all cases.
481//
482// Developers note:
483// ----------------
484// All binary operators have their corresponding `CanonicalForm'
485// assignment operators (e.g., `operator +()' corresponds to
486// `CanonicalForm::operator +=()', `div()' corresponds to
487// `CanonicalForm::div()).
488//
489// And that is how they are implemented, too: Each of the binary
490// operators first creates a copy of `lhs', adds `rhs' to this
491// copy using the assignment operator, and returns the result.
492//
493//}}}
494CF_INLINE CanonicalForm
495operator + ( const CanonicalForm & lhs, const CanonicalForm & rhs )
496{
497    CanonicalForm result( lhs );
498    result += rhs;
499    return result;
500}
501
502#ifndef INCL_CF_INLINE_CC
503CF_INLINE CanonicalForm
504operator - ( const CanonicalForm & lhs, const CanonicalForm & rhs )
505{
506    CanonicalForm result( lhs );
507    result -= rhs;
508    return result;
509}
510#endif
511
512CF_INLINE CanonicalForm
513operator * ( const CanonicalForm & lhs, const CanonicalForm & rhs )
514{
515    CanonicalForm result( lhs );
516    result *= rhs;
517    return result;
518}
519
520#ifndef INCL_CF_INLINE_CC
521CF_INLINE CanonicalForm
522operator / ( const CanonicalForm & lhs, const CanonicalForm & rhs )
523{
524    CanonicalForm result( lhs );
525    result /= rhs;
526    return result;
527}
528
529CF_INLINE CanonicalForm
530operator % ( const CanonicalForm & lhs, const CanonicalForm & rhs )
531{
532    CanonicalForm result( lhs );
533    result %= rhs;
534    return result;
535}
536#endif
537//}}}
538
539#ifndef INCL_CF_INLINE_CC
540//{{{ CF_INLINE CanonicalForm div, mod ( const CanonicalForm & lhs, const CanonicalForm & rhs )
541// docu: see binary operators above
542CF_INLINE CanonicalForm
543div ( const CanonicalForm & lhs, const CanonicalForm & rhs )
544{
545    CanonicalForm result( lhs );
546    result.div( rhs );
547    return result;
548}
549
550CF_INLINE CanonicalForm
551mod ( const CanonicalForm & lhs, const CanonicalForm & rhs )
552{
553    CanonicalForm result( lhs );
554    result.mod( rhs );
555    return result;
556}
557//}}}
558#endif
Note: See TracBrowser for help on using the repository browser.